|
|
@ -467,144 +467,147 @@ function get_constraints(
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pydef mutable struct JuMPSolver <: miplearn.solvers.internal.InternalSolver
|
|
|
|
function __init_JuMPSolver__()
|
|
|
|
function __init__(self, optimizer_factory)
|
|
|
|
@pydef mutable struct Class <: miplearn.solvers.internal.InternalSolver
|
|
|
|
self.data = JuMPSolverData(
|
|
|
|
function __init__(self, optimizer_factory)
|
|
|
|
optimizer_factory,
|
|
|
|
self.data = JuMPSolverData(
|
|
|
|
Dict(), # varname_to_var
|
|
|
|
optimizer_factory,
|
|
|
|
Dict(), # cname_to_constr
|
|
|
|
Dict(), # varname_to_var
|
|
|
|
nothing, # instance
|
|
|
|
Dict(), # cname_to_constr
|
|
|
|
nothing, # model
|
|
|
|
nothing, # instance
|
|
|
|
[], # bin_vars
|
|
|
|
nothing, # model
|
|
|
|
Dict(), # solution
|
|
|
|
[], # bin_vars
|
|
|
|
[], # reduced_costs
|
|
|
|
Dict(), # solution
|
|
|
|
Dict(), # dual_values
|
|
|
|
[], # reduced_costs
|
|
|
|
)
|
|
|
|
Dict(), # dual_values
|
|
|
|
end
|
|
|
|
)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function add_constraints(self, cf)
|
|
|
|
function add_constraints(self, cf)
|
|
|
|
lhs = cf.lhs
|
|
|
|
lhs = cf.lhs
|
|
|
|
if lhs isa Matrix
|
|
|
|
if lhs isa Matrix
|
|
|
|
# Undo incorrect automatic conversion performed by PyCall
|
|
|
|
# Undo incorrect automatic conversion performed by PyCall
|
|
|
|
lhs = [col[:] for col in eachcol(lhs)]
|
|
|
|
lhs = [col[:] for col in eachcol(lhs)]
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
add_constraints(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
lhs=lhs,
|
|
|
|
|
|
|
|
rhs=cf.rhs,
|
|
|
|
|
|
|
|
senses=cf.senses,
|
|
|
|
|
|
|
|
names=cf.names,
|
|
|
|
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
add_constraints(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
lhs=lhs,
|
|
|
|
|
|
|
|
rhs=cf.rhs,
|
|
|
|
|
|
|
|
senses=cf.senses,
|
|
|
|
|
|
|
|
names=cf.names,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function are_constraints_satisfied(self, cf; tol=1e-5)
|
|
|
|
function are_constraints_satisfied(self, cf; tol=1e-5)
|
|
|
|
lhs = cf.lhs
|
|
|
|
lhs = cf.lhs
|
|
|
|
if lhs isa Matrix
|
|
|
|
if lhs isa Matrix
|
|
|
|
# Undo incorrect automatic conversion performed by PyCall
|
|
|
|
# Undo incorrect automatic conversion performed by PyCall
|
|
|
|
lhs = [col[:] for col in eachcol(lhs)]
|
|
|
|
lhs = [col[:] for col in eachcol(lhs)]
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
return are_constraints_satisfied(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
lhs=lhs,
|
|
|
|
|
|
|
|
rhs=cf.rhs,
|
|
|
|
|
|
|
|
senses=cf.senses,
|
|
|
|
|
|
|
|
tol=tol,
|
|
|
|
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return are_constraints_satisfied(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
lhs=lhs,
|
|
|
|
|
|
|
|
rhs=cf.rhs,
|
|
|
|
|
|
|
|
senses=cf.senses,
|
|
|
|
|
|
|
|
tol=tol,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
build_test_instance_infeasible(self) =
|
|
|
|
build_test_instance_infeasible(self) =
|
|
|
|
build_test_instance_infeasible()
|
|
|
|
build_test_instance_infeasible()
|
|
|
|
|
|
|
|
|
|
|
|
build_test_instance_knapsack(self) =
|
|
|
|
build_test_instance_knapsack(self) =
|
|
|
|
build_test_instance_knapsack()
|
|
|
|
build_test_instance_knapsack()
|
|
|
|
|
|
|
|
|
|
|
|
clone(self) = JuMPSolver(self.data.optimizer_factory)
|
|
|
|
clone(self) = JuMPSolver(self.data.optimizer_factory)
|
|
|
|
|
|
|
|
|
|
|
|
fix(self, solution) =
|
|
|
|
fix(self, solution) =
|
|
|
|
fix!(self.data, solution)
|
|
|
|
fix!(self.data, solution)
|
|
|
|
|
|
|
|
|
|
|
|
get_solution(self) =
|
|
|
|
get_solution(self) =
|
|
|
|
isempty(self.data.solution) ? nothing : self.data.solution
|
|
|
|
isempty(self.data.solution) ? nothing : self.data.solution
|
|
|
|
|
|
|
|
|
|
|
|
get_constraints(
|
|
|
|
get_constraints(
|
|
|
|
self;
|
|
|
|
self;
|
|
|
|
with_static=true,
|
|
|
|
with_static=true,
|
|
|
|
with_sa=true,
|
|
|
|
with_sa=true,
|
|
|
|
with_lhs=true,
|
|
|
|
with_lhs=true,
|
|
|
|
) = get_constraints(
|
|
|
|
) = get_constraints(
|
|
|
|
self.data,
|
|
|
|
self.data,
|
|
|
|
with_static=with_static,
|
|
|
|
with_static=with_static,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
get_constraint_attrs(self) = [
|
|
|
|
get_constraint_attrs(self) = [
|
|
|
|
# "basis_status",
|
|
|
|
# "basis_status",
|
|
|
|
"categories",
|
|
|
|
"categories",
|
|
|
|
"dual_values",
|
|
|
|
"dual_values",
|
|
|
|
"lazy",
|
|
|
|
"lazy",
|
|
|
|
"lhs",
|
|
|
|
"lhs",
|
|
|
|
"names",
|
|
|
|
"names",
|
|
|
|
"rhs",
|
|
|
|
"rhs",
|
|
|
|
# "sa_rhs_down",
|
|
|
|
# "sa_rhs_down",
|
|
|
|
# "sa_rhs_up",
|
|
|
|
# "sa_rhs_up",
|
|
|
|
"senses",
|
|
|
|
"senses",
|
|
|
|
# "slacks",
|
|
|
|
# "slacks",
|
|
|
|
"user_features",
|
|
|
|
"user_features",
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
get_variables(
|
|
|
|
get_variables(
|
|
|
|
self;
|
|
|
|
self;
|
|
|
|
with_static=true,
|
|
|
|
with_static=true,
|
|
|
|
with_sa=true,
|
|
|
|
with_sa=true,
|
|
|
|
) = get_variables(self.data; with_static=with_static)
|
|
|
|
) = get_variables(self.data; with_static=with_static)
|
|
|
|
|
|
|
|
|
|
|
|
get_variable_attrs(self) = [
|
|
|
|
get_variable_attrs(self) = [
|
|
|
|
"names",
|
|
|
|
"names",
|
|
|
|
# "basis_status",
|
|
|
|
# "basis_status",
|
|
|
|
"categories",
|
|
|
|
"categories",
|
|
|
|
"lower_bounds",
|
|
|
|
"lower_bounds",
|
|
|
|
"obj_coeffs",
|
|
|
|
"obj_coeffs",
|
|
|
|
"reduced_costs",
|
|
|
|
"reduced_costs",
|
|
|
|
# "sa_lb_down",
|
|
|
|
# "sa_lb_down",
|
|
|
|
# "sa_lb_up",
|
|
|
|
# "sa_lb_up",
|
|
|
|
# "sa_obj_down",
|
|
|
|
# "sa_obj_down",
|
|
|
|
# "sa_obj_up",
|
|
|
|
# "sa_obj_up",
|
|
|
|
# "sa_ub_down",
|
|
|
|
# "sa_ub_down",
|
|
|
|
# "sa_ub_up",
|
|
|
|
# "sa_ub_up",
|
|
|
|
"types",
|
|
|
|
"types",
|
|
|
|
"upper_bounds",
|
|
|
|
"upper_bounds",
|
|
|
|
"user_features",
|
|
|
|
"user_features",
|
|
|
|
"values",
|
|
|
|
"values",
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
is_infeasible(self) =
|
|
|
|
is_infeasible(self) =
|
|
|
|
is_infeasible(self.data)
|
|
|
|
is_infeasible(self.data)
|
|
|
|
|
|
|
|
|
|
|
|
remove_constraints(self, names) =
|
|
|
|
remove_constraints(self, names) =
|
|
|
|
remove_constraints(
|
|
|
|
remove_constraints(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
[n for n in names],
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_instance(self, instance, model=nothing) =
|
|
|
|
|
|
|
|
set_instance!(self.data, instance, model=model)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_warm_start(self, solution) =
|
|
|
|
|
|
|
|
set_warm_start!(self.data, solution)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
solve(
|
|
|
|
|
|
|
|
self;
|
|
|
|
|
|
|
|
tee=false,
|
|
|
|
|
|
|
|
iteration_cb=nothing,
|
|
|
|
|
|
|
|
lazy_cb=nothing,
|
|
|
|
|
|
|
|
user_cut_cb=nothing,
|
|
|
|
|
|
|
|
) = solve(
|
|
|
|
self.data,
|
|
|
|
self.data,
|
|
|
|
[n for n in names],
|
|
|
|
tee=tee,
|
|
|
|
|
|
|
|
iteration_cb=iteration_cb,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
set_instance(self, instance, model=nothing) =
|
|
|
|
solve_lp(self; tee=false) =
|
|
|
|
set_instance!(self.data, instance, model=model)
|
|
|
|
solve_lp(self.data, tee=tee)
|
|
|
|
|
|
|
|
end
|
|
|
|
set_warm_start(self, solution) =
|
|
|
|
copy!(JuMPSolver, Class)
|
|
|
|
set_warm_start!(self.data, solution)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
solve(
|
|
|
|
|
|
|
|
self;
|
|
|
|
|
|
|
|
tee=false,
|
|
|
|
|
|
|
|
iteration_cb=nothing,
|
|
|
|
|
|
|
|
lazy_cb=nothing,
|
|
|
|
|
|
|
|
user_cut_cb=nothing,
|
|
|
|
|
|
|
|
) = solve(
|
|
|
|
|
|
|
|
self.data,
|
|
|
|
|
|
|
|
tee=tee,
|
|
|
|
|
|
|
|
iteration_cb=iteration_cb,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
solve_lp(self; tee=false) =
|
|
|
|
|
|
|
|
solve_lp(self.data, tee=tee)
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|