Example #1
0
def cplex_makespan_model(n: int, m: int, durations, machines) -> CpoModel:
    # n number of jobs, m machines
    # 1 line for un job with tasks on m machines

    naive = np.sum(durations)

    mdl = CpoModel()

    #Une variable est l'intervalle de durée pour une tache
    x = [[
        mdl.interval_var(size=durations[i, j], name="O{}-{}".format(i, j))
        for j in range(m)
    ] for i in range(n)]

    #contrainte end max d'une tache calculée avant
    for i in range(n):
        for j in range(m):
            mdl.add(mdl.end_of(x[i][j]) <= naive)

    #precedence
    for i in range(n):  #for each job
        for j in range(m - 1):  #taches ordonnées
            mdl.add(mdl.end_before_start(x[i][j], x[i][j + 1]))

    # une machine ne peut faire qu'une tache à la fois
    listtaches = [[] for k in range(m)]
    for i in range(n):
        for j in range(m):
            listtaches[machines[i, j]].append(x[i][j])

    for k in range(m):
        mdl.add(mdl.no_overlap(listtaches[k]))

    makespan = mdl.integer_var(0, naive, name="makespan")
    # le makespan est le max des tps pour chaque job
    mdl.add(makespan == mdl.max([mdl.end_of(x[i][m - 1]) for i in range(n)]))

    mdl.add(mdl.minimize(makespan))

    return mdl, x
Example #2
0
def recherche_exact(instance, temps):
    '''
    :param temps: int, temps de recherche
    :param instance: nom de l'instance str
    :return: None
    '''
    problem_data, optimum = loader(instance)
    nb_machine = problem_data["nb_machine"]
    nb_jobs = problem_data["nb_jobs"]
    problem = problem_data["problem"]

    machine, durations = separate(problem)

    model = CpoModel(name='Scheduling')

    # Variable
    job_operations = [[model.interval_var(size=durations[j][m],
                                          name="O{}-{}".format(j, m)) for m in range(nb_machine)] for j in
                      range(nb_jobs)]

    # chaque opération doit commencer aprés la fin de la précedente
    for j in range(nb_jobs):
        for s in range(1, nb_machine):
            model.add(model.end_before_start(job_operations[j][s - 1], job_operations[j][s]))

    # Pas d'overlap pour les operations executées sur une même machine
    machine_operations = [[] for m in range(nb_machine)]
    for j in range(nb_jobs):
        for s in range(0, nb_machine):
            machine_operations[machine[j][s]].append(job_operations[j][s])
    for lops in machine_operations:
        model.add(model.no_overlap(lops))

    # Minimiser la date de fin
    model.add(model.minimize(model.max([model.end_of(job_operations[i][nb_machine - 1]) for i in range(nb_jobs)])))

    # Solve model
    print("Solving model....")
    msol = model.solve(TimeLimit=temps)
Example #3
0

#-----------------------------------------------------------------------------
# Build the model
#-----------------------------------------------------------------------------

# Create model
mdl = CpoModel()

# Create one interval variable per task
tasks = {t['id']: mdl.interval_var(name="T{}".format(t['id'])) for t in TASKS}

# Add precedence constraints
for t in TASKS:
    for s in t['successors']:
        mdl.add(mdl.end_before_start(tasks[t['id']], tasks[s]))

# Create one optional interval variable per task mode and add alternatives for tasks
modes = {}  # Map of all modes
for t in TASKS:
    tmds = [mdl.interval_var(name=m['id'], optional=True, size=m['duration']) for m in t['modes']]
    mdl.add(mdl.alternative(tasks[t['id']], tmds))
    for m in tmds:
        modes[m.name] = m

# Initialize pulse functions for renewable and non renewable resources
renewables = [mdl.pulse((0, 0), 0) for j in range(NB_RENEWABLE)]
non_renewables = [0 for j in range(NB_NON_RENEWABLE)]
for m in MODES:
    dren = m['demandRenewable']
    dnren = m['demandNonRenewable']
Example #4
0
#-----------------------------------------------------------------------------

# Create model
mdl = CpoModel()

# Create one interval variable per job operation
job_operations = [[
    mdl.interval_var(size=JOB_DURATIONS[j][m], name="J{}-M{}".format(j, m))
    for m in range(NB_MACHINES)
] for j in range(NB_JOBS)]

