def _pm_expand(self,constr): # Get shape v = constr.left n = v.shape[0]-1 x = v[0:n,0] y = v[n,0] z = var() # Get power of 2 size m = 0 while (np.log2(n+m) % 1 != 0): m = m + 1 # Copy elements of x on a list and restrict them constr_list = [] el_list = [] for i in range(0,n,1): el_list+=[x[i,0]] if(not np.isscalar(x[i,0]) and type(x[i,0]) is not cvxpy_obj): constr_list += [greater(x[i,0],0)] # Construct expansion z = var() for i in range(0,m,1): el_list += [z] while(len(el_list) > 2): new_list = [] for i in range(0,len(el_list)/2): x1 = el_list[2*i] x2 = el_list[2*i+1] w = var() constr_list += [belongs(vstack((hstack((x1,w)), hstack((w,x2)))), sdc(2))] new_list += [w] el_list = new_list x1 = el_list[0] x2 = el_list[1] constr_list += [belongs(vstack((hstack((x1,z)), hstack((z,x2)))), sdc(2))] constr_list += [greater(z,0),greater(z,y)] return cvxpy_list(constr_list)
def _solve_isolating(self, *args): """ Description ----------- Isolate parameters and then solve program. Used by linearize method to obtain subgradient. Arguments must be numbers. A very important point is that solve_isolating introduces equality constraints and places them at the beginning of the constraint list. This is later used to construct the subgradient. """ # Process input if (len(args) != 0 and type(args[0]) is list): args = args[0] # Create argument list arg_list = [] for arg in args: if (np.isscalar(arg)): arg_list += [arg] elif (type(arg) is cvxpy_matrix): (m, n) = arg.shape for i in range(0, m, 1): for j in range(0, n, 1): arg_list += [arg[i, j]] else: raise ValueError('Arguments must be numeric') # Check number of arguments if (len(arg_list) != len(self.params)): raise ValueError('Invalid number of arguments') # Isolate parameters p1_map = {} new_constr = cvxpy_list([]) for p in self.params: v = var('v_' + p.name) p1_map[p] = v new_constr += cvxpy_list([equal(v, p)]) new_p1 = prog((self.action, re_eval(self.obj, p1_map)), new_constr + re_eval(self.constr, p1_map), self.params, self.options, self.name) # Substitute parameters with arguments p2_map = {} for k in range(0, len(arg_list), 1): p2_map[new_p1.params[k]] = arg_list[k] new_p2 = prog((new_p1.action, re_eval(new_p1.obj, p2_map)), re_eval(new_p1.constr, p2_map), [], new_p1.options, new_p1.name) # Solve program obj, lagrange_mul_eq = solve_prog(new_p2) self.lagrange_mul_eq = lagrange_mul_eq return obj
def _solve_isolating(self,*args): """ Description ----------- Isolate parameters and then solve program. Used by linearize method to obtain subgradient. Arguments must be numbers. A very important point is that solve_isolating introduces equality constraints and places them at the beginning of the constraint list. This is later used to construct the subgradient. """ # Process input if(len(args) != 0 and type(args[0]) is list): args = args[0] # Create argument list arg_list = [] for arg in args: if(np.isscalar(arg)): arg_list += [arg] elif(type(arg) is cvxpy_matrix): (m,n) = arg.shape for i in range(0,m,1): for j in range(0,n,1): arg_list += [arg[i,j]] else: raise ValueError('Arguments must be numeric') # Check number of arguments if(len(arg_list) != len(self.params)): raise ValueError('Invalid number of arguments') # Isolate parameters p1_map = {} new_constr = cvxpy_list([]) for p in self.params: v = var('v_'+p.name) p1_map[p] = v new_constr += cvxpy_list([equal(v,p)]) new_p1 = prog((self.action,re_eval(self.obj,p1_map)), new_constr+re_eval(self.constr,p1_map), self.params, self.options,self.name) # Substitute parameters with arguments p2_map = {} for k in range(0,len(arg_list),1): p2_map[new_p1.params[k]] = arg_list[k] new_p2 = prog((new_p1.action,re_eval(new_p1.obj,p2_map)), re_eval(new_p1.constr,p2_map), [],new_p1.options,new_p1.name) # Solve program obj,lagrange_mul_eq = solve_prog(new_p2) self.lagrange_mul_eq = lagrange_mul_eq return obj
def _pm_expand(self, constr): # Get shape v = constr.left n = v.shape[0] - 1 x = v[0:n, 0] y = v[n, 0] z = var() # Get power of 2 size m = 0 while np.log2(n + m) % 1 != 0: m = m + 1 # Copy elements of x on a list and restrict them constr_list = [] el_list = [] for i in range(0, n, 1): el_list += [x[i, 0]] if not np.isscalar(x[i, 0]) and type(x[i, 0]) is not cvxpy_obj: constr_list += [greater(x[i, 0], 0)] # Construct expansion z = var() for i in range(0, m, 1): el_list += [z] while len(el_list) > 2: new_list = [] for i in range(0, len(el_list) / 2): x1 = el_list[2 * i] x2 = el_list[2 * i + 1] w = var() constr_list += [belongs(vstack((hstack((x1, w)), hstack((w, x2)))), sdc(2))] new_list += [w] el_list = new_list x1 = el_list[0] x2 = el_list[1] constr_list += [belongs(vstack((hstack((x1, z)), hstack((z, x2)))), sdc(2))] constr_list += [greater(z, 0), greater(z, y)] return cvxpy_list(constr_list)
def expand(arg): # Constant if(type(arg) is cvxpy_obj): return arg,cvxpy_list([]) # Scalar variable elif(type(arg) is cvxpy_scalar_var): return arg,cvxpy_list([]) # Summation elif(type(arg) is cvxpy_tree and arg.item.name == '+'): # Get item and children item = arg.item children = arg.children # New var v = var() # Expand children new_children = [] new_constr = cvxpy_list([]) for child in children: # Multiplication if(child.type == TREE and child.item.name == '*'): child_var,child_constr = expand(child.children[1]) new_children += [child.children[0].data*child_var] new_constr += child_constr # Else else: child_var,child_constr = expand(child) new_children += [child_var] new_constr += child_constr # Return (Always right side is the new variable) new_tree = cvxpy_tree(item,new_children) return v,cvxpy_list([equal(new_tree,v)])+new_constr # Multiplication elif(type(arg) is cvxpy_tree and arg.item.name == '*'): # Get item and children item = arg.item children = arg.children # New var v = var() # Apply expand to second operand (first is a constant) child_var,child_constr = expand(children[1]) # Return result (Always right side is the new variable) new_tree = cvxpy_tree(item,[children[0],child_var]) new_eq = cvxpy_list([equal(new_tree,v)]) new_eq += child_constr return v,new_eq # Function elif(type(arg) is cvxpy_tree and arg.item.type == FUNCTION): # Get item and children item = arg.item children = arg.children # New var v = var() # Analyze children new_children = [] new_constr = cvxpy_list([]) for child in children: child_var,child_constr = expand(child) new_children += [child_var] new_constr += child_constr # Return (Always right side is the new variable) new_tree = cvxpy_tree(item,new_children) new_constr += item._range_constr(v) new_constr += item._dom_constr(new_children) return v,cvxpy_list([equal(new_tree,v)])+new_constr # Constraint elif(type(arg) is cvxpy_constr): # Not set membership if(arg.op != 'in'): # Apply expand to left and right side obj1,constr_list1 = expand(arg.left) obj2,constr_list2 = expand(arg.right) # Return new constraints new_constr = cvxpy_constr(obj1,arg.op,obj2) new_list = cvxpy_list([new_constr]) new_list += constr_list1 new_list += constr_list2 return new_list # Set membership else: obj, constr_list = expand(arg.left) new_constr = cvxpy_constr(obj,arg.op,arg.right) return cvxpy_list([new_constr])+constr_list # Array elif(type(arg) is cvxpy_expression or type(arg) is cvxpy_var): (m,n) = arg.shape new_list = cvxpy_list([]) new_exp = cvxpy_expression(m,n) for i in range(0,m,1): for j in range(0,n,1): # Number: Upgrade if(np.isscalar(arg[i,j])): new_exp[i,j] = cvxpy_obj(CONSTANT,arg[i,j],str(arg[i,j])) # Not a number else: obj,constr_list = expand(arg[i,j]) new_exp[i,j] = obj new_list += constr_list return new_exp,new_list # List of constraints elif(type(arg) is cvxpy_list): # Empty list if(len(arg) == 0): return cvxpy_list([]) else: new_list = map(expand,arg) return reduce(lambda x,y:x+y,new_list) # Invalid else: raise ValueError('Invalid argument')
def expand(arg): # Constant if (type(arg) is cvxpy_obj): return arg, cvxpy_list([]) # Scalar variable elif (type(arg) is cvxpy_scalar_var): return arg, cvxpy_list([]) # Summation elif (type(arg) is cvxpy_tree and arg.item.name == '+'): # Get item and children item = arg.item children = arg.children # New var v = var() # Expand children new_children = [] new_constr = cvxpy_list([]) for child in children: # Multiplication if (child.type == TREE and child.item.name == '*'): child_var, child_constr = expand(child.children[1]) new_children += [child.children[0].data * child_var] new_constr += child_constr # Else else: child_var, child_constr = expand(child) new_children += [child_var] new_constr += child_constr # Return (Always right side is the new variable) new_tree = cvxpy_tree(item, new_children) return v, cvxpy_list([equal(new_tree, v)]) + new_constr # Multiplication elif (type(arg) is cvxpy_tree and arg.item.name == '*'): # Get item and children item = arg.item children = arg.children # New var v = var() # Apply expand to second operand (first is a constant) child_var, child_constr = expand(children[1]) # Return result (Always right side is the new variable) new_tree = cvxpy_tree(item, [children[0], child_var]) new_eq = cvxpy_list([equal(new_tree, v)]) new_eq += child_constr return v, new_eq # Function elif (type(arg) is cvxpy_tree and arg.item.type == FUNCTION): # Get item and children item = arg.item children = arg.children # New var v = var() # Analyze children new_children = [] new_constr = cvxpy_list([]) for child in children: child_var, child_constr = expand(child) new_children += [child_var] new_constr += child_constr # Return (Always right side is the new variable) new_tree = cvxpy_tree(item, new_children) new_constr += item._range_constr(v) new_constr += item._dom_constr(new_children) return v, cvxpy_list([equal(new_tree, v)]) + new_constr # Constraint elif (type(arg) is cvxpy_constr): # Not set membership if (arg.op != 'in'): # Apply expand to left and right side obj1, constr_list1 = expand(arg.left) obj2, constr_list2 = expand(arg.right) # Return new constraints new_constr = cvxpy_constr(obj1, arg.op, obj2) new_list = cvxpy_list([new_constr]) new_list += constr_list1 new_list += constr_list2 return new_list # Set membership else: obj, constr_list = expand(arg.left) new_constr = cvxpy_constr(obj, arg.op, arg.right) return cvxpy_list([new_constr]) + constr_list # Array elif (type(arg) is cvxpy_expression or type(arg) is cvxpy_var): (m, n) = arg.shape new_list = cvxpy_list([]) new_exp = cvxpy_expression(m, n) for i in range(0, m, 1): for j in range(0, n, 1): # Number: Upgrade if (np.isscalar(arg[i, j])): new_exp[i, j] = cvxpy_obj(CONSTANT, arg[i, j], str(arg[i, j])) # Not a number else: obj, constr_list = expand(arg[i, j]) new_exp[i, j] = obj new_list += constr_list return new_exp, new_list # List of constraints elif (type(arg) is cvxpy_list): # Empty list if (len(arg) == 0): return cvxpy_list([]) else: new_list = map(expand, arg) return reduce(lambda x, y: x + y, new_list) # Invalid else: raise ValueError('Invalid argument')