-
Notifications
You must be signed in to change notification settings - Fork 40
/
tight.py
41 lines (37 loc) · 1.88 KB
/
tight.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"Implements Tight"
from .set import ConstraintSet
from ..small_scripts import mag
from ..small_scripts import appendsolwarning
from .. import SignomialsEnabled
class Tight(ConstraintSet):
"ConstraintSet whose inequalities must result in an equality."
reltol = 1e-3
def __init__(self, constraints, *, reltol=None, **kwargs):
super().__init__(constraints)
self.reltol = reltol or self.reltol
self.__dict__.update(kwargs) # NOTE: for Berk's use in labelling
def process_result(self, result):
"Checks that all constraints are satisfied with equality"
super().process_result(result)
variables = result["variables"]
for constraint in self.flat():
with SignomialsEnabled():
leftsubbed = constraint.left.sub(variables).value
rightsubbed = constraint.right.sub(variables).value
rel_diff = abs(1 - leftsubbed/rightsubbed)
if rel_diff >= self.reltol:
msg = ("Constraint [%.100s... %s %.100s...] is not tight:"
" the left hand side evaluated to %s but"
" the right hand side evaluated to %s"
" (Allowable error: %s%%, Actual error: %.2g%%)" %
(constraint.left, constraint.oper, constraint.right,
leftsubbed, rightsubbed,
self.reltol*100, mag(rel_diff)*100))
if hasattr(leftsubbed, "magnitude"):
rightsubbed = rightsubbed.to(leftsubbed.units).magnitude
leftsubbed = leftsubbed.magnitude
constraint.tightvalues = (leftsubbed, constraint.oper,
rightsubbed)
constraint.rel_diff = rel_diff
appendsolwarning(msg, constraint, result,
"Unexpectedly Loose Constraints")