Example #1
0
 def solve(self, **kwargs):
     res_storage = solve(method=self.method,
                         rcpsp_model=self.model_rcpsp,
                         **self.args_solve)
     list_solution_fits = []
     for s, fit in res_storage.list_solution_fits:
         sol: RCPSPSolution = s
         mode = sol.rcpsp_modes
         modes = {i + 2: mode[i] for i in range(len(mode))}
         modes[self.model.source_task] = 1
         modes[self.model.sink_task] = 1
         # print(fit, " found by ", self.method.__name__)
         ms_rcpsp_solution = MS_RCPSPSolution_Variant(
             problem=self.model,
             priority_list_task=sol.rcpsp_permutation,
             modes_vector=sol.rcpsp_modes,
             priority_worker_per_task=[[
                 w for w in self.model.employees
             ] for i in range(self.model.n_jobs_non_dummy)],
         )
         list_solution_fits += [(ms_rcpsp_solution,
                                 self.aggreg_from_sol(ms_rcpsp_solution))]
     return ResultStorage(
         list_solution_fits=list_solution_fits,
         mode_optim=self.params_objective_function.sense_function,
     )
Example #2
0
 def generate_super_pareto(self):
     sols = []
     for rs in self.list_result_storage:
         for s in rs.list_solution_fits:
             sols.append(s)
     rs = ResultStorage(list_solution_fits=sols, best_solution=None)
     pareto_store = result_storage_to_pareto_front(result_storage=rs,
                                                   problem=None)
     return pareto_store
Example #3
0
 def adding_constraint_from_results_store(
     self, milp_solver: LP_Solver_MRSCPSP, result_storage: ResultStorage
 ) -> Iterable[Any]:
     current_solution: MS_RCPSPSolution = result_storage.get_best_solution()
     # st = milp_solver.start_solution
     # if self.problem.evaluate(st)["makespan"] < self.problem.evaluate(current_solution)["makespan"]:
     #    current_solution = st
     start = []
     for j in current_solution.schedule:
         start_time_j = current_solution.schedule[j]["start_time"]
         mode = current_solution.modes[j]
         start += [(milp_solver.start_times_task[j], start_time_j)]
         start += [(milp_solver.modes[j][mode], 1)]
         for m in milp_solver.modes[j]:
             start += [(milp_solver.modes[j][m], 1 if mode == m else 0)]
     milp_solver.model.start = start
     constraints_dict = {}
     constraints_dict["range_start_time"] = []
     max_time = max(
         [
             current_solution.schedule[x]["end_time"]
             for x in current_solution.schedule
         ]
     )
     last_jobs = [
         x
         for x in current_solution.schedule
         if current_solution.schedule[x]["end_time"] >= max_time - 5
     ]
     nb_jobs = self.problem.nb_tasks
     jobs_to_fix = set(
         random.sample(
             current_solution.schedule.keys(), int(self.fraction_to_fix * nb_jobs)
         )
     )
     for lj in last_jobs:
         if lj in jobs_to_fix:
             jobs_to_fix.remove(lj)
     for job in jobs_to_fix:
         start_time_j = current_solution.schedule[job]["start_time"]
         min_st = max(start_time_j - self.minus_delta, 0)
         max_st = min(start_time_j + self.plus_delta, max_time)
         constraints_dict["range_start_time"].append(
             milp_solver.model.add_constr(
                 milp_solver.start_times_task[job] <= max_st
             )
         )
         constraints_dict["range_start_time"].append(
             milp_solver.model.add_constr(
                 milp_solver.start_times_task[job] >= min_st
             )
         )
     if milp_solver.lp_solver == MilpSolverName.GRB:
         milp_solver.model.solver.update()
     return constraints_dict
 def adding_constraint_from_results_store(
     self,
     cp_solver: Union[CP_RCPSP_MZN, CP_MRCPSP_MZN],
     child_instance,
     result_storage: ResultStorage,
 ) -> Iterable[Any]:
     constraints_dict = {}
     current_solution, fit = result_storage.get_best_solution_fit()
     max_time = max([
         current_solution.rcpsp_schedule[x]["end_time"]
         for x in current_solution.rcpsp_schedule
     ])
     last_jobs = [
         x for x in current_solution.rcpsp_schedule
         if current_solution.rcpsp_schedule[x]["end_time"] >= max_time -
         self.delta_time_from_makepan_to_not_fix
     ]
     nb_jobs = self.problem.n_jobs + 2
     jobs_to_fix = set(
         random.sample(
             current_solution.rcpsp_schedule.keys(),
             int(self.fraction_to_fix * nb_jobs),
         ))
     for lj in last_jobs:
         if lj in jobs_to_fix:
             jobs_to_fix.remove(lj)
     list_strings = []
     for job in jobs_to_fix:
         start_time_j = current_solution.rcpsp_schedule[job]["start_time"]
         min_st = max(start_time_j - self.minus_delta, 0)
         max_st = min(start_time_j + self.plus_delta, max_time)
         if isinstance(cp_solver, CP_RCPSP_MZN):
             string1 = "constraint s[" + str(job) + "] <= " + str(
                 max_st) + ";\n"
             string2 = "constraint s[" + str(job) + "] >= " + str(
                 min_st) + ";\n"
         elif isinstance(cp_solver, CP_MRCPSP_MZN):
             string1 = "constraint start[" + str(job) + "] <= " + str(
                 max_st) + ";\n"
             string2 = "constraint start[" + str(job) + "] >= " + str(
                 min_st) + ";\n"
         list_strings += [string1]
         list_strings += [string2]
         child_instance.add_string(string1)
         child_instance.add_string(string2)
     for job in current_solution.rcpsp_schedule:
         if isinstance(cp_solver, CP_RCPSP_MZN):
             string = ("constraint s[" + str(job) + "] <= " +
                       str(max_time + 50) + ";\n")
         if isinstance(cp_solver, CP_MRCPSP_MZN):
             string = ("constraint start[" + str(job) + "] <= " +
                       str(max_time + 50) + ";\n")
         child_instance.add_string(string)
     return list_strings
Example #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
Example #6
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
Example #7
0
 def adding_constraint_from_results_store(
     self, milp_solver: Union[LP_RCPSP, LP_MRCPSP], result_storage: ResultStorage
 ) -> Iterable[Any]:
     constraints_dict = {}
     current_solution, fit = result_storage.get_best_solution_fit()
     # milp_solver.init_model(greedy_start=False, start_solution=current_solution)
     # Starting point :
     start = []
     for j in milp_solver.J:
         start_time_j = current_solution.rcpsp_schedule[j + 1]["start_time"]
         for t in milp_solver.T:
             if start_time_j == t:
                 start += [(milp_solver.x[j][t], 1)]
             else:
                 start += [(milp_solver.x[j][t], 0)]
     milp_solver.model.start = start
     constraints_dict["range_start_time"] = []
     max_time = max(
         [
             current_solution.rcpsp_schedule[x]["end_time"]
             for x in current_solution.rcpsp_schedule
         ]
     )
     last_jobs = [
         x
         for x in current_solution.rcpsp_schedule
         if current_solution.rcpsp_schedule[x]["end_time"] >= max_time - 5
     ]
     nb_jobs = self.problem.n_jobs + 2
     jobs_to_fix = set(
         random.sample(
             current_solution.rcpsp_schedule.keys(),
             int(self.fraction_to_fix * nb_jobs),
         )
     )
     for lj in last_jobs:
         if lj in jobs_to_fix:
             jobs_to_fix.remove(lj)
     for job in jobs_to_fix:
         start_time_j = current_solution.rcpsp_schedule[job]["start_time"]
         min_st = max(start_time_j - self.minus_delta, 0)
         max_st = min(start_time_j + self.plus_delta, max_time)
         for t in milp_solver.T:
             if t < min_st or t > max_st:
                 constraints_dict["range_start_time"].append(
                     milp_solver.model.add_constr(milp_solver.x[job - 1][t] == 0)
                 )
     if milp_solver.lp_solver == LP_RCPSP_Solver.GRB:
         milp_solver.model.solver.update()
     return constraints_dict
