def _configure_sympy(sympy, available): if not available: return _operatorMap.update({ sympy.Add: _sum, sympy.Mul: _prod, sympy.Pow: lambda x, y: x**y, sympy.exp: lambda x: EXPR.exp(x), sympy.log: lambda x: EXPR.log(x), sympy.sin: lambda x: EXPR.sin(x), sympy.asin: lambda x: EXPR.asin(x), sympy.sinh: lambda x: EXPR.sinh(x), sympy.asinh: lambda x: EXPR.asinh(x), sympy.cos: lambda x: EXPR.cos(x), sympy.acos: lambda x: EXPR.acos(x), sympy.cosh: lambda x: EXPR.cosh(x), sympy.acosh: lambda x: EXPR.acosh(x), sympy.tan: lambda x: EXPR.tan(x), sympy.atan: lambda x: EXPR.atan(x), sympy.tanh: lambda x: EXPR.tanh(x), sympy.atanh: lambda x: EXPR.atanh(x), sympy.ceiling: lambda x: EXPR.ceil(x), sympy.floor: lambda x: EXPR.floor(x), sympy.sqrt: lambda x: EXPR.sqrt(x), sympy.Abs: lambda x: abs(x), sympy.Derivative: _nondifferentiable, sympy.Tuple: lambda *x: x, }) _pyomo_operator_map.update({ EXPR.SumExpression: sympy.Add, EXPR.ProductExpression: sympy.Mul, EXPR.NPV_ProductExpression: sympy.Mul, EXPR.MonomialTermExpression: sympy.Mul, }) _functionMap.update({ 'exp': sympy.exp, 'log': sympy.log, 'log10': lambda x: sympy.log(x) / sympy.log(10), 'sin': sympy.sin, 'asin': sympy.asin, 'sinh': sympy.sinh, 'asinh': sympy.asinh, 'cos': sympy.cos, 'acos': sympy.acos, 'cosh': sympy.cosh, 'acosh': sympy.acosh, 'tan': sympy.tan, 'atan': sympy.atan, 'tanh': sympy.tanh, 'atanh': sympy.atanh, 'ceil': sympy.ceiling, 'floor': sympy.floor, 'sqrt': sympy.sqrt, })
def _diff_PowExpression(node, val_dict, der_dict): """ Parameters ---------- node: pyomo.core.expr.numeric_expr.PowExpression val_dict: ComponentMap der_dict: ComponentMap """ assert len(node.args) == 2 arg1, arg2 = node.args der = der_dict[node] val1 = val_dict[arg1] val2 = val_dict[arg2] der_dict[arg1] += der * val2 * val1**(val2 - 1) if arg2.__class__ not in nonpyomo_leaf_types: der_dict[arg2] += der * val1**val2 * log(val1)
def test_model_with_unrelated_nonlinear_expressions(self): m = ConcreteModel() m.x = Var([1, 2, 3], bounds=(0, 3)) m.y = Var() m.z = Var() @m.Constraint([1, 2]) def cons(m, i): return m.x[i] <= m.y**i m.cons2 = Constraint(expr=m.x[1] >= m.y) m.cons3 = Constraint(expr=m.x[2] >= m.z - 3) # This is vacuous, but I just want something that's not quadratic m.cons4 = Constraint(expr=m.x[3] <= log(m.y + 1)) fme = TransformationFactory('contrib.fourier_motzkin_elimination') fme.apply_to(m, vars_to_eliminate=m.x, constraint_filtering_callback=None) constraints = m._pyomo_contrib_fme_transformation.projected_constraints # 0 <= y <= 3 cons = constraints[6] self.assertEqual(cons.lower, 0) self.assertIs(cons.body, m.y) cons = constraints[5] self.assertEqual(cons.lower, -3) body = generate_standard_repn(cons.body) self.assertTrue(body.is_linear()) self.assertEqual(len(body.linear_vars), 1) self.assertIs(body.linear_vars[0], m.y) self.assertEqual(body.linear_coefs[0], -1) # z <= y**2 + 3 cons = constraints[4] self.assertEqual(cons.lower, -3) body = generate_standard_repn(cons.body) self.assertTrue(body.is_quadratic()) self.assertEqual(len(body.linear_vars), 1) self.assertIs(body.linear_vars[0], m.z) self.assertEqual(body.linear_coefs[0], -1) self.assertEqual(len(body.quadratic_vars), 1) self.assertEqual(body.quadratic_coefs[0], 1) self.assertIs(body.quadratic_vars[0][0], m.y) self.assertIs(body.quadratic_vars[0][1], m.y) # z <= 6 cons = constraints[2] self.assertEqual(cons.lower, -6) body = generate_standard_repn(cons.body) self.assertTrue(body.is_linear()) self.assertEqual(len(body.linear_vars), 1) self.assertEqual(body.linear_coefs[0], -1) self.assertIs(body.linear_vars[0], m.z) # 0 <= ln(y+ 1) cons = constraints[1] self.assertEqual(cons.lower, 0) body = generate_standard_repn(cons.body) self.assertTrue(body.is_nonlinear()) self.assertFalse(body.is_quadratic()) self.assertEqual(len(body.linear_vars), 0) self.assertEqual(body.nonlinear_expr.name, 'log') self.assertEqual(len(body.nonlinear_expr.args[0].args), 2) self.assertIs(body.nonlinear_expr.args[0].args[0], m.y) self.assertEqual(body.nonlinear_expr.args[0].args[1], 1) # 0 <= y**2 cons = constraints[3] self.assertEqual(cons.lower, 0) body = generate_standard_repn(cons.body) self.assertTrue(body.is_quadratic()) self.assertEqual(len(body.quadratic_vars), 1) self.assertEqual(body.quadratic_coefs[0], 1) self.assertIs(body.quadratic_vars[0][0], m.y) self.assertIs(body.quadratic_vars[0][1], m.y) # check constraints valid for a selection of points (this is nonconvex, # but anyway...) pts = [ #(sqrt(3), 6), Not numerically stable enough for this test (1, 4), (3, 6), (3, 0), (0, 0), (2, 6) ] for pt in pts: m.y.fix(pt[0]) m.z.fix(pt[1]) for i in constraints: self.assertLessEqual(value(constraints[i].lower), value(constraints[i].body)) m.y.fixed = False m.z.fixed = False # check post process these are non-convex, so I don't want to deal with # it... (and this is a good test that I *don't* deal with it.) constraints[4].deactivate() constraints[3].deactivate() constraints[1].deactivate() # NOTE also that some of the suproblems in this test are unbounded: We # need to keep those constraints. fme.post_process_fme_constraints(m, SolverFactory('glpk')) # we needed all the constraints, so we kept them all self.assertEqual(len(constraints), 6) # last check that if someone activates something on the model in # between, we just use it. (I struggle to imagine why you would do this # because why withold the information *during* FME, but if there's some # reason, we may as well use all the information we've got.) m.some_new_cons = Constraint(expr=m.y <= 2) fme.post_process_fme_constraints(m, SolverFactory('glpk')) # now we should have lost one constraint self.assertEqual(len(constraints), 5) # and it should be the y <= 3 one... self.assertIsNone(dict(constraints).get(5))
def build_nonexclusive_model(): m = ConcreteModel() m.streams = RangeSet(25) m.x = Var(m.streams, bounds=(0, 50), initialize=5) m.stage1_split = Constraint(expr=m.x[1] == m.x[2] + m.x[4]) m.unit1 = Disjunction(expr=[ [ # Unit 1 m.x[2] == exp(m.x[3]) - 1, ], [ # No Unit 1 m.x[2] == 0, m.x[3] == 0 ] ]) m.unit2 = Disjunction(expr=[ [ # Unit 2 m.x[5] == log(m.x[4] + 1), ], [ # No Unit 2 m.x[4] == 0, m.x[5] == 0 ] ]) m.stage1_mix = Constraint(expr=m.x[3] + m.x[5] == m.x[6]) m.stage2_split = Constraint(expr=m.x[6] == sum(m.x[i] for i in (7, 9, 11, 13))) m.unit3 = Disjunction(expr=[ [ # Unit 3 m.x[8] == 2 * log(m.x[7]) + 3, m.x[7] >= 0.2, ], [ # No Unit 3 m.x[7] == 0, m.x[8] == 0 ] ]) m.unit4 = Disjunction(expr=[ [ # Unit 4 m.x[10] == 1.8 * log(m.x[9] + 4), ], [ # No Unit 4 m.x[9] == 0, m.x[10] == 0 ] ]) m.unit5 = Disjunction(expr=[ [ # Unit 5 m.x[12] == 1.2 * log(m.x[11]) + 2, m.x[11] >= 0.001, ], [ # No Unit 5 m.x[11] == 0, m.x[12] == 0 ] ]) m.unit6 = Disjunction(expr=[ [ # Unit 6 m.x[15] == sqrt(m.x[14] - 3) * m.x[23] + 1, m.x[14] >= 5, m.x[14] <= 20, ], [ # No Unit 6 m.x[14] == 0, m.x[15] == 0 ] ]) m.stage2_special_mix = Constraint(expr=m.x[14] == m.x[13] + m.x[23]) m.stage2_mix = Constraint(expr=sum(m.x[i] for i in (8, 10, 12, 15)) == m.x[16]) m.stage3_split = Constraint(expr=m.x[16] == sum(m.x[i] for i in (17, 19, 21))) m.unit7 = Disjunction(expr=[ [ # Unit 7 m.x[18] == m.x[17] * 0.9, ], [ # No Unit 7 m.x[17] == 0, m.x[18] == 0 ] ]) m.unit8 = Disjunction(expr=[ [ # Unit 8 m.x[20] == log(m.x[19] ** 1.5) + 2, m.x[19] >= 1, ], [ # No Unit 8 m.x[19] == 0, m.x[20] == 0 ] ]) m.unit9 = Disjunction(expr=[ [ # Unit 9 m.x[22] == log(m.x[21] + sqrt(m.x[21])) + 1, m.x[21] >= 4, ], [ # No Unit 9 m.x[21] == 0, m.x[22] == 0 ] ]) m.stage3_special_split = Constraint(expr=m.x[22] == m.x[23] + m.x[24]) m.stage3_mix = Constraint(expr=m.x[25] == sum(m.x[i] for i in (18, 20, 24))) m.obj = Objective(expr=-10 * m.x[25] + m.x[1]) return m
def build_model(): """ Base Model Optimal solution: Select units 1, 3, 8 Objective value -36.62 """ m = ConcreteModel() m.streams = RangeSet(25) m.x = Var(m.streams, bounds=(0, 50), initialize=5) m.stage1_split = Constraint(expr=m.x[1] == m.x[2] + m.x[4]) m.first_stage = Disjunction(expr=[ [ # Unit 1 m.x[2] == exp(m.x[3]) - 1, m.x[4] == 0, m.x[5] == 0 ], [ # Unit 2 m.x[5] == log(m.x[4] + 1), m.x[2] == 0, m.x[3] == 0 ] ]) m.stage1_mix = Constraint(expr=m.x[3] + m.x[5] == m.x[6]) m.stage2_split = Constraint(expr=m.x[6] == sum(m.x[i] for i in (7, 9, 11, 13))) m.second_stage = Disjunction(expr=[ [ # Unit 3 m.x[8] == 2 * log(m.x[7]) + 3, m.x[7] >= 0.2, ] + [m.x[i] == 0 for i in (9, 10, 11, 12, 14, 15)], [ # Unit 4 m.x[10] == 1.8 * log(m.x[9] + 4), ] + [m.x[i] == 0 for i in (7, 8, 11, 12, 14, 15)], [ # Unit 5 m.x[12] == 1.2 * log(m.x[11]) + 2, m.x[11] >= 0.001, ] + [m.x[i] == 0 for i in (7, 8, 9, 10, 14, 15)], [ # Unit 6 m.x[15] == sqrt(m.x[14] - 3) * m.x[23] + 1, m.x[14] >= 5, m.x[14] <= 20, ] + [m.x[i] == 0 for i in (7, 8, 9, 10, 11, 12)] ]) m.stage2_special_mix = Constraint(expr=m.x[14] == m.x[13] + m.x[23]) m.stage2_mix = Constraint(expr=sum(m.x[i] for i in (8, 10, 12, 15)) == m.x[16]) m.stage3_split = Constraint(expr=m.x[16] == sum(m.x[i] for i in (17, 19, 21))) m.third_stage = Disjunction(expr=[ [ # Unit 7 m.x[18] == m.x[17] * 0.9, ] + [m.x[i] == 0 for i in (19, 20, 21, 22)], [ # Unit 8 m.x[20] == log(m.x[19] ** 1.5) + 2, m.x[19] >= 1, ] + [m.x[i] == 0 for i in (17, 18, 21, 22)], [ # Unit 9 m.x[22] == log(m.x[21] + sqrt(m.x[21])) + 1, m.x[21] >= 4, ] + [m.x[i] == 0 for i in (17, 18, 19, 20)] ]) m.stage3_special_split = Constraint(expr=m.x[22] == m.x[23] + m.x[24]) m.stage3_mix = Constraint(expr=m.x[25] == sum(m.x[i] for i in (18, 20, 24))) m.obj = Objective(expr=-10 * m.x[25] + m.x[1]) return m
if type(x[1]) is tuple: # sympy >= 1.3 returns tuples (var, order) wrt = x[1][0] else: # early versions of sympy returned the bare var wrt = x[1] raise NondifferentiableError( "The sub-expression '%s' is not differentiable with respect to %s" % (x[0], wrt)) _operatorMap = { sympy.Add: _sum, sympy.Mul: _prod, sympy.Pow: lambda x, y: x**y, sympy.exp: lambda x: current.exp(x), sympy.log: lambda x: current.log(x), sympy.sin: lambda x: current.sin(x), sympy.asin: lambda x: current.asin(x), sympy.sinh: lambda x: current.sinh(x), sympy.asinh: lambda x: current.asinh(x), sympy.cos: lambda x: current.cos(x), sympy.acos: lambda x: current.acos(x), sympy.cosh: lambda x: current.cosh(x), sympy.acosh: lambda x: current.acosh(x), sympy.tan: lambda x: current.tan(x), sympy.atan: lambda x: current.atan(x), sympy.tanh: lambda x: current.tanh(x), sympy.atanh: lambda x: current.atanh(x), sympy.ceiling: lambda x: current.ceil(x), sympy.floor: lambda x: current.floor(x), sympy.sqrt: lambda x: current.sqrt(x),
def test_model_with_unrelated_nonlinear_expressions(self): m = ConcreteModel() m.x = Var([1, 2, 3], bounds=(0, 3)) m.y = Var() m.z = Var() @m.Constraint([1, 2]) def cons(m, i): return m.x[i] <= m.y**i m.cons2 = Constraint(expr=m.x[1] >= m.y) m.cons3 = Constraint(expr=m.x[2] >= m.z - 3) # This is vacuous, but I just want something that's not quadratic m.cons4 = Constraint(expr=m.x[3] <= log(m.y + 1)) TransformationFactory('contrib.fourier_motzkin_elimination').\ apply_to(m, vars_to_eliminate=m.x) constraints = m._pyomo_contrib_fme_transformation.projected_constraints # 0 <= y <= 3 cons = constraints[6] self.assertEqual(cons.lower, 0) self.assertIs(cons.body, m.y) cons = constraints[5] self.assertEqual(cons.lower, -3) body = generate_standard_repn(cons.body) self.assertTrue(body.is_linear()) self.assertEqual(len(body.linear_vars), 1) self.assertIs(body.linear_vars[0], m.y) self.assertEqual(body.linear_coefs[0], -1) # z <= y**2 + 3 cons = constraints[4] self.assertEqual(cons.lower, -3) body = generate_standard_repn(cons.body) self.assertTrue(body.is_quadratic()) self.assertEqual(len(body.linear_vars), 1) self.assertIs(body.linear_vars[0], m.z) self.assertEqual(body.linear_coefs[0], -1) self.assertEqual(len(body.quadratic_vars), 1) self.assertEqual(body.quadratic_coefs[0], 1) self.assertIs(body.quadratic_vars[0][0], m.y) self.assertIs(body.quadratic_vars[0][1], m.y) # z <= 6 cons = constraints[2] self.assertEqual(cons.lower, -6) body = generate_standard_repn(cons.body) self.assertTrue(body.is_linear()) self.assertEqual(len(body.linear_vars), 1) self.assertEqual(body.linear_coefs[0], -1) self.assertIs(body.linear_vars[0], m.z) # 0 <= ln(y+ 1) cons = constraints[1] self.assertEqual(cons.lower, 0) body = generate_standard_repn(cons.body) self.assertTrue(body.is_nonlinear()) self.assertFalse(body.is_quadratic()) self.assertEqual(len(body.linear_vars), 0) self.assertEqual(body.nonlinear_expr.name, 'log') self.assertEqual(len(body.nonlinear_expr.args[0].args), 2) self.assertIs(body.nonlinear_expr.args[0].args[0], m.y) self.assertEqual(body.nonlinear_expr.args[0].args[1], 1) # 0 <= y**2 cons = constraints[3] self.assertEqual(cons.lower, 0) body = generate_standard_repn(cons.body) self.assertTrue(body.is_quadratic()) self.assertEqual(len(body.quadratic_vars), 1) self.assertEqual(body.quadratic_coefs[0], 1) self.assertIs(body.quadratic_vars[0][0], m.y) self.assertIs(body.quadratic_vars[0][1], m.y) # check constraints valid for a selection of points (this is nonconvex, # but anyway...) pts = [ #(sqrt(3), 6), Not numerically stable enough for this test (1, 4), (3, 6), (3, 0), (0, 0), (2, 6) ] for pt in pts: m.y.fix(pt[0]) m.z.fix(pt[1]) for i in constraints: self.assertLessEqual(value(constraints[i].lower), value(constraints[i].body))