コード例 #1
0
def pm_expand(constr_list):
    """
    Description
    -----------
    Expands functions which are implemented
    using partial minimization descriptions.
    constr_list: cvxpy_list of constraints.

    Arguments
    ---------
    constr_list: cvxpy_list of constraints.
    """

    new_list = cvxpy_list([])
    for c in constr_list:
        if (c.left.type == TREE and c.left.item.type == FUNCTION
                and c.left.item.expansion_type == PM):
            new_constr = transform(expand(c.left.item._pm_expand(c)))
            new_constr = pm_expand(new_constr._get_convex())
            new_list += new_constr
        elif (c.left.type == EXPRESSION and c.right.type == SET
              and c.right.expansion_type == PM):
            new_constr = transform(expand(c.right._pm_expand(c)))
            new_constr = pm_expand(new_constr._get_convex())
            new_list += new_constr
        else:
            new_list += cvxpy_list([c])

    # Return new list
    return new_list
コード例 #2
0
def pm_expand(constr_list):
    """
    Description
    -----------
    Expands functions which are implemented
    using partial minimization descriptions.
    constr_list: cvxpy_list of constraints.

    Arguments
    ---------
    constr_list: cvxpy_list of constraints.
    """

    new_list = cvxpy_list([])
    for c in constr_list:
        if(c.left.type == TREE and
           c.left.item.type == FUNCTION and
           c.left.item.expansion_type == PM):
            new_constr = transform(expand(c.left.item._pm_expand(c)))
            new_constr = pm_expand(new_constr._get_convex())
            new_list += new_constr
        elif(c.left.type == EXPRESSION and
             c.right.type == SET and
             c.right.expansion_type == PM):
            new_constr = transform(expand(c.right._pm_expand(c)))
            new_constr = pm_expand(new_constr._get_convex())
            new_list += new_constr
        else:
            new_list += cvxpy_list([c])

    # Return new list
    return new_list
コード例 #3
0
    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
コード例 #4
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
    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
コード例 #5
0
    def _pm_expand(self,constr):
        
        # Get objects
        v = constr.left
        v = vstack([v[i,0] for i in range(0,v.shape[0])])
        n = v.shape[0]-1
        x = vstack([v[0:n,0]])
        y = v[n,0]
        z = variable()

        # One element
        if n==1:
            return cvxpy_list([greater_equals(x,0),
                               greater_equals(x,y)])

        # Get power of 2 size
        m = 0
        while np.log2(n+m) % 1 != 0:
            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_equals(x[i,0],0)]

        # Construct expansion
        for i in range(0,m,1):
            el_list += [z]
        while len(el_list) > 2:
            new_list = []
            for i in range(0,int(len(el_list)/2)):
                x1 = el_list[2*i]
                x2 = el_list[2*i+1]
                w = variable()
                constr_list += [belongs(vstack((hstack((x1,w)),
                                                hstack((w,x2)))),
                                        semidefinite_cone)]
                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)))),
                                semidefinite_cone)]
        constr_list += [greater_equals(z,0),greater_equals(z,y)]
        return cvxpy_list(constr_list)
コード例 #6
0
ファイル: geo_mean_cone.py プロジェクト: rubiruchi/sim_rel
    def _pm_expand(self, constr):

        # Get objects
        v = constr.left
        v = vstack([v[i, 0] for i in range(0, v.shape[0])])
        n = v.shape[0] - 1
        x = vstack([v[0:n, 0]])
        y = v[n, 0]
        z = variable()

        # One element
        if n == 1:
            return cvxpy_list([greater_equals(x, 0), greater_equals(x, y)])

        # Get power of 2 size
        m = 0
        while np.log2(n + m) % 1 != 0:
            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_equals(x[i, 0], 0)]

        # Construct expansion
        for i in range(0, m, 1):
            el_list += [z]
        while len(el_list) > 2:
            new_list = []
            for i in range(0, int(len(el_list) / 2)):
                x1 = el_list[2 * i]
                x2 = el_list[2 * i + 1]
                w = variable()
                constr_list += [
                    belongs(vstack((hstack((x1, w)), hstack((w, x2)))),
                            semidefinite_cone)
                ]
                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)))),
                    semidefinite_cone)
        ]
        constr_list += [greater_equals(z, 0), greater_equals(z, y)]
        return cvxpy_list(constr_list)
