job_shop_lib.dispatching¶
Contains classes and functions to solve the Job Shop Scheduling Problem step-by-step.
Handles the logic of scheduling operations on machines. |
|
Abstract class that allows objects to observe and respond to changes within the |
|
Observer that stores the history of the dispatcher. |
|
Stores the operations that have not been dispatched yet. |
|
Observer that identifies which available operations are optimal based on a reference schedule. |
|
Configuration for initializing any type of class. |
|
|
alias of |
Enumeration of ready operations filter types. |
|
Creates and returns a filter function based on the specified filter strategy name. |
|
Filters out all the operations that are dominated. |
|
Filters out all the operations associated with machines which earliest operation is not the current time. |
|
Filters out all the operations associated with non-idle machines. |
|
Filters out all the operations that can't start immediately. |
|
Creates and returns a |
|
|
alias of |
Default start time calculator that implements the standard behavior. |
|
Returns a start time calculator that adds setup times based on machine IDs. |
|
Returns a start time calculator that adds setup times based on a matrix of setup times. |
|
Returns a start time calculator that accounts for machine breakdowns. |
|
Factory for a calculator with sequence-dependent setup times. |
|
Returns a start time calculator that respects operation arrival times. |
Dispatching refers to the decision-making process of selecting which job should be processed next on a particular machine when that machine becomes available.
- class Dispatcher(instance, ready_operations_filter=None, start_time_calculator=<function no_setup_time_calculator>)[source]¶
Bases:
objectHandles the logic of scheduling operations on machines.
This class allow us to just define the order in which operations are sequenced and the machines in which they are processed. It is then responsible for scheduling the operations on the machines and keeping track of the next available time for each machine and job.
The core method of the class are:
dispatch(operation[, machine_id])Schedules the given operation on the given machine.
reset()Resets the dispatcher to its initial state.
It also provides methods to query the state of the schedule and the operations:
Returns the current time of the schedule.
Returns a list of available operations for processing, optionally filtering out operations using the filter function.
Returns the list of ready machines.
Returns the list of ready jobs.
Returns the list of operations that have not been scheduled.
Returns the list of operations that have been scheduled.
Returns the list of operations that are currently being processed.
Returns the set of operations that have been completed.
Returns the list of operations that have not been completed yet.
is_scheduled(operation)Checks if the given operation has been scheduled.
is_ongoing(scheduled_operation)Checks if the given operation is currently being processed.
next_operation(job_id)Returns the next operation to be scheduled for the given job.
earliest_start_time(operation)Calculates the earliest start time for a given operation based on machine and job constraints.
remaining_duration(scheduled_operation)Calculates the remaining duration of a scheduled operation.
The above methods which do not take any arguments are cached to improve performance. After each scheduling operation, the cache is cleared.
- Parameters:
instance (JobShopInstance) -- The instance of the job shop problem to be solved.
ready_operations_filter (Callable[[Dispatcher, list[Operation]], list[Operation]] | None) -- A function that filters out operations that are not ready to be scheduled. The function should take the dispatcher and a list of operations as input and return a list of operations that are ready to be scheduled. If
None, no filtering is done.start_time_calculator (StartTimeCalculator) -- A function that calculates the start time for a given operation on a given machine. The function should take a dispatcher, an operation and a machine id as input and return the start time for the operation. Defaults to the standard calculation which is the maximum of the machine's next available time and the job's next available time. This allows for implementing context-dependent setup times, downtime, and machine breakdowns.
- instance¶
The instance of the job shop problem to be scheduled.
- schedule¶
The schedule of operations on machines.
- ready_operations_filter¶
A function that filters out operations that are not ready to be scheduled.
- start_time_calculator¶
A function that calculates the start time for a given operation on a given machine.
- subscribers: list[DispatcherObserver]¶
A list of observers subscribed to the dispatcher.
- property machine_next_available_time: list[int]¶
Returns the next available time for each machine.
- property job_next_operation_index: list[int]¶
Returns the index of the next operation to be scheduled for each job.
- property job_next_available_time: list[int]¶
Returns the next available time for each job.
- subscribe(observer)[source]¶
Subscribes an observer to the dispatcher.
- Parameters:
observer (DispatcherObserver)
- unsubscribe(observer)[source]¶
Unsubscribes an observer from the dispatcher.
- Parameters:
observer (DispatcherObserver)
- dispatch(operation, machine_id=None)[source]¶
Schedules the given operation on the given machine.
The start time of the operation is computed based on the next available time for the machine and the next available time for the job to which the operation belongs. The operation is then scheduled on the machine and the tracking attributes are updated.
- Parameters:
operation (Operation) -- The operation to be scheduled.
machine_id (int | None) -- The id of the machine on which the operation is to be scheduled. If
None, theOperation'smachine_idattribute is used.
- Raises:
ValidationError -- If the operation is not ready to be scheduled.
UninitializedAttributeError -- If the operation has multiple machines in its list and no
machine_idis provided.
- Return type:
None
- is_operation_ready(operation)[source]¶
Returns True if the given operation is ready to be scheduled.
An operation is ready to be scheduled if it is the next operation to be scheduled for its job.
- Parameters:
operation (Operation) -- The operation to be checked.
- Return type:
bool
- start_time(operation, machine_id)[source]¶
Computes the start time for the given operation on the given machine.
Uses the configured start time calculator to compute the start time. By default, this is the maximum of the next available time for the machine and the next available time for the job to which the operation belongs.
- Parameters:
operation (Operation) -- The operation to be scheduled.
machine_id (int) -- The id of the machine on which the operation is to be scheduled.
- Return type:
int
- create_or_get_observer(observer, condition=<function Dispatcher.<lambda>>, **kwargs)[source]¶
Creates a new observer of the specified type or returns an existing observer of the same type if it already exists in the dispatcher's list of observers.
- Parameters:
observer (type[ObserverType]) -- The type of observer to be created or retrieved.
condition (Callable[[DispatcherObserver], bool]) -- A function that takes an observer and returns True if it is the observer to be retrieved. By default, it returns True for all observers.
**kwargs -- Additional keyword arguments to be passed to the observer's constructor.
- Return type:
ObserverType
- current_time()[source]¶
Returns the current time of the schedule.
The current time is the minimum start time of the available operations.
- Return type:
int
- min_start_time(operations)[source]¶
Returns the minimum start time of the available operations.
- Parameters:
operations (list[Operation])
- Return type:
int
- available_operations()[source]¶
Returns a list of available operations for processing, optionally filtering out operations using the filter function.
This method first gathers all possible next operations from the jobs being processed. It then optionally filters these operations using the filter function.
- Returns:
A list of
Operationobjects that are available for scheduling.- Return type:
list[Operation]
- raw_ready_operations()[source]¶
Returns a list of available operations for processing without applying the filter function.
- Returns:
A list of
Operationobjects that are available for scheduling based on precedence and machine constraints only.- Return type:
list[Operation]
- unscheduled_operations()[source]¶
Returns the list of operations that have not been scheduled.
- Return type:
list[Operation]
- scheduled_operations()[source]¶
Returns the list of operations that have been scheduled.
- Return type:
list[ScheduledOperation]
- earliest_start_time(operation)[source]¶
Calculates the earliest start time for a given operation based on machine and job constraints.
This method is different from the
start_timemethod in that it takes into account every machine that can process the operation, not just the one that will process it. However, it also assumes that the operation is ready to be scheduled in the job in favor of performance.- Parameters:
operation (Operation) -- The operation for which to calculate the earliest start time.
- Returns:
The earliest start time for the operation.
- Return type:
int
- remaining_duration(scheduled_operation)[source]¶
Calculates the remaining duration of a scheduled operation.
The method computes the remaining time for an operation to finish, based on the maximum of the operation's start time or the current time. This helps in determining how much time is left from 'now' until the operation is completed.
- Parameters:
scheduled_operation (ScheduledOperation) -- The operation for which to calculate the remaining time.
- Returns:
The remaining duration.
- Return type:
int
- completed_operations()[source]¶
Returns the set of operations that have been completed.
This method returns the operations that have been scheduled and the current time is greater than or equal to the end time of the operation.
- Return type:
set[ScheduledOperation]
- uncompleted_operations()[source]¶
Returns the list of operations that have not been completed yet.
This method checks for operations that either haven't been scheduled or have been scheduled but haven't reached their completion time.
Note: The behavior of this method changed in version 0.5.0. Previously, it only returned unscheduled operations. For the old behavior, use the unscheduled_operations method.
- Return type:
list[Operation]
- ongoing_operations()[source]¶
Returns the list of operations that are currently being processed.
This method returns the operations that have been scheduled and are currently being processed by the machines.
- Return type:
list[ScheduledOperation]
- is_scheduled(operation)[source]¶
Checks if the given operation has been scheduled.
- Parameters:
operation (Operation)
- Return type:
bool
- is_ongoing(scheduled_operation)[source]¶
Checks if the given operation is currently being processed.
- Parameters:
scheduled_operation (ScheduledOperation)
- Return type:
bool
- next_operation(job_id)[source]¶
Returns the next operation to be scheduled for the given job.
- Parameters:
job_id (int) -- The id of the job for which to return the next operation.
- Raises:
ValidationError -- If there are no more operations left for the job.
- Return type:
- class DispatcherObserver(dispatcher, *, subscribe=True)[source]¶
Bases:
ABCAbstract class that allows objects to observe and respond to changes within the
Dispatcher.It follows the Observer design pattern, where observers subscribe to the dispatcher and receive updates when certain events occur, such as when an operation is scheduled or when the dispatcher is reset.
- dispatcher¶
The
Dispatcherinstance to observe.
- Parameters:
dispatcher (Dispatcher) -- The
Dispatcherinstance to observe.subscribe (bool) -- If
True, automatically subscribes the observer to the dispatcher when it is initialized. Defaults toTrue.
- Raises:
ValidationError -- If
is_singletonisTrueand an observer of the same type already exists in the dispatcher's list of subscribers.
Example:
from job_shop_lib.dispatching import DispatcherObserver, Dispatcher from job_shop_lib import ScheduledOperation class HistoryObserver(DispatcherObserver): def __init__(self, dispatcher: Dispatcher): super().__init__(dispatcher) self.history: list[ScheduledOperation] = [] def update(self, scheduled_operation: ScheduledOperation): self.history.append(scheduled_operation) def reset(self): self.history = []
- property is_singleton: bool¶
Returns whether this observer is a singleton.
This is a class attribute that determines whether only one instance of this observer type can be subscribed to the dispatcher.
- abstract update(scheduled_operation)[source]¶
Called when an operation is scheduled on a machine.
- Parameters:
scheduled_operation (ScheduledOperation)
- class HistoryObserver(dispatcher, *, subscribe=True)[source]¶
Bases:
DispatcherObserverObserver that stores the history of the dispatcher.
- Parameters:
dispatcher (Dispatcher)
subscribe (bool)
- update(scheduled_operation)[source]¶
Called when an operation is scheduled on a machine.
- Parameters:
scheduled_operation (ScheduledOperation)
- class UnscheduledOperationsObserver(dispatcher, *, subscribe=True)[source]¶
Bases:
DispatcherObserverStores the operations that have not been dispatched yet.
This observer maintains a list of deques, each containing unscheduled operations for a specific job. It provides methods to access and manipulate unscheduled operations efficiently.
- Parameters:
dispatcher (Dispatcher)
subscribe (bool)
- property unscheduled_operations: Iterable[Operation]¶
An iterable of all unscheduled operations across all jobs.
- property num_unscheduled_operations: int¶
The total number of unscheduled operations.
- update(scheduled_operation)[source]¶
Removes a scheduled operation from the unscheduled operations.
This method is called by the dispatcher when an operation is scheduled. It removes the operation from its job's deque of unscheduled operations.
- Parameters:
scheduled_operation (ScheduledOperation) -- The operation that has been scheduled.
- Return type:
None
- class OptimalOperationsObserver(dispatcher, reference_schedule, *, subscribe=True)[source]¶
Bases:
DispatcherObserverObserver that identifies which available operations are optimal based on a reference schedule.
This observer compares the available operations at each step with a reference schedule to determine which operations would lead to the optimal solution. It can be used for training purposes or to analyze decision making in dispatching algorithms.
- optimal_operations¶
Set of operations that are considered optimal based on the reference schedule.
- reference_schedule¶
The reference schedule used to determine optimal operations.
- Parameters:
dispatcher (Dispatcher) -- The dispatcher instance to observe.
reference_schedule (Schedule) -- A complete schedule that represents the optimal or reference solution.
subscribe (bool) -- If True, automatically subscribes to the dispatcher.
- Raises:
ValidationError -- If the reference schedule is incomplete or if it doesn't match the dispatcher's instance.
- update(scheduled_operation)[source]¶
Updates the optimal operations after an operation is scheduled.
- Parameters:
scheduled_operation (ScheduledOperation) -- The operation that was just scheduled.
- Return type:
None
- class DispatcherObserverConfig(class_type, kwargs=<factory>)[source]¶
Bases:
Generic[T]Configuration for initializing any type of class.
Useful for specifying the type of the
DispatcherObserverand additional keyword arguments to pass to the dispatcher observer constructor while not containing thedispatcherargument.- Parameters:
class_type (T) -- Type of the class to be initialized. It can be the class type, an enum value, or a string. This is useful for the creation of
DispatcherObserverinstances from the factory functions.kwargs (dict[str, Any]) -- Keyword arguments needed to initialize the class. It must not contain the
dispatcherargument.
- class_type: T¶
Type of the class to be initialized. It can be the class type, an enum value, or a string. This is useful for the creation of
DispatcherObserverinstances from the factory functions.
- kwargs: dict[str, Any]¶
Keyword arguments needed to initialize the class. It must not contain the
dispatcherargument.
- class ReadyOperationsFilterType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
str,EnumEnumeration of ready operations filter types.
A filter function is used by the
Dispatcherclass to reduce the amount of available operations to choose from.- DOMINATED_OPERATIONS = 'dominated_operations'¶
- NON_IMMEDIATE_MACHINES = 'non_immediate_machines'¶
- NON_IDLE_MACHINES = 'non_idle_machines'¶
- NON_IMMEDIATE_OPERATIONS = 'non_immediate_operations'¶
- ready_operations_filter_factory(filter_name)[source]¶
Creates and returns a filter function based on the specified filter strategy name.
The filter function filters operations based on certain criteria such as dominated operations, immediate machine operations, etc.
- Parameters:
filter_name (str | ReadyOperationsFilterType | Callable[[Dispatcher, list[Operation]], list[Operation]]) -- The name of the filter function to be used. See
ReadyOperationsFilterTypefor supported values. Alternatively, a custom filter function can be passed directly.- Returns:
A function that takes a
Dispatcherinstance and a list ofOperationinstances as input and returns a list ofOperationinstances based on the specified filter function.- Raises:
ValidationError -- If the
filter_nameargument is not recognized or is not supported.- Return type:
Callable[[Dispatcher, list[Operation]], list[Operation]]
- filter_dominated_operations(dispatcher, operations)[source]¶
Filters out all the operations that are dominated. An operation is dominated if there is another operation that ends before it starts on the same machine.
- Parameters:
dispatcher (Dispatcher)
operations (list[Operation])
- Return type:
list[Operation]
- filter_non_immediate_machines(dispatcher, operations)[source]¶
Filters out all the operations associated with machines which earliest operation is not the current time.
- Parameters:
dispatcher (Dispatcher)
operations (list[Operation])
- Return type:
list[Operation]
- filter_non_idle_machines(dispatcher, operations)[source]¶
Filters out all the operations associated with non-idle machines.
A machine is considered idle if there are no ongoing operations currently scheduled on it. This filter removes operations that are associated with machines that are busy (i.e., have at least one uncompleted operation).
Utilizes :meth:
Dispatcher.ongoing_operations()to determine machine statuses.- Parameters:
dispatcher (Dispatcher) -- The dispatcher object.
operations (list[Operation]) -- The list of operations to filter.
- Returns:
The list of operations that are associated with idle machines.
- Return type:
list[Operation]
- filter_non_immediate_operations(dispatcher, operations)[source]¶
Filters out all the operations that can't start immediately.
An operation can start immediately if its earliest start time is the current time.
The current time is determined by the minimum start time of the operations.
- Parameters:
dispatcher (Dispatcher) -- The dispatcher object.
operations (list[Operation]) -- The list of operations to filter.
- Return type:
list[Operation]
- create_composite_operation_filter(ready_operations_filters)[source]¶
Creates and returns a
ReadyOperationsFilterfunction by combining multiple filter strategies.The composite filter function applies multiple filter strategies iteratively in the order they are specified in the list.
- Parameters:
ready_operations_filters (Iterable[Callable[[Dispatcher, list[Operation]], list[Operation]] | str | ReadyOperationsFilterType]) -- A list of filter strategies to be used. Supported values are 'dominated_operations' and 'non_immediate_machines' or any Callable that takes a
Dispatcherinstance and a list ofOperationinstances as input and returns a list ofOperationinstances.- Returns:
A function that takes a
Dispatcherinstance and a list ofOperationinstances as input and returns a list ofOperationinstances based on the specified list of filter strategies.- Raises:
ValidationError -- If any of the filter strategies in the list are not recognized or are not supported.
- Return type:
Callable[[Dispatcher, list[Operation]], list[Operation]]
- no_setup_time_calculator(dispatcher, operation, machine_id)[source]¶
Default start time calculator that implements the standard behavior.
The start time is the maximum of the machine's next available time, the job's next available time, and the operation's release date.
- Parameters:
dispatcher (Dispatcher) -- The dispatcher instance.
operation (Operation) -- The operation to be scheduled.
machine_id (int) -- The id of the machine on which the operation is to be scheduled.
- Returns:
The start time for the operation on the given machine.
- Return type:
int
- get_machine_dependent_setup_time_calculator(setup_times, default=0)[source]¶
Returns a start time calculator that adds setup times based on machine IDs.
- Parameters:
setup_times (dict[int, int]) -- Dictionary mapping machine_id to setup time in time units.
default (int) -- Default setup time to use if a machine_id is not found in the setup_times dictionary.
- Returns:
A start time calculator function that adds setup times.
Example
>>> setup_calc = get_machine_dependent_setup_time_calculator( ... {0: 2, 1: 1, 2: 3} ... ) >>> dispatcher = Dispatcher(instance, start_time_calculator=setup_calc)
- get_matrix_setup_time_calculator(setup_times)[source]¶
Returns a start time calculator that adds setup times based on a matrix of setup times.
- Parameters:
setup_times (Sequence[Sequence[int]] | ndarray[tuple[int, ...], dtype[integer]]) -- A 2D matrix where setup_times[i][j] is the setuptime for switching from operation
ito operationj. Here,iandjare operation's IDs.- Returns:
A start time calculator function that adds setup times based on the matrix.
- Return type:
Callable[[Dispatcher, Operation, int], int]
Example
>>> setup_calc = get_matrix_setup_time_calculator([[0, 2], [1, 0]]) >>> dispatcher = Dispatcher(instance, start_time_calculator=setup_calc)
- get_breakdown_calculator(breakdowns)[source]¶
Returns a start time calculator that accounts for machine breakdowns.
This calculator adjusts the start time of an operation based on when the machine is expected to be down due to breakdowns, maintenance, holidays, etc.
- Parameters:
breakdowns (dict[int, list[tuple[int, int]]]) -- Dictionary mapping machine_id to list of (start_time, duration) tuples representing when the machine breaks down.
- Returns:
A start time calculator function that accounts for breakdowns.
Example
>>> breakdown_calc = breakdown_calculator({0: [(5, 3)], 1: [(8, 2)]}) >>> dispatcher = Dispatcher(instance, ... start_time_calculator=breakdown_calc)
- get_job_dependent_setup_calculator(same_job_setup=0, different_job_setup=4, initial_setup=0)[source]¶
Factory for a calculator with sequence-dependent setup times.
This calculator determines setup time based on whether the current operation's job matches the job of the previously processed operation on the same machine.
- Parameters:
same_job_setup (int) -- Setup time when the previous operation on the machine was from the same job.
different_job_setup (int) -- Setup time when the previous operation on the machine was from a different job.
initial_setup (int) -- Setup time for the first operation on a machine or if the machine is currently idle.
- Returns:
A start time calculator function that applies sequence-dependent setup times.
Example
>>> seq_dep_calc = sequence_dependent_setup_calculator( ... same_job_setup=1, different_job_setup=4, initial_setup=1 ... ) >>> # Assuming 'instance' is a JobShopInstance >>> dispatcher = Dispatcher( ... instance, start_time_calculator=seq_dep_calc ... )
- get_arrival_calculator(arrival_times=None)[source]¶
Returns a start time calculator that respects operation arrival times.
This calculator uses a predefined matrix of arrival times to ensure that no operation begins before its specified arrival time. If the
arrival_timesmatrix isn't provided directly, the calculator attempts to retrieve it from the dispatcher's instance metadata using the key"arrival_times_matrix".- Parameters:
arrival_times (Sequence[Sequence[int]] | ndarray[tuple[int, ...], dtype[integer]] | None) -- A 2D matrix where
arrival_times[i][j]is the arrival time for the operation at indexjof jobi. IfNone, the calculator will attempt to retrieve it from the dispatcher metadata.- Returns:
A start time calculator function that uses the arrival times.
- Return type:
Callable[[Dispatcher, Operation, int], int]
Example
>>> arrival_calc = get_arrival_calculator([[0, 2], [1, 0]]) >>> dispatcher = Dispatcher( ... instance, start_time_calculator=arrival_calc ... )
Modules
Contains |
|
Contains the dispatching rules for the job shop scheduling problem. |