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

79 sol = example.sol 

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

81 

82 def test_evaluated_fixed_variables(self, example): 

83 sol = example.sol 

84 t_night = example.t_night 

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

86 

87 def test_evaluated_free_variables(self, example): 

88 x2 = example.x2 

89 sol = example.sol 

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

91 

92 def test_external_constraint(self, example): 

93 pass 

94 

95 def test_migp(self, example): 

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

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

98 else: 

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

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

101 

102 def test_external_function(self, example): 

103 external_code = example.external_code 

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

105 

106 def test_external_sp(self, example): 

107 m = example.m 

108 sol = m.localsolve(verbosity=0) 

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

110 

111 def test_freeing_fixed_variables(self, example): 

112 x = example.x 

113 y = Variable("y", 3) 

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

115 sol = m.solve(verbosity=0) 

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

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

118 

119 del m.substitutions["y"] 

120 sol = m.solve(verbosity=0) 

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

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

123 

124 def test_gettingstarted(self, example): 

125 pass 

126 

127 

128 def test_loose_constraintsets(self, example): 

129 m = example.m 

130 sol = m.solve(verbosity=0) 

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

132 

133 def test_sub_multi_values(self, example): 

134 x = example.x 

135 y = example.y 

136 z = example.z 

137 p = example.p 

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

139 self.assertTrue(all( 

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

141 )) 

142 

143 def test_substitutions(self, example): 

144 x = example.x 

145 p = example.p 

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

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

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

149 

150 def test_tight_constraintsets(self, example): 

151 m = example.m 

152 sol = m.solve(verbosity=0) 

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

154 

155 def test_vectorization(self, example): 

156 x = example.x 

157 y = example.y 

158 z = example.z 

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

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

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

162 

163 def test_model_var_access(self, example): 

164 model = example.PS 

165 _ = model["E"] 

166 with self.assertRaises(ValueError): 

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

168 

169 def test_performance_modeling(self, example): 

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

171 

172 sol = m.solve(verbosity=0) 

173 sol.table() 

174 sol.save("solution.pkl") 

175 sol.table() 

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

177 sol_loaded.table() 

178 

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

180 sweepsol.table() 

181 sweepsol.save("sweepsolution.pkl") 

182 sweepsol.table() 

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

184 sol_loaded.table() 

185 

186 def test_sp_to_gp_sweep(self, example): 

187 sol = example.sol 

188 cost = sol["cost"] 

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

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

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

192 

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

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

195 with self.assertRaises(UnknownInfeasible): 

196 example.gp.solve(verbosity=0) 

197 else: 

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

199 

200 def test_vectorize(self, example): 

201 pass 

202 

203 def test_primal_infeasible_ex1(self, example): 

204 primal_or_unknown = PrimalInfeasible 

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

206 primal_or_unknown = UnknownInfeasible 

207 with self.assertRaises(primal_or_unknown): 

208 example.m.solve(verbosity=0) 

209 

210 def test_primal_infeasible_ex2(self, example): 

211 primal_or_unknown = PrimalInfeasible 

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

213 primal_or_unknown = UnknownInfeasible 

214 with self.assertRaises(primal_or_unknown): 

215 example.m.solve(verbosity=0) 

216 

217 def test_docstringparsing(self, example): 

218 pass 

219 

220 def test_debug(self, example): 

221 dual_or_primal = DualInfeasible 

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

223 dual_or_primal = PrimalInfeasible 

224 with self.assertRaises(UnboundedGP): 

225 example.m.gp() 

226 with self.assertRaises(dual_or_primal): 

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

228 gp.solve(verbosity=0) 

229 

230 primal_or_unknown = PrimalInfeasible 

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

232 primal_or_unknown = UnknownInfeasible 

233 with self.assertRaises(primal_or_unknown): 

234 example.m2.solve(verbosity=0) 

235 

236 with self.assertRaises(UnboundedGP): 

237 example.m3.gp() 

238 with self.assertRaises(DualInfeasible): 

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

240 gp3.solve(verbosity=0) 

241 

242 def test_simple_sp(self, example): 

243 pass 

244 

245 def test_simple_box(self, example): 

246 pass 

247 

248 def test_x_greaterthan_1(self, example): 

249 pass 

250 

251 def test_beam(self, example): 

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

253 

254 def test_water_tank(self, example): 

255 pass 

256 

257 def test_sin_approx_example(self, example): 

258 pass 

259 

260 def test_simpleflight(self, example): 

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

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

263 freevarcheck = { 

264 "A": 8.46, 

265 "C_D": 0.0206, 

266 "C_f": 0.0036, 

267 "C_L": 0.499, 

268 "Re": 3.68e+06, 

269 "S": 16.4, 

270 "W": 7.34e+03, 

271 "V": 38.2, 

272 "W_w": 2.40e+03 

273 } 

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

275 senscheck = { 

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

277 "e": -0.4785, 

278 "V_{min}": -0.3691, 

279 "k": 0.4300, 

280 r"\mu": 0.0860, 

281 "(CDA0)": 0.0915, 

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

283 r"\tau": -0.2903, 

284 "N_{ult}": 0.2903, 

285 "W_0": 1.0107, 

286 r"\rho": -0.2275 

287 } 

288 for key in freevarcheck: 

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

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

291 for key in senscheck: 

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

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

294 

295 def test_relaxation(self, example): 

296 pass 

297 

298 def test_unbounded(self, example): 

299 pass 

300 

301 

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

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

304SOLVERS = settings["installed_solvers"] 

305if os.path.isdir(EXAMPLE_DIR): 

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

307else: # pragma: no cover 

308 TESTS = [] 

309 

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

311 # pylint:disable=wrong-import-position 

312 from gpkit.tests.helpers import run_tests 

313 run_tests(TESTS)