Skip to content

Commit

Permalink
Merge pull request #105 from JuliaOpt/loadtwice
Browse files Browse the repository at this point in the history
fix multiple loadproblem! calls
  • Loading branch information
mlubin authored Jan 4, 2017
2 parents 0fa0c77 + ffbb200 commit 6dd11c2
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 30 deletions.
4 changes: 3 additions & 1 deletion src/CplexSolverInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function CplexMathProgModel(;options...)
set_param!(env, string(name), value)
end

m = CplexMathProgModel(_Model(env), nothing, nothing, nothing, nothing, nothing, nothing, NaN)
m = CplexMathProgModel(Model(env), nothing, nothing, nothing, nothing, nothing, nothing, NaN)
return m
end

Expand Down Expand Up @@ -76,6 +76,8 @@ function loadproblem!(m::CplexMathProgModel, filename::String)
end

function loadproblem!(m::CplexMathProgModel, A, collb, colub, obj, rowlb, rowub, sense)
# throw away old model but keep env
m.inner = Model(m.inner.env)
add_vars!(m.inner, float(obj), float(collb), float(colub))

neginf = typemin(eltype(rowlb))
Expand Down
33 changes: 32 additions & 1 deletion src/cpx_env.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
type Env
ptr::Ptr{Void}
num_models::Int
finalize_called::Bool

function Env()
stat = Array(Cint, 1)
tmp = @cpx_ccall(openCPLEX, Ptr{Void}, (Ptr{Cint},), stat)
if tmp == C_NULL
error("CPLEX: Error creating environment")
end
new(tmp)
env = new(tmp, 0, false)
finalizer(env, env -> begin
if env.num_models == 0
close_CPLEX(env)
else
env.finalize_called = true
end
end)
env
end
end

Expand All @@ -18,6 +28,27 @@ function is_valid(env::Env)
env.ptr != C_NULL
end

function notify_new_model(env::Env)
env.num_models += 1
end

function notify_freed_model(env::Env)
@assert env.num_models > 0
env.num_models -= 1
if env.num_models <= 0 && env.finalize_called
close_CPLEX(env)
end
end

function close_CPLEX(env::Env)
tmp = Ptr{Void}[env.ptr]
stat = @cpx_ccall(closeCPLEX, Cint, (Ptr{Void},), tmp)
env.ptr = C_NULL
if stat != 0
throw(CplexError(env, stat))
end
end

function set_logfile(env::Env, filename::String)
@assert isascii(filename)
fp = @cpx_ccall(fopen, Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}), filename, "w")
Expand Down
34 changes: 6 additions & 28 deletions src/cpx_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ type Model
end

function Model(env::Env, lp::Ptr{Void})
notify_new_model(env)
model = Model(env, lp, false, false, nothing, Cint[0])
finalizer(model, free_problem)
finalizer(model, m -> begin
free_problem(m)
notify_freed_model(env)
end)
set_terminate(model)
model
end

function Model(env::Env, name::String)
function Model(env::Env, name::String="CPLEX.jl")
@assert is_valid(env)
stat = Array(Cint, 1)
tmp = @cpx_ccall(createprob, Ptr{Void}, (Ptr{Void}, Ptr{Cint}, Ptr{Cchar}), env.ptr, stat, name)
Expand All @@ -24,24 +28,6 @@ function Model(env::Env, name::String)
return Model(env, tmp)
end

# internal function that wraps finalizer for model and environment together
function _Model(env::Env)
@assert is_valid(env)
stat = Array(Cint, 1)
tmp = @cpx_ccall(createprob, Ptr{Void}, (Ptr{Void}, Ptr{Cint}, Ptr{Cchar}), env.ptr, stat, "CPLEX.jl")
if tmp == C_NULL
throw(CplexError(model.env, stat))
end
model = Model(env, tmp, false, false, nothing, Cint[0])
finalizer(model, model::Model -> begin
tmp = model.env
free_problem(model)
close_CPLEX(tmp)
end)
set_terminate(model)
return model
end

function read_model(model::Model, filename::String)
stat = @cpx_ccall(readcopyprob, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Cchar}, Ptr{Cchar}), model.env.ptr, model.lp, filename, C_NULL)
if stat != 0
Expand Down Expand Up @@ -171,14 +157,6 @@ function free_problem(model::Model)
end
end

function close_CPLEX(env::Env)
tmp = Ptr{Void}[env.ptr]
stat = @cpx_ccall(closeCPLEX, Cint, (Ptr{Void},), tmp)
if stat != 0
throw(CplexError(env, stat))
end
end

function set_terminate(model::Model)
stat = @cpx_ccall(setterminate, Cint, (Ptr{Void},Ptr{Cint}), model.env.ptr, model.terminator)
if stat != 0
Expand Down
14 changes: 14 additions & 0 deletions test/env.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using CPLEX, MathProgBase, Base.Test

@testset "Use loadproblem! twice" begin
solver = CplexSolver()
# Check that the env for each model is the same
m = MathProgBase.LinearQuadraticModel(solver)
env = m.inner.env
MathProgBase.loadproblem!(m, [1 0], [1, 1], [1, Inf], [1, 0], [0], [Inf], :Min)
@test m.inner.env === env
@test CPLEX.is_valid(env)
MathProgBase.loadproblem!(m, [0 1], [-Inf, 1], [1, 1], [0, 1], [-Inf], [0], :Min)
@test m.inner.env === env
@test CPLEX.is_valid(env)
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tests = ["low_level_api",
"qp_01",
"qp_02",
"qcqp_01",
"env",
"mathprog"]

for t in tests
Expand Down

0 comments on commit 6dd11c2

Please sign in to comment.