Ejemplo n.º 1
0
def solver(graph=None, update=False, full=False, data=None, SO=False):
    """Find the UE link flow
    
    Parameters
    ----------
    graph: graph object
    update: if update==True: update link flows and link,path delays in graph
    full: if full=True, also return x (link flows per OD pair)
    data: (Aeq, beq, ffdelays, parameters, type) from get_data(graph)
    """
    if data is None: data = get_data(graph)
    Aeq, beq, ffdelays, pm, type = data
    n = len(ffdelays)
    p = Aeq.size[1]/n
    A, b = spmatrix(-1.0, range(p*n), range(p*n)), matrix(0.0, (p*n,1))
    if type == 'Polynomial':
        if not SO: pm = pm * spdiag([1.0/(j+2) for j in range(pm.size[1])])
        def F(x=None, z=None): return objective_poly(x, z, matrix([[ffdelays], [pm]]), p)
    if type == 'Hyperbolic':
        if SO:
            def F(x=None, z=None): return objective_hyper_SO(x, z, matrix([[ffdelays-div(pm[:,0],pm[:,1])], [pm]]), p)
        else:
            def F(x=None, z=None): return objective_hyper(x, z, matrix([[ffdelays-div(pm[:,0],pm[:,1])], [pm]]), p)
    dims = {'l': p*n, 'q': [], 's': []}
    x = solvers.cp(F, G=A, h=b, A=Aeq, b=beq, kktsolver=get_kktsolver(A, dims, Aeq, F))['x']
    linkflows = matrix(0.0, (n,1))
    for k in range(p): linkflows += x[k*n:(k+1)*n]
    
    if update:
        logging.info('Update link flows, delays in Graph.'); graph.update_linkflows_linkdelays(linkflows)
        logging.info('Update path delays in Graph.'); graph.update_pathdelays()
    
    if full: return linkflows, x    
    return linkflows
Ejemplo n.º 2
0
def solver(graph=None, update=False, full=False, data=None, SO=False):
    """Find the UE link flow
    
    Parameters
    ----------
    graph: graph object
    update: if update==True: update link flows and link,path delays in graph
    full: if full=True, also return x (link flows per OD pair)
    data: (Aeq, beq, ffdelays, parameters, type) from get_data(graph)
    """
    if data is None: data = get_data(graph)
    Aeq, beq, ffdelays, pm, type = data
    n = len(ffdelays)
    p = Aeq.size[1]/n
    A, b = spmatrix(-1.0, range(p*n), range(p*n)), matrix(0.0, (p*n,1))
    if type == 'Polynomial':
        if not SO: pm = pm * spdiag([1.0/(j+2) for j in range(pm.size[1])])
        def F(x=None, z=None): return objective_poly(x, z, matrix([[ffdelays], [pm]]), p)
    if type == 'Hyperbolic':
        if SO:
            def F(x=None, z=None): return objective_hyper_SO(x, z, matrix([[ffdelays-div(pm[:,0],pm[:,1])], [pm]]), p)
        else:
            def F(x=None, z=None): return objective_hyper(x, z, matrix([[ffdelays-div(pm[:,0],pm[:,1])], [pm]]), p)
    dims = {'l': p*n, 'q': [], 's': []}
    x = solvers.cp(F, G=A, h=b, A=Aeq, b=beq, kktsolver=get_kktsolver(A, dims, Aeq, F))['x']
    linkflows = matrix(0.0, (n,1))
    for k in range(p): linkflows += x[k*n:(k+1)*n]
    
    if update:
        logging.info('Update link flows, delays in Graph.'); graph.update_linkflows_linkdelays(linkflows)
        logging.info('Update path delays in Graph.'); graph.update_pathdelays()
    
    if full: return linkflows, x    
    return linkflows
