From b17207c747212889f33fd152db2d51a97a9150eb Mon Sep 17 00:00:00 2001 From: ccoffrin Date: Fri, 16 Jun 2017 15:17:43 -0400 Subject: [PATCH 1/2] preliminary migration of nlp tests --- test/nlp.jl | 240 ++++++++++++++++++++++++++++------------------- test/runtests.jl | 2 + 2 files changed, 148 insertions(+), 94 deletions(-) diff --git a/test/nlp.jl b/test/nlp.jl index bf7d3fd..724cde4 100644 --- a/test/nlp.jl +++ b/test/nlp.jl @@ -1,9 +1,10 @@ using Base.Test using MathProgBase + # Here the type represents the complete instance, but it # could also store instance data. -type HS071 <: MathProgBase.AbstractNLPEvaluator +type HS071 <: MPB.AbstractNLPEvaluator end # hs071 @@ -14,7 +15,7 @@ end # Start at (1,5,5,1) # End at (1.000..., 4.743..., 3.821..., 1.379...) -function MathProgBase.initialize(d::HS071, requested_features::Vector{Symbol}) +function MPB.initialize(d::HS071, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac, :Hess]) error("Unsupported feature $feat") @@ -24,28 +25,28 @@ function MathProgBase.initialize(d::HS071, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::HS071) = [:Grad, :Jac, :Hess] +MPB.features_available(d::HS071) = [:Grad, :Jac, :Hess] -MathProgBase.eval_f(d::HS071, x) = x[1] * x[4] * (x[1] + x[2] + x[3]) + x[3] +MPB.eval_f(d::HS071, x) = x[1] * x[4] * (x[1] + x[2] + x[3]) + x[3] -function MathProgBase.eval_g(d::HS071, g, x) +function MPB.eval_g(d::HS071, g, x) g[1] = x[1] * x[2] * x[3] * x[4] g[2] = x[1]^2 + x[2]^2 + x[3]^2 + x[4]^2 end -function MathProgBase.eval_grad_f(d::HS071, grad_f, x) +function MPB.eval_grad_f(d::HS071, grad_f, x) grad_f[1] = x[1] * x[4] + x[4] * (x[1] + x[2] + x[3]) grad_f[2] = x[1] * x[4] grad_f[3] = x[1] * x[4] + 1 grad_f[4] = x[1] * (x[1] + x[2] + x[3]) end -MathProgBase.jac_structure(d::HS071) = [1,1,1,1,2,2,2,2],[1,2,3,4,1,2,3,4] +MPB.jac_structure(d::HS071) = [1,1,1,1,2,2,2,2],[1,2,3,4,1,2,3,4] # lower triangle only -MathProgBase.hesslag_structure(d::HS071) = [1,2,2,3,3,3,4,4,4,4],[1,1,2,1,2,3,1,2,3,4] +MPB.hesslag_structure(d::HS071) = [1,2,2,3,3,3,4,4,4,4],[1,1,2,1,2,3,1,2,3,4] -function MathProgBase.eval_jac_g(d::HS071, J, x) +function MPB.eval_jac_g(d::HS071, J, x) # Constraint (row) 1 J[1] = x[2]*x[3]*x[4] # 1,1 J[2] = x[1]*x[3]*x[4] # 1,2 @@ -58,7 +59,7 @@ function MathProgBase.eval_jac_g(d::HS071, J, x) J[8] = 2*x[4] # 2,4 end -function MathProgBase.eval_hesslag(d::HS071, H, x, σ, μ) +function MPB.eval_hesslag(d::HS071, H, x, σ, μ) # Again, only lower left triangle # Objective H[1] = σ * (2*x[4]) # 1,1 @@ -90,35 +91,48 @@ end function nlptest(solver) @testset "Testing NLP with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [1,1,1,1] u = [5,5,5,5] lb = [25, 40] ub = [Inf, 40] - MathProgBase.loadproblem!(m, 4, 2, l, u, lb, ub, :Min, HS071()) - MathProgBase.setwarmstart!(m,[1,5,5,1]) + vrefs = MPB.loadnlp!(m, 4, 2, l, u, lb, ub, MPB.MinSense, HS071()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), vrefs) + + @test isapprox(primal_sol[1], 1.0000000000000000, atol=1e-5) + @test isapprox(primal_sol[2], 4.7429996418092970, atol=1e-5) + @test isapprox(primal_sol[3], 3.8211499817883077, atol=1e-5) + @test isapprox(primal_sol[4], 1.3794082897556983, atol=1e-5) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 17.014017145179164, atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0000000000000000, atol=1e-5) - @test isapprox(x[2], 4.7429996418092970, atol=1e-5) - @test isapprox(x[3], 3.8211499817883077, atol=1e-5) - @test isapprox(x[4], 1.3794082897556983, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 17.014017145179164, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.setwarmstart!(m,[1,5,5,1]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end + # Same as above but no hessian callback -type HS071_2 <: MathProgBase.AbstractNLPEvaluator +type HS071_2 <: MPB.AbstractNLPEvaluator end # hs071 @@ -129,7 +143,7 @@ end # Start at (1,5,5,1) # End at (1.000..., 4.743..., 3.821..., 1.379...) -function MathProgBase.initialize(d::HS071_2, requested_features::Vector{Symbol}) +function MPB.initialize(d::HS071_2, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac]) error("Unsupported feature $feat") @@ -139,50 +153,60 @@ function MathProgBase.initialize(d::HS071_2, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::HS071_2) = [:Grad, :Jac] +MPB.features_available(d::HS071_2) = [:Grad, :Jac] -MathProgBase.eval_f(d::HS071_2, x) = MathProgBase.eval_f(HS071(), x) +MPB.eval_f(d::HS071_2, x) = MPB.eval_f(HS071(), x) -MathProgBase.eval_g(d::HS071_2, g, x) = MathProgBase.eval_g(HS071(), g, x) +MPB.eval_g(d::HS071_2, g, x) = MPB.eval_g(HS071(), g, x) -MathProgBase.eval_grad_f(d::HS071_2, grad_f, x) = MathProgBase.eval_grad_f(HS071(), grad_f, x) +MPB.eval_grad_f(d::HS071_2, grad_f, x) = MPB.eval_grad_f(HS071(), grad_f, x) -MathProgBase.jac_structure(d::HS071_2) = MathProgBase.jac_structure(HS071()) +MPB.jac_structure(d::HS071_2) = MPB.jac_structure(HS071()) -MathProgBase.eval_jac_g(d::HS071_2, J, x) = MathProgBase.eval_jac_g(HS071(), J, x) +MPB.eval_jac_g(d::HS071_2, J, x) = MPB.eval_jac_g(HS071(), J, x) function nlptest_nohessian(solver) @testset "Testing NLP without Hessian with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [1,1,1,1] u = [5,5,5,5] lb = [25, 40] ub = [Inf, 40] - MathProgBase.loadproblem!(m, 4, 2, l, u, lb, ub, :Min, HS071_2()) - MathProgBase.setwarmstart!(m,[1,5,5,1]) + vrefs = MPB.loadnlp!(m, 4, 2, l, u, lb, ub, MPB.MinSense, HS071_2()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1], 1.0000000000000000, atol=1e-5) + @test isapprox(primal_sol[2], 4.7429996418092970, atol=1e-5) + @test isapprox(primal_sol[3], 3.8211499817883077, atol=1e-5) + @test isapprox(primal_sol[4], 1.3794082897556983, atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0000000000000000, atol=1e-5) - @test isapprox(x[2], 4.7429996418092970, atol=1e-5) - @test isapprox(x[3], 3.8211499817883077, atol=1e-5) - @test isapprox(x[4], 1.3794082897556983, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 17.014017145179164, atol=1e-5) + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 17.014017145179164, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.setwarmstart!(m,[1,5,5,1]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end -# a test for convex nonlinear solvers -type QCQP <: MathProgBase.AbstractNLPEvaluator +# a test for convex nonlinear solvers +type QCQP <: MPB.AbstractNLPEvaluator end # min x - y @@ -191,7 +215,7 @@ end # solution: x+y = -1/3 # optimal objective -1-4/sqrt(3) -function MathProgBase.initialize(d::QCQP, requested_features::Vector{Symbol}) +function MPB.initialize(d::QCQP, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac, :Hess]) error("Unsupported feature $feat") @@ -201,30 +225,30 @@ function MathProgBase.initialize(d::QCQP, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::QCQP) = [:Grad, :Jac, :Hess] +MPB.features_available(d::QCQP) = [:Grad, :Jac, :Hess] -MathProgBase.eval_f(d::QCQP, x) = x[1]-x[2] +MPB.eval_f(d::QCQP, x) = x[1]-x[2] -function MathProgBase.eval_g(d::QCQP, g, x) +function MPB.eval_g(d::QCQP, g, x) g[1] = x[1] + x[1]^2 + x[1]*x[2] + x[2]^2 end -function MathProgBase.eval_grad_f(d::QCQP, grad_f, x) +function MPB.eval_grad_f(d::QCQP, grad_f, x) grad_f[1] = 1 grad_f[2] = -1 end -MathProgBase.jac_structure(d::QCQP) = [1,1],[1,2] +MPB.jac_structure(d::QCQP) = [1,1],[1,2] # lower triangle only -MathProgBase.hesslag_structure(d::QCQP) = [1,2,2],[1,1,2] +MPB.hesslag_structure(d::QCQP) = [1,2,2],[1,1,2] -function MathProgBase.eval_jac_g(d::QCQP, J, x) +function MPB.eval_jac_g(d::QCQP, J, x) J[1] = 1 + 2x[1] + x[2] J[2] = x[1]+2x[2] end -function MathProgBase.eval_hesslag(d::QCQP, H, x, σ, μ) +function MPB.eval_hesslag(d::QCQP, H, x, σ, μ) # Again, only lower left triangle # Objective, linear @@ -237,39 +261,52 @@ end function convexnlptest(solver) @testset "Testing convex NLP with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NonlinearModel(solver) l = [-2,-2] u = [2,2] lb = [-Inf] ub = [1.0] - MathProgBase.loadproblem!(m, 2, 1, l, u, lb, ub, :Min, QCQP()) + vrefs = MPB.loadnlp!(m, 2, 1, l, u, lb, ub, MPB.MinSense, QCQP()) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1]+primal_sol[2], -1/3, atol=1e-3) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, -1-4/sqrt(3), atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1]+x[2], -1/3, atol=1e-3) - @test isapprox(MathProgBase.getobjval(m), -1-4/sqrt(3), atol=1e-5) # Test that a second call to optimize! works - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + # the line below was added during break_everything and may break this test + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [0.0,0.0]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end # a test for unconstrained nonlinear solvers - -type Rosenbrock <: MathProgBase.AbstractNLPEvaluator +type Rosenbrock <: MPB.AbstractNLPEvaluator end # min (1-x)^2 + 100*(y-x^2)^2 # solution: (x,y) = (1,1) # optimal objective 0 -function MathProgBase.initialize(d::Rosenbrock, requested_features::Vector{Symbol}) +function MPB.initialize(d::Rosenbrock, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Hess]) error("Unsupported feature $feat") @@ -279,20 +316,20 @@ function MathProgBase.initialize(d::Rosenbrock, requested_features::Vector{Symbo end end -MathProgBase.features_available(d::Rosenbrock) = [:Grad, :Hess] +MPB.features_available(d::Rosenbrock) = [:Grad, :Hess] -MathProgBase.eval_f(d::Rosenbrock, x) = (1-x[1])^2 + 100*(x[2]-x[1]^2)^2 +MPB.eval_f(d::Rosenbrock, x) = (1-x[1])^2 + 100*(x[2]-x[1]^2)^2 -MathProgBase.eval_g(d::Rosenbrock, g, x) = nothing +MPB.eval_g(d::Rosenbrock, g, x) = nothing -function MathProgBase.eval_grad_f(d::Rosenbrock, grad_f, x) +function MPB.eval_grad_f(d::Rosenbrock, grad_f, x) grad_f[1] = -2*(1-x[1]) - 400*x[1]*(x[2]-x[1]^2) grad_f[2] = 200*(x[2]-x[1]^2) end -MathProgBase.hesslag_structure(d::Rosenbrock) = [1,2,2],[1,1,2] +MPB.hesslag_structure(d::Rosenbrock) = [1,2,2],[1,1,2] -function MathProgBase.eval_hesslag(d::Rosenbrock, H, x, σ, μ) +function MPB.eval_hesslag(d::Rosenbrock, H, x, σ, μ) # Again, only lower left triangle H[1] = σ*(2+100*(8x[1]^2-4*(x[2]-x[1]^2))) # d/dx^2 @@ -303,26 +340,41 @@ end function rosenbrocktest(solver) @testset "Testing NLP on the Rosenbrock function with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [-Inf,-Inf] u = [Inf,Inf] lb = Float64[] ub = Float64[] - MathProgBase.loadproblem!(m, 2, 0, l, u, lb, ub, :Min, Rosenbrock()) + MPB.loadnlp!(m, 2, 0, l, u, lb, ub, MPB.MinSense, Rosenbrock()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [10.0,10.0]) - MathProgBase.setwarmstart!(m,[10.0,10.0]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + MPB.optimize!(m) + stat = MPB.status(m) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0, atol=1e-5) - @test isapprox(x[2], 1.0, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 0.0, atol=1e-5) + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1], 1.0, atol=1e-5) + @test isapprox(primal_sol[2], 1.0, atol=1e-5) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 0.0, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + # the line below was added during break_everything and may break this test + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [10.0,10.0]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end diff --git a/test/runtests.jl b/test/runtests.jl index 32a6666..228523c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,7 @@ using GLPKMathProgInterface, Ipopt, ECOS +const MPB = MathProgBase + lp_solver = GLPKSolverLP() ip_solver = GLPKSolverMIP() conic_solver = ECOSSolver(verbose=false) From 69bcaaba6d5443072ea3b06555f92e5ce7356856 Mon Sep 17 00:00:00 2001 From: ccoffrin Date: Fri, 16 Jun 2017 18:21:55 -0400 Subject: [PATCH 2/2] WIP: adding first conic example --- test/conicinterface.jl | 57 +++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/test/conicinterface.jl b/test/conicinterface.jl index 6dad8b7..50fa492 100644 --- a/test/conicinterface.jl +++ b/test/conicinterface.jl @@ -9,7 +9,7 @@ using Base.Test using MathProgBase """ -function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false, tol=1e-6) +function coniclineartest(solver::MathProgBase.AbstractMathProgSolver; duals=false, tol=1e-6) @testset "Testing linear problems through conic interface with $solver" begin # Problem LIN1 - all vars in nonneg cone # min -3x - 2y - 4z @@ -23,21 +23,48 @@ function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false A = [ 1.0 1.0 1.0; 0.0 1.0 1.0] b = [ 3.0, 2.0] - m = MathProgBase.ConicModel(solver) - MathProgBase.loadproblem!(m, c, A, b, [(:Zero,1:2)], [(:NonNeg, 1:3)]) + m = MPB.Model(solver) + + #MathProgBase.loadproblem!(m, c, A, b, [(:Zero,1:2)], [(:NonNeg, 1:3)]) + v = MPB.addvariables!(m, 3) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + + vc = MPB.addconstraint!(m, v, MPB.NonNegative(3)) + c = MPB.addconstraint!(m, b, -A, MPB.Zero(2)) + + MPB.setobjective!(m, 1, 0.0, v, c) + MathProgBase.optimize!(m) - @test MathProgBase.status(m) == :Optimal - @test isapprox(MathProgBase.getobjval(m), -11, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[1], 1.0, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[2], 0.0, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[3], 2.0, atol=tol) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + obj = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj, -11, atol=tol) + + p_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(p_sol[1], 1.0, atol=tol) + @test isapprox(p_sol[2], 0.0, atol=tol) + @test isapprox(p_sol[3], 2.0, atol=tol) if duals - d = MathProgBase.getdual(m) - @test isapprox(d[1], 3.0, atol=tol) - @test isapprox(d[2], 1.0, atol=tol) - vardual = c + A'd - var = MathProgBase.getvardual(m) - @test isapprox(vardual, var, atol=tol) + @test MPB.cangetattribute(m, MPB.DualStatus()) + @test MPB.cangetattribute(m, MPB.ConstraintDual(), c) + @test MPB.cangetattribute(m, MPB.ConstraintDual(), vc) + + dual_status = MPB.getattribute(m, MPB.DualStatus()) + @test dual_status == MPB.FeasiblePoint + + d_sol = MPB.getattribute(m, MPB.ConstraintDual(), c) + @test isapprox(d_sol[1], 3.0, atol=tol) + @test isapprox(d_sol[2], 1.0, atol=tol) + + vardual = c + A'd_sol + vd_sol = MPB.getattribute(m, MPB.ConstraintDual(), vc) + @test isapprox(vardual, vd_sol, atol=tol) end end @@ -59,7 +86,7 @@ function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false 0.0 1.0 0.0; 0.0 0.0 -1.0] b = [ 3.0, 2.0, 0.0, 0.0, 0.0] - m = MathProgBase.ConicModel(solver) + m = MPB.ConicModel(solver) MathProgBase.loadproblem!(m,c, A, b, [(:Zero,1:2),(:NonPos,3:4),(:NonNeg,5)], [(:Free, 1:3)]) MathProgBase.optimize!(m)