Ejemplo n.º 1
0
    def solve(self, example):
        '''
        Solve problem

        Args:
            example: example object

        Returns:
            Results structure
        '''
        problem = example.cvxpy_problem

        if 'verbose' in self._settings:
            verbose = self._settings["verbose"]
        else:
            verbose = False

        try:
            obj_val = problem.solve(solver=cvxpy.ECOS, verbose=verbose)
        except cvxpy.SolverError:
            if 'verbose' in self._settings:  # if verbose is null, suppress it
                if self._settings['verbose']:
                    print("Error in ECOS solution\n")
            return Results(s.SOLVER_ERROR, None, None, None,
                           None, None)

        status = self.STATUS_MAP.get(problem.status, s.SOLVER_ERROR)

        # Obtain time and number of iterations
        run_time = problem.solver_stats.solve_time \
            + problem.solver_stats.setup_time

        niter = problem.solver_stats.num_iters

        # Get primal, dual solution
        x, y = example.revert_cvxpy_solution()

        # Validate status
        if not is_qp_solution_optimal(example.qp_problem, x, y,
                                      high_accuracy=self._settings.get('high_accuracy')):
            status = s.SOLVER_ERROR

        # Validate execution time
        if 'time_limit' in self._settings:
            if run_time > self._settings['time_limit']:
                status = s.TIME_LIMIT

        return Results(status,
                       obj_val,
                       x,
                       y,
                       run_time,
                       niter)
Ejemplo n.º 2
0
    def solve(self, example):
        '''
        Solve problem

        Args:
            problem: problem structure with QP matrices

        Returns:
            Results structure
        '''
        problem = example.qp_problem
        settings = self._settings.copy()
        high_accuracy = settings.pop('high_accuracy', None)

        # Setup OSQP
        m = osqp.OSQP()
        m.setup(problem['P'], problem['q'], problem['A'], problem['l'],
                problem['u'],
                **settings)

        # Solve
        results = m.solve()
        status = self.STATUS_MAP.get(results.info.status_val, s.SOLVER_ERROR)

        if status in s.SOLUTION_PRESENT:
            if not is_qp_solution_optimal(problem,
                                          results.x,
                                          results.y,
                                          high_accuracy=high_accuracy):
                status = s.SOLVER_ERROR

        # Verify solver time
        if settings.get('time_limit') is not None:
            if results.info.run_time > settings.get('time_limit'):
                status = s.TIME_LIMIT

        return_results = Results(status,
                                 results.info.obj_val,
                                 results.x,
                                 results.y,
                                 results.info.run_time,
                                 results.info.iter)

        return_results.status_polish = results.info.status_polish
        return_results.setup_time = results.info.setup_time
        return_results.solve_time = results.info.solve_time
        return_results.update_time = results.info.update_time
        return_results.rho_updates = results.info.rho_updates

        return return_results
