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
« 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
8class Tight(ConstraintSet):
9 "ConstraintSet whose inequalities must result in an equality."
10 reltol = 1e-3
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
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")