def _hessian(xs, f_x_expr): hess = ComponentMap() df_dx_map = reverse_sd(f_x_expr) for x in xs: ddf_ddx_map = reverse_sd(df_dx_map[x]) hess[x] = ddf_ddx_map return hess
def test_log(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(1, 2)) m.y = pe.Var(bounds=(1, 2)) m.z = pe.Var() m.w = pe.Var() m.c = pe.Constraint(expr=pe.log(m.x * m.y) + m.z == 0) m.c2 = pe.Constraint(expr=m.w - 3 * pe.log(m.x * m.y) == 0) rel = coramin.relaxations.relax(m) self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 2) self.assertEqual(len(rel.aux_vars), 2) self.assertAlmostEqual(rel.aux_vars[1].lb, 1) self.assertAlmostEqual(rel.aux_vars[1].ub, 4) self.assertAlmostEqual(rel.aux_vars[2].lb, math.log(1)) self.assertAlmostEqual(rel.aux_vars[2].ub, math.log(4)) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[2]], 1) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 2) self.assertEqual(rel.aux_cons[2].lower, 0) self.assertEqual(rel.aux_cons[2].upper, 0) ders = reverse_sd(rel.aux_cons[2].body) self.assertEqual(ders[rel.w], 1) self.assertEqual(ders[rel.aux_vars[2]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[2].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue( isinstance(rel.relaxations.rel0, coramin.relaxations.PWMcCormickRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertIn(rel.y, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) self.assertTrue(hasattr(rel.relaxations, 'rel1')) self.assertTrue( isinstance(rel.relaxations.rel1, coramin.relaxations.PWUnivariateRelaxation)) self.assertIn(rel.aux_vars[1], ComponentSet(rel.relaxations.rel1.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[2]), id(rel.relaxations.rel1.get_aux_var())) self.assertFalse(rel.relaxations.rel1.is_rhs_convex()) self.assertTrue(rel.relaxations.rel1.is_rhs_concave()) self.assertFalse(hasattr(rel.relaxations, 'rel2'))
def test_cubic(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(-1,1)) m.y = pe.Var() m.z = pe.Var() m.w = pe.Var() m.c = pe.Constraint(expr=m.x**3 + m.y + m.z == 0) m.c2 = pe.Constraint(expr=m.w - 3*m.x**3 == 0) rel = coramin.relaxations.relax(m) # this problem should turn into # # aux2 + y + z = 0 => aux_con[1] # w - 3*aux2 = 0 => aux_con[2] # aux1 = x**2 => rel0 # aux2 = x*aux1 => rel1 self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 2) self.assertEqual(len(rel.aux_vars), 2) self.assertAlmostEqual(rel.aux_vars[1].lb, 0) self.assertAlmostEqual(rel.aux_vars[1].ub, 1) self.assertAlmostEqual(rel.aux_vars[2].lb, -1) self.assertAlmostEqual(rel.aux_vars[2].ub, 1) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[2]], 1) self.assertEqual(ders[rel.y], 1) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 3) self.assertEqual(rel.aux_cons[2].lower, 0) self.assertEqual(rel.aux_cons[2].upper, 0) ders = reverse_sd(rel.aux_cons[2].body) self.assertEqual(ders[rel.w], 1) self.assertEqual(ders[rel.aux_vars[2]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[2].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue(isinstance(rel.relaxations.rel0, coramin.relaxations.PWXSquaredRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) self.assertTrue(hasattr(rel.relaxations, 'rel1')) self.assertTrue(isinstance(rel.relaxations.rel1, coramin.relaxations.PWMcCormickRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel1.get_rhs_vars())) self.assertIn(rel.aux_vars[1], ComponentSet(rel.relaxations.rel1.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[2]), id(rel.relaxations.rel1.get_aux_var()))
def test_product3(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(-1,1)) m.y = pe.Var(bounds=(-1,1)) m.z = pe.Var() m.c = pe.Constraint(expr=m.z - m.x*m.y*3 == 0) rel = coramin.relaxations.relax(m) self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 1) self.assertEqual(len(rel.aux_vars), 1) self.assertAlmostEqual(rel.aux_vars[1].lb, -1) self.assertAlmostEqual(rel.aux_vars[1].ub, 1) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[1]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue(isinstance(rel.relaxations.rel0, coramin.relaxations.PWMcCormickRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertIn(rel.y, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) relaxations = list(coramin.relaxations.relaxation_data_objects(rel)) self.assertEqual(len(relaxations), 1)
def test_pow_neg_odd2(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(-2, -1)) m.y = pe.Var() m.z = pe.Var() m.w = pe.Var() m.p = pe.Param(initialize=-3) m.c = pe.Constraint(expr=m.x**m.p + m.y + m.z == 0) m.c2 = pe.Constraint(expr=m.w - 3 * m.x**m.p == 0) rel = coramin.relaxations.relax(m) self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 2) self.assertEqual(len(rel.aux_vars), 1) self.assertAlmostEqual(rel.aux_vars[1].lb, -1) self.assertAlmostEqual(rel.aux_vars[1].ub, -0.125) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[1]], 1) self.assertEqual(ders[rel.y], 1) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 3) self.assertEqual(rel.aux_cons[2].lower, 0) self.assertEqual(rel.aux_cons[2].upper, 0) ders = reverse_sd(rel.aux_cons[2].body) self.assertEqual(ders[rel.w], 1) self.assertEqual(ders[rel.aux_vars[1]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[2].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue( isinstance(rel.relaxations.rel0, coramin.relaxations.PWUnivariateRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) self.assertFalse(rel.relaxations.rel0.is_rhs_convex()) self.assertTrue(rel.relaxations.rel0.is_rhs_concave()) self.assertFalse(hasattr(rel.relaxations, 'rel1'))
def test_exp(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=2.0) e = pyo.exp(m.x) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_acos(self): m = pe.ConcreteModel() m.x = pe.Var(initialize=0.5) e = pe.acos(m.x) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_NPV(self): m = pyo.ConcreteModel() m.p = pyo.Param(initialize=2.0, mutable=True) e = pyo.log(m.p) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.p], pyo.value(symbolic[m.p]), tol) self.assertAlmostEqual(derivs[m.p], approx_deriv(e, m.p), tol)
def test_abs(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=2.0) e = 2 * abs(m.x) with self.assertRaisesRegexp( DifferentiationException, r'Cannot perform symbolic differentiation of abs\(x\)'): reverse_sd(e) derivs = reverse_ad(e) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) m.x.value = -2 derivs = reverse_ad(e) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) m.x.value = 0 with self.assertRaisesRegexp(DifferentiationException, r'Cannot differentiate abs\(x\) at x=0'): reverse_ad(e)
def test_quadratic(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(-1, 1)) m.y = pe.Var() m.z = pe.Var() m.w = pe.Var() m.c = pe.Constraint(expr=m.x**2 + m.y + m.z == 0) m.c2 = pe.Constraint(expr=m.w - 3 * m.x**2 == 0) rel = coramin.relaxations.relax(m) self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 2) self.assertEqual(len(rel.aux_vars), 1) self.assertAlmostEqual(rel.aux_vars[1].lb, 0) self.assertAlmostEqual(rel.aux_vars[1].ub, 1) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[1]], 1) self.assertEqual(ders[rel.y], 1) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 3) self.assertEqual(rel.aux_cons[2].lower, 0) self.assertEqual(rel.aux_cons[2].upper, 0) ders = reverse_sd(rel.aux_cons[2].body) self.assertEqual(ders[rel.w], 1) self.assertEqual(ders[rel.aux_vars[1]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[2].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue( isinstance(rel.relaxations.rel0, coramin.relaxations.PWXSquaredRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) self.assertFalse(hasattr(rel.relaxations, 'rel1'))
def test_sum(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=2.0) m.y = pyo.Var(initialize=3.0) e = 2.0 * m.x + 3.0 * m.y - m.x * m.y derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_linear_expression(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=2.0) m.y = pyo.Var(initialize=3.0) m.p = pyo.Param(initialize=2.5, mutable=True) e = LinearExpression(constant=m.p, linear_vars=[m.x, m.y], linear_coefs=[1.8, m.p]) e = pyo.log(e) derivs = reverse_ad(e) symbolic = reverse_sd(e) for v in [m.x, m.y, m.p]: self.assertAlmostEqual(derivs[v], pyo.value(symbolic[v]), tol) self.assertAlmostEqual(derivs[v], approx_deriv(e, v), tol)
def test_nested_named_expressions(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=0.23) m.y = pyo.Var(initialize=0.88) m.a = pyo.Expression(expr=(m.x + 1)**2) m.b = pyo.Expression(expr=3 * (m.a + m.y)) e = 2 * m.a + 2 * m.b + 2 * m.b + 2 * m.a derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol + 3) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_duplicate_expressions(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=0.23) m.y = pyo.Var(initialize=0.88) a = (m.x + 1)**2 b = 3 * (a + m.y) e = 2 * a + 2 * b + 2 * b + 2 * a derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol + 3) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_multiple_named_expressions(self): m = pyo.ConcreteModel() m.x = pyo.Var() m.y = pyo.Var() m.x.value = 1 m.y.value = 1 m.E = pyo.Expression(expr=m.x * m.y) e = m.E - m.E derivs = reverse_ad(e) self.assertAlmostEqual(derivs[m.x], 0) self.assertAlmostEqual(derivs[m.y], 0) symbolic = reverse_sd(e) self.assertAlmostEqual(pyo.value(symbolic[m.x]), 0) self.assertAlmostEqual(pyo.value(symbolic[m.y]), 0)
def test_nested(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=2) m.y = pyo.Var(initialize=3) m.p = pyo.Param(initialize=0.5, mutable=True) e = pyo.exp(m.x**m.p + 3.2 * m.y - 12) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol + 3) self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol + 3) self.assertAlmostEqual(derivs[m.p], pyo.value(symbolic[m.p]), tol + 3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol) self.assertAlmostEqual(derivs[m.p], approx_deriv(e, m.p), tol)
def test_expressiondata(self): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=3) m.e = pyo.Expression(expr=m.x * 2) @m.Expression([1, 2]) def e2(m, i): if i == 1: return m.x + 4 else: return m.x ** 2 m.o = pyo.Objective(expr=m.e + 1 + m.e2[1] + m.e2[2]) derivs = reverse_ad(m.o.expr) symbolic = reverse_sd(m.o.expr) self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol)
def _check_coefficents(comp, expr, too_large, too_small, largs_coef_map, small_coef_map): ders = reverse_sd(expr) for _v, _der in ders.items(): if isinstance(_v, _GeneralVarData): if _v.is_fixed(): continue der_lb, der_ub = compute_bounds_on_expr(_der) der_lb, der_ub = _bounds_to_float(der_lb, der_ub) if der_lb <= -too_large or der_ub >= too_large: if comp not in largs_coef_map: largs_coef_map[comp] = list() largs_coef_map[comp].append((_v, der_lb, der_ub)) if abs(der_lb) <= too_small and abs(der_ub) < too_small: if der_lb != 0 or der_ub != 0: if comp not in small_coef_map: small_coef_map[comp] = list() small_coef_map[comp].append((_v, der_lb, der_ub))
def __init__(self, expr, x): self._expr = expr self._x = x self._deriv = reverse_sd(expr)[x]
def test_pow_neg(self): m = pe.ConcreteModel() m.x = pe.Var(bounds=(-1,1)) m.y = pe.Var() m.z = pe.Var() m.w = pe.Var() m.p = pe.Param(initialize=-2) m.c = pe.Constraint(expr=m.x**m.p + m.y + m.z == 0) m.c2 = pe.Constraint(expr=m.w - 3*m.x**m.p == 0) rel = coramin.relaxations.relax(m) # This model should be relaxed to # # aux2 + y + z = 0 # w - 3 * aux2 = 0 # aux1 = x**2 # aux1*aux2 = aux3 # aux3 = 1 # self.assertTrue(hasattr(rel, 'aux_cons')) self.assertTrue(hasattr(rel, 'aux_vars')) self.assertEqual(len(rel.aux_cons), 2) self.assertEqual(len(rel.aux_vars), 3) self.assertAlmostEqual(rel.aux_vars[1].lb, 0) self.assertAlmostEqual(rel.aux_vars[1].ub, 1) self.assertTrue(rel.aux_vars[3].is_fixed()) self.assertEqual(rel.aux_vars[3].value, 1) self.assertEqual(rel.aux_cons[1].lower, 0) self.assertEqual(rel.aux_cons[1].upper, 0) ders = reverse_sd(rel.aux_cons[1].body) self.assertEqual(ders[rel.z], 1) self.assertEqual(ders[rel.aux_vars[2]], 1) self.assertEqual(ders[rel.y], 1) self.assertEqual(len(list(identify_variables(rel.aux_cons[1].body))), 3) self.assertEqual(rel.aux_cons[2].lower, 0) self.assertEqual(rel.aux_cons[2].upper, 0) ders = reverse_sd(rel.aux_cons[2].body) self.assertEqual(ders[rel.w], 1) self.assertEqual(ders[rel.aux_vars[2]], -3) self.assertEqual(len(list(identify_variables(rel.aux_cons[2].body))), 2) self.assertTrue(hasattr(rel, 'relaxations')) self.assertTrue(hasattr(rel.relaxations, 'rel0')) self.assertTrue(isinstance(rel.relaxations.rel0, coramin.relaxations.PWXSquaredRelaxation)) self.assertIn(rel.x, ComponentSet(rel.relaxations.rel0.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[1]), id(rel.relaxations.rel0.get_aux_var())) self.assertTrue(rel.relaxations.rel0.is_rhs_convex()) self.assertFalse(rel.relaxations.rel0.is_rhs_concave()) self.assertTrue(hasattr(rel.relaxations, 'rel1')) self.assertTrue(isinstance(rel.relaxations.rel1, coramin.relaxations.PWMcCormickRelaxation)) self.assertIn(rel.aux_vars[1], ComponentSet(rel.relaxations.rel1.get_rhs_vars())) self.assertIn(rel.aux_vars[2], ComponentSet(rel.relaxations.rel1.get_rhs_vars())) self.assertEqual(id(rel.aux_vars[3]), id(rel.relaxations.rel1.get_aux_var())) self.assertFalse(hasattr(rel.relaxations, 'rel2'))