# Force each operation to start after the end of the previous
for j in range(NB_JOBS):
    for m in range(1, NB_MACHINES):
        mdl.add(
            mdl.end_before_start(job_operations[j][m - 1],
                                 job_operations[j][m]))

# Force no overlap for operations executed on a same machine
for m in range(NB_MACHINES):
    mdl.add(mdl.no_overlap([job_operations[j][m] for j in range(NB_JOBS)]))

# Minimize termination date
mdl.add(
    mdl.minimize(
        mdl.max([
            mdl.end_of(job_operations[i][NB_MACHINES - 1])
            for i in range(NB_JOBS)
        ])))

#-----------------------------------------------------------------------------
# Solve the model and display the result
Example #5
0
# Create model
mdl = CpoModel()

masonry = mdl.interval_var(name='masonry', size=35)
carpentry = mdl.interval_var(name='carpentry', size=15)
plumbing = mdl.interval_var(name='plumbing', size=40)
ceiling = mdl.interval_var(name='ceiling', size=15)
roofing = mdl.interval_var(name='roofing', size=5)
painting = mdl.interval_var(name='painting', size=10)
windows = mdl.interval_var(name='windows', size=5)
facade = mdl.interval_var(name='facade', size=10)
garden = mdl.interval_var(name='garden', size=5)
moving = mdl.interval_var(name='moving', size=5)

# Add precedence constraints
mdl.add(mdl.end_before_start(masonry, carpentry))
mdl.add(mdl.end_before_start(masonry, plumbing))
mdl.add(mdl.end_before_start(masonry, ceiling))
mdl.add(mdl.end_before_start(carpentry, roofing))
mdl.add(mdl.end_before_start(ceiling, painting))
mdl.add(mdl.end_before_start(roofing, windows))
mdl.add(mdl.end_before_start(roofing, facade))
mdl.add(mdl.end_before_start(plumbing, facade))
mdl.add(mdl.end_before_start(roofing, garden))
mdl.add(mdl.end_before_start(plumbing, garden))
mdl.add(mdl.end_before_start(windows, moving))
mdl.add(mdl.end_before_start(facade, moving))
mdl.add(mdl.end_before_start(garden, moving))
mdl.add(mdl.end_before_start(painting, moving))

#-----------------------------------------------------------------------------
for i in range(len(ALL_TASKS)):
    ALL_TASKS[i].id = i

#-----------------------------------------------------------------------------
# Build the model
#-----------------------------------------------------------------------------

# Create model
mdl = CpoModel()

# Create interval variable for each building task
tasks = [mdl.interval_var(size=t.duration, name=t.name) for t in ALL_TASKS]

# Add precedence constraints
for p, s in PRECEDENCES:
    mdl.add(mdl.end_before_start(tasks[p.id], tasks[s.id]))

# Cost function
cost = []  # List of individual costs
fearliness = dict()  # Task earliness cost function (for display)
ftardiness = dict()  # Task tardiness cost function (for display)

for t in ALL_TASKS:
    task = tasks[t.id]
    if t.release_date is not None:
        f = CpoSegmentedFunction((-t.earliness_cost, 0),
                                 [(t.release_date, 0, 0)])
        cost.append(mdl.start_eval(task, f))
        fearliness[t] = f
    if t.due_date is not None:
        f = CpoSegmentedFunction((0, 0), [(t.due_date, 0, t.tardiness_cost)])
Example #7
0
    for task in SKILLS:
        wtasks[(house, task)] = mdl.interval_var(
            optional=True, name="house {} skill {}".format(house, task))

# Maximization objective of the model
obj2 = mdl.sum([
    s.level * mdl.presence_of(wtasks[(h, s)]) for s in SKILLS for h in HOUSES
])
mdl.add(mdl.maximize(obj2))

# Constraints of the model
for h in HOUSES:
    # Temporal constraints
    for p in TASK_PRECEDENCES:
        mdl.add(
            mdl.end_before_start(tasks[(h, find_tasks(p.beforeTask))],
                                 tasks[(h, find_tasks(p.afterTask))]))
    # Alternative workers
    for t in TASKS:
        mdl.add(
            mdl.alternative(
                tasks[(h, t)],
                [wtasks[(h, s)] for s in SKILLS if (s.task == t.name)], 1))
    # Continuity constraints
    for c in CONTINUITIES:
        mdl.add(
            mdl.presence_of(wtasks[(h, find_skills(c.worker, c.task1))]) ==
            mdl.presence_of(wtasks[(h, find_skills(c.worker, c.task2))]))

