def vstack(seq): """ | Stacks objects vertically. :param seq: tuple or list of numbers, :ref:`scalar objects<scalar_ref>` or :ref:`multidimensional objects<multi_ref>`. :return: :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. """ # Check input if (type(seq) is not tuple and type(seq) is not list): raise TypeError('Invalid argument') # Process input new_list = [] numeric = True for x in seq: if np.isscalar(x): new_list += [matrix(x)] elif type(x) is cvxpy_obj: new_list += [matrix(x.value)] elif type(x).__name__ in SCALAR_OBJS: numeric = False new_x = cvxpy_array(1, 1) new_x[0, 0] = x new_list += [new_x] elif type(x).__name__ in ARRAY_OBJS: numeric = False new_list += [x] elif type(x) is cvxpy_matrix: new_list += [x] else: raise TypeError('Invalid Input') # Input is numeric if numeric: return np.vstack(new_list) # Verify dimensions n = new_list[0].shape[1] for x in new_list: if x.shape[1] != n: raise ValueError('Invalid Dimensions') # Allocate new array m = int(np.sum([x.shape[0] for x in new_list])) new_ar = cvxpy_array(m, n) # Fill new array k = 0 for x in new_list: for i in range(0, x.shape[0], 1): for j in range(0, x.shape[1], 1): new_ar[i + k, j] = x[i, j] k = k + x.shape[0] # Return new array return new_ar
def diag(v): """ | Extracts diagonal or constructs a diagonal array. :param v: number, :ref:`scalar object<scalar_ref>`, square or one dimensional :ref:`multidimensional object<multi_ref>`. :return: number, :ref:`scalar object<scalar_ref>` or :ref:`multidimensional object<multi_ref>`. """ # Check input if (np.isscalar(v) or type(v).__name__ in SCALAR_OBJS): return v elif (type(v) is cvxpy_matrix or type(v).__name__ in ARRAY_OBJS): if v.shape[1]==1: v = v.T else: raise TypeError('Invalid argument type') # Get shape (m,n) = v.shape # Input is 2D if m!=1 and n!=1: # Must be square if m!=n: raise ValueError('Invalid dimensions') # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.diag(v)).T # Object array else: new_ar = cvxpy_array(m,1) for i in range(0,m,1): new_ar[i,0] = v[i,i] return new_ar # Input is 1D else: # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.diagflat(v)) # Object array else: new_ar = cvxpy_array(n,n) for i in range(0,n,1): new_ar[i,i] = v[0,i] return new_ar
def diag(v): """ | Extracts diagonal or constructs a diagonal array. :param v: number, :ref:`scalar object<scalar_ref>`, square or one dimensional :ref:`multidimensional object<multi_ref>`. :return: number, :ref:`scalar object<scalar_ref>` or :ref:`multidimensional object<multi_ref>`. """ # Check input if (np.isscalar(v) or type(v).__name__ in SCALAR_OBJS): return v elif (type(v) is cvxpy_matrix or type(v).__name__ in ARRAY_OBJS): if v.shape[1] == 1: v = v.T else: raise TypeError('Invalid argument type') # Get shape (m, n) = v.shape # Input is 2D if m != 1 and n != 1: # Must be square if m != n: raise ValueError('Invalid dimensions') # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.diag(v)).T # Object array else: new_ar = cvxpy_array(m, 1) for i in range(0, m, 1): new_ar[i, 0] = v[i, i] return new_ar # Input is 1D else: # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.diagflat(v)) # Object array else: new_ar = cvxpy_array(n, n) for i in range(0, n, 1): new_ar[i, i] = v[0, i] return new_ar
def vstack(t): """ Vertical stack. """ # Verify input type new_list = [] numeric = True for x in t: if(np.isscalar(x)): new_list += [matrix(x)] elif(type(x) is cvxpy_obj): new_list += [matrix(x.data)] elif(type(x).__name__ in SCALAR_OBJS): numeric = False new_x = cvxpy_expression(1,1) new_x[0,0] = x new_list += [new_x] elif(type(x).__name__ in ARRAY_OBJS): numeric = False new_list += [x] elif(type(x) is cvxpy_matrix): new_list += [x] else: raise ValueError('Invalid Input') # Input is numeric if(numeric): return np.vstack(new_list) # Verify dimensions n = new_list[0].shape[1] for x in new_list: if(x.shape[1] != n): raise ValueError('Invalid Dimensions') # Allocate new expression m = 0 for x in new_list: m += x.shape[0] new_exp = cvxpy_expression(m,n) # Fill new expression k = 0 for x in new_list: for i in range(0,x.shape[0],1): for j in range(0,x.shape[1],1): new_exp[i+k,j] = x[i,j] k = k + x.shape[0] # Return new expression return new_exp
def vstack(t): """ Vertical stack. """ # Verify input type new_list = [] numeric = True for x in t: if (np.isscalar(x)): new_list += [matrix(x)] elif (type(x) is cvxpy_obj): new_list += [matrix(x.data)] elif (type(x).__name__ in SCALAR_OBJS): numeric = False new_x = cvxpy_expression(1, 1) new_x[0, 0] = x new_list += [new_x] elif (type(x).__name__ in ARRAY_OBJS): numeric = False new_list += [x] elif (type(x) is cvxpy_matrix): new_list += [x] else: raise ValueError('Invalid Input') # Input is numeric if (numeric): return np.vstack(new_list) # Verify dimensions n = new_list[0].shape[1] for x in new_list: if (x.shape[1] != n): raise ValueError('Invalid Dimensions') # Allocate new expression m = 0 for x in new_list: m += x.shape[0] new_exp = cvxpy_expression(m, n) # Fill new expression k = 0 for x in new_list: for i in range(0, x.shape[0], 1): for j in range(0, x.shape[1], 1): new_exp[i + k, j] = x[i, j] k = k + x.shape[0] # Return new expression return new_exp
def diagflat(arg): """ List, row or column vector to diagonal matrix. """ # Argument is a list if (type(arg) is list): arg = hstack(arg) # Argument is a matrix or object array elif (type(arg) is cvxpy_matrix or type(arg).__name__ in ARRAY_OBJS): (m, n) = arg.shape if (m != 1 and n != 1): raise ValueError('Argument must be one dimensional') elif (n == 1): arg = arg.T # Invalid argument else: raise ValueError('Invalid argument') # Argument is numeric numeric = True for i in range(0, arg.shape[1], 1): if (not np.isscalar(arg[0, i])): numeric = False if (numeric): return matrix(np.diagflat(arg)) # Not numeric (m, n) = arg.shape new_exp = cvxpy_expression(n, n) for i in range(0, n, 1): new_exp[i, i] = arg[0, i] return new_exp
def eye(n): """ | See **numpy.eye**. :param n: rows. :return: :ref:`matrix<matrix_obj>`. """ return matrix(np.eye(n))
def sqrtm(x): """ | See **scipy.linalg.sqrtm**. :param x: positive semidefinite matrix. :return: :ref:`matrix<matrix_obj>`. """ return matrix(np.real(sci_sqrtm(x)))
def ones(shape): """ | See **numpy.ones**. :param shape: integer or pair of integers. :return: :ref:`matrix<matrix_obj>`. """ return matrix(np.ones(shape))
def rand(m, n): """ | See **numpy.random.rand**. :param m: rows. :param n: columns. :return: :ref:`matrix<matrix_obj>`. """ return matrix(np.random.rand(m, n))
def rand(m,n): """ | See **numpy.random.rand**. :param m: rows. :param n: columns. :return: :ref:`matrix<matrix_obj>`. """ return matrix(np.random.rand(m,n))
def reshape(v, newshape): """ | Reshapes the array to dimensions newshape (see np.reshape) | in FORTRAN (column-major) order. :param v: :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. :param newshape: tuple with two integers. :return: the reshaped variable or matrix, :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. """ # Check input if (type(v) is cvxpy_matrix or type(v).__name__ in ARRAY_OBJS): pass else: raise TypeError('Invalid argument type') if not (hasattr(newshape, '__iter__') and len(newshape) == 2): raise TypeError('Invalid argument for newshape') # Get shape (m,n) = v.shape # Get new shape (mn,nn) = newshape if mn*nn != m*n: raise ValueError('Output dimension size does not match input dimension') # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.reshape(v, newshape, order='F')) # Object array else: new_ar = cvxpy_array(mn,nn) for j in range(0,n,1): for i in range(0,m,1): k = j*m + i new_ar[k % mn,k / mn] = v[i,j] return new_ar
def reshape(v, newshape): """ | Reshapes the array to dimensions newshape (see np.reshape) | in FORTRAN (column-major) order. :param v: :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. :param newshape: tuple with two integers. :return: the reshaped variable or matrix, :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. """ # Check input if (type(v) is cvxpy_matrix or type(v).__name__ in ARRAY_OBJS): pass else: raise TypeError('Invalid argument type') if not (hasattr(newshape, '__iter__') and len(newshape) == 2): raise TypeError('Invalid argument for newshape') # Get shape (m, n) = v.shape # Get new shape (mn, nn) = newshape if mn * nn != m * n: raise ValueError( 'Output dimension size does not match input dimension') # cvxpy matrix if type(v) is cvxpy_matrix: return matrix(np.reshape(v, newshape, order='F')) # Object array else: new_ar = cvxpy_array(mn, nn) for j in range(0, n, 1): for i in range(0, m, 1): k = j * m + i new_ar[k % mn, k / mn] = v[i, j] return new_ar
def diag(arg): """ Extract the diagonal from square array-like object. """ # Check size (m,n) = arg.shape if(m!=n): raise ValueError('Invalid dimensions') # cvxpy matrix if(type(arg) is cvxpy_matrix): return matrix(np.diag(arg)).T # Object array elif(type(arg).__name__ in ARRAY_OBJS): new_exp = cvxpy_expression(m,1) for i in range(0,m,1): new_exp[i,0] = arg[i,i] return new_exp # Error else: raise ValueError('Invalid argument type')
def diag(arg): """ Extract the diagonal from square array-like object. """ # Check size (m, n) = arg.shape if (m != n): raise ValueError('Invalid dimensions') # cvxpy matrix if (type(arg) is cvxpy_matrix): return matrix(np.diag(arg)).T # Object array elif (type(arg).__name__ in ARRAY_OBJS): new_exp = cvxpy_expression(m, 1) for i in range(0, m, 1): new_exp[i, 0] = arg[i, i] return new_exp # Error else: raise ValueError('Invalid argument type')
def diagflat(arg): """ List, row or column vector to diagonal matrix. """ # Argument is a list if(type(arg) is list): arg = hstack(arg) # Argument is a matrix or object array elif(type(arg) is cvxpy_matrix or type(arg).__name__ in ARRAY_OBJS): (m,n) = arg.shape if(m!=1 and n!=1): raise ValueError('Argument must be one dimensional') elif(n == 1): arg = arg.T # Invalid argument else: raise ValueError('Invalid argument') # Argument is numeric numeric = True for i in range(0,arg.shape[1],1): if(not np.isscalar(arg[0,i])): numeric = False if(numeric): return matrix(np.diagflat(arg)) # Not numeric (m,n) = arg.shape new_exp = cvxpy_expression(n,n) for i in range(0,n,1): new_exp[i,i] = arg[0,i] return new_exp
def zeros(shape): """ Matrix of zeros. """ return matrix(np.zeros(shape))
def ones(shape): """ Matrix of ones. """ return matrix(np.ones(shape))
def eye(n): return matrix(np.eye(n))
def rand(m, n): return matrix(np.random.rand(m, n))
def solve_prog(p): """ Description ----------- Solve optimization program. Arguments --------- p: cvxpy_program """ # Reset variable counter var_reset() # Check parameters if (len(p.get_params()) != 0): if (not p.options['quiet']): print 'Error: Parameters present' return np.NaN, np.NaN # Original if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Original *' print '****************************' p.show() # Expanded p_expanded = p._get_expanded() if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Expanded *' print '****************************' p_expanded.show() # Equivalent p_equivalent = p_expanded._get_equivalent() if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Equivalent *' print '****************************' p_equivalent.show() # Nonconvex constraints bad_constr = p_equivalent.constr._get_nonconvex() if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Nonconvex Constraints *' print '****************************\n' print bad_constr # Convex Relaxation p_cvx_relaxation = p_equivalent._get_cvx_relaxation() if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Convex Relaxation *' print '****************************' p_cvx_relaxation.show() # Solve convex relaxation if (not p.options['quiet']): print '\nSolving convex relaxation ...' sol = solve_convex(p_cvx_relaxation, 'rel') lagrange_mul_eq = matrix(sol['y']) if (not p.options['quiet']): print 'Relaxation status: ', sol['status'] # Relaxation status: primal infeasible if (sol['status'] == 'primal infeasible'): if (not p.options['quiet']): print 'Original program is primal infeasible' if (p.action == MINIMIZE): return np.inf, lagrange_mul_eq else: return -np.inf, lagrange_mul_eq # Relaxation status: uknown elif (sol['status'] == 'unknown'): relaxation_obj = None # Relaxation status: dual infeasible elif (sol['status'] == 'dual infeasible'): if (p.action == MINIMIZE): relaxation_obj = -np.inf else: relaxation_obj = np.inf # Relaxacion status: optimal else: relaxation_obj = p_cvx_relaxation.obj.get_value() # Report max slack if (len(bad_constr) != 0 and not p.options['quiet']): print 'Max Slack: ', print max( map(lambda x: x.get_value(), [abs(c.left - c.right) for c in bad_constr])) # Tighten if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Tightening Stage *' print '****************************' elif (not p.options['quiet']): print '\nAttempting tightening ...' valid_scp = scp(p_cvx_relaxation, bad_constr, sol) if (not valid_scp): return np.NaN, np.NaN # Prepare results if (len(bad_constr) == 0): obj = relaxation_obj else: obj = p.obj.get_value() if (p.action == MINIMIZE): bound_str = 'Lower Bound' if (relaxation_obj != None): bound = np.min([relaxation_obj, obj]) gap = np.max([obj - relaxation_obj, 0.0]) else: bound_str = 'Upper Bound' if (relaxation_obj != None): bound = np.max([relaxation_obj, obj]) gap = np.max([relaxation_obj - obj, 0.0]) # Show results if (p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Results *' print '****************************' elif (not p.options['quiet']): print '\nResults' if (not p.options['quiet']): print 'Objective =\t%.5e' % obj if (relaxation_obj != None): print bound_str + ' =\t%.5e' % bound print 'Gap =\t\t%.5e' % gap else: print bound_str + ' =\tUnknown' print 'Gap =\t\tUnknown' if (len(bad_constr) != 0): ms = max( map(lambda x: x.get_value(), [abs(c.left - c.right) for c in bad_constr])) print 'Max Slack =\t%.5e' % ms # Return objective and dual var return obj, lagrange_mul_eq
def sqrtm(A): """ Matrix square root. """ return matrix(sci_sqrtm(A))
def solve_prog(p): """ Description ----------- Solve optimization program. Arguments --------- p: cvxpy_program """ # Reset variable counter var_reset() # Check parameters if(len(p.get_params()) != 0): if(not p.options['quiet']): print 'Error: Parameters present' return np.NaN,np.NaN # Original if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Original *' print '****************************' p.show() # Expanded p_expanded = p._get_expanded() if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Expanded *' print '****************************' p_expanded.show() # Equivalent p_equivalent = p_expanded._get_equivalent() if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Equivalent *' print '****************************' p_equivalent.show() # Nonconvex constraints bad_constr = p_equivalent.constr._get_nonconvex() if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Nonconvex Constraints *' print '****************************\n' print bad_constr # Convex Relaxation p_cvx_relaxation = p_equivalent._get_cvx_relaxation() if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Convex Relaxation *' print '****************************' p_cvx_relaxation.show() # Solve convex relaxation if(not p.options['quiet']): print '\nSolving convex relaxation ...' sol = solve_convex(p_cvx_relaxation,'rel') lagrange_mul_eq = matrix(sol['y']) if(not p.options['quiet']): print 'Relaxation status: ',sol['status'] # Relaxation status: primal infeasible if(sol['status'] == 'primal infeasible'): if(not p.options['quiet']): print 'Original program is primal infeasible' if(p.action == MINIMIZE): return np.inf,lagrange_mul_eq else: return -np.inf,lagrange_mul_eq # Relaxation status: uknown elif(sol['status'] == 'unknown'): relaxation_obj = None # Relaxation status: dual infeasible elif(sol['status'] == 'dual infeasible'): if(p.action == MINIMIZE): relaxation_obj = -np.inf else: relaxation_obj = np.inf # Relaxacion status: optimal else: relaxation_obj = p_cvx_relaxation.obj.get_value() # Report max slack if(len(bad_constr) != 0 and not p.options['quiet']): print 'Max Slack: ', print max(map(lambda x:x.get_value(), [abs(c.left-c.right) for c in bad_constr])) # Tighten if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Tightening Stage *' print '****************************' elif(not p.options['quiet']): print '\nAttempting tightening ...' valid_scp = scp(p_cvx_relaxation,bad_constr,sol) if(not valid_scp): return np.NaN,np.NaN # Prepare results if(len(bad_constr) == 0): obj = relaxation_obj else: obj = p.obj.get_value() if(p.action == MINIMIZE): bound_str = 'Lower Bound' if(relaxation_obj != None): bound = np.min([relaxation_obj,obj]) gap = np.max([obj-relaxation_obj,0.0]) else: bound_str = 'Upper Bound' if(relaxation_obj != None): bound = np.max([relaxation_obj,obj]) gap = np.max([relaxation_obj-obj,0.0]) # Show results if(p.options['show steps'] and not p.options['quiet']): print '\n' print '****************************' print '* Results *' print '****************************' elif(not p.options['quiet']): print '\nResults' if(not p.options['quiet']): print 'Objective =\t%.5e' %obj if(relaxation_obj != None): print bound_str+' =\t%.5e' %bound print 'Gap =\t\t%.5e' %gap else: print bound_str+' =\tUnknown' print 'Gap =\t\tUnknown' if(len(bad_constr) != 0): ms = max(map(lambda x:x.get_value(), [abs(c.left-c.right) for c in bad_constr])) print 'Max Slack =\t%.5e' %ms # Return objective and dual var return obj,lagrange_mul_eq
def rand(m,n): return matrix(np.random.rand(m,n))
def vstack(seq): """ | Stacks objects vertically. :param seq: tuple or list of numbers, :ref:`scalar objects<scalar_ref>` or :ref:`multidimensional objects<multi_ref>`. :return: :ref:`array<array_obj>` or :ref:`matrix<matrix_obj>`. """ # Check input if (type(seq) is not tuple and type(seq) is not list): raise TypeError('Invalid argument') # Process input new_list = [] numeric = True for x in seq: if np.isscalar(x): new_list += [matrix(x)] elif type(x) is cvxpy_obj: new_list += [matrix(x.value)] elif type(x).__name__ in SCALAR_OBJS: numeric = False new_x = cvxpy_array(1,1) new_x[0,0] = x new_list += [new_x] elif type(x).__name__ in ARRAY_OBJS: numeric = False new_list += [x] elif type(x) is cvxpy_matrix: new_list += [x] else: raise TypeError('Invalid Input') # Input is numeric if numeric: return np.vstack(new_list) # Verify dimensions n = new_list[0].shape[1] for x in new_list: if x.shape[1] != n: raise ValueError('Invalid Dimensions') # Allocate new array m = int(np.sum([x.shape[0] for x in new_list])) new_ar = cvxpy_array(m,n) # Fill new array k = 0 for x in new_list: for i in range(0,x.shape[0],1): for j in range(0,x.shape[1],1): new_ar[i+k,j] = x[i,j] k = k + x.shape[0] # Return new array return new_ar