def test_iadd(self): 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.copy()) if rank == 1: bm.set_block(1, 1, m.copy()) serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m.copy()) serial_bm.set_block(1, 1, m.copy()) bm += bm serial_bm += serial_bm rows, columns = np.nonzero(bm.ownership_mask) for i, j in zip(rows, columns): if bm.get_block(i, j) is not None: self.assertTrue( np.allclose( bm.get_block(i, j).toarray(), serial_bm.get_block(i, j).toarray())) bm += serial_bm serial_bm += serial_bm self._compare_mpi_and_serial_block_matrices(bm, serial_bm)
def expansion_matrix_xu(self): Pxu = BlockMatrix(self.nblocks + 1, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): Pxu.set_block(sid, sid, nlp.expansion_matrix_xu()) Pxu[self.nblocks, self.nblocks] = coo_matrix((self.nz, 0)) return Pxu
def test_reset_bcol(self): 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) bm.broadcast_block_sizes() serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m) serial_bm.set_block(1, 1, m) self.assertTrue( np.allclose(serial_bm.row_block_sizes(), bm.row_block_sizes())) bm.reset_bcol(0) serial_bm.reset_bcol(0) self.assertTrue( np.allclose(serial_bm.col_block_sizes(), bm.col_block_sizes())) bm.reset_bcol(1) serial_bm.reset_bcol(1) self.assertTrue( np.allclose(serial_bm.col_block_sizes(), bm.col_block_sizes()))
def test_abs(self): 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) bm.broadcast_block_sizes() serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m) serial_bm.set_block(1, 1, m) res = abs(bm) serial_res = abs(serial_bm) rows, columns = np.nonzero(bm.ownership_mask) for i, j in zip(rows, columns): if res.get_block(i, j) is not None: self.assertTrue( np.allclose( res.get_block(i, j).toarray(), serial_res.get_block(i, j).toarray()))
def test_isub(self): 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.copy()) if rank == 1: bm.set_block(1, 1, m.copy()) bm.broadcast_block_sizes() serial_bm = BlockMatrix(2, 2) serial_bm.set_block(0, 0, m.copy()) serial_bm.set_block(1, 1, m.copy()) bm -= bm serial_bm -= serial_bm rows, columns = np.nonzero(bm.ownership_mask) for i, j in zip(rows, columns): if bm.get_block(i, j) is not None: self.assertTrue( np.allclose( bm.get_block(i, j).toarray(), serial_bm.get_block(i, j).toarray())) with self.assertRaises(Exception) as context: bm -= serial_bm
def test_setitem(self): m = BlockMatrix(2, 2) m.set_block(0, 1, self.block_m) self.assertFalse(m.is_empty_block(0, 1)) self.assertEqual(m._brow_lengths[0], self.block_m.shape[0]) self.assertEqual(m._bcol_lengths[1], self.block_m.shape[1]) self.assertEqual(m.get_block(0, 1).shape, self.block_m.shape)
def test_getitem(self): m = BlockMatrix(3, 3) for i in range(3): for j in range(3): self.assertIsNone(m.get_block(i, j)) m.set_block(0, 1, self.block_m) self.assertEqual(m.get_block(0, 1).shape, self.block_m.shape)
def jacobian_c(self, x, out=None, **kwargs): """Returns the Jacobian of the equalities evaluated at x Parameters ---------- x : array_like Array with values of primal variables. out : BlockMatrix, optional Output matrix with the structure of the jacobian already defined. Returns ------- BlockMatrix """ assert x.size == self.nx, 'Dimension mismatch' if isinstance(x, BlockVector): assert x.nblocks == self.nblocks + 1 x_ = x elif isinstance(x, np.ndarray): block_x = self.create_vector_x() block_x.copyfrom(x) x_ = block_x else: raise RuntimeError('Input vector format not recognized') if out is None: jac_c = BlockMatrix(2 * self.nblocks, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = x_.get_block(sid) jac_c.set_block(sid, sid, nlp.jacobian_c(xi)) # coupling matrices Ai jac_c[sid + self.nblocks, sid] = self._AB_coo.get_block(sid, sid) # coupling matrices Bi jac_c[sid + self.nblocks, self.nblocks] = -identity(self.nz) return jac_c else: assert isinstance(out, BlockMatrix), 'out must be a BlockMatrix' assert out.bshape == (2 * self.nblocks, self.nblocks + 1), "Block shape mismatch" jac_c = out for sid, nlp in enumerate(self._nlps): xi = x_.get_block(sid) nlp.jacobian_c(xi, out=jac_c.get_block(sid, sid)) Ai = jac_c[sid + self.nblocks, sid] assert Ai.shape == self._AB_coo.get_block(sid, sid).shape, \ 'Block {} mismatch shape'.format((sid + self.nblocks, sid)) assert Ai.nnz == self._AB_coo.get_block(sid, sid).nnz, \ 'Block {} mismatch nnz'.format((sid + self.nblocks, sid)) Bi = jac_c[sid + self.nblocks, self.nblocks] assert Bi.shape == (self.nz, self.nz), \ 'Block {} mismatch shape'.format((sid + self.nblocks, self.nblocks)) assert Bi.nnz == self.nz, \ 'Block {} mismatch nnz'.format((sid + self.nblocks, self.nblocks)) return jac_c
def coupling_matrix(self): AB = BlockMatrix(self.nblocks + 1, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): col = self._zid_to_vid[sid] row = np.arange(self.nz, dtype=np.int) data = np.ones(self.nz) AB.set_block( sid, sid, csr_matrix((data, (row, col)), shape=(self.nz, nlp.nx))) AB[self.nblocks, self.nblocks] = -identity(self.nz) return AB
def create_blocks(self, m: np.ndarray, x: np.ndarray): m = coo_matrix(m) r = m * x bm = BlockMatrix(2, 2) bm.set_block(0, 0, m.copy()) bm.set_block(1, 1, m.copy()) br = BlockVector(2) br.set_block(0, r.copy()) br.set_block(1, r.copy()) bx = BlockVector(2) bx.set_block(0, x.copy()) bx.set_block(1, x.copy()) return bm, bx, br
def test_dimensions(self): bm = BlockMatrix(2, 2) self.assertTrue(bm.has_undefined_row_sizes()) self.assertTrue(bm.has_undefined_col_sizes()) with self.assertRaises(NotFullyDefinedBlockMatrixError): shape = bm.shape with self.assertRaises(NotFullyDefinedBlockMatrixError): bm.set_block(0, 0, BlockMatrix(2, 2)) with self.assertRaises(NotFullyDefinedBlockMatrixError): row_sizes = bm.row_block_sizes() with self.assertRaises(NotFullyDefinedBlockMatrixError): col_sizes = bm.col_block_sizes() bm2 = BlockMatrix(2, 2) bm2.set_block(0, 0, coo_matrix((2, 2))) bm2.set_block(1, 1, coo_matrix((2, 2))) bm3 = bm2.copy() bm.set_block(0, 0, bm2) bm.set_block(1, 1, bm3) self.assertFalse(bm.has_undefined_row_sizes()) self.assertFalse(bm.has_undefined_col_sizes()) self.assertEqual(bm.shape, (8, 8)) bm.set_block(0, 0, None) self.assertFalse(bm.has_undefined_row_sizes()) self.assertFalse(bm.has_undefined_col_sizes()) self.assertEqual(bm.shape, (8, 8)) self.assertTrue(np.all(bm.row_block_sizes() == np.ones(2) * 4)) self.assertTrue(np.all(bm.col_block_sizes() == np.ones(2) * 4)) self.assertTrue( np.all(bm.row_block_sizes(copy=False) == np.ones(2) * 4)) self.assertTrue( np.all(bm.col_block_sizes(copy=False) == np.ones(2) * 4))
def main(): m = create_model(4.5, 1.0) opt = pyo.SolverFactory('ipopt') results = opt.solve(m, tee=True) nlp = PyomoNLP(m) x = nlp.init_primals() y = compute_init_lam(nlp, x=x) nlp.set_primals(x) nlp.set_duals(y) J = nlp.extract_submatrix_jacobian(pyomo_variables=[m.x1, m.x2, m.x3], pyomo_constraints=[m.const1, m.const2]) H = nlp.extract_submatrix_hessian_lag( pyomo_variables_rows=[m.x1, m.x2, m.x3], pyomo_variables_cols=[m.x1, m.x2, m.x3]) M = BlockMatrix(2, 2) M.set_block(0, 0, H) M.set_block(1, 0, J) M.set_block(0, 1, J.transpose()) Np = BlockMatrix(2, 1) Np.set_block( 0, 0, nlp.extract_submatrix_hessian_lag( pyomo_variables_rows=[m.x1, m.x2, m.x3], pyomo_variables_cols=[m.eta1, m.eta2])) Np.set_block( 1, 0, nlp.extract_submatrix_jacobian(pyomo_variables=[m.eta1, m.eta2], pyomo_constraints=[m.const1, m.const2])) ds = spsolve(M.tocsc(), -Np.tocsc()) print("ds:\n", ds.todense()) ################################################################# p0 = np.array([pyo.value(m.nominal_eta1), pyo.value(m.nominal_eta2)]) p = np.array([4.45, 1.05]) dp = p - p0 dx = ds.dot(dp)[0:3] x_indices = nlp.get_primal_indices([m.x1, m.x2, m.x3]) x_names = np.array(nlp.primals_names()) new_x_sens = x[x_indices] + dx print("dp:", dp) print("dx:", dx) print("Variable names: \n", x_names[x_indices]) print("Sensitivity based x:\n", new_x_sens) ################################################################# m = create_model(4.45, 1.05) opt = pyo.SolverFactory('ipopt') results = opt.solve(m, tee=False) nlp = PyomoNLP(m) new_x = nlp.init_primals()[nlp.get_primal_indices([m.x1, m.x2, m.x3])] print("NLP based x:\n", new_x) return new_x_sens, new_x
def _create_hessian_structure(self): # Note: This method requires the complicated vars map to be # created beforehand hess_lag = BlockMatrix(self.nblocks + 1, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = nlp.x_init() yi = nlp.y_init() hess_lag.set_block(sid, sid, nlp.hessian_lag(xi, yi)) hess_lag[self.nblocks, self.nblocks] = coo_matrix((self.nz, self.nz)) flat_hess = hess_lag.tocoo() self._irows_hess = flat_hess.row self._jcols_hess = flat_hess.col self._nnz_hess_lag = flat_hess.nnz
def build_compression_matrix(compression_mask): """ Return a sparse matrix CM of ones such that compressed_vector = CM*full_vector based on the compression mask Parameters ---------- compression_mask: np.ndarray or pyomo.contrib.pynumero.sparse.block_vector.BlockVector Returns ------- cm: coo_matrix or BlockMatrix The compression matrix """ if isinstance(compression_mask, BlockVector): n = compression_mask.nblocks res = BlockMatrix(nbrows=n, nbcols=n) for ndx, block in enumerate(compression_mask): sub_matrix = build_compression_matrix(block) res.set_block(ndx, ndx, sub_matrix) return res elif type(compression_mask) is np.ndarray: cols = compression_mask.nonzero()[0] nnz = len(cols) rows = np.arange(nnz, dtype=np.int) data = np.ones(nnz) return coo_matrix((data, (rows, cols)), shape=(nnz, len(compression_mask))) elif isinstance(compression_mask, mpi_block_vector.MPIBlockVector): from pyomo.contrib.pynumero.sparse.mpi_block_matrix import MPIBlockMatrix n = compression_mask.nblocks rank_ownership = np.ones((n, n), dtype=np.int64) * -1 for i in range(n): rank_ownership[i, i] = compression_mask.rank_ownership[i] res = MPIBlockMatrix(nbrows=n, nbcols=n, rank_ownership=rank_ownership, mpi_comm=compression_mask.mpi_comm, assert_correct_owners=False) for ndx in compression_mask.owned_blocks: block = compression_mask.get_block(ndx) sub_matrix = build_compression_matrix(block) res.set_block(ndx, ndx, sub_matrix) return res
def test_abs(self): row = np.array([0, 3, 1, 2, 3, 0]) col = np.array([0, 0, 1, 2, 3, 3]) data = -1.0 * np.array([2., 1, 3, 4, 5, 1]) m = coo_matrix((data, (row, col)), shape=(4, 4)) self.block_m = m bm = BlockMatrix(2, 2) bm.set_block(0, 0, m) bm.set_block(1, 1, m) bm.set_block(0, 1, m) abs_flat = abs(bm.tocoo()) abs_mat = abs(bm) self.assertIsInstance(abs_mat, BlockMatrix) self.assertTrue(np.allclose(abs_flat.toarray(), abs_mat.toarray()))
def jacobian_d(self, x, out=None, **kwargs): """Returns the Jacobian of the inequalities evaluated at x Parameters ---------- x : array_like Array with values of primal variables. out : coo_matrix, optional Output matrix with the structure of the jacobian already defined. Returns ------- BlockMatrix """ assert x.size == self.nx, "Dimension mismatch" if isinstance(x, BlockVector): assert x.nblocks == self.nblocks + 1 x_ = x elif isinstance(x, np.ndarray): block_x = self.create_vector_x() block_x.copyfrom(x) x_ = block_x else: raise RuntimeError('Input vector format not recognized') if out is None: jac_d = BlockMatrix(self.nblocks, self.nblocks) for sid, nlp in enumerate(self._nlps): xi = x_.get_block(sid) jac_d.set_block(sid, sid, nlp.jacobian_d(xi)) return jac_d else: assert isinstance(out, BlockMatrix), 'out must be a BlockMatrix' assert out.bshape == (self.nblocks, self.nblocks), 'Block shape mismatch' jac_d = out for sid, nlp in enumerate(self._nlps): xi = x_.get_block(sid) nlp.jacobian_d(xi, out=jac_d.get_block(sid, sid)) return jac_d
def test_dot(self): A_dense = self.basic_m.toarray() A_block = self.basic_m x = np.ones(A_dense.shape[1]) block_x = BlockVector(2) block_x.set_block(0, np.ones(self.block_m.shape[1])) block_x.set_block(1, np.ones(self.block_m.shape[1])) flat_res = A_block.dot(x).flatten() block_res = A_block.dot(block_x) self.assertTrue(np.allclose(A_dense.dot(x), flat_res)) self.assertTrue(np.allclose(A_dense.dot(x), block_res.flatten())) self.assertEqual(block_res.bshape[0], 2) m = BlockMatrix(2, 2) sub_m = np.array([[1, 0], [0, 1]]) sub_m = coo_matrix(sub_m) m.set_block(0, 1, sub_m.copy()) m.set_block(1, 0, sub_m.copy()) x = np.arange(4) res = m * x self.assertTrue(np.allclose(res.flatten(), np.array([2, 3, 0, 1])))
def compute_init_lam(nlp, x=None, lam_max=1e3): if x is None: x = nlp.init_primals() else: assert x.size == nlp.n_primals() nlp.set_primals(x) assert nlp.n_ineq_constraints( ) == 0, "only supported for equality constrained nlps for now" nx = nlp.n_primals() nc = nlp.n_constraints() # create Jacobian jac = nlp.evaluate_jacobian() # create gradient of objective df = nlp.evaluate_grad_objective() # create KKT system kkt = BlockMatrix(2, 2) kkt.set_block(0, 0, identity(nx)) kkt.set_block(1, 0, jac) kkt.set_block(0, 1, jac.transpose()) zeros = np.zeros(nc) rhs = BlockVector(2) rhs.set_block(0, -df) rhs.set_block(1, zeros) flat_kkt = kkt.tocoo().tocsc() flat_rhs = rhs.flatten() sol = spsolve(flat_kkt, flat_rhs) return sol[nlp.n_primals():nlp.n_primals() + nlp.n_constraints()]
def setUp(self): 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)) self.block_m = m bm = BlockMatrix(2, 2) bm.name = 'basic_matrix' bm.set_block(0, 0, m.copy()) bm.set_block(1, 1, m.copy()) bm.set_block(0, 1, m.copy()) self.basic_m = bm self.dense = np.zeros((8, 8)) self.dense[0:4, 0:4] = m.toarray() self.dense[0:4, 4:8] = m.toarray() self.dense[4:8, 4:8] = m.toarray() self.composed_m = BlockMatrix(2, 2) self.composed_m.set_block(0, 0, self.block_m.copy()) self.composed_m.set_block(1, 1, self.basic_m.copy())
def test_get_block_row_index(self): m = BlockMatrix(2, 4) m.set_block(0, 0, coo_matrix((3, 2))) m.set_block(0, 1, coo_matrix((3, 4))) m.set_block(0, 2, coo_matrix((3, 3))) m.set_block(0, 3, coo_matrix((3, 6))) m.set_block(1, 3, coo_matrix((5, 6))) brow = m.get_block_row_index(0) self.assertEqual(brow, 0) brow = m.get_block_row_index(6) self.assertEqual(brow, 1)
def _setup_jacs(self): self._jac_ineq.set_col_size(self._num_time_blocks, self._total_num_coupling_vars) for ndx, nlp in self._nlps.items(): self._jac_ineq.set_row_size(ndx, nlp.n_ineq_constraints()) self._jac_ineq.set_col_size(ndx, nlp.n_primals()) sub_block = BlockMatrix(nbrows=3, nbcols=1) sub_block.set_row_size(0, nlp.n_eq_constraints()) sub_block.set_col_size(0, nlp.n_primals()) sub_block.set_block(1, 0, self._link_backward_matrices[ndx]) sub_block.set_block(2, 0, self._link_forward_matrices[ndx]) self._jac_eq.set_block(ndx, ndx, sub_block) sub_block = BlockMatrix(nbrows=3, nbcols=1) sub_block.set_row_size(0, nlp.n_eq_constraints()) sub_block.set_col_size(0, self._total_num_coupling_vars) sub_block.set_block(1, 0, -self._link_backward_coupling_matrices[ndx]) sub_block.set_block(2, 0, -self._link_forward_coupling_matrices[ndx]) self._jac_eq.set_block(ndx, self._num_time_blocks, sub_block)
def test_get_block_column_index(self): m = BlockMatrix(2, 4) m.set_block(0, 0, coo_matrix((3, 2))) m.set_block(0, 1, coo_matrix((3, 4))) m.set_block(0, 2, coo_matrix((3, 3))) m.set_block(0, 3, coo_matrix((3, 6))) m.set_block(1, 3, coo_matrix((5, 6))) bcol = m.get_block_column_index(8) self.assertEqual(bcol, 2) bcol = m.get_block_column_index(5) self.assertEqual(bcol, 1) bcol = m.get_block_column_index(14) self.assertEqual(bcol, 3)
def main(show_plot=True): if show_plot: import matplotlib.pylab as plt instance = create_problem(0.0, 10.0) # Discretize model using Orthogonal Collocation discretizer = pyo.TransformationFactory('dae.collocation') discretizer.apply_to(instance, nfe=100, ncp=3, scheme='LAGRANGE-RADAU') discretizer.reduce_collocation_points(instance, var=instance.u, ncp=1, contset=instance.t) # Interface pyomo model with nlp nlp = PyomoNLP(instance) x = nlp.create_new_vector('primals') x.fill(1.0) nlp.set_primals(x) lam = nlp.create_new_vector('duals') lam.fill(1.0) nlp.set_duals(lam) # Evaluate jacobian jac = nlp.evaluate_jacobian() if show_plot: plt.spy(jac) plt.title('Jacobian of the constraints\n') plt.show() # Evaluate hessian of the lagrangian hess_lag = nlp.evaluate_hessian_lag() if show_plot: plt.spy(hess_lag) plt.title('Hessian of the Lagrangian function\n') plt.show() # Build KKT matrix kkt = BlockMatrix(2, 2) kkt.set_block(0, 0, hess_lag) kkt.set_block(1, 0, jac) kkt.set_block(0, 1, jac.transpose()) if show_plot: plt.spy(kkt.tocoo()) plt.title('KKT system\n') plt.show()
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 _setup_kkt_and_rhs_structure(self): # First setup the diagonal blocks for ndx, nlp in self._nlps.items(): sub_kkt = BlockMatrix(nbrows=2, nbcols=2) n = nlp.n_primals() + nlp.n_eq_constraints( ) + 2 * nlp.n_ineq_constraints() sub_kkt.set_row_size(0, n) sub_kkt.set_col_size(0, n) if ndx == 0: sub_kkt.set_row_size(1, 0) sub_kkt.set_col_size(1, 0) else: sub_kkt.set_row_size(1, self._num_states) sub_kkt.set_col_size(1, self._num_states) row_1 = BlockMatrix(nbrows=1, nbcols=4) if ndx == 0: row_1.set_row_size(0, 0) else: row_1.set_row_size(0, self._num_states) row_1.set_col_size(0, nlp.n_primals()) row_1.set_col_size(1, nlp.n_ineq_constraints()) row_1.set_col_size(2, nlp.n_eq_constraints()) row_1.set_col_size(3, nlp.n_ineq_constraints()) row_1.set_block(0, 0, self._link_backward_matrices[ndx]) sub_kkt.set_block(1, 0, row_1) sub_kkt.set_block(0, 1, row_1.transpose()) self._kkt.set_block(ndx, ndx, sub_kkt) sub_rhs = BlockVector(2) sub_rhs.set_block(0, np.zeros(n)) if ndx == 0: sub_rhs.set_block(1, np.zeros(0)) else: sub_rhs.set_block(1, np.zeros(self._num_states)) self._rhs.set_block(ndx, sub_rhs) # Setup the border blocks for ndx, nlp in self._nlps.items(): nlp = self._nlps[ndx] block = BlockMatrix(nbrows=2, nbcols=2) sub_block = BlockMatrix(nbrows=self._num_time_blocks, nbcols=4) sub_block.set_col_size(0, nlp.n_primals()) sub_block.set_col_size(1, nlp.n_ineq_constraints()) sub_block.set_col_size(2, nlp.n_eq_constraints()) sub_block.set_col_size(3, nlp.n_ineq_constraints()) for sub_ndx in range(self._num_time_blocks): if sub_ndx == self._num_time_blocks - 1: sub_block.set_row_size(sub_ndx, 0) else: sub_block.set_row_size(sub_ndx, self._num_states) sub_block.set_block(ndx, 0, self._link_forward_matrices[ndx]) block.set_block(0, 0, sub_block) block.set_block( 1, 1, -self._link_backward_coupling_matrices[ndx].transpose()) self._kkt.set_block(self._num_time_blocks, ndx, block) self._kkt.set_block(ndx, self._num_time_blocks, block.transpose()) # Setup the bottom right block block = BlockMatrix(2, 2) rhs_block = BlockVector(2) sub_block = BlockMatrix(1, self._num_time_blocks) sub_rhs_block = BlockVector(self._num_time_blocks) for ndx in range(self._num_time_blocks): sub_block.set_block( 0, ndx, -self._link_forward_coupling_matrices[ndx].transpose()) if ndx == self._num_time_blocks - 1: sub_rhs_block.set_block(ndx, np.zeros(0)) else: sub_rhs_block.set_block(ndx, np.zeros(self._num_states)) rhs_block.set_block(0, sub_rhs_block) rhs_block.set_block(1, np.zeros(self._total_num_coupling_vars)) block.set_block(1, 0, sub_block) block.set_block(0, 1, sub_block.transpose()) self._kkt.set_block(self._num_time_blocks, self._num_time_blocks, block) self._rhs.set_block(self._num_time_blocks, rhs_block)
# Interface pyomo model with nlp nlp = PyomoNLP(instance) x = nlp.create_new_vector('primals') x.fill(1.0) nlp.set_primals(x) lam = nlp.create_new_vector('duals') lam.fill(1.0) nlp.set_duals(lam) # Evaluate jacobian jac = nlp.evaluate_jacobian() plt.spy(jac) plt.title('Jacobian of the constraints\n') plt.show() # Evaluate hessian of the lagrangian hess_lag = nlp.evaluate_hessian_lag() plt.spy(hess_lag) plt.title('Hessian of the Lagrangian function\n') plt.show() # Build KKT matrix kkt = BlockMatrix(2, 2) kkt.set_block(0, 0, hess_lag) kkt.set_block(1, 0, jac) kkt.set_block(0, 1, jac.transpose()) plt.spy(kkt.tocoo()) plt.title('KKT system\n') plt.show()
def evaluate_primal_dual_kkt_matrix(self, timer=None): if timer is None: timer = HierarchicalTimer() timer.start('eval hess') hessian = self._nlp.evaluate_hessian_lag() timer.stop('eval hess') timer.start('eval jac') jac_eq = self._nlp.evaluate_jacobian_eq() jac_ineq = self._nlp.evaluate_jacobian_ineq() timer.stop('eval jac') duals_primals_lb = self._duals_primals_lb duals_primals_ub = self._duals_primals_ub duals_slacks_lb = self._duals_slacks_lb duals_slacks_ub = self._duals_slacks_ub primals = self._nlp.get_primals() timer.start('hess block') data = (duals_primals_lb / (primals - self._nlp.primals_lb()) + duals_primals_ub / (self._nlp.primals_ub() - primals)) n = self._nlp.n_primals() indices = np.arange(n) hess_block = scipy.sparse.coo_matrix((data, (indices, indices)), shape=(n, n)) hess_block += hessian timer.stop('hess block') timer.start('slack block') data = (duals_slacks_lb / (self._slacks - self._nlp.ineq_lb()) + duals_slacks_ub / (self._nlp.ineq_ub() - self._slacks)) n = self._nlp.n_ineq_constraints() indices = np.arange(n) slack_block = scipy.sparse.coo_matrix((data, (indices, indices)), shape=(n, n)) timer.stop('slack block') timer.start('set block') kkt = BlockMatrix(4, 4) kkt.set_block(0, 0, hess_block) kkt.set_block(1, 1, slack_block) kkt.set_block(2, 0, jac_eq) kkt.set_block(0, 2, jac_eq.transpose()) kkt.set_block(3, 0, jac_ineq) kkt.set_block(0, 3, jac_ineq.transpose()) kkt.set_block( 3, 1, -scipy.sparse.identity(self._nlp.n_ineq_constraints(), format='coo')) kkt.set_block( 1, 3, -scipy.sparse.identity(self._nlp.n_ineq_constraints(), format='coo')) timer.stop('set block') return kkt
results = opt.solve(m, tee=True) ################################################################# nlp = PyomoNLP(m) x = nlp.init_primals() y = compute_init_lam(nlp, x=x) nlp.set_primals(x) nlp.set_duals(y) J = nlp.extract_submatrix_jacobian(pyomo_variables=[m.x1, m.x2, m.x3], pyomo_constraints=[m.const1, m.const2]) H = nlp.extract_submatrix_hessian_lag(pyomo_variables_rows=[m.x1, m.x2, m.x3], pyomo_variables_cols=[m.x1, m.x2, m.x3]) M = BlockMatrix(2, 2) M.set_block(0, 0, H) M.set_block(1, 0, J) M.set_block(0, 1, J.transpose()) Np = BlockMatrix(2, 1) Np.set_block( 0, 0, nlp.extract_submatrix_hessian_lag(pyomo_variables_rows=[m.x1, m.x2, m.x3], pyomo_variables_cols=[m.eta1, m.eta2])) Np.set_block( 1, 0, nlp.extract_submatrix_jacobian(pyomo_variables=[m.eta1, m.eta2], pyomo_constraints=[m.const1, m.const2])) ds = spsolve(M.tocsc(), -Np.tocsc())
def test_mpi_schur_complement(self): rank_by_index = list() for ndx in range(3): for _rank in range(size): if (ndx - _rank) % size == 0: rank_by_index.append(_rank) rank_by_index.append(-1) A = MPIBlockMatrix(nbrows=4, nbcols=4, rank_ownership=[ rank_by_index, rank_by_index, rank_by_index, rank_by_index ], mpi_comm=comm) if rank_by_index[0] == rank: A.set_block( 0, 0, coo_matrix(np.array([[1, 1], [0, 1]], dtype=np.double))) if rank_by_index[1] == rank: A.set_block( 1, 1, coo_matrix(np.array([[1, 0], [0, 1]], dtype=np.double))) if rank_by_index[2] == rank: A.set_block( 2, 2, coo_matrix(np.array([[1, 0], [1, 1]], dtype=np.double))) A.set_block(3, 3, coo_matrix(np.array([[0, 0], [0, 1]], dtype=np.double))) if rank_by_index[0] == rank: A.set_block( 3, 0, coo_matrix(np.array([[0, -1], [0, 0]], dtype=np.double))) if rank_by_index[1] == rank: A.set_block( 3, 1, coo_matrix(np.array([[-1, 0], [0, -1]], dtype=np.double))) if rank_by_index[2] == rank: A.set_block( 3, 2, coo_matrix(np.array([[0, 0], [-1, 0]], dtype=np.double))) A.broadcast_block_sizes() local_A = BlockMatrix(4, 4) local_A.set_block( 0, 0, coo_matrix(np.array([[1, 1], [0, 1]], dtype=np.double))) local_A.set_block( 1, 1, coo_matrix(np.array([[1, 0], [0, 1]], dtype=np.double))) local_A.set_block( 2, 2, coo_matrix(np.array([[1, 0], [1, 1]], dtype=np.double))) local_A.set_block( 3, 3, coo_matrix(np.array([[0, 0], [0, 1]], dtype=np.double))) local_A.set_block( 3, 0, coo_matrix(np.array([[0, -1], [0, 0]], dtype=np.double))) local_A.set_block( 3, 1, coo_matrix(np.array([[-1, 0], [0, -1]], dtype=np.double))) local_A.set_block( 3, 2, coo_matrix(np.array([[0, 0], [-1, 0]], dtype=np.double))) local_A.set_block(0, 3, local_A.get_block(3, 0).transpose(copy=True)) local_A.set_block(1, 3, local_A.get_block(3, 1).transpose(copy=True)) local_A.set_block(2, 3, local_A.get_block(3, 2).transpose(copy=True)) rhs = MPIBlockVector(nblocks=4, rank_owner=rank_by_index, mpi_comm=comm) if rank_by_index[0] == rank: rhs.set_block(0, np.array([1, 0], dtype=np.double)) if rank_by_index[1] == rank: rhs.set_block(1, np.array([0, 0], dtype=np.double)) if rank_by_index[2] == rank: rhs.set_block(2, np.array([0, 1], dtype=np.double)) rhs.set_block(3, np.array([1, 1], dtype=np.double)) rhs.broadcast_block_sizes() local_rhs = BlockVector(4) local_rhs.set_block(0, np.array([1, 0], dtype=np.double)) local_rhs.set_block(1, np.array([0, 0], dtype=np.double)) local_rhs.set_block(2, np.array([0, 1], dtype=np.double)) local_rhs.set_block(3, np.array([1, 1], dtype=np.double)) x1 = np.linalg.solve(local_A.toarray(), local_rhs.flatten()) solver_class = parapint.linalg.MPISchurComplementLinearSolver sc_solver = solver_class( subproblem_solvers={ ndx: ScipyInterface(compute_inertia=True) for ndx in range(3) }, schur_complement_solver=ScipyInterface(compute_inertia=True)) sc_solver.do_symbolic_factorization(A) sc_solver.do_numeric_factorization(A) x2 = sc_solver.do_back_solve(rhs) self.assertTrue(np.allclose(x1, x2.make_local_copy().flatten())) inertia1 = sc_solver.get_inertia() eig = np.linalg.eigvals(local_A.toarray()) pos = np.count_nonzero(eig > 0) neg = np.count_nonzero(eig < 0) zero = np.count_nonzero(eig == 0) inertia2 = (pos, neg, zero) self.assertEqual(inertia1, inertia2) sc_solver.do_numeric_factorization(A) x2 = sc_solver.do_back_solve(rhs) self.assertTrue(np.allclose(x1, x2.make_local_copy().flatten()))
def test_matrix_multiply(self): """ Test [A B C * [G J = [A*G + B*H + C*I A*J + B*K + C*L D E F] H K D*G + E*H + F*I D*J + E*K + F*L] I L] """ np.random.seed(0) A = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) B = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) C = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) D = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) E = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) F = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) G = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) H = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) I = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) J = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) K = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) L = sp.csr_matrix(np.random.normal(0, 10, (2, 2))) bm1 = BlockMatrix(2, 3) bm2 = BlockMatrix(3, 2) bm1.set_block(0, 0, A) bm1.set_block(0, 1, B) bm1.set_block(0, 2, C) bm1.set_block(1, 0, D) bm1.set_block(1, 1, E) bm1.set_block(1, 2, F) bm2.set_block(0, 0, G) bm2.set_block(1, 0, H) bm2.set_block(2, 0, I) bm2.set_block(0, 1, J) bm2.set_block(1, 1, K) bm2.set_block(2, 1, L) got = (bm1 * bm2).toarray() exp00 = (A * G + B * H + C * I).toarray() exp01 = (A * J + B * K + C * L).toarray() exp10 = (D * G + E * H + F * I).toarray() exp11 = (D * J + E * K + F * L).toarray() exp = np.zeros((4, 4)) exp[0:2, 0:2] = exp00 exp[0:2, 2:4] = exp01 exp[2:4, 0:2] = exp10 exp[2:4, 2:4] = exp11 self.assertTrue(np.allclose(got, exp))