Example #8
0
 def adding_constraint_from_results_store(
     self, cp_solver: CP_MS_MRCPSP_MZN, child_instance, result_storage: ResultStorage
 ) -> Iterable[Any]:
     new_fitness = result_storage.get_best_solution_fit()[1]
     if self.last_index_param is not None:
         if new_fitness != self.last_fitness:
             self.status[self.last_index_param]["nb_improvement"] += 1
             self.last_fitness = new_fitness
             self.list_proba[self.last_index_param] *= 1.05
             self.list_proba = self.list_proba / np.sum(self.list_proba)
         else:
             self.list_proba[self.last_index_param] *= 0.95
             self.list_proba = self.list_proba / np.sum(self.list_proba)
     else:
         self.last_fitness = new_fitness
     if random.random() <= 0.95:
         choice = np.random.choice(self.index_np, size=1, p=self.list_proba)[0]
     else:
         max_improvement = max(
             [
                 self.status[x]["nb_improvement"]
                 / max(self.status[x]["nb_usage"], 1)
                 for x in self.status
             ]
         )
         choice = random.choice(
             [
                 x
                 for x in self.status
                 if self.status[x]["nb_improvement"]
                 / max(self.status[x]["nb_usage"], 1)
                 == 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
     )
Example #9
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
Example #10
0
    def solve(self, **kwargs):
        # Initialise the population (here at random)
        population = self._toolbox.population()

        fits = self._toolbox.map(self._toolbox.evaluate, population)
        for fit, ind in zip(fits, population):
            ind.fitness.values = fit

        #  Define the statistics to collect at each generation
        hof = tools.HallOfFame(1)
        stats = tools.Statistics(lambda ind: ind.fitness.values)
        stats.register("avg", np.mean)
        stats.register("std", np.std)
        stats.register("min", np.min)
        stats.register("max", np.max)

        # Run the GA: final population and statistics logbook are created
        pop_vector, logbook = algorithms.eaSimple(
            population=population,
            toolbox=self._toolbox,
            cxpb=self._crossover_rate,
            mutpb=self._mut_rate,
            ngen=int(self._max_evals / self._pop_size),
            stats=stats,
            halloffame=hof,
            verbose=self._deap_verbose,
        )

        best_vector = hof[0]

        s_pure_int = [i for i in best_vector]
        kwargs = {
            self._encoding_variable_name: s_pure_int,
            "problem": self.problem
        }
        problem_sol = self.problem.get_solution_type()(**kwargs)

        result_storage = ResultStorage(
            list_solution_fits=[(problem_sol,
                                 self.aggreg_from_sol(problem_sol))],
            best_solution=problem_sol,
            mode_optim=self.params_objective_function.sense_function,
        )
        return result_storage
Example #11
0
    def adding_constraint_from_results_store(
        self, milp_solver: LP_RCPSP_Solver, result_storage: ResultStorage
    ) -> Iterable[Any]:

        nb_jobs = self.problem.n_jobs + 2
        constraints_dict = {}
        current_solution, fit = result_storage.get_best_solution_fit()

        # Starting point :
        start = []
        for j in milp_solver.J:
            start_time_j = current_solution.rcpsp_schedule[j + 1]["start_time"]
            for t in milp_solver.T:
                if start_time_j == t:
                    start += [(milp_solver.x[j][t], 1)]
                else:
                    start += [(milp_solver.x[j][t], 0)]
        milp_solver.model.start = start

        # Fix start time for a subset of task.
        jobs_to_fix = set(
            random.sample(
                current_solution.rcpsp_schedule.keys(),
                int(self.fraction_fix_start_time * nb_jobs),
            )
        )
        constraints_dict["fix_start_time"] = []
        for job_to_fix in jobs_to_fix:
            for t in milp_solver.T:
                if current_solution.rcpsp_schedule[job_to_fix]["start_time"] == t:
                    constraints_dict["fix_start_time"].append(
                        milp_solver.model.add_constr(
                            milp_solver.x[job_to_fix - 1][t] == 1
                        )
                    )
                else:
                    constraints_dict["fix_start_time"].append(
                        milp_solver.model.add_constr(
                            milp_solver.x[job_to_fix - 1][t] == 0
                        )
                    )
            if milp_solver.lp_solver == LP_RCPSP_Solver.GRB:
                milp_solver.model.solver.update()
        return constraints_dict
Example #12
0
 def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage:
     retrieve_all_solution = parameters_milp.retrieve_all_solution
     nb_solutions_max = parameters_milp.n_solutions_max
     nb_solution = min(nb_solutions_max, self.model.SolCount)
     if not retrieve_all_solution:
         nb_solution = 1
     list_solution_fits = []
     for s in range(nb_solution):
         self.model.params.SolutionNumber = s
         rcpsp_schedule = {}
         modes = {}
         objective = self.model.getAttr("ObjVal")
         for (task, mode, t) in self.x:
             value = self.x[(task, mode, t)].getAttr("Xn")
             if value >= 0.5:
                 rcpsp_schedule[task] = {
                     "start_time": t,
                     "end_time": t
                     + self.rcpsp_model.mode_details[task][mode]["duration"],
                 }
                 modes[task] = mode
         print("Size schedule : ", len(rcpsp_schedule.keys()))
         try:
             modes.pop(1)
             modes.pop(self.rcpsp_model.n_jobs + 2)
             modes_vec = [modes[k] for k in sorted(modes)]
             solution = RCPSPSolution(
                 problem=self.rcpsp_model,
                 rcpsp_schedule=rcpsp_schedule,
                 rcpsp_modes=modes_vec,
                 rcpsp_schedule_feasible=True,
             )
             fit = self.aggreg_from_sol(solution)
             list_solution_fits += [(solution, fit)]
         except:
             pass
     return ResultStorage(
         list_solution_fits=list_solution_fits,
         best_solution=min(list_solution_fits, key=lambda x: x[1])[0],
         mode_optim=self.params_objective_function.sense_function,
     )
Example #13
0
    def get_starting_solution(self) -> ResultStorage:
        multi_skill_rcpsp = self.problem.build_multimode_rcpsp_calendar_representative()
        from skdecide.discrete_optimization.rcpsp.solver.rcpsp_lp_lns_solver import (
            InitialSolutionRCPSP,
        )

        init_solution = InitialSolutionRCPSP(
            problem=multi_skill_rcpsp,
            params_objective_function=self.params_objective_function,
            initial_method=self.initial_method,
        )
        s = init_solution.get_starting_solution()
        list_solution_fits = []
        for s, fit in s.list_solution_fits:
            sol: RCPSPSolution = s
            mode = sol.rcpsp_modes
            modes = {i + 2: mode[i] for i in range(len(mode))}
            modes[self.problem.source_task] = 1
            modes[self.problem.sink_task] = 1
            # ms_rcpsp_solution = MS_RCPSPSolution(problem=self.problem,
            #                                      modes=modes,
            #                                      schedule=sol.rcpsp_schedule,
            #                                      employee_usage=None)
            ms_rcpsp_solution = MS_RCPSPSolution_Variant(
                problem=self.problem,
                priority_list_task=sol.rcpsp_permutation,
                modes_vector=sol.rcpsp_modes,
                priority_worker_per_task=[
                    [w for w in self.problem.employees]
                    for i in range(self.problem.n_jobs_non_dummy)
                ],
            )
            list_solution_fits += [(ms_rcpsp_solution, self.aggreg(ms_rcpsp_solution))]
        return ResultStorage(
            list_solution_fits=list_solution_fits,
            mode_optim=self.params_objective_function.sense_function,
        )
Example #14
0
    def solve(self, **kwargs):
        # Initialise the population (here at random)

        count_evals = 0
        current_encoding_index = 0

        for i in range(len(self.encodings)):
            self.problem.set_fixed_attributes(
                self.encodings[i], self.problem.get_dummy_solution())

        while count_evals < self.max_evals:

            ga_solver = Ga(
                problem=self.problem,
                encoding=self.encodings[current_encoding_index],
                objective_handling=self.objective_handling,
                objectives=self.objectives,
                objective_weights=self.objective_weights,
                mutation=self.mutations[current_encoding_index],
                max_evals=self.sub_evals[current_encoding_index],
            )
            tmp_sol = ga_solver.solve().get_best_solution()
            count_evals += self.sub_evals[current_encoding_index]

            # TODO: implement function below (1 in rcpsp domains, 1 in rcpsp solutions)
            self.problem.set_fixed_attributes(
                self.encodings[current_encoding_index], tmp_sol)

        problem_sol = tmp_sol

        result_storage = ResultStorage(
            list_solution_fits=[(problem_sol,
                                 self.aggreg_from_sol(problem_sol))],
            best_solution=problem_sol,
            mode_optim=self.params_objective_function.sense_function,
        )
        return result_storage
Example #15
0
    def adding_constraint_from_results_store(
        self, milp_solver: LP_Solver_MRSCPSP, result_storage: ResultStorage
    ) -> Iterable[Any]:

        nb_jobs = self.problem.nb_tasks
        constraints_dict = {}
        current_solution, fit = result_storage.get_best_solution_fit()

        start = []
        for j in current_solution.schedule:
            start_time_j = current_solution.schedule[j]["start_time"]
            mode = current_solution.modes[j]
            start += [(milp_solver.start_times_task[j], start_time_j)]
            start += [(milp_solver.modes[j][mode], 1)]
            for m in milp_solver.modes[j]:
                start += [(milp_solver.modes[j][m], 1 if mode == m else 0)]
        milp_solver.model.start = start
        # Fix start time for a subset of task.
        jobs_to_fix = set(
            random.sample(
                current_solution.rcpsp_schedule.keys(),
                int(self.fraction_fix_start_time * nb_jobs),
            )
        )
        constraints_dict["fix_start_time"] = []
        for job_to_fix in jobs_to_fix:
            constraints_dict["fix_start_time"].append(
                milp_solver.model.add_constr(
                    milp_solver.start_times_task[job_to_fix]
                    - current_solution.schedule[job_to_fix]["start_time"]
                    == 0
                )
            )
        if milp_solver.lp_solver == MilpSolverName.GRB:
            milp_solver.model.solver.update()
        return constraints_dict
Example #16
0
 def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage:
     retrieve_all_solution = parameters_milp.retrieve_all_solution
     nb_solutions_max = parameters_milp.n_solutions_max
     nb_solution = min(nb_solutions_max, self.model.num_solutions)
     if not retrieve_all_solution:
         nb_solution = 1
     list_solution_fits = []
     print(nb_solution, " solutions found")
     for s in range(nb_solution):
         rcpsp_schedule = {}
         objective = self.model.objective_values[s]
         for (j, t) in product(self.J, self.T):
             value = self.x[j][t].xi(s)
             if value >= 0.5:
                 rcpsp_schedule[j + 1] = {
                     "start_time": t,
                     "end_time": t
                     + self.rcpsp_model.mode_details[j + 1][1]["duration"],
                 }
         print("Size schedule : ", len(rcpsp_schedule.keys()))
         try:
             solution = RCPSPSolution(
                 problem=self.rcpsp_model,
                 rcpsp_schedule=rcpsp_schedule,
                 rcpsp_schedule_feasible=True,
             )
             fit = self.aggreg_from_sol(solution)
             list_solution_fits += [(solution, fit)]
         except:
             print("Problem =", rcpsp_schedule, len(rcpsp_schedule))
             pass
     return ResultStorage(
         list_solution_fits=list_solution_fits,
         best_solution=min(list_solution_fits, key=lambda x: x[1])[0],
         mode_optim=self.params_objective_function.sense_function,
     )
Example #17
0
    def retrieve_solutions(self,
                           parameters_milp: ParametersMilp) -> ResultStorage:
        retrieve_all_solution = parameters_milp.retrieve_all_solution
        nb_solutions_max = parameters_milp.n_solutions_max
        nb_solution = min(nb_solutions_max, self.model.num_solutions)
        if not retrieve_all_solution:
            nb_solution = 1
        list_solution_fits = []
        print(nb_solution, " solutions found")
        for s in range(nb_solution):
            rcpsp_schedule = {}
            modes = {}
            objective = self.model.objective_values[s]
            results = {}
            employee_usage = {}
            employee_usage_solution = {}
            for task in self.start_times:
                for mode in self.start_times[task]:
                    for t in self.start_times[task][mode]:
                        value = self.start_times[task][mode][t].xi(s)
                        results[(task, mode, t)] = value
                        if value >= 0.5:
                            rcpsp_schedule[task] = {
                                "start_time":
                                int(t),
                                "end_time":
                                int(t + self.rcpsp_model.mode_details[task]
                                    [mode]["duration"]),
                            }
                            modes[task] = mode
            for t in self.employee_usage:
                employee_usage[t] = self.employee_usage[t].xi(s)
                if employee_usage[t] >= 0.5:
                    if t[1] not in employee_usage_solution:
                        employee_usage_solution[t[1]] = {}
                    if t[0] not in employee_usage_solution[t[1]]:
                        employee_usage_solution[t[1]][t[0]] = set()
                    employee_usage_solution[t[1]][t[0]].add(t[4])
                    # (employee, task, mode, time, skill)

            modes = {}
            modes_task = {}
            for t in self.modes:
                for m in self.modes[t]:
                    modes[(t, m)] = self.modes[t][m].xi(s)
                    if modes[(t, m)] >= 0.5:
                        modes_task[t] = m
            durations = {}
            for t in self.durations:
                durations[t] = self.durations[t].xi(s)
            start_time = {}
            for t in self.start_times_task:
                start_time[t] = self.start_times_task[t].xi(s)
            end_time = {}
            for t in self.start_times_task:
                end_time[t] = self.end_times_task[t].xi(s)
            print("Size schedule : ", len(rcpsp_schedule.keys()))
            print(
                "results",
                "(task, mode, time)",
                {x: results[x]
                 for x in results if results[x] == 1.0},
            )
            print(
                "Employee usage : ",
                "(employee, task, mode, time, skill)",
                {
                    x: employee_usage[x]
                    for x in employee_usage if employee_usage[x] == 1.0
                },
            )
            print(
                "task mode : ",
                "(task, mode)",
                {t: modes[t]
                 for t in modes if modes[t] == 1.0},
            )
            print("durations : ", durations)
            print("Start time ", start_time)
            print("End time ", end_time)
            solution = MS_RCPSPSolution(
                problem=self.rcpsp_model,
                modes=modes_task,
                schedule=rcpsp_schedule,
                employee_usage=employee_usage_solution,
            )
            fit = self.aggreg_from_sol(solution)
            list_solution_fits += [(solution, fit)]
        return ResultStorage(
            list_solution_fits=list_solution_fits,
            mode_optim=self.params_objective_function.sense_function,
        )
Example #18
0
    def adding_constraint_from_results_store(
        self, milp_solver: LP_MRCPSP_GUROBI, result_storage: ResultStorage
    ) -> Iterable[Any]:
        current_solution, fit = result_storage.get_best_solution_fit()
        st = milp_solver.start_solution
        if (
            self.problem.evaluate(st)["makespan"]
            < self.problem.evaluate(current_solution)["makespan"]
        ):
            current_solution = st
        start = []
        for j in current_solution.rcpsp_schedule:
            start_time_j = current_solution.rcpsp_schedule[j]["start_time"]
            mode_j = (
                1
                if j == 1 or j == self.problem.n_jobs + 2
                else current_solution.rcpsp_modes[j - 2]
            )
            start += [
                (
                    milp_solver.durations[j],
                    self.problem.mode_details[j][mode_j]["duration"],
                )
            ]
            for k in milp_solver.variable_per_task[j]:
                task, mode, time = k
                if start_time_j == time and mode == mode_j:
                    milp_solver.x[k].start = 1
                    milp_solver.starts[j].start = start_time_j
                else:
                    milp_solver.x[k].start = 0

        # milp_solver.model.start = start
        constraints_dict = {}
        constraints_dict["range_start_time"] = []
        max_time = max(
            [
                current_solution.rcpsp_schedule[x]["end_time"]
                for x in current_solution.rcpsp_schedule
            ]
        )
        last_jobs = [
            x
            for x in current_solution.rcpsp_schedule
            if current_solution.rcpsp_schedule[x]["end_time"] >= max_time - 5
        ]
        nb_jobs = self.problem.n_jobs + 2
        jobs_to_fix = set(
            random.sample(
                current_solution.rcpsp_schedule.keys(),
                int(self.fraction_to_fix * nb_jobs),
            )
        )
        for lj in last_jobs:
            if lj in jobs_to_fix:
                jobs_to_fix.remove(lj)
        for job in jobs_to_fix:
            start_time_j = current_solution.rcpsp_schedule[job]["start_time"]
            min_st = max(start_time_j - self.minus_delta, 0)
            max_st = min(start_time_j + self.plus_delta, max_time)
            for key in milp_solver.variable_per_task[job]:
                t = key[2]
                if t < min_st or t > max_st:
                    constraints_dict["range_start_time"].append(
                        milp_solver.model.addConstr(milp_solver.x[key] == 0)
                    )
        milp_solver.model.update()
        return constraints_dict
Example #19
0
    def adding_constraint_from_results_store(
        self, cp_solver: CP_MS_MRCPSP_MZN, child_instance, result_storage: ResultStorage
    ) -> Iterable[Any]:
        constraints_dict = {}
        r = random.random()
        if r <= 0.2:
            current_solution, fit = result_storage.get_last_best_solution()
        elif r <= 0.4:
            current_solution, fit = result_storage.get_best_solution_fit()
        elif r <= 0.99:
            current_solution, fit = result_storage.get_random_best_solution()
        else:
            current_solution, fit = result_storage.get_random_solution()
            print("Fit", fit)

        current_solution: MS_RCPSPSolution = current_solution
        max_time = max(
            [
                current_solution.schedule[x]["end_time"]
                for x in current_solution.schedule
            ]
        )
        last_jobs = [
            x
            for x in current_solution.schedule
            if current_solution.schedule[x]["end_time"] >= max_time - 20
        ]
        # last_jobs = []
        nb_jobs = self.problem.n_jobs_non_dummy + 2
        jobs_to_fix = set(
            random.sample(
                current_solution.schedule.keys(), int(self.fraction_to_fix * nb_jobs)
            )
        )
        for lj in last_jobs:
            if lj in jobs_to_fix:
                jobs_to_fix.remove(lj)
        list_strings = []
        self.employees_position = sorted(self.problem.employees)
        task_to_fix = set(
            random.sample(
                current_solution.schedule.keys(),
                int(self.fraction_task_to_fix_employee * nb_jobs),
            )
        )
        employee_to_not_fix = set(
            random.sample(
                range(1, len(self.employees_position) + 1),
                min(5, int(1.0 * len(self.employees_position))),
            )
        )
        employee_usage = {
            emp: [
                task
                for task in current_solution.employee_usage
                if emp in current_solution.employee_usage[task]
            ]
            for emp in self.problem.employees
        }
        employee_usage_max_time = {
            emp: max(
                [current_solution.schedule[t]["end_time"] for t in employee_usage[emp]]
            )
            if len(employee_usage[emp]) > 0
            else 0
            for emp in employee_usage
        }
        # employee_usage_time = {emp: sum([current_solution.schedule[t]["end_time"] -
        #                                  current_solution.schedule[t]["start_time"]
        #                                  for t in employee_usage[emp]])
        #                        for emp in employee_usage}
        if False:
            sorted_employee = list(
                sorted(employee_usage, key=lambda x: employee_usage_max_time[x])
            )
            for i in range(int(len(employee_usage) / 4)):
                index = self.employees_position.index(sorted_employee[i]) + 1
                string1 = (
                    "constraint sum(task in Act)(unit_used["
                    + str(index)
                    + ", task] >= "
                    + str(int(len(employee_usage[sorted_employee[i]])))
                    + ";\n"
                )
            for i in range(int(len(employee_usage) / 4)):
                index = (
                    self.employees_position.index(
                        sorted_employee[len(sorted_employee) - 1 - i]
                    )
                    + 1
                )
                string1 = (
                    "constraint sum(task in Act)(unit_used["
                    + str(index)
                    + ", task] <= "
                    + str(
                        int(
                            len(
                                employee_usage[
                                    sorted_employee[len(sorted_employee) - 1 - i]
                                ]
                            )
                        )
                    )
                    + ";\n"
                )

        for i in range(1, len(self.employees_position) + 1):
            # if i in employee_to_not_fix:
            #     continue
            for task in task_to_fix:
                emp = self.employees_position[i - 1]
                if (
                    task in current_solution.employee_usage
                    and emp in current_solution.employee_usage[task]
                    and len(current_solution.employee_usage[task][emp]) > 0
                ):
                    string1 = (
                        "constraint unit_used[" + str(i) + "," + str(task) + "] = 1;\n"
                    )
                else:
                    string1 = (
                        "constraint unit_used[" + str(i) + "," + str(task) + "] = 0;\n"
                    )
                child_instance.add_string(string1)
                list_strings += [string1]
        for job in [self.problem.sink_task]:
            start_time_j = current_solution.schedule[job]["start_time"]
            string1 = (
                "constraint start[" + str(job) + "] <= " + str(start_time_j) + ";\n"
            )
            list_strings += [string1]
            child_instance.add_string(string1)
        for job in jobs_to_fix:
            start_time_j = current_solution.schedule[job]["start_time"]
            min_st = max(start_time_j - self.minus_delta, 0)
            max_st = min(start_time_j + self.plus_delta, max_time)
            string1 = "constraint start[" + str(job) + "] <= " + str(max_st) + ";\n"
            string2 = "constraint start[" + str(job) + "] >= " + str(min_st) + ";\n"
            list_strings += [string1]
            list_strings += [string2]
            child_instance.add_string(string1)
            child_instance.add_string(string2)
        for job in current_solution.schedule.keys():
            if job in jobs_to_fix:
                continue
            # start_time_j = current_solution.schedule[job]["start_time"]
            # min_st = max(start_time_j-100, 0)
            # max_st = min(start_time_j+100, max_time)
            # string1 = "constraint start[" + str(job) + "] <= " + str(max_time) + ";\n"
            # string2 = "constraint start[" + str(job) + "] >= " + str(min_st) + ";\n"
            # list_strings += [string1]
            # list_strings += [string2]
            # child_instance.add_string(string1)
            # child_instance.add_string(string2)
        return list_strings
Example #20
0
    def adding_constraint_from_results_store(
        self,
        cp_solver: Union[CP_RCPSP_MZN, CP_MRCPSP_MZN],
        child_instance,
        result_storage: ResultStorage,
    ) -> Iterable[Any]:
        solution, fit = result_storage.get_best_solution_fit()
        if "satisfy" in solution.__dict__.keys() and solution.satisfy:
            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, solution
        )
        list_strings = []
        max_time = max(
            [solution.rcpsp_schedule[x]["end_time"] for x in solution.rcpsp_schedule]
        )
        tasks = sorted(self.problem_calendar.mode_details.keys())
        for r in constraints:
            for t in constraints[r]:
                index = tasks.index(t)
                s = None
                if isinstance(cp_solver, CP_MRCPSP_MZN):
                    if (
                        constraints[r][t][0] is not None
                        and constraints[r][t][1] is not None
                    ):
                        s = (
                            """constraint start["""
                            + str(index + 1)
                            + """]<="""
                            + str(constraints[r][t][0])
                            + " \/ "
                            "start["
                            ""
                            + str(index + 1)
                            + """]>="""
                            + str(constraints[r][t][1])
                            + """;\n"""
                        )
                    elif (
                        constraints[r][t][0] is None
                        and constraints[r][t][1] is not None
                    ):
                        s = (
                            """constraint start["""
                            + str(index + 1)
                            + """]>="""
                            + str(constraints[r][t][1])
                            + """;\n"""
                        )
                    elif (
                        constraints[r][t][0] is not None
                        and constraints[r][t][1] is None
                    ):
                        s = (
                            """constraint start["""
                            + str(index + 1)
                            + """]<="""
                            + str(constraints[r][t][0])
                            + """;\n"""
                        )
                elif isinstance(cp_solver, CP_RCPSP_MZN):
                    if (
                        constraints[r][t][0] is not None
                        and constraints[r][t][1] is not None
                    ):
                        s = (
                            """constraint s["""
                            + str(index + 1)
                            + """]<="""
                            + str(constraints[r][t][0])
                            + " \/ "
                            "s["
                            ""
                            + str(index + 1)
                            + """]>="""
                            + str(constraints[r][t][1])
                            + """;\n"""
                        )
                    elif (
                        constraints[r][t][0] is None
                        and constraints[r][t][1] is not None
                    ):
                        s = (
                            """constraint s["""
                            + str(index + 1)
                            + """]>="""
                            + str(constraints[r][t][1])
                            + """;\n"""
                        )
                    elif (
                        constraints[r][t][0] is not None
                        and constraints[r][t][1] is None
                    ):
                        s = (
                            """constraint s["""
                            + str(index + 1)
                            + """]<="""
                            + str(constraints[r][t][0])
                            + """;\n"""
                        )
                if s is not None:
                    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]:
                if random.random() < 0.1:
                    continue
                ind = index[0]
                rq = self.problem_calendar.resources[r][ind]

                if isinstance(cp_solver, CP_MRCPSP_MZN):
                    s = (
                        """constraint """
                        + str(rq)
                        + """>=sum( i in Act ) (
                                    bool2int(start[i] <="""
                        + str(ind)
                        + """ /\ """
                        + str(ind)
                        + """< 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(ind)
                        + """ /\ """
                        + str(ind)
                        + """< s[i] + d[i]) * rr["""
                        + str(index_ressource + 1)
                        + """,i]);\n"""
                    )
                child_instance.add_string(s)
                list_strings += [s]

        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:
            res = ResultStorage(
                list_solution_fits=satisfiable, mode_optim=result_storage.mode_optim
            )
            self.other_constraint.adding_constraint_from_results_store(
                cp_solver, child_instance, res
            )
        return ["req"] + list_strings
 def solve(
     self,
     initial_variable: Solution,
     nb_iteration_max: int,
     pickle_result=False,
     pickle_name="tsp",
 ) -> ResultLS:
     objective = self.aggreg_from_dict_values(
         self.evaluator.evaluate(initial_variable))
     cur_variable = initial_variable.copy()
     cur_best_variable = initial_variable.copy()
     cur_objective = objective
     cur_best_objective = objective
     if self.store_solution:
         store = ResultStorage(
             list_solution_fits=[(initial_variable, objective)],
             best_solution=initial_variable.copy(),
             limit_store=True,
             nb_best_store=1000,
         )
     else:
         store = ResultStorage(
             list_solution_fits=[(initial_variable, objective)],
             best_solution=initial_variable.copy(),
             limit_store=True,
             nb_best_store=1,
         )
     self.restart_handler.best_fitness = objective
     iteration = 0
     while iteration < nb_iteration_max:
         local_improvement = False
         global_improvement = False
         local_move_accepted = False
         if self.mode_mutation == ModeMutation.MUTATE:
             nv, move = self.mutator.mutate(cur_variable)
             objective = self.aggreg_from_dict_values(
                 self.evaluator.evaluate(nv))
         elif self.mode_mutation == ModeMutation.MUTATE_AND_EVALUATE:
             nv, move, objective = self.mutator.mutate_and_compute_obj(
                 cur_variable)
             objective = self.aggreg_from_dict_values(objective)
         if self.mode_optim == ModeOptim.MINIMIZATION and objective < cur_objective:
             accept = True
             local_improvement = True
             global_improvement = objective < cur_best_objective
         elif (self.mode_optim == ModeOptim.MAXIMIZATION
               and objective > cur_objective):
             accept = True
             local_improvement = True
             global_improvement = objective > cur_best_objective
         else:
             r = random.random()
             fac = 1 if self.mode_optim == ModeOptim.MAXIMIZATION else -1
             p = math.exp(fac * (objective - cur_objective) /
                          self.temperature_handler.temperature)
             accept = p > r
             local_move_accepted = accept
         if accept:
             cur_objective = objective
             cur_variable = nv
             # print("iter ", iteration)
             # print("acceptance ", objective)
         else:
             cur_variable = move.backtrack_local_move(nv)
             # print(move)
             # print("cur_variable", cur_variable)
         if self.store_solution:
             store.add_solution(nv.copy(), objective)
         if global_improvement:
             print("iter ", iteration)
             # print(cur_variable)
             print("new obj ", objective, " better than ",
                   cur_best_objective)
             cur_best_objective = objective
             cur_best_variable = cur_variable.copy()
             if not self.store_solution:
                 store.add_solution(cur_variable.copy(), objective)
         self.temperature_handler.next_temperature()
         # Update the temperature
         self.restart_handler.update(nv, objective, global_improvement,
                                     local_improvement)
         # Update info in restart handler
         cur_variable, cur_objective = self.restart_handler.restart(
             cur_variable, cur_objective)
         # possibly restart somewhere
         iteration += 1
         if pickle_result and iteration % 20000 == 0:
             pickle.dump(cur_best_variable, open(pickle_name + ".pk", "wb"))
     store.finalize()
     return store
Example #22
0
 def solve(self, **kwargs) -> ResultStorage:
     greedy_choice = kwargs.get("greedy_choice",
                                GreedyChoice.MOST_SUCCESSORS)
     verbose = kwargs.get("verbose", False)
     current_succ = {
         k: {
             "succs": set(self.successors_map[k]["succs"]),
             "nb": self.successors_map[k]["nb"],
         }
         for k in self.successors_map
     }
     current_pred = {
         k: {
             "succs": set(self.predecessors_map[k]["succs"]),
             "nb": self.predecessors_map[k]["nb"],
         }
         for k in self.predecessors_map
     }
     schedule = {}
     current_ressource_available = self.resources.copy()
     current_ressource_non_renewable = {
         nr: self.resources[nr]
         for nr in self.non_renewable
     }
     schedule[1] = {"start_time": 0, "end_time": 0}
     available_activities = {
         n
         for n in current_pred
         if n not in schedule and current_pred[n]["nb"] == 0
     }
     available_activities.update(
         {n
          for n in self.all_activities if n not in current_pred})
     for neighbor in current_pred:
         if 1 in current_pred[neighbor]["succs"]:
             current_pred[neighbor]["succs"].remove(1)
             current_pred[neighbor]["nb"] -= 1
             if current_pred[neighbor]["nb"] == 0:
                 available_activities.add(neighbor)
     if verbose:
         print(current_pred)
     queue = []
     current_time = 0
     perm = []
     while len(schedule) < self.n_jobs + 2:
         if verbose:
             print(len(schedule))
             print("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]
                    for r in current_ressource_available)
         ]
         if verbose:
             print("Ressources : ", current_ressource_available)
         while len(possible_activities) > 0:
             if greedy_choice == GreedyChoice.MOST_SUCCESSORS:
                 next_activity = max(possible_activities,
                                     key=lambda x: current_succ[x]["nb"])
             if greedy_choice == GreedyChoice.SAMPLE_MOST_SUCCESSORS:
                 prob = np.array([
                     current_succ[possible_activities[i]]["nb"]
                     for i in range(len(possible_activities))
                 ])
                 s = np.sum(prob)
                 if s != 0:
                     prob = prob / s
                 else:
                     prob = (1.0 / len(possible_activities) * np.ones(
                         (len(possible_activities))))
                 next_activity = np.random.choice(np.arange(
                     0, len(possible_activities)),
                                                  size=1,
                                                  p=prob)[0]
                 next_activity = possible_activities[next_activity]
             if greedy_choice == GreedyChoice.FASTEST:
                 next_activity = min(
                     possible_activities,
                     key=lambda x: self.mode_details[x][self.modes_dict[x]][
                         "duration"],
                 )
             if greedy_choice == GreedyChoice.TOTALLY_RANDOM:
                 next_activity = random.choice(possible_activities)
             available_activities.remove(next_activity)
             perm += [next_activity - 2]
             schedule[next_activity] = {}
             schedule[next_activity]["start_time"] = current_time
             schedule[next_activity]["end_time"] = (
                 current_time + self.mode_details[next_activity][
                     self.modes_dict[next_activity]]["duration"])
             push(queue, (schedule[next_activity]["end_time"],
                          next_activity, "end_"))
             for r in self.resources:
                 current_ressource_available[r] -= self.mode_details[
                     next_activity][self.modes_dict[next_activity]][r]
                 if r in current_ressource_non_renewable:
                     current_ressource_non_renewable[
                         r] -= self.mode_details[next_activity][
                             self.modes_dict[next_activity]][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]
                        for r in current_ressource_available)
             ]
         current_time, activity, descr = pop(queue)
         for neighbor in current_pred:
             if activity in current_pred[neighbor]["succs"]:
                 current_pred[neighbor]["succs"].remove(activity)
                 current_pred[neighbor]["nb"] -= 1
                 if current_pred[neighbor]["nb"] == 0:
                     available_activities.add(neighbor)
         for r in self.resources:
             if r not in current_ressource_non_renewable:
                 current_ressource_available[r] += self.mode_details[
                     activity][self.modes_dict[activity]][r]
     if verbose:
         print("Final Time ", current_time)
     sol = RCPSPSolution(
         problem=self.rcpsp_model,
         rcpsp_permutation=perm[:-1],
         rcpsp_schedule=schedule,
         rcpsp_modes=[self.modes_dict[i + 2] for i in range(self.n_jobs)],
         rcpsp_schedule_feasible=True,
     )
     result_storage = ResultStorage(
         list_solution_fits=[(sol, self.aggreg_from_sol(sol))],
         best_solution=sol,
         mode_optim=self.params_objective_function.sense_function,
     )
     return result_storage
Example #23
0
    def solve(self, **kwargs) -> ResultStorage:
        greedy_choice = kwargs.get("greedy_choice",
                                   GreedyChoice.MOST_SUCCESSORS)
        verbose = kwargs.get("verbose", False)
        current_succ = {
            k: {
                "succs": set(self.successors_map[k]["succs"]),
                "nb": self.successors_map[k]["nb"],
            }
            for k in self.successors_map
        }
        current_pred = {
            k: {
                "succs": set(self.predecessors_map[k]["succs"]),
                "nb": self.predecessors_map[k]["nb"],
            }
            for k in self.predecessors_map
        }
        schedule = {}
        partial_solution: PartialSolution = kwargs.get("partial_solution",
                                                       None)
        # TODO continue on this... the mode partial solution will probaby override the self.modes_dict at some point.
        if partial_solution is not None:
            if partial_solution.start_times is not None:
                starting_time = 0
                for task in partial_solution.start_times:
                    schedule[task] = {
                        "start_time": partial_solution.start_times[task]
                    }
                    starting_time = max(starting_time,
                                        partial_solution.start_times[task])
            if partial_solution.end_times is not None:
                for task in partial_solution.end_times:
                    if task in schedule:
                        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
        }

        current_ressource_non_renewable = {
            nr: list(self.resources[nr]) + [self.resources[nr][-1]] * 100
            for nr in self.non_renewable
        }

        if 1 not in schedule:
            schedule[1] = {"start_time": 0, "end_time": 0}

        available_activities = {
            n
            for n in current_pred
            if n not in schedule and current_pred[n]["nb"] == 0
        }
        available_activities.update(
            {n
             for n in self.all_activities if n not in current_pred})
        for neighbor in current_pred:
            if 1 in current_pred[neighbor]["succs"]:
                current_pred[neighbor]["succs"].remove(1)
                current_pred[neighbor]["nb"] -= 1
                if current_pred[neighbor]["nb"] == 0:
                    available_activities.add(neighbor)
        if verbose:
            print(current_pred)
        queue = []
        current_time = 0
        perm = []
        while len(schedule) < self.n_jobs + 2:
            if True:
                print(len(schedule), current_time)
                print("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,
                        len(current_ressource_available[r]) - 1)]
                    for r in current_ressource_available for time in range(
                        current_time,
                        current_time +
                        self.mode_details[n][self.modes_dict[n]]["duration"],
                    ))
            ]

            if verbose:
                print("Ressources : ", current_ressource_available)

            while len(possible_activities) > 0:
                if greedy_choice == GreedyChoice.MOST_SUCCESSORS:
                    next_activity = max(possible_activities,
                                        key=lambda x: current_succ[x]["nb"])
                if greedy_choice == GreedyChoice.SAMPLE_MOST_SUCCESSORS:
                    prob = np.array([
                        current_succ[possible_activities[i]]["nb"]
                        for i in range(len(possible_activities))
                    ])
                    s = np.sum(prob)
                    if s != 0:
                        prob = prob / s
                    else:
                        prob = (1.0 / len(possible_activities) * np.ones(
                            (len(possible_activities))))
                    next_activity = np.random.choice(np.arange(
                        0, len(possible_activities)),
                                                     size=1,
                                                     p=prob)[0]
                    next_activity = possible_activities[next_activity]
                if greedy_choice == GreedyChoice.FASTEST:
                    next_activity = min(
                        possible_activities,
                        key=lambda x: self.mode_details[x][self.modes_dict[x]][
                            "duration"],
                    )
                if greedy_choice == GreedyChoice.TOTALLY_RANDOM:
                    next_activity = random.choice(possible_activities)
                available_activities.remove(next_activity)
                perm += [next_activity - 2]
                schedule[next_activity] = {}
                schedule[next_activity]["start_time"] = current_time
                schedule[next_activity]["end_time"] = (
                    current_time + self.mode_details[next_activity][
                        self.modes_dict[next_activity]]["duration"])
                push(queue, (schedule[next_activity]["end_time"],
                             next_activity, "end_"))
                mode = self.modes_dict[next_activity]
                duration = self.mode_details[next_activity][mode]["duration"]
                for r in self.resources:
                    for t in range(current_time, current_time + duration):
                        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]

                possible_activities = [
                    n for n in available_activities
                    if all(self.mode_details[n][self.modes_dict[n]][r] <=
                           current_ressource_available[r][time]
                           for r in current_ressource_available
                           for time in range(
                               current_time,
                               current_time + self.mode_details[n][
                                   self.modes_dict[n]]["duration"] + 1,
                           ))
                ]
            if len(queue) > 0:
                current_time, activity, descr = pop(queue)
                for neighbor in current_pred:
                    if activity in current_pred[neighbor]["succs"]:
                        current_pred[neighbor]["succs"].remove(activity)
                        current_pred[neighbor]["nb"] -= 1
                        if current_pred[neighbor]["nb"] == 0:
                            available_activities.add(neighbor)
            else:
                current_time += 1
        if verbose:
            print("Final Time ", current_time)
        sol = RCPSPSolution(
            problem=self.rcpsp_model,
            rcpsp_permutation=perm[:-1],
            rcpsp_schedule=schedule,
            rcpsp_modes=[self.modes_dict[i + 2] for i in range(self.n_jobs)],
            rcpsp_schedule_feasible=True,
        )
        result_storage = ResultStorage(
            list_solution_fits=[(sol, self.aggreg_from_sol(sol))],
            best_solution=sol,
            mode_optim=self.params_objective_function.sense_function,
        )
        return result_storage
Example #24
0
 def solve(self,
           parameters_cp: ParametersCP,
           nb_iteration_lns: int,
           nb_iteration_no_improvement: Optional[int] = None,
           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)
         store_with_all = ResultStorage(list(store_lns.list_solution_fits),
                                        mode_optim=store_lns.mode_optim)
         init_solution, objective = store_lns.get_best_solution_fit()
         best_solution = init_solution.copy()
         satisfy = self.problem_calendar.satisfy(init_solution)
         best_objective = objective
     else:
         best_objective = (float("inf") if sense == ModeOptim.MINIMIZATION
                           else -float("inf"))
         best_solution = None
         constraint_iterable = {"empty": []}
         store_lns = None
         store_with_all = None
     constraint_to_keep = set()
     for iteration in range(nb_iteration_lns):
         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:
                     child.add_string(c)
                 constraint_iterable = (
                     self.constraint_handler.
                     adding_constraint_from_results_store(
                         cp_solver=self.cp_solver,
                         child_instance=child,
                         result_storage=store_lns,
                     ))
                 if constraint_iterable[0] == "req":
                     constraint_to_keep.update(
                         set([c for c in constraint_iterable[1:]]))
             if True:
                 if iteration == 0:
                     result = child.solve(
                         timeout=timedelta(
                             seconds=parameters_cp.TimeLimit_iter0),
                         intermediate_solutions=parameters_cp.
                         intermediate_solution,
                     )
                 else:
                     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)
                 if len(result_store.list_solution_fits) > 0:
                     bsol, fit = result_store.get_best_solution_fit()
                     result_store = self.post_process_solution.build_other_solution(
                         result_store)
                     bsol, fit = result_store.get_best_solution_fit()
                     if sense == ModeOptim.MAXIMIZATION and fit >= best_objective:
                         if fit > best_objective:
                             current_nb_iteration_no_improvement = 0
                         else:
                             current_nb_iteration_no_improvement += 1
                         best_solution = bsol
                         best_objective = fit
                     elif sense == ModeOptim.MAXIMIZATION:
                         current_nb_iteration_no_improvement += 1
                     elif sense == ModeOptim.MINIMIZATION and fit <= best_objective:
                         if fit < best_objective:
                             current_nb_iteration_no_improvement = 0
                         else:
                             current_nb_iteration_no_improvement += 1
                         best_solution = bsol
                         best_objective = fit
                     elif sense == ModeOptim.MINIMIZATION:
                         current_nb_iteration_no_improvement += 1
                     if skip_first_iteration and iteration == 0:
                         store_lns = result_store
                         store_with_all = ResultStorage(
                             list_solution_fits=list(
                                 store_lns.list_solution_fits),
                             mode_optim=store_lns.mode_optim,
                         )
                     store_lns = result_store
                     for s, f in store_lns.list_solution_fits:
                         store_with_all.list_solution_fits += [(s, f)]
                     for s, f in store_with_all.list_solution_fits:
                         if s.satisfy:
                             store_lns.list_solution_fits += [(s, f)]
                 else:
                     current_nb_iteration_no_improvement += 1
                 if (skip_first_iteration
                         and result.status == Status.OPTIMAL_SOLUTION
                         and iteration == 0 and best_solution.satisfy):
                     break
             else:
                 current_nb_iteration_no_improvement += 1
             if time.time() - deb_time > max_time_seconds:
                 break
             if current_nb_iteration_no_improvement > nb_iteration_no_improvement:
                 break
     return store_with_all
Example #25
0
    def adding_constraint_from_results_store(
        self,
        cp_solver: Union[CP_MS_MRCPSP_MZN],
        child_instance,
        result_storage: ResultStorage,
    ) -> Iterable[Any]:
        solution, fit = result_storage.get_best_solution_fit()
        solution: MS_RCPSPSolution = solution
        if "satisfy" in solution.__dict__.keys() and solution.satisfy:
            return self.other_constraint.adding_constraint_from_results_store(
                cp_solver,
                child_instance,
                ResultStorage(
                    list_solution_fits=[(solution, fit)],
                    mode_optim=result_storage.mode_optim,
                ),
            )
        ressource_breaks, constraints, constraints_employee = get_ressource_breaks(
            self.problem_calendar, solution)
        list_strings = []
        max_time = max(
            [solution.schedule[x]["end_time"] for x in solution.schedule])
        tasks = sorted(self.problem_calendar.mode_details.keys())
        for r in constraints:
            for t in constraints[r]:
                index = tasks.index(t)
                s = None
                if isinstance(cp_solver, CP_MS_MRCPSP_MZN):
                    if (constraints[r][t][0] is not None
                            and constraints[r][t][1] is not None):
                        s = ("""constraint start[""" + str(index + 1) +
                             """]<=""" + str(constraints[r][t][0]) + " \/ "
                             "start["
                             "" + str(index + 1) + """]>=""" +
                             str(constraints[r][t][1]) + """;\n""")
                    elif (constraints[r][t][0] is None
                          and constraints[r][t][1] is not None):
                        s = ("""constraint start[""" + str(index + 1) +
                             """]>=""" + str(constraints[r][t][1]) + """;\n""")
                    elif (constraints[r][t][0] is not None
                          and constraints[r][t][1] is None):
                        s = ("""constraint start[""" + str(index + 1) +
                             """]<=""" + str(constraints[r][t][0]) + """;\n""")
                if s is not None:
                    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<max_time:
        #             if isinstance(cp_solver, CP_MRCPSP_MZN):
        #                 s = """constraint """ + str(rq) + """>=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:
            for index in ressource_breaks[r]:
                if random.random() < 0.6:
                    continue
                ind = index[0]
                if r in self.problem_calendar.resources_availability:
                    index_ressource = cp_solver.resources_index.index(r)
                    rq = self.problem_calendar.resources_availability[r][ind]
                    # if random.random() <= 0.3:
                    #    continue
                    s = ("""constraint """ + str(rq) + """>=sum( i in Act ) (
                                        bool2int(start[i] <=""" + str(ind) +
                         """ /\ """ + str(ind) +
                         """< start[i] + adur[i]) * arreq[""" +
                         str(index_ressource + 1) + """,i]);\n""")
                    child_instance.add_string(s)
                    list_strings += [s]

                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])
                    # if random.random() <= 0.3:
                    #    continue
                    s = ("""constraint """ + str(rq) + """>=sum( i in Act ) (
                                        bool2int(start[i] <=""" + str(ind) +
                         """ /\ """ + str(ind) +
                         """< start[i] + adur[i]) * unit_used[""" +
                         str(index_ressource + 1) + """,i]);\n""")
                    child_instance.add_string(s)
                    list_strings += [s]

        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:
            res = ResultStorage(list_solution_fits=satisfiable,
                                mode_optim=result_storage.mode_optim)
            self.other_constraint.adding_constraint_from_results_store(
                cp_solver, child_instance, res)
        return ["req"] + list_strings