コード例 #7
0
    def __init__(self, action, obj, constr, params, opt, name):

        # Function attributes
        self.name = name
        self.type = FUNCTION
        self.atom = False
        self.expansion_type = PM
        if (action == MINIMIZE):
            self.curvature = CONVEX
        else:
            self.curvature = CONCAVE

        # Program attributes
        self.lagrange_mul_eq = None
        self.action = action
        self.obj = obj
        self.constr = cvxpy_list(constr)
        if (opt != None):
            self.options = opt
        else:
            self.options = {
                'SCP_ALG': SCP_ALG_OPT.copy(),
                'SCP_SOL': SCP_SOLVER_OPT.copy(),
                'REL_SOL': RELAX_SOLVER_OPT.copy(),
                'show steps': False,
                'quiet': True
            }

        # Store parameters
        param_list = []
        for param in params:
            if (type(param) is cvxpy_scalar_param):
                param_list += [param]
            elif (type(param) is cvxpy_param):
                (m, n) = param.shape
                for i in range(0, m, 1):
                    for j in range(0, n, 1):
                        param_list += [param[i, j]]
            else:
                raise ValueError('Invalid parameter')
        self.params = cvxpy_list(param_list)

        # Verify parameters
        exp_params = self.get_params()
        if (len(exp_params) != len(self.params)):
            raise ValueError('Parameters do not match')
        for x in exp_params:
            if (x not in self.params):
                raise ValueError('Parameters do not match')
コード例 #8
0
ファイル: arrays.py プロジェクト: yfamy123/subgradient-py
 def get_params(self):
     l = cvxpy_list([])
     for i in range(0,self.shape[0],1):
         for j in range(0,self.shape[1],1):
             if(not np.isscalar(self[i,j])):
                 l += self[i,j].get_params()
     return l
コード例 #9
0
    def __init__(self,object_type,value,name):
        """
        Class constructor.
        
        :param object_type: Keyword (See cvxpy.def).
        :param value: Number.
        :param name: String.
        """

        self.type = object_type
        self.value = value
        self.name = name
        self.shape = (1,1)
        self.variables = cvxpy_list()
        self.parameters = cvxpy_list()        
        self.T = self
コード例 #10
0
def call_solver(p, quiet):
    """
    Calls solver. 

    :param p: Convex cvxpy_program. 
              Assumed to be expanded.
    :param quiet: Boolean.
    """

    # Set printing format for cvxopt sparse matrices
    opt.spmatrix_str = opt.printing.spmatrix_str_triplet

    # Expand objects defined via partial minimization
    constr_list = cvxpy_list(pm_expand(p.constraints))

    # Get variables
    variables = constr_list.variables
    variables.sort()

    # Count variables
    n = len(variables)

    # Create variable-index map
    var_to_index = {}
    for i in range(0, n, 1):
        var_to_index[variables[i]] = i

    # Construct objective vector
    c = construct_c(p.objective, var_to_index, n, p.action)

    # Construct Ax == b
    A, b = construct_Ab(constr_list._get_eq(), var_to_index, n)

    # Construct  Gx <= h
    G, h, dim_l, dim_q, dim_s = construct_Gh(constr_list._get_ineq_in(),
                                             var_to_index, n)

    # Construct F
    F = construct_F(constr_list._get_ineq_in(), var_to_index, n)

    # Call cvxopt
    solvers.options['maxiters'] = p.options['maxiters']
    solvers.options['abstol'] = p.options['abstol']
    solvers.options['reltol'] = p.options['reltol']
    solvers.options['feastol'] = p.options['feastol']
    solvers.options['show_progress'] = not quiet
    dims = {'l': dim_l, 'q': dim_q, 's': dim_s}
    if F is None:
        r = solvers.conelp(c, G, h, dims, A, b)
    else:
        r = solvers.cpl(c, F, G, h, dims, A, b)

    # Store numerical values
    if r['status'] != PRIMAL_INFEASIBLE:
        for v in variables:
            v.value = r['x'][var_to_index[v]]

    # Return result
    return r
コード例 #11
0
def call_solver(p,quiet):
    """
    Calls solver. 

    :param p: Convex cvxpy_program. 
              Assumed to be expanded.
    :param quiet: Boolean.
    """

    # Set printing format for cvxopt sparse matrices
    opt.spmatrix_str = opt.printing.spmatrix_str_triplet 	
    
    # Expand objects defined via partial minimization
    constr_list = cvxpy_list(pm_expand(p.constraints))
    
    # Get variables
    variables = constr_list.variables
    variables.sort()

    # Count variables
    n = len(variables)

    # Create variable-index map
    var_to_index = {}
    for i in range(0,n,1):
        var_to_index[variables[i]] = i

    # Construct objective vector
    c = construct_c(p.objective,var_to_index,n,p.action)

    # Construct Ax == b
    A,b = construct_Ab(constr_list._get_eq(),var_to_index,n)

    # Construct  Gx <= h
    G,h,dim_l,dim_q,dim_s = construct_Gh(constr_list._get_ineq_in(),
                                         var_to_index,n)
    
    # Construct F
    F = construct_F(constr_list._get_ineq_in(),var_to_index,n)

    # Call cvxopt
    solvers.options['maxiters'] = p.options['maxiters']
    solvers.options['abstol'] = p.options['abstol']
    solvers.options['reltol'] = p.options['reltol']
    solvers.options['feastol'] = p.options['feastol']
    solvers.options['show_progress'] = not quiet
    dims = {'l':dim_l, 'q':dim_q, 's':dim_s}
    if F is None:
        r =  solvers.conelp(c,G,h,dims,A,b)
    else:
        r =  solvers.cpl(c,F,G,h,dims,A,b)

    # Store numerical values
    if r['status'] != PRIMAL_INFEASIBLE:
        for v in variables:
            v.value =  r['x'][var_to_index[v]]

    # Return result
    return r