def feasible_pathflows(graph, l_obs, obs=None, update=False,
                       with_cell_paths=False, with_ODs=False, x_true=None, wp_trajs=None):
    """Attempts to find feasible pathflows given partial of full linkflows
    
    Parameters:
    ----------
    graph: Graph object
    l_obs: observations of link flows
    obs: indices of the observed links
    update: if True, update path flows in graph
    with_cell_paths: if True, include cell paths as constraints
    with_ODs: if True, include ODs in the constraints if no with_cell_paths or in the objective if with_cell_paths
    """
    assert with_cell_paths or with_ODs # we must have some measurements!
    n = graph.numpaths
    # route to links flow constraints
    A, b = linkpath_incidence(graph), l_obs
    if obs: A = A[obs,:] # trim matrix if we have partial observations
    Aineq, bineq = spmatrix(-1.0, range(n), range(n)), matrix(0.0, (n,1)) # positive constraints
    if not with_cell_paths: # if just with ODs flow measurements:
        Aeq, beq = path_to_OD_simplex(graph) # route to OD flow constraints
    else: # if we have cellpath flow measurements:
        assert wp_trajs is not None
        Aeq, beq = WP.simplex(graph, wp_trajs) # route to cellpath flow constraints
        if with_ODs: # if we have ODs + cellpaths measurements
          T, d = path_to_OD_simplex(graph) # route to OD flow constraints included in objective
          A, b = matrix([A, T]), matrix([b, d]) # add the constraints to the objective
        
    if x_true is not None:
        err1 =  np.linalg.norm(A * x_true - b, 1) / np.linalg.norm(b, 1)
        err2 = np.linalg.norm(Aeq * x_true - beq) / np.linalg.norm(beq, 1)
        assert err1 < TOL, 'Ax!=b'
        assert err2 < TOL, 'Aeq x!=beq'
    # construct objective for cvxopt.solvers.qp
    Q, c = A.trans()*A, -A.trans()*b
    #x = solvers.qp(Q + REG_EPS*spmatrix(1.0, range(n), range(n)), c, Aineq, bineq, Aeq, beq)['x']
    # try with cvxopt.solvers.cp
    def qp_objective(x=None, z=None):
      if x is None: return 0, matrix(1.0, (n, 1))
      f = 0.5 * x.trans()*Q*x + c.trans() * x
      Df = (Q*x + c).trans()
      if z is None: return f, Df
      return f, Df, z[0]*Q
  
    dims = {'l': n, 'q': [], 's': []}
    x = solvers.cp(qp_objective, G=Aineq, h=bineq, A=Aeq, b=beq, 
        kktsolver=get_kktsolver(Aineq, dims, Aeq, qp_objective))['x']
    
    if update:
        logging.info('Update link flows, delays in Graph.'); graph.update_linkflows_linkdelays(P*x)
        logging.info('Update path delays in Graph.'); graph.update_pathdelays()
        logging.info('Update path flows in Graph object.'); graph.update_pathflows(x)
    #import ipdb
    #rank = 5
    #if with_ODs == False:
    #    ipdb.set_trace()
    return x, rn.rank(matrix([A, Aeq])), n
    