Example #26
0
    def compute_schedule_from_priority_list(self, permutation_jobs: List[int],
                                            modes_dict: Dict[int, int]):
        current_pred = {
            k: {
                "succs": set(self.immediate_predecessors[k]),
                "nb": len(self.immediate_predecessors[k]),
            }
            for k in self.immediate_predecessors
        }
        schedule = {}
        current_ressource_available = self.resources.copy()
        current_ressource_non_renewable = {
            nr: self.resources[nr]
            for nr in self.non_renewable
        }
        schedule[1] = {"start_time": 0, "end_time": 0}
        available_activities = {
            n
            for n in current_pred
            if n not in schedule and current_pred[n]["nb"] == 0
        }
        available_activities.update(
            {n
             for n in self.all_activities if n not in current_pred})
        for neighbor in self.immediate_successors[1]:
            if 1 in current_pred[neighbor]["succs"]:
                current_pred[neighbor]["succs"].remove(1)
                current_pred[neighbor]["nb"] -= 1
                if current_pred[neighbor]["nb"] == 0:
                    available_activities.add(neighbor)
        permutation_jobs.remove(1)
        queue = []
        current_time = 0
        perm = []
        while len(schedule) < self.n_jobs + 2:
            possible_activities = [
                n for n in available_activities
                if all(self.mode_details[n][modes_dict[n]][r] <=
                       current_ressource_available[r]
                       for r in current_ressource_available)
            ]
            while len(possible_activities) > 0:
                next_activity = min(possible_activities,
                                    key=lambda x: permutation_jobs.index(x))
                available_activities.remove(next_activity)
                perm += [next_activity - 2]
                schedule[next_activity] = {}
                schedule[next_activity]["start_time"] = current_time
                schedule[next_activity]["end_time"] = (
                    current_time + self.mode_details[next_activity][
                        modes_dict[next_activity]]["duration"])
                permutation_jobs.remove(next_activity)
                push(queue, (schedule[next_activity]["end_time"],
                             next_activity, "end_"))
                for r in self.resources:
                    current_ressource_available[r] -= self.mode_details[
                        next_activity][modes_dict[next_activity]][r]
                    if r in current_ressource_non_renewable:
                        current_ressource_non_renewable[
                            r] -= self.mode_details[next_activity][
                                modes_dict[next_activity]][r]
                possible_activities = [
                    n for n in available_activities
                    if all(self.mode_details[n][modes_dict[n]][r] <=
                           current_ressource_available[r]
                           for r in current_ressource_available)
                ]

            current_time, activity, descr = pop(queue)
            for neighbor in self.immediate_successors[activity]:
                if activity in current_pred[neighbor]["succs"]:
                    current_pred[neighbor]["succs"].remove(activity)
                    current_pred[neighbor]["nb"] -= 1
                    if current_pred[neighbor]["nb"] == 0:
                        available_activities.add(neighbor)
            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]

        sol = RCPSPSolution(
            problem=self.rcpsp_model,
            rcpsp_permutation=perm[:-1],
            rcpsp_schedule=schedule,
            rcpsp_modes=[modes_dict[i + 1] for i in range(self.n_jobs)],
            rcpsp_schedule_feasible=True,
        )
        result_storage = ResultStorage(
            list_solution_fits=[(sol, self.aggreg_from_sol(sol))],
            best_solution=sol,
            mode_optim=self.params_objective_function.sense_function,
        )
        return result_storage
