/
tight.py
57 lines (53 loc) · 2.72 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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"Implements Tight"
from .set import ConstraintSet
from ..nomials import PosynomialInequality, SignomialInequality
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, raiseerror=False, **kwargs):
super().__init__(constraints)
self.reltol = reltol or self.reltol
self.raiseerror = raiseerror
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():
rel_diff = 0
if isinstance(constraint, PosynomialInequality):
leftsubbed = constraint.left.sub(variables).value
rightsubbed = constraint.right.sub(variables).value
rel_diff = abs(1 - leftsubbed/rightsubbed)
elif isinstance(constraint, SignomialInequality):
siglt0, = constraint.unsubbed
posy, negy = siglt0.posy_negy()
posy = posy.sub(variables).value
negy = negy.sub(variables).value
rel_diff = abs(1 - posy/negy)
if rel_diff >= self.reltol:
# do another substitution for the sake of printing
with SignomialsEnabled():
leftsubbed = constraint.left.sub(variables).value
rightsubbed = constraint.right.sub(variables).value
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 self.raiseerror:
raise ValueError(msg)
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")