Ejemplo n.º 3
0
    def solve(self, example):
        '''
        Solve problem

        Args:
            example: example object

        Returns:
            Results structure
        '''
        p = example.qp_problem

        if p['A'] is not None:
            # Convert Matrices in CSR format
            p['A'] = p['A'].tocsr()

        if p['P'] is not None:
            # Convert P matrix to COO format
            p['P'] = p['P'].tocoo()

        # Get problem dimensions
        n = p['n']
        m = p['m']

        # Adjust infinity values in bounds
        u = np.copy(p['u'])
        l = np.copy(p['l'])

        for i in range(m):
            if u[i] >= 1e20:
                u[i] = grb.GRB.INFINITY
            if l[i] <= -1e20:
                l[i] = -grb.GRB.INFINITY

        # Create a new model
        model = grb.Model("qp")

        # Add variables
        for i in range(n):
            model.addVar(ub=grb.GRB.INFINITY, lb=-grb.GRB.INFINITY)
        model.update()
        x = model.getVars()

        # Add inequality constraints: iterate over the rows of A
        # adding each row into the model
        if p['A'] is not None:
            # Ignore newer interface for now
            #  if hasattr(model, '_v811_addMConstrs'):
            #      # New interface, all constraints at once
            #      # Get senses
            #      senses = np.repeat(grb.GRB.EQUAL, m)
            #      double_idx = np.array([])  # Array of double constrants for ranges
            #      for i in range(m):
            #          #  if (np.abs(l[i] - u[i]) < 1e-08):
            #          #      # equal case already handled!
            #          if (l[i] == -grb.GRB.INFINITY) & (u[i] != grb.GRB.INFINITY):
            #              senses[i] = grb.GRB.LESS_EQUAL
            #          elif (l[i] != -grb.GRB.INFINITY) & (u[i] == grb.GRB.INFINITY):
            #      # Construct sense
            #
            #  else:
            # Old interface
            for i in range(m):
                start = p['A'].indptr[i]
                end = p['A'].indptr[i + 1]
                variables = [x[j] for j in p['A'].indices[start:end]]  # nnz
                coeff = p['A'].data[start:end]
                expr = grb.LinExpr(coeff, variables)
                if (np.abs(l[i] - u[i]) < 1e-08):
                    model.addConstr(expr, grb.GRB.EQUAL, u[i])
                elif (l[i] == -grb.GRB.INFINITY) & (u[i] == grb.GRB.INFINITY):
                    # Dummy constraint that is always satisfied.
                    # Gurobi crashes if both constraints in addRange function
                    # are infinite.
                    model.addConstr(0. * expr, grb.GRB.LESS_EQUAL, 10.)
                else:
                    model.addRange(expr, lower=l[i], upper=u[i])

        # Define objective
        if p['P'] is not None:
            if hasattr(model, '_v811_setMObjective'):
                # New interface for gurobi > v8.1.1
                model._v811_setMObjective(0.5 * p['P'], p['q'])
            else:
                #  Old interface
                obj = grb.QuadExpr()  # Set quadratic part
                if p['P'].count_nonzero(
                ):  # If there are any nonzero elms in P
                    for i in range(p['P'].nnz):
                        obj.add(.5 * p['P'].data[i] * x[p['P'].row[i]] *
                                x[p['P'].col[i]])
                obj.add(grb.LinExpr(p['q'], x))  # Add linear part
                model.setObjective(obj)  # Set objective

        # Set parameters
        if 'verbose' in self._settings:  # if verbose is null, suppress it
            if self._settings['verbose'] == 0:
                model.setParam("OutputFlag", 0)
        else:
            # If verbose not specified, suppress it as well
            model.setParam("OutputFlag", 0)

        for param, value in self._settings.items():  # Set other parameters
            if (param != "verbose") and (param != "time_limit") \
                    and (param != "high_accuracy"):
                model.setParam(param, value)

        # Update model
        model.update()

        # Solve problem
        try:
            model.optimize()
        except:  # Error in the solution
            if self._settings['verbose']:
                print("Error in GUROBI solution\n")
            run_time = model.Runtime
            return Results(s.SOLVER_ERROR, None, None, None, run_time, None)

        # Get status
        status = self.STATUS_MAP.get(model.Status, s.SOLVER_ERROR)

        # Get computation time
        run_time = model.Runtime

        # Total Number of iterations
        niter = model.BarIterCount

        if status in s.SOLUTION_PRESENT:
            # Get objective value
            objval = model.objVal

            # Get solution
            x = np.array([x[i].X for i in range(n)])

            # Get dual variables  (Gurobi uses swapped signs (-1))
            constrs = model.getConstrs()
            y = -np.array([constrs[i].Pi for i in range(m)])

            if not is_qp_solution_optimal(
                    p, x, y,
                    high_accuracy=self._settings.get('high_accuracy')):
                status = s.SOLVER_ERROR

            # Validate execution time (do not trust commercial solvers)
            if 'time_limit' in self._settings:
                if run_time > self._settings['time_limit']:
                    status = s.TIME_LIMIT

            return Results(status, objval, x, y, run_time, niter)
        else:
            return Results(status, None, None, None, run_time, niter)
