# Transition times and transition costs using a circuit constraint.
self.switch_literals = dict() # indexed by (machine_id, i,j) # []
self.total_cost = []
for machine_id in self.all_machines:
print(f'machine_id: {machine_id}')
machine_starts = starts_per_machines[machine_id]
machine_ends = ends_per_machines[machine_id]
machine_presences = presences_per_machines[machine_id]
machine_resources = resources_per_machines[machine_id]
machine_materials = materials_per_machines[machine_id]
machine_ranks = ranks_per_machines[machine_id]
intervals = intervals_per_machines[machine_id]
arcs = []
num_machine_tasks = len(machine_starts)
all_machine_tasks = range(num_machine_tasks)
collect_j = []
for i in all_machine_tasks:
# Initial arc from the dummy node (0) to a task.
start_lit = self.model.NewBoolVar('start_lit %i on machine %i' % (i, machine_id))
self.all_variables.append(start_lit)
arcs.append([0, i + 1, start_lit])
# If this task is the first, set both rank and start to 0.
self.model.Add(machine_ranks[i] == 0).OnlyEnforceIf(start_lit)
# Final arc from an arc to the dummy node.
final_arc = self.model.NewBoolVar('final_arc %i on machine %i' % (i, machine_id))
self.all_variables.append(final_arc)
arcs.append([i + 1, 0, final_arc])
# Self arc if the task is not performed.
arcs.append([i + 1, i + 1, machine_presences[i].Not()])
self.model.Add(machine_ranks[i] == -1).OnlyEnforceIf(machine_presences[i].Not())
# Compute the transition time if task j is the successor of task i.
parts_i = machine_starts[i].Name().split('_')
job_id_i, task_id_i, alt_id_i = int(parts_i[1][1:]), int(parts_i[2][1:]), int(parts_i[3][1:])
self.model.Add(self.add_time_trans[job_id_i, task_id_i, alt_id_i ] == 0).OnlyEnforceIf(start_lit)
for j in all_machine_tasks:
if i == j:
continue
lit = self.model.NewBoolVar('%i follows %i on machine %i' % (j, i, machine_id))
self.all_variables.append(lit)
arcs.append([i + 1, j + 1, lit])
self.model.AddImplication(lit, machine_presences[i])
self.model.AddImplication(lit, machine_presences[j])
# Maintain rank incrementally.
self.model.Add(machine_ranks[j] == machine_ranks[i] + 1).OnlyEnforceIf(lit)
# for solution hinting
self.switch_literals[(machine_id, i,j)] = lit
####
# Start of computing transition time
# Transition time is the duration time of the setup of task j
# The duration is needed for the part above and split_intervals_setter_Einspindler and split_intervals_setter_Rundtakt
# Compute the transition time if task j is the successor of task i.
parts_j = machine_starts[j].Name().split('_')
job_id_j, task_id_j, alt_id_j = int(parts_j[1][1:]), int(parts_j[2][1:]), int(parts_j[3][1:])
transition_time = self.ruestzeiten_werkzeugliste_id.loc[int(parts_i[1][1:])+1, int(parts_j[1][1:])+1]
if machine_materials[i] != machine_materials[j]:
materialfaktor = materialwechsel.loc[machine_materials[i], machine_materials[j]]# 3 #ruestzeiten
else:
materialfaktor = 0
# simplified for this example
additional_time = transition_time + materialfaktor
# End of computing transition time
####
# We add the
self.model.Add(machine_starts[j] >= machine_ends[i]).OnlyEnforceIf(lit)
# TEMP
#self.model.Add(machine_starts[j] <= machine_ends[i] + 0 + (max_distance_per_machine[machine_id]+90)*24).OnlyEnforceIf(lit)
if arcs:
self.model.AddCircuit(arcs)