Skip to content

Commit

Permalink
Fix lns init phase + constraint handler mix for minizinc subsolvers
Browse files Browse the repository at this point in the history
- Fix ConstraintHandlerMix for minizinc subsolvers (and add test)
- Raise errors when lns has no initial_solution_provider but does not
  skip the initial phase or when it does not return a solution
  • Loading branch information
nhuet committed Oct 17, 2024
1 parent 6373c72 commit 6c6fba3
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 12 deletions.
31 changes: 19 additions & 12 deletions discrete_optimization/generic_tools/lns_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,25 @@ def solve(

self.init_model(**kwargs)

if (
not skip_initial_solution_provider
and self.initial_solution_provider is not None
):
if skip_initial_solution_provider:
best_objective = (
float("inf") if sense == ModeOptim.MINIMIZATION else -float("inf")
)
store_lns = None
stopping = False
else:
if self.initial_solution_provider is None:
raise ValueError(
"`initial_solution_provider` cannot be None "
"if `skip_initial_solution_provider` is False."
)
store_lns = self.initial_solution_provider.get_starting_solution()
store_lns = self.post_process_solution.build_other_solution(store_lns)
init_solution, objective = store_lns.get_best_solution_fit()
if init_solution is None:
satisfy = False
raise RuntimeError(
"`initial_solution_provider` + `post_process_solution` gave no solution."
)
else:
satisfy = self.problem.satisfy(init_solution)
logger.debug(f"Satisfy Initial solution {satisfy}")
Expand All @@ -348,12 +358,6 @@ def solve(
best_objective = objective
# end of step callback: stopping?
stopping = callbacks_list.on_step_end(step=0, res=store_lns, solver=self)
else:
best_objective = (
float("inf") if sense == ModeOptim.MINIMIZATION else -float("inf")
)
store_lns = None
stopping = False

result_store: ResultStorage
lsn_contraints: Optional[Iterable[Any]] = None
Expand Down Expand Up @@ -590,7 +594,10 @@ def adding_constraint_from_results_store(
self.last_index_param = choice
self.status[self.last_index_param]["nb_usage"] += 1
logger.debug(f"Status {self.status}")
return ch.adding_constraint_from_results_store(solver, result_storage, **kwargs)
constraints = ch.adding_constraint_from_results_store(
solver=solver, result_storage=result_storage, **kwargs
)
return constraints

def remove_constraints_from_previous_iteration(
self, solver: SolverDO, previous_constraints: Iterable[Any], **kwargs: Any
Expand Down
28 changes: 28 additions & 0 deletions tests/rcpsp/solvers/test_lns.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
from discrete_optimization.generic_rcpsp_tools.solvers.lns_cp import (
LnsCpMznGenericRcpspSolver,
)
from discrete_optimization.generic_rcpsp_tools.solvers.lns_cp.neighbor_builder import (
mix,
)
from discrete_optimization.generic_tools.callbacks.early_stoppers import TimerStopper
from discrete_optimization.generic_tools.cp_tools import ParametersCp
from discrete_optimization.generic_tools.lns_cp import LnsCpMzn
from discrete_optimization.rcpsp.parser import get_data_available, parse_file
from discrete_optimization.rcpsp.problem import RcpspProblem
from discrete_optimization.rcpsp.solvers.cp_mzn import CpRcpspSolver


@pytest.mark.parametrize(
Expand All @@ -34,3 +39,26 @@ def test_lns_solver(file_name):
)
sol, fit = results.get_best_solution_fit()
assert rcpsp_problem.satisfy(sol)


@pytest.mark.parametrize(
"file_name",
["j1201_1.sm"],
)
def test_mix_constraints_handlers(file_name):
files_available = get_data_available()
file = [f for f in files_available if file_name in f][0]
rcpsp_problem: RcpspProblem = parse_file(file)

constraints_handler = mix(rcpsp_problem=rcpsp_problem)
solver = LnsCpMzn(
problem=rcpsp_problem,
subsolver=CpRcpspSolver(problem=rcpsp_problem),
constraint_handler=constraints_handler,
)
solver.init_model()
res = solver.solve(
nb_iteration_lns=5, skip_initial_solution_provider=True, time_limit_subsolver=5
)
sol, fit = res.get_best_solution_fit()
assert rcpsp_problem.satisfy(sol)

0 comments on commit 6c6fba3

Please sign in to comment.