Ejemplo n.º 4
0
    def _solve(self, solver=s.ECOS, ignore_dcp=False, verbose=False):
        if not self.is_dcp():
            if ignore_dcp:
                print ("Problem does not follow DCP rules. "
                       "Solving a convex relaxation.")
            else:
                raise Exception("Problem does not follow DCP rules.")
        objective,constr_map,dims = self.canonicalize()
        var_offsets,x_length = self.variables(objective, 
                                              constr_map[s.EQ] + constr_map[s.INEQ])
       
        c,obj_offset = self.constraints_matrix([objective], var_offsets, x_length,
                                               self.dense_interface, self.dense_interface)
        A,b = self.constraints_matrix(constr_map[s.EQ], var_offsets, x_length,
                                      self.interface, self.dense_interface)
        G,h = self.constraints_matrix(constr_map[s.INEQ], var_offsets, x_length,
                                      self.interface, self.dense_interface)

        # ECHU: get the nonlinear constraints
        F = self.nonlinear_constraint_function(constr_map[s.NONLIN], var_offsets,
                                               x_length)

        # Save original cvxopt solver options.
        old_options = cvxopt.solvers.options
        # Silence cvxopt if verbose is False.
        cvxopt.solvers.options['show_progress'] = verbose
        # Always do one step of iterative refinement after solving KKT system.
        cvxopt.solvers.options['refinement'] = 1
        # Target cvxopt clp if nonlinear constraints exist
        if constr_map[s.NONLIN]:
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A, F)
            results = cvxopt.solvers.cpl(c.T,F,G,h,A=A,b=b,
                                         dims=dims,kktsolver=kktsolver)
            status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
            primal_val = results['primal objective']
        # Target cvxopt solver if SDP or invalid for ECOS.
        elif solver == s.CVXOPT or len(dims['s']) > 0 or min(G.size) == 0:
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A)
            # Adjust tolerance to account for regularization.
            cvxopt.solvers.options['feastol'] = 2*1e-6
            results = cvxopt.solvers.conelp(c.T,G,h,A=A,b=b,
                                            dims=dims,kktsolver=kktsolver)
            status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
            primal_val = results['primal objective']
        else: # If possible, target ECOS.
            # ECHU: ecos interface has changed and no longer relies on CVXOPT
            # as a result, we have to convert cvxopt data structures into
            # numpy arrays
            #
            # ideally, CVXPY would no longer user CVXOPT, except when calling
            # conelp
            #
            cnp, hnp, bnp = map(lambda x: np.fromiter(iter(x),dtype=np.double,count=len(x)), (c, h, b))
            Gp,Gi,Gx = G.CCS
            m,n1 = G.size
            Ap,Ai,Ax = A.CCS
            p,n2 = A.size
            Gp, Gi, Ap, Ai = map(lambda x: np.fromiter(iter(x),dtype=np.int32,count=len(x)), (Gp,Gi,Ap,Ai))
            Gx, Ax = map(lambda x: np.fromiter(iter(x),dtype=np.double,count=len(x)), (Gx, Ax))
            Gsp = sp.csc_matrix((Gx,Gi,Gp),shape=(m,n1))
            if p == 0:
                Asp = None
                bnp = None
            else:
                Asp = sp.csc_matrix((Ax,Ai,Ap),shape=(p,n2))
                
            # ECHU: end conversion
            results = ecos.solve(cnp,Gsp,hnp,dims,Asp,bnp,verbose=verbose)
            status = s.SOLVER_STATUS[s.ECOS][results['info']['exitFlag']]
            primal_val = results['info']['pcost']

        # Restore original cvxopt solver options.
        cvxopt.solvers.options = old_options

        if status == s.SOLVED:
            self.save_values(results['x'], sorted(var_offsets.keys()))
            self.save_values(results['y'], constr_map[s.EQ])
            if constr_map[s.NONLIN]:
                self.save_values(results['zl'], constr_map[s.INEQ])
            else:
                self.save_values(results['z'], constr_map[s.INEQ])
            return self.objective.value(primal_val - obj_offset[0])
        else:
            return status
Ejemplo n.º 5
0
    def _cvxopt_solve(self, objective, constr_map, dims,
                      sorted_vars, var_offsets, x_length,
                      verbose):
        """Calls the CVXOPT conelp or cpl solver and returns the result.

        Parameters
        ----------
            objective: Expression
                The canonicalized objective.
            constr_map: dict
                A dict of the canonicalized constraints.
            dims: dict
                A dict with information about the types of constraints.
            sorted_vars: list
                An ordered list of the problem variables.
            var_offsets: dict
                A dict mapping variable id to offset in the stacked variable x.
            x_length: int
                The height of x.
            verbose: bool
                Should the solver show output?

        Returns
        -------
        tuple
            (status, optimal objective, optimal x,
             optimal equality constraint dual,
             optimal inequality constraint dual)

        """
        c, obj_offset = self._constr_matrix([objective], var_offsets, x_length,
                                            self._CVXOPT_DENSE_INTF,
                                            self._CVXOPT_DENSE_INTF)
        # Convert obj_offset to a scalar.
        obj_offset = self._CVXOPT_DENSE_INTF.scalar_value(obj_offset)

        A, b = self._constr_matrix(constr_map[s.EQ], var_offsets, x_length,
                                   self._CVXOPT_SPARSE_INTF,
                                   self._CVXOPT_DENSE_INTF)
        G, h = self._constr_matrix(constr_map[s.INEQ], var_offsets, x_length,
                                   self._CVXOPT_SPARSE_INTF,
                                   self._CVXOPT_DENSE_INTF)

        # Save original cvxopt solver options.
        old_options = cvxopt.solvers.options
        # Silence cvxopt if verbose is False.
        cvxopt.solvers.options['show_progress'] = verbose
        # Always do one step of iterative refinement after solving KKT system.
        cvxopt.solvers.options['refinement'] = 1
        # Target cvxopt clp if nonlinear constraints exist
        if constr_map[s.EXP]:
            # Get the nonlinear constraints.
            F = self._merge_nonlin(constr_map[s.EXP], var_offsets,
                                   x_length)
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A, F)
            results = cvxopt.solvers.cpl(c.T, F, G, h, A=A, b=b,
                                         dims=dims, kktsolver=kktsolver)
        else:
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A)
            results = cvxopt.solvers.conelp(c.T, G, h, A=A, b=b,
                                            dims=dims, kktsolver=kktsolver)
        status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
        if status == s.OPTIMAL:
            primal_val = results['primal objective']
            value = self.objective._primal_to_result(
                          primal_val - obj_offset)
            # Restore original cvxopt solver options.
            cvxopt.solvers.options = old_options
            if constr_map[s.EXP]:
                ineq_dual = results['zl']
            else:
                ineq_dual = results['z']
            return (status, value, results['x'], results['y'], ineq_dual)
        else:
            return (status, None, None, None, None)
