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 numpy as np 

6 

7from gpkit import settings, Model, Variable 

8from gpkit.tests.helpers import generate_example_tests 

9from gpkit.small_scripts import mag 

10from gpkit.small_classes import Quantity 

11from gpkit.constraints.loose import Loose 

12from gpkit.exceptions import (UnknownInfeasible, 

13 PrimalInfeasible, DualInfeasible, UnboundedGP) 

14 

15 

16def assert_logtol(first, second, logtol=1e-6): 

17 "Asserts that the logs of two arrays have a given abstol" 

18 np.testing.assert_allclose(np.log(mag(first)), np.log(mag(second)), 

19 atol=logtol, rtol=0) 

20 

21 

22# pylint: disable=too-many-public-methods 

23class TestExamples(unittest.TestCase): 

24 """ 

25 To test a new example, add a function called `test_$EXAMPLENAME`, where 

26 $EXAMPLENAME is the name of your example in docs/source/examples without 

27 the file extension. 

28 

29 This function should accept two arguments (e.g. 'self' and 'example'). 

30 The imported example script will be passed to the second: anything that 

31 was a global variable (e.g, "sol") in the original script is available 

32 as an attribute (e.g., "example.sol") 

33 

34 If you don't want to perform any checks on the example besides making 

35 sure it runs, just put "pass" as the function's body, e.g.: 

36 

37 def test_dummy_example(self, example): 

38 pass 

39 

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

41 

42 def test_dummy_example(self, example): 

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

44 """ 

45 

46 # TODO: allow enabling plotting examples, make plots in correct folder... 

47 # def test_plot_sweep1d(self, _): 

48 # import matplotlib.pyplot as plt 

49 # plt.close("all") 

50 

51 def test_issue_1513(self, example): 

52 pass 

53 

54 def test_autosweep(self, example): 

55 from gpkit import ureg 

56 bst1, tol1 = example.bst1, example.tol1 

57 bst2, tol2 = example.bst2, example.tol2 

58 

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

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

61 sol1 = bst.sample_at(l_) 

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

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

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

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

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

67 

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

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

70 # before corner 

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

72 sol_bc = bst2.sample_at(A_bc) 

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

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

75 # after corner 

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

77 sol_ac = bst2.sample_at(A_ac) 

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

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

80 

81 def test_treemap(self, example): 

82 pass 

83 

84 def test_checking_result_changes(self, example): 

85 sol = example.sol 

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

87 

88 def test_evaluated_fixed_variables(self, example): 

89 sol = example.sol 

90 t_night = example.t_night 

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

92 

93 def test_evaluated_free_variables(self, example): 

94 x2 = example.x2 

95 sol = example.sol 

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

97 

98 def test_external_constraint(self, example): 

99 pass 

100 

101 def test_migp(self, example): 

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

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

104 else: 

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

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

107 

108 def test_external_function(self, example): 

109 external_code = example.external_code 

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

111 

112 def test_external_sp(self, example): 

113 m = example.m 

114 sol = m.localsolve(verbosity=0) 

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

116 

117 def test_freeing_fixed_variables(self, example): 

118 x = example.x 

119 y = Variable("y", 3) 

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

121 sol = m.solve(verbosity=0) 

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

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

124 

125 del m.substitutions["y"] 

126 sol = m.solve(verbosity=0) 

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

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

129 

130 def test_gettingstarted(self, example): 

131 pass 

132 

133 

134 def test_loose_constraintsets(self, example): 

135 m = example.m 

136 sol = m.solve(verbosity=0) 

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

138 

139 def test_sub_multi_values(self, example): 

140 x = example.x 

141 y = example.y 

142 z = example.z 

143 p = example.p 

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

145 self.assertTrue(all( 

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

147 )) 

148 

149 def test_substitutions(self, example): 

150 x = example.x 

151 p = example.p 

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

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

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

155 

156 def test_tight_constraintsets(self, example): 

157 m = example.m 

158 sol = m.solve(verbosity=0) 

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

160 

161 def test_vectorization(self, example): 

162 x = example.x 

163 y = example.y 

