Skip to content

Commit

Permalink
Unify behavior of getdual and getvariable: NaN+warn
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Dec 18, 2016
1 parent 03e0284 commit 0e21fda
Show file tree
Hide file tree
Showing 14 changed files with 250 additions and 23 deletions.
8 changes: 8 additions & 0 deletions test/before.dat-s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
1
2
1.000000000000000000e+00
0 1 1 1 -2.000000000000000000e+00
0 1 1 2 -9.999999999999997780e-01
1 1 1 1 1.000000000000000000e+00
1 1 2 2 1.000000000000000000e+00
8 changes: 8 additions & 0 deletions test/done.dat-s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
1
2
1.000000000000000000e+00
0 1 1 1 -2.000000000000000000e+00
0 1 1 2 -9.999999999999997780e-01
1 1 1 1 1.000000000000000000e+00
1 1 2 2 1.000000000000000000e+00
8 changes: 8 additions & 0 deletions test/init.dat-s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
1
2
1.000000000000000000e+00
0 1 1 1 -2.000000000000000000e+00
0 1 1 2 -9.999999999999997780e-01
1 1 1 1 1.000000000000000000e+00
1 1 2 2 1.000000000000000000e+00
4 changes: 2 additions & 2 deletions test/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ end
@test_throws ErrorException setobjectivesense(modErr, :Maximum)
@variable(modErr, errVar)
@test isnan(getvalue(errVar))
@test_throws ErrorException getdual(errVar)
@test isnan(getdual(errVar))

modErr = Model()
@variable(modErr, x, Bin)
@objective(modErr, Max, x)
con = @constraint(modErr, x <= 0.5)
solve(modErr)
@test_throws ErrorException getdual(con)
@test isnan(getdual(con))

modErr = Model()
@variable(modErr, 0 <= x <= 1)
Expand Down
6 changes: 6 additions & 0 deletions test/mosekbug.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
m = Model(solver=solver)
@variable(m, y1)
@variable(m, y2)
c = @SDconstraint(m, [y2 0 0; 0 y1 y2; 0 y2 0] <= [1 0 0; 0 0 0; 0 0 0])
@objective(m, Max, y2)
solve(m)
143 changes: 143 additions & 0 deletions test/newsolvers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Copyright 2016, Iain Dunning, Joey Huchette, Miles Lubin, and contributors
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#############################################################################
# JuMP
# An algebraic modelling langauge for Julia
# See https://github.com/JuliaOpt/JuMP.jl
#############################################################################
# test/solvers.jl
# Detect and load solvers
# Should be run as part of runtests.jl
#############################################################################

function try_import(name::Symbol)
try
@eval import $name
return true
catch e
return false
end
end

# Load available solvers
grb = try_import(:Gurobi)
cpx = try_import(:CPLEX)
mos = try_import(:Mosek)
cbc = try_import(:Cbc)
if cbc; import Clp; end
glp = try_import(:GLPKMathProgInterface)
ipt = try_import(:Ipopt)
nlo = try_import(:NLopt)
kni = try_import(:KNITRO)
eco = try_import(:ECOS)
osl = try_import(:CoinOptServices)
scs = try_import(:SCS)
nlw = try_import(:AmplNLWriter)
brn = try_import(:BARON)
csd = try_import(:SemidefiniteProgramming)
sda = try_import(:SemidefiniteProgramming)