コード例 #12
0
 def _dom_constr(self, args):
     """
     Description
     -----------
     Dummy method to make the program 
     appear as a function.
     """
     return cvxpy_list([])
コード例 #13
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
 def _dom_constr(self,args):
     """
     Description
     -----------
     Dummy method to make the program 
     appear as a function.
     """
     return cvxpy_list([])
コード例 #14
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
    def __init__(self,action,obj,constr,params,opt,name):
        
        # Function attributes
        self.name = name
        self.type = FUNCTION
        self.atom = False
        self.expansion_type = PM
        if(action == MINIMIZE):
            self.curvature = CONVEX
        else:
            self.curvature = CONCAVE
       
        # Program attributes
        self.lagrange_mul_eq = None
        self.action = action
        self.obj = obj
        self.constr = cvxpy_list(constr)
        if(opt != None):
            self.options = opt
        else:
            self.options = {'SCP_ALG':SCP_ALG_OPT.copy(),
                            'SCP_SOL':SCP_SOLVER_OPT.copy(),
                            'REL_SOL':RELAX_SOLVER_OPT.copy(),
                            'show steps':False,'quiet': True}

        # Store parameters
        param_list = []
        for param in params:
            if(type(param) is cvxpy_scalar_param):
                param_list += [param]
            elif(type(param) is cvxpy_param):
                (m,n) = param.shape
                for i in range(0,m,1):
                    for j in range(0,n,1):
                        param_list += [param[i,j]]
            else:
                raise ValueError('Invalid parameter')
        self.params = cvxpy_list(param_list)

        # Verify parameters
        exp_params = self.get_params()
        if(len(exp_params) != len(self.params)):
            raise ValueError('Parameters do not match')
        for x in exp_params:
            if(x not in self.params):
                raise ValueError('Parameters do not match')
コード例 #15
0
ファイル: arrays.py プロジェクト: rubiruchi/sim_rel
    def __getattribute__(self, name):

        # Transpose
        if name == 'T':
            new_ar = cvxpy_sparray(self.shape[1], self.shape[0])
            for i in range(0, self.shape[0], 1):
                rowi_indeces = self.rows[i]
                rowi_values = self.data[i]
                for k in range(0, len(rowi_indeces)):
                    new_ar[rowi_indeces[k], i] = rowi_values[k]
            return new_ar

        # Variables
        elif name == 'variables':
            l = []
            for i in range(0, self.shape[0], 1):
                for obj in self.data[i]:
                    if not np.isscalar(obj):
                        l += obj.variables
            return cvxpy_list(set(l))

        # Parameters
        elif name == 'parameters':
            l = []
            for i in range(0, self.shape[0], 1):
                for obj in self.data[i]:
                    if not np.isscalar(obj):
                        l += obj.parameters
            return cvxpy_list(set(l))

        # Value
        elif name == 'value':
            mat = cvxpy_spmatrix((self.shape[0], self.shape[1]), np.float64)
            for i in range(0, self.shape[0], 1):
                rowi_indeces = self.rows[i]
                rowi_values = self.data[i]
                for k in range(0, len(rowi_indeces)):
                    if np.isscalar(rowi_values[k]):
                        mat[i, rowi_indeces[k]] = rowi_values[k]
                    else:
                        mat[i, rowi_indeces[k]] = rowi_values[k].value
            return mat

        # Other attribute
        else:
            return object.__getattribute__(self, name)