164 z = example.z 

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

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

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

168 

169 def test_model_var_access(self, example): 

170 model = example.PS 

171 _ = model["E"] 

172 with self.assertRaises(ValueError): 

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

174 

175 def test_performance_modeling(self, example): 

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

177 

178 sol = m.solve(verbosity=0) 

179 sol.table() 

180 sol.save("solution.pkl") 

181 sol.table() 

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

183 sol_loaded.table() 

184 

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

186 sweepsol.table() 

187 sweepsol.save("sweepsolution.pkl") 

188 sweepsol.table() 

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

190 sol_loaded.table() 

191 

192 def test_sp_to_gp_sweep(self, example): 

193 sol = example.sol 

194 cost = sol["cost"] 

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

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

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

198 

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

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

201 with self.assertRaises(UnknownInfeasible): 

202 example.gp.solve(verbosity=0) 

203 else: 

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

205 

206 def test_vectorize(self, example): 

207 pass 

208 

209 def test_primal_infeasible_ex1(self, example): 

210 primal_or_unknown = PrimalInfeasible 

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

212 primal_or_unknown = UnknownInfeasible 

213 with self.assertRaises(primal_or_unknown): 

214 example.m.solve(verbosity=0) 

215 

216 def test_primal_infeasible_ex2(self, example): 

217 primal_or_unknown = PrimalInfeasible 

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

219 primal_or_unknown = UnknownInfeasible 

220 with self.assertRaises(primal_or_unknown): 

221 example.m.solve(verbosity=0) 

222 

223 def test_docstringparsing(self, example): 

224 pass 

225 

226 def test_debug(self, example): 

227 dual_or_primal = DualInfeasible 

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

229 dual_or_primal = PrimalInfeasible 

230 with self.assertRaises(UnboundedGP): 

231 example.m.gp() 

232 with self.assertRaises(dual_or_primal): 

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

234 gp.solve(verbosity=0) 

235 

236 primal_or_unknown = PrimalInfeasible 

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

238 primal_or_unknown = UnknownInfeasible 

239 with self.assertRaises(primal_or_unknown): 

240 example.m2.solve(verbosity=0) 

241 

242 with self.assertRaises(UnboundedGP): 

243 example.m3.gp() 

244 with self.assertRaises(DualInfeasible): 

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

246 gp3.solve(verbosity=0) 

247 

248 def test_simple_sp(self, example): 

249 pass 

250 

251 def test_simple_box(self, example): 

252 pass 

253 

254 def test_x_greaterthan_1(self, example): 

255 pass 

256 

257 def test_beam(self, example): 

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

259 

260 def test_water_tank(self, example): 

261 pass 

262 

263 def test_sin_approx_example(self, example): 

264 pass 

265 

266 def test_simpleflight(self, example): 

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

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

269 freevarcheck = { 

270 "A": 8.46, 

271 "C_D": 0.0206, 

272 "C_f": 0.0036, 

273 "C_L": 0.499, 

274 "Re": 3.68e+06, 

275 "S": 16.4, 

276 "W": 7.34e+03, 

277 "V": 38.2, 

278 "W_w": 2.40e+03 

279 } 

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

281 senscheck = { 

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

283 "e": -0.4785, 

284 "V_{min}": -0.3691, 

285 "k": 0.4300, 

286 r"\mu": 0.0860, 

287 "(CDA0)": 0.0915, 

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

289 r"\tau": -0.2903, 

290 "N_{ult}": 0.2903, 

291 "W_0": 1.0107, 

292 r"\rho": -0.2275 

293 } 

294 for key in freevarcheck: 

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

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

297 for key in senscheck: 

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

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

300 

301 def test_relaxation(self, example): 

302 pass 

303 

304 def test_unbounded(self, example): 

305 pass 

306 

307 

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

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

310SOLVERS = settings["installed_solvers"] 

311if os.path.isdir(EXAMPLE_DIR): 

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

313else: # pragma: no cover 

314 TESTS = [] 

315 

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

317 # pylint:disable=wrong-import-position 

318 from gpkit.tests.helpers import run_tests 

319 run_tests(TESTS)