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)
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
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)
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)
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)