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_composite_nlp(self): G = np.array([[6, 2, 1], [2, 5, 2], [1, 2, 4]]) A = np.array([[1, 0, 1], [0, 1, 1]]) b = np.array([3, 0]) c = np.array([-8, -3, -3]) scenarios = dict() coupling_vars = dict() n_scenarios = 2 np.random.seed(seed=985739465) bs = [b, b + 0.001] for i in range(n_scenarios): instance = create_model3(G, A, bs[i], c) nlp = PyomoNLP(instance) scenario_name = "s{}".format(i) scenarios[scenario_name] = nlp coupling_vars[scenario_name] = [nlp.variable_idx(instance.x[0])] nlp = TwoStageStochasticNLP(scenarios, coupling_vars) solver = CyIpoptSolver(nlp) x, info = solver.solve(tee=False) x_sol = np.array([ 2.00003846, -0.99996154, 0.99996154, 2.00003846, -0.99996154, 1.00096154, 2.00003846 ]) self.assertTrue(np.allclose(x, x_sol, rtol=1e-4)) self.assertAlmostEqual(nlp.objective(x), -6.99899, 3)
def test_pyomo_external_model(self): m = pyo.ConcreteModel() m.Pin = pyo.Var(initialize=100, bounds=(0,None)) m.c1 = pyo.Var(initialize=1.0, bounds=(0,None)) m.c2 = pyo.Var(initialize=1.0, bounds=(0,None)) m.F = pyo.Var(initialize=10, bounds=(0,None)) m.P1 = pyo.Var() m.P2 = pyo.Var() m.F_con = pyo.Constraint(expr = m.F == 10) m.Pin_con = pyo.Constraint(expr = m.Pin == 100) # simple parameter estimation test m.obj = pyo.Objective(expr= (m.P1 - 90)**2 + (m.P2 - 40)**2) cyipopt_problem = \ PyomoExternalCyIpoptProblem(m, PressureDropModel(), [m.Pin, m.c1, m.c2, m.F], [m.P1, m.P2] ) # check that the dummy variable is initialized expected_dummy_var_value = pyo.value(m.Pin) + pyo.value(m.c1) + pyo.value(m.c2) + pyo.value(m.F) \ + 0 + 0 # + pyo.value(m.P1) + pyo.value(m.P2) # not initialized - therefore should use zero self.assertAlmostEqual(pyo.value(m._dummy_variable_CyIpoptPyomoExNLP), expected_dummy_var_value) # solve the problem solver = CyIpoptSolver(cyipopt_problem, {'hessian_approximation':'limited-memory'}) x, info = solver.solve(tee=False) cyipopt_problem.load_x_into_pyomo(x) self.assertAlmostEqual(pyo.value(m.c1), 0.1, places=5) self.assertAlmostEqual(pyo.value(m.c2), 0.5, places=5)
def test_options(self): model = create_model1() nlp = PyomoNLP(model) solver = CyIpoptSolver(CyIpoptNLP(nlp), options={'max_iter': 1}) x, info = solver.solve(tee=False) nlp.set_primals(x) self.assertAlmostEqual(nlp.evaluate_objective(), -5.0879028e+02, places=5)
def test_model1_with_scaling(self): m = create_model1() m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT) m.scaling_factor[m.o] = 1e-6 # scale the objective m.scaling_factor[m.c] = 2.0 # scale the equality constraint m.scaling_factor[m.d] = 3.0 # scale the inequality constraint m.scaling_factor[m.x[1]] = 4.0 # scale one of the x variables cynlp = CyIpoptNLP(PyomoNLP(m)) options={'nlp_scaling_method': 'user-scaling', 'output_file': '_cyipopt-scaling.log', 'file_print_level':10, 'max_iter': 0} solver = CyIpoptSolver(cynlp, options=options) x, info = solver.solve() with open('_cyipopt-scaling.log', 'r') as fd: solver_trace = fd.read() os.remove('_cyipopt-scaling.log') # check for the following strings in the log and then delete the log self.assertIn('nlp_scaling_method = user-scaling', solver_trace) self.assertIn('output_file = _cyipopt-scaling.log', solver_trace) self.assertIn('objective scaling factor = 1e-06', solver_trace) self.assertIn('x scaling provided', solver_trace) self.assertIn('c scaling provided', solver_trace) self.assertIn('d scaling provided', solver_trace) self.assertIn('DenseVector "x scaling vector" with 3 elements:', solver_trace) self.assertIn('x scaling vector[ 1]= 1.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 2]= 1.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 3]= 4.0000000000000000e+00', solver_trace) self.assertIn('DenseVector "c scaling vector" with 1 elements:', solver_trace) self.assertIn('c scaling vector[ 1]= 2.0000000000000000e+00', solver_trace) self.assertIn('DenseVector "d scaling vector" with 1 elements:', solver_trace) self.assertIn('d scaling vector[ 1]= 3.0000000000000000e+00', solver_trace)
def test_model2(self): model = create_model2() nlp = PyomoNLP(model) solver = CyIpoptSolver(nlp) x, info = solver.solve(tee=False) x_sol = np.array([3.0, 1.99997807]) y_sol = np.array([0.00017543]) self.assertTrue(np.allclose(x, x_sol, rtol=1e-4)) self.assertAlmostEqual(nlp.objective(x), -31.000000057167462, 3) self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
def test_model1(self): model = create_model1() nlp = PyomoNLP(model) solver = CyIpoptSolver(nlp) x, info = solver.solve(tee=False) x_sol = np.array([3.85958688, 4.67936007, 3.10358931]) y_sol = np.array([-1.0, 53.90357665]) self.assertTrue(np.allclose(x, x_sol, rtol=1e-4)) self.assertAlmostEqual(nlp.objective(x), -428.6362455416348) self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
def test_model2(self): model = create_model2() nlp = PyomoNLP(model) solver = CyIpoptSolver(CyIpoptNLP(nlp)) x, info = solver.solve(tee=False) x_sol = np.array([3.0, 1.99997807]) y_sol = np.array([0.00017543]) self.assertTrue(np.allclose(x, x_sol, rtol=1e-4)) nlp.set_primals(x) nlp.set_duals(y_sol) self.assertAlmostEqual(nlp.evaluate_objective(), -31.000000057167462, places=5) self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
def test_model3(self): G = np.array([[6, 2, 1], [2, 5, 2], [1, 2, 4]]) A = np.array([[1, 0, 1], [0, 1, 1]]) b = np.array([3, 0]) c = np.array([-8, -3, -3]) model = create_model3(G, A, b, c) nlp = PyomoNLP(model) solver = CyIpoptSolver(nlp) x, info = solver.solve(tee=False) x_sol = np.array([2.0, -1.0, 1.0]) y_sol = np.array([-3., 2.]) self.assertTrue(np.allclose(x, x_sol, rtol=1e-4)) self.assertAlmostEqual(nlp.objective(x), -3.5, 3) self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
def test_pyomo_external_model_ndarray_scaling(self): m = pyo.ConcreteModel() m.Pin = pyo.Var(initialize=100, bounds=(0, None)) m.c1 = pyo.Var(initialize=1.0, bounds=(0, None)) m.c2 = pyo.Var(initialize=1.0, bounds=(0, None)) m.F = pyo.Var(initialize=10, bounds=(0, None)) m.P1 = pyo.Var() m.P2 = pyo.Var() m.F_con = pyo.Constraint(expr=m.F == 10) m.Pin_con = pyo.Constraint(expr=m.Pin == 100) # simple parameter estimation test m.obj = pyo.Objective(expr=(m.P1 - 90)**2 + (m.P2 - 40)**2) # set scaling parameters for the pyomo variables and constraints m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT) m.scaling_factor[m.obj] = 0.1 # scale the objective m.scaling_factor[m.Pin] = 2.0 # scale the variable m.scaling_factor[m.c1] = 3.0 # scale the variable m.scaling_factor[m.c2] = 4.0 # scale the variable m.scaling_factor[m.F] = 5.0 # scale the variable m.scaling_factor[m.P1] = 6.0 # scale the variable m.scaling_factor[m.P2] = 7.0 # scale the variable m.scaling_factor[m.F_con] = 8.0 # scale the pyomo constraint m.scaling_factor[m.Pin_con] = 9.0 # scale the pyomo constraint # test that this all works with ndarray input as well cyipopt_problem = \ PyomoExternalCyIpoptProblem(pyomo_model=m, ex_input_output_model=PressureDropModel(), inputs=[m.Pin, m.c1, m.c2, m.F], outputs=[m.P1, m.P2], outputs_eqn_scaling=np.asarray([10.0, 11.0], dtype=np.float64) ) # solve the problem options = { 'hessian_approximation': 'limited-memory', 'nlp_scaling_method': 'user-scaling', 'output_file': '_cyipopt-pyomo-ext-scaling-ndarray.log', 'file_print_level': 10, 'max_iter': 0 } solver = CyIpoptSolver(cyipopt_problem, options=options) x, info = solver.solve(tee=False) with open('_cyipopt-pyomo-ext-scaling-ndarray.log', 'r') as fd: solver_trace = fd.read() os.remove('_cyipopt-pyomo-ext-scaling-ndarray.log') self.assertIn('nlp_scaling_method = user-scaling', solver_trace) self.assertIn('output_file = _cyipopt-pyomo-ext-scaling-ndarray.log', solver_trace) self.assertIn('objective scaling factor = 0.1', solver_trace) self.assertIn('x scaling provided', solver_trace) self.assertIn('c scaling provided', solver_trace) self.assertIn('d scaling provided', solver_trace) self.assertIn('DenseVector "x scaling vector" with 7 elements:', solver_trace) self.assertIn('x scaling vector[ 1]= 6.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 2]= 7.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 3]= 2.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 4]= 3.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 5]= 4.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 6]= 5.0000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 7]= 1.0000000000000000e+00', solver_trace) self.assertIn('DenseVector "c scaling vector" with 5 elements:', solver_trace) self.assertIn('c scaling vector[ 1]= 8.0000000000000000e+00', solver_trace) self.assertIn('c scaling vector[ 2]= 9.0000000000000000e+00', solver_trace) self.assertIn('c scaling vector[ 3]= 1.0000000000000000e+00', solver_trace) self.assertIn('c scaling vector[ 4]= 1.0000000000000000e+01', solver_trace) self.assertIn('c scaling vector[ 5]= 1.1000000000000000e+01', solver_trace)