コード例 #16
0
ファイル: arrays.py プロジェクト: a85531506/research_project
    def __getattribute__(self,name):

        # Transpose
        if name == 'T':
            new_ar = cvxpy_sparray(self.shape[1],self.shape[0])
            for i in range(0,self.shape[0],1):
                rowi_indeces = self.rows[i]
                rowi_values = self.data[i]
                for k in range(0,len(rowi_indeces)):
                    new_ar[rowi_indeces[k],i] = rowi_values[k]
            return new_ar

        # Variables
        elif name == 'variables':
            l = []
            for i in range(0,self.shape[0],1):
                for obj in self.data[i]:
                    if not np.isscalar(obj):
                        l += obj.variables
            return cvxpy_list(set(l))

        # Parameters
        elif name == 'parameters':
            l = []
            for i in range(0,self.shape[0],1):
                for obj in self.data[i]:
                    if not np.isscalar(obj):
                        l += obj.parameters
            return cvxpy_list(set(l))

        # Value
        elif name == 'value':
            mat = cvxpy_spmatrix((self.shape[0],self.shape[1]),np.float64)
            for i in range(0,self.shape[0],1):
                rowi_indeces = self.rows[i]
                rowi_values = self.data[i]
                for k in range(0,len(rowi_indeces)):
                    if np.isscalar(rowi_values[k]):
                        mat[i,rowi_indeces[k]] = rowi_values[k] 
                    else:
                        mat[i,rowi_indeces[k]] = rowi_values[k].value
            return mat
        
        # Other attribute
        else:
            return object.__getattribute__(self,name)
コード例 #17
0
    def __getattribute__(self,name):

        # Parameters
        if name == 'parameters':
            return cvxpy_list([self])

        # Other
        else:
            return object.__getattribute__(self,name)
コード例 #18
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
 def get_params(self):
     """
     Description
     -----------
     Construct a set with the parameters present
     in the program.
     """
     constr_params = self.constr.get_params()
     obj_params = self.obj.get_params()
     all_params = constr_params
     for v in obj_params:
         l1 = map(lambda x: x is v,all_params)
         if(len(l1) != 0):
             if not reduce(lambda x,y: x or y,l1):
                 all_params += cvxpy_list([v])
         else:
             all_params += cvxpy_list([v])
     return all_params
コード例 #19
0
    def __getattribute__(self,name):

        # Variables
        if name == 'variables':
            return cvxpy_list([self])

        # Other
        else:
            return object.__getattribute__(self,name)
コード例 #20
0
 def get_params(self):
     """
     Description
     -----------
     Construct a set with the parameters present
     in the program.
     """
     constr_params = self.constr.get_params()
     obj_params = self.obj.get_params()
     all_params = constr_params
     for v in obj_params:
         l1 = map(lambda x: x is v, all_params)
         if (len(l1) != 0):
             if not reduce(lambda x, y: x or y, l1):
                 all_params += cvxpy_list([v])
         else:
             all_params += cvxpy_list([v])
     return all_params
コード例 #21
0
def transform(constr_list):
    """
    Description 
    -----------
    Transforms nonlinear equality constraints
    to equivalent form involving two inequalities.

    Arguments
    ---------
    constr_list: cvxpy_list of constraints in 
    expanded form so that all nonlinear constraints
    are equalities.
    """

    # New list
    new_list = cvxpy_list([])

    # Transform
    for constr in constr_list:

        # Function
        if (constr.left.type == TREE and constr.left.item.type == FUNCTION):

            # Get function
            fn = constr.left.item

            # Get equivalent transformation
            new_constr = cvxpy_list([
                less(constr.left, constr.right),
                greater(constr.left, constr.right)
            ])

            # Append
            new_list += cvxpy_list(new_constr)

        # Not a function
        else:

            # Append
            new_list += cvxpy_list([constr])

    # Return transformed list
    return new_list
コード例 #22
0
ファイル: arrays.py プロジェクト: rubiruchi/sim_rel
    def __getattribute__(self, name):

        # Transpose
        if name == 'T':
            new_ar = cvxpy_array(self.shape[1], self.shape[0])
            for i in range(0, self.shape[0], 1):
                for j in range(0, self.shape[1], 1):
                    new_ar.data[j][i] = self.data[i][j]
            return new_ar

        # Variables
        elif name == 'variables':
            l = []
            for i in range(0, self.shape[0], 1):
                for j in range(0, self.shape[1], 1):
                    if not np.isscalar(self.data[i][j]):
                        l += self.data[i][j].variables
            return cvxpy_list(set(l))

        # Parameters
        elif name == 'parameters':
            l = []
            for i in range(0, self.shape[0], 1):
                for j in range(0, self.shape[1], 1):
                    if not np.isscalar(self.data[i][j]):
                        l += self.data[i][j].parameters
            return cvxpy_list(set(l))

        # Value
        elif name == 'value':
            mat = cvxpy_matrix(np.zeros((self.shape[0], self.shape[1])),
                               np.float64)
            for i in range(0, self.shape[0], 1):
                for j in range(0, self.shape[1], 1):
                    if np.isscalar(self.data[i][j]):
                        mat[i, j] = self.data[i][j]
                    else:
                        mat[i, j] = self.data[i][j].value
            return mat

        # Other attribute
        else:
            return object.__getattribute__(self, name)
