示例#1
0
    def init_model(self, **args):
        no_ressource = len(self.rcpsp_model.resources_list) == 0
        # no_ressource = False
        model_type = ("multi-calendar"
                      if not no_ressource else "multi-calendar-no-ressource")
        # model_type = "multi-calendar"
        model = Model(files_mzn[model_type])
        custom_output_type = args.get("output_type", False)
        exact_skills_need = args.get("exact_skills_need", True)
        if custom_output_type:
            model.output_type = MS_RCPSPSolCP
            self.custom_output_type = True

        solver = Solver.lookup(map_cp_solver_name[self.cp_solver_name])
        resources_list = sorted(
            list(self.rcpsp_model.resources_availability.keys()))
        self.resources_index = resources_list
        instance = Instance(solver, model)
        n_res = len(resources_list)
        keys = []
        if not no_ressource:
            instance["n_res"] = n_res
            keys += ["n_res"]
        if model_type == "multi-calendar":
            instance["exact_skills_need"] = exact_skills_need
            keys += ["exact_skills_need"]
            instance["add_calendar_constraint_unit"] = args.get(
                "add_calendar_constraint_unit", False)
            keys += ["add_calendar_constraint_unit"]
        instance["exact_skills_need"] = exact_skills_need
        instance["one_ressource_per_task"] = self.one_ressource_per_task
        keys += ["one_ressource_per_task"]

        n_tasks = self.rcpsp_model.n_jobs_non_dummy + 2
        instance["n_tasks"] = n_tasks
        keys += ["n_tasks"]
        sorted_tasks = sorted(self.rcpsp_model.mode_details.keys())
        n_opt = sum([
            len(list(self.rcpsp_model.mode_details[key].keys()))
            for key in sorted_tasks
        ])
        instance["n_opt"] = n_opt
        keys += ["n_opt"]
        modes = []
        dur = []
        counter = 0
        self.modeindex_map = {}
        for act in sorted_tasks:
            tmp = list(sorted(self.rcpsp_model.mode_details[act].keys()))
            # tmp = [counter + x for x in tmp]
            for i in range(len(tmp)):
                original_mode_index = tmp[i]
                mod_index = counter + tmp[i]
                tmp[i] = mod_index
                self.modeindex_map[mod_index] = {
                    "task": act,
                    "original_mode_index": original_mode_index,
                }
            modes.append(set(tmp))
            counter = tmp[-1]
            dur = dur + [
                self.rcpsp_model.mode_details[act][key]["duration"]
                for key in sorted(self.rcpsp_model.mode_details[act].keys())
            ]

        instance["modes"] = modes
        keys += ["modes"]
        instance["dur"] = dur
        keys += ["dur"]

        if not no_ressource:
            rreq = []
            index = 0
            for res in resources_list:
                rreq.append([])
                for task in sorted_tasks:
                    for mod in sorted(
                            self.rcpsp_model.mode_details[task].keys()):
                        rreq[index].append(
                            int(self.rcpsp_model.mode_details[task][mod][res]))
                index += 1

        skills_set = sorted(list(self.rcpsp_model.skills_set))
        nb_units = len(self.rcpsp_model.employees)
        skill_required = []
        index = 0
        for skill in skills_set:
            skill_required.append([])
            for task in sorted_tasks:
                for mod in sorted(self.rcpsp_model.mode_details[task].keys()):
                    skill_required[index].append(
                        int(self.rcpsp_model.mode_details[task][mod].get(
                            skill, 0)))
            index += 1
        if True:
            if no_ressource:
                instance["max_time"] = self.rcpsp_model.horizon
                keys += ["max_time"]
            else:
                one_ressource = list(
                    self.rcpsp_model.resources_availability.keys())[0]
                instance["max_time"] = min(
                    len(self.rcpsp_model.resources_availability[one_ressource])
                    - 1,
                    self.rcpsp_model.horizon,
                )
                # instance["max_time"] = 2842
                keys += ["max_time"]
                ressource_capacity_time = [[
                    int(x)
                    for x in self.rcpsp_model.resources_availability[res][:(
                        instance["max_time"] + 1)]
                ] for res in resources_list]

                instance["ressource_capacity_time"] = ressource_capacity_time
                keys += ["ressource_capacity_time"]
        instance["nb_skill"] = len(self.rcpsp_model.skills_set)
        instance["skillreq"] = skill_required
        instance["nb_units"] = nb_units
        keys += ["nb_skill", "skillreq", "nb_units"]
        ressource_unit_capacity_time = [[
            1 if x else 0
            for x in self.rcpsp_model.employees[j].calendar_employee[:(
                instance["max_time"] + 1)]
        ] for j in sorted(self.rcpsp_model.employees)]

        import math

        skillunits = [[
            int(
                math.floor(
                    self.rcpsp_model.employees[j].dict_skill[s].skill_value))
            if s in self.rcpsp_model.employees[j].dict_skill else 0
            for s in skills_set
        ] for j in sorted(self.rcpsp_model.employees)]
        self.employees_position = sorted(self.rcpsp_model.employees)
        instance["ressource_unit_capacity_time"] = ressource_unit_capacity_time
        instance["skillunits"] = skillunits
        keys += ["skillunits", "ressource_unit_capacity_time"]

        # print('rreq: ', rreq)
        if not no_ressource:
            instance["rreq"] = rreq
            keys += ["rreq"]

            rcap = [
                int(max(self.rcpsp_model.resources_availability[x]))
                for x in resources_list
            ]
            instance["rcap"] = rcap
            keys += ["rcap"]
            rtype = [
                2 if res in self.rcpsp_model.non_renewable_resources else 1
                for res in resources_list
            ]

            instance["rtype"] = rtype
            keys += ["rtype"]

        succ = [
            set(self.rcpsp_model.successors[task]) for task in sorted_tasks
        ]

        instance["succ"] = succ
        keys += ["succ"]
        self.instance = instance
        p_s: Union[PartialSolution, None] = args.get("partial_solution", None)
        if p_s is not None:
            constraint_strings = []
            if p_s.start_times is not None:
                for task in p_s.start_times:
                    string = ("constraint start[" + str(task) + "] == " +
                              str(p_s.start_times[task]) + ";\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.partial_permutation is not None:
                for t1, t2 in zip(p_s.partial_permutation[:-1],
                                  p_s.partial_permutation[1:]):
                    string = ("constraint start[" + str(t1) + "] <= start[" +
                              str(t2) + "];\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.list_partial_order is not None:
                for l in p_s.list_partial_order:
                    for t1, t2 in zip(l[:-1], l[1:]):
                        string = ("constraint start[" + str(t1) +
                                  "] <= start[" + str(t2) + "];\n")
                        self.instance.add_string(string)
                        constraint_strings += [string]
            if p_s.task_mode is not None:
                for task in p_s.start_times:
                    indexes = [
                        i for i in self.modeindex_map
                        if self.modeindex_map[i]["task"] == task
                        and self.modeindex_map[i]["original_mode_index"] ==
                        p_s.task_mode[task]
                    ]
                    if len(indexes) >= 0:
                        string = "constraint mrun[" + str(
                            indexes[0]) + "] == 1;"
                        self.instance.add_string(string)
                        constraint_strings += [string]
            if p_s.start_together is not None:
                for t1, t2 in p_s.start_together:
                    string = ("constraint start[" + str(t1) + "] == start[" +
                              str(t2) + "];\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_after_nunit is not None:
                for t1, t2, delta in p_s.start_after_nunit:
                    string = ("constraint start[" + str(t2) + "] >= start[" +
                              str(t1) + "]+" + str(delta) + ";\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_at_end_plus_offset is not None:
                for t1, t2, delta in p_s.start_at_end_plus_offset:
                    string = ("constraint start[" + str(t2) + "] >= start[" +
                              str(t1) + "]+adur[" + str(t1) + "]+" +
                              str(delta) + ";\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_at_end is not None:
                for t1, t2 in p_s.start_at_end:
                    string = ("constraint start[" + str(t2) + "] == start[" +
                              str(t1) + "]+adur[" + str(t1) + "];\n")
                    self.instance.add_string(string)
                    constraint_strings += [string]
示例#2
0
 def init_model(self, **args):
     model_type = args.get("model_type", "single")
     if model_type == "single-preemptive":
         nb_preemptive = args.get("nb_preemptive", 2)
     model = Model(files_mzn[model_type])
     custom_output_type = args.get("output_type", False)
     if custom_output_type:
         model.output_type = RCPSPSolCP
         self.custom_output_type = True
     solver = Solver.lookup(map_cp_solver_name[self.cp_solver_name])
     instance = Instance(solver, model)
     if model_type == "single-preemptive":
         instance["nb_preemptive"] = nb_preemptive
         # TODO : make this as options.
         instance["possibly_preemptive"] = [
             True for task in self.rcpsp_model.mode_details
         ]
         instance["max_preempted"] = 3
     n_res = len(list(self.rcpsp_model.resources.keys()))
     # print('n_res: ', n_res)
     instance["n_res"] = n_res
     sorted_resources = sorted(self.rcpsp_model.resources_list)
     self.resources_index = sorted_resources
     rc = [int(self.rcpsp_model.resources[r]) for r in sorted_resources]
     # print('rc: ', rc)
     instance["rc"] = rc
     n_tasks = self.rcpsp_model.n_jobs + 2
     # print('n_tasks: ', n_tasks)
     instance["n_tasks"] = n_tasks
     sorted_tasks = sorted(self.rcpsp_model.mode_details.keys())
     d = [
         int(self.rcpsp_model.mode_details[key][1]['duration'])
         for key in sorted_tasks
     ]
     # print('d: ', d)
     instance["d"] = d
     rr = []
     index = 0
     for res in sorted_resources:
         rr.append([])
         for task in sorted_tasks:
             rr[index].append(
                 int(self.rcpsp_model.mode_details[task][1][res]))
         index += 1
     instance["rr"] = rr
     suc = [set(self.rcpsp_model.successors[task]) for task in sorted_tasks]
     instance["suc"] = suc
     self.instance = instance
     p_s: Union[PartialSolution, None] = args.get("partial_solution", None)
     if p_s is not None:
         constraint_strings = []
         if p_s.start_times is not None:
             for task in p_s.start_times:
                 string = "constraint s[" + str(task) + "] == " + str(
                     p_s.start_times[task]) + ";\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
         if p_s.partial_permutation is not None:
             for t1, t2 in zip(p_s.partial_permutation[:-1],
                               p_s.partial_permutation[1:]):
                 string = "constraint s[" + str(t1) + "] <= s[" + str(
                     t2) + "];\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
         if p_s.list_partial_order is not None:
             for l in p_s.list_partial_order:
                 for t1, t2 in zip(l[:-1], l[1:]):
                     string = "constraint s[" + str(t1) + "] <= s[" + str(
                         t2) + "];\n"
                     self.instance.add_string(string)
                     constraint_strings += [string]
         if p_s.start_together is not None:
             for t1, t2 in p_s.start_together:
                 string = "constraint s[" + str(t1) + "] == s[" + str(
                     t2) + "];\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
         if p_s.start_after_nunit is not None:
             for t1, t2, delta in p_s.start_after_nunit:
                 string = "constraint s[" + str(t2) + "] >= s[" + str(
                     t1) + "]+" + str(delta) + ";\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
         if p_s.start_at_end_plus_offset is not None:
             for t1, t2, delta in p_s.start_at_end_plus_offset:
                 string = "constraint s[" + str(t2) + "] >= s[" + str(
                     t1) + "]+d[" + str(t1) + "]+" + str(delta) + ";\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
         if p_s.start_at_end is not None:
             for t1, t2 in p_s.start_at_end:
                 string = "constraint s[" + str(t2) + "] == s[" + str(
                     t1) + "]+d[" + str(t1) + "];\n"
                 self.instance.add_string(string)
                 constraint_strings += [string]
示例#3
0
        return KillerSudokuBoard(base, self.board,hints,seed)

if __name__ == "__main__":
    SOLVABLE = False
    outputfile = "f-output4h35"#int(sys.argv[1])
    base = 4 #int(sys.argv[2])
    assert base > 0
    hints = 35
    # TODO: Seed not producing reliable results
    seed = 54 
    print("Starting Minizinc Module")

    gecode = Solver.lookup("gecode")
    model = Model()
    model.add_file(os.path.dirname(__file__) +"\\SudokuGeneration.mzn")
    model.output_type = Board
    instance = Instance(gecode, model)

    instance["Base"] = base

    result = instance.solve(verbose=True, debug_output=Path("./debug_output.txt"))
    kill_b:KillerSudokuBoard = result.solution.getKillerSudoku(base, hints, seed)

    print("Sudoku Generation Complete")
    print("Starting Cage Generation")
    if SOLVABLE:
        print("Valid")
        kill_b.gen_cages_valid(base*base*base)
    else: #Note: Sudokus obtained by the invalid process MAY be solvable, it's just not likely.
        print("Invalid")
        kill_b.gen_cages_invalid(base*base*base+2)
示例#4
0
    def init_model(self, **args):
        model = Model(files_mzn["multi-no-bool"])

        model.output_type = MRCPSP_Result
        solver = Solver.lookup(map_cp_solver_name[self.cp_solver_name])
        resources_list = list(self.rcpsp_model.resources.keys())
        instance = Instance(solver, model)
        n_res = len(resources_list)
        # print('n_res: ', n_res)
        keys = []

        instance["n_res"] = n_res
        keys += ["n_res"]

        # rc = [val for val in self.rcpsp_model.resources.values()]
        # # print('rc: ', rc)
        # instance["rc"] = rc

        n_tasks = self.rcpsp_model.n_jobs + 2
        # print('n_tasks: ', n_tasks)
        instance["n_tasks"] = n_tasks
        keys += ["n_tasks"]

        sorted_tasks = sorted(self.rcpsp_model.mode_details.keys())
        # print('mode_details: ', self.rcpsp_model.mode_details)
        n_opt = sum([
            len(list(self.rcpsp_model.mode_details[key].keys()))
            for key in sorted_tasks
        ])
        # print('n_opt: ', n_opt)
        instance["n_opt"] = n_opt
        keys += ["n_opt"]

        modes = []
        dur = []

        counter = 0
        self.modeindex_map = {}
        general_counter = 1
        for act in sorted_tasks:
            tmp = sorted(self.rcpsp_model.mode_details[act].keys())
            # tmp = [counter + x for x in tmp]
            set_mode_task = set()
            for i in range(len(tmp)):
                original_mode_index = tmp[i]
                set_mode_task.add(general_counter)
                self.modeindex_map[general_counter] = {
                    'task': act,
                    'original_mode_index': original_mode_index
                }
                general_counter += 1
            modes.append(set_mode_task)
            dur = dur + [
                self.rcpsp_model.mode_details[act][key]['duration']
                for key in tmp
            ]

        # print('modes: ', modes)
        instance['modes'] = modes
        keys += ["modes"]

        # print('dur: ', dur)
        instance['dur'] = dur
        keys += ["dur"]

        rreq = []
        index = 0
        for res in resources_list:
            rreq.append([])
            for task in sorted_tasks:
                for mod in sorted(self.rcpsp_model.mode_details[task].keys()):
                    rreq[index].append(
                        int(self.rcpsp_model.mode_details[task][mod][res]))
            index += 1

        # print('rreq: ', rreq)
        instance["rreq"] = rreq
        keys += ["rreq"]

        if not self.calendar:
            rcap = [self.rcpsp_model.resources[x] for x in resources_list]
        else:
            rcap = [
                int(max(self.rcpsp_model.resources[x])) for x in resources_list
            ]
        # print('rcap: ', rcap)
        instance["rcap"] = rcap
        keys += ["rcap"]

        # print('non_renewable_resources:', self.rcpsp_model.non_renewable_resources)
        rtype = [
            2 if res in self.rcpsp_model.non_renewable_resources else 1
            for res in resources_list
        ]

        # print('rtype: ', rtype)
        instance["rtype"] = rtype
        keys += ["rtype"]

        succ = [
            set(self.rcpsp_model.successors[task]) for task in sorted_tasks
        ]
        # print('succ: ', succ)

        instance["succ"] = succ
        keys += ["succ"]

        if self.calendar:
            one_ressource = list(self.rcpsp_model.resources.keys())[0]
            instance["max_time"] = len(
                self.rcpsp_model.resources[one_ressource])
            print(instance["max_time"])
            keys += ["max_time"]
            ressource_capacity_time = [[
                int(x) for x in self.rcpsp_model.resources[res]
            ] for res in resources_list]
            # print(instance["max_time"])
            # print(len(ressource_capacity_time))
            # print([len(x) for x in ressource_capacity_time])
            instance["ressource_capacity_time"] = ressource_capacity_time
            keys += ["ressource_capacity_time"]

        # import pymzn
        # pymzn.dict2dzn({key: instance[key] for key in keys},
        #                fout='rcpsp_.dzn')
        self.instance = instance
        p_s: Union[PartialSolution, None] = args.get("partial_solution", None)
        if p_s is not None:
            constraint_strings = []
            if p_s.start_times is not None:
                for task in p_s.start_times:
                    string = "constraint start[" + str(task) + "] == " + str(
                        p_s.start_times[task]) + ";\n"
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.partial_permutation is not None:
                for t1, t2 in zip(p_s.partial_permutation[:-1],
                                  p_s.partial_permutation[1:]):
                    string = "constraint start[" + str(
                        t1) + "] <= start[" + str(t2) + "];\n"
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.list_partial_order is not None:
                for l in p_s.list_partial_order:
                    for t1, t2 in zip(l[:-1], l[1:]):
                        string = "constraint start[" + str(
                            t1) + "] <= start[" + str(t2) + "];\n"
                        self.instance.add_string(string)
                        constraint_strings += [string]
            if p_s.task_mode is not None:
                for task in p_s.start_times:
                    indexes = [
                        i for i in self.modeindex_map
                        if self.modeindex_map[i]["task"] == task
                        and self.modeindex_map[i]["original_mode_index"] ==
                        p_s.task_mode[task]
                    ]
                    if len(indexes) >= 0:
                        string = "constraint mrun[" + str(
                            indexes[0]) + "] == 1;"
                        self.instance.add_string(string)
                        constraint_strings += [string]
示例#5
0
    def init_model(self, **args):
        model_type = args.get("model_type", None)
        if model_type is None:
            model_type = "multi" if not self.calendar else "multi-calendar"
        model = Model(files_mzn[model_type])
        custom_output_type = args.get("output_type", False)
        if custom_output_type:
            model.output_type = RCPSPSolCP
            self.custom_output_type = True
        solver = Solver.lookup(map_cp_solver_name[self.cp_solver_name])
        resources_list = list(self.rcpsp_model.resources.keys())
        self.resources_index = resources_list
        instance = Instance(solver, model)
        n_res = len(resources_list)

        keys = []

        instance["n_res"] = n_res
        keys += ["n_res"]

        n_tasks = self.rcpsp_model.n_jobs + 2

        instance["n_tasks"] = n_tasks
        keys += ["n_tasks"]

        sorted_tasks = sorted(self.rcpsp_model.mode_details.keys())

        n_opt = sum(
            [
                len(list(self.rcpsp_model.mode_details[key].keys()))
                for key in sorted_tasks
            ]
        )

        instance["n_opt"] = n_opt
        keys += ["n_opt"]

        modes = []
        dur = []
        self.modeindex_map = {}
        general_counter = 1
        for act in sorted_tasks:
            tmp = sorted(self.rcpsp_model.mode_details[act].keys())
            # tmp = [counter + x for x in tmp]
            set_mode_task = set()
            for i in range(len(tmp)):
                original_mode_index = tmp[i]
                set_mode_task.add(general_counter)
                self.modeindex_map[general_counter] = {
                    "task": act,
                    "original_mode_index": original_mode_index,
                }
                general_counter += 1
            modes.append(set_mode_task)
            dur = dur + [
                self.rcpsp_model.mode_details[act][key]["duration"] for key in tmp
            ]

        instance["modes"] = modes
        keys += ["modes"]

        instance["dur"] = dur
        keys += ["dur"]

        rreq = []
        index = 0
        for res in resources_list:
            rreq.append([])
            for task in sorted_tasks:
                for mod in sorted(self.rcpsp_model.mode_details[task].keys()):
                    rreq[index].append(
                        int(self.rcpsp_model.mode_details[task][mod][res])
                    )
            index += 1

        instance["rreq"] = rreq
        keys += ["rreq"]

        if not self.calendar:
            rcap = [int(self.rcpsp_model.resources[x]) for x in resources_list]
        else:
            rcap = [int(max(self.rcpsp_model.resources[x])) for x in resources_list]

        instance["rcap"] = rcap
        keys += ["rcap"]

        rtype = [
            2 if res in self.rcpsp_model.non_renewable_resources else 1
            for res in resources_list
        ]

        instance["rtype"] = rtype
        keys += ["rtype"]

        succ = [set(self.rcpsp_model.successors[task]) for task in sorted_tasks]

        instance["succ"] = succ
        keys += ["succ"]

        if self.calendar:
            one_ressource = list(self.rcpsp_model.resources.keys())[0]
            instance["max_time"] = len(self.rcpsp_model.resources[one_ressource])
            keys += ["max_time"]
            ressource_capacity_time = [
                [int(x) for x in self.rcpsp_model.resources[res]]
                for res in resources_list
            ]

            instance["ressource_capacity_time"] = ressource_capacity_time
            keys += ["ressource_capacity_time"]

        self.instance = instance
        p_s: Union[PartialSolution, None] = args.get("partial_solution", None)
        if p_s is not None:
            constraint_strings = []
            if p_s.start_times is not None:
                for task in p_s.start_times:
                    string = (
                        "constraint start["
                        + str(task)
                        + "] == "
                        + str(p_s.start_times[task])
                        + ";\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.partial_permutation is not None:
                for t1, t2 in zip(
                    p_s.partial_permutation[:-1], p_s.partial_permutation[1:]
                ):
                    string = (
                        "constraint start[" + str(t1) + "] <= start[" + str(t2) + "];\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.list_partial_order is not None:
                for l in p_s.list_partial_order:
                    for t1, t2 in zip(l[:-1], l[1:]):
                        string = (
                            "constraint start["
                            + str(t1)
                            + "] <= start["
                            + str(t2)
                            + "];\n"
                        )
                        self.instance.add_string(string)
                        constraint_strings += [string]
            if p_s.task_mode is not None:
                for task in p_s.start_times:
                    indexes = [
                        i
                        for i in self.modeindex_map
                        if self.modeindex_map[i]["task"] == task
                        and self.modeindex_map[i]["original_mode_index"]
                        == p_s.task_mode[task]
                    ]
                    if len(indexes) >= 0:
                        string = "constraint mrun[" + str(indexes[0]) + "] == 1;"
                        self.instance.add_string(string)
                        constraint_strings += [string]
            if p_s.start_together is not None:
                for t1, t2 in p_s.start_together:
                    string = (
                        "constraint start[" + str(t1) + "] == start[" + str(t2) + "];\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_after_nunit is not None:
                for t1, t2, delta in p_s.start_after_nunit:
                    string = (
                        "constraint start["
                        + str(t2)
                        + "] >= start["
                        + str(t1)
                        + "]+"
                        + str(delta)
                        + ";\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_at_end_plus_offset is not None:
                for t1, t2, delta in p_s.start_at_end_plus_offset:
                    string = (
                        "constraint start["
                        + str(t2)
                        + "] >= start["
                        + str(t1)
                        + "]+adur["
                        + str(t1)
                        + "]+"
                        + str(delta)
                        + ";\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]
            if p_s.start_at_end is not None:
                for t1, t2 in p_s.start_at_end:
                    string = (
                        "constraint start["
                        + str(t2)
                        + "] == start["
                        + str(t1)
                        + "]+adur["
                        + str(t1)
                        + "];\n"
                    )
                    self.instance.add_string(string)
                    constraint_strings += [string]