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_autosweep(self, example): 

52 from gpkit import ureg 

53 bst1, tol1 = example.bst1, example.tol1 

54 bst2, tol2 = example.bst2, example.tol2 

55 

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

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

58 sol1 = bst.sample_at(l_) 

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

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

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

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

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

64 

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

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

67 # before corner 

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

69 sol_bc = bst2.sample_at(A_bc) 

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

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

72 # after corner 

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

74 sol_ac = bst2.sample_at(A_ac) 

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

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

77 

78 def test_treemap(self, example): 

79 pass 

80 

81 def test_checking_result_changes(self, example): 

82 sol = example.sol 

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

84 

85 def test_evaluated_fixed_variables(self, example): 

86 sol = example.sol 

87 t_night = example.t_night 

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

89 

90 def test_evaluated_free_variables(self, example): 

91 x2 = example.x2 

92 sol = example.sol 

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

94 

95 def test_external_constraint(self, example): 

96 pass 

97 

98 def test_migp(self, example): 

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

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

101 else: 

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

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

104 

105 def test_external_function(self, example): 

106 external_code = example.external_code 

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

108 

109 def test_external_sp(self, example): 

110 m = example.m 

111 sol = m.localsolve(verbosity=0) 

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

113 

114 def test_freeing_fixed_variables(self, example): 

115 x = example.x 

116 y = Variable("y", 3) 

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

118 sol = m.solve(verbosity=0) 

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

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

121 

122 del m.substitutions["y"] 

123 sol = m.solve(verbosity=0) 

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

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

126 

127 def test_gettingstarted(self, example): 

128 pass 

129 

130 

131 def test_loose_constraintsets(self, example): 

132 m = example.m 

133 sol = m.solve(verbosity=0) 

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

135 

136 def test_sub_multi_values(self, example): 

137 x = example.x 

138 y = example.y 

139 z = example.z 

140 p = example.p 

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

142 self.assertTrue(all( 

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

144 )) 

145 

146 def test_substitutions(self, example): 

147 x = example.x 

148 p = example.p 

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

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

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

152 

153 def test_tight_constraintsets(self, example): 

154 m = example.m 

155 sol = m.solve(verbosity=0) 

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

157 

158 def test_vectorization(self, example): 

159 x = example.x 

160 y = example.y 

161 z = example.z 

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

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

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

165 

166 def test_model_var_access(self, example): 

167 model = example.PS 

168 _ = model["E"] 

169 with self.assertRaises(ValueError): 

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

171 

172 def test_performance_modeling(self, example): 

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

174 

175 sol = m.solve(verbosity=0) 

176 sol.table() 

177 sol.save("solution.pkl") 

178 sol.table() 

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

180 sol_loaded.table() 

181 

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

183 sweepsol.table() 

184 sweepsol.save("sweepsolution.pkl") 

185 sweepsol.table() 

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

187 sol_loaded.table() 

188 

189 def test_sp_to_gp_sweep(self, example): 

190 sol = example.sol 

191 cost = sol["cost"] 

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

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

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

195 

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

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

198 with self.assertRaises(UnknownInfeasible): 

199 example.gp.solve(verbosity=0) 

200 else: 

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

202 

203 def test_vectorize(self, example): 

204 pass 

205 

206 def test_primal_infeasible_ex1(self, example): 

207 primal_or_unknown = PrimalInfeasible 

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

209 primal_or_unknown = UnknownInfeasible 

210 with self.assertRaises(primal_or_unknown): 

211 example.m.solve(verbosity=0) 

212 

213 def test_primal_infeasible_ex2(self, example): 

214 primal_or_unknown = PrimalInfeasible 

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

216 primal_or_unknown = UnknownInfeasible 

217 with self.assertRaises(primal_or_unknown): 

218 example.m.solve(verbosity=0) 

219 

220 def test_docstringparsing(self, example): 

221 pass 

222 

223 def test_debug(self, example): 

224 dual_or_primal = DualInfeasible 

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

226 dual_or_primal = PrimalInfeasible 

227 with self.assertRaises(UnboundedGP): 

228 example.m.gp() 

229 with self.assertRaises(dual_or_primal): 

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

231 gp.solve(verbosity=0) 

232 

233 primal_or_unknown = PrimalInfeasible 

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

235 primal_or_unknown = UnknownInfeasible 

236 with self.assertRaises(primal_or_unknown): 

237 example.m2.solve(verbosity=0) 

238 

239 with self.assertRaises(UnboundedGP): 

240 example.m3.gp() 

241 with self.assertRaises(DualInfeasible): 

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

243 gp3.solve(verbosity=0) 

244 

245 def test_simple_sp(self, example): 

246 pass 

247 

248 def test_simple_box(self, example): 

249 pass 

250 

251 def test_x_greaterthan_1(self, example): 

252 pass 

253 

254 def test_beam(self, example): 

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

256 

257 def test_water_tank(self, example): 

258 pass 

259 

260 def test_sin_approx_example(self, example): 

261 pass 

262 

263 def test_simpleflight(self, example): 

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

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

266 freevarcheck = { 

267 "A": 8.46, 

268 "C_D": 0.0206, 

269 "C_f": 0.0036, 

270 "C_L": 0.499, 

271 "Re": 3.68e+06, 

272 "S": 16.4, 

273 "W": 7.34e+03, 

274 "V": 38.2, 

275 "W_w": 2.40e+03 

276 } 

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

278 senscheck = { 

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

280 "e": -0.4785, 

281 "V_{min}": -0.3691, 

282 "k": 0.4300, 

283 r"\mu": 0.0860, 

284 "(CDA0)": 0.0915, 

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

286 r"\tau": -0.2903, 

287 "N_{ult}": 0.2903, 

288 "W_0": 1.0107, 

289 r"\rho": -0.2275 

290 } 

291 for key in freevarcheck: 

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

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

294 for key in senscheck: 

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

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

297 

298 def test_relaxation(self, example): 

299 pass 

300 

301 def test_unbounded(self, example): 

302 pass 

303 

304 

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

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

307SOLVERS = settings["installed_solvers"] 

308if os.path.isdir(EXAMPLE_DIR): 

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

310else: # pragma: no cover 

311 TESTS = [] 

312 

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

314 # pylint:disable=wrong-import-position 

315 from gpkit.tests.helpers import run_tests 

316 run_tests(TESTS)