Hide keyboard shortcuts

Hot-keys on this page

r m x p   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 

7 

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) 

15 

16 

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) 

21 

22 

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. 

29 

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") 

34 

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.: 

37 

38 def test_dummy_example(self, example): 

39 pass 

40 

41 But it's good practice to ensure the example's solution as well, e.g.: 

42 

43 def test_dummy_example(self, example): 

44 self.assertAlmostEqual(example.sol["cost"], 3.121) 

45 """ 

46 

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") 

51 

52 def test_issue_1513(self, example): 

53 pass 

54 

55 def test_issue_1522(self, example): 

56 pass 

57 

58 def test_autosweep(self, example): 

59 from gpkit import ureg 

60 bst1, tol1 = example.bst1, example.tol1 

61 bst2, tol2 = example.bst2, example.tol2 

62 

63 l_ = np.linspace(1, 10, 100) 

64 for bst in [bst1, example.bst1_loaded]: 

65 sol1 = bst.sample_at(l_) 

66 assert_logtol(sol1("l"), l_) 

67 assert_logtol(sol1("A"), l_**2 + 1, tol1) 

68 assert_logtol(sol1["cost"], (l_**2 + 1)**2, tol1) 

69 self.assertEqual(Quantity(1.0, sol1("A").units), 

70 Quantity(1.0, ureg.m)**2) 

71 

72 ndig = -int(np.log10(tol2)) 

73 self.assertAlmostEqual(bst2.cost_at("cost", 3), 1.0, ndig) 

74 # before corner 

75 A_bc = np.linspace(1, 3, 50) 

76 sol_bc = bst2.sample_at(A_bc) 

77 assert_logtol(sol_bc("A"), (A_bc/3)**0.5, tol2) 

78 assert_logtol(sol_bc["cost"], A_bc/3, tol2) 

79 # after corner 

80 A_ac = np.linspace(3, 10, 50) 

81 sol_ac = bst2.sample_at(A_ac) 

82 assert_logtol(sol_ac("A"), (A_ac/3)**2, tol2) 

83 assert_logtol(sol_ac["cost"], (A_ac/3)**4, tol2) 

84 

85 def test_treemap(self, example): 

86 pass 

87 

88 def test_checking_result_changes(self, example): 

89 sol = example.sol 

90 self.assertAlmostEqual(sol["cost"], 0.48, 2) 

91 

92 def test_evaluated_fixed_variables(self, example): 

93 sol = example.sol 

94 t_night = example.t_night 

95 self.assertTrue((sol["variables"][t_night] == [16, 12, 8]).all()) 

96 

97 def test_evaluated_free_variables(self, example): 

98 x2 = example.x2 

99 sol = example.sol 

100 self.assertTrue(abs(sol(x2) - 4) <= 1e-4) 

101 

102 def test_external_constraint(self, example): 

103 pass 

104 

105 def test_migp(self, example): 

106 if settings["default_solver"] == "mosek_conif": 

107 assert_logtol(example.sol(example.x), [1]*3 + [2]*6 + [3]*2) 

108 else: 

109 assert_logtol(example.sol(example.x), 

110 np.sqrt(example.sol(example.num))) 

111 

112 def test_external_function(self, example): 

113 external_code = example.external_code 

114 self.assertEqual(external_code(0), 0) 

115 

116 def test_external_sp(self, example): 

117 m = example.m 

118 sol = m.localsolve(verbosity=0) 

119 self.assertAlmostEqual(sol["cost"], 0.707, places=3) 

120 

121 def test_freeing_fixed_variables(self, example): 

122 x = example.x 

123 y = Variable("y", 3) 

124 m = Model(x, [x >= 1 + y, y >= 1]) 

125 sol = m.solve(verbosity=0) 

126 self.assertTrue(abs(sol["cost"] - 4) <= 1e-4) 

127 self.assertTrue(y in sol["constants"]) 

128 

129 del m.substitutions["y"] 

130 sol = m.solve(verbosity=0) 

131 self.assertTrue(abs(sol["cost"] - 2) <= 1e-4) 

132 self.assertTrue(y in sol["freevariables"]) 

133 

134 def test_gettingstarted(self, example): 

135 pass 

136 

137 

138 def test_loose_constraintsets(self, example): 

139 m = example.m 

140 sol = m.solve(verbosity=0) 

141 self.assertAlmostEqual(sol["cost"], 2, 3) 

142 

143 def test_sub_multi_values(self, example): 

144 x = example.x 

145 y = example.y 

146 z = example.z 

147 p = example.p 

148 self.assertTrue(all(p.sub({x: 1, "y": 2}) == 2*z)) 

149 self.assertTrue(all( 

150 p.sub({x: 1, y: 2, "z": [1, 2]}) == z.sub({z: [2, 4]}) 

151 )) 

152 

153 def test_substitutions(self, example): 

154 x = example.x 

155 p = example.p 

156 self.assertTrue(p.sub({x: 3}) == 9) 

157 self.assertTrue(p.sub({x.key: 3}) == 9) 

158 self.assertTrue(p.sub({"x": 3}) == 9) 

159 

160 def test_tight_constraintsets(self, example): 

161 m = example.m 

162 sol = m.solve(verbosity=0) 

163 self.assertAlmostEqual(sol["cost"], 2, places=2) 

164 

165 def test_vectorization(self, example): 

166 x = example.x 

167 y = example.y 

168 z = example.z 

169 self.assertEqual(y.shape, (5, 3)) 

170 self.assertEqual(x.shape, (2, 5, 3)) 

171 self.assertEqual(z.shape, (7, 3)) 

172 

173 def test_model_var_access(self, example): 

174 model = example.PS 

175 _ = model["E"] 

176 with self.assertRaises(ValueError): 

177 _ = model["m"] # multiple variables called m 

178 

179 def test_performance_modeling(self, example): 

180 m = Model(example.M.cost, Loose(example.M), example.M.substitutions) 

181 sol = m.solve(verbosity=0) 

182 sol.table() 

183 sol.save("solution.pkl") 

184 sol.table() 

185 sol_loaded = pickle.load(open("solution.pkl", "rb")) 

186 sol_loaded.table() 

187 

188 sweepsol = m.sweep({example.AC.fuse.W: (50, 100, 150)}, verbosity=0) 

189 sweepsol.table() 

190 sweepsol.save("sweepsolution.pkl") 

191 sweepsol.table() 

192 sol_loaded = pickle.load(open("sweepsolution.pkl", "rb")) 

193 sol_loaded.table() 

194 

195 # testing savejson 

196 sol.savejson("solution.json") 

197 json_dict = {} 

198 with open("solution.json", "r") as rf: 

199 json_dict = json.load(rf) 

200 for var in sol["variables"]: 

201 self.assertTrue(np.all(json_dict[str(var.key)]['v'] 

202 == sol["variables"][var.key])) 

203 self.assertEqual(json_dict[str(var.key)]['u'], var.unitstr()) 

204 

205 def test_sp_to_gp_sweep(self, example): 

206 sol = example.sol 

207 cost = sol["cost"] 

208 self.assertAlmostEqual(cost[0], 4628.21, places=2) 

209 self.assertAlmostEqual(cost[1], 6226.60, places=2) 

210 self.assertAlmostEqual(cost[2], 7362.77, places=2) 

211 

212 def test_boundschecking(self, example): # pragma: no cover 

213 if "mosek_cli" in settings["default_solver"]: 

214 with self.assertRaises(UnknownInfeasible): 

215 example.gp.solve(verbosity=0) 

216 else: 

217 example.gp.solve(verbosity=0) # mosek_conif and cvxopt solve it 

218 

219 def test_vectorize(self, example): 

220 pass 

221 

222 def test_primal_infeasible_ex1(self, example): 

223 primal_or_unknown = PrimalInfeasible 

224 if "cvxopt" in settings["default_solver"]: # pragma: no cover 

225 primal_or_unknown = UnknownInfeasible 

226 with self.assertRaises(primal_or_unknown): 

227 example.m.solve(verbosity=0) 

228 

229 def test_primal_infeasible_ex2(self, example): 

230 primal_or_unknown = PrimalInfeasible 

231 if "cvxopt" in settings["default_solver"]: # pragma: no cover 

232 primal_or_unknown = UnknownInfeasible 

233 with self.assertRaises(primal_or_unknown): 

234 example.m.solve(verbosity=0) 

235 

236 def test_docstringparsing(self, example): 

237 pass 

238 

239 def test_debug(self, example): 

240 dual_or_primal = DualInfeasible 

241 if "mosek_conif" == settings["default_solver"]: # pragma: no cover 

242 dual_or_primal = PrimalInfeasible 

243 with self.assertRaises(UnboundedGP): 

244 example.m.gp() 

245 with self.assertRaises(dual_or_primal): 

246 gp = example.m.gp(checkbounds=False) 

247 gp.solve(verbosity=0) 

248 

249 primal_or_unknown = PrimalInfeasible 

250 if "cvxopt" == settings["default_solver"]: # pragma: no cover 

251 primal_or_unknown = UnknownInfeasible 

252 with self.assertRaises(primal_or_unknown): 

253 example.m2.solve(verbosity=0) 

254 

255 with self.assertRaises(UnboundedGP): 

256 example.m3.gp() 

257 with self.assertRaises(DualInfeasible): 

258 gp3 = example.m3.gp(checkbounds=False) 

259 gp3.solve(verbosity=0) 

260 

261 def test_simple_sp(self, example): 

262 pass 

263 

264 def test_simple_box(self, example): 

265 pass 

266 

267 def test_x_greaterthan_1(self, example): 

268 pass 

269 

270 def test_beam(self, example): 

271 self.assertFalse(np.isnan(example.sol("w")).any()) 

272 

273 def test_water_tank(self, example): 

274 pass 

275 

276 def test_sin_approx_example(self, example): 

277 pass 

278 

279 def test_simpleflight(self, example): 

280 self.assertTrue(example.sol.almost_equal(example.sol_loaded)) 

281 for sol in [example.sol, example.sol_loaded]: 

282 freevarcheck = { 

283 "A": 8.46, 

284 "C_D": 0.0206, 

285 "C_f": 0.0036, 

286 "C_L": 0.499, 

287 "Re": 3.68e+06, 

288 "S": 16.4, 

289 "W": 7.34e+03, 

290 "V": 38.2, 

291 "W_w": 2.40e+03 

292 } 

293 # sensitivity values from p. 34 of W. Hoburg's thesis 

294 senscheck = { 

295 r"(\frac{S}{S_{wet}})": 0.4300, 

296 "e": -0.4785, 

297 "V_{min}": -0.3691, 

298 "k": 0.4300, 

299 r"\mu": 0.0860, 

300 "(CDA0)": 0.0915, 

301 "C_{L,max}": -0.1845, 

302 r"\tau": -0.2903, 

303 "N_{ult}": 0.2903, 

304 "W_0": 1.0107, 

305 r"\rho": -0.2275 

306 } 

307 for key in freevarcheck: 

308 sol_rat = mag(sol["variables"][key])/freevarcheck[key] 

309 self.assertTrue(abs(1-sol_rat) < 1e-2) 

310 for key in senscheck: 

311 sol_rat = sol["sensitivities"]["variables"][key]/senscheck[key] 

312 self.assertTrue(abs(1-sol_rat) < 1e-2) 

313 

314 def test_relaxation(self, example): 

315 pass 

316 

317 def test_unbounded(self, example): 

318 pass 

319 

320 

321FILE_DIR = os.path.dirname(os.path.realpath(__file__)) 

322EXAMPLE_DIR = os.path.abspath(FILE_DIR + '../../../docs/source/examples') 

323SOLVERS = settings["installed_solvers"] 

324if os.path.isdir(EXAMPLE_DIR): 

325 TESTS = generate_example_tests(EXAMPLE_DIR, [TestExamples], SOLVERS) 

326else: # pragma: no cover 

327 TESTS = [] 

328 

329if __name__ == "__main__": # pragma: no cover 

330 # pylint:disable=wrong-import-position 

331 from gpkit.tests.helpers import run_tests 

332 run_tests(TESTS)