Ejemplo n.º 4
0
    def solve(self, example):
        '''
        Solve problem

        Args:
            example: example object

        Returns:
            Results structure
        '''
        p = example.qp_problem
        n, m = p['n'], p['m']

        if p['P'] is not None:
            P = np.ascontiguousarray(p['P'].todense())

        if 'A_nobounds' in p:
            A = np.ascontiguousarray(p['A_nobounds'].todense())
            m = A.shape[0]
        elif p['A'] is not None:
            A = np.ascontiguousarray(p['A'].todense())

        # Define contiguous array vectors
        q = np.ascontiguousarray(p['q'])

        if 'l_nobounds' in p:
            l = np.ascontiguousarray(p['l_nobounds'])
        else:
            l = np.ascontiguousarray(p['l'])

        if 'u_nobounds' in p:
            u = np.ascontiguousarray(p['u_nobounds'])
        else:
            u = np.ascontiguousarray(p['u'])

        if 'lx' in p:
            lx = np.ascontiguousarray(p['lx'])
        else:
            lx = np.ascontiguousarray(-np.inf * np.ones(n))

        if 'ux' in p:
            ux = np.ascontiguousarray(p['ux'])
        else:
            ux = np.ascontiguousarray(np.inf * np.ones(n))

        # Redirect output if verbose is False
        if 'verbose' in self._settings:
            if self._settings['verbose'] is False:
                with stdout_redirected():
                    qpoases_m = qpoases.PyQProblem(n, m)
            else:
                qpoases_m = qpoases.PyQProblem(n, m)
        else:
            # Suppress output also if we do not specify verbose
            with stdout_redirected():
                qpoases_m = qpoases.PyQProblem(n, m)

        options = qpoases.PyOptions()

        for param, value in self._settings.items():
            if param == 'verbose':
                if value is False:
                    options.printLevel = qpoases.PyPrintLevel.NONE
            elif param == 'time_limit':
                qpoases_cpu_time = np.array([value])
            elif param == 'nWSR':
                qpoases_nWSR = np.array([value])
            else:
                exec("options.%s = %s" % (param, value))

        qpoases_m.setOptions(options)

        if 'time_limit' not in self._settings:
            # Set default to max 10 seconds in runtime
            qpoases_cpu_time = np.array([10.])

        if 'nWSR' not in self._settings:
            # Set default to max 1000000 working set recalculations
            qpoases_nWSR = np.array([1000000])

        # Solve problem
        status = qpoases_m.init(P, q, A, lx, ux, l, u,
                                qpoases_nWSR, qpoases_cpu_time)

        # Check status
        status = self.STATUS_MAP.get(status, s.SOLVER_ERROR)

        # run_time
        run_time = qpoases_cpu_time[0]

        # number of iterations
        niter = qpoases_nWSR[0]

        if status in s.SOLUTION_PRESENT:
            x = np.zeros(n)
            y_temp = np.zeros(n + m)
            obj_val = qpoases_m.getObjVal()
            qpoases_m.getPrimalSolution(x)
            qpoases_m.getDualSolution(y_temp)

            # Change sign
            y = -y_temp[n:]

            if 'A_nobounds' in p:
                # If explicit bounds provided, reconstruct dual variable
                # Bounds on all the variables
                y_bounds = -y_temp[:n]
                # Limit to only the actual bounds
                y_bounds = y_bounds[p['bounds_idx']]

                y = np.concatenate((y, y_bounds))

            if not is_qp_solution_optimal(p, x, y):
                status = s.SOLVER_ERROR

            return Results(status, obj_val,
                           x, y,
                           run_time, niter)
        else:
            return Results(status, None, None, None,
                           run_time, niter)
