diff --git a/Project.toml b/Project.toml index b2c7d69..693701a 100644 --- a/Project.toml +++ b/Project.toml @@ -22,8 +22,11 @@ julia = "1" [extras] Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" + Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Compat", "Random"] +test = ["Test", "Compat", "Random", "FileIO", "JLD2"] diff --git a/test/polishing.jl b/test/polishing.jl index 919f469..e6ba8ef 100644 --- a/test/polishing.jl +++ b/test/polishing.jl @@ -72,53 +72,20 @@ tol = 1e-3 @test results.info.status_polish == 1 end - @testset "polish_random" begin - seed!(1) - n = 30 - m = 50 - Pt = sprandn(n, n, 0.5) - P = Pt * Pt' - q = randn(n) - A = sprandn(m, n, 0.5) - l = -3 .+ randn(m) - u = 3 .+ randn(m) - - # Solve problem + # load randomly generated problem with known accurate solution from Mosek + problem_data = FileIO.load("./problem_data/random_polish_qp.jld2"); + P = problem_data["P"]; q = problem_data["q"]; A = problem_data["A"]; u = problem_data["u"]; l = problem_data["l"]; options = setup_polishing() model = OSQP.Model() OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) results = OSQP.solve!(model) - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println(x_test) - # println(y_test) - # println(obj_test) - - x_test = [0.369834, -0.0209277, 0.068939, -0.604151, 0.60773, -0.715965, -0.128837, -0.593642, 0.928932, 0.678794, 0.194334, 0.228124, 0.188779, 0.607246, 0.479752, 0.0878951, 0.275489, 0.761593, 0.0600479, -0.950663, -0.191354, 1.12286, -0.593261, -0.0932879, 0.0286826, -0.0257784, 0.358456, -0.0693514, -0.00358498, -0.0270959] - y_test = [4.88779e-14, 0.441478, 5.89704e-14, 1.76439e-13, 8.10529e-15, 4.9186e-14, 5.00637e-14, 2.00889e-14, 5.39402e-13, -1.9796e-14, 1.52041e-13, 0.149979, 8.97844e-12, 5.93941e-14, -4.11719e-14, -2.38358e-13, 0.226114, -1.8933e-14, 1.54839e-13, 2.99422e-14, 7.16687e-15, -5.32536e-14, 0.116129, -2.53245e-14, 1.21586e-14, -1.66761e-13, 3.04905e-14, 7.35909e-14, 3.84878e-12, -3.09855e-15, 4.30889e-9, 4.09921e-14, -2.4863e-14, -2.46841e-14, 4.37156e-15, 0.219029, -5.14155e-14, 8.31705e-14, 4.51252e-15, -7.90941e-14, 0.206435, -0.196264, 1.06762e-14, 0.338783, 7.58781e-10, -0.105739, 3.30014e-13, -4.05467e-14, 3.3212e-14, -0.161755] - - obj_test = -6.021607803961248 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test isapprox(results.x, problem_data["x_test"], atol=tol) + @test isapprox(results.y, problem_data["y_test"], atol=tol) + @test isapprox(results.info.obj_val, problem_data["obj_test"], atol=tol) @test results.info.status_polish == 1 end diff --git a/test/problem_data/random_polish_qp.jld2 b/test/problem_data/random_polish_qp.jld2 new file mode 100644 index 0000000..64451f7 Binary files /dev/null and b/test/problem_data/random_polish_qp.jld2 differ diff --git a/test/runtests.jl b/test/runtests.jl index 0b3850f..a74b1ed 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using OSQP using Test, SparseArrays, LinearAlgebra using Random: seed! - +using FileIO tests = [ "basic.jl", "dual_infeasibility.jl", diff --git a/test/update_matrices.jl b/test/update_matrices.jl index ad0d90b..d170d1e 100644 --- a/test/update_matrices.jl +++ b/test/update_matrices.jl @@ -49,425 +49,430 @@ end tol = 1e-5 -@testset "update_matrices" begin - - @testset "solve" begin - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - - - x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] - y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] - obj_test = -0.6736977821770016 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - - - end - - - @testset "update_P" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrix - Pnew_triu = triu(P_new) - Pnew_triu_idx = collect(1 : length(Pnew_triu.nzval)) - OSQP.update!(model, Px=Pnew_triu.nzval, Px_idx=Pnew_triu_idx) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - - x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] - y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] - obj_test = -0.6736977821770016 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_P_allind" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrix - Pnew_triu = triu(P_new) - OSQP.update!(model, Px=Pnew_triu.nzval) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - - x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] - y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] - obj_test = -0.6736977821770016 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_A" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrix - A_new_idx = collect(1 : length(A_new.nzval)) - OSQP.update!(model, Ax=A_new.nzval, Ax_idx=A_new_idx) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_A_allind" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrix - OSQP.update!(model, Ax=A_new.nzval) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_P_A_indP_indA" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrices P and A - P_new_triu = triu(P_new) - P_new_triu_idx = collect(1 : length(P_new_triu.nzval)) - A_new_idx = collect(1 : length(A_new.nzval)) - - OSQP.update!(model, Px=P_new_triu.nzval, Px_idx=P_new_triu_idx, - Ax=A_new.nzval, Ax_idx=A_new_idx) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_P_A_indP" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrices P and A - P_new_triu = triu(P_new) - P_new_triu_idx = collect(1 : length(P_new_triu.nzval)) - - OSQP.update!(model, Px=P_new_triu.nzval, Px_idx=P_new_triu_idx, - Ax=A_new.nzval) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_P_A_indA" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrices P and A - P_new_triu = triu(P_new) - A_new_idx = collect(1 : length(A_new.nzval)) - - OSQP.update!(model, Px=P_new_triu.nzval, - Ax=A_new.nzval, Ax_idx=A_new_idx) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - - @testset "update_P_A_allind" begin - - problem, options = setup_update_matrices() - - (n, m, P, q, A, l, u) = (problem[:n], problem[:m], - problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) - P_new = problem[:P_new] - A_new = problem[:A_new] - - model = OSQP.Model() - OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) - - # Update matrices P and A - P_new_triu = triu(P_new) - - OSQP.update!(model, Px=P_new_triu.nzval, Ax=A_new.nzval) - results = OSQP.solve!(model) - - # # Solve with Gurobi - # using Gurobi - # env = Gurobi.Env() - # setparam!(env, "OutputFlag", 1) - # model = Gurobi.Model(env, "model") - # add_cvars!(model, q); update_model!(model) - # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) - # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) - # add_qpterms!(model, P_new); update_model!(model) - # optimize(model) - # x_test = get_solution(model) - # obj_test= get_objval(model) - # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) - # y_test = y_test[m+1:end] + y_test[1:m] - # - # println("x_test = $(x_test)") - # println("y_test = $(y_test)") - # println("obj_test = $(obj_test)") - # - x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] - y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] - obj_test = -0.02187014865840703 - - @test isapprox(results.x, x_test, atol=tol) - @test isapprox(results.y, y_test, atol=tol) - @test isapprox(results.info.obj_val, obj_test, atol=tol) - @test results.info.status == :Solved - end - +# This unit test relies on a precomputed reference solution for a randomly generated problem (done in Julia v1.0). +# However, in newer versions of Julia the random number stream changed leading to a different problem being generated. +if VERSION < v"1.1" + + @testset "update_matrices" begin + + @testset "solve" begin + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + + + x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] + y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] + obj_test = -0.6736977821770016 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + + + end + + + @testset "update_P" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrix + Pnew_triu = triu(P_new) + Pnew_triu_idx = collect(1 : length(Pnew_triu.nzval)) + OSQP.update!(model, Px=Pnew_triu.nzval, Px_idx=Pnew_triu_idx) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + + x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] + y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] + obj_test = -0.6736977821770016 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_P_allind" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrix + Pnew_triu = triu(P_new) + OSQP.update!(model, Px=Pnew_triu.nzval) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + + x_test = [-0.324865, 0.598681, -0.066646, -0.00653471, -0.0736556] + y_test = [-2.72542e-10, -1.927e-12, -0.547374, -2.25907e-10, -0.645086, -4.09874e-9, -1.4083e-11, -1.26234e-11] + obj_test = -0.6736977821770016 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_A" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrix + A_new_idx = collect(1 : length(A_new.nzval)) + OSQP.update!(model, Ax=A_new.nzval, Ax_idx=A_new_idx) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_A_allind" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrix + OSQP.update!(model, Ax=A_new.nzval) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_P_A_indP_indA" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrices P and A + P_new_triu = triu(P_new) + P_new_triu_idx = collect(1 : length(P_new_triu.nzval)) + A_new_idx = collect(1 : length(A_new.nzval)) + + OSQP.update!(model, Px=P_new_triu.nzval, Px_idx=P_new_triu_idx, + Ax=A_new.nzval, Ax_idx=A_new_idx) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_P_A_indP" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrices P and A + P_new_triu = triu(P_new) + P_new_triu_idx = collect(1 : length(P_new_triu.nzval)) + + OSQP.update!(model, Px=P_new_triu.nzval, Px_idx=P_new_triu_idx, + Ax=A_new.nzval) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_P_A_indA" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrices P and A + P_new_triu = triu(P_new) + A_new_idx = collect(1 : length(A_new.nzval)) + + OSQP.update!(model, Px=P_new_triu.nzval, + Ax=A_new.nzval, Ax_idx=A_new_idx) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + @testset "update_P_A_allind" begin + + problem, options = setup_update_matrices() + + (n, m, P, q, A, l, u) = (problem[:n], problem[:m], + problem[:P], problem[:q], problem[:A], problem[:l], problem[:u]) + P_new = problem[:P_new] + A_new = problem[:A_new] + + model = OSQP.Model() + OSQP.setup!(model; P=P, q=q, A=A, l=l, u=u, options...) + + # Update matrices P and A + P_new_triu = triu(P_new) + + OSQP.update!(model, Px=P_new_triu.nzval, Ax=A_new.nzval) + results = OSQP.solve!(model) + + # # Solve with Gurobi + # using Gurobi + # env = Gurobi.Env() + # setparam!(env, "OutputFlag", 1) + # model = Gurobi.Model(env, "model") + # add_cvars!(model, q); update_model!(model) + # add_constrs!(model, A_new, repmat(['<'], m), u); update_model!(model) + # add_constrs!(model, A_new, repmat(['>'], m), l); update_model!(model) + # add_qpterms!(model, P_new); update_model!(model) + # optimize(model) + # x_test = get_solution(model) + # obj_test= get_objval(model) + # y_test = -Gurobi.get_dblattrarray(model, "Pi", 1, 2 * m) + # y_test = y_test[m+1:end] + y_test[1:m] + # + # println("x_test = $(x_test)") + # println("y_test = $(y_test)") + # println("obj_test = $(obj_test)") + # + x_test = [-0.0318085, 0.067069, -0.0242966, -0.0593736, -0.0321274] + y_test = [-2.16989e-10, -1.01848, -0.516013, -0.0227263, -3.19721e-10, -1.04482, -3.4596e-10, -4.51608e-10] + obj_test = -0.02187014865840703 + + @test isapprox(results.x, x_test, atol=tol) + @test isapprox(results.y, y_test, atol=tol) + @test isapprox(results.info.obj_val, obj_test, atol=tol) + @test results.info.status == :Solved + end + + end end