# No overlap constraint
for w in WORKERS:
    mdl.add(
Example #8
0
def tw_schedule(time_slot, tasks):
    start_time = time_slot[0]
    end_time = time_slot[1]

    mdl = CpoModel(name="generate_tw")
    # Create model for CP and solve for the first time to obtain initial time windows
    # Decision variables: time interval of each task
    task_vars = {}
    early = lambda x: "task_" + str(x) + "_early"
    late = lambda x: "task_" + str(x) + "_late"
    for id in tasks:
        if tasks[id].exact_time != None:
            # print("exact time: {}".format(tasks[id].exact_time))
            task_vars[early(id)] = mdl.interval_var(start=tasks[id].exact_time,
                                                    size=tasks[id].duration,
                                                    name=early(id))
            task_vars[late(id)] = mdl.interval_var(start=tasks[id].exact_time,
                                                   size=tasks[id].duration,
                                                   name=late(id))
        else:
            task_vars[early(id)] = mdl.interval_var(size=tasks[id].duration,
                                                    name=early(id))
            task_vars[late(id)] = mdl.interval_var(size=tasks[id].duration,
                                                   name=late(id))
    slot = mdl.interval_var(start=start_time,
                            end=end_time)  # Time interval of entire time slot
    # Add Constraints:
    for id in tasks:
        # 1st constraint: all intervals are within start and end time
        mdl.add(mdl.start_before_start(slot, task_vars[early(id)]))
        mdl.add(mdl.end_before_end(task_vars[early(id)], slot))
        mdl.add(mdl.start_before_start(slot, task_vars[late(id)]))
        mdl.add(mdl.end_before_end(task_vars[late(id)], slot))
        # mdl.add(mdl.span(slot, task_vars.values()))

        if tasks[id].precedence_before != []:
            # Tasks that have precedence_before constraints
            # 2nd Constraints: end of precedence_before_task is before start of current task
            for id_before in tasks[id].precedence_before:
                mdl.add(
                    mdl.end_before_start(task_vars[early(id_before)],
                                         task_vars[early(id)]))
                mdl.add(
                    mdl.end_before_start(task_vars[late(id_before)],
                                         task_vars[late(id)]))

    # Add objective:
    obj = mdl.maximize(
        sum([
            mdl.start_of(task_vars[late(id)]) -
            mdl.start_of(task_vars[early(id)]) for id in tasks
        ]))
    mdl.add(obj)

    # Solve model
    # sol = mdl.solve(TimeLimit = 10, LogVerbosity = "Verbose")
    sol = mdl.solve(
        TimeLimit=10,
        LogVerbosity="Quiet",
        agent='local',
        execfile=
        '/Applications/CPLEX_Studio201/cpoptimizer/bin/x86-64_osx/cpoptimizer')
    # sol = mdl.solve()

    if sol:
        # sol.write()
        time_window = {
            id: (sol.get_var_solution(task_vars[early(id)]).get_start(),
                 sol.get_var_solution(task_vars[late(id)]).get_start())
            for id in tasks
        }
    else:
        print("Instance not feasible - earliest start time")
        return {}

    return time_window
# about the machine costs.

task_intervals_on_machines = {m['id']: [] for m in data['machines']}
task_intervals = []

for machine in data['machines']:
    m_id = machine['id']

    # Sequencing of intervals
    num_intervals = len(on_intervals[m_id])
    for i in range(1, num_intervals):
        model.add(
            model.if_then(model.presence_of(on_intervals[m_id][i]),
                          model.presence_of(on_intervals[m_id][i - 1])))
        model.add(
            model.end_before_start(on_intervals[m_id][i - 1],
                                   on_intervals[m_id][i], 1))

    # Bind with task intervals
    for on_i in on_intervals[m_id]:
        machine_on_off[m_id] += model.pulse(on_i, 1)
        model.add(
            model.always_constant(tasks_running_on_machines[m_id], on_i, True,
                                  True))

for task in data['tasks']:
    # Master task interval
    task_interval = model.interval_var(
        size=task['duration'],
        start=(task['earliest_start_time'],
               task['latest_end_time'] - task['duration']),
        end=(task['earliest_start_time'] + task['duration'],
Example #10
0
tasks = {}
mtasks = {}
for j in range(NB_JOBS):
    for i,t in enumerate(Tasks[j]):
#        print((j,JOBS[j][2 * t],t),JOBS[j][2 * Tasks[j][-1] ])
        tasks[(j,JOBS[j][2 * t],t)] = mdl.interval_var(size = Durations[j][i], name="J{}-M{}".format(j, JOBS[j][2 * t]))
#    print("SKILLS")
    for s in Skills[j]:
#        print((j,s),"J{}-{}".format(j, s))
        mtasks[(j,s)] = mdl.interval_var(optional=True, name=str(j))#"J{}-{}".format(j, s)

for j in range(NB_JOBS):
#    print(j)
    for p in Precedences:
#        print((j,JOBS[j][2 * p[0]]),(j,JOBS[j][2 * p[1]]))
        mdl.add( mdl.end_before_start(tasks[j,JOBS[j][2 * p[0]],p[0]], tasks[j,JOBS[j][2 * p[1]],p[1]]) )
#for j in range(NB_JOBS):
#    for t in Tasks[j]:
#        print( (j,JOBS[j][2 * t]), [(j,s) for s in Skills[j] if s[0][:len('M'+str(JOBS[j][2 * t])) ] == 'M'+str(JOBS[j][2 * t]) and s[0][len('M'+str(JOBS[j][2 * t])): len('M'+str(JOBS[j][2 * t]))+1] in 'e'] )

for j in range(NB_JOBS):
    for t in Tasks[j]:
        mdl.add( 
                mdl.alternative(
                        tasks[j,JOBS[j][2 * t],t], 
                        [mtasks[j,s] for s in Skills[j] 
                        if s[0][:len('M'+str(JOBS[j][2 * t]))] == 'M'+str(JOBS[j][2 * t]) and s[0][len('M'+str(JOBS[j][2 * t])): len('M'+str(JOBS[j][2 * t]))+1] in 'e'
                        ] 
                        ) 
                )
for m in Maschines:
Example #11
0
]

# ОГРАНИЧЕНИЯ #
# Учтём приоритеты
for i in range(NB_RESOURCES):
    successors_tasks = []
    high_priority = []
    for k, j in enumerate(TASKS):
        if j["rnd"] == i and j["rank"] == 1:
            successors_tasks.append(k)
        if j["rnd"] == i and j["rank"] == 0:
            high_priority.append(k)

    for s in high_priority:
        for m in successors_tasks:
            mdl.add(mdl.end_before_start(tasks[m], tasks[s]))

# Учтём ресурсы (разработчиков)
for r in range(NB_RESOURCES):
    resources = [
        mdl.pulse(tasks[t], DEMANDS[t][r]) for t in range(NB_TASKS)
        if DEMANDS[t][r] > 0
    ]
    mdl.add(mdl.sum(resources) <= CAPACITIES[r])

# одновременно только одна задача
for i in range(NB_RESOURCES):
    lops = []
    for k, j in enumerate(TASKS):
        if j["rnd"] == i:
            lops.append(tasks[k])
def CP_model_subsequence_restricted(params):
##
    NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, ITEM_SIZES, COLORS, NUM_BINS, Timelimit, SEED = params


    print("*** Running CP Subseq Restricted with instance NUM_COLORS{} NUM_ITEMS{} BIN_SIZE {} DISCREPANCY {} SEED {}".format(
        NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED))

    mdl = CpoModel()

    ITEMS = [mdl.interval_var(start=[0, sum(ITEM_SIZES)], size=ITEM_SIZES[item], optional=False, name="item_"+str(item)) for item in range(NUM_ITEMS)]
    ITEMS_TO_BINS = [[mdl.interval_var(start=(0, BIN_SIZE-min(ITEM_SIZES)), end=(min(ITEM_SIZES), BIN_SIZE), size=ITEM_SIZES[item], optional=True, name="item{}InBin{}".format(item, bin)) for bin in range(NUM_BINS)] for item in range(NUM_ITEMS)]

    ITEMS_S = mdl.sequence_var(ITEMS, types=COLORS, name="itemSequence")
    BIN_S = [mdl.sequence_var([ITEMS_TO_BINS[item][bin] for item in range(NUM_ITEMS)], types=[COLORS[item] for item in range(NUM_ITEMS)], name="bin{}Sequence".format(bin)) for bin in range(NUM_BINS)]

    # COLORS_S = [[mdl.sequence_var(ITEMS[item][bin] for item in range(NUM_ITEMS) if COLORS[item] == color)] for color in range(NUM_COLORS)]
    BINS_USED = [mdl.binary_var() for bin in range(NUM_BINS)]


    for item in range(NUM_ITEMS):
        # for bin in range(NUM_BINS):
        #     mdl.add_kpi(
        #         mdl.presence_of(ITEMS_TO_BINS[item][bin]),
        #         "item_"+str(item)+" "+str(bin)
        #     )
        mdl.add(
            mdl.sum(
                [mdl.presence_of(
                    ITEMS_TO_BINS[item][bin])
                    for bin in range(NUM_BINS)]
                ) == 1
        )

    # for item in range(NUM_ITEMS):
    #     mdl.add(
    #         mdl.alternative(ITEMS[item], [ITEMS_TO_BINS[item][bin] for bin in range(NUM_BINS)])
    #     )

    for bin in range(NUM_BINS):
        mdl.add(mdl.no_overlap(BIN_S[bin]))


    for item in range(NUM_ITEMS-1):
        mdl.add(
            mdl.end_before_start(ITEMS[item], ITEMS[item+1])
        )

    mdl.add(mdl.no_overlap(ITEMS_S))

    for bin in range(NUM_BINS):
        mdl.add(
            mdl.same_common_subsequence(
                ITEMS_S,
                BIN_S[bin],
            )
        )

    for item in range(NUM_ITEMS):
        for bin in range(NUM_BINS):
            # if (item, bin) in [(17,5), (20, 5), (29, 5)]:
            #     mdl.add_kpi(mdl.type_of_next(BIN_S[bin], ITEMS_TO_BINS[item][bin], lastValue=-1, absentValue=-1), name="typeofnext{}_{}".format(item, bin))
            #
            #     mdl.add_kpi(mdl.type_of_prev(BIN_S[bin], ITEMS_TO_BINS[item][bin], firstValue=-1, absentValue=-1), name="typeofprev{}_{}".format(item, bin))

            mdl.add(
                COLORS[item] != mdl.type_of_next(BIN_S[bin], ITEMS_TO_BINS[item][bin], lastValue=-1, absentValue=-1)
            )

            mdl.add(
                COLORS[item] != mdl.type_of_prev(BIN_S[bin], ITEMS_TO_BINS[item][bin], firstValue=-1, absentValue=-1)
            )

    for bin in range(NUM_BINS):
        mdl.add(
            BINS_USED[bin] ==  mdl.any([
                mdl.presence_of(ITEMS_TO_BINS[item][bin]) for item in range(NUM_ITEMS)
            ])
        )
    for bin in range(NUM_BINS-1):
        mdl.add(
            BINS_USED[bin] >= BINS_USED[bin+1]
        )

    mdl.add(
        mdl.minimize(
            mdl.sum(
                BINS_USED
            )
        )
    )

    # mdl.add(
    #         mdl.sum(
    #             BINS_USED
    #         ) < 48
    # )

    try:

        msol = mdl.solve(TimeLimit = Timelimit)
        mdl._myInstance = (NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED)

        if msol:

            ITEMS_TO_BINS_S = []
            for bin in range(NUM_BINS):
                b_ = []
                for item in range(NUM_ITEMS):
                    s = msol[ITEMS_TO_BINS[item][bin]]
                    if s:
                        b_.append(s)
                ITEMS_TO_BINS_S.append(b_)
            # return mdl

            seq = msol.get_var_solution(BIN_S[0])

            print(ITEM_SIZES)
            print("CL: ",COLORS)

            Xs = []
            for item in range(NUM_ITEMS):
                for bin in range(NUM_BINS):
                    s = msol[ITEMS_TO_BINS[item][bin]]
                    if s:
                        # print(s)
                        Xs.append(bin)
            print("Xs: ", Xs)

            Xs = np.array(Xs)
            if solution_checker(Xs, params, "restricted_cp_subsequence"):
                write_to_global_cp(msol, mdl, 'restricted_subsequence')

    except Exception as err:
        print(err)
        write_to_global_failed(params, 'restricted_cp_subsequence', is_bad_solution=False)
Example #13
0
    _name = "delivery{}".format(d + 1)
    itvs[(d, 2)] = mdl.interval_var(size=minutes_on_delivery[d], name=_name)
#альтернатива между работниками
for i in range(numdetails):
    for j in range(2):
        mdl.add(
            mdl.alternative(itvs[(i, j)],
                            [itvs_3[(i, j)], itvs_2[(i, j)], itvs_1[(i, j)]]))
#навесим последовательность TO DO для 1,2,3
#for h in range(numdetails):
#        mdl.add(mdl.end_before_start(itvs[(h, 1)], itvs[(h, 2)]))
#for h in range(numdetails):
#        mdl.add(mdl.end_before_start(itvs[(h, 0)], itvs[(h, 1)]))
#навесим последовательность жестко
for h in range(numdetails):
    mdl.add(mdl.end_before_start(itvs[(h, 1)], itvs[(h, 2)]))
for h in range(numdetails):
    mdl.add(mdl.end_before_start(itvs[(h, 0)], itvs[(h, 1)]))
for h in range(numdetails):
    mdl.add(mdl.start_at_end(itvs[(h, 1)], itvs[(h, 0)]))
#навесим принадлежность
for h in range(numdetails):
    mdl.add(mdl.span(details[h], [itvs[(h, t)] for t in range(3)]))
workers = {}
workers1 = {
    "worker1":
    mdl.sequence_var(
        [itvs_1[(h, t)] for h in range(numdetails) for t in range(2)],
        types=[t for h in range(numdetails) for t in range(2)],
        name="worker1")
}
Example #14
0

#-----------------------------------------------------------------------------
# Build the model
#-----------------------------------------------------------------------------

# Create model
mdl = CpoModel()

# Create task interval variables
tasks = [mdl.interval_var(name="T{}".format(i + 1), size=DURATIONS[i]) for i in range(NB_TASKS)]

# Add precedence constraints
for t in range(NB_TASKS):
    for s in SUCCESSORS[t]:
        mdl.add(mdl.end_before_start(tasks[t], tasks[s - 1]))

# Constrain capacity of resources
for r in range(NB_RESOURCES):
    resources = [mdl.pulse(tasks[t], DEMANDS[t][r]) for t in range(NB_TASKS) if DEMANDS[t][r] > 0]
    mdl.add(mdl.sum(resources) <= CAPACITIES[r])

# Minimize end of all tasks
mdl.add(mdl.minimize(mdl.max([mdl.end_of(t) for t in tasks])))


#-----------------------------------------------------------------------------
# Solve the model and display the result
#-----------------------------------------------------------------------------

# Solve model
Example #15
0
    def create_model(self):
        mdl = CpoModel(name = "TAS Scheduling")
        #####################################################
        # Creating interval variables for WEST module
        #####################################################
        i = 0
        MS1_vars = []
        MS4_vars = []
        GTW_vars = []
        WEST_vars = []
        table_occupied_WEST = []

        kits_pulse_for_choice = []
        for i in range(len(self.timeOUEST)):
            min_start_time = int(date_converter.convert_to_work_time(datetime.timestamp(pd.to_datetime(self.req_matOUEST.iloc[i,2]))))

            #print(min_start_time, self.req_matOUEST.iloc[i,2])
            meca_length = int(self.timeOUEST.iloc[i, 2] / 10)
            qc_length = int(self.timeOUEST.iloc[i, 3] / 10)

            kit_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), name = "kitting " + self.timeOUEST.index[i])
            kit_interval1mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_max, name = "kitting 1 op " + self.timeOUEST.index[i], optional = True)
            kit_interval2mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_mid, name = "kitting 2 op " + self.timeOUEST.index[i], optional = True)
            kit_interval3mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_min, name = "kitting 3 op " + self.timeOUEST.index[i], optional = True)

            mdl.add(mdl.alternative(interval = kit_interval, array = [kit_interval1mec, kit_interval2mec, kit_interval3mec]))

            kits_pulse_for_choice += [kit_interval1mec, kit_interval2mec, kit_interval3mec]

            meca_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = meca_length, name = "meca " + self.timeOUEST.index[i])
            qc_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = qc_length, name = "qc " + self.timeOUEST.index[i])

            table_slot_occupied_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = (0, 9999999999999), name = "Table occupied " + self.timeOUEST.index[i])
            table_occupied_WEST += [table_slot_occupied_interval]

            mdl.add(mdl.end_before_start(kit_interval, meca_interval))
            mdl.add(mdl.end_before_start(meca_interval, qc_interval))

            mdl.add(mdl.start_at_end(table_slot_occupied_interval, kit_interval))
            mdl.add(mdl.start_at_end(meca_interval, table_slot_occupied_interval))
            
            WEST_vars += [kit_interval]
            WEST_vars += [meca_interval]
            WEST_vars += [qc_interval]

            if i < 19:
                MS1_vars += [kit_interval]
                MS1_vars += [meca_interval]
                MS1_vars += [qc_interval]

            elif i >= 45:
                GTW_vars += [kit_interval]
                GTW_vars += [meca_interval]
                GTW_vars += [qc_interval]
            
            else:
                MS4_vars += [kit_interval]
                MS4_vars += [meca_interval]
                MS4_vars += [qc_interval]


        ######################################################
        # Creating interval variables for EAST module
        ######################################################
        FOV_vars = []
        MS2_vars = []
        MS3_vars = []
        EAST_vars = []
        table_occupied_EAST = []

        for i in range(len(self.timeEST)):
            min_start_time = int(date_converter.convert_to_work_time(datetime.timestamp(pd.to_datetime(self.req_matOUEST.iloc[i,2]))))

            meca_length = int(self.timeOUEST.iloc[i, 2] / 10)
            qc_length = int(self.timeOUEST.iloc[i, 3] / 10)
            
            kit_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), name = "kitting " + self.timeEST.index[i])
            kit_interval1mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_max, name = "kitting 1 op " + self.timeEST.index[i], optional = True)
            kit_interval2mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_mid, name = "kitting 2 op " + self.timeEST.index[i], optional = True)
            kit_interval3mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_min, name = "kitting 3 op " + self.timeEST.index[i], optional = True)

            mdl.add(mdl.alternative(interval = kit_interval, array = [kit_interval1mec, kit_interval2mec, kit_interval3mec]))

            kits_pulse_for_choice += [kit_interval1mec, kit_interval2mec, kit_interval3mec]

            meca_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = meca_length, name = "meca " + self.timeEST.index[i])
            qc_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = qc_length, name = "qc " + self.timeEST.index[i])

            table_slot_occupied_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = (0, 9999999999999), name = "Table occupied " + self.timeEST.index[i])
            table_occupied_EAST += [table_slot_occupied_interval]

            mdl.add(mdl.end_before_start(kit_interval, meca_interval))
            mdl.add(mdl.end_before_start(meca_interval, qc_interval))

            mdl.add(mdl.start_at_end(table_slot_occupied_interval, kit_interval))
            mdl.add(mdl.start_at_end(meca_interval, table_slot_occupied_interval))

            EAST_vars += [kit_interval]
            EAST_vars += [meca_interval]
            EAST_vars += [qc_interval]
            
            if i < 11:
                FOV_vars += [kit_interval]
                FOV_vars += [meca_interval]
                FOV_vars += [qc_interval]

            elif i >= 25:
                MS3_vars += [kit_interval]
                MS3_vars += [meca_interval]
                MS3_vars += [qc_interval]

            else:
                MS2_vars += [kit_interval]
                MS2_vars += [meca_interval]
                MS2_vars += [qc_interval]

        ##################################################
        # Setting requirement relations between interval variables
        ##################################################
        for task in MS1_vars:
            for i in range(len(self.req_taskOUEST)):
                if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskOUEST.iloc[i, 0])):
                        for other_task in WEST_vars:
                            if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))
        #print("##############################################")
        for task in MS4_vars:
            for i in range(len(self.req_taskOUEST)):
                if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskOUEST.iloc[i, 0])):
                        for other_task in WEST_vars:
                            if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))
        #print("##############################################")
        for task in GTW_vars:
            for i in range(len(self.req_taskOUEST)):
                if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskOUEST.iloc[i, 0])):
                        for other_task in WEST_vars:
                            if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))
        #print("##############################################")
        for task in MS2_vars:
            for i in range(len(self.req_taskEST)):
                if (self.req_taskEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskEST.iloc[i, 0])):
                        for other_task in EAST_vars:
                            if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))
        #print("##############################################")
        for task in MS3_vars:
            for i in range(len(self.req_taskEST)):
                if (self.req_taskEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskEST.iloc[i, 0])):
                        for other_task in EAST_vars:
                            if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))
        #print("##############################################")
        for task in FOV_vars:
            for i in range(len(self.req_taskEST)):
                if (self.req_taskEST.index[i] in task.name) and "meca" in task.name:
                    for j in range(len(self.req_taskEST.iloc[i, 0])):
                        for other_task in EAST_vars:
                            if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name:
                                mdl.add(mdl.end_before_start(other_task, task))

        ##############################################
        # Adding resources constraints
        ##############################################

        all_tasks = EAST_vars + WEST_vars

        meca_resources = [mdl.pulse(task, 1) for task in EAST_vars if "meca" in task.name]
        meca_resources += [mdl.pulse(task, 1) for task in WEST_vars if "meca" in task.name]
        meca_resources += [mdl.pulse(task, 1) for task in kits_pulse_for_choice if "kitting 1 op" in task.name]
        meca_resources += [mdl.pulse(task, 2) for task in kits_pulse_for_choice if "kitting 2 op" in task.name]
        meca_resources += [mdl.pulse(task, 3) for task in kits_pulse_for_choice if "kitting 3 op" in task.name]

        qc_resources = [mdl.pulse(task, 1) for task in EAST_vars if "qc" in task.name]
        qc_resources += [mdl.pulse(task, 1) for task in WEST_vars if "qc" in task.name]

        work_slots_EAST = [mdl.pulse(task, 1) for task in EAST_vars if "qc" in task.name or "meca" in task.name]
        work_slots_WEST = [mdl.pulse(task, 1) for task in WEST_vars if "qc" in task.name or "meca" in task.name]

        kitting_slots_EAST = [mdl.pulse(task, 1) for task in table_occupied_EAST]
        kitting_slots_EAST += [mdl.pulse(task, 1) for task in EAST_vars if "kitting" in task.name]
        kitting_slots_WEST = [mdl.pulse(task, 1) for task in table_occupied_WEST]
        kitting_slots_WEST += [mdl.pulse(task, 1) for task in WEST_vars if "kitting" in task.name]

        mdl.add(mdl.sum(meca_resources) <= 3)
        mdl.add(mdl.sum(qc_resources) <= 1)
        mdl.add(mdl.sum(work_slots_EAST) <= 2)
        mdl.add(mdl.sum(work_slots_WEST) <= 2)
        mdl.add(mdl.sum(kitting_slots_EAST) <= 3)
        mdl.add(mdl.sum(kitting_slots_WEST) <= 3)

        [mdl.add(mdl.start_of(task) % (14*6) < 11*6) for task in all_tasks if "meca" in task.name]

        MS1_meca_qc = [task for task in MS1_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(MS1_meca_qc))

        MS2_meca_qc = [task for task in MS2_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(MS2_meca_qc))

        MS3_meca_qc = [task for task in MS3_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(MS3_meca_qc))

        MS4_meca_qc = [task for task in MS4_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(MS4_meca_qc))

        FOV_meca_qc = [task for task in FOV_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(FOV_meca_qc))

        GTW_meca_qc = [task for task in GTW_vars if (("meca" in task.name) or ("qc" in task.name))]
        mdl.add(mdl.no_overlap(GTW_meca_qc))

        mdl.add(mdl.minimize(mdl.max([mdl.end_of(t) for t in all_tasks]) - mdl.min([mdl.start_of(t) for t in all_tasks])))

        return mdl
Example #16
0
    modes_data.append(mode)

#-----------------------------------------------------------------------------
# Build the model
#-----------------------------------------------------------------------------

# Create model
mdl = CpoModel()

# Create one interval variable per task
tasks = {t: mdl.interval_var(name=t.name) for t in tasks_data}

# Add precedence constraints
for t in tasks_data:
    for s in t.successors:
        mdl.add(mdl.end_before_start(tasks[t], tasks[tasks_data[s]]))

# Create one optional interval variable per mode
modes = {
    m: mdl.interval_var(name=m.name, optional=True, size=m.duration)
    for m in modes_data
}

# Add mode alternative for each task
for t in tasks_data:
    mdl.add(mdl.alternative(tasks[t], [modes[m] for m in t.modes]))

# Initialize pulse functions for renewable and non renewable resources
renewables = [mdl.pulse((0, 0), 0) for j in range(NB_RENEWABLE)]
non_renewables = [0 for j in range(NB_NON_RENEWABLE)]
for m in modes_data: