def conv_helper(kernel, size): """Returns the column convolution matrix for a given vector. Parameters ---------- NumPy 1D array : kernel The convolution kernel. size : tuple The dimension of the final matrix. Returns ------- NumPy matrix The matrix representing the convolution operation. """ kernel = intf.from_2D_to_1D(kernel) # Create a Toeplitz matrix with kernel as columns. rows = size[0] nonzeros = kernel.size toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = kernel cols = size[1] toeplitz_row = np.zeros(cols) toeplitz_row[0] = kernel[0] return np.matrix(sp_la.toeplitz(toeplitz_col, toeplitz_row))
def conv_mat(lin_op): """Returns the coefficient matrix for CONV linear op. Parameters ---------- lin_op : LinOp The conv linear op. Returns ------- list of NumPy matrix The matrix representing the convolution operation. """ constant = const_mat(lin_op.data) # Cast to 1D. constant = intf.from_2D_to_1D(constant) # Create a Toeplitz matrix with constant as columns. rows = lin_op.size[0] nonzeros = lin_op.data.size[0] toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = constant cols = lin_op.args[0].size[0] toeplitz_row = np.zeros(cols) toeplitz_row[0] = constant[0] coeff = sp_la.toeplitz(toeplitz_col, toeplitz_row) return [np.matrix(coeff)]
def conv_mat(lin_op): """Returns the coefficient matrix for CONV linear op. Parameters ---------- lin_op : LinOp The conv linear op. Returns ------- SciPy CSC matrix The matrix representing the convolution operation. """ constant = const_mat(lin_op.data) # Cast to 1D. constant = intf.from_2D_to_1D(constant) # Create a Toeplitz matrix with constant as columns. rows = lin_op.size[0] nonzeros = lin_op.data.size[0] toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = constant cols = lin_op.args[0].size[0] toeplitz_row = np.zeros(cols) toeplitz_row[0] = constant[0] coeff = sp_la.toeplitz(toeplitz_col, toeplitz_row) return coeff
def _cache_to_matrix(self, mat_cache): """Converts the cached representation of the constraints matrix. Parameters ---------- mat_cache : MatrixCache The cached version of the matrix-vector pair. Returns ------- A (matrix, vector) tuple. """ # Get parameter values. param_cache = self._init_matrix_cache(mat_cache.constraints, mat_cache.size[0]) self._lin_matrix(param_cache) rows, cols = mat_cache.size # Create the constraints matrix. # Combine the cached data with the parameter data. V, I, J = mat_cache.coo_tup Vp, Ip, Jp = param_cache.coo_tup if len(V) + len(Vp) > 0: matrix = sp.coo_matrix((V + Vp, (I + Ip, J + Jp)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = self.matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = self.matrix_intf.zeros(rows, cols) # Convert 2D ND arrays to 1D combo_vec = mat_cache.const_vec + param_cache.const_vec const_vec = intf.from_2D_to_1D(combo_vec) return (matrix, -const_vec)
def conv_coeffs(lin_op): """Returns the coefficients for CONV linear op. Parameters ---------- lin_op : LinOp The conv linear op. Returns ------- list A list of (id, size, coefficient) tuples. """ lh_coeffs = get_coefficients(lin_op.data) constant = merge_constants(lh_coeffs) # Cast to 1D. constant = intf.from_2D_to_1D(constant) rh_coeffs = get_coefficients(lin_op.args[0]) # Create a Toeplitz matrix with constant as columns. rows = lin_op.size[0] nonzeros = lin_op.data.size[0] toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = constant cols = lin_op.args[0].size[0] toeplitz_row = np.zeros(cols) toeplitz_row[0] = constant[0] coeff = sp_la.toeplitz(toeplitz_col, toeplitz_row) # Multiply the right hand terms by the toeplitz matrix. return mul_by_const(coeff, rh_coeffs, (rows, 1))
def mul_elemwise_coeffs(lin_op): """Returns the coefficients for MUL_ELEM linear op. Parameters ---------- lin_op : LinOp The mul_elem linear op. Returns ------- list A list of (id, size, coefficient) tuples. """ lh_coeffs = get_coefficients(lin_op.data) constant = merge_constants(lh_coeffs) # Convert the constant to a giant diagonal matrix. vectorized = intf.from_2D_to_1D(flatten(constant)) constant = sp.diags(vectorized, 0) rh_coeffs = get_coefficients(lin_op.args[0]) new_coeffs = [] # Multiply left-hand constant by right-hand terms. for (id_, rh_size, coeff) in rh_coeffs: new_coeffs.append((id_, rh_size, constant * coeff)) return new_coeffs
def conv_helper(kernel, size): """Returns the column convolution matrix for a given vector. Parameters ---------- NumPy 1D array : kernel The convolution kernel. size : tuple The dimension of the final matrix. Returns ------- NumPy matrix The matrix representing the convolution operation. """ kernel = intf.from_2D_to_1D(kernel) # Create a Toeplitz matrix with kernel as columns. rows = size[0] nonzeros = kernel.size toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = kernel cols = size[1] toeplitz_row = np.zeros(cols) toeplitz_row[0] = kernel[0] return np.matrix(sp_la.toeplitz(toeplitz_col, toeplitz_row))
def conv_mat(lin_op): """Returns the coefficient matrix for CONV linear op. Parameters ---------- lin_op : LinOp The conv linear op. Returns ------- list of NumPy matrices The matrix representing the convolution operation. """ constant = const_mat(lin_op.data) # Cast to 1D. constant = intf.from_2D_to_1D(constant) if isinstance(constant, sym.SymMatrix): raise TypeError('Convolution of parameters and variables not currently supported') # TODO # Create a Toeplitz matrix with constant as columns. rows = lin_op.size[0] nonzeros = lin_op.data.size[0] toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = constant cols = lin_op.args[0].size[0] toeplitz_row = np.zeros(cols) toeplitz_row[0] = constant[0] coeff = sp_la.toeplitz(toeplitz_col, toeplitz_row) return [np.matrix(coeff)]
def conv_coeffs(lin_op): """Returns the coefficients for CONV linear op. Parameters ---------- lin_op : LinOp The conv linear op. Returns ------- list A list of (id, size, coefficient) tuples. """ lh_coeffs = get_coefficients(lin_op.data) constant = merge_constants(lh_coeffs) # Cast to 1D. constant = intf.from_2D_to_1D(constant) rh_coeffs = get_coefficients(lin_op.args[0]) # Create a Toeplitz matrix with constant as columns. rows = lin_op.size[0] nonzeros = lin_op.data.size[0] toeplitz_col = np.zeros(rows) toeplitz_col[0:nonzeros] = constant cols = lin_op.args[0].size[0] toeplitz_row = np.zeros(cols) toeplitz_row[0] = constant[0] coeff = sp_la.toeplitz(toeplitz_col, toeplitz_row) # Multiply the right hand terms by the toeplitz matrix. return mul_by_const(coeff, rh_coeffs, (rows, 1))
def _cache_to_matrix(self, mat_cache): """Converts the cached representation of the constraints matrix. Parameters ---------- mat_cache : MatrixCache The cached version of the matrix-vector pair. Returns ------- A (matrix, vector) tuple. """ rows, cols = mat_cache.size # Create the constraints matrix. V, I, J = mat_cache.coo_tup if len(V) > 0: matrix = sp.coo_matrix((V, (I, J)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = self.matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = self.matrix_intf.zeros(rows, cols) # Convert 2D ND arrays to 1D const_vec = intf.from_2D_to_1D(mat_cache.const_vec) return (matrix, -const_vec)
def _cache_to_matrix(self, mat_cache): """Converts the cached representation of the constraints matrix. Parameters ---------- mat_cache : MatrixCache The cached version of the matrix-vector pair. Returns ------- A (matrix, vector) tuple. """ # Get parameter values. param_cache = self._init_matrix_cache(mat_cache.constraints, mat_cache.size[0]) self._lin_matrix(param_cache) rows, cols = mat_cache.size # Create the constraints matrix. # Combine the cached data with the parameter data. V, I, J = mat_cache.coo_tup Vp, Ip, Jp = param_cache.coo_tup if len(V) + len(Vp) > 0: matrix = sp.coo_matrix((V + Vp, (I + Ip, J + Jp)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = self.matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = self.matrix_intf.zeros(rows, cols) # Convert 2D ND arrays to 1D combo_vec = mat_cache.const_vec + param_cache.const_vec const_vec = intf.from_2D_to_1D(combo_vec) return (matrix, -const_vec)
def _cache_to_matrix(self, mat_cache): """Converts the cached representation of the constraints matrix. Parameters ---------- mat_cache : MatrixCache The cached version of the matrix-vector pair. Returns ------- A (matrix, vector) tuple. """ rows, cols = mat_cache.size # Create the constraints matrix. V, I, J = mat_cache.coo_tup if len(V) > 0: matrix = sp.coo_matrix((V, (I, J)), (rows, cols)) # Convert the constraints matrix to the correct type. matrix = self.matrix_intf.const_to_matrix(matrix, convert_scalars=True) else: # Empty matrix. matrix = self.matrix_intf.zeros(rows, cols) # Convert 2D ND arrays to 1D const_vec = intf.from_2D_to_1D(mat_cache.const_vec) return (matrix, -const_vec)
def op_mul(lin_op, args): """Applies the linear operator to the arguments. Parameters ---------- lin_op : LinOp A linear operator. args : list The arguments to the operator. Returns ------- NumPy matrix or SciPy sparse matrix. The result of applying the linear operator. """ # Constants convert directly to their value. if lin_op.type in [lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]: result = lin_op.data elif lin_op.type is lo.PARAM: result = lin_op.data.value # No-op is not evaluated. elif lin_op.type is lo.NO_OP: return None # For non-leaves, recurse on args. elif lin_op.type is lo.SUM: result = sum(args) elif lin_op.type is lo.NEG: result = -args[0] elif lin_op.type is lo.MUL: coeff = mul(lin_op.data, {}) result = coeff*args[0] elif lin_op.type is lo.RMUL: coeff = mul(lin_op.data, {}) result = args[0]*coeff elif lin_op.type is lo.MUL_ELEM: coeff = mul(lin_op.data, {}) result = np.multiply(args[0], coeff) elif lin_op.type is lo.DIV: divisor = mul(lin_op.data, {}) result = args[0]/divisor elif lin_op.type is lo.SUM_ENTRIES: result = np.sum(args[0]) elif lin_op.type is lo.INDEX: row_slc, col_slc = lin_op.data result = args[0][row_slc, col_slc] elif lin_op.type is lo.TRANSPOSE: result = args[0].T elif lin_op.type is lo.CONV: result = conv_mul(lin_op, args[0]) elif lin_op.type is lo.PROMOTE: result = np.ones(lin_op.size)*args[0] elif lin_op.type is lo.DIAG_VEC: val = intf.from_2D_to_1D(args[0]) result = np.diag(val) elif lin_op.type is lo.RESHAPE: result = np.reshape(args[0], lin_op.size, order='F') else: raise Exception("Unknown linear operator.") return result
def get_objective(self): """Returns the linear objective and a scalar offset. """ c, offset = self._cache_to_matrix(self.obj_cache) c = self.vec_intf.const_to_matrix(c.T, convert_scalars=True) c = intf.from_2D_to_1D(c) offset = self.vec_intf.scalar_value(offset) # Negate offset because was negated before. return c, -offset
def get_objective(self): """Returns the linear objective and a scalar offset. """ c, offset = self._cache_to_matrix(self.obj_cache) c = self.vec_intf.const_to_matrix(c.T, convert_scalars=True) c = intf.from_2D_to_1D(c) offset = self.vec_intf.scalar_value(offset) # Negate offset because was negated before. return c, -offset
def op_mul(lin_op, args): """Applies the linear operator to the arguments. Parameters ---------- lin_op : LinOp A linear operator. args : list The arguments to the operator. Returns ------- NumPy matrix or SciPy sparse matrix. The result of applying the linear operator. """ #print lin_op.type # Constants convert directly to their value. if lin_op.type in [lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]: result = lin_op.data # No-op is not evaluated. elif lin_op.type is lo.NO_OP: return None # For non-leaves, recurse on args. elif lin_op.type is lo.SUM: result = sum(args) elif lin_op.type is lo.NEG: result = -args[0] elif lin_op.type is lo.MUL: coeff = mul(lin_op.data, {}) result = coeff * args[0] elif lin_op.type is lo.DIV: divisor = mul(lin_op.data, {}) result = args[0] / divisor elif lin_op.type is lo.SUM_ENTRIES: result = np.sum(args[0]) elif lin_op.type is lo.INDEX: row_slc, col_slc = lin_op.data result = args[0][row_slc, col_slc] elif lin_op.type is lo.TRANSPOSE: result = args[0].T elif lin_op.type is lo.CONV: result = conv_mul(lin_op, args[0]) elif lin_op.type is lo.PROMOTE: result = np.ones(lin_op.size) * args[0] elif lin_op.type is lo.DIAG_VEC: val = intf.from_2D_to_1D(args[0]) result = np.diag(val) else: raise Exception("Unknown linear operator.") #print result return result
def mul_elemwise_mat(lin_op): """Returns the coefficient matrix for MUL_ELEM linear op. Parameters ---------- lin_op : LinOp The mul_elem linear op. Returns ------- SciPy CSC matrix The matrix representing the mul_elemwise operation. """ constant = const_mat(lin_op.data) # Convert the constant to a giant diagonal matrix. vectorized = intf.from_2D_to_1D(flatten(constant)) return sp.diags(vectorized, 0).tocsc()
def _grad(self, values): """Gives the (sub/super)gradient of the atom w.r.t. each argument. Matrix expressions are vectorized, so the gradient is a matrix. Args: values: A list of numeric values for the arguments. Returns: A list of SciPy CSC sparse matrices or None. """ # Grad: 1 for each of k largest indices. value = intf.from_2D_to_1D(values[0].flatten().T) indices = np.argsort(-value)[:int(self.k)] D = np.zeros((self.args[0].size[0]*self.args[0].size[1], 1)) D[indices] = 1 return [sp.csc_matrix(D)]
def _grad(self, values): """Gives the (sub/super)gradient of the atom w.r.t. each argument. Matrix expressions are vectorized, so the gradient is a matrix. Args: values: A list of numeric values for the arguments. Returns: A list of SciPy CSC sparse matrices or None. """ # Grad: 1 for each of k largest indices. value = intf.from_2D_to_1D(values[0].flatten().T) indices = np.argsort(-value)[:int(self.k)] D = np.zeros((self.args[0].shape[0]*self.args[0].shape[1], 1)) D[indices] = 1 return [sp.csc_matrix(D)]
def mul_elemwise_mat(lin_op): """Returns the coefficient matrix for MUL_ELEM linear op. Parameters ---------- lin_op : LinOp The mul_elem linear op. Returns ------- list of SciPy CSC matrix The matrix representing the mul_elemwise operation. """ constant = const_mat(lin_op.data) # Convert the constant to a giant diagonal matrix. vectorized = intf.from_2D_to_1D(flatten(constant)) return [sp.diags(vectorized, 0).tocsc()]
def numeric(self, values): """Returns the sum of the k largest entries of the matrix. """ value = intf.from_2D_to_1D(values[0].flatten().T) indices = np.argsort(-value)[:int(self.k)] return value[indices].sum()
def numeric(self, values): """Returns the sum of the k largest entries of the matrix. """ value = intf.from_2D_to_1D(values[0].flatten().T) indices = np.argsort(-value)[:int(self.k)] return value[indices].sum()
def numeric(self, values): """Convert the vector constant into a diagonal matrix. """ # Convert values to 1D. value = intf.from_2D_to_1D(values[0]) return np.diag(value)