コード例 #23
0
ファイル: arrays.py プロジェクト: a85531506/research_project
    def __getattribute__(self,name):

        # Transpose
        if name == 'T':
            new_ar = cvxpy_array(self.shape[1],self.shape[0])
            for i in range(0,self.shape[0],1):
                for j in range(0,self.shape[1],1):
                    new_ar.data[j][i] = self.data[i][j]
            return new_ar

        # Variables
        elif name == 'variables':
            l = []
            for i in range(0,self.shape[0],1):
                for j in range(0,self.shape[1],1):
                    if not np.isscalar(self.data[i][j]):
                        l += self.data[i][j].variables
            return cvxpy_list(set(l))

        # Parameters
        elif name == 'parameters':
            l = []
            for i in range(0,self.shape[0],1):
                for j in range(0,self.shape[1],1):
                    if not np.isscalar(self.data[i][j]):
                        l += self.data[i][j].parameters
            return cvxpy_list(set(l))

        # Value
        elif name == 'value':
            mat = cvxpy_matrix(np.zeros((self.shape[0],self.shape[1])),np.float64)
            for i in range(0,self.shape[0],1):
                for j in range(0,self.shape[1],1):
                    if np.isscalar(self.data[i][j]):
                        mat[i,j] = self.data[i][j]
                    else:
                        mat[i,j] = self.data[i][j].value
            return mat
        
        # Other attribute
        else:
            return object.__getattribute__(self,name)
コード例 #24
0
ファイル: transform.py プロジェクト: yfamy123/subgradient-py
def transform(constr_list):
    """
    Description 
    -----------
    Transforms nonlinear equality constraints
    to equivalent form involving two inequalities.

    Arguments
    ---------
    constr_list: cvxpy_list of constraints in 
    expanded form so that all nonlinear constraints
    are equalities.
    """

    # New list
    new_list = cvxpy_list([])

    # Transform
    for constr in constr_list:

        # Function
        if(constr.left.type == TREE and
           constr.left.item.type == FUNCTION):

            # Get function
            fn = constr.left.item

            # Get equivalent transformation
            new_constr = cvxpy_list([less(constr.left,constr.right),
                                     greater(constr.left,constr.right)])
        
            # Append
            new_list += cvxpy_list(new_constr)
        
        # Not a function
        else:
            
            # Append
            new_list += cvxpy_list([constr])
            
    # Return transformed list
    return new_list
コード例 #25
0
 def _pm_expand(self, constr):
     """
     Description: Return the partial minimization 
     expansion of the function. 
     Argument constr: The constraint to be
     replaced. It is assumed to be in expanded
     format so the right hand side is a variable.
     """
     arg = constr.left.children[0]
     right = constr.right
     return cvxpy_list([less(-right, arg), less(arg, right)])
コード例 #26
0
ファイル: abs.py プロジェクト: yfamy123/subgradient-py
 def _pm_expand(self,constr):
     """
     Description: Return the partial minimization 
     expansion of the function. 
     Argument constr: The constraint to be
     replaced. It is assumed to be in expanded
     format so the right hand side is a variable.
     """
     arg = constr.left.children[0]
     right = constr.right
     return cvxpy_list([less(-right,arg),
                        less(arg,right)])
コード例 #27
0
    def __getattribute__(self,name):
        
        # Variables
        if name == 'variables':
            l = list(map(lambda x: x.variables,self.children))
            return cvxpy_list(set(reduce(lambda x,y:x+y,l,[])))
        
        # Parameters
        elif name == 'parameters':
            l = list(map(lambda x: x.parameters,self.children))
            return cvxpy_list(set(reduce(lambda x,y:x+y,l,[])))

        # Value
        elif name == 'value':
            
            # Summation
            if (self.item.type == OPERATOR and 
                self.item.name == SUMMATION):
                return np.sum(list(map(lambda x:x.value,self.children)))

            # Multiplication
            elif (self.item.type == OPERATOR and 
                  self.item.name == MULTIPLICATION):
                return self.children[0].value*self.children[1].value

            # Function
            elif self.item.type == FUNCTION:
                return self.item(list(map(lambda x: x.value,self.children)))
            
            # Error
            else:
                raise TypeError('Invalid tree item')

        # Other
        else:
            return object.__getattribute__(self,name)
