Coverage for gpkit\tests\t_tools.py: 0%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Tests for tools module"""
2import unittest
3import numpy as np
4from numpy import log
5from gpkit import Variable, VectorVariable, Model, NomialArray
6from gpkit.tools.autosweep import BinarySweepTree
7from gpkit.tools.tools import te_exp_minus1, te_secant, te_tangent
8from gpkit.small_scripts import mag
9from gpkit import parse_variables
12def assert_logtol(first, second, logtol=1e-6):
13 "Asserts that the logs of two arrays have a given abstol"
14 np.testing.assert_allclose(log(mag(first)), log(mag(second)),
15 atol=logtol, rtol=0)
18class OnlyVectorParse(Model):
19 """
20 Variables of length 3
21 ---------------------
22 x [-] just another variable
23 """
24 @parse_variables(__doc__, globals())
25 def setup(self):
26 pass
29class Fuselage(Model):
30 """The thing that carries the fuel, engine, and payload
32 Variables
33 ---------
34 f [-] Fineness
35 g 9.81 [m/s^2] Standard gravity
36 k [-] Form factor
37 l [ft] Length
38 mfac 2.0 [-] Weight margin factor
39 R [ft] Radius
40 rhocfrp 1.6 [g/cm^3] Density of CFRP
41 rhofuel 6.01 [lbf/gallon] Density of 100LL fuel
42 S [ft^2] Wetted area
43 t 0.024 [in] Minimum skin thickness
44 Vol [ft^3] Volume
45 W [lbf] Weight
47 Upper Unbounded
48 ---------------
49 k, W
51 """
53 # pylint: disable=undefined-variable, invalid-name
54 @parse_variables(__doc__, globals())
55 def setup(self, Wfueltot):
56 return [
57 f == l/R/2,
58 k >= 1 + 60/f**3 + f/400,
59 3*(S/np.pi)**1.6075 >= 2*(l*R*2)**1.6075 + (2*R)**(2*1.6075),
60 Vol <= 4*np.pi/3*(l/2)*R**2,
61 Vol >= Wfueltot/rhofuel,
62 W/mfac >= S*rhocfrp*t*g,
63 ]
66class TestTools(unittest.TestCase):
67 """TestCase for math models"""
69 def test_vector_only_parse(self):
70 # pylint: disable=no-member
71 m = OnlyVectorParse()
72 self.assertTrue(hasattr(m, "x"))
73 self.assertIsInstance(m.x, NomialArray)
74 self.assertEqual(len(m.x), 3)
76 def test_parse_variables(self):
77 Fuselage(Variable("Wfueltot", 5, "lbf"))
79 def test_binary_sweep_tree(self):
80 bst0 = BinarySweepTree([1, 2], [{"cost": 1}, {"cost": 8}], None, None)
81 assert_logtol(bst0.sample_at([1, 1.5, 2])["cost"], [1, 3.375, 8], 1e-3)
82 bst0.add_split(1.5, {"cost": 4})
83 assert_logtol(bst0.sample_at([1, 1.25, 1.5, 1.75, 2])["cost"],
84 [1, 2.144, 4, 5.799, 8], 1e-3)
86 def test_dual_objective(self):
87 L = Variable("L")
88 W = Variable("W")
89 eqns = [L >= 1, W >= 1,
90 L*W == 10]
91 N = 4
92 ws = Variable("w_{CO}", ("sweep", np.linspace(1/N, 1-1/N, N)), "-")
93 w_s = Variable("v_{CO}", lambda c: 1-c[ws], "-")
94 obj = ws*(L+W) + w_s*(W**-1 * L**-3)
95 m = Model(obj, eqns)
96 sol = m.solve(verbosity=0)
97 a = sol["cost"]
98 b = np.array([1.58856898, 2.6410391, 3.69348122, 4.74591386])
99 self.assertTrue((abs(a-b)/(a+b+1e-7) < 1e-7).all())
101 def test_te_exp_minus1(self):
102 """Test Taylor expansion of e^x - 1"""
103 x = Variable('x')
104 self.assertEqual(te_exp_minus1(x, 1), x)
105 self.assertEqual(te_exp_minus1(x, 3), x + x**2/2 + x**3/6)
106 self.assertEqual(te_exp_minus1(x, 0), 0)
107 # make sure x was not modified
108 self.assertEqual(x, Variable('x'))
109 # try for VectorVariable too
110 y = VectorVariable(3, 'y')
111 self.assertEqual(te_exp_minus1(y, 1), y)
112 self.assertEqual(te_exp_minus1(y, 3), y + y**2/2 + y**3/6)
113 self.assertEqual(te_exp_minus1(y, 0), 0)
114 # make sure y was not modified
115 self.assertEqual(y, VectorVariable(3, 'y'))
117 def test_te_secant(self):
118 "Test Taylor expansion of secant(var)"
119 x = Variable('x')
120 self.assertEqual(te_secant(x, 1), 1 + x**2/2)
121 a = te_secant(x, 2)
122 b = 1 + x**2/2 + 5*x**4/24
123 self.assertTrue(all([abs(val) <= 1e-10
124 for val in (a.hmap - b.hmap).values()])) # pylint:disable=no-member
125 self.assertEqual(te_secant(x, 0), 1)
126 # make sure x was not modified
127 self.assertEqual(x, Variable('x'))
128 # try for VectorVariable too
129 y = VectorVariable(3, 'y')
130 self.assertTrue(te_secant(y, 0) == 1) # truthy bc monomial constraint
131 self.assertTrue(all(te_secant(y, 1) == 1 + y**2/2))
132 self.assertTrue(all(te_secant(y, 2) == 1 + y**2/2 + 5*y**4/24))
133 # make sure y was not modified
134 self.assertEqual(y, VectorVariable(3, 'y'))
135 _ = te_secant(x, 13) # to trigger the extension
137 def test_te_tangent(self):
138 "Test Taylor expansion of tangent(var)"
139 x = Variable('x')
140 self.assertEqual(te_tangent(x, 1), x)
141 self.assertEqual(te_tangent(x, 3), x + x**3/3 + 2*x**5/15)
142 self.assertEqual(te_tangent(x, 0), 0)
143 # make sure x was not modified
144 self.assertEqual(x, Variable('x'))
145 # try for VectorVariable too
146 y = VectorVariable(3, 'y')
147 self.assertEqual(te_tangent(y, 1), y)
148 self.assertEqual(te_tangent(y, 3), y + y**3/3 + 2*y**5/15)
149 self.assertEqual(te_tangent(y, 0), 0)
150 # make sure y was not modified
151 self.assertEqual(y, VectorVariable(3, 'y'))
152 with self.assertRaises(NotImplementedError):
153 _ = te_tangent(x, 16)
156TESTS = [TestTools]
159if __name__ == "__main__": # pragma: no cover
160 # pylint: disable=wrong-import-position
161 from gpkit.tests.helpers import run_tests
162 run_tests(TESTS)