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 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 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: 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 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_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 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 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 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. * 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