コード例 #28
0
ファイル: interface.py プロジェクト: yfamy123/subgradient-py
def compare(obj1,op,obj2):
    
    # Both scalars 
    if((np.isscalar(obj1) or type(obj1).__name__ in SCALAR_OBJS) and
       (np.isscalar(obj2) or type(obj2).__name__ in SCALAR_OBJS)):
        
        # Upgrade scalars to cvxpy_obj
        if(np.isscalar(obj1)):
            obj1 = cvxpy_obj(CONSTANT,obj1,str(obj1))
        if(np.isscalar(obj2)):
            obj2 = cvxpy_obj(CONSTANT,obj2,str(obj2))

        # Construct and return constraint
        return cvxpy_constr(obj1,op,obj2)

    # Upgrate scalars to arrays
    if((type(obj1) is cvxpy_matrix or type(obj1).__name__ in ARRAY_OBJS) and
       (np.isscalar(obj2) or type(obj2).__name__ in SCALAR_OBJS)):
        (m,n) = obj1.shape
        new_exp = cvxpy_expression(m,n)
        for i in range(0,m,1):
            for j in range(0,n,1):
                new_exp[i,j] = obj2
        obj2 = new_exp
    if((type(obj2) is cvxpy_matrix or type(obj2).__name__ in ARRAY_OBJS) and
       (np.isscalar(obj1) or type(obj1).__name__ in SCALAR_OBJS)):
        (m,n) = obj2.shape
        new_exp = cvxpy_expression(m,n)
        for i in range(0,m,1):
            for j in range(0,n,1):
                new_exp[i,j] = obj1
        obj1 = new_exp
    
    # Both arrays
    if((type(obj1) is cvxpy_matrix or type(obj1).__name__ in ARRAY_OBJS) and
       (type(obj2) is cvxpy_matrix or type(obj2).__name__ in ARRAY_OBJS)):
        constr = []
        if(obj1.shape != obj2.shape):
            raise ValueError('Invalid dimensions')
        (m,n) = obj1.shape
        for i in range(0,m,1):
            for j in range(0,n,1):
                constr += [compare(obj1[i,j],op,obj2[i,j])]
        return cvxpy_list(constr)

    # Invalid arguments
    raise ValueError('Objects not comparable')    
コード例 #29
0
def compare(obj1, op, obj2):

    # Both scalars
    if ((np.isscalar(obj1) or type(obj1).__name__ in SCALAR_OBJS)
            and (np.isscalar(obj2) or type(obj2).__name__ in SCALAR_OBJS)):

        # Upgrade scalars to cvxpy_obj
        if (np.isscalar(obj1)):
            obj1 = cvxpy_obj(CONSTANT, obj1, str(obj1))
        if (np.isscalar(obj2)):
            obj2 = cvxpy_obj(CONSTANT, obj2, str(obj2))

        # Construct and return constraint
        return cvxpy_constr(obj1, op, obj2)

    # Upgrate scalars to arrays
    if ((type(obj1) is cvxpy_matrix or type(obj1).__name__ in ARRAY_OBJS)
            and (np.isscalar(obj2) or type(obj2).__name__ in SCALAR_OBJS)):
        (m, n) = obj1.shape
        new_exp = cvxpy_expression(m, n)
        for i in range(0, m, 1):
            for j in range(0, n, 1):
                new_exp[i, j] = obj2
        obj2 = new_exp
    if ((type(obj2) is cvxpy_matrix or type(obj2).__name__ in ARRAY_OBJS)
            and (np.isscalar(obj1) or type(obj1).__name__ in SCALAR_OBJS)):
        (m, n) = obj2.shape
        new_exp = cvxpy_expression(m, n)
        for i in range(0, m, 1):
            for j in range(0, n, 1):
                new_exp[i, j] = obj1
        obj1 = new_exp

    # Both arrays
    if ((type(obj1) is cvxpy_matrix or type(obj1).__name__ in ARRAY_OBJS) and
        (type(obj2) is cvxpy_matrix or type(obj2).__name__ in ARRAY_OBJS)):
        constr = []
        if (obj1.shape != obj2.shape):
            raise ValueError('Invalid dimensions')
        (m, n) = obj1.shape
        for i in range(0, m, 1):
            for j in range(0, n, 1):
                constr += [compare(obj1[i, j], op, obj2[i, j])]
        return cvxpy_list(constr)

    # Invalid arguments
    raise ValueError('Objects not comparable')
コード例 #30
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
    def is_dcp(self,args=None):
        """
        Description
        -----------
        Checks if the program follows DCP rules.
        If args is None, the check is done on the
        body of the program. If args is a list of
        arguments, the parameters are replaced
        with the arguments and the check is done
        on the resulting program. This function
        is called with a list of arguments when 
        cvxpy_tree.is_dcp is executed.
        
        Arguments
        ---------
        args: List of arguments
        """

        # No arguments: Check body of program
        if(args == None):
            if(self.action == MINIMIZE and
               not self.obj.is_convex()):
                return False
            elif(self.action == MAXIMIZE and
                 not self.obj.is_concave()):
                return False
            else:
                return self.constr.is_dcp()

        # Arguments given: Replace parameters and then check
        else:

            # Check if some argument has parameters
            if(len(cvxpy_list(args).get_params()) != 0):
                return False

            # Create a param-arg map
            p_map = {}
            for k in range(0,len(args),1):
                p_map[self.params[k]] = args[k]

            # Re-evaluate
            new_p = prog((self.action,re_eval(self.obj,p_map)),
                         re_eval(self.constr,p_map))

            # Check dcp on resulting program
            return new_p.is_dcp()
