예제 #1
0
 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}
예제 #2
0
 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
예제 #3
0
    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,
        )
예제 #4
0
 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
예제 #5
0
 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
예제 #6
0
 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)
예제 #7
0
    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
예제 #8
0
 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)
예제 #9
0
 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,
     )
예제 #10
0
    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
예제 #11
0
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
        },
예제 #12
0
    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,
        )