def setUp(self): # Reset random seed for repeatability np.random.seed(1) # Random Example n = 30 m = 50 p = 5 # Number of integer variables # Generate random Matrices Pt = spa.random(n, n, density=0.6) P = Pt.dot(Pt.T).tocsc() q = np.random.randn(n) A = spa.random(m, n, density=0.6).tocsc() u = 3 + np.random.randn(m) l = -3 + np.random.randn(m) # Generate random vector of indeces i_idx = np.random.choice(np.arange(0, n), p, replace=False) # Generate variable bounds i_l = -1*np.ones(p) i_u = 1*np.ones(p) self.p = mpbpy.QuadprogProblem(P, q, A, l, u, i_idx, i_l, i_u)
def setUp(self): # Dual infeasible example P = spa.csc_matrix(np.diag(np.array([4., 0.]))) q = np.array([0., 2]) A = spa.csc_matrix([[1., 1.], [-1., 1.]]) l = np.array([-np.inf, -np.inf]) u = np.array([2., 3.]) self.p = mpbpy.QuadprogProblem(P, q, A, l, u)
def load_maros_meszaros_problem(f): # Load file m = spio.loadmat(f) # Convert matrices P = m['Q'].astype(float) n = P.shape[0] q = m['c'].T.flatten().astype(float) A = m['A'].astype(float) A = spspa.vstack([A, spspa.eye(n)]) u = np.append(m['ru'].T.flatten().astype(float), m['ub'].T.flatten().astype(float)) l = np.append(m['rl'].T.flatten().astype(float), m['lb'].T.flatten().astype(float)) # Define problem p = mpbpy.QuadprogProblem(P, q, A, l, u) return p
def setUp(self): # Reset random seed for repeatability np.random.seed(1) # Random Example n = 30 m = 50 # Generate random Matrices Pt = spa.random(n, n, density=0.6) P = Pt.dot(Pt.T).tocsc() q = np.random.randn(n) A = spa.random(m, n, density=0.6).tocsc() u = 3 + np.random.randn(m) l = -3 + np.random.randn(m) # Make random problem primal infeasible A[int(n / 2), :] = A[int(n / 2) + 1, :] l[int(n / 2)] = u[int(n / 2) + 1] + 10 * np.random.rand() u[int(n / 2)] = l[int(n / 2)] + 0.5 self.p = mpbpy.QuadprogProblem(P, q, A, l, u)
def solve_problem(qp_matrices, n_prob, solver='osqp'): """ Solve SVM problem """ # Shorter name for qp_matrices qp = qp_matrices # Initialize time vector time = np.zeros(n_prob) # Initialize number of iterations vector niter = np.zeros(n_prob) # Get dimensions m = len(qp.lx) n = len(qp.q) - m print('n = %d and solver %s' % (n, solver)) if solver == 'osqp': # Construct qp matrices Aosqp = spa.vstack([ qp.A, spa.hstack([spa.csc_matrix((m, n)), spa.eye(m)]), ]).tocsc() losqp = np.hstack([qp.l, qp.lx]) uosqp = np.hstack([qp.u, qp.ux]) for i in range(n_prob): # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q, Aosqp, losqp, uosqp, auto_rho=True, polish=False, verbose=False) # Solve results = m.solve() x = results.x status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # import mathprogbasepy as mpbpy # prob = mpbpy.QuadprogProblem(qp.P, qp.q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() elif solver == 'qpoases': for i in range(n_prob): n_dim = qp.P.shape[0] # Number of variables m_dim = qp.A.shape[0] # Number of constraints without bounds # Initialize qpoases and set options qpoases_m = qpoases.PyQProblem(n_dim, m_dim) options = qpoases.PyOptions() options.printLevel = qpoases.PyPrintLevel.NONE qpoases_m.setOptions(options) # Construct bounds for qpoases lx = np.append(-np.inf * np.ones(n), qp.lx) ux = np.append(np.inf * np.ones(n), qp.ux) # Setup matrix P and A P = np.ascontiguousarray(qp.P.todense()) A = np.ascontiguousarray(qp.A.todense()) # Reset cpu time qpoases_cpu_time = np.array([20.]) # Reset number of working set recalculations nWSR = np.array([1000]) # Solve res_qpoases = qpoases_m.init(P, np.ascontiguousarray(qp.q), A, np.ascontiguousarray(lx), np.ascontiguousarray(ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) if res_qpoases != 0: raise ValueError('qpoases did not solve the problem!') # Save time and number of iterations time[i] = qpoases_cpu_time[0] niter[i] = nWSR[0] elif solver == 'gurobi': for i in range(n_prob): # Construct qp matrices Agurobi = spa.vstack([ qp.A, spa.hstack([spa.csc_matrix((m, n)), spa.eye(m)]), ]).tocsc() lgurobi = np.hstack([qp.l, qp.lx]) ugurobi = np.hstack([qp.u, qp.ux]) # Solve with gurobi prob = mpbpy.QuadprogProblem(qp.P, qp.q, Agurobi, lgurobi, ugurobi) res = prob.solve(solver=mpbpy.GUROBI, verbose=False) niter[i] = res.total_iter time[i] = res.cputime elif solver == 'mosek': for i in range(n_prob): # Construct qp matrices Amosek = spa.vstack([ qp.A, spa.hstack([spa.csc_matrix((m, n)), spa.eye(m)]), ]).tocsc() lmosek = np.hstack([qp.l, qp.lx]) umosek = np.hstack([qp.u, qp.ux]) # Solve with mosek prob = mpbpy.QuadprogProblem(qp.P, qp.q, Amosek, lmosek, umosek) res = prob.solve(solver=mpbpy.MOSEK, verbose=False) niter[i] = res.total_iter time[i] = res.cputime elif solver == 'ecos': for i in range(n_prob): # Construct the problem # minimize x.T * x + gamma 1.T * t # subject to t >= diag(b) A x + 1 # t >= 0 n_var = qp.A_svm.shape[1] m_var = qp.A_svm.shape[0] x = cvxpy.Variable(n_var) t = cvxpy.Variable(m_var) objective = cvxpy.Minimize( cvxpy.quad_form(x, spa.eye(n_var)) + qp.gamma * np.ones(m_var) * t) constraints = [ t >= spa.diags(qp.b_svm).dot(qp.A_svm) * x + 1, t >= 0 ] problem = cvxpy.Problem(objective, constraints) problem.solve(solver=cvxpy.ECOS, verbose=False) # Obtain time and number of iterations time[i] = problem.solver_stats.setup_time + \ problem.solver_stats.solve_time niter[i] = problem.solver_stats.num_iters # # DEBUG: solve with mosek # Amosek = spa.vstack([ # qp.A, # spa.hstack([spa.csc_matrix((m, n)), spa.eye(m)]), # ]).tocsc() # lmosek = np.hstack([qp.l, qp.lx]) # umosek = np.hstack([qp.u, qp.ux]) # # # Solve with mosek # prob = mpbpy.QuadprogProblem(qp.P, qp.q, Amosek, lmosek, umosek) # res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # x_mosek = res.x[:n_var] # # import ipdb; ipdb.set_trace() else: raise ValueError('Solver not understood') # Return statistics return utils.Statistics(time), utils.Statistics(niter)
def solve(n_vec, m_vec, p_vec, repeat, dns_level, seed, solver='gurobi'): """ Solve random optimization problems """ print("Solving random problems with solver %s\n" % solver) # Define statistics to record std_solve_time = np.zeros(len(n_vec)) avg_solve_time = np.zeros(len(n_vec)) min_solve_time = np.zeros(len(n_vec)) max_solve_time = np.zeros(len(n_vec)) n_prob = len(n_vec) # Store also OSQP time if solver == 'miosqp': # Add OSQP solve times statistics avg_osqp_solve_time = np.zeros(len(n_vec)) # reset random seed np.random.seed(seed) for i in range(n_prob): # Get dimensions n = n_vec[i] m = m_vec[i] p = p_vec[i] print("problem n = %i, m = %i, p = %i" % (n, m, p)) # Define vector of cpu times solve_time_temp = np.zeros(repeat) # Store also OSQP time if solver == 'miosqp': osqp_solve_time_temp = np.zeros(repeat) for j in tqdm(range(repeat)): # for j in range(repeat): # Generate random vector of indeces i_idx = np.random.choice(np.arange(0, n), p, replace=False) # Generate random Matrices Pt = spa.random(n, n, density=dns_level) P = spa.csc_matrix(np.dot(Pt, Pt.T)) q = sp.randn(n) A = spa.random(m, n, density=dns_level) u = 2 + sp.rand(m) l = -2 + sp.rand(m) # Enforce [0, 1] bounds on variables i_l = np.zeros(p) i_u = np.ones(p) # A, l, u = miosqp.add_bounds(i_idx, 0., 1., A, l, u) if solver == 'gurobi': # Solve with gurobi prob = mpbpy.QuadprogProblem(P, q, A, l, u, i_idx, i_l, i_u) res_gurobi = prob.solve(solver=mpbpy.GUROBI, verbose=False, Threads=1) if res_gurobi.status != 'optimal': import ipdb ipdb.set_trace() solve_time_temp[j] = 1e3 * res_gurobi.cputime elif solver == 'miosqp': # Define problem settings miosqp_settings = { # integer feasibility tolerance 'eps_int_feas': 1e-03, # maximum number of iterations 'max_iter_bb': 1000, # tree exploration rule # [0] depth first # [1] two-phase: depth first until first incumbent and then best bound 'tree_explor_rule': 1, # branching rule # [0] max fractional part 'branching_rule': 0, 'verbose': False, 'print_interval': 1} osqp_settings = {'eps_abs': 1e-03, 'eps_rel': 1e-03, 'eps_prim_inf': 1e-04, 'verbose': False} model = miosqp.MIOSQP() model.setup(P, q, A, l, u, i_idx, i_l, i_u, miosqp_settings, osqp_settings) res_miosqp = model.solve() # DEBUG (check if solutions match) # prob = mpbpy.QuadprogProblem(P, q, A, l, u, i_idx, i_l, i_u) # res_gurobi = prob.solve(solver=mpbpy.GUROBI, verbose=False) # if (np.linalg.norm(res_gurobi.x - res_miosqp.x) / # np.linalg.norm(res_gurobi.x)) > 1e-02: # import ipdb; ipdb.set_trace() # # import ipdb; ipdb.set_trace() if res_miosqp.status != miosqp.MI_SOLVED: import ipdb ipdb.set_trace() # Solution time solve_time_temp[j] = 1e3 * res_miosqp.run_time # Store OSQP time in percentage if solver == 'miosqp': osqp_solve_time_temp[j] = \ 100 * (res_miosqp.osqp_solve_time / res_miosqp.run_time) # Get time statistics std_solve_time[i] = np.std(solve_time_temp) avg_solve_time[i] = np.mean(solve_time_temp) max_solve_time[i] = np.max(solve_time_temp) min_solve_time[i] = np.min(solve_time_temp) # Store also OSQP time if solver == 'miosqp': avg_osqp_solve_time[i] = np.mean(osqp_solve_time_temp) # Create pandas dataframe for the results df_dict = {'n': n_vec, 'm': m_vec, 'p': p_vec, 't_min': min_solve_time, 't_max': max_solve_time, 't_avg': avg_solve_time, 't_std': std_solve_time} # Store also OSQP time if solver == 'miosqp': df_dict.update({'t_osqp_avg': avg_osqp_solve_time}) timings = pd.DataFrame(df_dict) return timings
def compute_mpc_input(self, x0, u_prev, solver='gurobi'): """ Compute MPC input at initial state x0 with specified solver """ qp = self.qp_matrices N = qp.N # Update objective q = 2. * (qp.q_x.dot(x0) + qp.q_u) # Update bounds SA_tildex0 = qp.SA_tilde.dot(x0) qp.u[:6 * N] = SA_tildex0 # qp.l[:6 * N] = -SA_tildex0 if solver == 'gurobi': # Solve problem prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u, qp.i_idx, qp.i_l, qp.i_u, x0=u_prev) res_gurobi = prob.solve(solver=mpbpy.GUROBI, verbose=False, Threads=1) u = res_gurobi.x obj_val = res_gurobi.obj_val solve_time = res_gurobi.cputime elif solver == 'miosqp': if self.solver is None: # Define problem settings miosqp_settings = {'eps_int_feas': 1e-02, # integer feasibility tolerance 'max_iter_bb': 2000, # maximum number of iterations 'tree_explor_rule': 1, # tree exploration rule # [0] depth first # [1] two-phase: depth first until first incumbent and then best bound 'branching_rule': 0, # branching rule # [0] max fractional part 'verbose': False, 'print_interval': 1} osqp_settings = {'eps_abs': 1e-03, 'eps_rel': 1e-03, 'eps_prim_inf': 1e-04, # 'rho': 0.001, # 'rho': 0.1, 'verbose': False} self.solver = miosqp.MIOSQP() self.solver.setup(qp.P, q, qp.A, qp.l, qp.u, qp.i_idx, qp.i_l, qp.i_u, miosqp_settings, osqp_settings) else: self.solver.update_vectors(q, qp.l, qp.u) self.solver.set_x0(u_prev) res_miosqp = self.solver.solve() # import ipdb; ipdb.set_trace() # DEBUG Check if gurobi gives same solution # N.B. They do not match when the norm of the # difference of the objective functions # is below the tolerance # # prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u, qp.i_idx) # res_gurobi = prob.solve(solver=mpbpy.GUROBI, verbose=False, x0=u_prev) # if np.linalg.norm(res_miosqp.x - res_gurobi.x)> 1e-02: # print("Norm of difference of solution = %.4e" % \ # np.linalg.norm(res_miosqp.x - res_gurobi.x)) # import ipdb; ipdb.set_trace() if res_miosqp.status != miosqp.MI_SOLVED: import ipdb; ipdb.set_trace() u = res_miosqp.x obj_val = res_miosqp.upper_glob solve_time = res_miosqp.run_time osqp_solve_time = 100 * res_miosqp.osqp_solve_time / res_miosqp.run_time # Get first input u0 = u[:6] if solver == 'miosqp': return u0, obj_val, solve_time, u, \ osqp_solve_time, \ res_miosqp.osqp_iter_avg else: return u0, obj_val, solve_time, u, 0, 0
def solve_loop(qp_matrices, solver='osqp', osqp_settings=None): """ Solve lasso optimization loop for all lambdas """ # Shorter name for qp_matrices qp = qp_matrices # Extract features n = qp.n print('n = %d and solver %s' % (n, solver)) # Get number of problems to solve n_prob = qp.q.shape[1] # Initialize time vector time = np.zeros(n_prob) # Initialize number of iterations vector niter = np.zeros(n_prob) if solver == 'osqp': # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, 0], qp.A, qp.l, qp.u, **osqp_settings) for i in range(n_prob): q = qp.q[:, i] # Update linear cost m.update(q=q) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() elif solver == 'osqp_coldstart': # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, 0], qp.A, qp.l, qp.u, **osqp_settings) for i in range(n_prob): q = qp.q[:, i] # Update linear cost m.update(q=q) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() # DEBUG print iterations per value of lambda # lambda_vals = np.logspace(-2, 2, 101)[::-1] # # import matplotlib.pylab as plt # plt.figure() # ax = plt.gca() # plt.plot(lambda_vals, niter) # ax.set_xlabel(r'$\lambda$') # ax.set_ylabel(r'iter') # plt.show(block=False) # import ipdb; ipdb.set_trace() elif solver == 'osqp_no_caching': for i in range(n_prob): # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, i], qp.A, qp.l, qp.u, **osqp_settings) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() elif solver == 'qpoases': n_dim = qp.P.shape[0] # Number of variables m_dim = qp.A.shape[0] # Number of constraints without bounds # Initialize qpoases and set options qpoases_m = qpoases.PyQProblem(n_dim, m_dim) options = qpoases.PyOptions() options.printLevel = qpoases.PyPrintLevel.NONE qpoases_m.setOptions(options) # Setup matrix P and A P = np.ascontiguousarray(qp.P.todense()) A = np.ascontiguousarray(qp.A.todense()) for i in range(n_prob): # Get linera cost as contiguous array q = np.ascontiguousarray(qp.q[:, i]) # Reset cpu time qpoases_cpu_time = np.array([10.]) # Reset number of of working set recalculations nWSR = np.array([1000]) if i == 0: # First iteration res_qpoases = qpoases_m.init(P, q, A, np.ascontiguousarray(qp.lx), np.ascontiguousarray(qp.ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) else: # Solve new hot started problem res_qpoases = qpoases_m.hotstart(q, np.ascontiguousarray(qp.lx), np.ascontiguousarray(qp.ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) # # DEBUG Solve with gurobi # qpoases solution # sol_qpoases = np.zeros(n + k) # qpoases_m.getPrimalSolution(sol_qpoases) # import mathprogbasepy as mpbpy # Agrb = spa.vstack((qp.A, # spa.hstack((spa.eye(n), spa.csc_matrix((n, k))) # ))).tocsc() # lgrb = np.append(qp.l, qp.lx) # ugrb = np.append(qp.u, qp.ux) # prob = mpbpy.QuadprogProblem(spa.csc_matrix(qp.P), q, # Agrb, lgrb, ugrb) # res = prob.solve(solver=mpbpy.GUROBI, verbose=True) # print("Norm difference x qpoases - GUROBI = %.4f" % # np.linalg.norm(sol_qpoases - res.x)) # print("Norm difference objval qpoases - GUROBI = %.4f" % # abs(qpoases_m.getObjVal() - res.obj_val)) # import ipdb; ipdb.set_trace() # if res_qpoases != 0: # raise ValueError('qpoases did not solve the problem!') # Save time time[i] = qpoases_cpu_time[0] # Save number of iterations niter[i] = nWSR[0] elif solver == 'gurobi': for i in range(n_prob): # Get linera cost as contiguous array q = qp.q[:, i] # Solve with gurobi prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u) res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'mosek': for i in range(n_prob): # Get linera cost as contiguous array q = qp.q[:, i] # Solve with mosek prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u) res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'ecos': n_var = qp_matrices.A_lasso.shape[1] m_var = qp_matrices.A_lasso.shape[0] for i in range(n_prob): if n_var <= 60: # (problem becomes too big otherwise): # Model with CVXPY # minimize y' * y + lambda * 1' * t # subject to y = Ax - b # -t <= x <= t lambda_i = qp_matrices.lambdas[i] x = cvxpy.Variable(n_var) y = cvxpy.Variable(m_var) t = cvxpy.Variable(n_var) objective = cvxpy.Minimize( cvxpy.quad_form(y, spa.eye(m_var)) + lambda_i * np.ones(n_var) * t) constraints = [ y == qp_matrices.A_lasso * x - qp_matrices.b_lasso, -t <= x, x <= t ] problem = cvxpy.Problem(objective, constraints) problem.solve(solver=cvxpy.ECOS, verbose=False) # DEBUG: Solve with MOSEK q = qp.q[:, i] # Solve with mosek # prob = mpbpy.QuadprogProblem(qp.P, q, qp.A, qp.l, qp.u) # res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # x_mosek = res.x[:n_var] # import ipdb; ipdb.set_trace() # Obtain time and number of iterations time[i] = problem.solver_stats.setup_time + \ problem.solver_stats.solve_time niter[i] = problem.solver_stats.num_iters else: time[i] = 0 niter[i] = 0 else: raise ValueError('Solver not understood') # Return statistics return utils.Statistics(time), utils.Statistics(niter)
# Test rho = 0.1 osqp_opts = {'rho': rho, 'adaptive_rho': True, 'adaptive_rho_interval': 25, 'sigma': 1e-06, 'scaled_termination': False, 'check_termination': 1, 'polish': False, 'verbose': True, 'linsys_solver': 'suitesparse ldl' } qp = mpbpy.QuadprogProblem(P, q, A, l, u) res_gurobi = qp.solve(solver=mpbpy.GUROBI, verbose=True) model = osqppurepy.OSQP() model.setup(P=P, q=q, A=A, l=l, u=u, **osqp_opts) res_osqppurepy = model.solve() # Solve with SuiteSparse LDL model = osqp.OSQP() model.setup(P=P, q=q, A=A, l=l, u=u, **osqp_opts) res_osqp = model.solve() # Check difference with gurobi if res_gurobi.status == 'optimal': print("Difference OSQP vs Gurobi")
def main(): sp.random.seed(1) # Possible ops: {'small1', 'small2', 'random', # 'primal_infeasible', 'random_primal_infeasible', # 'maros_meszaros', 'lp', 'dual_infeasible_lp', # 'dual_infeasible_qp'} example = 'random_primal_infeasible' if example == 'maros_meszaros': # Maros Meszaros Examples # f = 'tests/maros_meszaros/CVXQP2_S.mat' # f = 'tests/maros_meszaros/CVXQP1_S.mat' # f = 'tests/maros_meszaros/AUG2D.mat' f = 'maros_meszaros/CONT-200.mat' # f = 'tests/maros_meszaros/PRIMAL3.mat' # f = 'tests/maros_meszaros/QBANDM.mat' p = load_maros_meszaros_problem(f) elif example == 'small1': # Our Examples # Small Example 1 P = spspa.csc_matrix(np.array([[4., 1.], [1., 2.]])) q = np.ones(2) A = spspa.vstack( [spspa.csc_matrix(np.ones((1, 2))), spspa.eye(P.shape[0])]).tocsc() l = np.array([1.0, 0.0, 0.0]) u = np.array([1.0, 0.7, 0.7]) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'small2': # Small Example 2 P = spspa.csc_matrix(np.array([[11., 0.], [0., 0.]])) q = np.array([3, 4]) A = spspa.csc_matrix( np.array([[-1, 0], [0, -1], [-1, -3], [2, 5], [3, 4]])) u = np.array([0., 0., -15, 100, 80]) l = -np.inf * np.ones(len(u)) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'primal_infeasible': # primal_infeasible example # P = spspa.eye(2) P = spspa.csc_matrix((2, 2)) q = np.ones(2) A = spspa.csc_matrix(np.array([[1, 0], [0, 1], [1, 1]])) l = np.array([0., 0., -1.]) u = np.array([np.inf, np.inf, -1.]) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'random_primal_infeasible': # Random Example n = 50 m = 500 # Generate random Matrices Pt = sp.randn(n, n) P = spspa.csc_matrix(np.dot(Pt.T, Pt)) q = sp.randn(n) A = spspa.csc_matrix(sp.randn(m, n)) u = 3 + sp.randn(m) # l = u l = -3 + sp.randn(m) # Make random problem primal_infeasible A[int(n / 2), :] = A[int(n / 2) + 1, :] l[int(n / 2)] = u[int(n / 2) + 1] + 100 * sp.rand() u[int(n / 2)] = l[int(n / 2)] + 0.5 # l[int(n/3)] = u[int(n/3)] + 100 * sp.rand() # l[int(n/4)] = u[int(n/4)] + 50. * sp.rand() p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'dual_infeasible_lp': # Dual infeasible example P = spspa.csc_matrix((2, 2)) q = np.array([2, -1]) A = spspa.eye(2) l = np.array([0., 0.]) u = np.array([np.inf, np.inf]) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'dual_infeasible_qp': # Dual infeasible example P = spspa.csc_matrix(np.diag(np.array([4., 0.]))) q = np.array([0, 2]) A = spspa.csc_matrix([[1., 1.], [-1., 1.]]) l = np.array([-np.inf, -np.inf]) u = np.array([2., 3.]) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'random': # Random Example n = 30 m = 50 # Generate random Matrices Pt = sp.randn(n, n) P = spspa.csc_matrix(np.dot(Pt.T, Pt)) q = sp.randn(n) A = spspa.csc_matrix(sp.randn(m, n)) u = 3 + sp.randn(m) # l = u l = -3 + sp.randn(m) p = mpbpy.QuadprogProblem(P, q, A, l, u) elif example == 'lp': # Random Example n = 10 m = 1000 # Generate random Matrices P = spspa.csc_matrix(np.zeros((n, n))) q = sp.randn(n) A = spspa.vstack([spspa.csc_matrix(sp.randn(m, n)), spspa.eye(n)]) l = np.append(-3 + sp.randn(m), -3 + sp.randn(n)) u = np.append(3 + sp.randn(m), 3 + sp.randn(n)) p = mpbpy.QuadprogProblem(P, q, A, l, u) else: assert False, "Unknown example" # Solve with CPLEX # print("\nSolve with CPLEX") # print("-----------------") # resultsCPLEX = p.solve(solver=mpbpy.CPLEX, verbose=True) # Solve with GUROBI print("\nSolve with GUROBI") print("-----------------") resultsGUROBI = p.solve(solver=mpbpy.GUROBI, OutputFlag=1) # Solve with OSQP. You can pass options to OSQP solver print("\nSolve with OSQP") print("-----------------") resultsOSQP = p.solve( solver=mpbpy.OSQP, max_iter=5000, # eps_rel=1e-3, # eps_abs=1e-3, # alpha=1.6, # rho=0.00001, # Works with LP check_termination=1, # sigma=1e-3, polish=True, verbose=True) import ipdb ipdb.set_trace() if resultsGUROBI.status in mpbpy_prob.SOLUTION_PRESENT: # print("\n") # print("Comparison CPLEX - GUROBI") # print("-------------------------") # print("Difference in objective value %.8f" % # np.linalg.norm(resultsCPLEX.objval - resultsGUROBI.objval)) # print("Norm of solution difference %.8f" % # np.linalg.norm(resultsCPLEX.x - resultsGUROBI.x)) # print("Norm of dual difference %.8f" % # np.linalg.norm(resultsCPLEX.y - resultsGUROBI.y)) print("\n") print("Comparison OSQP - GUROBI") print("-------------------------") print("Difference in objective value %.8f" % np.linalg.norm(resultsOSQP.obj_val - resultsGUROBI.obj_val)) print("Norm of solution difference %.8f" % np.linalg.norm(resultsOSQP.x - resultsGUROBI.x)) print("Norm of dual difference %.8f" % np.linalg.norm(resultsOSQP.y - resultsGUROBI.y))
import pickle # Load one problem with open('./data/%s.pickle' % 'helicopter_scaling_small', 'rb') as f: problem = pickle.load(f) # OSQP settings osqp_settings = { 'verbose': True, 'scaling': True, 'scaling_iter': 50, 'early_terminate_interval': 1, 'auto_rho': True, 'rho': 0.1, 'polish': False } # Solve with OSQP model = osqp.OSQP() model.setup(problem['P'], problem['q'], problem['A'], problem['l'], problem['u'], **osqp_settings) res_osqp = model.solve() # Solve with GUROBI import mathprogbasepy as mpbpy qp = mpbpy.QuadprogProblem(problem['P'], problem['q'], problem['A'], problem['l'], problem['u']) res_gurobi = qp.solve(solver=mpbpy.GUROBI, verbose=False) print("GUROBI time = %.4e" % res_gurobi.cputime) print("OSQP time = %.4e" % res_osqp.info.run_time)
def solve_loop(qp_matrices, problem, nsim, solver='osqp'): """ Solve MPC loop """ # Shorter name for qp_matrices qp = qp_matrices # Get dimensions (nx, nu) = problem.B.shape N = problem.N print('N = %d and solver %s' % (N, solver)) # Initialize time and number of iterations vectors time = np.zeros(nsim) niter = np.zeros(nsim) if solver == 'osqp': # Construct qp matrices if len(problem.xmin) > 0: # If the problem has state constraints Aosqp = spa.vstack([ qp.A, spa.eye((N + 1) * nx + N * nu), ]).tocsc() else: Aosqp = spa.vstack([ qp.A, spa.hstack( [spa.csc_matrix((N * nu, (N + 1) * nx)), spa.eye(N * nu)]), ]).tocsc() losqp = np.hstack([qp.l, qp.lx]) uosqp = np.hstack([qp.u, qp.ux]) # Initial state x0 = problem.x0 # Setup OSQP m = osqp.OSQP() m.setup( qp.P, qp.q, Aosqp, losqp, uosqp, # auto_rho=False, auto_rho=True, max_iter=2500, scaling=True, scaling_iter=50, polish=False, verbose=False) for i in range(nsim): # Solve with osqp res = m.solve() # Save time and number of iterations time[i] = res.info.run_time niter[i] = res.info.iter # Check if status is correct status = res.info.status_val if status != m.constant('OSQP_SOLVED'): # # Dump file to 'bad_convergence/data'folder # import pickle # problem = {'P': qp.P, # 'q': qp.q, # 'A': Aosqp, # 'l': losqp, # 'u': uosqp} # with open('bad_convergence/data/%s.pickle' % 'helicopter_scaling_large', 'wb') as f: # pickle.dump(problem, f) import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # Apply first control input to the plant u = res.x[-N * nu:-(N - 1) * nu] x0 = problem.A.dot(x0) + problem.B.dot(u) # Update linear constraints if len(problem.tmin) > 0: losqp = np.hstack([b(x0, nx, N), problem.tmin, qp.lx]) uosqp = np.hstack([b(x0, nx, N), problem.tmax, qp.ux]) else: losqp = np.hstack([b(x0, nx, N), qp.lx]) uosqp = np.hstack([b(x0, nx, N), qp.ux]) m.update(l=losqp, u=uosqp) elif solver == 'osqp_coldstart': # Construct qp matrices if len(problem.xmin) > 0: # If the problem has state constraints Aosqp = spa.vstack([ qp.A, spa.eye((N + 1) * nx + N * nu), ]).tocsc() else: Aosqp = spa.vstack([ qp.A, spa.hstack( [spa.csc_matrix((N * nu, (N + 1) * nx)), spa.eye(N * nu)]), ]).tocsc() losqp = np.hstack([qp.l, qp.lx]) uosqp = np.hstack([qp.u, qp.ux]) # Initial state x0 = problem.x0 # Setup OSQP m = osqp.OSQP() m.setup( qp.P, qp.q, Aosqp, losqp, uosqp, warm_start=False, auto_rho=True, # auto_rho=False, rho=0.1, max_iter=2500, scaling_iter=50, polish=False, verbose=False) for i in range(nsim): # Solve with osqp res = m.solve() # Save time and number of iterations time[i] = res.info.run_time niter[i] = res.info.iter # Check if status is correct status = res.info.status_val if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # Apply first control input to the plant u = res.x[-N * nu:-(N - 1) * nu] x0 = problem.A.dot(x0) + problem.B.dot(u) # Update linear constraints if len(problem.tmin) > 0: losqp = np.hstack([b(x0, nx, N), problem.tmin, qp.lx]) uosqp = np.hstack([b(x0, nx, N), problem.tmax, qp.ux]) else: losqp = np.hstack([b(x0, nx, N), qp.lx]) uosqp = np.hstack([b(x0, nx, N), qp.ux]) m.update(l=losqp, u=uosqp) elif solver == 'osqp_no_caching': # Construct qp matrices if len(problem.xmin) > 0: # If the problem has state constraints Aosqp = spa.vstack([ qp.A, spa.eye((N + 1) * nx + N * nu), ]).tocsc() else: Aosqp = spa.vstack([ qp.A, spa.hstack( [spa.csc_matrix((N * nu, (N + 1) * nx)), spa.eye(N * nu)]), ]).tocsc() losqp = np.hstack([qp.l, qp.lx]) uosqp = np.hstack([qp.u, qp.ux]) # Initial state x0 = problem.x0 for i in range(nsim): # Setup OSQP m = osqp.OSQP() m.setup( qp.P, qp.q, Aosqp, losqp, uosqp, warm_start=False, auto_rho=True, # auto_rho=False, rho=0.1, max_iter=2500, scaling_iter=50, polish=False, verbose=False) # Solve res = m.solve() # Save time and number of iterations time[i] = res.info.run_time niter[i] = res.info.iter # Check if status is correct status = res.info.status_val if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # Apply first control input to the plant u = res.x[-N * nu:-(N - 1) * nu] x0 = problem.A.dot(x0) + problem.B.dot(u) # Update linear constraints if len(problem.tmin) > 0: losqp = np.hstack([b(x0, nx, N), problem.tmin, qp.lx]) uosqp = np.hstack([b(x0, nx, N), problem.tmax, qp.ux]) else: losqp = np.hstack([b(x0, nx, N), qp.lx]) uosqp = np.hstack([b(x0, nx, N), qp.ux]) m.update(l=losqp, u=uosqp) elif solver == 'qpoases': n_dim = qp.P.shape[0] # Number of variables m_dim = qp.A.shape[0] # Number of constraints without bounds # Initialize qpoases and set options qpoases_m = qpoases.PyQProblem(n_dim, m_dim) options = qpoases.PyOptions() options.printLevel = qpoases.PyPrintLevel.NONE qpoases_m.setOptions(options) # Construct bounds for qpoases lx = np.append(-np.inf * np.ones((N + 1) * nx), qp.lx) ux = np.append(np.inf * np.ones((N + 1) * nx), qp.ux) # Setup matrix P and A P = np.ascontiguousarray(qp.P.todense()) A = np.ascontiguousarray(qp.A.todense()) # Initial state x0 = problem.x0 # RHS of the linear equality constraints lqpoases = qp.l uqpoases = qp.u for i in range(nsim): # Reset cpu time qpoases_cpu_time = np.array([60.]) # Reset number of of working set recalculations nWSR = np.array([1e6]) if i == 0: # First iteration res_qpoases = qpoases_m.init(P, np.ascontiguousarray(qp.q), A, np.ascontiguousarray(lx), np.ascontiguousarray(ux), np.ascontiguousarray(lqpoases), np.ascontiguousarray(uqpoases), nWSR, qpoases_cpu_time) else: # Solve new hot started problem res_qpoases = qpoases_m.hotstart( np.ascontiguousarray(qp.q), np.ascontiguousarray(lx), np.ascontiguousarray(ux), np.ascontiguousarray(lqpoases), np.ascontiguousarray(uqpoases), nWSR, qpoases_cpu_time) if res_qpoases != 0: raise ValueError('qpoases did not solve the problem!') # Save time and number of iterations time[i] = qpoases_cpu_time[0] niter[i] = nWSR[0] # Get qpoases solution sol_qpoases = np.zeros((N + 1) * nx + N * nu) qpoases_m.getPrimalSolution(sol_qpoases) # Apply first control input to the plant u = sol_qpoases[-N * nu:-(N - 1) * nu] x0 = problem.A.dot(x0) + problem.B.dot(u) # Update linear constraints if len(problem.tmin) > 0: lqpoases = np.hstack([b(x0, nx, N), problem.tmin]) uqpoases = np.hstack([b(x0, nx, N), problem.tmax]) else: lqpoases = np.hstack([b(x0, nx, N)]) uqpoases = np.hstack([b(x0, nx, N)]) elif solver == 'gurobi' or solver == 'mosek': # Construct qp matrices if len(problem.xmin) > 0: # If the problem has state constraints Agurobi = spa.vstack([ qp.A, spa.eye((N + 1) * nx + N * nu), ]).tocsc() else: Agurobi = spa.vstack([ qp.A, spa.hstack( [spa.csc_matrix((N * nu, (N + 1) * nx)), spa.eye(N * nu)]), ]).tocsc() lgurobi = np.hstack([qp.l, qp.lx]) ugurobi = np.hstack([qp.u, qp.ux]) # Initial state x0 = problem.x0 for i in range(nsim): # Solve with gurobi prob = mpbpy.QuadprogProblem(qp.P, qp.q, Agurobi, lgurobi, ugurobi) if solver == 'gurobi': res = prob.solve(solver=mpbpy.GUROBI, verbose=False) else: res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # Save time and number of iterations time[i] = res.cputime niter[i] = res.total_iter # Check if status is correct status = res.status if status != 'optimal': import ipdb ipdb.set_trace() raise ValueError('Gurobi did not solve the problem!') # Apply first control input to the plant u = res.x[-N * nu:-(N - 1) * nu] x0 = problem.A.dot(x0) + problem.B.dot(u) # Update QP problem if len(problem.tmin) > 0: lgurobi = np.hstack([b(x0, nx, N), problem.tmin, qp.lx]) ugurobi = np.hstack([b(x0, nx, N), problem.tmax, qp.ux]) else: lgurobi = np.hstack([b(x0, nx, N), qp.lx]) ugurobi = np.hstack([b(x0, nx, N), qp.ux]) else: raise ValueError('Solver not understood') # Return statistics return utils.Statistics(time), utils.Statistics(niter)
import numpy as np import mathprogbasepy as mpbpy sp.random.seed(2) n = 100 m = 500 A = sparse.random(m, n, density=0.9, format='csc') lA = -sp.rand(m) * 2. uA = sp.rand(m) * 2. P = sparse.random(n, n, density=0.9, format='csc') P = P.dot(P.T) q = sp.randn(n) qp = mpbpy.QuadprogProblem(P, q, A, lA, uA) osqp_opts = {'rho': 1e-7, 'auto_rho': True, 'sigma': 1e-06, # 'eps_rel': 1e-08, # 'eps_abs': 1e-08, 'scaled_termination': False, 'early_terminate_interval': 1, 'polish': False, 'scaling': True, 'scaling_iter': 15, 'max_iter': 2500, 'verbose': True }
def solve_loop(qp_matrices, solver='osqp'): """ Solve portfolio optimization loop for all gammas """ # Shorter name for qp_matrices qp = qp_matrices # Get dimensions n = len(qp.lx) k = len(qp.l) - 1 print('n = %d and solver %s' % (n, solver)) # Get number of problems to solve n_prob = qp.q.shape[1] # Initialize time vector time = np.zeros(n_prob) # Initialize number of iterations vector niter = np.zeros(n_prob) if solver == 'osqp': # Construct qp matrices Aosqp = spa.vstack( (qp.A, spa.hstack((spa.eye(n), spa.csc_matrix((n, k)))))).tocsc() losqp = np.append(qp.l, qp.lx) uosqp = np.append(qp.u, qp.ux) # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, 0], Aosqp, losqp, uosqp, auto_rho=True, polish=False, verbose=False) for i in range(n_prob): q = qp.q[:, i] # Update linear cost m.update(q=q) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() elif solver == 'osqp_coldstart': # Construct qp matrices Aosqp = spa.vstack( (qp.A, spa.hstack((spa.eye(n), spa.csc_matrix((n, k)))))).tocsc() losqp = np.append(qp.l, qp.lx) uosqp = np.append(qp.u, qp.ux) # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, 0], Aosqp, losqp, uosqp, warm_start=False, auto_rho=True, polish=False, verbose=False) for i in range(n_prob): q = qp.q[:, i] # Update linear cost m.update(q=q) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() # DEBUG print iterations per value of gamma # gamma_vals = np.logspace(-2, 2, 101)[::-1] # # import matplotlib.pylab as plt # plt.figure() # ax = plt.gca() # plt.plot(gamma_vals, niter) # ax.set_xlabel(r'$\gamma$') # ax.set_ylabel(r'iter') # plt.show(block=False) # import ipdb; ipdb.set_trace() elif solver == 'osqp_no_caching': # Construct qp matrices Aosqp = spa.vstack( (qp.A, spa.hstack((spa.eye(n), spa.csc_matrix((n, k)))))).tocsc() losqp = np.append(qp.l, qp.lx) uosqp = np.append(qp.u, qp.ux) for i in range(n_prob): # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q[:, i], Aosqp, losqp, uosqp, warm_start=False, auto_rho=True, polish=False, verbose=False) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb ipdb.set_trace() raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() # DEBUG print iterations per value of gamma # gamma_vals = np.logspace(-2, 2, 101)[::-1] # # import matplotlib.pylab as plt # plt.figure() # ax = plt.gca() # plt.plot(gamma_vals, niter) # ax.set_xlabel(r'$\gamma$') # ax.set_ylabel(r'iter') # plt.show(block=False) # import ipdb; ipdb.set_trace() elif solver == 'qpoases': n_dim = qp.P.shape[0] # Number of variables m_dim = qp.A.shape[0] # Number of constraints without bounds # Initialize qpoases and set options qpoases_m = qpoases.PyQProblem(n_dim, m_dim) options = qpoases.PyOptions() options.printLevel = qpoases.PyPrintLevel.NONE qpoases_m.setOptions(options) # Construct bounds for qpoases lx = np.append(qp.lx, -np.inf * np.ones(k)) ux = np.append(qp.ux, np.inf * np.ones(k)) # Setup matrix P and A P = np.ascontiguousarray(qp.P.todense()) A = np.ascontiguousarray(qp.A.todense()) for i in range(n_prob): # Get linera cost as contiguous array q = np.ascontiguousarray(qp.q[:, i]) # Reset cpu time qpoases_cpu_time = np.array([20.]) # Reset number of of working set recalculations nWSR = np.array([1000]) if i == 0: # First iteration res_qpoases = qpoases_m.init(P, q, A, np.ascontiguousarray(lx), np.ascontiguousarray(ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) else: # Solve new hot started problem res_qpoases = qpoases_m.hotstart(q, np.ascontiguousarray(lx), np.ascontiguousarray(ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) # # DEBUG Solve with gurobi # qpoases solution # sol_qpoases = np.zeros(n + k) # qpoases_m.getPrimalSolution(sol_qpoases) # import mathprogbasepy as mpbpy # Agrb = spa.vstack((qp.A, # spa.hstack((spa.eye(n), spa.csc_matrix((n, k))) # ))).tocsc() # lgrb = np.append(qp.l, qp.lx) # ugrb = np.append(qp.u, qp.ux) # prob = mpbpy.QuadprogProblem(spa.csc_matrix(qp.P), q, # Agrb, lgrb, ugrb) # res = prob.solve(solver=mpbpy.GUROBI, verbose=True) # print("Norm difference x qpoases - GUROBI = %.4f" % # np.linalg.norm(sol_qpoases - res.x)) # print("Norm difference objval qpoases - GUROBI = %.4f" % # abs(qpoases_m.getObjVal() - res.obj_val)) # import ipdb; ipdb.set_trace() if res_qpoases != 0: raise ValueError('qpoases did not solve the problem!') # Save time time[i] = qpoases_cpu_time[0] # Save number of iterations niter[i] = nWSR[0] elif solver == 'gurobi': # Construct qp matrices Agurobi = spa.vstack( (qp.A, spa.hstack((spa.eye(n), spa.csc_matrix((n, k)))))).tocsc() lgurobi = np.append(qp.l, qp.lx) ugurobi = np.append(qp.u, qp.ux) for i in range(n_prob): # Get linera cost as contiguous array q = qp.q[:, i] # Solve with gurobi prob = mpbpy.QuadprogProblem(qp.P, q, Agurobi, lgurobi, ugurobi) res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'mosek': # Construct qp matrices Amosek = spa.vstack( (qp.A, spa.hstack((spa.eye(n), spa.csc_matrix((n, k)))))).tocsc() lmosek = np.append(qp.l, qp.lx) umosek = np.append(qp.u, qp.ux) for i in range(n_prob): # Get linera cost as contiguous array q = qp.q[:, i] # Solve with mosek prob = mpbpy.QuadprogProblem(qp.P, q, Amosek, lmosek, umosek) res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'ecos': for i in range(n_prob): # Construct the problem # minimize x' D x + y' I y - (1/gamma) * mu' x # subject to 1' x = 1 # F' x = y # 0 <= x <= 1 n_var = qp.F.shape[0] m_var = qp.F.shape[1] x = cvxpy.Variable(n_var) y = cvxpy.Variable(m_var) objective = cvxpy.Minimize( cvxpy.quad_form(x, qp.D) + cvxpy.quad_form(y, spa.eye(m_var)) + -1 / qp.gammas[i] * qp.mu * x) constraints = [ np.ones(n_var) * x == 1, qp.F.T * x == y, 0 <= x, x <= 1 ] problem = cvxpy.Problem(objective, constraints) problem.solve(solver=cvxpy.ECOS, verbose=False) # Obtain time and number of iterations time[i] = problem.solver_stats.setup_time + \ problem.solver_stats.solve_time niter[i] = problem.solver_stats.num_iters # # DEBUG: Solve with MOSEK # Amosek = spa.vstack((qp.A, # spa.hstack((spa.eye(n), spa.csc_matrix((n, k))) # ))).tocsc() # lmosek = np.append(qp.l, qp.lx) # umosek = np.append(qp.u, qp.ux) # prob = mpbpy.QuadprogProblem(qp.P, qp.q[:, i], # Amosek, lmosek, umosek) # res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # x_mosek = res.x[:n_var] # import ipdb; ipdb.set_trace() else: raise ValueError('Solver not understood') # Return statistics return utils.Statistics(time), utils.Statistics(niter)
def solve_problem(qp_matrices, n_prob, solver='osqp'): """ Solve equality constrained optimization """ # Shorter name for qp_matrices qp = qp_matrices # Get dimensions n = len(qp.q) m = len(qp.l) print('n = %d and solver %s' % (n, solver)) # Initialize time vector time = np.zeros(n_prob) # Initialize number of iterations vector niter = np.zeros(n_prob) if solver == 'osqp': for i in range(n_prob): # Setup OSQP m = osqp.OSQP() m.setup(qp.P, qp.q, qp.A, qp.l, qp.u, rho=1000, # Set high rho to enforce feasibility auto_rho=False, polish=False, verbose=False) # Solve results = m.solve() x = results.x y = results.y status = results.info.status_val niter[i] = results.info.iter time[i] = results.info.run_time # Check if status correct if status != m.constant('OSQP_SOLVED'): import ipdb; ipdb.set_trace() # raise ValueError('OSQP did not solve the problem!') # DEBUG # solve with gurobi # prob = mpbpy.QuadprogProblem(qp.P, q, Aosqp, losqp, uosqp) # res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # print('Norm difference OSQP-GUROBI %.3e' % # np.linalg.norm(x - res.x)) # import ipdb; ipdb.set_trace() elif solver == 'qpoases': n_dim = qp.P.shape[0] # Number of variables m_dim = qp.A.shape[0] # Number of constraints without bounds for i in range(n_prob): # Initialize qpoases and set options qpoases_m = qpoases.PyQProblem(n_dim, m_dim) options = qpoases.PyOptions() options.printLevel = qpoases.PyPrintLevel.NONE qpoases_m.setOptions(options) # Reset cpu time qpoases_cpu_time = np.array([60.]) # Reset number of of working set recalculations nWSR = np.array([10000]) # First iteration res_qpoases = qpoases_m.init(np.ascontiguousarray(qp.P.todense()), np.ascontiguousarray(qp.q), np.ascontiguousarray(qp.A.todense()), np.ascontiguousarray(qp.lx), np.ascontiguousarray(qp.ux), np.ascontiguousarray(qp.l), np.ascontiguousarray(qp.u), nWSR, qpoases_cpu_time) # # DEBUG Solve with gurobi # qpoases solution # sol_qpoases = np.zeros(n + k) # qpoases_m.getPrimalSolution(sol_qpoases) # import mathprogbasepy as mpbpy # Agrb = spa.vstack((qp.A, # spa.hstack((spa.eye(n), spa.csc_matrix((n, k))) # ))).tocsc() # lgrb = np.append(qp.l, qp.lx) # ugrb = np.append(qp.u, qp.ux) # prob = mpbpy.QuadprogProblem(spa.csc_matrix(qp.P), q, # Agrb, lgrb, ugrb) # res = prob.solve(solver=mpbpy.GUROBI, verbose=True) # print("Norm difference x qpoases - GUROBI = %.4f" % # np.linalg.norm(sol_qpoases - res.x)) # print("Norm difference objval qpoases - GUROBI = %.4f" % # abs(qpoases_m.getObjVal() - res.obj_val)) # import ipdb; ipdb.set_trace() if res_qpoases != 0: raise ValueError('qpoases did not solve the problem!') # Save time time[i] = qpoases_cpu_time[0] # Save number of iterations niter[i] = nWSR[0] elif solver == 'gurobi': for i in range(n_prob): # Solve with gurobi prob = mpbpy.QuadprogProblem(qp.P, qp.q, qp.A, qp.l, qp.u) res = prob.solve(solver=mpbpy.GUROBI, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'mosek': for i in range(n_prob): # Solve with mosek prob = mpbpy.QuadprogProblem(qp.P, qp.q, qp.A, qp.l, qp.u) res = prob.solve(solver=mpbpy.MOSEK, verbose=False) # Save time time[i] = res.cputime # Save number of iterations niter[i] = res.total_iter elif solver == 'ecos': for i in range(n_prob): # Solve with ECOS (via CVXPY) n_var = qp.P.shape[0] x_var = cvxpy.Variable(n_var) objective = cvxpy.Minimize(.5 * cvxpy.quad_form(x_var, qp.P) + qp.q * x_var) constraints = [qp.A * x_var <= qp.u, qp.A * x_var >= qp.l] problem = cvxpy.Problem(objective, constraints) problem.solve(solver=cvxpy.ECOS) # Obtain time and number of iterations time[i] = problem.solver_stats.setup_time + \ problem.solver_stats.solve_time niter[i] = problem.solver_stats.num_iters else: raise ValueError('Solver not understood') # Return statistics return utils.Statistics(time), utils.Statistics(niter)