# Create solver lists
# LP solvers
lp_solvers = Any[]
grb && push!(lp_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(lp_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(lp_solvers, Mosek.MosekSolver(LOG=0))
cbc && push!(lp_solvers, Clp.ClpSolver())
glp && push!(lp_solvers, GLPKMathProgInterface.GLPKSolverLP())
ipt && push!(lp_solvers, Ipopt.IpoptSolver(print_level=0))
eco && push!(lp_solvers, ECOS.ECOSSolver(verbose=false))
osl && push!(lp_solvers, CoinOptServices.OsilSolver())
scs && push!(lp_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))
# MILP solvers
ip_solvers = Any[]
grb && push!(ip_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(ip_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(ip_solvers, Mosek.MosekSolver(LOG=0))
cbc && push!(ip_solvers, Cbc.CbcSolver(logLevel=0))
glp && push!(ip_solvers, GLPKMathProgInterface.GLPKSolverMIP())
osl && push!(ip_solvers, CoinOptServices.OsilSolver())
# Support semi-continuous, semi-integer solvers
semi_solvers = Any[]
grb && push!(semi_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(semi_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
# SOS solvers
sos_solvers = Any[]
grb && push!(sos_solvers, Gurobi.GurobiSolver(OutputFlag=0))
cpx && push!(sos_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
cbc && push!(sos_solvers, Cbc.CbcSolver())
# Conic solvers with duals
conic_solvers_with_duals = Any[]
eco && push!(conic_solvers_with_duals, ECOS.ECOSSolver(verbose=false))
scs && push!(conic_solvers_with_duals, SCS.SCSSolver(eps=1e-6,verbose=0))
mos && push!(conic_solvers_with_duals, Mosek.MosekSolver(LOG=0))
# Callback solvers
lazy_solvers, lazylocal_solvers, cut_solvers, cutlocal_solvers, heur_solvers, info_solvers = Any[], Any[], Any[], Any[], Any[], Any[]
if grb
push!(lazy_solvers, Gurobi.GurobiSolver(OutputFlag=0, Presolve=0))
push!( cut_solvers, Gurobi.GurobiSolver(PreCrush=1, Cuts=0, Presolve=0, Heuristics=0.0, OutputFlag=0))
push!(heur_solvers, Gurobi.GurobiSolver(Cuts=0, Presolve=0, Heuristics=0.0, OutputFlag=0))
# push!(heur_solvers, Gurobi.GurobiSolver(Heuristics=0.0, OutputFlag=0))
push!(info_solvers, Gurobi.GurobiSolver(OutputFlag=0))
end
if cpx
push!(lazy_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
push!(lazylocal_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0, CPX_PARAM_FRACCUTS=-1, CPX_PARAM_EACHCUTLIM=0, CPX_PARAM_HEURFREQ=-1))
push!( cut_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
push!(cutlocal_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0, CPX_PARAM_FRACCUTS=-1, CPX_PARAM_EACHCUTLIM=0, CPX_PARAM_HEURFREQ=-1))
push!(heur_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
push!(info_solvers, CPLEX.CplexSolver(CPX_PARAM_PRELINEAR=0, CPX_PARAM_PREIND=0, CPX_PARAM_ADVIND=0, CPX_PARAM_MIPSEARCH=1,CPX_PARAM_MIPCBREDLP=0,CPX_PARAM_SCRIND=0))
end
if glp
push!(lazy_solvers, GLPKMathProgInterface.GLPKSolverMIP())
push!( cut_solvers, GLPKMathProgInterface.GLPKSolverMIP())
push!(heur_solvers, GLPKMathProgInterface.GLPKSolverMIP())
push!(info_solvers, GLPKMathProgInterface.GLPKSolverMIP())
end
# Quadratic support
quad_solvers = Any[]
grb && push!(quad_solvers, Gurobi.GurobiSolver(QCPDual=1,OutputFlag=0))
cpx && push!(quad_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
mos && push!(quad_solvers, Mosek.MosekSolver(LOG=0))
quad_mip_solvers = copy(quad_solvers)
osl && push!(quad_solvers, CoinOptServices.OsilSolver(CoinOptServices.OSOption("sb","yes",solver="ipopt")))
soc_solvers = copy(quad_solvers)
ipt && push!(quad_solvers, Ipopt.IpoptSolver(print_level=0))
eco && push!(soc_solvers, ECOS.ECOSSolver(verbose=false))
scs && push!(soc_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))
osl && push!(quad_mip_solvers, CoinOptServices.OsilBonminSolver(CoinOptServices.OSOption("sb","yes",category="ipopt")))
osl && push!(quad_mip_solvers, CoinOptServices.OsilCouenneSolver())
rsoc_solvers = Any[]
mos && push!(rsoc_solvers, Mosek.MosekSolver(LOG=0))
grb && push!(rsoc_solvers, Gurobi.GurobiSolver(QCPDual=1,OutputFlag=0))
cpx && push!(rsoc_solvers, CPLEX.CplexSolver(CPX_PARAM_SCRIND=0))
# Nonlinear solvers
nlp_solvers = Any[]
ipt && push!(nlp_solvers, Ipopt.IpoptSolver(print_level=0))
nlo && push!(nlp_solvers, NLopt.NLoptSolver(algorithm=:LD_SLSQP))
kni && push!(nlp_solvers, KNITRO.KnitroSolver(objrange=1e16,outlev=0,opttol=1e-8))
osl && push!(nlp_solvers, CoinOptServices.OsilSolver(CoinOptServices.OSOption("sb","yes",solver="ipopt")))
nlw && osl && push!(nlp_solvers, AmplNLWriter.BonminNLSolver(["bonmin.nlp_log_level=0"; "bonmin.bb_log_level=0"]))
convex_nlp_solvers = copy(nlp_solvers)
brn && push!(nlp_solvers, BARON.BaronSolver())
mos && push!(convex_nlp_solvers, Mosek.MosekSolver(LOG=0))
# Mixed-Integer Nonlinear solvers
minlp_solvers = Any[]
kni && push!(minlp_solvers, KNITRO.KnitroSolver(outlev=0))
osl && push!(minlp_solvers, CoinOptServices.OsilBonminSolver(CoinOptServices.OSOption("sb","yes",category="ipopt")))
osl && push!(minlp_solvers, CoinOptServices.OsilCouenneSolver())
nlw && osl && push!(minlp_solvers, AmplNLWriter.BonminNLSolver(["bonmin.nlp_log_level=0"; "bonmin.bb_log_level=0"]))
nlw && osl && push!(minlp_solvers, AmplNLWriter.CouenneNLSolver())
brn && push!(minlp_solvers, BARON.BaronSolver())
# Semidefinite solvers
sdp_solvers = Any[]
csd && push!(sdp_solvers, SemidefiniteProgramming.CSDP())
sda && push!(sdp_solvers, SemidefiniteProgramming.SDPA())
#mos && push!(sdp_solvers, Mosek.MosekSolver(LOG=0))
#scs && push!(sdp_solvers, SCS.SCSSolver(eps=1e-6,verbose=0))

const error_map = Dict()
grb && (error_map[Gurobi.GurobiSolver] = Gurobi.GurobiError)
cpx && (error_map[CPLEX.CplexSolver] = CPLEX.CplexError)
15 changes: 15 additions & 0 deletions test/prob.dat-s
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
3
4
1 1 1 2
-3.000000000000000000e+00 0.000000000000000000e+00 -2.000000000000000000e+00
0 1 1 1 -2.000000000000000000e+00
0 2 1 1 1.000000000000000000e+00
1 1 1 1 -2.000000000000000000e+00
1 2 1 1 1.000000000000000000e+00
1 3 1 1 1.000000000000000000e+00
1 4 1 1 1.000000000000000000e+00
2 4 1 2 5.000000000000000000e-01
3 1 1 1 -1.000000000000000000e+00
3 2 1 1 1.000000000000000000e+00
3 3 1 1 -1.000000000000000000e+00
3 4 2 2 1.000000000000000000e+00
20 changes: 3 additions & 17 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,14 @@
using JuMP
using Base.Test

# Static tests - don't require a solver
include("print.jl")
include("variable.jl")
include("expr.jl")
include("operator.jl")
include("macros.jl")

# Fuzzer of macros to build expressions
include("fuzzer.jl")

# Load solvers
include("solvers.jl")

# Solver-dependent tests
include("model.jl"); length( lp_solvers) == 0 && warn("Model tests not run!")
include("probmod.jl"); length( lp_solvers) == 0 && warn("Prob. mod. tests not run!")
include("callback.jl"); length( lazy_solvers) == 0 && warn("Callback tests not run!")
include("qcqpmodel.jl"); length( quad_solvers) == 0 && warn("Quadratic tests not run!")
include("nonlinear.jl"); length( nlp_solvers) == 0 && warn("Nonlinear tests not run!")
length(minlp_solvers) == 0 && warn("Mixed-integer Nonlinear tests not run!")
#include("nonlinear.jl"); length( nlp_solvers) == 0 && warn("Nonlinear tests not run!")
# length(minlp_solvers) == 0 && warn("Mixed-integer Nonlinear tests not run!")
include("sdp.jl"); length( sdp_solvers) == 0 && warn("Semidefinite tests not run!")
include("socduals.jl"); length(conic_solvers_with_duals) == 0 && warn("Conic solvers with duals tests not run!")
#include("socduals.jl"); length(conic_solvers_with_duals) == 0 && warn("Conic solvers with duals tests not run!")
# Throw an error if anything failed
#FactCheck.exitstatus()

Expand Down
8 changes: 4 additions & 4 deletions test/sdp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ ispsd(x::JuMP.JuMPArray) = ispsd(x.innerArray)
@variable(m, X[1:2,1:2], SDP)
c = @constraint(m, X[1,1]+X[2,2] == 1)
@objective(m, Min, 2*X[1,1]+2*X[1,2])
@test_throws ErrorException getdual(X)
@test all(isnan.(getdual(X)))
status = solve(m)

@test status == :Optimal
Expand All @@ -599,7 +599,7 @@ ispsd(x::JuMP.JuMPArray) = ispsd(x.innerArray)
@variable(m, y)
c = @SDconstraint(m, [2-y 1; 1 -y] >= 0)
@objective(m, Max, y)
@test_throws ErrorException getdual(c)
@test all(isnan(getdual(c)))
status = solve(m)

@test status == :Optimal
Expand All @@ -625,7 +625,7 @@ ispsd(x::JuMP.JuMPArray) = ispsd(x.innerArray)
@variable(m, y)
c = @SDconstraint(m, [0 y; y 0] <= [1 0; 0 0])
@objective(m, Max, y)
@test_throws ErrorException getdual(c)
@test all(isnan(getdual(c)))
status = solve(m)

@test status == :Optimal
Expand All @@ -645,7 +645,7 @@ ispsd(x::JuMP.JuMPArray) = ispsd(x.innerArray)
@variable(m, X[1:2,1:2], SDP)
c = @constraint(m, 2*X[1,2] == 1)
@objective(m, Min, X[1,1])
@test_throws ErrorException getdual(X)
@test all(isnan(getdual(X)))
status = solve(m)

@test status == :Optimal
Expand Down
25 changes: 25 additions & 0 deletions test/sdpgap.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
facts("[sdp] Test SDP with finite nonzero duality gap") do
for solver in sdp_solvers
m = Model(solver=solver)
@variable(m, y1)
@variable(m, y2)
c = @SDconstraint(m, [y2 0 0; 0 y1 y2; 0 y2 0] <= [1 0 0; 0 0 0; 0 0 0])
@objective(m, Max, y2)
solve(m)

# The dual problem has objective
# min X_11
# and the optimal value of the dual objective is 1 with X_11 = 1
# However the objective value of the primal is 0
# See Example 2.14 of:
# Blekherman, G., Parrilo, P. A., & Thomas, R. R. (Eds.).
# Semidefinite optimization and convex algebraic geometry SIAM 2013

@fact getobjectivevalue(m) --> roughly(0, 1e-5)
@fact getvalue(y2) --> roughly(0, 1e-5)
X = getdual(c)
@fact getvalue(X[1,1]) --> roughly(1, 1e-5)
@fact getvalue(X[2,2]) --> roughly(0, 1e-5)
@fact getvalue(X[2,3]) --> roughly(0, 1e-5)
end
end
8 changes: 8 additions & 0 deletions test/semidef.dat-s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
1
2
1.0
0 1 1 2 -0.9999999999999998
0 1 1 1 -2.0
1 1 2 2 1.0
1 1 1 1 1.0
7 changes: 7 additions & 0 deletions test/semidef.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
4.142135622877822776e-01
1 1 1 1 2.414213562373094923e+00
1 1 1 2 9.999999999999997780e-01
1 1 2 2 4.142135623730949234e-01
2 1 1 1 1.464466568186767181e-01
2 1 1 2 -3.535534379959800466e-01
2 1 2 2 8.535533431367539059e-01
9 changes: 9 additions & 0 deletions test/test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using JuMP

A = [2.0 0.0;
0.0 1.0]

m = Model()
@variable(m, X[1:2,1:2], SDP)

println(@SDconstraint(m, X >= A))
4 changes: 4 additions & 0 deletions test/tmp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using JuMP
m = Model()
@variable(m, X[1:3,1:3], SDP)
getdual(X)

0 comments on commit 0e21fda

Please sign in to comment.