Getting Started to Job Shop Lib¶
The main class of the library is the JobShopInstance
class, which stores a list of jobs and its Operations
.
Each operation is also a class, which stores the machine(s) in which the operation can be processed and its duration (also known as processing time). Let’s see an example of how to use the JobShopInstance
class to model a JSSP instance.
In this example, we model a simple Job Shop Scheduling Problem using the JobShopInstance
class. We define three types of machines: CPU, GPU, and Data Center, each represented by a unique identifier.
[1]:
from job_shop_lib import JobShopInstance, Operation
CPU = 0
GPU = 1
DATA_CENTER = 2
job_1 = [Operation(CPU, 1), Operation(GPU, 1), Operation(DATA_CENTER, 7)]
job_2 = [Operation(GPU, 5), Operation(DATA_CENTER, 1), Operation(CPU, 1)]
job_3 = [Operation(DATA_CENTER, 1), Operation(CPU, 3), Operation(GPU, 2)]
jobs = [job_1, job_2, job_3]
instance = JobShopInstance(
jobs,
name="Example",
# Any extra parameters are stored inside the
# metadata attribute as a dictionary:
lower_bound=7,
)
instance
[1]:
JobShopInstance(name=Example, num_jobs=3, num_machines=3)
The job and its position in it are automatically inferred. Now, we can access to some stats of the instance:
[2]:
print("Number of jobs:", instance.num_jobs)
print("Number of machines:", instance.num_machines)
print("Number of operations:", instance.num_operations)
print("Name:", instance.name)
print("Is flexible?:", instance.is_flexible)
print("Max operation time:", instance.max_duration)
print("Machine loads:", instance.machine_loads)
Number of jobs: 3
Number of machines: 3
Number of operations: 9
Name: Example
Is flexible?: False
Max operation time: 7
Machine loads: [5, 8, 9]
[3]:
import numpy as np
np.array(instance.durations_matrix)
[3]:
array([[1, 1, 7],
[5, 1, 1],
[1, 3, 2]])
[4]:
np.array(instance.machines_matrix)
[4]:
array([[0, 1, 2],
[1, 2, 0],
[2, 0, 1]])
Some of this attributes could take \(O(num\_operations)\) to compute. This is the reason we use the functools.cached_property
decorator to cache the results of the computation of these attributes.
Note that we just had to specify the machines in which the operation can be processed and its duration. The job_id
and the position of the operation in the job are automatically inferred by the JobShopInstance
class.
[5]:
first_operation = job_1[0]
print("Machine id:", first_operation.machine_id)
print("Duration:", first_operation.duration)
# If the operation only has one machine, we can use the `machine_id` property
# instead of the `machines` attribute:
print("Job id:", first_operation.job_id)
print("Position:", first_operation.position_in_job)
print("Operation id:", first_operation.operation_id)
print("String representation:", str(first_operation))
Machine id: 0
Duration: 1
Job id: 0
Position: 0
Operation id: 0
String representation: O(m=0, d=1, j=0, p=0)