def rmul_mat(lin_op): """Returns the coefficient matrix for RMUL linear op. Parameters ---------- lin_op : LinOp The rmul linear op. Returns ------- list of SciPy CSC matrix or scalar. The matrix for the multiplication on the right operator. """ constant = const_mat(lin_op.data) if isinstance(constant, sym.SymMatrix): sym_eye = sym.as_sym_matrix(sp.csc_matrix(sp.eye(lin_op.size[0]))) constant = sym.kron(sym.transpose(constant), sym_eye) else: # Scalars don't need to be replicated. if not intf.is_scalar(constant): # Matrix is the kronecker product of constant.T and identity. # Each column in the product is a linear combination of the # columns of the left hand multiple. constant = sp.kron(constant.T, sp.eye(lin_op.size[0])).tocsc() return [constant]
def mul_by_const(constant, rh_coeffs, size): """Multiplies a constant by a list of coefficients. Parameters ---------- constant : numeric type The constant to multiply by. rh_coeffs : list The coefficients of the right hand side. size : tuple (product rows, product columns) Returns ------- list A list of (id, size, coefficient) tuples. """ new_coeffs = [] rep_mat = sp.block_diag(size[1] * [constant]).tocsc() # Multiply all left-hand constants by right-hand terms. for (id_, rh_size, coeff) in rh_coeffs: # For scalar left hand constants, # if right hand term is constant, # or single column, just multiply. # Keeps scalars and dense constants as original type. if intf.is_scalar(constant) or \ id_ is lo.CONSTANT_ID or size[1] == 1: product = constant * coeff # For promoted variables with matrix coefficients, # flatten the matrix. elif size != (1, 1) and intf.is_scalar(coeff): flattened_const = flatten(constant) product = flattened_const * coeff # Otherwise replicate the matrix. else: product = rep_mat * coeff new_coeffs.append((id_, rh_size, product)) rh_coeffs = new_coeffs return new_coeffs
def mul_by_const(constant, rh_coeffs, size): """Multiplies a constant by a list of coefficients. Parameters ---------- constant : numeric type The constant to multiply by. rh_coeffs : list The coefficients of the right hand side. size : tuple (product rows, product columns) Returns ------- list A list of (id, size, coefficient) tuples. """ new_coeffs = [] # Multiply all left-hand constants by right-hand terms. for (id_, rh_size, coeff) in rh_coeffs: rep_mat = sp.block_diag(size[1] * [constant]).tocsc() # For scalar right hand constants # or single column, just multiply. if intf.is_scalar(constant) or id_ is lo.CONSTANT_ID or size[1] == 1: product = constant * coeff # For promoted variables with matrix coefficients, # flatten the matrix. elif size != (1, 1) and intf.is_scalar(coeff): flattened_const = flatten(constant) product = flattened_const * coeff # Otherwise replicate the matrix. else: product = rep_mat * coeff new_coeffs.append((id_, rh_size, product)) rh_coeffs = new_coeffs return new_coeffs
def mul_mat(lin_op): """Returns the coefficient matrix for MUL linear op. Parameters ---------- lin_op : LinOp The mul linear op. Returns ------- SciPy CSC matrix or scalar. The matrix for the multiplication on the left operator. """ constant = const_mat(lin_op.data) # Scalars don't need to be replicated. if not intf.is_scalar(constant): constant = sp.block_diag(lin_op.size[1] * [constant]).tocsc() return constant
def mul_mat(lin_op): """Returns the coefficient matrix for MUL linear op. Parameters ---------- lin_op : LinOp The mul linear op. Returns ------- list of SciPy CSC matrix or scalar. The matrix for the multiplication on the left operator. """ constant = const_mat(lin_op.data) # Scalars don't need to be replicated. if not intf.is_scalar(constant): constant = sp.block_diag(lin_op.size[1]*[constant]).tocsc() return [constant]
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 _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 rmul_mat(lin_op): """Returns the coefficient matrix for RMUL linear op. Parameters ---------- lin_op : LinOp The rmul linear op. Returns ------- list of SciPy CSC matrix or scalar. The matrix for the multiplication on the right operator. """ constant = const_mat(lin_op.data) # Scalars don't need to be replicated. if not intf.is_scalar(constant): # Matrix is the kronecker product of constant.T and identity. # Each column in the product is a linear combination of the # columns of the left hand multiple. constant = sp.kron(constant.T, sp.eye(lin_op.size[0])).tocsc() return [constant]
def mul_mat(lin_op): """Returns the coefficient matrix for MUL linear op. Parameters ---------- lin_op : LinOp The mul linear op. Returns ------- list of SciPy CSC matrix or scalar. The matrix for the multiplication on the left operator. """ constant = const_mat(lin_op.data) #constant = sym.as_sym_matrix(const_mat(lin_op.data)) if isinstance(constant, sym.SymMatrix): if constant.shape != (1,1): constant = sym.block_diag(lin_op.size[1]*[constant]) else: # Scalars don't need to be replicated.268 if not intf.is_scalar(constant): constant = sp.block_diag(lin_op.size[1]*[constant]).tocsc() return [constant]
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)
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)