def test_atom(): for atom_list, objective_type in atoms: for atom, size, args, obj_val in atom_list: for row in range(size[0]): for col in range(size[1]): for solver in SOLVERS_TO_TRY: # Atoms with Constant arguments. const_args = [Constant(arg) for arg in args] yield (run_atom, atom, Problem( objective_type(atom(*const_args)[row, col])), obj_val[row, col].value, solver) # Atoms with Variable arguments. variables = [] constraints = [] for idx, expr in enumerate(args): variables.append(Variable(*intf.size(expr))) constraints.append(variables[-1] == expr) objective = objective_type(atom(*variables)[row, col]) yield (run_atom, atom, Problem(objective, constraints), obj_val[row, col].value, solver) # Atoms with Parameter arguments. parameters = [] for expr in args: parameters.append(Parameter(*intf.size(expr))) parameters[ -1].value = intf.DEFAULT_INTF.const_to_matrix( expr) objective = objective_type(atom(*parameters)[row, col]) yield (run_atom, atom, Problem(objective), obj_val[row, col].value, solver)
def test_atom(): for atom_list, objective_type in atoms: for atom, size, args, obj_val in atom_list: for row in xrange(size[0]): for col in xrange(size[1]): for solver in [ECOS, SCS, CVXOPT, POGS]: # Atoms with Constant arguments. yield (run_atom, atom, Problem(objective_type(atom(*args)[row,col])), obj_val[row,col].value, solver) # Atoms with Variable arguments. variables = [] constraints = [] for idx, expr in enumerate(args): variables.append( Variable(*intf.size(expr) )) constraints.append( variables[-1] == expr) objective = objective_type(atom(*variables)[row,col]) yield (run_atom, atom, Problem(objective, constraints), obj_val[row,col].value, solver) # Atoms with Parameter arguments. parameters = [] for expr in args: parameters.append( Parameter(*intf.size(expr)) ) parameters[-1].value = intf.DEFAULT_INTERFACE.const_to_matrix(expr) objective = objective_type(atom(*parameters)[row,col]) yield (run_atom, atom, Problem(objective), obj_val[row,col].value, solver)
def _validate_value(self, val): """Check that the value satisfies the parameter's symbolic attributes. Parameters ---------- val : numeric type The value assigned. Returns ------- numeric type The value converted to the proper matrix type. """ # Convert val to the proper matrix type. val = intf.DEFAULT_INTERFACE.const_to_matrix(val) size = intf.size(val) if size != self.size: raise ValueError("Invalid dimensions (%s, %s) for %s value." % (size[0], size[1], self.__class__.__name__)) # All signs are valid if sign is unknown. # Otherwise value sign must match declared sign. sign = intf.sign(val) if self.is_positive() and not sign.is_positive() or \ self.is_negative() and not sign.is_negative(): raise ValueError("Invalid sign for %s value." % self.__class__.__name__) return val
def _validate_value(self, val): """Check that the value satisfies the leaf's symbolic attributes. Parameters ---------- val : numeric type The value assigned. Returns ------- numeric type The value converted to the proper matrix type. """ if val is not None: # Convert val to the proper matrix type. val = intf.DEFAULT_INTF.const_to_matrix(val) size = intf.size(val) if size != self.size: raise ValueError( "Invalid dimensions (%s, %s) for %s value." % (size[0], size[1], self.__class__.__name__) ) # All signs are valid if sign is unknown. # Otherwise value sign must match declared sign. pos_val, neg_val = intf.sign(val) if self.is_positive() and not pos_val or \ self.is_negative() and not neg_val: raise ValueError( "Invalid sign for %s value." % self.__class__.__name__ ) return val
def _validate_value(self, val): """Check that the value satisfies the leaf's symbolic attributes. Parameters ---------- val : numeric type The value assigned. Returns ------- numeric type The value converted to the proper matrix type. """ if val is not None: # Convert val to the proper matrix type. val = intf.DEFAULT_INTF.const_to_matrix(val) size = intf.size(val) if size != self.size: raise ValueError("Invalid dimensions (%s, %s) for %s value." % (size[0], size[1], self.__class__.__name__)) # All signs are valid if sign is unknown. # Otherwise value sign must match declared sign. pos_val, neg_val = intf.sign(val) if self.is_positive() and not pos_val or \ self.is_negative() and not neg_val: raise ValueError("Invalid sign for %s value." % self.__class__.__name__) # Round to correct sign. elif self.is_positive(): val = np.maximum(val, 0) elif self.is_negative(): val = np.minimum(val, 0) return val
def init_dcp_attr(self): shape = u.Shape(*intf.size(self.value)) # If scalar, check sign. Else unknown sign. if shape.size == (1, 1): sign = u.Sign.val_to_sign(self.value) else: sign = u.Sign.UNKNOWN self._dcp_attr = u.DCPAttr(sign, u.Curvature.CONSTANT, shape)
def test_numpy_scalars(self): n = 6 eps = 1e-6 cvxopt.setseed(10) P0 = cvxopt.normal(n, n) eye = cvxopt.spmatrix(1.0, range(n), range(n)) P0 = P0.T * P0 + eps * eye print P0 P1 = cvxopt.normal(n, n) P1 = P1.T*P1 P2 = cvxopt.normal(n, n) P2 = P2.T*P2 P3 = cvxopt.normal(n, n) P3 = P3.T*P3 q0 = cvxopt.normal(n, 1) q1 = cvxopt.normal(n, 1) q2 = cvxopt.normal(n, 1) q3 = cvxopt.normal(n, 1) r0 = cvxopt.normal(1, 1) r1 = cvxopt.normal(1, 1) r2 = cvxopt.normal(1, 1) r3 = cvxopt.normal(1, 1) slack = Variable() # Form the problem x = Variable(n) objective = Minimize( 0.5*quad_form(x,P0) + q0.T*x + r0 + slack) constraints = [0.5*quad_form(x,P1) + q1.T*x + r1 <= slack, 0.5*quad_form(x,P2) + q2.T*x + r2 <= slack, 0.5*quad_form(x,P3) + q3.T*x + r3 <= slack, ] # We now find the primal result and compare it to the dual result # to check if strong duality holds i.e. the duality gap is effectively zero p = Problem(objective, constraints) primal_result = p.solve(solver=SCS_MAT_FREE, verbose=True, equil_steps=1, max_iters=5000, equil_p=2, stoch=True, samples=10, precond=True) # Note that since our data is random, we may need to run this program multiple times to get a feasible primal # When feasible, we can print out the following values print x.value # solution lam1 = constraints[0].dual_value lam2 = constraints[1].dual_value lam3 = constraints[2].dual_value print type(lam1) P_lam = P0 + lam1*P1 + lam2*P2 + lam3*P3 q_lam = q0 + lam1*q1 + lam2*q2 + lam3*q3 r_lam = r0 + lam1*r1 + lam2*r2 + lam3*r3 dual_result = -0.5*q_lam.T.dot(P_lam).dot(q_lam) + r_lam print dual_result.shape self.assertEquals(intf.size(dual_result), (1,1))
def test_numpy_scalars(self): n = 6 eps = 1e-6 cvxopt.setseed(10) P0 = cvxopt.normal(n, n) eye = cvxopt.spmatrix(1.0, range(n), range(n)) P0 = P0.T * P0 + eps * eye print P0 P1 = cvxopt.normal(n, n) P1 = P1.T * P1 P2 = cvxopt.normal(n, n) P2 = P2.T * P2 P3 = cvxopt.normal(n, n) P3 = P3.T * P3 q0 = cvxopt.normal(n, 1) q1 = cvxopt.normal(n, 1) q2 = cvxopt.normal(n, 1) q3 = cvxopt.normal(n, 1) r0 = cvxopt.normal(1, 1) r1 = cvxopt.normal(1, 1) r2 = cvxopt.normal(1, 1) r3 = cvxopt.normal(1, 1) slack = cp.Variable() # Form the problem x = cp.Variable(n) objective = cp.Minimize(0.5 * cp.quad_form(x, P0) + q0.T * x + r0 + slack) constraints = [ 0.5 * cp.quad_form(x, P1) + q1.T * x + r1 <= slack, 0.5 * cp.quad_form(x, P2) + q2.T * x + r2 <= slack, 0.5 * cp.quad_form(x, P3) + q3.T * x + r3 <= slack, ] # We now find the primal result and compare it to the dual result # to check if strong duality holds i.e. the duality gap is effectively zero p = cp.Problem(objective, constraints) primal_result = p.solve() # Note that since our data is random, we may need to run this program multiple times to get a feasible primal # When feasible, we can print out the following values print x.value # solution lam1 = constraints[0].dual_value lam2 = constraints[1].dual_value lam3 = constraints[2].dual_value print type(lam1) P_lam = P0 + lam1 * P1 + lam2 * P2 + lam3 * P3 q_lam = q0 + lam1 * q1 + lam2 * q2 + lam3 * q3 r_lam = r0 + lam1 * r1 + lam2 * r2 + lam3 * r3 dual_result = -0.5 * q_lam.T.dot(P_lam).dot(q_lam) + r_lam print dual_result.shape self.assertEquals(intf.size(dual_result), (1, 1))
def test_coefficients(self): exp = vstack(self.x).canonical_form[0] coeffs = exp.coefficients() self.assertEqual(coeffs.keys(), self.x.coefficients().keys()) exp = vstack(self.x, self.y).canonical_form[0] coeffs = exp.coefficients() self.assertItemsEqual(coeffs.keys(), self.x.coefficients().keys() + self.y.coefficients().keys()) for k, blocks in coeffs.items(): self.assertEqual(len(blocks), 1) for block in blocks: self.assertEqual(intf.size(block), (4, 2)) exp = vstack(self.A, self.B, self.C).canonical_form[0] coeffs = exp.coefficients() blocks = coeffs[self.A] self.assertEqual(len(blocks), 2) for block in blocks: self.assertEqual(intf.size(block), (10, 6))
def test_numpy_scalars(self): n = 6 eps = 1e-6 np.random.seed(10) P0 = np.random.randn(n, n) eye = np.eye(n) P0 = P0.T.dot(P0) + eps * eye print(P0) P1 = np.random.randn(n, n) P1 = P1.T.dot(P1) P2 = np.random.randn(n, n) P2 = P2.T.dot(P2) P3 = np.random.randn(n, n) P3 = P3.T.dot(P3) q0 = np.random.randn(n, 1) q1 = np.random.randn(n, 1) q2 = np.random.randn(n, 1) q3 = np.random.randn(n, 1) r0 = np.random.randn(1, 1) r1 = np.random.randn(1, 1) r2 = np.random.randn(1, 1) r3 = np.random.randn(1, 1) slack = Variable() # Form the problem x = Variable(n) objective = Minimize(0.5*quad_form(x, P0) + q0.T*x + r0 + slack) constraints = [0.5*quad_form(x, P1) + q1.T*x + r1 <= slack, 0.5*quad_form(x, P2) + q2.T*x + r2 <= slack, 0.5*quad_form(x, P3) + q3.T*x + r3 <= slack, ] # We now find the primal result and compare it to the dual result # to check if strong duality holds i.e. the duality gap is effectively zero p = Problem(objective, constraints) primal_result = p.solve() # Note that since our data is random, we may need to run this program multiple times to get a feasible primal # When feasible, we can print out the following values print(x.value) # solution lam1 = constraints[0].dual_value lam2 = constraints[1].dual_value lam3 = constraints[2].dual_value print(type(lam1)) P_lam = P0 + lam1*P1 + lam2*P2 + lam3*P3 q_lam = q0 + lam1*q1 + lam2*q2 + lam3*q3 r_lam = r0 + lam1*r1 + lam2*r2 + lam3*r3 dual_result = -0.5*q_lam.T.dot(P_lam).dot(q_lam) + r_lam print(dual_result.shape) self.assertEqual(intf.size(dual_result), (1, 1))
def test_coefficients(self): exp = vstack(self.x).canonical_form[0] coeffs = exp.coefficients() self.assertEqual(coeffs.keys(), self.x.coefficients().keys()) exp = vstack(self.x, self.y).canonical_form[0] coeffs = exp.coefficients() self.assertItemsEqual(coeffs.keys(), self.x.coefficients().keys() + \ self.y.coefficients().keys()) for k, blocks in coeffs.items(): self.assertEqual(len(blocks), 1) for block in blocks: self.assertEqual(intf.size(block), (4, 2)) exp = vstack(self.A, self.B, self.C).canonical_form[0] coeffs = exp.coefficients() blocks = coeffs[self.A] self.assertEqual(len(blocks), 2) for block in blocks: self.assertEqual(intf.size(block), (10, 6))
def flatten(matrix): """Converts the matrix into a column vector. Parameters ---------- matrix : The matrix to flatten. """ np_mat = intf.DEFAULT_INTERFACE matrix = np_mat.const_to_matrix(matrix, convert_scalars=True) size = intf.size(matrix) return np_mat.reshape(matrix, (size[0]*size[1], 1))
def flatten(matrix): """Converts the matrix into a column vector. Parameters ---------- matrix : The matrix to flatten. """ np_mat = intf.DEFAULT_INTERFACE matrix = np_mat.const_to_matrix(matrix, convert_scalars=True) size = intf.size(matrix) return np_mat.reshape(matrix, (size[0] * size[1], 1))
def flatten(matrix): """Converts the matrix into a column vector. Parameters ---------- matrix : The matrix to flatten. """ if isinstance(matrix, sym.SymMatrix): vec = matrix.as_vector() else: np_mat = intf.DEFAULT_INTF matrix = np_mat.const_to_matrix(matrix, convert_scalars=True) size = intf.size(matrix) return np_mat.reshape(matrix, (size[0]*size[1], 1)) return vec
def __init__(self, value): # TODO HACK. # A fix for c.T*x where c is a 1D array. self.is_1D_array = False # Keep sparse matrices sparse. if intf.is_sparse(value): self._value = intf.DEFAULT_SPARSE_INTF.const_to_matrix(value) self._sparse = True else: if isinstance(value, np.ndarray) and len(value.shape) == 1: self.is_1D_array = True self._value = intf.DEFAULT_INTF.const_to_matrix(value) self._sparse = False # Set DCP attributes. self._size = intf.size(self.value) self._is_pos, self._is_neg = intf.sign(self.value) super(Constant, self).__init__()
def _process_constr(self, constr, mat_cache, vert_offset): """Extract the coefficients from a constraint. Parameters ---------- constr : LinConstr The linear constraint to process. mat_cache : MatrixCache The cached version of the matrix-vector pair. vert_offset : int The row offset of the constraint. """ V, I, J = mat_cache.coo_tup coeffs = op2mat.get_coefficients(constr.expr) for id_, block in coeffs: vert_start = vert_offset vert_end = vert_start + constr.size[0]*constr.size[1] if id_ is lo.CONSTANT_ID: # Flatten the block. block = self.vec_intf.const_to_matrix(block) block_size = intf.size(block) block = self.vec_intf.reshape( block, (block_size[0]*block_size[1], 1) ) mat_cache.const_vec[vert_start:vert_end, :] += block else: horiz_offset = self.sym_data.var_offsets[id_] if intf.is_scalar(block): block = intf.scalar_value(block) V.append(block) I.append(vert_start) J.append(horiz_offset) else: # Block is a numpy matrix or # scipy CSC sparse matrix. if not intf.is_sparse(block): block = intf.DEFAULT_SPARSE_INTF.const_to_matrix( block ) block = block.tocoo() V.extend(block.data) I.extend(block.row + vert_start) J.extend(block.col + horiz_offset)
def value(self): # Catch the case when the expression is known to be # zero through DCP analysis. if self.is_zero(): result = intf.DEFAULT_INTERFACE.zeros(*self.size) else: arg_values = [] for arg in self.args: # A argument without a value makes all higher level # values None. if arg.value is None: return None else: arg_values.append(arg.value) result = self.numeric(arg_values) # Reduce to a scalar if possible. if intf.size(result) == (1, 1): return intf.scalar_value(result) else: return result
def _process_constr(self, constr, mat_cache, vert_offset): """Extract the coefficients from a constraint. Parameters ---------- constr : LinConstr The linear constraint to process. mat_cache : MatrixCache The cached version of the matrix-vector pair. vert_offset : int The row offset of the constraint. """ V, I, J = mat_cache.coo_tup coeffs = op2mat.get_coefficients(constr.expr) for id_, block in coeffs: vert_start = vert_offset vert_end = vert_start + constr.size[0] * constr.size[1] if id_ is lo.CONSTANT_ID: # Flatten the block. block = self.vec_intf.const_to_matrix(block) block_size = intf.size(block) block = self.vec_intf.reshape( block, (block_size[0] * block_size[1], 1)) mat_cache.const_vec[vert_start:vert_end, :] += block else: horiz_offset = self.sym_data.var_offsets[id_] if intf.is_scalar(block): block = intf.scalar_value(block) V.append(block) I.append(vert_start) J.append(horiz_offset) else: # Block is a numpy matrix or # scipy CSC sparse matrix. if not intf.is_sparse(block): block = intf.DEFAULT_SPARSE_INTERFACE.const_to_matrix( block) block = block.tocoo() V.extend(block.data) I.extend(block.row + vert_start) J.extend(block.col + horiz_offset)
def test_get_coefficients(self): """Test the get_coefficients function. """ size = (5, 4) # Eye x = create_var(size) coeffs = get_coefficients(x) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(id_, x.data) self.assertItemsAlmostEqual(mat.todense(), sp.eye(20).todense()) # Eye with scalar mult. x = create_var(size) A = create_const(5, (1, 1)) coeffs = get_coefficients(mul_expr(A, x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertItemsAlmostEqual(mat.todense(), 5*sp.eye(20).todense()) # Promoted x = create_var((1, 1)) coeffs = get_coefficients(promote(x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (20, 1)) self.assertItemsAlmostEqual(mat, np.ones((20, 1))) # Normal size = (5, 5) x = create_var((5, 1)) A = create_const(np.ones(size), size) coeffs = get_coefficients(mul_expr(A, x, (5, 1))) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (5, 5)) self.assertItemsAlmostEqual(mat.todense(), A.data) # Blocks size = (5, 5) x = create_var(size) A = create_const(np.ones(size), size) coeffs = get_coefficients(mul_expr(A, x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (25, 25)) self.assertItemsAlmostEqual(mat.todense(), sp.block_diag(5*[np.ones(size)]).todense()) # Scalar constant size = (1, 1) A = create_const(5, size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(intf.size(mat), (1, 1)) self.assertEqual(mat, 5) # Dense constant size = (5, 4) A = create_const(np.ones(size), size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0]*size[1], 1)) self.assertItemsAlmostEqual(mat, np.ones(size)) # Sparse constant size = (5, 5) A = create_const(sp.eye(5), size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0]*size[1], 1)) self.assertItemsAlmostEqual(mat, sp.eye(5).todense()) # Parameter size = (5, 4) param = Parameter(*size) param.value = np.ones(size) A = create_param(param, size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0]*size[1], 1)) self.assertItemsAlmostEqual(mat, param.value)
def init_dcp_attr(self): shape = u.Shape(*intf.size(self.value)) sign = intf.sign(self.value) self._dcp_attr = u.DCPAttr(sign, u.Curvature.CONSTANT, shape)
def test_get_coefficients(self): """Test the get_coefficients function. """ size = (5, 4) # Eye x = create_var(size) coeffs = get_coefficients(x) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(id_, x.data) self.assertItemsAlmostEqual(mat.todense(), sp.eye(20).todense()) # Eye with scalar mult. x = create_var(size) A = create_const(5, (1, 1)) coeffs = get_coefficients(mul_expr(A, x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertItemsAlmostEqual(mat.todense(), 5 * sp.eye(20).todense()) # Promoted x = create_var((1, 1)) coeffs = get_coefficients(promote(x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (20, 1)) self.assertItemsAlmostEqual(mat, np.ones((20, 1))) # Normal size = (5, 5) x = create_var((5, 1)) A = create_const(np.ones(size), size) coeffs = get_coefficients(mul_expr(A, x, (5, 1))) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (5, 5)) self.assertItemsAlmostEqual(mat.todense(), A.data) # Blocks size = (5, 5) x = create_var(size) A = create_const(np.ones(size), size) coeffs = get_coefficients(mul_expr(A, x, size)) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (25, 25)) self.assertItemsAlmostEqual( mat.todense(), sp.block_diag(5 * [np.ones(size)]).todense()) # Scalar constant size = (1, 1) A = create_const(5, size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(intf.size(mat), (1, 1)) self.assertEqual(mat, 5) # Dense constant size = (5, 4) A = create_const(np.ones(size), size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0] * size[1], 1)) self.assertItemsAlmostEqual(mat, np.ones(size)) # Sparse constant size = (5, 5) A = create_const(sp.eye(5), size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0] * size[1], 1)) self.assertItemsAlmostEqual(mat, sp.eye(5).todense()) # Parameter size = (5, 4) param = Parameter(*size) param.value = np.ones(size) A = create_param(param, size) coeffs = get_coefficients(A) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (size[0] * size[1], 1)) self.assertItemsAlmostEqual(mat, param.value)
def validate_matrix(self, matrix): if self.size != intf.size(matrix): raise Exception(("The argument's dimensions must match " "the variable's dimensions."))
def test_index(self): """Test the get_coefficients function for index. """ size = (5, 4) # Eye key = (slice(0, 2, None), slice(0, 2, None)) x = create_var(size) expr = index(x, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(id_, x.data) self.assertEqual(mat.shape, (4, 20)) test_mat = np.mat(range(20)).T self.assertItemsAlmostEqual((mat * test_mat).reshape((2, 2), order='F'), test_mat.reshape(size, order='F')[key]) # Eye with scalar mult. key = (slice(0, 2, None), slice(0, 2, None)) x = create_var(size) A = create_const(5, (1, 1)) expr = mul_expr(A, x, size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] test_mat = np.mat(range(20)).T self.assertItemsAlmostEqual((mat * test_mat).reshape( (2, 2), order='F'), 5 * test_mat.reshape(size, order='F')[key]) # Promoted key = (slice(0, 2, None), slice(0, 2, None)) x = create_var((1, 1)) value = np.array(range(20)).reshape(size) A = create_const(value, size) prom_x = promote(x, (size[1], 1)) expr = mul_expr(A, diag_vec(prom_x), size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (4, 1)) self.assertItemsAlmostEqual(mat, value[key]) # Normal size = (5, 5) key = (slice(0, 2, None), slice(0, 1, None)) x = create_var((5, 1)) A = create_const(np.ones(size), size) expr = mul_expr(A, x, (5, 1)) expr = index(expr, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 5)) self.assertItemsAlmostEqual(mat.todense(), A.data[slice(0, 2, None)]) # Blocks size = (5, 5) key = (slice(0, 2, None), slice(0, 2, None)) x = create_var(size) value = np.array(range(25)).reshape(size) A = create_const(value, size) expr = mul_expr(A, x, size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (4, 25)) test_mat = np.mat(range(25)).T self.assertItemsAlmostEqual( (mat * test_mat).reshape((2, 2), order='F'), (A.data * test_mat.reshape(size, order='F'))[key]) # Scalar constant size = (1, 1) A = create_const(5, size) key = (slice(0, 1, None), slice(0, 1, None)) expr = index(A, (1, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(intf.size(mat), (1, 1)) self.assertEqual(mat, 5) # Dense constant size = (5, 4) key = (slice(0, 2, None), slice(0, 1, None)) value = np.array(range(20)).reshape(size) A = create_const(value, size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, value[key]) # Sparse constant size = (5, 5) key = (slice(0, 2, None), slice(0, 1, None)) A = create_const(sp.eye(5), size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, sp.eye(5).todense()[key]) # Parameter size = (5, 4) key = (slice(0, 2, None), slice(0, 1, None)) param = Parameter(*size) value = np.array(range(20)).reshape(size) param.value = value A = create_param(param, size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, param.value[key])
def _constr_matrix(self, constraints, var_offsets, x_length, matrix_intf, vec_intf): """Returns a matrix and vector representing a list of constraints. In the matrix, each constraint is given a block of rows. Each variable coefficient is inserted as a block with upper left corner at matrix[variable offset, constraint offset]. The constant term in the constraint is added to the vector. Parameters ---------- constraints : list A list of constraints. var_offsets : dict A dict of variable id to horizontal offset. x_length : int The length of the x vector. matrix_intf : interface The matrix interface to use for creating the constraints matrix. vec_intf : interface The matrix interface to use for creating the constant vector. Returns ------- tuple A (matrix, vector) tuple. """ rows = sum([c.size[0] * c.size[1] for c in constraints]) cols = x_length V, I, J = [], [], [] const_vec = vec_intf.zeros(rows, 1) vert_offset = 0 for constr in constraints: coeffs = op2mat.get_coefficients(constr.expr) for id_, size, block in coeffs: vert_start = vert_offset vert_end = vert_start + constr.size[0] * constr.size[1] if id_ is lo.CONSTANT_ID: # Flatten the block. block = self._DENSE_INTF.const_to_matrix(block) block_size = intf.size(block) block = self._DENSE_INTF.reshape( block, (block_size[0] * block_size[1], 1)) const_vec[vert_start:vert_end, :] += block else: horiz_offset = var_offsets[id_] if intf.is_scalar(block): block = intf.scalar_value(block) V.append(block) I.append(vert_start) J.append(horiz_offset) else: # Block is a numpy matrix or # scipy CSC sparse matrix. if not intf.is_sparse(block): block = self._SPARSE_INTF.const_to_matrix(block) block = block.tocoo() V.extend(block.data) I.extend(block.row + vert_start) J.extend(block.col + horiz_offset) vert_offset += constr.size[0] * constr.size[1] # Create the constraints matrix. if len(V) > 0: matrix = sp.coo_matrix((V, (I, J)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = matrix_intf.zeros(rows, cols) return (matrix, -const_vec)
def test_index(self): """Test the get_coefficients function for index. """ size = (5, 4) # Eye key = (slice(0,2,None), slice(0,2,None)) x = create_var(size) expr = index(x, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(id_, x.data) self.assertEqual(mat.shape, (4, 20)) test_mat = np.mat(range(20)).T self.assertItemsAlmostEqual((mat*test_mat).reshape((2, 2), order='F'), test_mat.reshape(size, order='F')[key]) # Eye with scalar mult. key = (slice(0,2,None), slice(0,2,None)) x = create_var(size) A = create_const(5, (1, 1)) expr = mul_expr(A, x, size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] test_mat = np.mat(range(20)).T self.assertItemsAlmostEqual((mat*test_mat).reshape((2, 2), order='F'), 5*test_mat.reshape(size, order='F')[key]) # Promoted key = (slice(0,2,None), slice(0,2,None)) x = create_var((1, 1)) value = np.array(range(20)).reshape(size) A = create_const(value, size) prom_x = promote(x, (size[1], 1)) expr = mul_expr(A, diag_vec(prom_x), size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (4, 1)) self.assertItemsAlmostEqual(mat, value[key]) # Normal size = (5, 5) key = (slice(0,2,None), slice(0,1,None)) x = create_var((5, 1)) A = create_const(np.ones(size), size) expr = mul_expr(A, x, (5, 1)) expr = index(expr, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 5)) self.assertItemsAlmostEqual(mat.todense(), A.data[slice(0,2,None)]) # Blocks size = (5, 5) key = (slice(0,2,None), slice(0,2,None)) x = create_var(size) value = np.array(range(25)).reshape(size) A = create_const(value, size) expr = mul_expr(A, x, size) expr = index(expr, (2, 2), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (4, 25)) test_mat = np.mat(range(25)).T self.assertItemsAlmostEqual((mat*test_mat).reshape((2, 2), order='F'), (A.data*test_mat.reshape(size, order='F'))[key]) # Scalar constant size = (1, 1) A = create_const(5, size) key = (slice(0,1,None), slice(0,1,None)) expr = index(A, (1, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(intf.size(mat), (1, 1)) self.assertEqual(mat, 5) # Dense constant size = (5, 4) key = (slice(0,2,None), slice(0,1,None)) value = np.array(range(20)).reshape(size) A = create_const(value, size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, value[key]) # Sparse constant size = (5, 5) key = (slice(0,2,None), slice(0,1,None)) A = create_const(sp.eye(5), size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, sp.eye(5).todense()[key]) # Parameter size = (5, 4) key = (slice(0,2,None), slice(0,1,None)) param = Parameter(*size) value = np.array(range(20)).reshape(size) param.value = value A = create_param(param, size) expr = index(A, (2, 1), key) coeffs = get_coefficients(expr) assert len(coeffs) == 1 id_, mat = coeffs[0] self.assertEqual(mat.shape, (2, 1)) self.assertItemsAlmostEqual(mat, param.value[key])
def _constr_matrix(self, constraints, var_offsets, x_length, matrix_intf, vec_intf): """Returns a matrix and vector representing a list of constraints. In the matrix, each constraint is given a block of rows. Each variable coefficient is inserted as a block with upper left corner at matrix[variable offset, constraint offset]. The constant term in the constraint is added to the vector. Parameters ---------- constraints : list A list of constraints. var_offsets : dict A dict of variable id to horizontal offset. x_length : int The length of the x vector. matrix_intf : interface The matrix interface to use for creating the constraints matrix. vec_intf : interface The matrix interface to use for creating the constant vector. Returns ------- tuple A (matrix, vector) tuple. """ rows = sum([c.size[0] * c.size[1] for c in constraints]) cols = x_length V, I, J = [], [], [] const_vec = vec_intf.zeros(rows, 1) vert_offset = 0 for constr in constraints: coeffs = op2mat.get_coefficients(constr.expr) for id_, block in coeffs: vert_start = vert_offset vert_end = vert_start + constr.size[0]*constr.size[1] if id_ is lo.CONSTANT_ID: # Flatten the block. block = self._DENSE_INTF.const_to_matrix(block) block_size = intf.size(block) block = self._DENSE_INTF.reshape( block, (block_size[0]*block_size[1], 1) ) const_vec[vert_start:vert_end, :] += block else: horiz_offset = var_offsets[id_] if intf.is_scalar(block): block = intf.scalar_value(block) V.append(block) I.append(vert_start) J.append(horiz_offset) else: # Block is a numpy matrix or # scipy CSC sparse matrix. if not intf.is_sparse(block): block = self._SPARSE_INTF.const_to_matrix(block) block = block.tocoo() V.extend(block.data) I.extend(block.row + vert_start) J.extend(block.col + horiz_offset) vert_offset += constr.size[0]*constr.size[1] # Create the constraints matrix. if len(V) > 0: matrix = sp.coo_matrix((V, (I, J)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = matrix_intf.zeros(rows, cols) return (matrix, -const_vec)