def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: bs = result_storage.get_best_solution() colors = bs.colors set_colors = sorted(set(colors)) nb_colors = len(set(set_colors)) new_color_dict = {set_colors[i]: i for i in range(nb_colors)} new_solution = ColoringSolution( problem=self.problem, colors=[new_color_dict[colors[i]] for i in range(len(colors))]) fit = self.aggreg_from_sol(new_solution) result_storage.add_solution(new_solution, fit) return result_storage
def adding_constraint_from_results_store( self, milp_solver: ColoringLP, result_storage: ResultStorage) -> Iterable[Any]: subpart_color = set( random.sample( milp_solver.nodes_name, int(self.fraction_to_fix * milp_solver.number_of_nodes))) dict_color_fixed = {} dict_color_start = {} current_solution = result_storage.get_best_solution_fit()[0] max_color = max(current_solution.colors) for n in milp_solver.nodes_name: dict_color_start[n] = current_solution.colors[ milp_solver.index_nodes_name[n]] if n in subpart_color and dict_color_start[n] <= max_color - 1: dict_color_fixed[n] = dict_color_start[n] colors_var = milp_solver.variable_decision["colors_var"] lns_constraint = {} for key in colors_var: n, c = key if c == dict_color_start[n]: colors_var[n, c].start = 1 colors_var[n, c].varhintval = 1 else: colors_var[n, c].start = 0 colors_var[n, c].varhintval = 0 if n in dict_color_fixed: if c == dict_color_fixed[n]: lns_constraint[(n, c)] = milp_solver.model.addConstr( colors_var[key] == 1, name=str((n, c))) else: lns_constraint[(n, c)] = milp_solver.model.addConstr( colors_var[key] == 0, name=str((n, c))) return lns_constraint
def get_starting_solution(self) -> ResultStorage: multi_skill_rcpsp = self.problem.build_multimode_rcpsp_calendar_representative() from skdecide.builders.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)
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 ]) delta_t = max_time / self.nb_cut_part task_of_interest = [ t for t in current_solution.rcpsp_schedule if delta_t * self.current_sub_part <= current_solution.rcpsp_schedule[t]["start_time"] <= delta_t * (self.current_sub_part + 1) ] 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) for t in task_of_interest: if t in jobs_to_fix: jobs_to_fix.remove(t) 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) self.current_sub_part = (self.current_sub_part + 1) % self.nb_cut_part return list_strings
def retrieve_solutions(self, result, parameters_cp: ParametersCP) -> ResultStorage: intermediate_solutions = parameters_cp.intermediate_solution l_items = [] objectives = [] if intermediate_solutions: for i in range(len(result)): l_items += [result[i, "list_items"]] objectives += [result[i, "objective"]] else: l_items += [result["list_items"]] objectives += [result["objective"]] list_solutions_fit = [] for items, objective in zip(l_items, objectives): taken = [0] * self.knapsack_model.nb_items weight = 0 value = 0 for i in range(len(items)): if items[i] != 0: taken[self.knapsack_model.list_items[items[i] - 1].index] = 1 weight += self.knapsack_model.list_items[items[i] - 1].weight value += self.knapsack_model.list_items[items[i] - 1].value sol = KnapsackSolution(problem=self.knapsack_model, value=value, weight=weight, list_taken=taken) fit = self.aggreg_sol(sol) list_solutions_fit += [(sol, fit)] return ResultStorage( list_solution_fits=list_solutions_fit, best_solution=None, mode_optim=self.params_objective_function.sense_function)
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)
def build_other_solution(self, result_storage: ResultStorage) -> ResultStorage: new_solution = sgs_variant(solution=result_storage.get_best_solution(), problem=self.problem, predecessors_dict=self.immediate_predecessors) fit = self.aggreg_from_sol(new_solution) result_storage.add_solution(new_solution, fit) import random for s in random.sample(result_storage.list_solution_fits, min(len(result_storage.list_solution_fits), 50)): new_solution = sgs_variant(solution=s[0], problem=self.problem, predecessors_dict=self.immediate_predecessors) fit = self.aggreg_from_sol(new_solution) result_storage.add_solution(new_solution, fit) return result_storage
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)
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)
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
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
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
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) # print('len(rs): ', len(rs.list_solution_fits)) pareto_store = result_storage_to_pareto_front(result_storage=rs, problem=None) # print('len(pareto_store): ', len(pareto_store.list_solution_fits)) # print('hhhh: ', [x[1].vector_fitness for x in pareto_store.list_solution_fits]) return pareto_store
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]] # print("Objective : ", result[i, "objective"]) else: object_result += [result] for res in object_result: modes = [] for j in range(len(res.mode_chosen)): if (self.modeindex_map[j + 1]['task'] != 1) and (self.modeindex_map[j + 1]['task'] != self.rcpsp_model.n_jobs + 2): modes.append(self.modeindex_map[res.mode_chosen[j]] ['original_mode_index']) elif (self.modeindex_map[j + 1]['task'] == 1) or (self.modeindex_map[j + 1]['task'] == self.rcpsp_model.n_jobs + 2): modes.append(1) rcpsp_schedule = {} start_times = res.dict["start"] for i in range(len(start_times)): rcpsp_schedule[i + 1] = { 'start_time': start_times[i], 'end_time': start_times[i] + self.rcpsp_model.mode_details[i + 1][modes[i]]['duration'] } sol = RCPSPSolution(problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_modes=modes[1:-1], rcpsp_schedule_feasible=True) objective = self.aggreg_from_dict_values( self.rcpsp_model.evaluate(sol)) if objective > best_makespan: best_makespan = objective best_solution = sol.copy() list_solutions_fit += [(sol, objective)] result_storage = ResultStorage( list_solution_fits=list_solutions_fit, best_solution=best_solution, mode_optim=self.params_objective_function.sense_function, limit_store=False) return result_storage
def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage: solution = [0] * self.number_of_nodes for key in self.variable_decision["colors_var"]: value = self.variable_decision["colors_var"][key].x if value >= 0.5: node = key[0] color = key[1] solution[self.index_nodes_name[node]] = color color_solution = ColoringSolution(self.coloring_problem, solution) fit = self.aggreg_from_sol(color_solution) return ResultStorage(list_solution_fits=[(color_solution, fit)], best_solution=color_solution, mode_optim=self.sense_optim)
def get_starting_solution(self) -> ResultStorage: if self.initial_method == InitialColoringMethod.DUMMY: sol = self.problem.get_dummy_solution() fit = self.aggreg_sol(sol) return ResultStorage( list_solution_fits=[(sol, fit)], best_solution=sol, mode_optim=self.params_objective_function.sense_function) else: solver = GreedyColoring( color_problem=self.problem, params_objective_function=self.params_objective_function) return solver.solve()
def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage: solution = [0] * self.facility_problem.customer_count for key in self.variable_decision["x"]: try: value = self.variable_decision["x"][key].x except: value = self.variable_decision["x"][key] ## To deal with already fixed variable. if value >= 0.5: f = key[0] c = key[1] solution[c] = f facility_solution = FacilitySolution(self.facility_problem, solution) result_store = ResultStorage(list_solution_fits=[(facility_solution, self.aggreg_sol(facility_solution))], best_solution=facility_solution, mode_optim=self.params_objective_function.sense_function) return result_store
def get_starting_solution(self) -> ResultStorage: if self.initial_method == InitialMethodRCPSP.PILE: print("Compute greedy") greedy_solver = PileSolverRCPSP(self.problem) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) if self.initial_method == InitialMethodRCPSP.PILE_CALENDAR: print("Compute greedy") greedy_solver = PileSolverRCPSP_Calendar(self.problem) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) elif self.initial_method == InitialMethodRCPSP.DUMMY: print("Compute dummy") solution = self.problem.get_dummy_solution() fit = self.aggreg(solution) store_solution = ResultStorage(list_solution_fits=[(solution, fit)], best_solution=solution, 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) print(mutations) list_mutation = [mutate[0].build(self.problem, dummy, **mutate[1]) for mutate in mutations if mutate[0] == PermutationMutationRCPSP] # and mutate[1]["other_mutation"] == TwoOptMutation] mixed_mutation = BasicPortfolioMutation(list_mutation, np.ones((len(list_mutation)))) res = RestartHandlerLimit(500, cur_solution=dummy, cur_objective=self.problem.evaluate(dummy)) sa = SimulatedAnnealing(evaluator=self.problem, mutator=mixed_mutation, restart_handler=res, temperature_handler=TemperatureSchedulingFactor(2, res, 0.9999), mode_mutation=ModeMutation.MUTATE, params_objective_function=self.params_objective_function, store_solution=True, nb_solutions=10000) store_solution = sa.solve(dummy, nb_iteration_max=10000, pickle_result=False) return store_solution
def retrieve_solutions( self, result, parameters_cp: ParametersCP = ParametersCP.default() ) -> ResultStorage: intermediate_solutions = parameters_cp.intermediate_solution best_solution = None best_makespan = -float("inf") list_solutions_fit = [] starts = [] if intermediate_solutions: for i in range(len(result)): if isinstance(result[i], RCPSPSolCP): starts += [result[i].dict["s"]] else: starts += [result[i, "s"]] else: if isinstance(result, RCPSPSolCP): starts += [result.dict["s"]] else: starts = [result["s"]] for start_times in starts: rcpsp_schedule = {} for k in range(len(start_times)): rcpsp_schedule[k + 1] = { 'start_time': start_times[k], 'end_time': start_times[k] + self.rcpsp_model.mode_details[k + 1][1]['duration'] } sol = RCPSPSolution(problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_schedule_feasible=True) objective = self.aggreg_from_dict_values( self.rcpsp_model.evaluate(sol)) if objective > best_makespan: best_makespan = objective best_solution = sol.copy() list_solutions_fit += [(sol, objective)] result_storage = ResultStorage( list_solution_fits=list_solutions_fit, best_solution=best_solution, mode_optim=self.params_objective_function.sense_function, limit_store=False) return result_storage
def 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
def solve(self, **kwargs): strategy: NXGreedyColoringMethod = kwargs.get( "strategy", NXGreedyColoringMethod.best) print(strategy) verbose: bool = kwargs.get("verbose", False) strategy_name = strategy.name if strategy_name == "best": strategies_to_test = strategies else: strategies_to_test = [strategy_name] best_solution = None best_nb_color = float('inf') for strategy in strategies_to_test: try: colors = nx.algorithms.coloring.greedy_color(self.nx_graph, strategy=strategy, interchange=False) sorted_nodes = sorted(list(colors.keys())) number_colors = len(set(list(colors.values()))) solution = [colors[i] for i in sorted_nodes] if verbose: print(strategy, " : number colors : ", number_colors) if number_colors < best_nb_color: best_solution = solution best_nb_color = number_colors except Exception as e: print("Failed strategy : ", strategy, e) pass if verbose: print("best : ", best_nb_color) solution = ColoringSolution(self.color_problem, colors=best_solution, nb_color=None) solution = solution.to_reformated_solution( ) # TODO : make this OPTIONAL fit = self.aggreg_sol(solution) if verbose: print("Solution found : ", solution) return ResultStorage( list_solution_fits=[(solution, fit)], best_solution=solution, mode_optim=self.params_objective_function.sense_function)
def adding_constraint_from_results_store( self, cp_solver: CPSolver, child_instance, result_storage: ResultStorage) -> Iterable[Any]: range_node = range(1, self.problem.number_of_nodes + 1) current_solution = result_storage.get_best_solution() subpart_color = set( random.sample( range_node, int(self.fraction_to_fix * self.problem.number_of_nodes))) dict_color = { i + 1: current_solution.colors[i] + 1 for i in range(self.problem.number_of_nodes) } current_nb_color = max(dict_color.values()) for i in range_node: if i in subpart_color and dict_color[i] < current_nb_color: child_instance.add_string("constraint color_graph[" + str(i) + "] == " + str(dict_color[i]) + ";\n") child_instance.add_string("constraint color_graph[" + str(i) + "] <= " + str(current_nb_color) + ";\n")
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, 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
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)
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() 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) cur_best_variable = initial_variable.copy() cur_objective = objective cur_best_objective = objective self.restart_handler.best_fitness = objective iteration = 0 while iteration < nb_iteration_max: accept = False local_improvement = False global_improvement = False if self.mode_mutation == ModeMutation.MUTATE: nv, move = self.mutator.mutate(cur_variable) objective = self.aggreg_from_solution(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 if accept: cur_objective = objective cur_variable = nv else: cur_variable = move.backtrack_local_move(nv) if self.store_solution: store.add_solution(nv, objective) if global_improvement: print("iter ", iteration) 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, objective) # 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
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) print("Satisfy ", satisfy) 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): print('Starting iteration n°', iteration, " current objective ", best_objective) try: print( "Best feasible solution ", max([ f for s, f in store_with_all.list_solution_fits if "satisfy" in s.__dict__.keys() and s.satisfy ])) except: print("No Feasible solution yet") with self.cp_solver.instance.branch() as child: if iteration == 0 and not skip_first_iteration or iteration >= 1: for c in constraint_to_keep: 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) print("iteration n°", iteration, "Solved !!!") print(result.status) if len(result_store.list_solution_fits) > 0: print("Solved !!!") bsol, fit = result_store.get_best_solution_fit() print("Fitness = ", fit) print("Post Process..") print("Satisfy best current sol : ") print(self.problem_calendar.satisfy(bsol)) result_store = self.post_process_solution.build_other_solution( result_store) bsol, fit = result_store.get_best_solution_fit() print("After postpro = ", fit) if sense == ModeOptim.MAXIMIZATION and fit >= best_objective: if fit > best_objective: current_nb_iteration_no_improvement = 0 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)] print("Satisfy : ", self.problem_calendar.satisfy(best_solution)) else: current_nb_iteration_no_improvement += 1 if skip_first_iteration and result.status == Status.OPTIMAL_SOLUTION and iteration == 0\ and best_solution.satisfy: print("Finish LNS because found optimal solution") break else: #except Exception as e: current_nb_iteration_no_improvement += 1 print("Failed ! reason : ", e) if time.time() - deb_time > max_time_seconds: print("Finish LNS with time limit reached") break print(current_nb_iteration_no_improvement, "/", nb_iteration_no_improvement) if current_nb_iteration_no_improvement > nb_iteration_no_improvement: print("Finish LNS with maximum no improvement iteration ") break return store_with_all
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): print("adding the other constraints !") 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] # print(s) # print("Res", r) # print("Time", index) if r in self.problem_calendar.employees: index_ressource = cp_solver.employees_position.index(r) rq = int(self.problem_calendar.employees[r]. calendar_employee[ind]) # 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] # print(s) # print("Res", r) # print("Time", index) satisfiable = [(s, f) for s, f in result_storage.list_solution_fits if "satisfy" in s.__dict__.keys() 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 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) ] # print(current_ressource_available, self.rcpsp_model.non_renewable_resources) current_time, activity, descr = pop(queue) for neighbor in self.immediate_successors[activity]: if activity in current_pred[neighbor]["succs"]: 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] # print("Final Time ", current_time) 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
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. / 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