Last active
March 26, 2019 15:30
-
-
Save mvernacc/5505ea8278f8cacff9ce0b2d447ccf1c to your computer and use it in GitHub Desktop.
Minimum working example of Issue 1390 from gpkit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Minimum working example of Issue 1390 | |
See https://github.com/convexengineering/gpkit/issues/1390 | |
""" | |
import traceback | |
from gpkit import Model, Variable, units, DimensionalityError | |
from gpkit.constraints.tight import Tight | |
class DummyModelRad(Model): | |
"""This one replicates the original error.""" | |
def setup(self): | |
x = Variable('x', 'radian', '') | |
constraints = [ | |
x >= 1. * units('radian'), | |
Tight([x <= 2.]), | |
] | |
return constraints | |
class DummyModelMeter(Model): | |
"""This one raises a different error.""" | |
def setup(self): | |
x = Variable('x', 'meter', '') | |
constraints = [ | |
x >= 1. * units('meter'), | |
Tight([x <= 2.]), | |
] | |
return constraints | |
class DummyModelDimless(Model): | |
"""This one works.""" | |
def setup(self): | |
x = Variable('x', '', '') | |
constraints = [ | |
x >= 1. * units(''), | |
Tight([x <= 2.]), | |
] | |
return constraints | |
def main(): | |
"""The optimization problem is: | |
min x | |
s.t. x >= 1 | |
x <= 2 | |
The optimal cost is `1` with `x = 1`. At the optimum, `x = 1 < 2`, | |
so the second constraint is not tight. Because the second constraint | |
was wrapped with Tight(), this enters the if clause on line 44 | |
of tight.py. On line 54, the lefthand side will have a `magnitude` | |
attr, because `x` is a pint variable (with units of rad). However | |
the righthand side is simply a float, so calling `rightsubbed.to()` | |
on line 55 will fail. | |
""" | |
print('**This one raises an AttributeError, like the original bug**') | |
m1 = DummyModelRad() | |
m1.cost = m1['x'] | |
try: | |
# This replicates the original error. | |
sol = m1.solve() | |
except AttributeError: | |
print(traceback.format_exc()) | |
"""This is the same optimization problem, but with `x` having units of | |
meter instead of radian. In this case, we do not see the error in tight.py. | |
Instead, we get are not allowed to create a constraint comparing `x` | |
(with units of meters) to `2.` (with no units). | |
""" | |
print('\n\n**This one raises an DimensionalityError on initialization**') | |
try: | |
# This creates a different error. | |
m2 = DummyModelMeter() | |
except DimensionalityError: | |
print(traceback.format_exc()) | |
"""This example uses the same optimization problem, but with `x` being dimensionless. | |
In this case the `leftsubbed` in `tight.py` does not have a `magnitude` attr, | |
and so the if clause on line 54 is not entered. | |
""" | |
print('\n\n**This one works**') | |
m3 = DummyModelDimless() | |
m3.cost = m3['x'] | |
sol = m3.solve() | |
print(sol.table()) | |
"""These examples illustrate that the bug only occurs in a weird edge | |
case where we compare a pint variable with units of radians to a non-pint | |
(e.g. float) variable. This comparison is allowed by pint (because radian | |
is vaguely equivalent to being dimensionless) but is not handled by `tight.py`. | |
""" | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment