Resource breaks

Open In Colab

If you’re using this notebook in Google Colab, be sure to install PyJobShop first by executing pip install pyjobshop in a cell.

This notebook demonstrates how to model resource breaks using PyJobShop. In real-world scheduling, machines and resources often have planned breaks or unavailable periods, for example, lunch breaks, weekends, or planned maintenance.

We’ll cover the following:

  • A basic example to model resource breaks

  • How to allow tasks to be interrupted by breaks

  • A common example where breaks can be used to model operator availability

Basic example

Let’s create a simple scheduling problem with breaks.

[1]:
from pyjobshop import Model

model = Model()

All resources in PyJobShop have a breaks argument which can be used to specify breaks. Here, we create one machine with a break between [4-5] that represents a lunch break.

[2]:
machine = model.add_machine(breaks=[(4, 5)])

Let’s consider two tasks that need to be processed, each with processing time of 3 hours:

[3]:
job = model.add_job()

for _ in range(2):
    task = model.add_task(job)
    processing_time = 3
    model.add_mode(task, machine, processing_time)
[4]:
print(model.summary())
1 jobs
1 resources
└─ 1 machines
2 tasks
2 modes
0 constraints
objective
└─ weight_makespan=1
[5]:
result = model.solve(display=False)
print(result)
Solution results
================
  objective: 8.00
lower bound: 8.00
     status: Optimal
    runtime: 0.01 seconds
[6]:
from pyjobshop.plot import plot_machine_gantt

plot_machine_gantt(result.best, model.data())
../_images/examples_breaks_9_0.png

Allowing tasks to be interrupted by breaks

Notice how the tasks are scheduled to avoid breaks. By default, tasks cannot overlap with any breaks. To allow tasks to be interrupted by breaks, set allow_breaks=True. Let’s recreate the same problem with break interruptions enabled.

[7]:
model = Model()
machine = model.add_machine(breaks=[(4, 5)])
job = model.add_job()

for _ in range(2):
    task = model.add_task(job, allow_breaks=True)
    processing_time = 3
    model.add_mode(task, machine, processing_time)
[8]:
result = model.solve(display=False)
print(result)
Solution results
================
  objective: 7.00
lower bound: 7.00
     status: Optimal
    runtime: 0.00 seconds
[9]:
plot_machine_gantt(result.best, model.data())
../_images/examples_breaks_13_0.png

Great, this indeed works as expected: the second task is started before the break, and continues after the break. As a result, the task takes 1 time unit longer (the break duration), but the total processing time is still the same. This information is also contained in the solution:

[10]:
result.best.tasks
[10]:
[TaskData(mode=0, resources=[0], start=0, end=3, idle=0, breaks=0, present=True),
 TaskData(mode=1, resources=[0], start=3, end=7, idle=0, breaks=1, present=True)]

Operator availability

In many job shops, machines require operator supervision during setup but can process independently after setup. This example shows how to model such scenarios using synchronized tasks with operator breaks.

[11]:
model = Model()

We create two resources: a machine that can run continuously, and an operator with breaks representing non-working hours (0-8 and 17-24).

[12]:
machine = model.add_machine(name="machine")
operator = model.add_machine(breaks=[(0, 8), (17, 24)], name="operator")

Now we create two tasks: a long processing task (15 hours) for the machine, and a short setup task (1 hour) that requires operator supervision.

[13]:
job = model.add_job()
processing_task = model.add_task(job, name="processing")
model.add_mode(processing_task, machine, duration=15)

setup_task = model.add_task(job, name="setup")
model.add_mode(setup_task, operator, duration=1);

The key constraint is synchronization: both tasks must start simultaneously. This ensures processing can only begin when an operator is available for setup, but the machine can continue running after the operator finishes.

[14]:
# Both tasks must start simultaneously
model.add_start_before_start(processing_task, setup_task)
model.add_start_before_start(setup_task, processing_task);

Let’s solve and visualize the schedule:

[15]:
result = model.solve(display=False)
plot_machine_gantt(result.best, model.data(), plot_labels=True)
../_images/examples_breaks_25_0.png

Perfect! The Gantt chart shows both tasks starting at time 8 when the operator becomes available. The setup task finishes quickly while the machine continues processing until time 23. This pattern is common in manufacturing where operators are needed for setup but machines can run autonomously during production.

Conclusion

This notebook showed how to model resource breaks in PyJobShop:

  • Use the breaks parameter to define unavailable periods for resources

  • Set allow_breaks=True to let tasks be interrupted by breaks

These features help model real-world scheduling constraints like lunch breaks, shift patterns, and operator availability.