Rewrite FileInstance

This commit is contained in:
2021-07-28 07:59:15 -05:00
parent c3ba762868
commit 9362c3b268
11 changed files with 294 additions and 276 deletions

View File

@@ -41,6 +41,8 @@ function _optimize_and_capture_output!(model; tee::Bool=false)
rm(logname)
if tee
println(log)
flush(stdout)
Base.Libc.flush_cstdio()
end
return log
end
@@ -150,7 +152,7 @@ function build_test_instance_knapsack()
@objective(model, Max, sum(x[i-1] * prices[i] for i in 1:n))
@constraint(model, eq_capacity, sum(x[i-1] * weights[i] for i in 1:n) - z == 0)
return PyJuMPInstance(model)
return JuMPInstance(model).py
end
@@ -159,7 +161,7 @@ function build_test_instance_infeasible()
@variable(model, x, Bin)
@objective(model, Max, x)
@constraint(model, x >= 2)
return PyJuMPInstance(model)
return JuMPInstance(model).py
end
@@ -389,6 +391,8 @@ end
function get_constraints(
data::JuMPSolverData;
with_static::Bool,
with_sa::Bool,
with_lhs::Bool,
)
names = []
senses, lhs, rhs = nothing, nothing, nothing
@@ -420,24 +424,26 @@ function get_constraints(
if with_static
if ftype == JuMP.AffExpr
push!(
lhs,
[
(
MOI.get(
if with_lhs
push!(
lhs,
[
(
MOI.get(
constr.model.moi_backend,
MOI.VariableName(),
term.variable_index
),
term.coefficient,
)
for term in MOI.get(
constr.model.moi_backend,
MOI.VariableName(),
term.variable_index
),
term.coefficient,
)
for term in MOI.get(
constr.model.moi_backend,
MOI.ConstraintFunction(),
constr.index,
).terms
]
)
MOI.ConstraintFunction(),
constr.index,
).terms
]
)
end
if stype == MOI.EqualTo{Float64}
push!(senses, "=")
push!(rhs, cset.value)
@@ -535,6 +541,8 @@ function __init_JuMPSolver__()
) = get_constraints(
self.data,
with_static=with_static,
with_sa=with_sa,
with_lhs=with_lhs,
)
get_constraint_attrs(self) = [

View File

@@ -17,6 +17,8 @@ function LearningSolver(
mode::AbstractString = "exact",
simulate_perfect::Bool = false,
solve_lp::Bool = true,
extract_sa::Bool = true,
extract_lhs::Bool = true,
)::LearningSolver
return LearningSolver(
miplearn.LearningSolver(
@@ -25,6 +27,8 @@ function LearningSolver(
solve_lp=solve_lp,
simulate_perfect=simulate_perfect,
components=components,
extract_lhs=extract_lhs,
extract_sa=extract_sa,
),
optimizer_factory,
)
@@ -47,66 +51,83 @@ end
function fit!(solver::LearningSolver, instances::Vector{<:Instance})
@python_call solver.py.fit([instance.py for instance in instances])
return
end
function parallel_solve!(solver::LearningSolver, instances::Vector{FileInstance})
filenames = [instance.filename for instance in instances]
function _solve(
solver_filename,
instance_filename;
discard_output::Bool,
)
@info "solve $instance_filename"
solver = load_solver(solver_filename)
solver.py._silence_miplearn_logger()
stats = solve!(
solver,
FileInstance(instance_filename),
discard_output = discard_output,
)
solver.py._restore_miplearn_logger()
GC.gc()
@info "solve $instance_filename [done]"
return stats
end
function parallel_solve!(
solver::LearningSolver,
instances::Vector{FileInstance};
discard_output::Bool = false,
)
instance_filenames = [instance.filename for instance in instances]
solver_filename = tempname()
save(solver_filename, solver)
@sync @distributed for filename in filenames
s = load_solver(solver_filename)
solve!(s, FileInstance(filename))
nothing
end
return pmap(
instance_filename -> _solve(
solver_filename,
instance_filename,
discard_output = discard_output,
),
instance_filenames,
on_error=identity,
)
end
function save(filename::AbstractString, solver::LearningSolver)
@info "Writing: $filename"
time = @elapsed begin
# Pickle solver.py
internal_solver = solver.py.internal_solver
internal_solver_prototype = solver.py.internal_solver_prototype
solver.py.internal_solver = nothing
solver.py.internal_solver_prototype = nothing
solver_py_filename = tempname()
miplearn.write_pickle_gz(solver.py, solver_py_filename, quiet=true)
solver_py = read(solver_py_filename)
solver.py.internal_solver = internal_solver
solver.py.internal_solver_prototype = internal_solver_prototype
jldsave(
filename;
miplearn_version="0.2",
solver_py=solver_py,
optimizer_factory=solver.optimizer_factory,
)
end
@info @sprintf("File written in %.2f seconds", time)
internal_solver = solver.py.internal_solver
internal_solver_prototype = solver.py.internal_solver_prototype
solver.py.internal_solver = nothing
solver.py.internal_solver_prototype = nothing
solver_py_filename = tempname()
miplearn.write_pickle_gz(solver.py, solver_py_filename)
solver_py = read(solver_py_filename)
solver.py.internal_solver = internal_solver
solver.py.internal_solver_prototype = internal_solver_prototype
jldsave(
filename;
miplearn_version="0.2",
solver_py=solver_py,
optimizer_factory=solver.optimizer_factory,
)
return
end
function load_solver(filename::AbstractString)::LearningSolver
@info "Reading: $filename"
solver = nothing
time = @elapsed begin
jldopen(filename, "r") do file
_check_miplearn_version(file)
solve_py_filename = tempname()
write(solve_py_filename, file["solver_py"])
solver_py = miplearn.read_pickle_gz(solve_py_filename, quiet=true)
internal_solver = JuMPSolver(file["optimizer_factory"])
solver_py.internal_solver_prototype = internal_solver
solver = LearningSolver(
solver_py,
file["optimizer_factory"],
)
end
jldopen(filename, "r") do file
_check_miplearn_version(file)
solve_py_filename = tempname()
write(solve_py_filename, file["solver_py"])
solver_py = miplearn.read_pickle_gz(solve_py_filename)
internal_solver = JuMPSolver(file["optimizer_factory"])
solver_py.internal_solver_prototype = internal_solver
return LearningSolver(
solver_py,
file["optimizer_factory"],
)
end
@info @sprintf("File read in %.2f seconds", time)
return solver
end

View File

@@ -4,12 +4,12 @@
function init_miplearn_ext(model)::Dict
if :miplearn keys(model.ext)
model.ext[:miplearn] = Dict{Symbol, Any}()
model.ext[:miplearn][:instance_features] = [0.0]
model.ext[:miplearn][:variable_features] = Dict{AbstractString, Vector{Float64}}()
model.ext[:miplearn][:variable_categories] = Dict{AbstractString, String}()
model.ext[:miplearn][:constraint_features] = Dict{AbstractString, Vector{Float64}}()
model.ext[:miplearn][:constraint_categories] = Dict{AbstractString, String}()
model.ext[:miplearn] = Dict()
model.ext[:miplearn]["instance_features"] = [0.0]
model.ext[:miplearn]["variable_features"] = Dict{AbstractString, Vector{Float64}}()
model.ext[:miplearn]["variable_categories"] = Dict{AbstractString, String}()
model.ext[:miplearn]["constraint_features"] = Dict{AbstractString, Vector{Float64}}()
model.ext[:miplearn]["constraint_categories"] = Dict{AbstractString, String}()
end
return model.ext[:miplearn]
end
@@ -17,7 +17,7 @@ end
function set_features!(m::Model, f::Array{Float64})::Nothing
ext = init_miplearn_ext(m)
ext[:instance_features] = f
ext["instance_features"] = f
return
end
@@ -25,7 +25,7 @@ end
function set_features!(v::VariableRef, f::Array{Float64})::Nothing
ext = init_miplearn_ext(v.model)
n = _get_and_check_name(v)
ext[:variable_features][n] = f
ext["variable_features"][n] = f
return
end
@@ -33,7 +33,7 @@ end
function set_category!(v::VariableRef, category::String)::Nothing
ext = init_miplearn_ext(v.model)
n = _get_and_check_name(v)
ext[:variable_categories][n] = category
ext["variable_categories"][n] = category
return
end
@@ -41,7 +41,7 @@ end
function set_features!(c::ConstraintRef, f::Array{Float64})::Nothing
ext = init_miplearn_ext(c.model)
n = _get_and_check_name(c)
ext[:constraint_features][n] = f
ext["constraint_features"][n] = f
return
end
@@ -49,7 +49,7 @@ end
function set_category!(c::ConstraintRef, category::String)::Nothing
ext = init_miplearn_ext(c.model)
n = _get_and_check_name(c)
ext[:constraint_categories][n] = category
ext["constraint_categories"][n] = category
return
end