Coverage for gpkit/constraints/tight.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-07 22:13 -0500

1"Implements Tight" 

2from .set import ConstraintSet 

3from ..small_scripts import mag 

4from ..small_scripts import appendsolwarning, initsolwarning 

5from .. import SignomialsEnabled 

6 

7 

8class Tight(ConstraintSet): 

9 "ConstraintSet whose inequalities must result in an equality." 

10 reltol = 1e-3 

11 

12 def __init__(self, constraints, *, reltol=None, **kwargs): 

13 super().__init__(constraints) 

14 self.reltol = reltol or self.reltol 

15 self.__dict__.update(kwargs) # NOTE: for Berk's use in labelling 

16 

17 def process_result(self, result): 

18 "Checks that all constraints are satisfied with equality" 

19 super().process_result(result) 

20 variables = result["variables"] 

21 initsolwarning(result, "Unexpectedly Loose Constraints") 

22 for constraint in self.flat(): 

23 with SignomialsEnabled(): 

24 leftval = constraint.left.sub(variables).value 

25 rightval = constraint.right.sub(variables).value 

26 rel_diff = mag(abs(1 - leftval/rightval)) 

27 if rel_diff >= self.reltol: 

28 # pylint: disable=consider-using-f-string 

29 msg = ("Constraint [%.100s... %s %.100s...] is not tight:" 

30 " the left hand side evaluated to %s but" 

31 " the right hand side evaluated to %s" 

32 " (Allowable error: %s%%, Actual error: %.2g%%)" % 

33 (constraint.left, constraint.oper, constraint.right, 

34 leftval, rightval, 

35 self.reltol*100, mag(rel_diff)*100)) 

36 if hasattr(leftval, "magnitude"): 

37 rightval = rightval.to(leftval.units).magnitude 

38 leftval = leftval.magnitude 

39 tightvalues = (leftval, constraint.oper, rightval) 

40 appendsolwarning(msg, (rel_diff, tightvalues, constraint), 

41 result, "Unexpectedly Loose Constraints")