Example #27
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
Example #28
0
    def solve(self, **kwargs):

        #  Define the statistics to collect at each generation
        stats = tools.Statistics(lambda ind: ind.fitness.values)
        stats.register("avg", np.mean, axis=0)
        stats.register("std", np.std, axis=0)
        stats.register("min", np.min, axis=0)
        stats.register("max", np.max, axis=0)

        logbook = tools.Logbook()
        logbook.header = "gen", "evals", "std", "min", "avg", "max"

        # Initialise the population (here at random)
        pop = self._toolbox.population()

        invalid_ind = [ind for ind in pop if not ind.fitness.valid]
        fitnesses = self._toolbox.map(self._toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # Compile statistics about the population
        record = stats.compile(pop)
        logbook.record(gen=0, evals=len(invalid_ind), **record)
        print(logbook.stream)

        # Begin the generational process
        ngen = int(self._max_evals / self._pop_size)
        print("ngen:", ngen)
        for gen in range(1, ngen):
            offspring = algorithms.varAnd(
                pop, self._toolbox, self._crossover_rate, self._mut_rate
            )

            # Evaluate the individuals with an invalid fitness
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = self._toolbox.map(self._toolbox.evaluate, invalid_ind)
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit

            # Select the next generation population from parents and offspring
            pop = self._toolbox.select(pop + offspring, self._pop_size)

            # Compile statistics about the new population
            record = stats.compile(pop)
            logbook.record(gen=gen, evals=len(invalid_ind), **record)
            print(logbook.stream)

        sols = []
        for s in pop:
            s_pure_int = [i for i in s]
            kwargs = {self._encoding_variable_name: s_pure_int, "problem": self.problem}
            problem_sol = self.problem.get_solution_type()(**kwargs)
            fits = self.evaluate_sol(problem_sol)
            # fits = TupleFitness(np.array(s.fitness.values), len(s.fitness.values))
            sols.append((problem_sol, fits))
        rs = ResultStorage(
            list_solution_fits=sols,
            best_solution=None,
            mode_optim=self.params_objective_function.sense_function,
        )
        return rs