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 = COOMatrix((data, (row, col)), shape=(4, 4)) m.name = 'basic_matrix' self.full_m = m row = np.array([0, 3, 1, 2, 3]) col = np.array([0, 0, 1, 2, 3]) data = np.array([2., 1., 3., 4., 5.]) m = CSCSymMatrix((data, (row, col)), shape=(4, 4)) m.name = 'basic_sym_matrix' self.basic_m = m row = np.array([0, 0, 1, 2, 3]) col = np.array([0, 3, 1, 2, 3]) data = np.array([2., 1., 3., 4., 5.]) m = COOSymMatrix((data, (col, row)), shape=(4, 4)) m.name = 'basic_sym_matrix' self.transposed = m row = np.array( [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5]) col = np.array( [0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5]) data = np.array([ 36., 17., 33., 19., 18., 43., 12., 11., 13., 18., 8., 7., 8., 6., 9., 15., 14., 16., 11., 8., 29. ]) m = CSCSymMatrix((data, (row, col)), shape=(6, 6)) m.name = 'G' self.g_matrix = m
def setUp(self): row = np.array([0, 1, 4, 1, 2, 7, 2, 3, 5, 3, 4, 5, 4, 7, 5, 6, 6, 7]) col = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7]) data = np.array([ 27, 5, 12, 56, 66, 34, 94, 31, 41, 7, 98, 72, 24, 33, 78, 47, 98, 41 ]) m = COOSymMatrix((data, (row, col)), shape=(8, 8)) self.block00 = m row = np.array([0, 3, 1, 0]) col = np.array([0, 3, 1, 2]) data = np.array([4, 5, 7, 9]) m = COOMatrix((data, (row, col)), shape=(4, 8)) self.block10 = m row = np.array([0, 1, 2, 3]) col = np.array([0, 1, 2, 3]) data = np.array([1, 1, 1, 1]) m = COOSymMatrix((data, (row, col)), shape=(4, 4)) self.block11 = m bm = BlockSymMatrix(2) bm.name = 'basic_matrix' bm[0, 0] = self.block00 bm[1, 0] = self.block10 bm[1, 1] = self.block11 self.basic_m = bm
def tril(A, k=0, format=None): """Return the lower triangular portion of a matrix in sparse format Returns the elements on or below the k-th diagonal of the matrix A. - k = 0 corresponds to the main diagonal - k > 0 is above the main diagonal - k < 0 is below the main diagonal Parameters ---------- A : dense or sparse matrix Matrix whose lower triangular portion is desired. k : integer : optional The top-most diagonal of the lower triangle. format : string Sparse format of the result, e.g. format="csr", etc. Returns ------- L : sparse matrix Lower triangular portion of A in sparse format. See Also -------- triu : upper triangle in sparse format Examples -------- >>> from pyomo.contrib.pynumero.sparse import CSRMatrix, tril >>> A = csr_matrix([[1, 2, 0, 0, 3], [4, 5, 0, 6, 7], [0, 0, 8, 9, 0]], ... dtype='int32') >>> A.toarray() array([[1, 2, 0, 0, 3], [4, 5, 0, 6, 7], [0, 0, 8, 9, 0]]) >>> tril(A).toarray() array([[1, 0, 0, 0, 0], [4, 5, 0, 0, 0], [0, 0, 8, 0, 0]]) >>> tril(A).nnz 4 >>> tril(A, k=1).toarray() array([[1, 2, 0, 0, 0], [4, 5, 0, 0, 0], [0, 0, 8, 9, 0]]) >>> tril(A, k=-1).toarray() array([[0, 0, 0, 0, 0], [4, 0, 0, 0, 0], [0, 0, 0, 0, 0]]) >>> tril(A, format='csc') <3x5 sparse matrix of type '<class 'numpy.int32'>' with 4 stored elements in Compressed Sparse Column format> """ from pyomo.contrib.pynumero.sparse import COOMatrix # convert to COOrdinate format where things are easy A = COOMatrix(A, copy=False) mask = A.row + k >= A.col return _masked_coo(A, mask).asformat(format)
def test_mul_sparse_matrix(self): # test symmetric times symmetric m = self.g_matrix dense_m = m.toarray() res = m * m dense_res = np.matmul(dense_m, dense_m) self.assertTrue(res.is_symmetric) self.assertTrue(np.allclose(res.toarray(), dense_res)) # test symmetric times unsymmetric m = self.basic_m dense_m2 = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]]) m2 = COOMatrix(dense_m2) res = m * m2 dense_res = np.matmul(m.toarray(), dense_m2) self.assertFalse(res.is_symmetric) self.assertTrue(np.allclose(res.toarray(), dense_res)) # test symmetric times full symmetric m2 = self.full_m dense_m = m.toarray() dense_m2 = m2.toarray() res = m * m2 dense_res = np.matmul(dense_m, dense_m2) self.assertTrue(res.is_symmetric) self.assertTrue(np.allclose(res.toarray(), dense_res)) # test symmetric times full scipycoo m2 = coo_matrix((self.full_m.data, (self.full_m.row, self.full_m.col)), shape=self.full_m.shape) dense_m = m.toarray() dense_m2 = m2.toarray() with self.assertRaises(Exception) as context: res = m * m2 m = self.basic_m dense_m2 = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]]) m2 = coo_matrix(dense_m2) with self.assertRaises(Exception) as context: res = m * m2
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 = COOMatrix((data, (row, col)), shape=(4, 4)) self.block_m = m bm = BlockMatrix(2, 2) bm.name = 'basic_matrix' bm[0, 0] = m bm[1, 1] = m bm[0, 1] = m self.basic_m = bm self.composed_m = BlockMatrix(2, 2) self.composed_m[0, 0] = self.block_m self.composed_m[1, 1] = self.basic_m
def test_sub_sparse(self): m = self.basic_m mm = m - m mm2 = np.zeros(m.shape, dtype=np.double) self.assertIsInstance(mm, CSRSymMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), mm2.flatten().tolist()) row = np.array([0, 3, 2]) col = np.array([0, 0, 2]) data = np.array([2., 1., 4.]) m2 = COOSymMatrix((data, (row, col)), shape=(4, 4)) test_m = np.array([[0., 0., 0., 0.], [0., 3., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 5.]]) mm = m - m2 self.assertIsInstance(mm, CSRSymMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist()) row = np.array([0, 3, 1, 0, 2]) col = np.array([0, 3, 1, 2, 1]) data = np.array([4., 5., 7., 9., 6.]) m2 = COOMatrix((data, (row, col)), shape=(4, 4)) mm = m - m2 test_m = np.array([[-2., 0., -9., 1.], [0., -4., 0., 0.], [0., -6., 4., 0.], [1., 0., 0., 0]]) self.assertIsInstance(mm, CSCMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist()) test_m = np.array([[2., 0., 9., -1.], [0., 4., 0., 0.], [0., 6., -4., 0.], [-1., 0., 0., 0]]) mm = m2 - m self.assertIsInstance(mm, CSRMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist())
def test_add_sparse(self): m = self.basic_m mm = m + m test_m = np.array([[2., 0., 0., 1.], [0., 3., 0., 0.], [0., 0., 4., 0.], [1., 0., 0., 5.]]) mm2 = test_m * 2 self.assertIsInstance(mm, CSRSymMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), mm2.flatten().tolist()) row = np.array([0, 3, 2]) col = np.array([0, 0, 2]) data = np.array([2., 1., 4.]) m2 = COOSymMatrix((data, (row, col)), shape=(4, 4)) test_m = np.array([[4., 0., 0., 2.], [0., 3., 0., 0.], [0., 0., 8., 0.], [2., 0., 0., 5.]]) mm = m + m2 self.assertIsInstance(mm, CSRSymMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist()) row = np.array([0, 3, 1, 0, 2]) col = np.array([0, 3, 1, 2, 1]) data = np.array([4., 5., 7., 9., 6.]) m2 = COOMatrix((data, (row, col)), shape=(4, 4)) mm = m + m2 test_m = np.array([[6., 0., 9., 1.], [0., 10., 0., 0.], [0., 6., 4., 0.], [1., 0., 0., 10.]]) self.assertIsInstance(mm, CSCMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist()) mm = m2 + m self.assertIsInstance(mm, CSRMatrix) self.assertListEqual(mm.toarray().flatten().tolist(), test_m.flatten().tolist())
def test_jacobian_c(self): nz = len(self.complicated_vars_ids) nxi = nz + self.G.shape[1] ngi = nz + self.A.shape[0] Ji = BlockMatrix(2, 2) Ji[0, 0] = COOMatrix(self.A) B1 = np.zeros((nz, self.A.shape[1])) B2 = np.zeros((nz, nz)) for i, v in enumerate(self.complicated_vars_ids): B1[i, v] = -1.0 B2[i, i] = 1.0 Ji[1, 0] = COOMatrix(B1) Ji[1, 1] = COOMatrix(B2) dense_Ji = Ji.todense() x = self.nlp.create_vector_x() jac_c = self.nlp.jacobian_c(x) total_nx = nxi * self.n_scenarios + nz total_nc = (ngi + nz) * self.n_scenarios self.assertEqual(jac_c.shape, (total_nc, total_nx)) # check block jacobians for i in range(self.n_scenarios): jac_ci = jac_c[i, i].todense() self.assertTrue(np.allclose(jac_ci, dense_Ji)) # check coupling jacobians Ai_ = BlockMatrix(1, 2) Ai_[0, 1] = IdentityMatrix(nz) Ai_[0, 0] = EmptyMatrix(nz, self.G.shape[1]) Ai_ = Ai_.todense() Bi_ = -IdentityMatrix(nz).todense() for i in range(self.n_scenarios): Ai = jac_c[self.n_scenarios + i, i] self.assertTrue(np.allclose(Ai.todense(), Ai_)) Bi = jac_c[self.n_scenarios + i, self.n_scenarios] self.assertTrue(np.allclose(Bi.todense(), Bi_)) # test flattened vector jac_g = self.nlp.jacobian_c(x.flatten()) total_nx = nxi * self.n_scenarios + nz total_nc = (ngi + nz) * self.n_scenarios self.assertEqual(jac_c.shape, (total_nc, total_nx)) # check block jacobians for i in range(self.n_scenarios): jac_ci = jac_c[i, i].todense() self.assertTrue(np.allclose(jac_ci, dense_Ji)) # check coupling jacobians Ai_ = BlockMatrix(1, 2) Ai_[0, 1] = IdentityMatrix(nz) Ai_[0, 0] = EmptyMatrix(nz, self.G.shape[1]) Ai_ = Ai_.todense() Bi_ = -IdentityMatrix(nz).todense() for i in range(self.n_scenarios): Ai = jac_c[self.n_scenarios + i, i] self.assertTrue(np.allclose(Ai.todense(), Ai_)) Bi = jac_c[self.n_scenarios + i, self.n_scenarios] self.assertTrue(np.allclose(Bi.todense(), Bi_))
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 : COOMatrix, optional Output matrix with the structure of the jacobian already defined. Returns ------- BlockMatrix """ assert x.size == self.nx, "Dimension missmatch" if out is None: if isinstance(x, BlockVector): assert x.nblocks == self.nblocks + 1 jac_c = BlockMatrix(2 * self.nblocks, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = x[sid] jac_c[sid, sid] = nlp.jacobian_c(xi) # coupling matrices Ai scenario_vids = self._zid_to_vid[sid] col = np.array([vid for vid in scenario_vids]) row = np.arange(0, self.nz) data = np.ones(self.nz, dtype=np.double) jac_c[sid + self.nblocks, sid] = COOMatrix( (data, (row, col)), shape=(self.nz, nlp.nx)) # coupling matrices Bi jac_c[sid + self.nblocks, self.nblocks] = -IdentityMatrix(self.nz) return jac_c elif isinstance(x, np.ndarray): assert x.size == self.nx block_x = self.create_vector_x() block_x.copyfrom(x) x_ = block_x jac_c = BlockMatrix(2 * self.nblocks, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = x_[sid] jac_c[sid, sid] = nlp.jacobian_c(xi) # coupling matrices Ai scenario_vids = self._zid_to_vid[sid] col = np.array([vid for vid in scenario_vids]) row = np.arange(0, self.nz) data = np.ones(self.nz, dtype=np.double) jac_c[sid + self.nblocks, sid] = COOMatrix( (data, (row, col)), shape=(self.nz, nlp.nx)) # coupling matrices Bi jac_c[sid + self.nblocks, self.nblocks] = -IdentityMatrix(self.nz) return jac_c else: raise RuntimeError("Input vector format not recognized") else: raise NotImplementedError("ToDo")
def _create_jacobian_structures(self): # Note: This method requires the complicated vars map to be # created beforehand # build general jacobian jac_g = BlockMatrix(2 * self.nblocks, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = nlp.x_init() jac_g[sid, sid] = nlp.jacobian_g(xi) # coupling matrices Ai scenario_vids = self._zid_to_vid[sid] col = np.array([vid for vid in scenario_vids]) row = np.arange(0, self.nz) data = np.ones(self.nz, dtype=np.double) jac_g[sid + self.nblocks, sid] = COOMatrix((data, (row, col)), shape=(self.nz, nlp.nx)) # coupling matrices Bi jac_g[sid + self.nblocks, self.nblocks] = -IdentityMatrix(self.nz) self._internal_jacobian_g = jac_g flat_jac_g = jac_g.tocoo() self._irows_jac_g = flat_jac_g.row self._jcols_jac_g = flat_jac_g.col self._nnz_jac_g = flat_jac_g.nnz # build jacobian equality constraints jac_c = BlockMatrix(2 * self.nblocks, self.nblocks + 1) for sid, nlp in enumerate(self._nlps): xi = nlp.x_init() jac_c[sid, sid] = nlp.jacobian_c(xi) # coupling matrices Ai scenario_vids = self._zid_to_vid[sid] col = np.array([vid for vid in scenario_vids]) row = np.arange(0, self.nz) data = np.ones(self.nz, dtype=np.double) jac_c[sid + self.nblocks, sid] = COOMatrix((data, (row, col)), shape=(self.nz, nlp.nx)) # coupling matrices Bi jac_c[sid + self.nblocks, self.nblocks] = -IdentityMatrix(self.nz) self._internal_jacobian_c = jac_c flat_jac_c = jac_c.tocoo() self._irows_jac_c = flat_jac_c.row self._jcols_jac_c = flat_jac_c.col self._nnz_jac_c = flat_jac_c.nnz # build jacobian inequality constraints jac_d = BlockMatrix(self.nblocks, self.nblocks) for sid, nlp in enumerate(self._nlps): xi = nlp.x_init() jac_d[sid, sid] = nlp.jacobian_d(xi) self._internal_jacobian_d = jac_d flat_jac_d = jac_d.tocoo() self._irows_jac_d = flat_jac_d.row self._jcols_jac_d = flat_jac_d.col self._nnz_jac_d = flat_jac_d.nnz
def triu(A, k=0, format=None): """Return the upper triangular portion of a matrix in sparse format Returns the elements on or above the k-th diagonal of the matrix A. - k = 0 corresponds to the main diagonal - k > 0 is above the main diagonal - k < 0 is below the main diagonal Parameters ---------- A : dense or sparse matrix Matrix whose upper triangular portion is desired. k : integer : optional The bottom-most diagonal of the upper triangle. format : string Sparse format of the result, e.g. format="csr", etc. Returns ------- L : sparse matrix Upper triangular portion of A in sparse format. See Also -------- tril : lower triangle in sparse format Examples -------- >>> from pyomo.contrib.pynumero.sparse import CSRMatrix, triu >>> A = CSRMatrix([[1, 2, 0, 0, 3], [4, 5, 0, 6, 7], [0, 0, 8, 9, 0]], ... dtype='int32') >>> A.toarray() array([[1, 2, 0, 0, 3], [4, 5, 0, 6, 7], [0, 0, 8, 9, 0]]) >>> triu(A).toarray() array([[1, 2, 0, 0, 3], [0, 5, 0, 6, 7], [0, 0, 8, 9, 0]]) >>> triu(A).nnz 8 >>> triu(A, k=1).toarray() array([[0, 2, 0, 0, 3], [0, 0, 0, 6, 7], [0, 0, 0, 9, 0]]) >>> triu(A, k=-1).toarray() array([[1, 2, 0, 0, 3], [4, 5, 0, 6, 7], [0, 0, 8, 9, 0]]) """ from pyomo.contrib.pynumero.sparse import COOMatrix # convert to COOrdinate format where things are easy if isinstance(A, SparseBase): if A.is_symmetric: A = A.tofullmatrix().tocoo() else: A = COOMatrix(A, copy=False) else: A = COOMatrix(A, copy=False) mask = A.row + k <= A.col return _masked_coo(A, mask).asformat(format)
def _masked_coo(mat, mask): from pyomo.contrib.pynumero.sparse import COOMatrix row = mat.row[mask] col = mat.col[mask] data = mat.data[mask] return COOMatrix((data, (row, col)), shape=mat.shape, dtype=mat.dtype)