From 9dad62f5d162a41504d56e6b5f9fc6b6620e09d6 Mon Sep 17 00:00:00 2001 From: Guillaume Alleon Date: Tue, 5 Oct 2021 07:27:29 +0200 Subject: [PATCH] Removing dead code and print --- .../domain/scheduling/scheduling_domains.py | 24 +-- .../scheduling_domains_modelling.py | 19 --- .../generic_tools/lns_cp.py | 26 +-- .../generic_tools/lns_mip.py | 9 +- .../rcpsp/rcpsp_model.py | 150 +----------------- .../rcpsp/rcpsp_solvers.py | 3 +- .../rcpsp/rcpsp_utils.py | 15 +- .../rcpsp/solver/calendar_solver_iterative.py | 103 +++--------- .../rcpsp/solver/cp_solvers.py | 84 +++------- .../rcpsp/solver/rcpsp_cp_lns_solver.py | 16 +- .../rcpsp/solver/rcpsp_lp_lns_solver.py | 6 +- .../rcpsp/solver/rcpsp_pile.py | 36 +---- .../solvers/calendar_solver_iterative.py | 41 +---- skdecide/hub/__init__.py | 58 ------- .../solver/do_solver/do_solver_scheduling.py | 11 +- .../hub/solver/do_solver/sk_to_do_binding.py | 1 - 16 files changed, 79 insertions(+), 523 deletions(-) diff --git a/skdecide/builders/domain/scheduling/scheduling_domains.py b/skdecide/builders/domain/scheduling/scheduling_domains.py index 8b87b1cf13..049a67acd2 100644 --- a/skdecide/builders/domain/scheduling/scheduling_domains.py +++ b/skdecide/builders/domain/scheduling/scheduling_domains.py @@ -646,28 +646,6 @@ def get_possible_starting_tasks(self, state: State): if all(m in state.tasks_complete for m in set(self.ancestors[n]).intersection(self.get_available_tasks(state)))] - # possible_task_precedence = [(n, mode) - # for n in state.tasks_remaining - # for mode in self.get_task_modes(n).keys() - # if all(m in state.tasks_complete - # for m in self.ancestors[n])] - - # print("Possible task precedence : ", possible_task_precedence) - - # possible_with_time_window_start = [(n, mode) - # for n, mode in possible_task_precedence - # if (state.t >= self.get_time_window()[n].earliest_start) - # and (state.t <= self.get_time_window()[n].latest_start) - # ] - - # TODO: Below - Make sure the foreseen end time of task is within the end TW - how to sample the duration for uncertain env? - # should we add a function get_latest_sampled_duration() to state ? - # possible_with_time_window_end = [(n, mode) - # for n, mode in possible_with_time_window_start - # if (state.t+state.tasks_details[n].sampled_duration >= self.get_time_window()[n].earliest_end) - # and (state.t+state.tasks_details[n].sampled_duration <= self.get_time_window()[n].latest_end) - # ] - possible_task_with_ressource = [(n, mode) for n, mode in possible_task_precedence if all(state.resource_availability[key] - @@ -887,7 +865,7 @@ def _get_next_state_distribution(self, memory: D.T_memory[D.T_state], return DeterministicTransitions._get_next_state_distribution(self, memory, action) """ -Scheduling action space that will work for domains that don't require any +Scheduling action space that will work for domains that don't require any ressource unit allocation in its formulation. """ class SchedulingActionSpace(EnumerableSpace[SchedulingAction], SamplableSpace[SchedulingAction]): diff --git a/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py b/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py index 0ea8f889b2..1b3886c7ea 100644 --- a/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py +++ b/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py @@ -138,25 +138,6 @@ def __eq__(self, other): return self.__hash__() == other.__hash__() -# class SamplableAction: -# """ -# [Deprecated and soon will disappear probably] -# Can be used to define all sub-actions that can happen at one point in time. Resource allocation can be managed. -# These actions are not enumerable due to their fine grain definition. They can only be sampled. -# -# E.g. -# action_tasks = {2: 'action': SamplableActionEnum.START, 'resources': [], 'mode': 1 -# 4: 'action': SamplableActionEnum.START, 'resources': ['ru_1', 'ru_2'], 'mode': None -# 5: 'action': SamplableActionEnum.PAUSE, 'resources': [], 'mode': None -# 6: 'action': SamplableActionEnum.REALLOCATE, 'resources': ['ru_3', 'ru_4'], 'mode': None -# } -# """ -# action_tasks: Dict[int, Dict[str, Any]] -# -# def __init__(self, action_tasks: Dict[int, Dict[str, Any]]): -# self.action_tasks = action_tasks - - class SchedulingAction: """ Can be used to define actions on single task. Resource allocation can only be managed through changes in the mode. diff --git a/skdecide/discrete_optimization/generic_tools/lns_cp.py b/skdecide/discrete_optimization/generic_tools/lns_cp.py index 256033768a..5a89accee5 100644 --- a/skdecide/discrete_optimization/generic_tools/lns_cp.py +++ b/skdecide/discrete_optimization/generic_tools/lns_cp.py @@ -75,7 +75,6 @@ def solve_lns(self, best_solution = init_solution.copy() satisfy = self.problem.satisfy(init_solution) - print("Satisfy ", satisfy) best_objective = objective else: best_objective = float('inf') if sense==ModeOptim.MINIMIZATION else -float("inf") @@ -83,8 +82,6 @@ def solve_lns(self, constraint_iterable = {"empty": []} store_lns = None for iteration in range(nb_iteration_lns): - print('Starting iteration n°', iteration, - " current objective ", best_objective) with self.cp_solver.instance.branch() as child: if iteration == 0 and not skip_first_iteration or iteration >= 1: constraint_iterable = self.constraint_handler \ @@ -99,16 +96,10 @@ def solve_lns(self, result = child.solve(timeout=timedelta(seconds=parameters_cp.TimeLimit), intermediate_solutions=parameters_cp.intermediate_solution) result_store = self.cp_solver.retrieve_solutions(result, parameters_cp=parameters_cp) - print("iteration n°", iteration, "Solved !!!") - print(result.status) if len(result_store.list_solution_fits) > 0: - print("Solved !!!") bsol, fit = result_store.get_best_solution_fit() - print("Fitness = ", fit) - print("Post Process..") result_store = self.post_process_solution.build_other_solution(result_store) bsol, fit = result_store.get_best_solution_fit() - print("After postpro = ", fit) if sense == ModeOptim.MAXIMIZATION and fit >= best_objective: if fit > best_objective: current_nb_iteration_no_improvement = 0 @@ -131,30 +122,15 @@ def solve_lns(self, store_lns = result_store for s, f in result_store.list_solution_fits: store_lns.add_solution(solution=s, fitness=f) - print("Satisfy : ", self.problem.satisfy(best_solution)) else: current_nb_iteration_no_improvement += 1 except Exception as e: current_nb_iteration_no_improvement += 1 - print("Failed ! reason : ", e) if time.time() - deb_time > max_time_seconds: - print("Finish LNS with time limit reached") break - print(current_nb_iteration_no_improvement, "/", nb_iteration_no_improvement) if current_nb_iteration_no_improvement > nb_iteration_no_improvement: - print("Finish LNS with maximum no improvement iteration ") break - # Useless to remove the constraints with the "with", the constraints are only active inside the with. - # print('Removing constraint:') - # # self.constraint_handler.remove_constraints_from_previous_iteration(cp_solver=self.cp_solver, - # # child_instance=child, - # # previous_constraints=constraint_iterable) - # print('Adding constraint:') - # constraint_iterable = self.constraint_handler.adding_constraint_from_results_store(cp_solver= - # self.cp_solver, - # child_instance=child, - # result_storage= - # store_lns) + return store_lns diff --git a/skdecide/discrete_optimization/generic_tools/lns_mip.py b/skdecide/discrete_optimization/generic_tools/lns_mip.py index bb21272cc4..cc75249c9a 100644 --- a/skdecide/discrete_optimization/generic_tools/lns_mip.py +++ b/skdecide/discrete_optimization/generic_tools/lns_mip.py @@ -101,13 +101,10 @@ def solve_lns(self, for iteration in range(nb_iteration_lns): result_store = self.milp_solver.solve(parameters_milp=parameters_milp, **args) - print("Solved !!!") bsol, fit = result_store.get_best_solution_fit() - print("Fitness = ", fit) - print("Post Process..") + result_store = self.post_process_solution.build_other_solution(result_store) bsol, fit = result_store.get_best_solution_fit() - print("After postpro = ", fit) if sense == ModeOptim.MAXIMIZATION and fit >= best_objective: if fit > best_objective: current_nb_iteration_no_improvement = 0 @@ -126,19 +123,15 @@ def solve_lns(self, store_lns = result_store for s, f in result_store.list_solution_fits: store_lns.add_solution(solution=s, fitness=f) - print('Removing constraint:') self.constraint_handler.remove_constraints_from_previous_iteration(milp_solver=self.milp_solver, previous_constraints=constraint_iterable) - print('Adding constraint:') constraint_iterable = self.constraint_handler.adding_constraint_from_results_store(milp_solver= self.milp_solver, result_storage= result_store) if time.time()-deb_time > max_time_seconds: - print("Finish LNS with time limit reached") break if current_nb_iteration_no_improvement > nb_iteration_no_improvement: - print("Finish LNS with maximum no improvement iteration ") break return store_lns diff --git a/skdecide/discrete_optimization/rcpsp/rcpsp_model.py b/skdecide/discrete_optimization/rcpsp/rcpsp_model.py index 683b50e703..0caa241f81 100644 --- a/skdecide/discrete_optimization/rcpsp/rcpsp_model.py +++ b/skdecide/discrete_optimization/rcpsp/rcpsp_model.py @@ -101,9 +101,7 @@ def __str__(self): sched_str = 'None' else: sched_str = str(self.rcpsp_schedule) - val = "RCPSP solution (rcpsp_schedule): " + sched_str - print('type: ', type(val)) - return val + return "RCPSP solution (rcpsp_schedule): " + sched_str def generate_permutation_from_schedule(self): sorted_task = [i - 2 for i in sorted(self.rcpsp_schedule, @@ -130,10 +128,7 @@ def compute_mean_resource_reserve(self): start_time = self.rcpsp_schedule[act_id]['start_time'] end_time = self.rcpsp_schedule[act_id]['end_time'] mode = self.rcpsp_modes[act_id-2] - # print('act_id: ', act_id) - # print('start_time: ', start_time) - # print('end_time: ', end_time) - # print('mode: ', mode) + for t in range(start_time, end_time): for res in resource_avail_in_time.keys(): resource_avail_in_time[res][t] -= self.problem.mode_details[act_id][mode][res] # 17 @@ -141,15 +136,12 @@ def compute_mean_resource_reserve(self): for tt in range(end_time + 1, makespan): resource_avail_in_time[res][tt] -= \ self.problem.mode_details[act_id][mode][res] - # print('resource_avail_in_time: ', resource_avail_in_time) mean_avail = {} for res in list(self.problem.resources.keys()): mean_avail[res] = np.mean(resource_avail_in_time[res]) mean_resource_reserve = np.mean([mean_avail[res] / self.problem.resources[res] for res in list(self.problem.resources.keys())]) - # print('mean_avail: ', mean_avail) - # print('original_avail: ', self.problem.resources) - # print('val: ', mean_resource_reserve) + return mean_resource_reserve def generate_schedule_from_permutation_serial_sgs(self): @@ -174,25 +166,20 @@ def generate_schedule_from_permutation_serial_sgs(self): perm_extended = [x+2 for x in perm] perm_extended.insert(0, 1) perm_extended.append(self.problem.n_jobs + 2) - # print('perm_extended: ', perm_extended) + modes_extended = deepcopy(self.rcpsp_modes) modes_extended.insert(0, 1) modes_extended.append(1) - # print('pre-modes_extended: ', modes_extended) # fix modes in case specified mode not in mode details for the activites for i in range(len(modes_extended)): - # print(list(self.problem.mode_details[i + 1].keys())) if modes_extended[i] not in list(self.problem.mode_details[i+1].keys()): modes_extended[i] = 1 if i != 0 and i != len(modes_extended)-1: self.rcpsp_modes[i-1] = modes_extended[i] - # print('modes_extended: ', modes_extended) - # print('start SGS') while len(perm_extended) > 0 and not unfeasible_non_renewable_resources: - # print('perm_extended: ', perm_extended) # get first activity in perm with precedences respected for id in perm_extended: respected = True @@ -203,13 +190,10 @@ def generate_schedule_from_permutation_serial_sgs(self): if respected: act_id = id break - # print('next act_id respecting precedences :', act_id) # for act_id in perm_extended: # 4 current_min_time = minimum_starting_time[act_id] # 5 - # print('current_min_time_0: ', current_min_time) valid = False # 6 while not valid: # 7 - # print('current_min_time: ', current_min_time) valid = True # 8 for t in range(current_min_time, current_min_time @@ -235,11 +219,9 @@ def generate_schedule_from_permutation_serial_sgs(self): activity_end_times[act_id] = current_min_time + self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration'] # 18 perm_extended.remove(act_id) - # print('scheduled to complete at: ', activity_end_times[act_id]) for s in self.problem.successors[act_id]: # 19 minimum_starting_time[s] = max(minimum_starting_time[s], activity_end_times[act_id]) # 20 - # print('activity_end_times: ', activity_end_times) self.rcpsp_schedule = {} for act_id in activity_end_times: self.rcpsp_schedule[act_id] = {} @@ -282,30 +264,23 @@ def generate_schedule_from_permutation_serial_sgs_2(self, current_t, completed_t perm_extended = [x+2 for x in perm] perm_extended.insert(0, 1) perm_extended.append(self.problem.n_jobs + 2) - # print('perm_extended: ', perm_extended) + modes_extended = deepcopy(self.rcpsp_modes) modes_extended.insert(0, 1) modes_extended.append(1) - # print('pre-modes_extended: ', modes_extended) all_activities = [x for x in list(self.problem.resources.keys()) if x not in list(completed_tasks)] - # print('all_activities: ', all_activities) perm_extended = [x for x in perm_extended if x not in list(completed_tasks)] - # print('perm_extended - removed completed_tasks: ', perm_extended) # fix modes in case specified mode not in mode details for the activites for i in range(len(modes_extended)): - # print(list(self.problem.mode_details[i + 1].keys())) if modes_extended[i] not in list(self.problem.mode_details[i+1].keys()): modes_extended[i] = 1 if i != 0 and i != len(modes_extended)-1: self.rcpsp_modes[i-1] = modes_extended[i] - # print('modes_extended: ', modes_extended) - # print('start SGS') while len(perm_extended) > 0 and not unfeasible_non_renewable_resources: - # print('perm_extended: ', perm_extended) # get first activity in perm with precedences respected for id in perm_extended: respected = True @@ -316,25 +291,15 @@ def generate_schedule_from_permutation_serial_sgs_2(self, current_t, completed_t if respected: act_id = id break - # print('next act_id respecting precedences :', act_id) # for act_id in perm_extended: # 4 current_min_time = minimum_starting_time[act_id] # 5 - # print('current_min_time_0: ', current_min_time) valid = False # 6 while not valid: # 7 - # print('current_min_time: ', current_min_time) valid = True # 8 for t in range(current_min_time, current_min_time +self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration']): # 9 - # print(act_id, t) for res in resource_avail_in_time.keys(): # 10 - # if t == 4: - # print('res--', res) - # print('t--', t) - # print('horizon', new_horizon) - # print('resource_avail_in_time[res][t]: ', resource_avail_in_time[res][t]) - # print('self.problem.mode_details[act_id][modes_extended[act_id-1]][res]: ', self.problem.mode_details[act_id][modes_extended[act_id-1]][res]) if t < new_horizon: if resource_avail_in_time[res][t] < self.problem.mode_details[act_id][modes_extended[act_id-1]][res]: # 11 valid = False # 12 @@ -343,11 +308,7 @@ def generate_schedule_from_permutation_serial_sgs_2(self, current_t, completed_t if not valid: # 13 current_min_time += 1 # 14 if not unfeasible_non_renewable_resources: - # print('current_min_time: ', current_min_time) - # print('in mode: ', modes_extended[act_id-1]) - # print('(mode details - duration: ', self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration']) end_t = current_min_time + self.problem.mode_details[act_id][modes_extended[act_id - 1]]['duration']-1 - # print('end_t: ', end_t) for t in range(current_min_time, current_min_time + self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration']): # 15 for res in resource_avail_in_time.keys(): # 16 resource_avail_in_time[res][t] -= self.problem.mode_details[act_id][modes_extended[act_id-1]][res] # 17 @@ -356,16 +317,12 @@ def generate_schedule_from_permutation_serial_sgs_2(self, current_t, completed_t resource_avail_in_time[res][tt] -= self.problem.mode_details[act_id][modes_extended[act_id - 1]][res] if resource_avail_in_time[res][tt] < 0: unfeasible_non_renewable_resources = True - # print('resource', res, 'exhausted', resource_avail_in_time[res][tt], 'initial avail: ', self.problem.resources[res]) - # print(res, ' resource_avail_in_time[res]: ', resource_avail_in_time[res]) activity_end_times[act_id] = current_min_time + self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration'] # 18 perm_extended.remove(act_id) - # print('scheduled to complete at: ', activity_end_times[act_id]) for s in self.problem.successors[act_id]: # 19 minimum_starting_time[s] = max(minimum_starting_time[s], activity_end_times[act_id]) # 20 - # print('activity_end_times: ', activity_end_times) self.rcpsp_schedule = {} for act_id in activity_end_times: self.rcpsp_schedule[act_id] = {} @@ -391,56 +348,6 @@ def __hash__(self): def __eq__(self, other): return self.rcpsp_permutation == other.rcpsp_permutation and self.rcpsp_modes == other.rcpsp_modes - # def generate_schedule_from_permutation_serial_sgs(self): - # perm = self.rcpsp_permutation - # activity_end_times = {} - # - # # 1, 2 - # resource_avail_in_time = {} - # for res in list(self.problem.resources.keys()): - # resource_avail_in_time[res] = np.full(self.problem.horizon, self.problem.resources[res], dtype=int).tolist() - # - # # 3 - # minimum_starting_time = {} - # for act in list(self.problem.successors.keys()): - # minimum_starting_time[act-1] = 0 - # - # perm_extended = [x+2 for x in perm] - # perm_extended.insert(0,1) - # perm_extended.append(self.problem.n_jobs + 2) - # # print('perm_extended: ', perm_extended) - # - # modes_extended = self.rcpsp_modes - # modes_extended.insert(0,1) - # modes_extended.append(1) - # # print('modes_extended: ', modes_extended) - # - # for act_id in perm_extended: # 4 - # current_min_time = minimum_starting_time[act_id] # 5 - # valid = False # 6 - # while not valid: # 7 - # valid = True # 8 - # for t in range(current_min_time, current_min_time+self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration']): # 9 - # # print(act_id, t) - # for res in resource_avail_in_time.keys(): # 10 - # if resource_avail_in_time[res][t] < self.problem.mode_details[act_id][modes_extended[act_id-1]][res]: # 11 - # valid = False # 12 - # if not valid: # 13 - # current_min_time += 1 # 14 - # for t in range(current_min_time, current_min_time + self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration']): # 15 - # for res in resource_avail_in_time.keys(): # 16 - # resource_avail_in_time[res][t] -= self.problem.mode_details[act_id][modes_extended[act_id-1]][res] # 17 - # activity_end_times[act_id] = current_min_time + self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration'] # 18 - # for s in self.problem.successors[act_id]: # 19 - # minimum_starting_time[s] = activity_end_times[act_id] # 20 - # - # # print('activity_end_times: ', activity_end_times) - # self.rcpsp_schedule = {} - # for act_id in activity_end_times: - # self.rcpsp_schedule[act_id] = {} - # self.rcpsp_schedule[act_id]['start_time'] = activity_end_times[act_id] - self.problem.mode_details[act_id][modes_extended[act_id-1]]['duration'] - # self.rcpsp_schedule[act_id]['end_time'] = activity_end_times[act_id] - class PartialSolution: def __init__(self, @@ -530,7 +437,6 @@ def evaluate_mobj_from_dict(self, dict_values: Dict[str, float]): def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: if rcpsp_sol.rcpsp_schedule_feasible is False: - print('Schedule flagged as infeasible when generated') return False else: modes_extended = deepcopy(rcpsp_sol.rcpsp_modes) @@ -548,19 +454,12 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: start = rcpsp_sol.rcpsp_schedule[act_id]['start_time'] end = rcpsp_sol.rcpsp_schedule[act_id]['end_time'] mode = modes_extended[act_id-1] - # print(act_id) for res in self.resources.keys():#self.mode_details[act_id][mode]: if start <= t and t < end: - # print('res: ', res) - # print('adding usage from act', act_id) - # print('mode:', mode) - # print('self.mode_details[act_id][mode][res]: ', self.mode_details[act_id][mode][res]) resource_usage[res] += self.mode_details[act_id][mode][res] for res in self.resources.keys(): if resource_usage[res] > self.resources[res]: - print('Time step resource violation: time: ', t, 'res', res, - 'res_usage: ', resource_usage[res], 'res_avail: ', self.resources[res]) return False # Check for non-renewable resource violation @@ -570,7 +469,6 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: mode = modes_extended[act_id-1] usage += self.mode_details[act_id][mode][res] if usage > self.resources[res]: - print('Non-renewable resource violation: act_id: ', act_id, 'res', res, 'res_usage: ', resource_usage[res], 'res_avail: ', self.resources[res]) return False # Check precedences / successors @@ -579,14 +477,12 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: start_succ = rcpsp_sol.rcpsp_schedule[succ_id]['start_time'] end_pred = rcpsp_sol.rcpsp_schedule[act_id]['end_time'] if start_succ < end_pred: - print('Precedence relationship broken: ', act_id, 'end at ', end_pred, 'while ', succ_id, 'start at', start_succ) return False return True def __str__(self): - val = "RCPSP model" - return val + return "RCPSP model" def get_solution_type(self): return RCPSPSolution @@ -600,7 +496,6 @@ def get_attribute_register(self) -> EncodingRegister: "n": self.n_jobs} max_number_modes = max([len(list(self.mode_details[x].keys())) for x in self.mode_details.keys()]) - # print('max_number_modes: ', max_number_modes) dict_register["rcpsp_modes"] = {"name": "rcpsp_modes", "type": [TypeAttribute.LIST_INTEGER], "n": self.n_jobs, @@ -699,7 +594,6 @@ def copy(self): def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: if rcpsp_sol.rcpsp_schedule_feasible is False: - print('Schedule flagged as infeasible when generated') return False else: modes_extended = deepcopy(rcpsp_sol.rcpsp_modes) @@ -716,19 +610,12 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: start = rcpsp_sol.rcpsp_schedule[act_id]['start_time'] end = rcpsp_sol.rcpsp_schedule[act_id]['end_time'] mode = modes_extended[act_id-1] - # print(act_id) for res in self.resources.keys():#self.mode_details[act_id][mode]: if start <= t and t < end: - # print('res: ', res) - # print('adding usage from act', act_id) - # print('mode:', mode) - # print('self.mode_details[act_id][mode][res]: ', self.mode_details[act_id][mode][res]) resource_usage[res] += self.mode_details[act_id][mode][res] for res in self.resources.keys(): if resource_usage[res] > self.resources[res][t]: - print('Time step resource violation: time: ', t, 'res', res, - 'res_usage: ', resource_usage[res], 'res_avail: ', self.resources[res]) return False # Check for non-renewable resource violation @@ -738,7 +625,6 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: mode = modes_extended[act_id-1] usage += self.mode_details[act_id][mode][res] if usage > self.resources[res][0]: - print('Non-renewable resource violation: act_id: ', act_id, 'res', res, 'res_usage: ', resource_usage[res], 'res_avail: ', self.resources[res]) return False # Check precedences / successors @@ -747,7 +633,6 @@ def satisfy(self, rcpsp_sol: RCPSPSolution)->bool: start_succ = rcpsp_sol.rcpsp_schedule[succ_id]['start_time'] end_pred = rcpsp_sol.rcpsp_schedule[act_id]['end_time'] if start_succ < end_pred: - print('Precedence relationship broken: ', act_id, 'end at ', end_pred, 'while ', succ_id, 'start at', start_succ) return False return True @@ -804,10 +689,8 @@ def set_fixed_attributes(self, encoding_str: str, sol: RCPSPSolution): att = self.get_attribute_register().dict_attribute_to_type[encoding_str]['name'] if att == 'rcpsp_modes': self.set_fixed_modes(sol.rcpsp_modes) - print('self.fixed_modes:', self.fixed_modes) elif att == 'rcpsp_permutation': self.set_fixed_permutation(sol.rcpsp_permutation) - print('self.fixed_permutation:', self.fixed_permutation) def set_fixed_modes(self, fixed_modes): self.fixed_modes = fixed_modes @@ -1107,47 +990,31 @@ def rcpsp_pre_helper_correction(self, rcpsp_sol: RCPSPSolution): for main_id in self.pre_helper_activities: pre_helper_ids.append(self.pre_helper_activities[main_id][0]) pre_helper_starts.append(rcpsp_sol.rcpsp_schedule[self.pre_helper_activities[main_id][0]]['start_time']) - # print('pre_helper_ids: ', pre_helper_ids) - # print('pre_helper_starts: ', pre_helper_starts) sorted_pre_helper_ids = [x for _, x in sorted(zip(pre_helper_starts, pre_helper_ids), reverse=True)] - # print('sorted_pre_helper_ids: ', sorted_pre_helper_ids) # for each pre_helper, try to start as late as possible for id in sorted_pre_helper_ids: - # print('id: ',id) - # print('original_start: ', corrected_sol.rcpsp_schedule[id]['start_time']) - # print('self.successors[id]: ', self.successors[id]) # Latest possible cannot be later than the earliest start of its successors all_successor_starts = [corrected_sol.rcpsp_schedule[s_id]['start_time'] for s_id in self.successors[id]] - # print('all_successor_starts: ', all_successor_starts) latest_end = min(all_successor_starts) - # print('initial latest_end: ',latest_end) duration = (corrected_sol.rcpsp_schedule[id]['end_time'] - corrected_sol.rcpsp_schedule[id]['start_time']) latest_start = latest_end - duration - # print('initial latest_start:', latest_start) - # print('self.compute_resource_consumption(): ', self.compute_resource_consumption(corrected_sol)) # Then iteratively check if the latest time is suitable resource-wise # if not try earlier # first copy the resource consumption array and remove consumption of the pre_helper activity consumption = np.copy(self.compute_resource_consumption(corrected_sol)) - # print('self.resources: ', self.resources) for i in range(len(list(self.resources.keys()))): res_str = list(self.resources.keys())[i] - # print('res_str: ', res_str) for t in range(corrected_sol.rcpsp_schedule[id]['start_time'], corrected_sol.rcpsp_schedule[id]['end_time']): - # print('t: ', t) consumption[i,t+1] -= self.mode_details[id][1][res_str] - # print('consumption -2: ', consumption) - # then start trying iteratively to fit the pre_helper activity as late as possible stop = False while not stop: all_good = True for t in range(latest_start, latest_start+duration): - # print('t: ',t) for i in range(len(list(self.resources.keys()))): res_str = list(self.resources.keys())[i] if consumption[i,t+1] + self.mode_details[id][1][res_str] > self.resources[res_str]: @@ -1156,13 +1023,10 @@ def rcpsp_pre_helper_correction(self, rcpsp_sol: RCPSPSolution): if all_good: corrected_sol.rcpsp_schedule[id]['start_time'] = latest_start corrected_sol.rcpsp_schedule[id]['end_time'] = latest_start+duration - # print('Corrected start: ',corrected_sol.rcpsp_schedule[id]['start_time']) - # print('Corrected end: ', corrected_sol.rcpsp_schedule[id]['end_time']) stop = True else: latest_start -= 1 - # print(' ---------- ') return corrected_sol.rcpsp_schedule @@ -1215,4 +1079,4 @@ def compute_graph_rcpsp(rcpsp_model: RCPSPModel): dict_transition["minus_max_duration"] = -max_duration dict_transition["link"] = 1 edges += [(n, succ, dict_transition)] - return Graph(nodes, edges, False) \ No newline at end of file + return Graph(nodes, edges, False) diff --git a/skdecide/discrete_optimization/rcpsp/rcpsp_solvers.py b/skdecide/discrete_optimization/rcpsp/rcpsp_solvers.py index 7d5de85ddc..d93c20207d 100644 --- a/skdecide/discrete_optimization/rcpsp/rcpsp_solvers.py +++ b/skdecide/discrete_optimization/rcpsp/rcpsp_solvers.py @@ -82,8 +82,7 @@ def look_for_solver(domain): for solver in solvers_compatibility: if class_domain in solvers_compatibility[solver]: available += [solver] - print("You have ", len(available), " solvers for your domain ") - print([solvers_map[a] for a in available]) + return available diff --git a/skdecide/discrete_optimization/rcpsp/rcpsp_utils.py b/skdecide/discrete_optimization/rcpsp/rcpsp_utils.py index e874a54ff5..ea64e202fc 100644 --- a/skdecide/discrete_optimization/rcpsp/rcpsp_utils.py +++ b/skdecide/discrete_optimization/rcpsp/rcpsp_utils.py @@ -75,8 +75,7 @@ def compute_schedule_per_resource_individual(rcpsp_model: RCPSPModel, key=lambda x: 100000*rcpsp_sol.rcpsp_schedule[x]["end_time"]+x) max_time = rcpsp_sol.rcpsp_schedule[sorted_task_by_end[-1]]["end_time"] min_time = rcpsp_sol.rcpsp_schedule[sorted_task_by_end[0]]["start_time"] - print("Min time ", min_time) - print("Max time ", max_time) + with_calendar = isinstance(rcpsp_model, RCPSPModelCalendar) array_ressource_usage = {resources[i]: @@ -118,14 +117,8 @@ def compute_schedule_per_resource_individual(rcpsp_model: RCPSPModel, if not with_calendar: range_interest = range(array_ressource_usage[r]["activity"].shape[1]) else: - # try: - # range_interest = [x for x in range(len(rcpsp_model.calendar_details[r])) if - # rcpsp_model.calendar_details[r][x][time_to_index[start_time]] == 1] - # except: range_interest = range(rcpsp_model.resources[r][time_to_index[start_time]]) while rneeded > 0: - # availables_people_r = [i for i in range(array_ressource_usage[r]["activity"].shape[1]) - # if array_ressource_usage[r]["activity"][time_to_index[start_time], i] == 0] availables_people_r = [i for i in range_interest if array_ressource_usage[r]["activity"][time_to_index[start_time], i] == 0] if verbose: @@ -151,12 +144,6 @@ def compute_schedule_per_resource_individual(rcpsp_model: RCPSPModel, # for plot purposes. rneeded -= 1 else: - print("r_needed ", rneeded) - print("Ressource needed : ", resources_needed) - print("ressource : ", r) - print("activity : ", activity) - print("Problem, can't build schedule") - print(array_ressource_usage[r]["activity"]) rneeded = 0 return array_ressource_usage diff --git a/skdecide/discrete_optimization/rcpsp/solver/calendar_solver_iterative.py b/skdecide/discrete_optimization/rcpsp/solver/calendar_solver_iterative.py index 86794a4154..e7a06164c8 100644 --- a/skdecide/discrete_optimization/rcpsp/solver/calendar_solver_iterative.py +++ b/skdecide/discrete_optimization/rcpsp/solver/calendar_solver_iterative.py @@ -58,12 +58,10 @@ def get_ressource_breaks(problem_calendar, problem_no_calendar, solution: RCPSPS for r in ressource_arrays: index = np.argwhere(ressource_arrays[r] > problem_calendar.resources[r]) index_ressource[r] = index - #print("Constraints broken : ", r, index) task_concerned[r] = [j for j in range(ressource_arrays_usage[r].shape[1]) if any(ressource_arrays_usage[r][ind[0], j] == 1 for ind in index if problem_calendar.resources[r][ind[0]] == 0)] - #print("Concerned : ", task_concerned[r]) task_concerned[r] = [sorted_keys_schedule[rr] for rr in task_concerned[r]] constraints[r] = {} for t in task_concerned[r]: @@ -76,10 +74,7 @@ def get_ressource_breaks(problem_calendar, problem_no_calendar, solution: RCPSPS if problem_calendar.resources[r][st] >= problem_calendar.mode_details[t][1][r]), None) - #if first_possible_start_before is not None: - # first_possible_start_before = \ - # max(0, - # first_possible_start_before-problem_calendar.mode_details[t][1]["duration"]+1) + constraints[r][t] = (first_possible_start_before, first_possible_start_future) return index_ressource, constraints @@ -125,7 +120,6 @@ def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: rb, constraints = get_ressource_breaks(self.problem_calendar, self.problem_no_calendar, sol[0]) sol[0].satisfy = not(any(len(rb[r]) > 0 for r in rb)) sol[0].constraints = constraints - print("Check Ressource : ", sol[0].satisfy) if sol[0].satisfy is False: if self.partial_solution is None: solution = RCPSPSolution(problem=self.problem_calendar, @@ -135,8 +129,7 @@ def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: solution.satisfy = self.check_sol(self.problem_calendar, solution) result_storage.list_solution_fits += [(solution, -self.problem_calendar.evaluate(solution)["makespan"])] - # result_storage.list_solution_fits = [r for r in result_storage.list_solution_fits - # if r[0].satisfy] + return result_storage @@ -153,7 +146,6 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_RCPSP_MZN, CP result_storage: ResultStorage) -> Iterable[Any]: solution, fit = result_storage.get_best_solution_fit() if ("satisfy" in solution.__dict__.keys() and solution.satisfy): - print("adding the other constraints !") return self.other_constraint.adding_constraint_from_results_store(cp_solver, child_instance, result_storage) ressource_breaks, constraints = get_ressource_breaks(self.problem_calendar, self.problem_no_calendar, @@ -185,22 +177,6 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_RCPSP_MZN, CP child_instance.add_string(s) list_strings += [s] - # for r in ressource_breaks: - # index_ressource = cp_solver.resources_index.index(r) - # for t in range(len(self.problem_calendar.resources[r])): - # rq = self.problem_calendar.resources[r][t] - # if t=sum( i in Act ) ( - # bool2int(start[i] <=""" + str(t) + """ /\ """ + str(t) \ - # + """< start[i] + adur[i]) * arreq[""" + str(index_ressource + 1) + """,i]);\n""" - # elif isinstance(cp_solver, CP_RCPSP_MZN): - # s = """constraint """ + str(rq) + """>=sum( i in Tasks ) ( - # bool2int(s[i] <=""" + str(t) + """ /\ """ + str(t) \ - # + """< s[i] + d[i]) * rr[""" + str(index_ressource + 1) + """,i]);\n""" - # child_instance.add_string(s) - # list_strings += [s] - for r in ressource_breaks: index_ressource = cp_solver.resources_index.index(r) for index in ressource_breaks[r]: @@ -208,8 +184,7 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_RCPSP_MZN, CP continue ind = index[0] rq = self.problem_calendar.resources[r][ind] - # if random.random() <= 0.3: - # continue + if isinstance(cp_solver, CP_MRCPSP_MZN): s = """constraint """+str(rq)+""">=sum( i in Act ) ( bool2int(start[i] <="""+str(ind)+""" /\ """+str(ind)\ @@ -220,8 +195,7 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_RCPSP_MZN, CP + """< s[i] + d[i]) * rr[""" + str(index_ressource + 1) + """,i]);\n""" child_instance.add_string(s) list_strings += [s] - # print("Res", r) - # print("Time", index) + satisfiable = [(s,f) for s, f in result_storage.list_solution_fits if "satisfy" in s.__dict__.keys() and s.satisfy] if len(satisfiable) > 0: @@ -254,37 +228,36 @@ def __init__(self, problem_calendar: RCPSPModelCalendar, partial_solution: Parti successors=self.problem_calendar.successors, horizon=self.problem_calendar.horizon, name_task=self.problem_calendar.name_task) - # solver = CP_MRCPSP_MZN(rcpsp_model=self.problem_no_calendar, - # cp_solver_name=CPSolverName.CHUFFED) - # solver = CP_RCPSP_MZN(rcpsp_model=self.problem_no_calendar, - # cp_solver_name=CPSolverName.CHUFFED) + solver = CP_MRCPSP_MZN(rcpsp_model=self.problem_no_calendar, cp_solver_name=CPSolverName.CHUFFED) + solver.init_model(output_type=True, model_type="multi", partial_solution=partial_solution) + parameters_cp = ParametersCP.default() parameters_cp.TimeLimit = 500 parameters_cp.TimeLimit_iter0 = 500 params_objective_function = get_default_objective_setup(problem=self.problem_no_calendar) - # constraint_handler = ConstraintHandlerFixStartTime(problem=rcpsp_problem, - # fraction_fix_start_time=0.5) + constraint_handler = ConstraintHandlerStartTimeInterval_CP(problem=self.problem_no_calendar, fraction_to_fix=0.99, minus_delta=10, plus_delta=10, delta_time_from_makepan_to_not_fix=5) - # constraint_handler = ConstraintHandlerAddCalendarConstraint(self.problem_calendar, - # self.problem_no_calendar, - # constraint_handler) + constraint_handler = build_neighbor_operator(option_neighbor=OptionNeighbor.MIX_LARGE_NEIGH, rcpsp_model=self.problem_no_calendar) + constraint_handler = ConstraintHandlerAddCalendarConstraint(self.problem_calendar, self.problem_no_calendar, constraint_handler) + initial_solution_provider = InitialSolutionRCPSP(problem=self.problem_calendar, initial_method=InitialMethodRCPSP.PILE_CALENDAR, params_objective_function=params_objective_function) + self.initial_solution_provider = initial_solution_provider self.constraint_handler = constraint_handler self.params_objective_function = params_objective_function @@ -300,13 +273,18 @@ def solve(self, max_time_seconds: Optional[int] = None, skip_first_iteration: bool = False, **args) -> ResultStorage: + sense = self.params_objective_function.sense_function + if max_time_seconds is None: max_time_seconds = 3600 * 24 # One day + if nb_iteration_no_improvement is None: nb_iteration_no_improvement = 2 * nb_iteration_lns + current_nb_iteration_no_improvement = 0 deb_time = time.time() + if not skip_first_iteration: store_lns = self.initial_solution_provider.get_starting_solution() store_lns = self.post_process_solution.build_other_solution(store_lns) @@ -315,7 +293,6 @@ def solve(self, init_solution, objective = store_lns.get_best_solution_fit() best_solution = init_solution.copy() satisfy = self.problem_calendar.satisfy(init_solution) - print("Satisfy ", satisfy) best_objective = objective else: best_objective = float('inf') if sense == ModeOptim.MINIMIZATION else -float("inf") @@ -323,15 +300,10 @@ def solve(self, constraint_iterable = {"empty": []} store_lns = None store_with_all = None + constraint_to_keep = set() + for iteration in range(nb_iteration_lns): - print('Starting iteration n°', iteration, - " current objective ", best_objective) - try: - print("Best feasible solution ", max([f for s, f in store_with_all.list_solution_fits - if "satisfy" in s.__dict__.keys() and s.satisfy])) - except: - print("No Feasible solution yet") with self.cp_solver.instance.branch() as child: if iteration == 0 and not skip_first_iteration or iteration >= 1: for c in constraint_to_keep: @@ -351,18 +323,14 @@ def solve(self, result = child.solve(timeout=timedelta(seconds=parameters_cp.TimeLimit), intermediate_solutions=parameters_cp.intermediate_solution) result_store = self.cp_solver.retrieve_solutions(result, parameters_cp=parameters_cp) - print("iteration n°", iteration, "Solved !!!") - print(result.status) + if len(result_store.list_solution_fits) > 0: - print("Solved !!!") + bsol, fit = result_store.get_best_solution_fit() - print("Fitness = ", fit) - print("Post Process..") - print("Satisfy best current sol : ") - print(self.problem_calendar.satisfy(bsol)) + result_store = self.post_process_solution.build_other_solution(result_store) bsol, fit = result_store.get_best_solution_fit() - print("After postpro = ", fit) + if sense == ModeOptim.MAXIMIZATION and fit >= best_objective: if fit > best_objective: current_nb_iteration_no_improvement = 0 @@ -391,41 +359,20 @@ def solve(self, for s, f in store_with_all.list_solution_fits: #if s.satisfy: store_lns.list_solution_fits += [(s, f)] - print("Satisfy : ", self.problem_calendar.satisfy(best_solution)) else: current_nb_iteration_no_improvement += 1 if skip_first_iteration and result.status == Status.OPTIMAL_SOLUTION and iteration == 0\ and best_solution.satisfy: - print("Finish LNS because found optimal solution") break else: - #except Exception as e: current_nb_iteration_no_improvement += 1 - print("Failed ! reason : ", e) + if time.time() - deb_time > max_time_seconds: print("Finish LNS with time limit reached") break - print(current_nb_iteration_no_improvement, "/", nb_iteration_no_improvement) + if current_nb_iteration_no_improvement > nb_iteration_no_improvement: print("Finish LNS with maximum no improvement iteration ") break - # Useless to remove the constraints with the "with", the constraints are only active inside the with. - # print('Removing constraint:') - # # self.constraint_handler.remove_constraints_from_previous_iteration(cp_solver=self.cp_solver, - # # child_instance=child, - # # previous_constraints=constraint_iterable) - # print('Adding constraint:') - # constraint_iterable = self.constraint_handler.adding_constraint_from_results_store(cp_solver= - # self.cp_solver, - # child_instance=child, - # result_storage= - # store_lns) return store_with_all - - - - - - - diff --git a/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py b/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py index 0e6d401ed2..b4d7d9ad44 100644 --- a/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py +++ b/skdecide/discrete_optimization/rcpsp/solver/cp_solvers.py @@ -36,7 +36,6 @@ class RCPSPSolCP: def __init__(self, objective, _output_item, **kwargs): self.objective = objective self.dict = kwargs - print("One solution ", self.objective) def check(self) -> bool: return True @@ -71,20 +70,20 @@ def init_model(self, **args): instance["possibly_preemptive"] = [True for task in self.rcpsp_model.mode_details] instance["max_preempted"] = 3 n_res = len(list(self.rcpsp_model.resources.keys())) - # print('n_res: ', n_res) + instance["n_res"] = n_res sorted_resources = sorted(self.rcpsp_model.resources_list) self.resources_index = sorted_resources rc = [int(self.rcpsp_model.resources[r]) for r in sorted_resources] - # print('rc: ', rc) + instance["rc"] = rc n_tasks = self.rcpsp_model.n_jobs + 2 - # print('n_tasks: ', n_tasks) + instance["n_tasks"] = n_tasks sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) d = [int(self.rcpsp_model.mode_details[key][1]['duration']) for key in sorted_tasks] - # print('d: ', d) + instance["d"] = d rr = [] index = 0 @@ -222,25 +221,21 @@ def init_model(self, **args): self.resources_index = resources_list instance = Instance(solver, model) n_res = len(resources_list) - # print('n_res: ', n_res) + keys = [] instance["n_res"] = n_res keys += ["n_res"] - # rc = [val for val in self.rcpsp_model.resources.values()] - # # print('rc: ', rc) - # instance["rc"] = rc - n_tasks = self.rcpsp_model.n_jobs + 2 - # print('n_tasks: ', n_tasks) + instance["n_tasks"] = n_tasks keys += ["n_tasks"] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) - # print('mode_details: ', self.rcpsp_model.mode_details) + n_opt = sum([len(list(self.rcpsp_model.mode_details[key].keys())) for key in sorted_tasks]) - # print('n_opt: ', n_opt) + instance["n_opt"] = n_opt keys += ["n_opt"] @@ -260,11 +255,10 @@ def init_model(self, **args): modes.append(set_mode_task) dur = dur + [self.rcpsp_model.mode_details[act][key]['duration'] for key in tmp] - # print('modes: ', modes) + instance['modes'] = modes keys += ["modes"] - # print('dur: ', dur) instance['dur'] = dur keys += ["dur"] @@ -278,7 +272,6 @@ def init_model(self, **args): rreq[index].append(int(self.rcpsp_model.mode_details[task][mod][res])) index += 1 - # print('rreq: ', rreq) instance["rreq"] = rreq keys += ["rreq"] @@ -286,20 +279,17 @@ def init_model(self, **args): rcap = [int(self.rcpsp_model.resources[x]) for x in resources_list] else: rcap = [int(max(self.rcpsp_model.resources[x])) for x in resources_list] - # print('rcap: ', rcap) + instance["rcap"] = rcap keys += ["rcap"] - # print('non_renewable_resources:', self.rcpsp_model.non_renewable_resources) rtype = [2 if res in self.rcpsp_model.non_renewable_resources else 1 for res in resources_list] - # print('rtype: ', rtype) instance["rtype"] = rtype keys += ["rtype"] succ = [set(self.rcpsp_model.successors[task]) for task in sorted_tasks] - # print('succ: ', succ) instance["succ"] = succ keys += ["succ"] @@ -307,19 +297,14 @@ def init_model(self, **args): if self.calendar: one_ressource = list(self.rcpsp_model.resources.keys())[0] instance["max_time"] = len(self.rcpsp_model.resources[one_ressource]) - print(instance["max_time"]) keys += ["max_time"] ressource_capacity_time = [[int(x) for x in self.rcpsp_model.resources[res]] for res in resources_list] - # print(instance["max_time"]) - # print(len(ressource_capacity_time)) - # print([len(x) for x in ressource_capacity_time]) + instance["ressource_capacity_time"] = ressource_capacity_time keys += ["ressource_capacity_time"] - # import pymzn - # pymzn.dict2dzn({key: instance[key] for key in keys}, - # fout='rcpsp_.dzn') + self.instance = instance p_s: Union[PartialSolution, None] = args.get("partial_solution", None) if p_s is not None: @@ -471,25 +456,21 @@ def init_model(self, **args): resources_list = list(self.rcpsp_model.resources.keys()) instance = Instance(solver, model) n_res = len(resources_list) - # print('n_res: ', n_res) + keys = [] instance["n_res"] = n_res keys += ["n_res"] - # rc = [val for val in self.rcpsp_model.resources.values()] - # # print('rc: ', rc) - # instance["rc"] = rc - n_tasks = self.rcpsp_model.n_jobs + 2 - # print('n_tasks: ', n_tasks) + instance["n_tasks"] = n_tasks keys += ["n_tasks"] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) - # print('mode_details: ', self.rcpsp_model.mode_details) + n_opt = sum([len(list(self.rcpsp_model.mode_details[key].keys())) for key in sorted_tasks]) - # print('n_opt: ', n_opt) + instance["n_opt"] = n_opt keys += ["n_opt"] @@ -501,7 +482,7 @@ def init_model(self, **args): general_counter = 1 for act in sorted_tasks: tmp = sorted(self.rcpsp_model.mode_details[act].keys()) - # tmp = [counter + x for x in tmp] + set_mode_task = set() for i in range(len(tmp)): original_mode_index = tmp[i] @@ -512,16 +493,12 @@ def init_model(self, **args): dur = dur + [self.rcpsp_model.mode_details[act][key]['duration'] for key in tmp] - # print('modes: ', modes) instance['modes'] = modes keys += ["modes"] - - # print('dur: ', dur) instance['dur'] = dur keys += ["dur"] - rreq = [] index = 0 for res in resources_list: @@ -531,7 +508,6 @@ def init_model(self, **args): rreq[index].append(int(self.rcpsp_model.mode_details[task][mod][res])) index += 1 - # print('rreq: ', rreq) instance["rreq"] = rreq keys += ["rreq"] @@ -539,20 +515,17 @@ def init_model(self, **args): rcap = [self.rcpsp_model.resources[x] for x in resources_list] else: rcap = [int(max(self.rcpsp_model.resources[x])) for x in resources_list] - # print('rcap: ', rcap) + instance["rcap"] = rcap keys += ["rcap"] - # print('non_renewable_resources:', self.rcpsp_model.non_renewable_resources) rtype = [2 if res in self.rcpsp_model.non_renewable_resources else 1 for res in resources_list] - # print('rtype: ', rtype) instance["rtype"] = rtype keys += ["rtype"] succ = [set(self.rcpsp_model.successors[task]) for task in sorted_tasks] - # print('succ: ', succ) instance["succ"] = succ keys += ["succ"] @@ -560,19 +533,14 @@ def init_model(self, **args): if self.calendar: one_ressource = list(self.rcpsp_model.resources.keys())[0] instance["max_time"] = len(self.rcpsp_model.resources[one_ressource]) - print(instance["max_time"]) keys += ["max_time"] ressource_capacity_time = [[int(x) for x in self.rcpsp_model.resources[res]] for res in resources_list] - # print(instance["max_time"]) - # print(len(ressource_capacity_time)) - # print([len(x) for x in ressource_capacity_time]) + instance["ressource_capacity_time"] = ressource_capacity_time keys += ["ressource_capacity_time"] - # import pymzn - # pymzn.dict2dzn({key: instance[key] for key in keys}, - # fout='rcpsp_.dzn') + self.instance = instance p_s: Union[PartialSolution, None] = args.get("partial_solution", None) if p_s is not None: @@ -613,7 +581,6 @@ def retrieve_solutions(self, result, parameters_cp: ParametersCP=ParametersCP.de if intermediate_solutions: for i in range(len(result)): object_result += [result[i]] - # print("Objective : ", result[i, "objective"]) else: object_result += [result] for res in object_result: @@ -703,7 +670,6 @@ def init_model(self, **args): modes.append(set(tmp)) counter = tmp[-1] - # print('modes: ', modes) instance['modes'] = modes keys += ["modes"] @@ -716,13 +682,12 @@ def init_model(self, **args): rreq[index].append(int(self.rcpsp_model.mode_details[task][mod][res])) index += 1 - # print('rreq: ', rreq) instance["rreq"] = rreq keys += ["rreq"] rcap = [val for val in self.rcpsp_model.resources.values()] - # print('rcap: ', rcap) + if isinstance(rcap[0], list): rcap = [int(max(r)) for r in rcap] instance["rcap"] = rcap @@ -733,9 +698,6 @@ def init_model(self, **args): instance["rtype"] = rtype keys += ["rtype"] - # import pymzn # For debug purposes - # pymzn.dict2dzn({k: instance[k] for k in keys}, fout="debug_modes_satisfaction.dzn") - self.instance: Instance = instance p_s: Union[PartialSolution, None] = args.get("partial_solution", None) if p_s is not None: @@ -745,7 +707,6 @@ def init_model(self, **args): indexes = [i for i in self.modeindex_map if self.modeindex_map[i]["task"] == task and self.modeindex_map[i]["original_mode_index"] == p_s.task_mode[task]] if len(indexes) >= 0: - print("Index found : ", len(indexes)) string = "constraint mrun[" + str(indexes[0]) + "] == 1;" self.instance.add_string(string) constraint_strings += [string] @@ -779,12 +740,9 @@ def solve(self, parameters_cp: ParametersCP = None, **args): timeout = parameters_cp.TimeLimit intermediate_solutions = parameters_cp.intermediate_solution result = self.instance.solve(timeout=timedelta(seconds=timeout), - # nr_solutions=1000, - # nr_solutions=1, nr_solutions=parameters_cp.nr_solutions if not parameters_cp.all_solutions else None, all_solutions=parameters_cp.all_solutions) - #intermediate_solutions=intermediate_solutions) verbose = args.get("verbose", False) if verbose: print(result.status) diff --git a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_cp_lns_solver.py b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_cp_lns_solver.py index b727951de2..d6a04398cc 100644 --- a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_cp_lns_solver.py +++ b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_cp_lns_solver.py @@ -210,12 +210,12 @@ def adding_constraint_from_results_store(self, cp_solver: CP_MRCPSP_MZN, == max_improvement]) d_params = {key: getattr(self.list_params[int(choice)], key) for key in self.list_params[0].__dict__.keys()} - print("Params : ", d_params) + ch = ConstraintHandlerStartTimeInterval_CP(problem=self.problem, **d_params) self.current_iteration += 1 self.last_index_param = choice self.status[self.last_index_param]["nb_usage"] += 1 - print("Status ", self.status) + return ch.adding_constraint_from_results_store(cp_solver, child_instance, result_storage) @@ -379,10 +379,7 @@ def build_neighbor_operator(option_neighbor: OptionNeighbor, rcpsp_model): if option_neighbor == OptionNeighbor.OM: params = params_om probas = [1 / len(params)] * len(params) - # self.constraint_handler = ConstraintHandlerStartTimeInterval_CP(problem=self.rcpsp_model, - # fraction_to_fix=0.5, - # minus_delta=1, - # plus_delta=1) + constraint_handler = ConstraintHandlerMix(problem=rcpsp_model, list_params=params, list_proba=probas) return constraint_handler @@ -397,12 +394,7 @@ def __init__(self, rcpsp_model: RCPSPModel, option_neighbor: OptionNeighbor=Opti self.solver.init_model(output_type=True) self.parameters_cp = ParametersCP.default() params_objective_function = get_default_objective_setup(problem=self.rcpsp_model) - # constraint_handler = ConstraintHandlerFixStartTime(problem=rcpsp_problem, - # fraction_fix_start_time=0.5) - # self.constraint_handler = ConstraintHandlerStartTimeInterval_CP(problem=self.rcpsp_model, - # fraction_to_fix=0.6, - # minus_delta=5, - # plus_delta=5) + self.constraint_handler = build_neighbor_operator(option_neighbor=option_neighbor, rcpsp_model=self.rcpsp_model) self.initial_solution_provider = InitialSolutionRCPSP(problem=self.rcpsp_model, diff --git a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py index 2cadf7820e..02760d4d3f 100644 --- a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py +++ b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_lp_lns_solver.py @@ -49,15 +49,12 @@ def __init__(self, problem: RCPSPModel, def get_starting_solution(self) -> ResultStorage: if self.initial_method == InitialMethodRCPSP.PILE: - print("Compute greedy") greedy_solver = PileSolverRCPSP(self.problem) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) if self.initial_method == InitialMethodRCPSP.PILE_CALENDAR: - print("Compute greedy") greedy_solver = PileSolverRCPSP_Calendar(self.problem) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) elif self.initial_method == InitialMethodRCPSP.DUMMY: - print("Compute dummy") solution = self.problem.get_dummy_solution() fit = self.aggreg(solution) store_solution = ResultStorage(list_solution_fits=[(solution, fit)], best_solution=solution, @@ -68,7 +65,6 @@ def get_starting_solution(self) -> ResultStorage: elif self.initial_method == InitialMethodRCPSP.LS: dummy = self.problem.get_dummy_solution() _, mutations = get_available_mutations(self.problem, dummy) - print(mutations) list_mutation = [mutate[0].build(self.problem, dummy, **mutate[1]) for mutate in mutations @@ -346,4 +342,4 @@ def __init__(self, rcpsp_model: RCPSPModel, **kwargs): def solve(self, **kwargs) -> ResultStorage: return self.lns_solver.solve_lns(parameters_milp=self.parameters_milp, - nb_iteration_lns=kwargs.get("nb_iteration_lns", 100)) \ No newline at end of file + nb_iteration_lns=kwargs.get("nb_iteration_lns", 100)) diff --git a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_pile.py b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_pile.py index 25b23c88fe..ce03eacd6a 100644 --- a/skdecide/discrete_optimization/rcpsp/solver/rcpsp_pile.py +++ b/skdecide/discrete_optimization/rcpsp/solver/rcpsp_pile.py @@ -242,15 +242,10 @@ def solve(self, **kwargs)->ResultStorage: schedule[task]["end_time"] = partial_solution.end_times[task] current_ressource_available = {r: list(self.resources[r])+[self.resources[r][-1]]*100 for r in self.resources} - # if self.with_calendar: - # current_ressource_available = {r: current_ressource_available[r][0] - # for r in current_ressource_available} current_ressource_non_renewable = {nr: list(self.resources[nr])+[self.resources[nr][-1]]*100 for nr in self.non_renewable} - # if self.with_calendar: - # current_ressource_non_renewable = {r: current_ressource_non_renewable[r][0] - # for r in current_ressource_non_renewable} + if 1 not in schedule: schedule[1] = {"start_time": 0, "end_time": 0} @@ -274,7 +269,7 @@ def solve(self, **kwargs)->ResultStorage: if True: print(len(schedule), current_time) print("available activities : ", available_activities) - #print(len(available_activities), "available activities") + possible_activities = [n for n in available_activities if all(self.mode_details[n][self.modes_dict[n]][r] <= current_ressource_available[r][min(time, @@ -282,25 +277,11 @@ def solve(self, **kwargs)->ResultStorage: for r in current_ressource_available for time in range(current_time, current_time + self.mode_details[n][self.modes_dict[n]]["duration"]))] - if current_time >= 10000: - print("hey") - - #print(len(possible_activities)) - # for n in available_activities: - # for time in range(current_time, current_time - # + self.mode_details[n][self.modes_dict[n]]["duration"]+1): - # for r in current_ressource_available: - # print("task ", n) - # print("time ", time) - # print("res ", r) - # print("Need ", self.mode_details[n][self.modes_dict[n]][r], - # "Avail ", current_ressource_available[r][time]) - # print(self.mode_details[n][self.modes_dict[n]][r] - # <= current_ressource_available[r][time]) + if verbose: print("Ressources : ", current_ressource_available) + while len(possible_activities) > 0: - #print(len(possible_activities), current_time) if greedy_choice == GreedyChoice.MOST_SUCCESSORS: next_activity = max(possible_activities, key=lambda x: current_succ[x]["nb"]) @@ -334,9 +315,7 @@ def solve(self, **kwargs)->ResultStorage: current_ressource_available[r][t] -= self.mode_details[next_activity][mode][r] if r in current_ressource_non_renewable: current_ressource_non_renewable[r][t] -= self.mode_details[next_activity][mode][r] - #if verbose: - # print(current_time) - # #"Current ressource available : ", current_ressource_available) + possible_activities = [n for n in available_activities if all(self.mode_details[n][self.modes_dict[n]][r] <= current_ressource_available[r][time] @@ -356,7 +335,6 @@ def solve(self, **kwargs)->ResultStorage: current_time += 1 if verbose: print("Final Time ", current_time) - # print("Final Time ", current_time) sol = RCPSPSolution(problem=self.rcpsp_model, rcpsp_permutation=perm[:-1], rcpsp_schedule=schedule, @@ -427,7 +405,7 @@ def compute_schedule_from_priority_list(self, if all(self.mode_details[n][modes_dict[n]][r] <= current_ressource_available[r] for r in current_ressource_available)] - # print(current_ressource_available, self.rcpsp_model.non_renewable_resources) + current_time, activity, descr = pop(queue) for neighbor in self.immediate_successors[activity]: if activity in current_pred[neighbor]["succs"]: @@ -438,7 +416,7 @@ def compute_schedule_from_priority_list(self, for r in self.resources: if r not in current_ressource_non_renewable: current_ressource_available[r] += self.mode_details[activity][modes_dict[activity]][r] - # print("Final Time ", current_time) + sol = RCPSPSolution(problem=self.rcpsp_model, rcpsp_permutation=perm[:-1], rcpsp_schedule=schedule, diff --git a/skdecide/discrete_optimization/rcpsp_multiskill/solvers/calendar_solver_iterative.py b/skdecide/discrete_optimization/rcpsp_multiskill/solvers/calendar_solver_iterative.py index e4a0caa848..8d868f85c3 100644 --- a/skdecide/discrete_optimization/rcpsp_multiskill/solvers/calendar_solver_iterative.py +++ b/skdecide/discrete_optimization/rcpsp_multiskill/solvers/calendar_solver_iterative.py @@ -76,12 +76,10 @@ def get_ressource_breaks(problem_calendar: MS_RCPSPModel, for r in ressource_arrays: index = np.argwhere(ressource_arrays[r] > problem_calendar.resources_availability[r]) index_ressource[r] = index - # print("Constraints broken : ", r, index) task_concerned[r] = [j for j in range(ressource_arrays_usage[r].shape[1]) if any(ressource_arrays_usage[r][ind[0], j] == 1 for ind in index if problem_calendar.resources_availability[r][ind[0]] == 0)] - # print("Concerned : ", task_concerned[r]) task_concerned[r] = [sorted_keys_schedule[rr] for rr in task_concerned[r]] constraints[r] = {} for t in task_concerned[r]: @@ -105,14 +103,12 @@ def get_ressource_breaks(problem_calendar: MS_RCPSPModel, constraints_employee = {} for emp in employees_arrays: index = np.argwhere(employees_arrays[emp] > 1*problem_calendar.employees[emp].calendar_employee) - # print([employees_arrays[emp][i[0]] for i in index], - # [problem_calendar.employees[emp].calendar_employee[i[0]] for i in index]) + # index_ressource[emp] = index task_concerned[emp] = [j for j in range(employees_arrays_usage[emp].shape[1]) if any(employees_arrays_usage[emp][ind[0], j] == 1 for ind in index if not problem_calendar.employees[emp].calendar_employee[ind[0]])] - # print("Concerned : ", task_concerned[r]) task_concerned[emp] = [sorted_keys_schedule[rr] for rr in task_concerned[emp]] constraints_employee[emp] = {} for t in task_concerned[emp]: @@ -124,10 +120,7 @@ def get_ressource_breaks(problem_calendar: MS_RCPSPModel, first_possible_start_before = next((st for st in range(current_start, -1, -1) if problem_calendar.employees[emp].calendar_employee[st]), None) - # if first_possible_start_before is not None: - # first_possible_start_before = \ - # max(0, - # first_possible_start_before-problem_calendar.mode_details[t][1]["duration"]+1) + constraints_employee[emp] = (first_possible_start_before, first_possible_start_future) return index_ressource, constraints, constraints_employee @@ -181,7 +174,6 @@ def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: sol[0].satisfy = not(any(len(rb[r]) > 0 for r in rb)) sol[0].satisfy = self.problem_calendar.satisfy(sol[0]) sol[0].constraints = constraints - print("Check Ressource : ", sol[0].satisfy) if sol[0].satisfy is False: if self.partial_solution is None: s: MS_RCPSPSolution = sol[0] @@ -191,8 +183,7 @@ def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: solution.satisfy = self.problem_calendar.satisfy(solution) result_storage.list_solution_fits += [(solution, -self.problem_calendar.evaluate(solution)["makespan"])] - # result_storage.list_solution_fits = [r for r in result_storage.list_solution_fits - # if r[0].satisfy] + return result_storage @@ -210,7 +201,6 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_MS_MRCPSP_MZN solution, fit = result_storage.get_best_solution_fit() solution: MS_RCPSPSolution = solution if ("satisfy" in solution.__dict__.keys() and solution.satisfy): - print("adding the other constraints !") return self.other_constraint.adding_constraint_from_results_store(cp_solver, child_instance, ResultStorage(list_solution_fits=[(solution, fit)], @@ -266,9 +256,7 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_MS_MRCPSP_MZN + """< start[i] + adur[i]) * arreq["""+str(index_ressource+1)+""",i]);\n""" child_instance.add_string(s) list_strings += [s] - # print(s) - # print("Res", r) - # print("Time", index) + if r in self.problem_calendar.employees: index_ressource = cp_solver.employees_position.index(r) rq = int(self.problem_calendar.employees[r].calendar_employee[ind]) @@ -279,9 +267,6 @@ def adding_constraint_from_results_store(self, cp_solver: Union[CP_MS_MRCPSP_MZN + """< start[i] + adur[i]) * unit_used["""+str(index_ressource+1)+""",i]);\n""" child_instance.add_string(s) list_strings += [s] - # print(s) - # print("Res", r) - # print("Time", index) satisfiable = [(s, f) for s, f in result_storage.list_solution_fits if "satisfy" in s.__dict__.keys() @@ -372,7 +357,6 @@ def solve(self, init_solution, objective = store_lns.get_best_solution_fit() best_solution = init_solution.copy() satisfy = self.problem_calendar.satisfy(init_solution) - print("Satisfy ", satisfy) best_objective = objective else: best_objective = float('inf') if sense == ModeOptim.MINIMIZATION else -float("inf") @@ -382,8 +366,6 @@ def solve(self, store_with_all = None constraint_to_keep = set() for iteration in range(nb_iteration_lns): - print('Starting iteration n°', iteration, - " current objective ", best_objective) try: print("Best feasible solution ", max([f for s, f in store_with_all.list_solution_fits if "satisfy" in s.__dict__.keys() and s.satisfy])) @@ -407,18 +389,10 @@ def solve(self, result = child.solve(timeout=timedelta(seconds=parameters_cp.TimeLimit), intermediate_solutions=parameters_cp.intermediate_solution) result_store = self.cp_solver.retrieve_solutions(result, parameters_cp=parameters_cp) - print("iteration n°", iteration, "Solved !!!") - print(result.status) if len(result_store.list_solution_fits) > 0: - print("Solved !!!") bsol, fit = result_store.get_best_solution_fit() - print("Fitness = ", fit) - print("Post Process..") - print("Satisfy best current sol : ") - print(self.problem_calendar.satisfy(bsol)) result_store = self.post_process_solution.build_other_solution(result_store) bsol, fit = result_store.get_best_solution_fit() - print("After postpro = ", fit) if sense == ModeOptim.MAXIMIZATION and fit >= best_objective: if fit > best_objective: current_nb_iteration_no_improvement = 0 @@ -447,23 +421,16 @@ def solve(self, for s, f in store_with_all.list_solution_fits: if s.satisfy: store_lns.list_solution_fits += [(s,f)] - print("Satisfy : ", self.problem_calendar.satisfy(best_solution)) else: current_nb_iteration_no_improvement += 1 if skip_first_iteration and result.status == Status.OPTIMAL_SOLUTION and iteration == 0\ and best_solution.satisfy: - print("Finish LNS because found optimal solution") break else: - #except Exception as e: current_nb_iteration_no_improvement += 1 - print("Failed ! reason : ", e) if time.time() - deb_time > max_time_seconds: - print("Finish LNS with time limit reached") break - print(current_nb_iteration_no_improvement, "/", nb_iteration_no_improvement) if current_nb_iteration_no_improvement > nb_iteration_no_improvement: - print("Finish LNS with maximum no improvement iteration ") break return store_with_all diff --git a/skdecide/hub/__init__.py b/skdecide/hub/__init__.py index dfd2989f76..efef521855 100644 --- a/skdecide/hub/__init__.py +++ b/skdecide/hub/__init__.py @@ -20,63 +20,5 @@ pl.append(os.path.join(dirpath, 'bin')) os.environ["MZN_SOLVER_PATH"] = dirpath -#sys.path.extend(pl) - os.environ["PATH"] += os.pathsep + os.pathsep.join(pl) - -""" path_bin = os.environ.get("PATH", "").split(os.pathsep) -print(path_bin) -path_lib = os.environ.get("LD_LIBRARY_PATH", "").split(os.pathsep) -path_lib.extend(os.environ.get("DYLD_LIBRARY_PATH", "").split(os.pathsep)) - -# Add default MiniZinc locations to the path -if platform.system() == "Darwin": - MAC_LOCATIONS = [ - str(Path("/Applications/MiniZincIDE.app/Contents/Resources")), - str(Path("~/Applications/MiniZincIDE.app/Contents/Resources").expanduser()), - ] - path_bin.extend(MAC_LOCATIONS) - path_lib.extend(MAC_LOCATIONS) -elif platform.system() == "Windows": - WIN_LOCATIONS = [ - str(Path("c:/Program Files/MiniZinc")), - str(Path("c:/Program Files/MiniZinc IDE (bundled)")), - str(Path("c:/Program Files (x86)/MiniZinc")), - str(Path("c:/Program Files (x86)/MiniZinc IDE (bundled)")), - ] - path_bin.extend(WIN_LOCATIONS) - path_lib.extend(WIN_LOCATIONS) - - -path_bin_list = os.pathsep.join(path_bin) -path_lib_list = os.pathsep.join(path_lib) - -# Try to load the MiniZinc C API -env_backup = os.environ.copy() -os.environ["LD_LIBRARY_PATH"] = path_lib_list -os.environ["DYLD_LIBRARY_PATH"] = path_lib_list - -name = "minizinc" - -lib = find_library(name) - -if lib and Path(lib).suffix in [".dll", ".dylib", ".so"]: - pass - # TODO: - # from minizinc.API import APIDriver - - # library = cdll.LoadLibrary(lib) - # driver = APIDriver(library) - print("lib {} found".format(name)) -else: - # Try to locate the MiniZinc executable - executable = shutil.which(name, path=path_bin_list) - print("executable {} is {} in {}".format(name, executable, path_bin_list)) - -def goodbye(env_backup): - os.environ.clear() - os.environ.update(env_backup) - -import atexit -atexit.register(goodbye, env_backup=env_backup) """ \ No newline at end of file diff --git a/skdecide/hub/solver/do_solver/do_solver_scheduling.py b/skdecide/hub/solver/do_solver/do_solver_scheduling.py index b527be228a..7fb355dfae 100644 --- a/skdecide/hub/solver/do_solver/do_solver_scheduling.py +++ b/skdecide/hub/solver/do_solver/do_solver_scheduling.py @@ -63,9 +63,10 @@ def build_solver(solving_method: SolvingMethod, do_domain): SolvingMethod.LNS_LP: "lns-lp", SolvingMethod.LNS_CP: "lns-cp", SolvingMethod.LNS_CP_CALENDAR: "lns-cp-calendar"} - print([(av, solvers_map[av]) for av in available]) + smap = [(av, solvers_map[av]) for av in available if solvers_map[av][0] == solving_method_to_str[solving_method]] + if len(smap) > 0: return smap[0] @@ -142,7 +143,7 @@ def get_available_methods(self, domain: SchedulingDomain): from skdecide.discrete_optimization.rcpsp.rcpsp_solvers import look_for_solver, solvers_map available = look_for_solver(do_domain) smap = [(av, solvers_map[av]) for av in available] - print("available solvers :", smap) + return smap def _solve_domain(self, domain_factory: Callable[[], D]) -> None: @@ -163,9 +164,9 @@ def _solve_domain(self, domain_factory: Callable[[], D]) -> None: result_storage = self.solver.solve(**self.dict_params) best_solution: RCPSPSolution = result_storage.get_best_solution() fits = self.do_domain.evaluate(best_solution) - print("Best solution fitness found : ", fits) + self.best_solution = best_solution - print("Satisfiable ", self.do_domain.satisfy(self.best_solution)) + self.policy_object = from_solution_to_policy(solution=best_solution, domain=self.domain, policy_method_params=self.policy_method_params) @@ -183,5 +184,3 @@ def _get_next_action(self, observation: D.T_agent[D.T_observation]) -> D.T_agent def _is_policy_defined_for(self, observation: D.T_agent[D.T_observation]) -> bool: return self.policy_object.is_policy_defined_for(observation=observation) - - diff --git a/skdecide/hub/solver/do_solver/sk_to_do_binding.py b/skdecide/hub/solver/do_solver/sk_to_do_binding.py index 909ff491cf..806bcc2934 100644 --- a/skdecide/hub/solver/do_solver/sk_to_do_binding.py +++ b/skdecide/hub/solver/do_solver/sk_to_do_binding.py @@ -137,7 +137,6 @@ def build_do_domain(scheduling_domain: Union[SingleModeRCPSP, employees_dict = {} employees = scheduling_domain.get_resource_units_names() sorted_employees = sorted(employees) - print(sorted_employees) for employee, i in zip(sorted_employees, range(len(sorted_employees))): skills = scheduling_domain.get_skills_of_resource(resource=employee) skills_details = {r: SkillDetail(skill_value=skills[r],