Coverage for gpkit/tests/t_examples.py: 99%
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"""Unit testing of tests in docs/source/examples"""
2import unittest
3import os
4import pickle
5import json
6import numpy as np
8from gpkit import settings, Model, Variable
9from gpkit.tests.helpers import generate_example_tests
10from gpkit.small_scripts import mag
11from gpkit.small_classes import Quantity
12from gpkit.constraints.loose import Loose
13from gpkit.exceptions import (UnknownInfeasible,
14 PrimalInfeasible, DualInfeasible, UnboundedGP)
17def assert_logtol(first, second, logtol=1e-6):
18 "Asserts that the logs of two arrays have a given abstol"
19 np.testing.assert_allclose(np.log(mag(first)), np.log(mag(second)),
20 atol=logtol, rtol=0)
23# pylint: disable=too-many-public-methods
24class TestExamples(unittest.TestCase):
25 """
26 To test a new example, add a function called `test_$EXAMPLENAME`, where
27 $EXAMPLENAME is the name of your example in docs/source/examples without
28 the file extension.
30 This function should accept two arguments (e.g. 'self' and 'example').
31 The imported example script will be passed to the second: anything that
32 was a global variable (e.g, "sol") in the original script is available
33 as an attribute (e.g., "example.sol")
35 If you don't want to perform any checks on the example besides making
36 sure it runs, just put "pass" as the function's body, e.g.:
38 def test_dummy_example(self, example):
39 pass
41 But it's good practice to ensure the example's solution as well, e.g.:
43 def test_dummy_example(self, example):
44 self.assertAlmostEqual(example.sol["cost"], 3.121)
45 """
47 # TODO: allow enabling plotting examples, make plots in correct folder...
48 # def test_plot_sweep1d(self, _):
49 # import matplotlib.pyplot as plt
50 # plt.close("all")
52 def test_breakdowns(self, example):
53 pass
55 def test_issue_1513(self, example):
56 pass
58 def test_issue_1522(self, example):
59 pass
61 def test_autosweep(self, example):
62 from gpkit import ureg
63 bst1, tol1 = example.bst1, example.tol1
64 bst2, tol2 = example.bst2, example.tol2
66 l_ = np.linspace(1, 10, 100)
67 for bst in [bst1, example.bst1_loaded]:
68 sol1 = bst.sample_at(l_)
69 assert_logtol(sol1("l"), l_)
70 assert_logtol(sol1("A"), l_**2 + 1, tol1)
71 assert_logtol(sol1["cost"], (l_**2 + 1)**2, tol1)
72 self.assertEqual(Quantity(1.0, sol1("A").units),
73 Quantity(1.0, ureg.m)**2)
75 ndig = -int(np.log10(tol2))
76 self.assertAlmostEqual(bst2.cost_at("cost", 3), 1.0, ndig)
77 # before corner
78 A_bc = np.linspace(1, 3, 50)
79 sol_bc = bst2.sample_at(A_bc)
80 assert_logtol(sol_bc("A"), (A_bc/3)**0.5, tol2)
81 assert_logtol(sol_bc["cost"], A_bc/3, tol2)
82 # after corner
83 A_ac = np.linspace(3, 10, 50)
84 sol_ac = bst2.sample_at(A_ac)
85 assert_logtol(sol_ac("A"), (A_ac/3)**2, tol2)
86 assert_logtol(sol_ac["cost"], (A_ac/3)**4, tol2)
88 def test_treemap(self, example):
89 pass
91 def test_checking_result_changes(self, example):
92 sol = example.sol
93 self.assertAlmostEqual(sol["cost"], 0.48, 2)
95 def test_evaluated_fixed_variables(self, example):
96 sol = example.sol
97 t_night = example.t_night
98 self.assertTrue((sol["variables"][t_night] == [16, 12, 8]).all())
100 def test_evaluated_free_variables(self, example):
101 x2 = example.x2
102 sol = example.sol
103 self.assertTrue(abs(sol(x2) - 4) <= 1e-4)
105 def test_external_constraint(self, example):
106 pass
108 def test_migp(self, example):
109 if settings["default_solver"] == "mosek_conif":
110 assert_logtol(example.sol(example.x), [1]*3 + [2]*6 + [3]*2)
111 else:
112 assert_logtol(example.sol(example.x),
113 np.sqrt(example.sol(example.num)))
115 def test_external_function(self, example):
116 external_code = example.external_code
117 self.assertEqual(external_code(0), 0)
119 def test_external_sp(self, example):
120 m = example.m
121 sol = m.localsolve(verbosity=0)
122 self.assertAlmostEqual(sol["cost"], 0.707, places=3)
124 def test_freeing_fixed_variables(self, example):
125 x = example.x
126 y = Variable("y", 3)
127 m = Model(x, [x >= 1 + y, y >= 1])
128 sol = m.solve(verbosity=0)
129 self.assertTrue(abs(sol["cost"] - 4) <= 1e-4)
130 self.assertTrue(y in sol["constants"])
132 del m.substitutions["y"]
133 sol = m.solve(verbosity=0)
134 self.assertTrue(abs(sol["cost"] - 2) <= 1e-4)
135 self.assertTrue(y in sol["freevariables"])
137 def test_gettingstarted(self, example):
138 pass
141 def test_loose_constraintsets(self, example):
142 m = example.m
143 sol = m.solve(verbosity=0)
144 self.assertAlmostEqual(sol["cost"], 2, 3)
146 def test_sub_multi_values(self, example):
147 x = example.x
148 y = example.y
149 z = example.z
150 p = example.p
151 self.assertTrue(all(p.sub({x: 1, "y": 2}) == 2*z))
152 self.assertTrue(all(
153 p.sub({x: 1, y: 2, "z": [1, 2]}) == z.sub({z: [2, 4]})
154 ))
156 def test_substitutions(self, example):
157 x = example.x
158 p = example.p
159 self.assertTrue(p.sub({x: 3}) == 9)
160 self.assertTrue(p.sub({x.key: 3}) == 9)
161 self.assertTrue(p.sub({"x": 3}) == 9)
163 def test_tight_constraintsets(self, example):
164 m = example.m
165 sol = m.solve(verbosity=0)
166 self.assertAlmostEqual(sol["cost"], 2, places=2)
168 def test_vectorization(self, example):
169 x = example.x
170 y = example.y
171 z = example.z
172 self.assertEqual(y.shape, (5, 3))
173 self.assertEqual(x.shape, (2, 5, 3))
174 self.assertEqual(z.shape, (7, 3))
176 def test_model_var_access(self, example):
177 model = example.PS
178 _ = model["E"]
179 with self.assertRaises(ValueError):
180 _ = model["m"] # multiple variables called m
182 def test_performance_modeling(self, example):
183 m = Model(example.M.cost, Loose(example.M), example.M.substitutions)
184 sol = m.solve(verbosity=0)
185 sol.table()
186 sol.save("solution.pkl")
187 sol.table()
188 sol_loaded = pickle.load(open("solution.pkl", "rb"))
189 sol_loaded.table()
191 sweepsol = m.sweep({example.AC.fuse.W: (50, 100, 150)}, verbosity=0)
192 sweepsol.table()
193 sweepsol.save("sweepsolution.pkl")
194 sweepsol.table()
195 sol_loaded = pickle.load(open("sweepsolution.pkl", "rb"))
196 sol_loaded.table()
198 # testing savejson
199 sol.savejson("solution.json")
200 json_dict = {}
201 with open("solution.json", "r") as rf:
202 json_dict = json.load(rf)
203 for var in sol["variables"]:
204 self.assertTrue(np.all(json_dict[str(var.key)]['v']
205 == sol["variables"][var.key]))
206 self.assertEqual(json_dict[str(var.key)]['u'], var.unitstr())
208 def test_sp_to_gp_sweep(self, example):
209 sol = example.sol
210 cost = sol["cost"]
211 self.assertAlmostEqual(cost[0], 4628.21, places=2)
212 self.assertAlmostEqual(cost[1], 6226.60, places=2)
213 self.assertAlmostEqual(cost[2], 7362.77, places=2)
215 def test_boundschecking(self, example): # pragma: no cover
216 if "mosek_cli" in settings["default_solver"]:
217 with self.assertRaises(UnknownInfeasible):
218 example.gp.solve(verbosity=0)
219 else:
220 example.gp.solve(verbosity=0) # mosek_conif and cvxopt solve it
222 def test_vectorize(self, example):
223 pass
225 def test_primal_infeasible_ex1(self, example):
226 primal_or_unknown = PrimalInfeasible
227 if "cvxopt" in settings["default_solver"]: # pragma: no cover
228 primal_or_unknown = UnknownInfeasible
229 with self.assertRaises(primal_or_unknown):
230 example.m.solve(verbosity=0)
232 def test_primal_infeasible_ex2(self, example):
233 primal_or_unknown = PrimalInfeasible
234 if "cvxopt" in settings["default_solver"]: # pragma: no cover
235 primal_or_unknown = UnknownInfeasible
236 with self.assertRaises(primal_or_unknown):
237 example.m.solve(verbosity=0)
239 def test_docstringparsing(self, example):
240 pass
242 def test_debug(self, example):
243 dual_or_primal = DualInfeasible
244 if "mosek_conif" == settings["default_solver"]: # pragma: no cover
245 dual_or_primal = PrimalInfeasible
246 with self.assertRaises(UnboundedGP):
247 example.m.gp()
248 with self.assertRaises(dual_or_primal):
249 gp = example.m.gp(checkbounds=False)
250 gp.solve(verbosity=0)
252 primal_or_unknown = PrimalInfeasible
253 if "cvxopt" == settings["default_solver"]: # pragma: no cover
254 primal_or_unknown = UnknownInfeasible
255 with self.assertRaises(primal_or_unknown):
256 example.m2.solve(verbosity=0)
258 with self.assertRaises(UnboundedGP):
259 example.m3.gp()
260 with self.assertRaises(DualInfeasible):
261 gp3 = example.m3.gp(checkbounds=False)
262 gp3.solve(verbosity=0)
264 def test_simple_sp(self, example):
265 pass
267 def test_simple_box(self, example):
268 pass
270 def test_x_greaterthan_1(self, example):
271 pass
273 def test_beam(self, example):
274 self.assertFalse(np.isnan(example.sol("w")).any())
276 def test_water_tank(self, example):
277 pass
279 def test_sin_approx_example(self, example):
280 pass
282 def test_simpleflight(self, example):
283 self.assertTrue(example.sol.almost_equal(example.sol_loaded))
284 for sol in [example.sol, example.sol_loaded]:
285 freevarcheck = {
286 "A": 8.46,
287 "C_D": 0.0206,
288 "C_f": 0.0036,
289 "C_L": 0.499,
290 "Re": 3.68e+06,
291 "S": 16.4,
292 "W": 7.34e+03,
293 "V": 38.2,
294 "W_w": 2.40e+03
295 }
296 # sensitivity values from p. 34 of W. Hoburg's thesis
297 senscheck = {
298 r"(\frac{S}{S_{wet}})": 0.4300,
299 "e": -0.4785,
300 "V_{min}": -0.3691,
301 "k": 0.4300,
302 r"\mu": 0.0860,
303 "(CDA0)": 0.0915,
304 "C_{L,max}": -0.1845,
305 r"\tau": -0.2903,
306 "N_{ult}": 0.2903,
307 "W_0": 1.0107,
308 r"\rho": -0.2275
309 }
310 for key in freevarcheck:
311 sol_rat = mag(sol["variables"][key])/freevarcheck[key]
312 self.assertTrue(abs(1-sol_rat) < 1e-2)
313 for key in senscheck:
314 sol_rat = sol["sensitivities"]["variables"][key]/senscheck[key]
315 self.assertTrue(abs(1-sol_rat) < 1e-2)
317 def test_relaxation(self, example):
318 pass
320 def test_unbounded(self, example):
321 pass
324FILE_DIR = os.path.dirname(os.path.realpath(__file__))
325EXAMPLE_DIR = os.path.abspath(FILE_DIR + '../../../docs/source/examples')
326SOLVERS = settings["installed_solvers"]
327if os.path.isdir(EXAMPLE_DIR):
328 TESTS = generate_example_tests(EXAMPLE_DIR, [TestExamples], SOLVERS)
329else: # pragma: no cover
330 TESTS = []
332if __name__ == "__main__": # pragma: no cover
333 # pylint:disable=wrong-import-position
334 from gpkit.tests.helpers import run_tests
335 run_tests(TESTS)