def __init__(self, rcpsp_model: RCPSPModel, params_objective_function: ParamsObjectiveFunction = None, **kwargs): self.rcpsp_model = rcpsp_model self.resources = rcpsp_model.resources self.non_renewable = rcpsp_model.non_renewable_resources self.n_jobs = rcpsp_model.n_jobs self.mode_details = rcpsp_model.mode_details self.graph = rcpsp_model.compute_graph() self.nx_graph: nx.DiGraph = self.graph.to_networkx() self.successors_map = {} self.predecessors_map = {} # successors = nx.dfs_successors(self.nx_graph, 1, self.n_jobs+2) successors = { n: nx.algorithms.descendants(self.nx_graph, n) for n in self.nx_graph.nodes() } self.source = 1 self.sink = self.n_jobs + 2 self.all_activities = set(range(1, self.n_jobs + 3)) for k in successors: self.successors_map[k] = { "succs": successors[k], "nb": len(successors[k]) } predecessors = { n: nx.algorithms.ancestors(self.nx_graph, n) for n in self.nx_graph.nodes() } for k in predecessors: self.predecessors_map[k] = { "succs": predecessors[k], "nb": len(predecessors[k]), } ( self.aggreg_from_sol, self.aggreg_from_dict, self.params_objective_function, ) = build_aggreg_function_and_params_objective( problem=self.rcpsp_model, params_objective_function=params_objective_function, ) if isinstance(self.rcpsp_model, (MultiModeRCPSPModel, RCPSPModelCalendar)): solver = CP_MRCPSP_MZN_MODES(self.rcpsp_model, cp_solver_name=CPSolverName.CHUFFED) params_cp = ParametersCP.default() params_cp.time_limit = 1 params_cp.pool_solutions = 10000 params_cp.nr_solutions = 1 # params_cp.nr_solutions = float("inf") params_cp.all_solutions = False result_storage = solver.solve(parameters_cp=params_cp) one_mode_setting = result_storage[0] self.modes_dict = {} for i in range(len(one_mode_setting)): self.modes_dict[i + 1] = one_mode_setting[i] else: self.modes_dict = {t: 1 for t in self.mode_details}
def retrieve_solutions( self, result, parameters_cp: ParametersCP = ParametersCP.default() ): intermediate_solutions = parameters_cp.intermediate_solution best_solution = None best_makespan = -float("inf") list_solutions_fit = [] mruns = [] if intermediate_solutions: for i in range(len(result)): mruns += [result[i, "mrun"]] else: mruns += [result["mrun"]] all_modes = [] for mrun in mruns: modes = [1] * (self.rcpsp_model.n_jobs + 2) for i in range(len(mrun)): if ( mrun[i] == 1 and (self.modeindex_map[i + 1]["task"] != 1) and ( self.modeindex_map[i + 1]["task"] != self.rcpsp_model.n_jobs + 2 ) ): modes[self.modeindex_map[i + 1]["task"] - 1] = self.modeindex_map[ i + 1 ]["original_mode_index"] all_modes += [modes] return all_modes
def __init__(self, rcpsp_model: RCPSPModel, option_neighbor: OptionNeighbor = OptionNeighbor.MIX_ALL, **kwargs): self.rcpsp_model = rcpsp_model self.solver = CP_MRCPSP_MZN(rcpsp_model=self.rcpsp_model, cp_solver_name=CPSolverName.CHUFFED) self.solver.init_model(output_type=True) self.parameters_cp = ParametersCP.default() params_objective_function = get_default_objective_setup( problem=self.rcpsp_model) self.constraint_handler = build_neighbor_operator( option_neighbor=option_neighbor, rcpsp_model=self.rcpsp_model) self.initial_solution_provider = InitialSolutionRCPSP( problem=self.rcpsp_model, initial_method=InitialMethodRCPSP.PILE, params_objective_function=params_objective_function, ) self.lns_solver = LNS_CP( problem=self.rcpsp_model, cp_solver=self.solver, initial_solution_provider=self.initial_solution_provider, constraint_handler=self.constraint_handler, params_objective_function=params_objective_function, )
def get_starting_solution(self) -> ResultStorage: if self.initial_method == InitialMethodRCPSP.PILE: greedy_solver = PileSolverRCPSP(self.problem) store_solution = greedy_solver.solve( greedy_choice=GreedyChoice.MOST_SUCCESSORS ) if self.initial_method == InitialMethodRCPSP.PILE_CALENDAR: greedy_solver = PileSolverRCPSP_Calendar(self.problem) store_solution = greedy_solver.solve( greedy_choice=GreedyChoice.MOST_SUCCESSORS ) elif self.initial_method == InitialMethodRCPSP.DUMMY: solution = self.problem.get_dummy_solution() fit = self.aggreg(solution) store_solution = ResultStorage( list_solution_fits=[(solution, fit)], best_solution=solution, mode_optim=self.params_objective_function.sense_function, ) elif self.initial_method == InitialMethodRCPSP.CP: solver = CP_MRCPSP_MZN( rcpsp_model=self.problem, params_objective_function=self.params_objective_function, ) store_solution = solver.solve(parameters_cp=ParametersCP.default()) elif self.initial_method == InitialMethodRCPSP.LS: dummy = self.problem.get_dummy_solution() _, mutations = get_available_mutations(self.problem, dummy) list_mutation = [ mutate[0].build(self.problem, dummy, **mutate[1]) for mutate in mutations if mutate[0] == PermutationMutationRCPSP ] # and mutate[1]["other_mutation"] == TwoOptMutation] mixed_mutation = BasicPortfolioMutation( list_mutation, np.ones((len(list_mutation))) ) res = RestartHandlerLimit( 500, cur_solution=dummy, cur_objective=self.problem.evaluate(dummy) ) sa = SimulatedAnnealing( evaluator=self.problem, mutator=mixed_mutation, restart_handler=res, temperature_handler=TemperatureSchedulingFactor(2, res, 0.9999), mode_mutation=ModeMutation.MUTATE, params_objective_function=self.params_objective_function, store_solution=True, nb_solutions=10000, ) store_solution = sa.solve( dummy, nb_iteration_max=10000, pickle_result=False ) return store_solution
def retrieve_solutions( self, result, parameters_cp: ParametersCP = ParametersCP.default() ): intermediate_solutions = parameters_cp.intermediate_solution best_solution = None best_makespan = -float("inf") list_solutions_fit = [] starts = [] mruns = [] object_result: List[MRCPSP_Result] = [] if intermediate_solutions: for i in range(len(result)): object_result += [result[i]] else: object_result += [result] for res in object_result: modes = [] for j in range(len(res.mode_chosen)): if (self.modeindex_map[j + 1]["task"] != 1) and ( self.modeindex_map[j + 1]["task"] != self.rcpsp_model.n_jobs + 2 ): modes.append( self.modeindex_map[res.mode_chosen[j]]["original_mode_index"] ) elif (self.modeindex_map[j + 1]["task"] == 1) or ( self.modeindex_map[j + 1]["task"] == self.rcpsp_model.n_jobs + 2 ): modes.append(1) rcpsp_schedule = {} start_times = res.dict["start"] for i in range(len(start_times)): rcpsp_schedule[i + 1] = { "start_time": start_times[i], "end_time": start_times[i] + self.rcpsp_model.mode_details[i + 1][modes[i]]["duration"], } sol = RCPSPSolution( problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_modes=modes[1:-1], rcpsp_schedule_feasible=True, ) objective = self.aggreg_from_dict_values(self.rcpsp_model.evaluate(sol)) if objective > best_makespan: best_makespan = objective best_solution = sol.copy() list_solutions_fit += [(sol, objective)] result_storage = ResultStorage( list_solution_fits=list_solutions_fit, best_solution=best_solution, mode_optim=self.params_objective_function.sense_function, limit_store=False, ) return result_storage
def solve(self, parameters_cp: ParametersCP = ParametersCP.default(), **args): if self.instance is None: self.init_model(**args) timeout = parameters_cp.TimeLimit intermediate_solutions = parameters_cp.intermediate_solution result = self.instance.solve( timeout=timedelta(seconds=timeout), intermediate_solutions=intermediate_solutions, ) verbose = args.get("verbose", True) if verbose: print(result.status) return self.retrieve_solutions(result=result, parameters_cp=parameters_cp)
def retrieve_solutions( self, result, parameters_cp: ParametersCP = ParametersCP.default() ) -> ResultStorage: intermediate_solutions = parameters_cp.intermediate_solution best_solution = None best_makespan = -float("inf") list_solutions_fit = [] starts = [] if intermediate_solutions: for i in range(len(result)): if isinstance(result[i], RCPSPSolCP): starts += [result[i].dict["s"]] else: starts += [result[i, "s"]] else: if isinstance(result, RCPSPSolCP): starts += [result.dict["s"]] else: starts = [result["s"]] for start_times in starts: rcpsp_schedule = {} for k in range(len(start_times)): rcpsp_schedule[k + 1] = { "start_time": start_times[k], "end_time": start_times[k] + self.rcpsp_model.mode_details[k + 1][1]["duration"], } sol = RCPSPSolution( problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_schedule_feasible=True, ) objective = self.aggreg_from_dict_values(self.rcpsp_model.evaluate(sol)) if objective > best_makespan: best_makespan = objective best_solution = sol.copy() list_solutions_fit += [(sol, objective)] result_storage = ResultStorage( list_solution_fits=list_solutions_fit, best_solution=best_solution, mode_optim=self.params_objective_function.sense_function, limit_store=False, ) return result_storage
def solve( self, parameters_cp: ParametersCP = ParametersCP.default(), **args ): # partial_solution: PartialSolution=None, **args): if self.instance is None: self.init_model(**args) timeout = parameters_cp.TimeLimit intermediate_solutions = parameters_cp.intermediate_solution try: result = self.instance.solve( timeout=timedelta(seconds=timeout), intermediate_solutions=intermediate_solutions, ) except Exception as e: print(e) return None verbose = args.get("verbose", False) if verbose: print(result.status) print(result.statistics["solveTime"]) return self.retrieve_solutions(result, parameters_cp=parameters_cp)
def __init__(self, problem_calendar: MS_RCPSPModel, partial_solution: PartialSolution = None, option_neighbor: OptionNeighbor = OptionNeighbor.MIX_FAST, **kwargs): self.problem_calendar = problem_calendar self.problem_no_calendar = self.problem_calendar.copy() self.problem_no_calendar = MS_RCPSPModel( skills_set=self.problem_calendar.skills_set, resources_set=self.problem_calendar.resources_set, non_renewable_resources=self.problem_calendar. non_renewable_resources, resources_availability={ r: [int(max(self.problem_calendar.resources_availability[r]))] * len(self.problem_calendar.resources_availability[r]) for r in self.problem_calendar.resources_availability }, employees={ emp: self.problem_calendar.employees[emp].copy() for emp in self.problem_calendar.employees }, employees_availability=self.problem_calendar. employees_availability, mode_details=self.problem_calendar.mode_details, successors=self.problem_calendar.successors, horizon=self.problem_calendar.horizon, horizon_multiplier=self.problem_calendar.horizon_multiplier, ) for emp in self.problem_calendar.employees: self.problem_no_calendar.employees[emp].calendar_employee = [ max(self.problem_calendar.employees[emp].calendar_employee) ] * len(self.problem_calendar.employees[emp].calendar_employee) solver = CP_MS_MRCPSP_MZN(rcpsp_model=self.problem_no_calendar, cp_solver_name=CPSolverName.CHUFFED) solver.init_model( output_type=True, model_type="single", partial_solution=partial_solution, add_calendar_constraint_unit=False, exact_skills_need=False, ) 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 = build_neighbor_operator( option_neighbor=option_neighbor, rcpsp_model=self.problem_no_calendar) constraint_handler = ConstraintHandlerAddCalendarConstraint( self.problem_calendar, self.problem_no_calendar, constraint_handler) initial_solution_provider = InitialSolutionMS_RCPSP( 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 self.cp_solver = solver self.post_process_solution = PostProcessSolutionNonFeasible( self.problem_calendar, self.problem_no_calendar, partial_solution=partial_solution, )
def retrieve_solutions( self, result, parameters_cp: ParametersCP = ParametersCP.default()): intermediate_solutions = parameters_cp.intermediate_solution best_solution = None best_makespan = -float("inf") list_solutions_fit = [] starts = [] mruns = [] units_used = [] if intermediate_solutions: for i in range(len(result)): if isinstance(result[i], MS_RCPSPSolCP): starts += [result[i].dict["start"]] mruns += [result[i].dict["mrun"]] units_used += [result[i].dict["unit_used"]] else: starts += [result[i, "start"]] mruns += [result[i, "mrun"]] units_used += [result[i, "unit_used"]] else: if isinstance(result, MS_RCPSPSolCP): starts += [result.dict["start"]] mruns += [result.dict["mrun"]] units_used += [result.dict["unit_used"]] else: starts += [result["start"]] mruns += [result["mrun"]] units_used += [result["unit_used"]] # array_skill = result["array_skills_required"] for start_times, mrun, unit_used in zip(starts, mruns, units_used): modes = [] usage = {} for i in range(len(mrun)): if (mrun[i] and (self.modeindex_map[i + 1]["task"] != 1) and (self.modeindex_map[i + 1]["task"] != self.rcpsp_model.n_jobs_non_dummy + 2)): modes.append(self.modeindex_map[i + 1]["original_mode_index"]) elif (self.modeindex_map[i + 1]["task"] == 1) or (self.modeindex_map[i + 1]["task"] == self.rcpsp_model.n_jobs_non_dummy + 2): modes.append(1) for w in range(len(unit_used)): for task in range(len(unit_used[w])): if unit_used[w][task] == 1: task_id = task + 1 mode = modes[task_id - 1] skills_needed = set([ s # , self.rcpsp_model.mode_details[task_id][mode][s]) for s in self.rcpsp_model.skills_set if s in self.rcpsp_model.mode_details[task_id][mode] and self.rcpsp_model.mode_details[task_id][mode][s] > 0 ]) skills_worker = set([ s # self.rcpsp_model.employees[self.employees_position[w]].dict_skill[s].skill_value) for s in self.rcpsp_model.employees[ self.employees_position[w]].dict_skill if self.rcpsp_model.employees[ self.employees_position[w]].dict_skill[s]. skill_value > 0 ]) intersection = skills_needed.intersection( skills_worker) if len(intersection) > 0: if task_id not in usage: usage[task_id] = {} usage[task_id][ self.employees_position[w]] = intersection rcpsp_schedule = {} for i in range(len(start_times)): rcpsp_schedule[i + 1] = { "start_time": start_times[i], "end_time": start_times[i] + self.rcpsp_model.mode_details[i + 1][modes[i]]["duration"], } sol = MS_RCPSPSolution( problem=self.rcpsp_model, modes={i + 1: modes[i] for i in range(len(modes))}, schedule=rcpsp_schedule, employee_usage=usage, ) objective = self.aggreg_from_dict_values( self.rcpsp_model.evaluate(sol)) if objective > best_makespan: best_makespan = objective best_solution = sol.copy() list_solutions_fit += [(sol, objective)] result_storage = ResultStorage( list_solution_fits=list_solutions_fit, best_solution=best_solution, mode_optim=self.params_objective_function.sense_function, limit_store=False, ) return result_storage
from skdecide.discrete_optimization.rcpsp_multiskill.solvers.ms_rcpsp_ga_solver import ( GA_MSRCPSP_Solver, ) solvers = { "lp": [( LP_Solver_MRSCPSP, { "lp_solver": MilpSolverName.CBC, "parameters_milp": ParametersMilp.default(), }, )], "cp": [( CP_MS_MRCPSP_MZN, { "cp_solver_name": CPSolverName.CHUFFED, "parameters_cp": ParametersCP.default(), }, )], "lns": [( LNS_CP_MS_RCPSP_SOLVER, { "nb_iteration_lns": 20, "option_neighbor": OptionNeighbor.MIX_FAST }, )], "lns-cp": [( LNS_CP_MS_RCPSP_SOLVER, { "nb_iteration_lns": 20, "option_neighbor": OptionNeighbor.MIX_FAST },
def __init__( self, problem_calendar: RCPSPModelCalendar, partial_solution: PartialSolution = None, **kwargs ): self.problem_calendar = problem_calendar if not isinstance(problem_calendar, RCPSPModelCalendar): self.problem_calendar = RCPSPModelCalendar( resources={ r: [problem_calendar.resources[r]] * problem_calendar.horizon for r in problem_calendar.resources }, non_renewable_resources=self.problem_calendar.non_renewable_resources, mode_details=self.problem_calendar.mode_details, successors=self.problem_calendar.successors, horizon=self.problem_calendar.horizon, ) self.problem_no_calendar = RCPSPModel( resources={ r: int(max(self.problem_calendar.resources[r])) for r in self.problem_calendar.resources }, non_renewable_resources=self.problem_calendar.non_renewable_resources, mode_details=self.problem_calendar.mode_details, 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.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 = 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 = 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 self.cp_solver = solver self.post_process_solution = PostProcessSolutionNonFeasible( self.problem_calendar, self.problem_no_calendar, partial_solution=partial_solution, )