コード例 #31
0
ファイル: gmc.py プロジェクト: architkumar02/subgradient-py
    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)
コード例 #32
0
    def is_dcp(self, args=None):
        """
        Description
        -----------
        Checks if the program follows DCP rules.
        If args is None, the check is done on the
        body of the program. If args is a list of
        arguments, the parameters are replaced
        with the arguments and the check is done
        on the resulting program. This function
        is called with a list of arguments when 
        cvxpy_tree.is_dcp is executed.
        
        Arguments
        ---------
        args: List of arguments
        """

        # No arguments: Check body of program
        if (args == None):
            if (self.action == MINIMIZE and not self.obj.is_convex()):
                return False
            elif (self.action == MAXIMIZE and not self.obj.is_concave()):
                return False
            else:
                return self.constr.is_dcp()

        # Arguments given: Replace parameters and then check
        else:

            # Check if some argument has parameters
            if (len(cvxpy_list(args).get_params()) != 0):
                return False

            # Create a param-arg map
            p_map = {}
            for k in range(0, len(args), 1):
                p_map[self.params[k]] = args[k]

            # Re-evaluate
            new_p = prog((self.action, re_eval(self.obj, p_map)),
                         re_eval(self.constr, p_map))

            # Check dcp on resulting program
            return new_p.is_dcp()
コード例 #33
0
ファイル: max.py プロジェクト: zc8340311/subgradient-py
    def _pm_expand(self, constr):
        """
	Description
        -----------
        Return the partial minimization 
        expansion of the function. 
	
        Argument
        --------
        constr: The constraint to be replaced. 
        It is assumed the constraint was expanded
        and transformed so that the right hand side 
        is a variable.
	"""
        new_list = []
        for arg in constr.left.children:
            if type(arg) is cvxpy_obj:
                arg = arg.get_value()
            new_list += [less(arg, constr.right)]
        return cvxpy_list(new_list)
コード例 #34
0
ファイル: max.py プロジェクト: architkumar02/subgradient-py
    def _pm_expand(self, constr):
        """
	Description
        -----------
        Return the partial minimization 
        expansion of the function. 
	
        Argument
        --------
        constr: The constraint to be replaced. 
        It is assumed the constraint was expanded
        and transformed so that the right hand side 
        is a variable.
	"""
        new_list = []
        for arg in constr.left.children:
            if (type(arg) is cvxpy_obj):
                arg = arg.get_value()
            new_list += [less(arg, constr.right)]
        return cvxpy_list(new_list)
コード例 #35
0
ファイル: gmc.py プロジェクト: zc8340311/subgradient-py
    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)
コード例 #36
0
ファイル: program.py プロジェクト: yfamy123/subgradient-py
    def _pm_expand(self,constr):
        """
        Description
        -----------
        Given the constraint, which must be in the form
        self(args) operator variable, the parameters
        are replaced with arguments and then the 
        partial minimization description of the program
        is merged with the constraint.

        Argument
        --------
        constr: cvxpy_constr of the form self(args) 
        operator variable.
        """

        # Get arguments
        args = constr.left.children

        # Create arg-param map by position
        p_map = {}
        for k in range(0,len(args),1):
            p_map[self.params[k]] = args[k]

        # Create new program
        new_p = prog((self.action,re_eval(self.obj,p_map)),
                     re_eval(self.constr,p_map),[],
                     self.options,self.name)

        # Expand partial minimization
        right = constr.right
        new_constr = []
        if(self.curvature == CONVEX):
            new_constr += [less(new_p.obj,right)]
        else:
            new_constr += [greater(new_p.obj,right)]
        new_constr += new_p.constr
        
        # Return constraints
        return cvxpy_list(new_constr)
コード例 #37
0
    def _pm_expand(self, constr):
        """
        Description
        -----------
        Given the constraint, which must be in the form
        self(args) operator variable, the parameters
        are replaced with arguments and then the 
        partial minimization description of the program
        is merged with the constraint.

        Argument
        --------
        constr: cvxpy_constr of the form self(args) 
        operator variable.
        """

        # Get arguments
        args = constr.left.children

        # Create arg-param map by position
        p_map = {}
        for k in range(0, len(args), 1):
            p_map[self.params[k]] = args[k]

        # Create new program
        new_p = prog((self.action, re_eval(self.obj, p_map)),
                     re_eval(self.constr, p_map), [], self.options, self.name)

        # Expand partial minimization
        right = constr.right
        new_constr = []
        if (self.curvature == CONVEX):
            new_constr += [less(new_p.obj, right)]
        else:
            new_constr += [greater(new_p.obj, right)]
        new_constr += new_p.constr

        # Return constraints
        return cvxpy_list(new_constr)
