def test_intersect1d(self): vv1 = np.array([1.1, 3.3]) vv2 = np.array([4.4, 7.7]) bvv = BlockVector(2) bvv.set_blocks([vv1, vv2]) res = pn.intersect1d(self.bv, bvv) self.assertIsInstance(res, BlockVector) self.assertTrue(np.allclose(res.get_block(0), vv1)) self.assertTrue(np.allclose(res.get_block(1), vv2)) vv3 = np.array([1.1, 7.7]) res = pn.intersect1d(self.bv, vv3) self.assertIsInstance(res, BlockVector) self.assertTrue(np.allclose(res.get_block(0), np.array([1.1]))) self.assertTrue(np.allclose(res.get_block(1), np.array([7.7]))) res = pn.intersect1d(vv3, self.bv) self.assertIsInstance(res, BlockVector) self.assertTrue(np.allclose(res.get_block(0), np.array([1.1]))) self.assertTrue(np.allclose(res.get_block(1), np.array([7.7])))
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(CyIpoptNLP(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)) nlp.set_primals(x) nlp.set_duals(y_sol) self.assertAlmostEqual(nlp.evaluate_objective(), -3.5, places=5) self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
def evaluate_external_jacobian(self, x): dy0dx0 = -0.2 / (x[0]**2 * x[1]) dy0dx1 = -0.2 / (x[0] * x[1]**2) dy1dx0 = -0.5 * x[1]**0.5 / x[0]**2 dy1dx1 = 0.25 / (x[0] * x[1]**0.5) return np.array([[dy0dx0, dy0dx1], [dy1dx0, dy1dx1]])
def evaluate_external_jacobian(self, x): dy0dx0 = -2.0 * x[1] dy0dx1 = -2.0 * x[0] - 2.0 * x[1] dy1dx0 = -dy0dx0 - x[1] - 2.0 * x[0] dy1dx1 = -dy0dx1 - x[0] return np.array([[dy0dx0, dy0dx1], [dy1dx0, dy1dx1]])
def setUpClass(cls): # test problem 1 row = np.array([0, 3, 1, 2, 3, 0]) col = np.array([0, 0, 1, 2, 3, 3]) data = np.array([2., 1, 3, 4, 5, 1]) m = coo_matrix((data, (row, col)), shape=(4, 4)) rank = comm.Get_rank() # create mpi matrix rank_ownership = [[0, -1], [-1, 1]] bm = MPIBlockMatrix(2, 2, rank_ownership, comm) if rank == 0: bm.set_block(0, 0, m) if rank == 1: bm.set_block(1, 1, m) # create serial matrix image serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m) serial_bm.set_block(1, 1, m) cls.square_serial_mat = serial_bm bm.broadcast_block_sizes() cls.square_mpi_mat = bm # create mpi matrix rank_ownership = [[0, -1], [-1, 1]] bm = MPIBlockMatrix(2, 2, rank_ownership, comm) if rank == 0: bm.set_block(0, 0, m) if rank == 1: bm.set_block(1, 1, m) cls.square_mpi_mat_no_broadcast = bm # create matrix with shared blocks rank_ownership = [[0, -1], [-1, 1]] bm = MPIBlockMatrix(2, 2, rank_ownership, comm) if rank == 0: bm.set_block(0, 0, m) if rank == 1: bm.set_block(1, 1, m) bm.set_block(0, 1, m) bm.broadcast_block_sizes() cls.square_mpi_mat2 = bm # create serial matrix image serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m) serial_bm.set_block(1, 1, m) serial_bm.set_block(0, 1, m) cls.square_serial_mat2 = serial_bm row = np.array([0, 1, 2, 3]) col = np.array([0, 1, 0, 1]) data = np.array([1., 1., 1., 1.]) m2 = coo_matrix((data, (row, col)), shape=(4, 2)) rank_ownership = [[0, -1, 0], [-1, 1, -1]] bm = MPIBlockMatrix(2, 3, rank_ownership, comm) if rank == 0: bm.set_block(0, 0, m) bm.set_block(0, 2, m2) if rank == 1: bm.set_block(1, 1, m) bm.broadcast_block_sizes() cls.rectangular_mpi_mat = bm bm = BlockMatrix(2, 3) bm.set_block(0, 0, m) bm.set_block(0, 2, m2) bm.set_block(1, 1, m) cls.rectangular_serial_mat = bm
def test_grad_objective(self): w_estimates = np.array([5.0, 5.0]) z_estimates = np.array([2.0, 2.0]) rho = 2.0 nlp = AdmmNLP(self.pyomo_nlp, self.coupling_vars, rho=rho, w_estimates=w_estimates, z_estimates=z_estimates) hessian_base = self.model.hessian_f c = self.model.grad_f A = np.array([[1, 0, 0], [0, 0, 1]], dtype=np.double) x = nlp.create_vector_x() x.fill(1.0) df = hessian_base.dot(x) + c df += A.transpose().dot(w_estimates) df += rho * (A.transpose().dot(A).dot(x) - A.transpose().dot(z_estimates)) self.assertTrue(np.allclose(df, nlp.grad_objective(x))) # second nlp w_estimates = np.array([1.0, 2.0, 3.0]) z_estimates = np.array([3.0, 4.0, 5.0]) nlp = AdmmNLP(self.pyomo_nlp2, self.coupling_vars2, rho=3.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model2 transform = AdmmModel() aug_model = transform.create_using( m, complicating_vars=[m.x[1], m.x[3], m.x[5]], z_estimates=z_estimates, w_estimates=w_estimates, rho=3.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() self.assertTrue( np.allclose(nlp.grad_objective(x), nl.grad_objective(x))) # third nlp w_estimates = np.array([1.0]) z_estimates = np.array([3.0]) nlp = AdmmNLP(self.pyomo_nlp3, self.coupling_vars3, rho=8.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model3 transform = AdmmModel() aug_model = transform.create_using(m, complicating_vars=[m.x[1]], z_estimates=z_estimates, w_estimates=w_estimates, rho=8.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() x.fill(1.0) self.assertTrue( np.allclose(nlp.grad_objective(x), nl.grad_objective(x)))
def test_objective(self): w_estimates = np.array([5.0, 5.0]) z_estimates = np.array([2.0, 2.0]) rho = 2.0 nlp = AdmmNLP(self.pyomo_nlp, self.coupling_vars, rho=rho, w_estimates=w_estimates, z_estimates=z_estimates) hessian_base = self.model.hessian_f c = self.model.grad_f A = np.array([[1, 0, 0], [0, 0, 1]], dtype=np.double) x = nlp.create_vector_x() x.fill(1.0) f = 0.5 * x.transpose().dot(hessian_base.dot(x)) + c.dot(x) difference = A.dot(x) - z_estimates f += w_estimates.dot(difference) f += 0.5 * rho * np.linalg.norm(difference)**2 self.assertEqual(f, nlp.objective(x)) # second nlp w_estimates = np.array([1.0, 2.0, 3.0]) z_estimates = np.array([3.0, 4.0, 5.0]) nlp = AdmmNLP(self.pyomo_nlp2, self.coupling_vars2, rho=5.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model2 transform = AdmmModel() aug_model = transform.create_using( m, complicating_vars=[m.x[1], m.x[3], m.x[5]], z_estimates=z_estimates, w_estimates=w_estimates, rho=5.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() self.assertAlmostEqual(nlp.objective(x), nl.objective((x))) # third nlp w_estimates = np.array([1.0]) z_estimates = np.array([3.0]) nlp = AdmmNLP(self.pyomo_nlp3, self.coupling_vars3, rho=7.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model3 transform = AdmmModel() aug_model = transform.create_using(m, complicating_vars=[m.x[1]], z_estimates=z_estimates, w_estimates=w_estimates, rho=7.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() self.assertAlmostEqual(nlp.objective(x), nl.objective((x)))
def test_hessian_lag(self): hessian_base = self.model.hessian_f ata = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 1]], dtype=np.double) rho = self.nlp.rho admm_hessian = hessian_base + ata * rho x = self.nlp.create_vector_x() y = self.nlp.create_vector_y() hess_lag = self.nlp.hessian_lag(x, y) dense_hess_lag = hess_lag.todense() self.assertTrue(np.allclose(dense_hess_lag, admm_hessian)) # second nlp w_estimates = np.array([1.0, 2.0, 3.0]) z_estimates = np.array([3.0, 4.0, 5.0]) nlp = AdmmNLP(self.pyomo_nlp2, self.coupling_vars2, rho=7.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model2 transform = AdmmModel() aug_model = transform.create_using( m, complicating_vars=[m.x[1], m.x[3], m.x[5]], z_estimates=z_estimates, w_estimates=w_estimates, rho=7.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() y = nlp.create_vector_y() hess_lag = nlp.hessian_lag(x, y) dense_hess_lag = hess_lag.todense() hess_lagp = nl.hessian_lag(x, y) dense_hess_lagp = hess_lagp.todense() self.assertTrue(np.allclose(dense_hess_lag, dense_hess_lagp)) # third nlp w_estimates = np.array([1.0]) z_estimates = np.array([3.0]) nlp = AdmmNLP(self.pyomo_nlp3, self.coupling_vars3, rho=1.0, w_estimates=w_estimates, z_estimates=z_estimates) m = self.model3 transform = AdmmModel() aug_model = transform.create_using(m, complicating_vars=[m.x[1]], z_estimates=z_estimates, w_estimates=w_estimates, rho=1.0) nl = PyomoNLP(aug_model) x = nlp.create_vector_x() y = nlp.create_vector_y() hess_lag = nlp.hessian_lag(x, y) dense_hess_lag = hess_lag.todense() hess_lagp = nl.hessian_lag(x, y) dense_hess_lagp = hess_lagp.todense() self.assertTrue(np.allclose(dense_hess_lag, dense_hess_lagp))
def test_xu(self): xu = [np.inf, 100.0, np.inf] self.assertTrue(np.allclose(xu, self.nlp3.xu())) xu = np.array([100.0]) self.assertTrue(np.allclose(xu, self.nlp3.xu(condensed=True)))
def test_xl(self): xl = np.array([-np.inf, 0, 0]) self.assertTrue(np.allclose(xl, self.nlp3.xl())) xl = np.zeros(2) self.assertTrue(np.allclose(xl, self.nlp3.xl(condensed=True)))
def test_c_maps(self): c_mask = np.array([True, True, False, False, False], dtype=bool) self.assertTrue(np.allclose(self.nlp3._c_mask, c_mask)) c_map = np.array([0, 1]) self.assertTrue(np.allclose(self.nlp3._c_map, c_map))
def test_parallel_vector_ops(self): z1_local, z2, z3 = parallel_vector_ops.main() z1_correct = np.array([6, 6, 6, 2, 2, 2, 4, 4, 4, 2, 4, 6]) self.assertTrue(np.allclose(z1_local, z1_correct)) self.assertAlmostEqual(z2, 56) self.assertAlmostEqual(z3, 3)
def test_hessian_2(self): # Test with duals different than vector of ones 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_nonlinear_linking_constraints(m) nlp = PyomoNLPWithGreyBoxBlocks(m) primals = np.array([0, 1, 2, 3, 4, 5, 6, 7]) duals = np.array([4.4, -3.3, 2.2, -1.1, 0.0]) nlp.set_primals(primals) nlp.set_duals(duals) hess = nlp.evaluate_hessian_lag() # Variable order (verified by a previous test): # [ # "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", # ] row = [0, 1, 7] col = [0, 1, 7] # Data entries are influenced by multiplier values. data = [4.4 * 2.0, -3.3 * 2.0, 2.2 * 2.0] # ^ These variables only appear in linking constraints rcd_dict = dict(((i, j), val) for i, j, val in zip(row, col, data)) # These are the coordinates of the Hessian corresponding to # external variables with true nonzeros. The coordinates have # terms due to objective, linking constraints, and external # constraints. Values were extracted from the external model # while writing this test, which is just meant to verify # that the different Hessians combined properly. ex_block_nonzeros = { (2, 2): 2.0 + 4.4 * (-1.0) + -1.1 * (-0.10967928), (2, 3): -1.1 * (-0.10684633), (3, 2): -1.1 * (-0.10684633), (2, 4): -1.1 * (0.19329898), (4, 2): -1.1 * (0.19329898), (3, 3): 2.0 + (-3.3) * (-1.0) + -1.1 * (-1.31592135), (3, 4): -1.1 * (1.13920361), (4, 3): -1.1 * (1.13920361), (4, 4): 2.0 + 2.2 * (-1.0) + -1.1 * (-1.0891866), (5, 5): 2.0, (6, 6): 2.0, } rcd_dict.update(ex_block_nonzeros) # Because "external Hessians" are computed by factorizing matrices, # we have dense blocks in the Hessian for now. ex_block_coords = [2, 3, 4, 5, 6] for i, j in itertools.product(ex_block_coords, ex_block_coords): row.append(i) col.append(j) if (i, j) not in rcd_dict: rcd_dict[i, j] = 0.0 self.assertEqual(len(row), len(hess.row)) for i, j, val in zip(hess.row, hess.col, hess.data): self.assertIn((i, j), rcd_dict) self.assertAlmostEqual(rcd_dict[i, j], val, delta=1e-8)
def test_jacobian(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) primals = np.array([0, 1, 2, 3, 4, 5, 6, 7]) nlp.set_primals(primals) jac = nlp.evaluate_jacobian() # Variable and constraint orders (verified by previous test): # Rows: # [ # "linking_constraint[0]", # "linking_constraint[1]", # "linking_constraint[2]", # "ex_block.residual_0", # "ex_block.residual_1", # ] # Cols: # [ # "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", # ] row = [ 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, ] col = [ 0, 2, 1, 3, 7, 4, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, ] data = [ 1, -1, 1, -1, 1, -1, -0.16747094, -1.00068434, 1.72383729, 1, 0, -0.30708535, -0.28546127, -0.25235924, 0, 1, ] self.assertEqual(len(row), len(jac.row)) rcd_dict = dict(((i, j), val) for i, j, val in zip(row, col, data)) for i, j, val in zip(jac.row, jac.col, jac.data): self.assertIn((i, j), rcd_dict) self.assertAlmostEqual(rcd_dict[i, j], val, delta=1e-8)
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)