Ejemplo n.º 6
0
    def _solve(self, solver=s.ECOS, ignore_dcp=False, verbose=False):
        """Solves a DCP compliant optimization problem.

        Saves the values of primal and dual variables in the variable
        and constraint objects, respectively.

        Args:
            solver: The solver to use. Defaults to ECOS.
            ignore_dcp: Overrides the default of raising an exception if
                        the problem is not DCP.
            verbose: Overrides the default of hiding solver output.

        Returns:
            The optimal value for the problem, or a string indicating
            why the problem could not be solved.
        """
        if not self.is_dcp():
            if ignore_dcp:
                print ("Problem does not follow DCP rules. "
                       "Solving a convex relaxation.")
            else:
                raise Exception("Problem does not follow DCP rules.")
        objective, constr_map, dims = self.canonicalize()

        all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.INEQ])
        var_offsets, x_length = self._get_var_offsets(objective, all_ineq)

        c, obj_offset = self._constr_matrix([objective], var_offsets, x_length,
                                            self._DENSE_INTF,
                                            self._DENSE_INTF)
        A, b = self._constr_matrix(constr_map[s.EQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)
        G, h = self._constr_matrix(constr_map[s.INEQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)

        # Save original cvxopt solver options.
        old_options = cvxopt.solvers.options
        # Silence cvxopt if verbose is False.
        cvxopt.solvers.options['show_progress'] = verbose
        # Always do one step of iterative refinement after solving KKT system.
        cvxopt.solvers.options['refinement'] = 1
        # Target cvxopt clp if nonlinear constraints exist
        if constr_map[s.NONLIN]:
            # Get the nonlinear constraints.
            F = self._merge_nonlin(constr_map[s.NONLIN], var_offsets, x_length)
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A, F)
            results = cvxopt.solvers.cpl(c.T, F, G, h, A=A, b=b,
                                         dims=dims,kktsolver=kktsolver)
            status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
            primal_val = results['primal objective']
        # Target cvxopt solver if SDP or invalid for ECOS.
        elif solver == s.CVXOPT or len(dims['s']) > 0 or min(G.size) == 0:
            # Get custom kktsolver.
            kktsolver = get_kktsolver(G, dims, A)
            # Adjust tolerance to account for regularization.
            cvxopt.solvers.options['feastol'] = 2*1e-6
            results = cvxopt.solvers.conelp(c.T, G, h, A=A, b=b,
                                            dims=dims, kktsolver=kktsolver)
            status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
            primal_val = results['primal objective']
        else: # If possible, target ECOS.
            # ECHU: ecos interface has changed and no longer relies on CVXOPT
            # as a result, we have to convert cvxopt data structures into
            # numpy arrays
            #
            # ideally, CVXPY would no longer user CVXOPT, except when calling
            # conelp
            #
            cnp, hnp, bnp = (np.fromiter(iter(x),
                                        dtype=np.double,
                                        count=len(x))
                             for x in (c, h, b))
            Gp, Gi, Gx = G.CCS
            m, n1 = G.size
            Ap, Ai, Ax = A.CCS
            p, n2 = A.size
            Gp, Gi, Ap, Ai = (np.fromiter(iter(x),
                                         dtype=np.int32,
                                         count=len(x))
                              for x in (Gp, Gi, Ap, Ai))
            Gx, Ax = (np.fromiter(iter(x),
                                  dtype=np.double,
                                  count=len(x))
                      for x in (Gx, Ax))
            Gsp = sp.csc_matrix((Gx, Gi, Gp), shape=(m, n1))
            if p == 0:
                Asp = None
                bnp = None
            else:
                Asp = sp.csc_matrix((Ax, Ai, Ap), shape=(p, n2))

            # ECHU: end conversion
            results = ecos.solve(cnp, Gsp, hnp, dims, Asp, bnp, verbose=verbose)
            status = s.SOLVER_STATUS[s.ECOS][results['info']['exitFlag']]
            primal_val = results['info']['pcost']

        # Restore original cvxopt solver options.
        cvxopt.solvers.options = old_options

        if status == s.SOLVED:
            self._save_values(results['x'], var_offsets.keys())
            self._save_values(results['y'], constr_map[s.EQ])
            if constr_map[s.NONLIN]:
                self._save_values(results['zl'], constr_map[s.INEQ])
            else:
                self._save_values(results['z'], constr_map[s.INEQ])
            return self.objective._primal_to_result(primal_val - obj_offset[0])
        else:
            return status
Ejemplo n.º 7
0
    def _solve(self, solver=s.ECOS, ignore_dcp=False, verbose=False):
        """Solves a DCP compliant optimization problem.

        Saves the values of primal and dual variables in the variable
        and constraint objects, respectively.

        Parameters
        ----------
        solver : str, optional
            The solver to use. Defaults to ECOS.
        ignore_dcp : bool, optional
            Overrides the default of raising an exception if the problem is not
            DCP.
        verbose : bool, optional
            Overrides the default of hiding solver output.

        Returns
        -------
        float
            The optimal value for the problem, or a string indicating
            why the problem could not be solved.
        """
        if not self.is_dcp():
            if ignore_dcp:
                print ("Problem does not follow DCP rules. "
                       "Solving a convex relaxation.")
            else:
                raise Exception("Problem does not follow DCP rules.")
        objective, constr_map, dims = self.canonicalize()

        all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.INEQ])
        var_offsets, x_length = self._get_var_offsets(objective, all_ineq)

        c, obj_offset = self._constr_matrix([objective], var_offsets, x_length,
                                            self._DENSE_INTF,
                                            self._DENSE_INTF)
        # Convert obj_offset to a scalar.
        obj_offset = self._DENSE_INTF.scalar_value(obj_offset)

        A, b = self._constr_matrix(constr_map[s.EQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)
        G, h = self._constr_matrix(constr_map[s.INEQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)

        # Save original cvxopt solver options.
        old_options = cvxopt.solvers.options
        # Silence cvxopt if verbose is False.
        cvxopt.solvers.options['show_progress'] = verbose
        # Always do one step of iterative refinement after solving KKT system.
        cvxopt.solvers.options['refinement'] = 1
        # Target cvxopt solver if SDP or invalid for ECOS.
        if solver == s.CVXOPT or len(dims['s']) > 0 \
            or min(G.shape) == 0 or constr_map[s.NONLIN]:
            # Convert c,A,b,G,h to cvxopt matrices.
            c, b, h = map(lambda vec:
                self._CVXOPT_DENSE_INTF.const_to_matrix(vec,
                    convert_scalars=True),
                [c, b, h])
            A, G = map(lambda mat:
                self._CVXOPT_SPARSE_INTF.const_to_matrix(mat,
                    convert_scalars=True),
                [A, G])
            # Target cvxopt clp if nonlinear constraints exist
            if constr_map[s.NONLIN]:
                # Get the nonlinear constraints.
                F = self._merge_nonlin(constr_map[s.NONLIN], var_offsets,
                                       x_length)
                # Get custom kktsolver.
                kktsolver = get_kktsolver(G, dims, A, F)
                results = cvxopt.solvers.cpl(c.T, F, G, h, A=A, b=b,
                                             dims=dims,kktsolver=kktsolver)
                status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
                primal_val = results['primal objective']
            else:
                # Get custom kktsolver.
                kktsolver = get_kktsolver(G, dims, A)
                # Adjust tolerance to account for regularization.
                cvxopt.solvers.options['feastol'] = 2*1e-6
                results = cvxopt.solvers.conelp(c.T, G, h, A=A, b=b,
                                                dims=dims, kktsolver=kktsolver)
                status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
                primal_val = results['primal objective']
        else: # If possible, target ECOS.
            # Convert c,h,b to 1D arrays.
            c, h, b = map(lambda mat: np.asarray(mat)[:, 0], [c.T, h, b])
            results = ecos.solve(c, G, h, dims, A, b, verbose=verbose)
            status = s.SOLVER_STATUS[s.ECOS][results['info']['exitFlag']]
            primal_val = results['info']['pcost']

        # Restore original cvxopt solver options.
        cvxopt.solvers.options = old_options

        if status == s.OPTIMAL:
            self._save_values(results['x'], var_offsets.keys())
            self._save_values(results['y'], constr_map[s.EQ])
            if constr_map[s.NONLIN]:
                self._save_values(results['zl'], constr_map[s.INEQ])
            else:
                self._save_values(results['z'], constr_map[s.INEQ])
            self._value = self.objective._primal_to_result(
                          primal_val - obj_offset)
        else:
            self._handle_failure(status, var_offsets.keys(),
                itertools.chain(constr_map[s.EQ], constr_map[s.INEQ]))
        self._status = status
        return self.value
Ejemplo n.º 8
0
def feasible_pathflows(graph,
                       l_obs,
                       obs=None,
                       update=False,
                       with_cell_paths=False,
                       with_ODs=False,
                       x_true=None,
                       wp_trajs=None):
    """Attempts to find feasible pathflows given partial of full linkflows
    
    Parameters:
    ----------
    graph: Graph object
    l_obs: observations of link flows
    obs: indices of the observed links
    update: if True, update path flows in graph
    with_cell_paths: if True, include cell paths as constraints
    with_ODs: if True, include ODs in the constraints if no with_cell_paths or in the objective if with_cell_paths
    """
    assert with_cell_paths or with_ODs  # we must have some measurements!
    n = graph.numpaths
    # route to links flow constraints
    A, b = linkpath_incidence(graph), l_obs
    if obs: A = A[obs, :]  # trim matrix if we have partial observations
    Aineq, bineq = spmatrix(-1.0, range(n),
                            range(n)), matrix(0.0,
                                              (n, 1))  # positive constraints
    if not with_cell_paths:  # if just with ODs flow measurements:
        Aeq, beq = path_to_OD_simplex(graph)  # route to OD flow constraints
    else:  # if we have cellpath flow measurements:
        assert wp_trajs is not None
        Aeq, beq = WP.simplex(graph,
                              wp_trajs)  # route to cellpath flow constraints
        if with_ODs:  # if we have ODs + cellpaths measurements
            T, d = path_to_OD_simplex(
                graph)  # route to OD flow constraints included in objective
            A, b = matrix([A, T]), matrix(
                [b, d])  # add the constraints to the objective

    if x_true is not None:
        err1 = np.linalg.norm(A * x_true - b, 1) / np.linalg.norm(b, 1)
        err2 = np.linalg.norm(Aeq * x_true - beq) / np.linalg.norm(beq, 1)
        assert err1 < TOL, 'Ax!=b'
        assert err2 < TOL, 'Aeq x!=beq'
    # construct objective for cvxopt.solvers.qp
    Q, c = A.trans() * A, -A.trans() * b

    #x = solvers.qp(Q + REG_EPS*spmatrix(1.0, range(n), range(n)), c, Aineq, bineq, Aeq, beq)['x']
    # try with cvxopt.solvers.cp
    def qp_objective(x=None, z=None):
        if x is None: return 0, matrix(1.0, (n, 1))
        f = 0.5 * x.trans() * Q * x + c.trans() * x
        Df = (Q * x + c).trans()
        if z is None: return f, Df
        return f, Df, z[0] * Q

    dims = {'l': n, 'q': [], 's': []}
    x = solvers.cp(qp_objective,
                   G=Aineq,
                   h=bineq,
                   A=Aeq,
                   b=beq,
                   kktsolver=get_kktsolver(Aineq, dims, Aeq,
                                           qp_objective))['x']

    if update:
        logging.info('Update link flows, delays in Graph.')
        graph.update_linkflows_linkdelays(P * x)
        logging.info('Update path delays in Graph.')
        graph.update_pathdelays()
        logging.info('Update path flows in Graph object.')
        graph.update_pathflows(x)
    #import ipdb
    #rank = 5
    #if with_ODs == False:
    #    ipdb.set_trace()
    return x, rn.rank(matrix([A, Aeq])), n
Ejemplo n.º 9
0
    def _solve(self, solver=s.ECOS, ignore_dcp=False, verbose=False):
        """Solves a DCP compliant optimization problem.

        Saves the values of primal and dual variables in the variable
        and constraint objects, respectively.

        Parameters
        ----------
        solver : str, optional
            The solver to use. Defaults to ECOS.
        ignore_dcp : bool, optional
            Overrides the default of raising an exception if the problem is not
            DCP.
        verbose : bool, optional
            Overrides the default of hiding solver output.

        Returns
        -------
        float
            The optimal value for the problem, or a string indicating
            why the problem could not be solved.
        """
        if not self.is_dcp():
            if ignore_dcp:
                print ("Problem does not follow DCP rules. "
                       "Solving a convex relaxation.")
            else:
                raise Exception("Problem does not follow DCP rules.")
        objective, constr_map, dims = self.canonicalize()

        all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.INEQ])
        var_offsets, x_length = self._get_var_offsets(objective, all_ineq)

        c, obj_offset = self._constr_matrix([objective], var_offsets, x_length,
                                            self._DENSE_INTF,
                                            self._DENSE_INTF)
        # Convert obj_offset to a scalar.
        obj_offset = self._DENSE_INTF.scalar_value(obj_offset)

        A, b = self._constr_matrix(constr_map[s.EQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)
        G, h = self._constr_matrix(constr_map[s.INEQ], var_offsets, x_length,
                                   self._SPARSE_INTF, self._DENSE_INTF)

        # Save original cvxopt solver options.
        old_options = cvxopt.solvers.options
        # Silence cvxopt if verbose is False.
        cvxopt.solvers.options['show_progress'] = verbose
        # Always do one step of iterative refinement after solving KKT system.
        cvxopt.solvers.options['refinement'] = 1
        # Target cvxopt solver if SDP or invalid for ECOS.
        if solver == s.CVXOPT or len(dims['s']) > 0 \
            or min(G.shape) == 0 or constr_map[s.NONLIN]:
            # Convert c,A,b,G,h to cvxopt matrices.
            c, b, h = map(lambda vec:
                self._CVXOPT_DENSE_INTF.const_to_matrix(vec,
                    convert_scalars=True),
                [c, b, h])
            A, G = map(lambda mat:
                self._CVXOPT_SPARSE_INTF.const_to_matrix(mat,
                    convert_scalars=True),
                [A, G])
            # Target cvxopt clp if nonlinear constraints exist
            if constr_map[s.NONLIN]:
                # Get the nonlinear constraints.
                F = self._merge_nonlin(constr_map[s.NONLIN], var_offsets,
                                       x_length)
                # Get custom kktsolver.
                kktsolver = get_kktsolver(G, dims, A, F)
                results = cvxopt.solvers.cpl(c.T, F, G, h, A=A, b=b,
                                             dims=dims,kktsolver=kktsolver)
                status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
                primal_val = results['primal objective']
            else:
                # Get custom kktsolver.
                kktsolver = get_kktsolver(G, dims, A)
                # Adjust tolerance to account for regularization.
                cvxopt.solvers.options['feastol'] = 2*1e-6
                results = cvxopt.solvers.conelp(c.T, G, h, A=A, b=b,
                                                dims=dims, kktsolver=kktsolver)
                status = s.SOLVER_STATUS[s.CVXOPT][results['status']]
                primal_val = results['primal objective']
        else: # If possible, target ECOS.
            # Convert c,h,b to 1D arrays.
            c, h, b = map(lambda mat: np.asarray(mat)[:, 0], [c.T, h, b])
            results = ecos.solve(c, G, h, dims, A, b, verbose=verbose)
            status = s.SOLVER_STATUS[s.ECOS][results['info']['exitFlag']]
            primal_val = results['info']['pcost']

        # Restore original cvxopt solver options.
        cvxopt.solvers.options = old_options

        if status == s.OPTIMAL:
            self._save_values(results['x'], var_offsets.keys())
            self._save_values(results['y'], constr_map[s.EQ])
            if constr_map[s.NONLIN]:
                self._save_values(results['zl'], constr_map[s.INEQ])
            else:
                self._save_values(results['z'], constr_map[s.INEQ])
            self._value = self.objective._primal_to_result(
                          primal_val - obj_offset)
        else:
            self._handle_failure(status, var_offsets.keys(),
                itertools.chain(constr_map[s.EQ], constr_map[s.INEQ]))
        self._status = status
        return self.value