コード例 #38
0
    def is_affine(self):
        """
        Determines if tree is an affine expression.
        """

        # Summation
        if (self.item.type == OPERATOR and
            self.item.name == SUMMATION):
            return all(list(map(lambda x: x.is_affine(),self.children)))

        # Multiplication
        elif (self.item.type == OPERATOR and 
              self.item.name == MULTIPLICATION):
            ob2 = self.children[1]
            return ob2.is_affine()

        # Function
        elif self.item.type == FUNCTION:
            return len(cvxpy_list(self.children).variables) == 0
        
        # Error
        else:
            raise TypeError('Invalid tree item')
コード例 #39
0
 def get_vars(self):
     return cvxpy_list([])
コード例 #40
0
 def _range_constr(self, v):
     return cvxpy_list([greater(v, 0)])
コード例 #41
0
ファイル: max.py プロジェクト: zc8340311/subgradient-py
 def _dom_constr(self, args):
     return cvxpy_list([])
コード例 #42
0
ファイル: max.py プロジェクト: zc8340311/subgradient-py
 def _range_constr(self, v):
     return cvxpy_list([])
コード例 #43
0
def re_eval(arg,param_map):
    """
    Description
    -----------
    Replaces parameters found in arg using the param_map
    and re-evaluates the resulting object.
    
    Arguments
    ---------
    arg: Argument to be re-evaluated.
    param_map: Dictionery that maps the parameters 
    to objects.
    """

    # Number
    if(np.isscalar(arg)):
        return arg
    
    # Constant object
    elif(type(arg) is cvxpy_obj):
        return arg.get_value()
    
    # Scalar variable
    elif(type(arg) is cvxpy_scalar_var):
        return arg
    
    # Scalar param
    elif(type(arg) is cvxpy_scalar_param):
        return re_eval(param_map[arg],param_map)

    # Summation
    elif(type(arg) is cvxpy_tree and arg.item.name == '+'):
        new_children = map(lambda x:re_eval(x,param_map),arg.children)
        return sum(new_children)

    # Multiplication
    elif(type(arg) is cvxpy_tree and arg.item.name == '*'):
        child1 = re_eval(arg.children[0],param_map)
        child2 = re_eval(arg.children[1],param_map)
        return child1*child2

    # Function
    elif(type(arg) is cvxpy_tree and arg.item.type == FUNCTION):
        new_children = map(lambda x:re_eval(x,param_map),arg.children)
        return arg.item(new_children)

    # Constraint
    elif(type(arg) is cvxpy_constr):
        
        # Not set membership
        if(arg.op != 'in'):
            left = re_eval(arg.left ,param_map)
            right= re_eval(arg.right,param_map)
            if(arg.op == '=='):
                return equal(left,right)
            elif(arg.op == '<='):
                return less(left,right)
            else:
                return greater(left,right)

        # Set membership
        else:
            left = re_eval(arg.left,param_map)
            return belongs(left,arg.right)

    # Array
    elif(type(arg) is cvxpy_expression or
         type(arg) is cvxpy_var or
         type(arg) is cvxpy_param):
        (m,n) = arg.shape
        new_exp = cvxpy_expression(m,n)
        for i in range(0,m,1):
            for j in range(0,n,1):
                new_exp[i,j] = re_eval(arg[i,j],param_map)
        return new_exp

    # List
    elif(type(arg) is cvxpy_list):
        new_list = cvxpy_list([])
        for c in arg:
            new_list += cvxpy_list([re_eval(c,param_map)])
        return new_list

    # Invalid
    else:
        raise ValueError('Invalid argument')
コード例 #44
0
ファイル: square.py プロジェクト: yfamy123/subgradient-py
 def _range_constr(self, v):
     return cvxpy_list([greater(v,0)])
コード例 #45
0
ファイル: sqrt.py プロジェクト: architkumar02/subgradient-py
 def _dom_constr(self, args):
     arg = args[0]
     return cvxpy_list([greater(arg, 0)])
コード例 #46
0
ファイル: expand.py プロジェクト: yfamy123/subgradient-py
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')
コード例 #47
0
 def get_params(self):
     return cvxpy_list([])
コード例 #48
0
 def _dom_constr(self, args):
     return cvxpy_list([])
コード例 #49
0
 def get_params(self):
     l = map(lambda x: x.get_params(),self.children)
     if(len(l) != 0):
         return reduce(lambda x,y:x+y,l)
     else:
         return cvxpy_list([])
コード例 #50
0
ファイル: max.py プロジェクト: architkumar02/subgradient-py
 def _range_constr(self, v):
     return cvxpy_list([])
コード例 #51
0
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')