Ejemplo n.º 5
0
    def solve(self, example):
        '''
        Solve problem

        Args:
            example: example object

        Returns:
            Results structure
        '''
        p = example.qp_problem

        # Get problem dimensions
        n = p['P'].shape[0]
        m = p['A'].shape[0]

        '''
        Load problem
        '''
        # Create environment
        env = mosek.Env()

        # Create optimization task
        task = env.Task()

        if 'verbose' in self._settings:  # if verbose is null, suppress it
            if self._settings['verbose']:
                # Define a stream printer to grab output from MOSEK
                def streamprinter(text):
                    import sys
                    sys.stdout.write(text)
                    sys.stdout.flush()
                env.set_Stream(mosek.streamtype.log, streamprinter)
                task.set_Stream(mosek.streamtype.log, streamprinter)

        # Load problem into task object

        # Append 'm' empty constraints.
        # The constraints will initially have no bounds.
        task.appendcons(m)

        # Append 'n' variables.
        # The variables will initially be fixed at zero (x=0).
        task.appendvars(n)

        # Add linear cost by iterating over all variables
        for j in range(n):
            task.putcj(j, p['q'][j])
            task.putvarbound(j, mosek.boundkey.fr, -np.inf, np.inf)

        # Add constraints
        if p['A'] is not None:
            row_A, col_A, el_A = spa.find(p['A'])
            task.putaijlist(row_A, col_A, el_A)

            for j in range(m):
                # Get bounds and keys
                u_temp = p['u'][j] if p['u'][j] < 1e20 else np.inf
                l_temp = p['l'][j] if p['l'][j] > -1e20 else -np.inf

                # Divide 5 cases
                if (np.abs(l_temp - u_temp) < 1e-08):
                    bound_key = mosek.boundkey.fx
                elif l_temp == -np.inf and u_temp == np.inf:
                    bound_key = mosek.boundkey.fr
                elif l_temp != -np.inf and u_temp == np.inf:
                    bound_key = mosek.boundkey.lo
                elif l_temp != -np.inf and u_temp != np.inf:
                    bound_key = mosek.boundkey.ra
                elif l_temp == -np.inf and u_temp != np.inf:
                    bound_key = mosek.boundkey.up

                # Add bound
                task.putconbound(j, bound_key, l_temp, u_temp)

        # Add quadratic cost
        if p['P'].count_nonzero():  # If there are any nonzero elms in P
            P = spa.tril(p['P'], format='coo')
            task.putqobj(P.row, P.col, P.data)

        # Set problem minimization
        task.putobjsense(mosek.objsense.minimize)

        '''
        Set parameters
        '''
        for param, value in self._settings.items():
            if param == 'verbose':
                if value is False:
                    self._handle_str_param(task, 'MSK_IPAR_LOG'.strip(), 0)
            elif param != 'time_limit':
                if isinstance(param, str):
                    self._handle_str_param(task, param.strip(), value)
                else:
                    self._handle_enum_param(task, param, value)

        '''
        Solve problem
        '''
        try:
            # Optimization and check termination code
            task.optimize()
        except:
            if self._settings['verbose']:
                print("Error in MOSEK solution\n")
            return Results(s.SOLVER_ERROR, None, None, None,
                           None, None)

        if 'verbose' in self._settings:  # if verbose is null, suppress it
            if self._settings['verbose']:
                task.solutionsummary(mosek.streamtype.msg)

        '''
        Extract results
        '''

        # Get solution type and status
        soltype, solsta = self.choose_solution(task)

        # Map status using statusmap
        status = self.STATUS_MAP.get(solsta, s.SOLVER_ERROR)

        # Get statistics
        cputime = task.getdouinf(mosek.dinfitem.optimizer_time) + \
            task.getdouinf(mosek.dinfitem.presolve_time)
        total_iter = task.getintinf(mosek.iinfitem.intpnt_iter)

        if status in s.SOLUTION_PRESENT:
            # get primal variables values
            x = np.zeros(task.getnumvar())
            task.getxx(soltype, x)
            # get obj value
            objval = task.getprimalobj(soltype)
            # get dual
            y = np.zeros(task.getnumcon())
            task.gety(soltype, y)
            # it appears signs are inverted
            y = -y

            if not is_qp_solution_optimal(p, x, y):
                status = s.SOLVER_ERROR

            # Validate execution time
            if 'time_limit' in self._settings:
                if cputime > self._settings['time_limit']:
                    status = s.TIME_LIMIT

            return Results(status, objval, x, y,
                           cputime, total_iter)
        else:
            return Results(status, None, None, None,
                           cputime, None)