polish CP-SAT Python jobshop examples
This commit is contained in:
@@ -24,15 +24,17 @@ def main():
|
||||
"""Solves a jobshop with maintenance on one machine."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
jobs = [[(5, 0, 20)], [(10, 1, 20)], [(6, 3, 60)], [(10, 2, 100)],
|
||||
[(50, 4, 500)], [(12, 4, 50)], [(3, 0, 300)], [(5, 4, 500)],
|
||||
[(3, 3, 300)], [(5, 4, 500)]]
|
||||
jobs_data = [ # task = (machine_id, processing_time).
|
||||
[(0, 3), (1, 2), (2, 2)], # Job0
|
||||
[(0, 2), (2, 1), (1, 4)], # Job1
|
||||
[(1, 4), (2, 3)] # Job2
|
||||
]
|
||||
|
||||
machines_count = max(task[1] for job in jobs for task in job) + 1
|
||||
machines_count = 1 + max(task[0] for job in jobs_data for task in job)
|
||||
all_machines = range(machines_count)
|
||||
|
||||
# Computes horizon dynamically as the sum of all durations.
|
||||
horizon = sum(task[0] for job in jobs for task in job)
|
||||
horizon = sum(task[1] for job in jobs_data for task in job)
|
||||
|
||||
# Named tuple to store information about created variables.
|
||||
task_type = collections.namedtuple('Task', 'start end interval')
|
||||
@@ -44,31 +46,26 @@ def main():
|
||||
all_tasks = {}
|
||||
machine_to_intervals = collections.defaultdict(list)
|
||||
|
||||
for j, job in enumerate(jobs):
|
||||
for j, job in enumerate(jobs_data):
|
||||
for t, task in enumerate(job):
|
||||
suffix = '_%i_%i' % (j, t)
|
||||
start_var = model.NewIntVar(0, horizon, 'start' + suffix)
|
||||
end_var = model.NewIntVar(0, horizon, 'end' + suffix)
|
||||
interval_var = model.NewIntervalVar(start_var, task[0], end_var,
|
||||
interval_var = model.NewIntervalVar(start_var, task[1], end_var,
|
||||
'interval' + suffix)
|
||||
all_tasks[j, t] = task_type(
|
||||
start=start_var, end=end_var, interval=interval_var)
|
||||
machine_to_intervals[task[1]].append(interval_var)
|
||||
machine_to_intervals[task[0]].append(interval_var)
|
||||
|
||||
# Add maintenance interval.
|
||||
machine_to_intervals[0].append(model.NewIntervalVar(6, 4, 10, 'weekend_0'))
|
||||
machine_to_intervals[0].append(model.NewIntervalVar(4, 4, 8, 'weekend_0'))
|
||||
|
||||
# Create disjuctive constraints.
|
||||
for m in all_machines:
|
||||
model.AddNoOverlap(machine_to_intervals[m])
|
||||
|
||||
# Add deadlines on tasks.
|
||||
for j, job in enumerate(jobs):
|
||||
for t, task in enumerate(job):
|
||||
model.Add(all_tasks[j, t].end <= task[2])
|
||||
|
||||
# Precedences inside a job.
|
||||
for j, job in enumerate(jobs):
|
||||
for j, job in enumerate(jobs_data):
|
||||
for t in range(len(job) - 1):
|
||||
model.Add(all_tasks[j, t + 1].start >= all_tasks[j, t].end)
|
||||
|
||||
@@ -76,7 +73,7 @@ def main():
|
||||
obj_var = model.NewIntVar(0, horizon, 'makespan')
|
||||
model.AddMaxEquality(
|
||||
obj_var,
|
||||
[all_tasks[j, len(job) - 1].end for j, job in enumerate(jobs)])
|
||||
[all_tasks[j, len(job) - 1].end for j, job in enumerate(jobs_data)])
|
||||
model.Minimize(obj_var)
|
||||
|
||||
# Solve model.
|
||||
@@ -90,15 +87,15 @@ def main():
|
||||
|
||||
# Create one list of assigned tasks per machine.
|
||||
assigned_jobs = collections.defaultdict(list)
|
||||
for j, job in enumerate(jobs):
|
||||
for j, job in enumerate(jobs_data):
|
||||
for t, task in enumerate(job):
|
||||
machine = task[1]
|
||||
machine = task[0]
|
||||
assigned_jobs[machine].append(
|
||||
assigned_task_type(
|
||||
start=solver.Value(all_tasks[j, t].start),
|
||||
job=j,
|
||||
index=t,
|
||||
duration=task[0]))
|
||||
duration=task[1]))
|
||||
|
||||
# Create per machine output lines.
|
||||
sol_line = ''
|
||||
|
||||
@@ -112,32 +112,33 @@ def MinimalJobshopSat():
|
||||
job=job,
|
||||
index=task_id))
|
||||
|
||||
disp_col_width = 10
|
||||
|
||||
# Create per machine output lines.
|
||||
sol_line = ''
|
||||
sol_line_tasks = ''
|
||||
|
||||
print('Optimal Schedule', '\n')
|
||||
|
||||
for machine in all_machines:
|
||||
# Sort by starting time.
|
||||
assigned_jobs[machine].sort()
|
||||
sol_line += 'Machine ' + str(machine) + ': '
|
||||
sol_line_tasks += 'Machine ' + str(machine) + ': '
|
||||
sol_line += ' - machine ' + str(machine) + ': '
|
||||
sol_line_tasks += ' - machine ' + str(machine) + ': '
|
||||
|
||||
for assigned_task in assigned_jobs[machine]:
|
||||
name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)
|
||||
# Add spaces to output to align columns.
|
||||
sol_line_tasks += name + ' ' * (disp_col_width - len(name))
|
||||
sol_line_tasks += '%10s' % name
|
||||
start = assigned_task.start
|
||||
duration = jobs_data[assigned_task.job][assigned_task.index][1]
|
||||
|
||||
sol_tmp = '[%i,%i]' % (start, start + duration)
|
||||
# Add spaces to output to align columns.
|
||||
sol_line += sol_tmp + ' ' * (disp_col_width - len(sol_tmp))
|
||||
sol_line += '%10s' % sol_tmp
|
||||
|
||||
sol_line += '\n'
|
||||
sol_line_tasks += '\n'
|
||||
|
||||
# Finally print the solution found.
|
||||
print('Optimal Schedule', '\n')
|
||||
print(sol_line_tasks)
|
||||
print('Task Time Intervals\n')
|
||||
print(sol_line)
|
||||
|
||||
Reference in New Issue
Block a user