def test_htail(): Sw = Variable("S_w", 50, "ft**2", "wing area") cmac = Variable("cmac", 15, "in", "wing MAC") ht = HorizontalTail() fs = FlightState() ht.substitutions.update({ht.W: 5, ht.mh: 0.01, ht.planform.AR: 4, ht.Vh: 0.5, ht.lh: 10}) perf = ht.flight_model(ht, fs) m = Model(perf.Cd, [ht.Vh <= ht.planform.S*ht.lh/Sw/cmac, ht, perf]) m.solve(verbosity=0)
def test_trivial_vector_gp(self): "Create and solve a trivial GP with VectorVariables" x = VectorVariable(2, "x") y = VectorVariable(2, "y") prob = Model(cost=(sum(x) + 2 * sum(y)), constraints=[x * y >= 1]) sol = prob.solve(solver=self.solver, verbosity=0) self.assertEqual(sol("x").shape, (2, )) self.assertEqual(sol("y").shape, (2, )) for x, y in zip(sol("x"), sol("y")): self.assertAlmostEqual(x, np.sqrt(2.), self.ndig) self.assertAlmostEqual(y, 1 / np.sqrt(2.), self.ndig) self.assertAlmostEqual(sol["cost"] / (4 * np.sqrt(2)), 1., self.ndig)
def test_units_sub(self): # issue 809 T = Variable("T", "N", "thrust") Tmin = Variable("T_{min}", "N", "minimum thrust") m = Model(T, [T >= Tmin]) tminsub = 1000 * gpkit.ureg.lbf m.substitutions.update({Tmin: tminsub}) sol = m.solve(verbosity=0) self.assertEqual(sol(Tmin), tminsub) self.assertFalse( "1000N" in sol.table().replace(" ", "").replace("[", "").replace("]", ""))
def test_mdd_example(self): Cl = Variable("Cl", 0.5, "-", "Lift Coefficient") Mdd = Variable("Mdd", "-", "Drag Divergence Mach Number") m1 = Model(1 / Mdd, [1 >= 5 * Mdd + 0.5, Mdd >= 0.00001]) m2 = Model(1 / Mdd, [1 >= 5 * Mdd + 0.5]) m3 = Model(1 / Mdd, [1 >= 5 * Mdd + Cl, Mdd >= 0.00001]) sol1 = m1.solve(solver=self.solver, verbosity=0) sol2 = m2.solve(solver=self.solver, verbosity=0) sol3 = m3.solve(solver=self.solver, verbosity=0) # pylint: disable=no-member gp1, gp2, gp3 = [m.program for m in [m1, m2, m3]] self.assertEqual( gp1.A, CootMatrix(row=[0, 1, 2], col=[0, 0, 0], data=[-1, 1, -1])) self.assertEqual(gp2.A, CootMatrix(row=[0, 1], col=[0, 0], data=[-1, 1])) self.assertEqual( gp3.A, CootMatrix(row=[0, 1, 2], col=[0, 0, 0], data=[-1, 1, -1])) self.assertAlmostEqual(sol1(Mdd), sol2(Mdd)) self.assertAlmostEqual(sol1(Mdd), sol3(Mdd)) self.assertAlmostEqual(sol2(Mdd), sol3(Mdd))
def test_fmincon_generator_logspace(self): "Test fmincon comparison tool (logspace)" x = Variable('x') y = Variable('y') m = Model(x, [x**3.2 >= 17 * y + y**-0.2, x >= 2, y == 4]) obj, c, ceq, _, _ = generate_mfiles(m, writefiles=False, logspace=True) self.assertEqual(c, [('log( + 1.0*exp( +-3.2 * x(2) +-0.2 * x(1) ) + ' + '17.0*exp( +-3.2 * x(2) +1 * x(1) ) )'), 'log( + 2.0*exp( +-1 * x(2) ) )']) self.assertEqual(obj, 'log( + 1.0*exp( +1 * x(2) ) )') self.assertEqual(ceq, ['log( + 0.25*exp( +1 * x(1) ) )'])
def test_posyconstr_in_sp(self): x = Variable('x') y = Variable('y') with SignomialsEnabled(): sig_constraint = (x + y >= 0.1) m = Model(x * y, [Tight([x >= y]), x >= 2, y >= 1, sig_constraint]) sol = m.localsolve(verbosity=0) self.assertIs(sol["warnings"]["Unexpectedly Loose Constraints"][0][1], m[0][0]) self.assertAlmostEqual(m[0][0].rel_diff, 1, 3) m.pop(1) self.assertAlmostEqual(m.localsolve(verbosity=0)["cost"], 1, 5)
def test_unbounded_debugging(self): "Test nearly-dual-feasible problems" x = Variable("x") y = Variable("y") m = Model(x * y, [x * y**1.01 >= 100]) with self.assertRaises((DualInfeasible, UnknownInfeasible)): m.solve(self.solver, verbosity=0) # test one-sided bound m = Model(x * y, Bounded(m, verbosity=0, lower=0.001)) sol = m.solve(self.solver, verbosity=0) bounds = sol["boundedness"] self.assertEqual(bounds["sensitive to lower bound"], set([x.key])) # end test one-sided bound m = Model(x * y, Bounded(m, verbosity=0)) sol = m.solve(self.solver, verbosity=0) bounds = sol["boundedness"] # depends on solver, platform, whims of the numerical deities if "sensitive to upper bound" in bounds: # pragma: no cover self.assertIn(y.key, bounds["sensitive to upper bound"]) else: # pragma: no cover self.assertIn(x.key, bounds["sensitive to lower bound"])
def test_model(): x = Variable('x') y = Variable('y') a = Variable('a', 0.6, pr=10) b = Variable('b', 0.5, pr=10) constraints = [ a * b * x + a * b * y <= 1, b * x / y + b * x * y + a * b**2 * x**2 <= 1 ] return Model((x * y)**-1, constraints)
def test_spsubs(self): x = Variable("x", 5) y = Variable("y", lambda c: 2 * c[x]) z = Variable("z") w = Variable("w") with SignomialsEnabled(): cnstr = [z + w >= y * x, w <= y] m = Model(z, cnstr) m.localsolve(verbosity=0) self.assertTrue(m.substitutions["y"], "__call__")
def test_skipfailures(self): x = Variable("x") x_min = Variable("x_{min}", [1, 2]) m = Model(x, [x <= 1, x >= x_min]) sol = m.solve(verbosity=0, skipsweepfailures=True) sol.table() self.assertEqual(len(sol), 1) m.substitutions[x_min][1][0] = 5 with self.assertRaises(RuntimeWarning): sol = m.solve(verbosity=0, skipsweepfailures=True)
def test_small_named_signomial(self): x = Variable('x') z = Variable('z') local_ndig = 4 nonzero_adder = 0.1 # TODO: support reaching zero, issue #348 with SignomialsEnabled(): J = 0.01 * (x - 1)**2 + nonzero_adder with NamedVariables("SmallSignomial"): m = Model(z, [z >= J]) sol = m.localsolve(verbosity=0) self.assertAlmostEqual(sol['cost'], nonzero_adder, local_ndig) self.assertAlmostEqual(sol('x'), 0.98725425, self.ndig)
def test_zero_lower_unbounded(self): x = Variable('x', value=4) y = Variable('y', value=0) z = Variable('z') t1 = Variable('t1') t2 = Variable('t2') prob = Model(z, [z >= x + t1, t1 >= t2, t2 >= y]) prob.zero_lower_unbounded_variables() sol = prob.solve(verbosity=0) self.assertAlmostEqual(sol["cost"] / x.value, 1, self.ndig) self.assertAlmostEqual(sol("t2"), 0, self.ndig)
def test_vtail(): Sw = Variable("S_w", 50, "ft**2", "wing area") bw = Variable("b_w", 20, "ft", "wing span") vt = VerticalTail() fs = FlightState() vt.substitutions.update({vt.W: 5, vt.planform.AR: 3, vt.Vv: 0.04, vt.lv: 10, vt.planform.tau: 0.08}) perf = vt.flight_model(vt, fs) m = Model(perf.Cd, [vt.Vv <= vt.planform.S*vt.lv/Sw/bw, vt, fs, perf]) m.solve(verbosity=0)
def test_linked_sweep(self): def night_hrs(day_hrs): "twenty four minus day hours" return 24 - day_hrs t_day = Variable("t_{day}", "hours") t_night = Variable("t_{night}", night_hrs, "hours", args=[t_day]) x = Variable("x", "hours") m = Model(x, [x >= t_day, x >= t_night]) m.substitutions.update({t_day: ("sweep", [8, 12, 16])}) sol = m.solve(verbosity=0) self.assertEqual(len(sol["cost"]), 3) npt.assert_allclose(sol(t_day) + sol(t_night), 24)
def test_small_named_signomial(self): x = Variable("x") z = Variable("z") local_ndig = 4 nonzero_adder = 0.1 with SignomialsEnabled(): J = 0.01 * (x - 1)**2 + nonzero_adder with NamedVariables("SmallSignomial"): m = Model(z, [z >= J]) sol = m.localsolve(verbosity=0, solver=self.solver) self.assertAlmostEqual(sol["cost"], nonzero_adder, local_ndig) self.assertAlmostEqual(sol("x"), 0.98725425, self.ndig)
def test_posyconstr_in_sp(self): x = Variable('x') y = Variable('y') with SignomialsEnabled(): sig_constraint = (x + y >= 0.1) m = Model( x, [Tight([x >= y], raiseerror=True), x >= 2, y >= 1, sig_constraint]) with self.assertRaises(ValueError): m.localsolve(verbosity=0) m.pop(1) self.assertAlmostEqual(m.localsolve(verbosity=0)["cost"], 1)
def test_sp_relaxation(self): w = Variable('w') x = Variable('x') y = Variable('y') z = Variable('z') with SignomialsEnabled(): m = Model(x, [x + y >= w, x + y <= z / 2, y <= x, y >= 1], { z: 3, w: 3 }) r1 = ConstantsRelaxed(m) self.assertEqual(len(r1.varkeys), 8) mr1 = Model(x * r1.relaxvars.prod()**10, r1) cost1 = mr1.localsolve(verbosity=0)["cost"] self.assertAlmostEqual(cost1 / 1024, 1, self.ndig) m.debug(verbosity=0) with SignomialsEnabled(): m = Model(x, [x + y >= z, x + y <= z / 2, y <= x, y >= 1], {z: 3}) if self.solver != "cvxopt": m.debug(verbosity=0) r2 = ConstraintsRelaxed(m) self.assertEqual(len(r2.varkeys), 7) mr2 = Model(x * r2.relaxvars.prod()**10, r2) cost2 = mr2.localsolve(verbosity=0)["cost"] self.assertAlmostEqual(cost2 / 1024, 1, self.ndig) with SignomialsEnabled(): m = Model(x, [x + y >= z, x + y <= z / 2, y <= x, y >= 1], {z: 3}) if self.solver != "cvxopt": m.debug(verbosity=0) r3 = ConstraintsRelaxedEqually(m) self.assertEqual(len(r3.varkeys), 4) mr3 = Model(x * r3.relaxvar**10, r3) cost3 = mr3.localsolve(verbosity=0)["cost"] self.assertAlmostEqual(cost3 / (32 * 0.8786796585), 1, self.ndig)
def test_sp_bounded(self): x = Variable("x") y = Variable("y") with SignomialsEnabled(): m = Model(x, [x + y >= 1, y <= 0.1]) # solves cost = m.localsolve(verbosity=0, solver=self.solver)["cost"] self.assertAlmostEqual(cost, 0.9, self.ndig) with SignomialsEnabled(): m = Model(x, [x + y >= 1]) # dual infeasible with self.assertRaises((RuntimeWarning, ValueError)): m.localsolve(verbosity=0, solver=self.solver) with SignomialsEnabled(): m = Model(x, Bounded([x + y >= 1], verbosity=0)) sol = m.localsolve(verbosity=0, solver=self.solver) boundedness = sol["boundedness"] if "value near lower bound" in boundedness: self.assertIn(x.key, boundedness["value near lower bound"]) if "value near upper bound" in boundedness: self.assertIn(y.key, boundedness["value near upper bound"])
def test_composite_objective(self): L = Variable("L") W = Variable("W") eqns = [L >= 1, W >= 1, L * W == 10] obj = composite_objective(L + W, W**-1 * L**-3, sub={L: 1, W: 1}) m = Model(obj, eqns) sol = m.solve(verbosity=0) a = sol["sensitivities"]["variables"]["w_{CO}"].flatten() b = np.array([ 0, 0.98809322, 0.99461408, 0.99688676, 0.99804287, 0.99874303, 0.99921254, 0.99954926, 0.99980255, 1 ]) self.assertTrue((abs(a - b) / (a + b + 1e-7) < 1e-7).all())
def test_quantity_sub(self): if gpkit.units: x = Variable("x", 1, "cm") y = Variable("y", 1) self.assertEqual(x.sub({x: 1 * gpkit.units.m}).c.magnitude, 100) # NOTE: uncomment the below if requiring Quantity substitutions # self.assertRaises(ValueError, x.sub, x, 1) self.assertRaises(ValueError, x.sub, {x: 1 * gpkit.ureg.N}) self.assertRaises(ValueError, y.sub, {y: 1 * gpkit.ureg.N}) v = gpkit.VectorVariable(3, "v", "cm") subbed = v.sub({v: [1, 2, 3] * gpkit.ureg.m}) self.assertEqual([z.c.magnitude for z in subbed], [100, 200, 300]) v = VectorVariable(1, "v", "km") v_min = VectorVariable(1, "v_min", "km") m = Model(v.prod(), [v >= v_min], {v_min: [2 * gpkit.units("nmi")]}) cost = m.solve(verbosity=0)["cost"] self.assertAlmostEqual(cost / (3.704 * gpkit.ureg("km")), 1.0) m = Model(v.prod(), [v >= v_min], {v_min: np.array([2]) * gpkit.units("nmi")}) cost = m.solve(verbosity=0)["cost"] self.assertAlmostEqual(cost / (3.704 * gpkit.ureg("km")), 1.0)
def test_calcconst(self): x = Variable("x", "hours") t_day = Variable("t_{day}", 12, "hours") t_night = Variable("t_{night}", lambda c: 24 - c[t_day], "hours") m = Model(x, [x >= t_day, x >= t_night]) sol = m.solve(verbosity=0) self.assertAlmostEqual(sol(t_night) / gpkit.ureg.hours, 12) m.substitutions.update({t_day: ("sweep", [6, 8, 9, 13])}) sol = m.solve(verbosity=0) npt.assert_allclose(sol["sensitivities"]["constants"][t_day], [-1. / 3, -0.5, -0.6, +1], 1e-5) self.assertEqual(len(sol["cost"]), 4) npt.assert_allclose(sol(t_day) + sol(t_night), 24)
def test_cost_freeing(self): "Test freeing a variable that's in the cost." x = Variable("x", 1) x_min = Variable("x_{min}", 2) m = Model(x, [x >= x_min]) self.assertRaises((RuntimeWarning, ValueError), m.solve, solver=self.solver, verbosity=0) del m.substitutions["x"] self.assertAlmostEqual(m.solve(solver=self.solver, verbosity=0)["cost"], 2) del m.substitutions["x_{min}"] self.assertRaises((RuntimeWarning, ValueError), m.solve, solver=self.solver, verbosity=0)
def test_values_vs_subs(self): # Substitutions update method x = Variable("x") y = Variable("y") z = Variable("z") with SignomialsEnabled(): constraints = [x + y >= z, y >= x - 1] m = Model(x + y*z, constraints) m.substitutions.update({"z": 5}) sol = m.localsolve(verbosity=0) self.assertAlmostEqual(sol["cost"], 13, self.ndig) # Constant variable declaration method z = Variable("z", 5) with SignomialsEnabled(): constraints = [x + y >= z, y >= x - 1] m = Model(x + y*z, constraints) sol = m.localsolve(verbosity=0) self.assertAlmostEqual(sol["cost"], 13, self.ndig)
def test_result_access(self): x = Variable("x") y = Variable("y") with SignomialsEnabled(): sig = (y + 6 * x >= 13 + x**2) m = Model(y, [sig]) sol = m.localsolve(verbosity=0) self.assertTrue( all([ isinstance(gp.result.table(), Strings) for gp in m.program.gps ])) self.assertAlmostEqual(sol["cost"] / 4.0, 1.0, 5) self.assertAlmostEqual(sol("x") / 3.0, 1.0, 3)
def test_issue180(self): L = Variable("L") Lmax = Variable("L_{max}", 10) W = Variable("W") Wmax = Variable("W_{max}", 10) A = Variable("A", 10) Obj = Variable("Obj") a_val = 0.01 a = Variable("a", a_val) with SignomialsEnabled(): eqns = [ L <= Lmax, W <= Wmax, L * W >= A, Obj >= a * (2 * L + 2 * W) + (1 - a) * (12 * W**-1 * L**-3) ] m = Model(Obj, eqns) spsol = m.solve(self.solver, verbosity=0) # now solve as GP eqns[-1] = (Obj >= a_val * (2 * L + 2 * W) + (1 - a_val) * (12 * W**-1 * L**-3)) m = Model(Obj, eqns) gpsol = m.solve(self.solver, verbosity=0) self.assertAlmostEqual(spsol['cost'], gpsol['cost'])
def test_united_sub_sweep(self): A = Variable("A", "USD") h = Variable("h", "USD/count") Q = Variable("Q", "count") Y = Variable("Y", "USD") m = Model(Y, [Y >= h * Q + A / Q]) m.substitutions.update({ A: 500 * gpkit.units("USD"), h: 35 * gpkit.units("USD"), Q: ("sweep", [50, 100, 500]) }) firstcost = m.solve(verbosity=0)["cost"][0] self.assertAlmostEqual(firstcost, 1760, 3)
def test_singular(self): """ Create and solve GP with a singular A matrix """ if self.solver == 'cvxopt': # cvxopt can't solve this problem # (see https://github.com/cvxopt/cvxopt/issues/36) return x = Variable('x') y = Variable('y') m = Model(y * x, [y * x >= 12]) sol = m.solve(solver=self.solver, verbosity=0) self.assertAlmostEqual(sol["cost"], 12, self.ndig)
def test_initially_infeasible(self): x = Variable("x") y = Variable("y") with SignomialsEnabled(): sigc = x >= y + y**2 - y**3 sigc2 = x <= y**0.5 m = Model(1 / x, [sigc, sigc2, y <= 0.5]) sol = m.localsolve(verbosity=0, solver=self.solver) self.assertAlmostEqual(sol["cost"], 2**0.5, self.ndig) self.assertAlmostEqual(sol(y), 0.5, self.ndig)
def test_sigeq(self): x = Variable("x") y = VectorVariable(1, "y") # test vector input to sigeq c = Variable("c") with SignomialsEnabled(): m = Model(c, [ c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(x**2 + x, y) ]) sol = m.localsolve(solver=self.solver, verbosity=0) self.assertAlmostEqual(sol("x"), 0.1639472, self.ndig) self.assertAlmostEqual(sol("y"), 0.1908254, self.ndig) self.assertAlmostEqual(sol("c"), 0.2669448, self.ndig)
def test_sigeq(self): x = Variable("x") y = Variable("y") c = Variable("c") with SignomialsEnabled(): m = Model(c, [ c >= (x + 0.25)**2 + (y - 0.5)**2, SignomialEquality(x**2 + x, y) ]) sol = m.localsolve(verbosity=0) self.assertAlmostEqual(sol("x"), 0.1639472, 4) self.assertAlmostEqual(sol("y"), 0.1908254, 4) self.assertAlmostEqual(sol("c"), 0.2669448, 4)