def test_cyipopt_callback(self): # Use a callback to check that the reported infeasibility is # due to the scaled equality constraints. # Note that the scaled infeasibility is not what we see if we # call solve with tee=True, as by default the displayed infeasibility # is unscaled. Luckily, we can still access the scaled infeasibility # with a callback. m = self.make_model() scaling_factors = [1e-4, 1e4] m.epm.set_equality_constraint_scaling_factors(scaling_factors) nlp = PyomoNLPWithGreyBoxBlocks(m) def callback( local_nlp, alg_mod, iter_count, obj_value, inf_pr, inf_du, mu, d_norm, regularization_size, alpha_du, alpha_pr, ls_trials, ): primals = tuple(local_nlp.get_primals()) # I happen to know the order of the primals here u, v, x, y = primals # Calculate the scaled residuals I expect con_3_resid = scaling_factors[0] * abs( self.con_3_body(x, y, u, v) - self.con_3_rhs()) con_4_resid = scaling_factors[1] * abs( self.con_4_body(x, y, u, v) - self.con_4_rhs()) pred_inf_pr = max(con_3_resid, con_4_resid) # Make sure Ipopt is using the scaled constraints internally self.assertAlmostEqual(inf_pr, pred_inf_pr) cyipopt_nlp = CyIpoptNLP( nlp, intermediate_callback=callback, ) x0 = nlp.get_primals() cyipopt = CyIpoptSolver( cyipopt_nlp, options={ "max_iter": 0, "nlp_scaling_method": "user-scaling", }, ) cyipopt.solve(x0=x0)
def test_set_and_evaluate(self): m = pyo.ConcreteModel() m.ex_block = ExternalGreyBoxBlock(concrete=True) block = m.ex_block m_ex = _make_external_model() input_vars = [m_ex.a, m_ex.b, m_ex.r, m_ex.x_out, m_ex.y_out] external_vars = [m_ex.x, m_ex.y] residual_cons = [m_ex.c_out_1, m_ex.c_out_2] external_cons = [m_ex.c_ex_1, m_ex.c_ex_2] ex_model = ExternalPyomoModel( input_vars, external_vars, residual_cons, external_cons, ) block.set_external_model(ex_model) a = m.ex_block.inputs["input_0"] b = m.ex_block.inputs["input_1"] r = m.ex_block.inputs["input_2"] x = m.ex_block.inputs["input_3"] y = m.ex_block.inputs["input_4"] m.obj = pyo.Objective(expr=(x - 2.0)**2 + (y - 2.0)**2 + (a - 2.0)**2 + (b - 2.0)**2 + (r - 2.0)**2) _add_linking_constraints(m) nlp = PyomoNLPWithGreyBoxBlocks(m) # Set primals in model, get primals in nlp # set/get duals # evaluate constraints # evaluate Jacobian # evaluate Hessian self.assertEqual(nlp.n_primals(), 8) # PyomoNLPWithGreyBoxBlocks sorts variables by name primals_names = [ "a", "b", "ex_block.inputs[input_0]", "ex_block.inputs[input_1]", "ex_block.inputs[input_2]", "ex_block.inputs[input_3]", "ex_block.inputs[input_4]", "r", ] self.assertEqual(nlp.primals_names(), primals_names) np.testing.assert_equal(np.zeros(8), nlp.get_primals()) primals = np.array([0, 1, 2, 3, 4, 5, 6, 7]) nlp.set_primals(primals) np.testing.assert_equal(primals, nlp.get_primals()) nlp.load_state_into_pyomo() for name, val in zip(primals_names, primals): var = m.find_component(name) self.assertEqual(var.value, val) constraint_names = [ "linking_constraint[0]", "linking_constraint[1]", "linking_constraint[2]", "ex_block.residual_0", "ex_block.residual_1", ] self.assertEqual(constraint_names, nlp.constraint_names()) residuals = np.array([ -2.0, -2.0, 3.0, # These values were obtained by solving the same system # with Ipopt in another script. It may be better to do # the solve in this test in case the system changes. 5.0 - (-3.03051522), 6.0 - 3.583839997, ]) np.testing.assert_allclose(residuals, nlp.evaluate_constraints(), rtol=1e-8) duals = np.array([1, 2, 3, 4, 5]) nlp.set_duals(duals) self.assertEqual(ex_model.residual_con_multipliers, [4, 5]) np.testing.assert_equal(nlp.get_duals(), duals)