From fdbabe071f49af01f5c8ef0f4ed979d7fbb593c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 21 Nov 2017 15:23:06 +0100 Subject: [PATCH] Remove solver concept and AbstractSolverInstanceAttribute --- src/JuMP.jl | 25 ++--------------- src/solverinterface.jl | 16 +++++------ test/lp.jl | 3 +- test/sdp.jl | 63 +++++++++++++++++++++++++----------------- test/soc.jl | 6 ++-- 5 files changed, 53 insertions(+), 60 deletions(-) diff --git a/src/JuMP.jl b/src/JuMP.jl index 71830da2421..d1ff3a13083 100644 --- a/src/JuMP.jl +++ b/src/JuMP.jl @@ -35,7 +35,7 @@ export PSDCone, # Functions # Model related - setobjectivesense, setsolver, + setobjectivesense, writeLP, writeMPS, #addSOS1, addSOS2, solve, @@ -76,10 +76,6 @@ const BINREF = MOICON{MOI.SingleVariable,MOI.ZeroOne} @MOIU.instance JuMPInstance (ZeroOne, Integer) (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, PositiveSemidefiniteConeTriangle) () (SingleVariable,) (ScalarAffineFunction,ScalarQuadraticFunction) (VectorOfVariables,) (VectorAffineFunction,) -# dummy solver -type UnsetSolver <: MathOptInterface.AbstractSolver -end - ############################################################################### # Model class # Keeps track of all model and column info @@ -141,7 +137,6 @@ mutable struct Model <: AbstractModel # internal solver instance object solverinstance # Solver+option object from MPB or MOI - solver solverinstanceattached::Bool # callbacks callbacks @@ -172,11 +167,8 @@ mutable struct Model <: AbstractModel # dictionary keyed on an extension-specific symbol ext::Dict{Symbol,Any} # Default constructor - function Model(;solver=UnsetSolver(), simplify_nonlinear_expressions::Bool=false) + function Model(; simplify_nonlinear_expressions::Bool=false) # TODO need to support MPB also - if !isa(solver,MOI.AbstractSolver) - error("solver argument ($solver) must be an AbstractSolver") - end m = new() # TODO make pretty m.instance = JuMPInstance{Float64}() @@ -192,7 +184,6 @@ mutable struct Model <: AbstractModel m.objbound = 0.0 m.objval = 0.0 m.solverinstance = nothing - m.solver = solver m.solverinstanceattached = false m.callbacks = Any[] m.solvehook = nothing @@ -404,18 +395,6 @@ dualstatus(m::Model) = MOI.get(m, MOI.DualStatus()) # setobjective(::Model, ::Symbol, x::AbstractArray) = # error("in setobjective: array of size $(_size(x)) passed as objective; only scalar objectives are allowed") -""" - setsolver(m::Model, solver::MathOptInterface.AbstractSolver) - -Change the solver which will be used for the next call to `solve()`, discarding the current internal model if present. -""" -function setsolver(m::Model, solver::MOI.AbstractSolver) - m.solver = solver - m.solverinstance = nothing - m.solverinstanceattached = false - nothing -end - # # Deep copy the model # function Base.copy(source::Model) # diff --git a/src/solverinterface.jl b/src/solverinterface.jl index 541adf8dbf3..5369b8d1e0f 100644 --- a/src/solverinterface.jl +++ b/src/solverinterface.jl @@ -10,9 +10,9 @@ Attach the JuMP model `m` to a new solver instance. All instance data is transfe and while the solver instance remains attached, all modifications to the JuMP model are immediately mirrored in the solver instance. See also `isattached()` and `detach()`. """ -function attach(m::Model) +function attach(m::Model, solverinstance::MOI.AbstractSolverInstance) @assert !m.solverinstanceattached - m.solverinstance = MOI.SolverInstance(m.solver) + m.solverinstance = solverinstance solvervariables = MOI.addvariables!(m.solverinstance, numvar(m)) # TODO numvar shouldn't return unsigned int m.variabletosolvervariable = Dict{MOIVAR,MOIVAR}() @@ -60,24 +60,24 @@ function detach(m::Model) end """ - canget(m::JuMP.Model, attr::MathOptInterface.AbstractSolverInstanceAttribute)::Bool + canget(m::JuMP.Model, attr::MathOptInterface.AbstractInstanceAttribute)::Bool Return `true` if one may query the attribute `attr` from the solver instance attached to the JuMP model, false if not. Throws an error if no solver instance is currently attached. """ -function MOI.canget(m::Model, attr::MOI.AbstractSolverInstanceAttribute) +function MOI.canget(m::Model, attr::MOI.AbstractInstanceAttribute) @assert m.solverinstanceattached return MOI.canget(m.solverinstance, attr) end """ - get(m::JuMP.Model, attr::MathOptInterface.AbstractSolverInstanceAttribute) + get(m::JuMP.Model, attr::MathOptInterface.AbstractInstanceAttribute) Return the value of the attribute `attr` from the solver instance attached to the JuMP model. Throws an error if no solver instance is currently attached. """ -function MOI.get(m::Model, attr::MOI.AbstractSolverInstanceAttribute) +function MOI.get(m::Model, attr::MOI.AbstractInstanceAttribute) @assert m.solverinstanceattached return MOI.get(m.solverinstance, attr) end @@ -91,9 +91,7 @@ function solve(m::Model; return m.solvehook(m) end - if !m.solverinstanceattached - attach(m) - end + @assert m.solverinstanceattached MOI.optimize!(m.solverinstance) empty!(m.variableresult) diff --git a/test/lp.jl b/test/lp.jl index 908e2c87fa1..86a8a6a78eb 100644 --- a/test/lp.jl +++ b/test/lp.jl @@ -5,13 +5,14 @@ # st x + y <= 1 (x + y - 1 ∈ Nonpositives) # x, y >= 0 (x, y ∈ Nonnegatives) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x >= 0.0) @variable(m, y >= 0.0) @objective(m, Min, -x) @constraint(m, x + y <= 1) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.isattached(m) diff --git a/test/sdp.jl b/test/sdp.jl index 1df9dde8102..ae5191bfb76 100644 --- a/test/sdp.jl +++ b/test/sdp.jl @@ -30,7 +30,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # (x1,x2,x3) in C^3_q # X in C_sdp - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x[1:3]) @constraint(m, x in MOI.SecondOrderCone(3)) @@ -51,6 +51,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 @constraint(m, vecdot(A1, X) + x[1] == 1) @constraint(m, vecdot(A2, X) + x[2] + x[3] == 1/2) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.isattached(m) @@ -202,7 +203,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # end # @testset "SDP with SOC" begin -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # @variable(m, X[1:2,1:2], PSD) # @variable(m, y[0:2]) # @constraint(m, norm([y[1],y[2]]) <= y[0]) @@ -231,12 +232,13 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Y >= 0 0 0 0] 0 0 1] # y1 <= 0 y2 >= 0 @testset "Test problem #2" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, Y[1:3,1:3], PSD) c1 = @constraint(m, Y[2,1] <= 4) c2 = @constraint(m, Y[2,2] >= 3) @objective(m, Min, trace(Y)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -253,16 +255,13 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Y >= 0 0 0 0] 0 0 0] # y free @testset "Test problem #3" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x >= 0) @variable(m, Y[1:3,1:3], PSD) c = @constraint(m, Y[2,1] == 1) @objective(m, Min, Y[1,2]) - JuMP.solve(m) - @test JuMP.terminationstatus(m) == MOI.Success - @test JuMP.primalstatus(m) == MOI.FeasiblePoint - + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -284,13 +283,14 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # x >= 0 z <= 0 @testset "Test problem #4" begin #solver = fixscs(solver, 2000000) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x >= 0) @variable(m, Y[1:3,1:3], PSD) c1 = @constraint(m, x >= 1) c2 = @constraint(m, Y[2,1] == 1) @objective(m, Min, x + Y[1,1]) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -313,7 +313,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # end # # @testset "Test problem #5" begin -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # @variable(m, Y[1:3,1:3], PSD) # @constraint(m, Y[2,1] <= 4) # @constraint(m, Y[2,2] >= 3) @@ -335,13 +335,14 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 end @testset "Test problem #6" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, Y[1:3,1:3]) @constraint(m, Y[2,1] <= 4) @constraint(m, Y[2,2] >= 3) @constraint(m, sum(Y) >= 12) @objective(m, Min, operator_norm(m, Y)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -358,7 +359,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # end # # @testset "Test problem #7" begin -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # @variable(m, Y[1:3,1:3]) # @constraint(m, Y[1,1] >= 4) # @objective(m, Min, lambda_max(m, Y)) @@ -379,11 +380,12 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 end @testset "Test problem #8" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, Y[1:3,1:3], PSD) @constraint(m, trace(Y) <= 6) @objective(m, Max, lambda_min(m, Y)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -402,7 +404,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 end # @testset "Test problem #9" begin -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # n = 3 # x = [1,2,3] # lb = 0.5eye(n) @@ -418,7 +420,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # end @testset "Correlation example" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, X[1:3,1:3], PSD) @@ -435,6 +437,8 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Find upper bound @objective(m, Max, X[1,3]) + + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -456,13 +460,14 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Q >= 0 y free # o free X <= 0 @testset "Just another SDP" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, Q[1:2, 1:2], PSD) c1 = @constraint(m, Q[1,1] - 1 == Q[2,2]) @variable(m, objective) @SDconstraint(m, [1 Q[1,1]; Q[1,1] objective] ⪰ 0) @objective(m, Min, objective) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -483,14 +488,14 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Example 2.11 @testset "SDP variable and optimal objective not rational" begin # solver = fixscs(solver, 7000000) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, X[1:2,1:2], PSD) c = @constraint(m, X[1,1]+X[2,2] == 1) @objective(m, Min, 2*X[1,1]+2*X[1,2]) # @test all(isnan.(getdual(X))) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) - @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -503,11 +508,13 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # Example 2.13 @testset "SDP constraint and optimal objective not rational" begin #solver = fixscs(solver, 7000000) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, y) c = @SDconstraint(m, [2-y 1; 1 -y] >= 0) @objective(m, Max, y) #@test all(isnan, getdual(c)) + + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -530,11 +537,13 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # for any eps > 0 however there is no primal solution with objective value 0. @testset "SDP with dual solution not attained" begin #solver = fixscs(solver, 7000000) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, y) c = @SDconstraint(m, [0 y; y 0] <= [1 0; 0 0]) @objective(m, Max, y) #@test all(isnan, getdual(c)) + + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -551,11 +560,13 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 @testset "SDP with primal solution not attained" begin # solver = fixscs(solver, 7000000) - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, X[1:2,1:2], PSD) c = @constraint(m, 2*X[1,2] == 1) @objective(m, Min, X[1,1]) # @test all(isnan, getdual(X)) + + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -579,7 +590,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # # X+Xᵀ ⪰ 0 # @testset "SDP with dual solution not attained without symmetric A_i" begin # #solver = fixscs(solver, 10000000) -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # @variable(m, y) # @variable(m, z) # c = @SDconstraint(m, [0 y; z 0] <= [1 0; 0 0]) @@ -606,7 +617,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # # X+Xᵀ ⪰ 0 # @testset "SDP with dual solution not attained without symmetry" begin # #solver = fixscs(solver, 10000000) -# m = Model(solver=CSDPSolver(printlevel=0)) +# m = Model() # @variable(m, y) # @variable(m, z) # c = @SDconstraint(m, [0 y; z 0] <= [1 0; 0 0]) @@ -629,7 +640,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 # end @testset "Nonzero dual for a scalar variable with sdp solver" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x1 >= 0) @variable(m, x2 >= 0) @variable(m, x3 >= 0) @@ -638,6 +649,7 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 c = @SDconstraint(m, [2x1-x2-x3 0; 0 x1-x2+x3] >= [3 0; 0 2]) @objective(m, Min, 2x1 - x2) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint @@ -655,10 +667,11 @@ ispsd(x::Matrix) = minimum(eigvals(x)) ≥ -1e-3 @testset "No constraint" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, X[1:3,1:3], PSD) @objective(m, Min, trace(X)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.terminationstatus(m) == MOI.Success @test JuMP.primalstatus(m) == MOI.FeasiblePoint diff --git a/test/soc.jl b/test/soc.jl index e129a5f3961..a3cc7566e3c 100644 --- a/test/soc.jl +++ b/test/soc.jl @@ -1,6 +1,6 @@ @testset "Second-order Cone Programming" begin @testset "SOC1" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x) @variable(m, y) @variable(m, t >= 0) @@ -8,6 +8,7 @@ @constraint(m, x + y >= 1) @constraint(m, [t,x,y] in MOI.SecondOrderCone(3)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.isattached(m) @@ -23,7 +24,7 @@ end @testset "RotatedSOC1" begin - m = Model(solver=CSDPSolver(printlevel=0)) + m = Model() @variable(m, x[1:5] >= 0) @variable(m, 0 <= u <= 5) @@ -36,6 +37,7 @@ @constraint(m, [t1/sqrt(2),t2/sqrt(2),x...] in MOI.RotatedSecondOrderCone(7)) @constraint(m, [x[1]/sqrt(2), u/sqrt(2), v] in MOI.RotatedSecondOrderCone(3)) + JuMP.attach(m, CSDPInstance(printlevel=0)) JuMP.solve(m) @test JuMP.isattached(m)