diff --git a/discrete_optimization/generic_tools/cp_tools.py b/discrete_optimization/generic_tools/cp_tools.py index 96f1daf7e..b1eea3d06 100644 --- a/discrete_optimization/generic_tools/cp_tools.py +++ b/discrete_optimization/generic_tools/cp_tools.py @@ -87,8 +87,6 @@ class ParametersCP: """ intermediate_solution: bool - all_solutions: bool - nr_solutions: int free_search: bool multiprocess: bool nb_process: int @@ -97,8 +95,6 @@ class ParametersCP: def __init__( self, intermediate_solution: bool, - all_solutions: bool, - nr_solutions: int, free_search: bool = False, multiprocess: bool = False, nb_process: int = 1, @@ -107,12 +103,8 @@ def __init__( """ :param intermediate_solution: retrieve intermediate solutions - :param all_solutions: returns all solutions found by the cp solver - :param nr_solutions: the requested number of solutions """ self.intermediate_solution = intermediate_solution - self.all_solutions = all_solutions - self.nr_solutions = nr_solutions self.free_search = free_search self.multiprocess = multiprocess self.nb_process = nb_process @@ -122,8 +114,6 @@ def __init__( def default() -> "ParametersCP": return ParametersCP( intermediate_solution=True, - all_solutions=False, - nr_solutions=1000, free_search=False, optimisation_level=1, ) @@ -132,8 +122,6 @@ def default() -> "ParametersCP": def default_cpsat() -> "ParametersCP": return ParametersCP( intermediate_solution=True, - all_solutions=False, - nr_solutions=1000, free_search=False, multiprocess=True, nb_process=6, @@ -144,8 +132,6 @@ def default_cpsat() -> "ParametersCP": def default_fast_lns() -> "ParametersCP": return ParametersCP( intermediate_solution=True, - all_solutions=False, - nr_solutions=1000, free_search=False, ) @@ -153,16 +139,12 @@ def default_fast_lns() -> "ParametersCP": def default_free() -> "ParametersCP": return ParametersCP( intermediate_solution=True, - all_solutions=False, - nr_solutions=1000, free_search=True, ) def copy(self) -> "ParametersCP": return ParametersCP( intermediate_solution=self.intermediate_solution, - all_solutions=self.all_solutions, - nr_solutions=self.nr_solutions, free_search=self.free_search, multiprocess=self.multiprocess, nb_process=self.nb_process, diff --git a/discrete_optimization/generic_tools/lp_tools.py b/discrete_optimization/generic_tools/lp_tools.py index 5d5b7fd62..56f3a6cab 100644 --- a/discrete_optimization/generic_tools/lp_tools.py +++ b/discrete_optimization/generic_tools/lp_tools.py @@ -63,14 +63,12 @@ def __init__( mip_gap_abs: float, mip_gap: float, retrieve_all_solution: bool, - n_solutions_max: int, pool_search_mode: int = 0, ): self.pool_solutions = pool_solutions self.mip_gap_abs = mip_gap_abs self.mip_gap = mip_gap self.retrieve_all_solution = retrieve_all_solution - self.n_solutions_max = n_solutions_max self.pool_search_mode = pool_search_mode @staticmethod @@ -80,7 +78,6 @@ def default() -> "ParametersMilp": mip_gap_abs=0.0000001, mip_gap=0.000001, retrieve_all_solution=True, - n_solutions_max=10000, ) @@ -101,7 +98,7 @@ def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage: """ if parameters_milp.retrieve_all_solution: - n_solutions = min(parameters_milp.n_solutions_max, self.nb_solutions) + n_solutions = self.nb_solutions else: n_solutions = 1 list_solution_fits: List[Tuple[Solution, Union[float, TupleFitness]]] = [] @@ -238,7 +235,6 @@ def prepare_model( self.model.sol_pool_size = parameters_milp.pool_solutions if time_limit is not None: self.model.max_seconds = time_limit - self.model.max_solutions = parameters_milp.n_solutions_max def optimize_model( self, @@ -475,7 +471,7 @@ def solve( self.model.time_limit = time_limit self.model.parameters.mip.tolerances.mipgap = parameters_milp.mip_gap listener = None - if parameters_milp.retrieve_all_solution or parameters_milp.n_solutions_max > 1: + if parameters_milp.retrieve_all_solution: class SolutionStorage(SolutionListener): def __init__(self): diff --git a/discrete_optimization/rcpsp/solver/cp_solvers.py b/discrete_optimization/rcpsp/solver/cp_solvers.py index 76434b23b..c4d4e9d4d 100644 --- a/discrete_optimization/rcpsp/solver/cp_solvers.py +++ b/discrete_optimization/rcpsp/solver/cp_solvers.py @@ -1842,6 +1842,8 @@ def solve( self, parameters_cp: Optional[ParametersCP] = None, time_limit: Optional[float] = 100.0, + nr_solutions: int = 1, + all_solutions: bool = False, **args, ): """Solve the CP problem with minizinc @@ -1850,6 +1852,8 @@ def solve( parameters_cp: parameters specific to CP solvers time_limit: the solve process stops after this time limit (in seconds). If None, no time limit is applied. + nr_solutions: of not `all_solutions`, the solve stops after finding `nr_solutions` + all_solutions: if True, do not stop when reaching `nr_solutions` **args: passed to init_model() Returns: @@ -1866,10 +1870,8 @@ def solve( timeout = timedelta(seconds=time_limit) result = self.instance.solve( timeout=timeout, - nr_solutions=parameters_cp.nr_solutions - if not parameters_cp.all_solutions - else None, - all_solutions=parameters_cp.all_solutions, + nr_solutions=nr_solutions if not all_solutions else None, + all_solutions=all_solutions, intermediate_solutions=intermediate_solutions, ) logger.debug(result.status) diff --git a/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py b/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py index 255d7a5b2..1c0c67146 100644 --- a/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py +++ b/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py @@ -430,7 +430,6 @@ def __init__( mip_gap_abs=0.001, mip_gap=0.001, retrieve_all_solution=True, - n_solutions_max=100, ) self.constraint_handler = ConstraintHandlerStartTimeIntervalMRCPSP( problem=problem, fraction_to_fix=0.6, minus_delta=5, plus_delta=5 diff --git a/discrete_optimization/rcpsp/solver/rcpsp_pile.py b/discrete_optimization/rcpsp/solver/rcpsp_pile.py index 0f8a8e60b..24da94a17 100644 --- a/discrete_optimization/rcpsp/solver/rcpsp_pile.py +++ b/discrete_optimization/rcpsp/solver/rcpsp_pile.py @@ -83,10 +83,9 @@ def __init__( } if problem.is_rcpsp_multimode() or problem.is_varying_resource(): solver = CP_MRCPSP_MZN_MODES(problem, cp_solver_name=CPSolverName.CHUFFED) - params_cp = ParametersCP.default() - params_cp.nr_solutions = 1 - params_cp.all_solutions = False - result_storage = solver.solve(parameters_cp=params_cp, time_limit=1) + result_storage = solver.solve( + nr_solutions=1, all_solutions=False, time_limit=1 + ) one_mode_setting = result_storage[0] self.modes_dict = {} for i in range(len(one_mode_setting)): @@ -285,10 +284,9 @@ def __init__( } if problem.is_rcpsp_multimode() or problem.is_varying_resource(): solver = CP_MRCPSP_MZN_MODES(problem, cp_solver_name=CPSolverName.CHUFFED) - params_cp = ParametersCP.default() - params_cp.nr_solutions = 1 - params_cp.all_solutions = False - result_storage = solver.solve(parameters_cp=params_cp, time_limit=1) + result_storage = solver.solve( + nr_solutions=1, all_solutions=False, time_limit=1 + ) one_mode_setting = result_storage[0] self.modes_dict = {} for i in range(len(one_mode_setting)): diff --git a/discrete_optimization/rcpsp_multiskill/multiskill_to_rcpsp.py b/discrete_optimization/rcpsp_multiskill/multiskill_to_rcpsp.py index 08ed68466..377b1d0bc 100644 --- a/discrete_optimization/rcpsp_multiskill/multiskill_to_rcpsp.py +++ b/discrete_optimization/rcpsp_multiskill/multiskill_to_rcpsp.py @@ -44,11 +44,8 @@ def construct_rcpsp_by_worker_type( check_resource_compliance: bool = True, one_worker_type_per_task: bool = False, ): - params_cp = ParametersCP( - intermediate_solution=True, - all_solutions=False, - nr_solutions=100, - ) + params_cp = ParametersCP.default() + params_cp.intermediate_solution = True solver = PrecomputeEmployeesForTasks( ms_rcpsp_model=self.multiskill_model, cp_solver_name=CPSolverName.CHUFFED ) @@ -96,6 +93,8 @@ def construct_rcpsp_by_worker_type( results = solver.solve( parameters_cp=params_cp, time_limit=30, + all_solutions=False, + nr_solutions=100, ) best_overskill_results = min( results, key=lambda x: x.overskill_type diff --git a/discrete_optimization/rcpsp_multiskill/solvers/cp_solvers.py b/discrete_optimization/rcpsp_multiskill/solvers/cp_solvers.py index cb811a5d9..ff073f17c 100644 --- a/discrete_optimization/rcpsp_multiskill/solvers/cp_solvers.py +++ b/discrete_optimization/rcpsp_multiskill/solvers/cp_solvers.py @@ -2213,6 +2213,8 @@ def solve( self, parameters_cp: Optional[ParametersCP] = None, time_limit: Optional[float] = 100.0, + nr_solutions: int = 100, + all_solutions: bool = False, **args, ): """Solve the CP problem with minizinc @@ -2221,6 +2223,8 @@ def solve( parameters_cp: parameters specific to CP solvers time_limit: the solve process stops after this time limit (in seconds). If None, no time limit is applied. + nr_solutions: of not `all_solutions`, the solve stops after finding `nr_solutions` + all_solutions: if True, do not stop when reaching `nr_solutions` **args: passed to init_model() Returns: @@ -2237,8 +2241,9 @@ def solve( timeout = timedelta(seconds=time_limit) result = self.instance.solve( timeout=timeout, - nr_solutions=parameters_cp.nr_solutions, intermediate_solutions=intermediate_solutions, + nr_solutions=nr_solutions, + all_solutions=all_solutions, ) logger.debug(result.status) return self.retrieve_solutions(result=result, parameters_cp=parameters_cp) diff --git a/examples/rcpsp/rcpsp_cpsat_solver_example.py b/examples/rcpsp/rcpsp_cpsat_solver_example.py index 486f40c0a..dcee5b91e 100644 --- a/examples/rcpsp/rcpsp_cpsat_solver_example.py +++ b/examples/rcpsp/rcpsp_cpsat_solver_example.py @@ -30,7 +30,6 @@ def solve_makespan_with_cp_sat(problem: RCPSPModel): solver = CPSatRCPSPSolver(problem) solver.init_model() parameters_cp = ParametersCP.default() - parameters_cp.nr_solutions = 1 parameters_cp.nb_process = 8 result_storage = solver.solve( callbacks=[ @@ -51,7 +50,6 @@ def solve_resource_with_cp_sat(problem: RCPSPModel): solver = CPSatRCPSPSolverCumulativeResource(problem) solver.init_model(weight_on_used_resource=100, weight_on_makespan=1) parameters_cp = ParametersCP.default() - parameters_cp.nr_solutions = 1 parameters_cp.nb_process = 8 result_storage = solver.solve( callbacks=[ diff --git a/tests/facility/test_facility_lp_lns.py b/tests/facility/test_facility_lp_lns.py index 7914f5a80..65f055d21 100644 --- a/tests/facility/test_facility_lp_lns.py +++ b/tests/facility/test_facility_lp_lns.py @@ -50,7 +50,6 @@ def test_facility_lns(): mip_gap=0.0001, mip_gap_abs=0.001, retrieve_all_solution=True, - n_solutions_max=1000, ) solver = LP_Facility_Solver_PyMip( facility_problem, diff --git a/tests/knapsack/test_knapsack_lp_lns_solver.py b/tests/knapsack/test_knapsack_lp_lns_solver.py index fd92e7e01..a54cc85ca 100644 --- a/tests/knapsack/test_knapsack_lp_lns_solver.py +++ b/tests/knapsack/test_knapsack_lp_lns_solver.py @@ -37,7 +37,6 @@ def test_knapsack_lns(): mip_gap=0.0001, mip_gap_abs=0.001, retrieve_all_solution=True, - n_solutions_max=1000, ) solver = LPKnapsack( model, diff --git a/tests/rcpsp/solver/test_rcpsp_cp.py b/tests/rcpsp/solver/test_rcpsp_cp.py index f3d8005b0..0ec161bcb 100644 --- a/tests/rcpsp/solver/test_rcpsp_cp.py +++ b/tests/rcpsp/solver/test_rcpsp_cp.py @@ -73,7 +73,6 @@ def test_cp_sm(optimisation_level): solver = CP_RCPSP_MZN(rcpsp_problem, cp_solver_name=CPSolverName.CHUFFED) solver.init_model(output_type=True) parameters_cp = ParametersCP.default() - parameters_cp.nr_solutions = 1 parameters_cp.optimisation_level = optimisation_level result_storage = solver.solve(parameters_cp=parameters_cp, time_limit=100) solution, fit = result_storage.get_best_solution_fit() @@ -104,7 +103,6 @@ def test_cp_rcp(optimisation_level): solver = CP_RCPSP_MZN(rcpsp_problem, cp_solver_name=CPSolverName.CHUFFED) solver.init_model(output_type=True) parameters_cp = ParametersCP.default() - parameters_cp.nr_solutions = 1 parameters_cp.optimisation_level = optimisation_level result_storage = solver.solve(parameters_cp=parameters_cp, time_limit=20) solution, fit = result_storage.get_best_solution_fit() @@ -192,8 +190,6 @@ def test_ortools_with_cb(caplog, random_seed): file = [f for f in files_available if model in f][0] rcpsp_problem = parse_file(file) solver = CPSatRCPSPSolver(problem=rcpsp_problem) - parameters_cp = ParametersCP.default() - parameters_cp.nr_solutions = 1 class VariablePrinterCallback(Callback): def __init__(self) -> None: @@ -211,9 +207,7 @@ def on_step_end(self, step: int, res: ResultStorage, solver: CPSatRCPSPSolver): callbacks = [VariablePrinterCallback(), TimerStopper(2)] with caplog.at_level(logging.DEBUG): - result_storage = solver.solve( - callbacks=callbacks, parameters_cp=parameters_cp, time_limit=10 - ) + result_storage = solver.solve(callbacks=callbacks, time_limit=10) assert "Solution #1" in caplog.text assert ( diff --git a/tests/rcpsp/solver/test_rcpsp_find_modes.py b/tests/rcpsp/solver/test_rcpsp_find_modes.py index 225ad8706..aa61488e4 100644 --- a/tests/rcpsp/solver/test_rcpsp_find_modes.py +++ b/tests/rcpsp/solver/test_rcpsp_find_modes.py @@ -12,10 +12,7 @@ def test_find_modes(): file = [f for f in files_available if "j1010_1.mm" in f][0] rcpsp_problem = parse_file(file) solver = CP_MRCPSP_MZN_MODES(rcpsp_problem, cp_solver_name=CPSolverName.CHUFFED) - params_cp = ParametersCP.default() - params_cp.nr_solutions = float("inf") - params_cp.all_solutions = True - result_storage = solver.solve(parameters_cp=params_cp) + result_storage = solver.solve(all_solutions=True) assert len(result_storage) == 12744 diff --git a/tests/rcpsp/solver/test_rcpsp_lp_lns.py b/tests/rcpsp/solver/test_rcpsp_lp_lns.py index 690f0b704..8fd9cee88 100644 --- a/tests/rcpsp/solver/test_rcpsp_lp_lns.py +++ b/tests/rcpsp/solver/test_rcpsp_lp_lns.py @@ -49,7 +49,6 @@ def test_lns_sm(): mip_gap_abs=0.001, mip_gap=0.001, retrieve_all_solution=True, - n_solutions_max=100, ) params_objective_function = get_default_objective_setup(problem=rcpsp_problem) constraint_handler = ConstraintHandlerStartTimeInterval( @@ -105,7 +104,6 @@ def test_lns_mm(): mip_gap_abs=0.001, mip_gap=0.001, retrieve_all_solution=True, - n_solutions_max=100, ) constraint_handler = ConstraintHandlerFixStartTime( problem=rcpsp_problem, fraction_fix_start_time=0.3 diff --git a/tests/rcpsp_multiskill/test_rcpsp_ms_lp_lns.py b/tests/rcpsp_multiskill/test_rcpsp_ms_lp_lns.py index d67dfd298..6f50ba5e0 100644 --- a/tests/rcpsp_multiskill/test_rcpsp_ms_lp_lns.py +++ b/tests/rcpsp_multiskill/test_rcpsp_ms_lp_lns.py @@ -64,7 +64,6 @@ def test_multiskill_imopse(): mip_gap_abs=0.001, mip_gap=0.001, retrieve_all_solution=True, - n_solutions_max=100, ) constraint_handler = ConstraintHandlerStartTimeIntervalMRCPSP( problem=model, fraction_to_fix=0.95, minus_delta=5, plus_delta=5