job-shop-lib 0.5.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- job_shop_lib/__init__.py +19 -8
- job_shop_lib/{base_solver.py → _base_solver.py} +1 -1
- job_shop_lib/{job_shop_instance.py → _job_shop_instance.py} +155 -81
- job_shop_lib/_operation.py +118 -0
- job_shop_lib/{schedule.py → _schedule.py} +102 -84
- job_shop_lib/{scheduled_operation.py → _scheduled_operation.py} +25 -49
- job_shop_lib/benchmarking/__init__.py +66 -43
- job_shop_lib/benchmarking/_load_benchmark.py +88 -0
- job_shop_lib/constraint_programming/__init__.py +13 -0
- job_shop_lib/{cp_sat/ortools_solver.py → constraint_programming/_ortools_solver.py} +77 -22
- job_shop_lib/dispatching/__init__.py +51 -42
- job_shop_lib/dispatching/{dispatcher.py → _dispatcher.py} +223 -130
- job_shop_lib/dispatching/_dispatcher_observer_config.py +67 -0
- job_shop_lib/dispatching/_factories.py +135 -0
- job_shop_lib/dispatching/{history_tracker.py → _history_observer.py} +6 -7
- job_shop_lib/dispatching/_optimal_operations_observer.py +113 -0
- job_shop_lib/dispatching/_ready_operation_filters.py +168 -0
- job_shop_lib/dispatching/_unscheduled_operations_observer.py +70 -0
- job_shop_lib/dispatching/feature_observers/__init__.py +51 -13
- job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +212 -0
- job_shop_lib/dispatching/feature_observers/{duration_observer.py → _duration_observer.py} +20 -18
- job_shop_lib/dispatching/feature_observers/_earliest_start_time_observer.py +289 -0
- job_shop_lib/dispatching/feature_observers/_factory.py +95 -0
- job_shop_lib/dispatching/feature_observers/_feature_observer.py +228 -0
- job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +97 -0
- job_shop_lib/dispatching/feature_observers/_is_ready_observer.py +35 -0
- job_shop_lib/dispatching/feature_observers/{is_scheduled_observer.py → _is_scheduled_observer.py} +9 -5
- job_shop_lib/dispatching/feature_observers/{position_in_job_observer.py → _position_in_job_observer.py} +8 -10
- job_shop_lib/dispatching/feature_observers/{remaining_operations_observer.py → _remaining_operations_observer.py} +8 -26
- job_shop_lib/dispatching/rules/__init__.py +87 -0
- job_shop_lib/dispatching/rules/_dispatching_rule_factory.py +84 -0
- job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +201 -0
- job_shop_lib/dispatching/{dispatching_rules.py → rules/_dispatching_rules_functions.py} +70 -16
- job_shop_lib/dispatching/rules/_machine_chooser_factory.py +71 -0
- job_shop_lib/dispatching/rules/_utils.py +128 -0
- job_shop_lib/exceptions.py +18 -0
- job_shop_lib/generation/__init__.py +19 -0
- job_shop_lib/generation/_general_instance_generator.py +165 -0
- job_shop_lib/generation/_instance_generator.py +133 -0
- job_shop_lib/{generators/transformations.py → generation/_transformations.py} +16 -12
- job_shop_lib/generation/_utils.py +124 -0
- job_shop_lib/graphs/__init__.py +30 -12
- job_shop_lib/graphs/{build_disjunctive_graph.py → _build_disjunctive_graph.py} +41 -3
- job_shop_lib/graphs/{build_agent_task_graph.py → _build_resource_task_graphs.py} +28 -26
- job_shop_lib/graphs/_constants.py +38 -0
- job_shop_lib/graphs/_job_shop_graph.py +320 -0
- job_shop_lib/graphs/_node.py +182 -0
- job_shop_lib/graphs/graph_updaters/__init__.py +26 -0
- job_shop_lib/graphs/graph_updaters/_disjunctive_graph_updater.py +108 -0
- job_shop_lib/graphs/graph_updaters/_graph_updater.py +57 -0
- job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py +155 -0
- job_shop_lib/graphs/graph_updaters/_utils.py +25 -0
- job_shop_lib/py.typed +0 -0
- job_shop_lib/reinforcement_learning/__init__.py +68 -0
- job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py +398 -0
- job_shop_lib/reinforcement_learning/_resource_task_graph_observation.py +329 -0
- job_shop_lib/reinforcement_learning/_reward_observers.py +87 -0
- job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +443 -0
- job_shop_lib/reinforcement_learning/_types_and_constants.py +62 -0
- job_shop_lib/reinforcement_learning/_utils.py +199 -0
- job_shop_lib/visualization/__init__.py +0 -25
- job_shop_lib/visualization/gantt/__init__.py +48 -0
- job_shop_lib/visualization/gantt/_gantt_chart_creator.py +257 -0
- job_shop_lib/visualization/gantt/_gantt_chart_video_and_gif_creation.py +422 -0
- job_shop_lib/visualization/{gantt_chart.py → gantt/_plot_gantt_chart.py} +84 -21
- job_shop_lib/visualization/graphs/__init__.py +29 -0
- job_shop_lib/visualization/graphs/_plot_disjunctive_graph.py +418 -0
- job_shop_lib/visualization/graphs/_plot_resource_task_graph.py +389 -0
- {job_shop_lib-0.5.0.dist-info → job_shop_lib-1.0.0.dist-info}/METADATA +87 -55
- job_shop_lib-1.0.0.dist-info/RECORD +73 -0
- {job_shop_lib-0.5.0.dist-info → job_shop_lib-1.0.0.dist-info}/WHEEL +1 -1
- job_shop_lib/benchmarking/load_benchmark.py +0 -142
- job_shop_lib/cp_sat/__init__.py +0 -5
- job_shop_lib/dispatching/dispatching_rule_solver.py +0 -119
- job_shop_lib/dispatching/factories.py +0 -206
- job_shop_lib/dispatching/feature_observers/composite_feature_observer.py +0 -87
- job_shop_lib/dispatching/feature_observers/earliest_start_time_observer.py +0 -156
- job_shop_lib/dispatching/feature_observers/factory.py +0 -58
- job_shop_lib/dispatching/feature_observers/feature_observer.py +0 -113
- job_shop_lib/dispatching/feature_observers/is_completed_observer.py +0 -98
- job_shop_lib/dispatching/feature_observers/is_ready_observer.py +0 -40
- job_shop_lib/dispatching/pruning_functions.py +0 -116
- job_shop_lib/generators/__init__.py +0 -7
- job_shop_lib/generators/basic_generator.py +0 -197
- job_shop_lib/graphs/constants.py +0 -21
- job_shop_lib/graphs/job_shop_graph.py +0 -202
- job_shop_lib/graphs/node.py +0 -166
- job_shop_lib/operation.py +0 -122
- job_shop_lib/visualization/agent_task_graph.py +0 -257
- job_shop_lib/visualization/create_gif.py +0 -209
- job_shop_lib/visualization/disjunctive_graph.py +0 -210
- job_shop_lib-0.5.0.dist-info/RECORD +0 -48
- {job_shop_lib-0.5.0.dist-info → job_shop_lib-1.0.0.dist-info}/LICENSE +0 -0
@@ -1,25 +0,0 @@
|
|
1
|
-
"""Package for visualization."""
|
2
|
-
|
3
|
-
from job_shop_lib.visualization.gantt_chart import plot_gantt_chart
|
4
|
-
from job_shop_lib.visualization.create_gif import (
|
5
|
-
create_gif,
|
6
|
-
create_gantt_chart_frames,
|
7
|
-
plot_gantt_chart_wrapper,
|
8
|
-
create_gif_from_frames,
|
9
|
-
)
|
10
|
-
from job_shop_lib.visualization.disjunctive_graph import plot_disjunctive_graph
|
11
|
-
from job_shop_lib.visualization.agent_task_graph import (
|
12
|
-
plot_agent_task_graph,
|
13
|
-
three_columns_layout,
|
14
|
-
)
|
15
|
-
|
16
|
-
__all__ = [
|
17
|
-
"plot_gantt_chart",
|
18
|
-
"create_gif",
|
19
|
-
"create_gantt_chart_frames",
|
20
|
-
"plot_gantt_chart_wrapper",
|
21
|
-
"create_gif_from_frames",
|
22
|
-
"plot_disjunctive_graph",
|
23
|
-
"plot_agent_task_graph",
|
24
|
-
"three_columns_layout",
|
25
|
-
]
|
@@ -0,0 +1,48 @@
|
|
1
|
+
"""Contains functions and classes for visualizing job shop scheduling problems.
|
2
|
+
|
3
|
+
.. autosummary::
|
4
|
+
|
5
|
+
plot_gantt_chart
|
6
|
+
get_partial_gantt_chart_plotter
|
7
|
+
PartialGanttChartPlotter
|
8
|
+
create_gantt_chart_video
|
9
|
+
create_gantt_chart_gif
|
10
|
+
GanttChartCreator
|
11
|
+
GifConfig
|
12
|
+
VideoConfig
|
13
|
+
PartialGanttChartPlotterConfig
|
14
|
+
|
15
|
+
"""
|
16
|
+
|
17
|
+
from ._plot_gantt_chart import plot_gantt_chart
|
18
|
+
from ._gantt_chart_video_and_gif_creation import (
|
19
|
+
create_gantt_chart_gif,
|
20
|
+
create_gantt_chart_video,
|
21
|
+
create_gantt_chart_frames,
|
22
|
+
get_partial_gantt_chart_plotter,
|
23
|
+
create_video_from_frames,
|
24
|
+
create_gif_from_frames,
|
25
|
+
PartialGanttChartPlotter,
|
26
|
+
)
|
27
|
+
|
28
|
+
from ._gantt_chart_creator import (
|
29
|
+
GanttChartCreator,
|
30
|
+
PartialGanttChartPlotterConfig,
|
31
|
+
GifConfig,
|
32
|
+
VideoConfig,
|
33
|
+
)
|
34
|
+
|
35
|
+
__all__ = [
|
36
|
+
"plot_gantt_chart",
|
37
|
+
"create_gantt_chart_video",
|
38
|
+
"create_gantt_chart_gif",
|
39
|
+
"create_gantt_chart_frames",
|
40
|
+
"get_partial_gantt_chart_plotter",
|
41
|
+
"create_gif_from_frames",
|
42
|
+
"create_video_from_frames",
|
43
|
+
"GanttChartCreator",
|
44
|
+
"PartialGanttChartPlotterConfig",
|
45
|
+
"GifConfig",
|
46
|
+
"VideoConfig",
|
47
|
+
"PartialGanttChartPlotter",
|
48
|
+
]
|
@@ -0,0 +1,257 @@
|
|
1
|
+
"""Home of the `GanttChartCreator` class and its configuration types."""
|
2
|
+
|
3
|
+
from typing import TypedDict, Optional
|
4
|
+
import matplotlib.pyplot as plt
|
5
|
+
|
6
|
+
from job_shop_lib.dispatching import (
|
7
|
+
Dispatcher,
|
8
|
+
HistoryObserver,
|
9
|
+
)
|
10
|
+
from job_shop_lib.visualization.gantt import (
|
11
|
+
create_gantt_chart_video,
|
12
|
+
get_partial_gantt_chart_plotter,
|
13
|
+
create_gantt_chart_gif,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
class PartialGanttChartPlotterConfig(TypedDict, total=False):
|
18
|
+
"""A dictionary with the configuration for creating the
|
19
|
+
:class:`PartialGanttChartPlotter` function.
|
20
|
+
|
21
|
+
.. seealso::
|
22
|
+
|
23
|
+
- :class:`PartialGanttChartPlotter`
|
24
|
+
- :func:`get_partial_gantt_chart_plotter`
|
25
|
+
"""
|
26
|
+
|
27
|
+
title: Optional[str]
|
28
|
+
"""The title of the Gantt chart."""
|
29
|
+
|
30
|
+
cmap: str
|
31
|
+
"""The colormap to use in the Gantt chart."""
|
32
|
+
|
33
|
+
show_available_operations: bool
|
34
|
+
"""Whether to show available operations in each step."""
|
35
|
+
|
36
|
+
|
37
|
+
class GifConfig(TypedDict, total=False):
|
38
|
+
"""A dictionary with the configuration for creating the GIF using the
|
39
|
+
:func:`create_gantt_chart_gif` function.
|
40
|
+
|
41
|
+
.. seealso::
|
42
|
+
|
43
|
+
:func:`create_gantt_chart_gif`
|
44
|
+
"""
|
45
|
+
|
46
|
+
gif_path: Optional[str]
|
47
|
+
"""The path to save the GIF. It must end with '.gif'."""
|
48
|
+
|
49
|
+
fps: int
|
50
|
+
"""The frames per second of the GIF. Defaults to 1."""
|
51
|
+
|
52
|
+
remove_frames: bool
|
53
|
+
"""Whether to remove the frames after creating the GIF."""
|
54
|
+
|
55
|
+
frames_dir: Optional[str]
|
56
|
+
"""The directory to store the frames."""
|
57
|
+
|
58
|
+
plot_current_time: bool
|
59
|
+
"""Whether to plot the current time in the Gantt chart."""
|
60
|
+
|
61
|
+
|
62
|
+
class VideoConfig(TypedDict, total=False):
|
63
|
+
"""Configuration for creating the video using the
|
64
|
+
:func:`create_gantt_chart_video` function.
|
65
|
+
|
66
|
+
.. seealso::
|
67
|
+
|
68
|
+
:func:`create_gantt_chart_video`
|
69
|
+
"""
|
70
|
+
|
71
|
+
video_path: Optional[str]
|
72
|
+
"""The path to save the video. It must end with a valid video extension
|
73
|
+
(e.g., '.mp4')."""
|
74
|
+
|
75
|
+
fps: int
|
76
|
+
"""The frames per second of the video. Defaults to 1."""
|
77
|
+
|
78
|
+
remove_frames: bool
|
79
|
+
"""Whether to remove the frames after creating the video."""
|
80
|
+
|
81
|
+
frames_dir: Optional[str]
|
82
|
+
"""The directory to store the frames."""
|
83
|
+
|
84
|
+
plot_current_time: bool
|
85
|
+
"""Whether to plot the current time in the Gantt chart."""
|
86
|
+
|
87
|
+
|
88
|
+
class GanttChartCreator:
|
89
|
+
"""Facade class that centralizes the creation of Gantt charts, videos
|
90
|
+
and GIFs.
|
91
|
+
|
92
|
+
It leverages a :class:`HistoryObserver` to keep track of the operations
|
93
|
+
being scheduled and provides methods to plot the current state
|
94
|
+
of the schedule as a Gantt chart and to create a GIF or video that shows
|
95
|
+
the evolution of the schedule over time.
|
96
|
+
|
97
|
+
It adds a new :class:`HistoryObserver` to the dispatcher if it does
|
98
|
+
not have one already. Otherwise, it uses the observer already present.
|
99
|
+
|
100
|
+
Attributes:
|
101
|
+
history_observer:
|
102
|
+
The history observer observing the dispatcher's state.
|
103
|
+
gantt_chart_config:
|
104
|
+
Configuration for plotting the Gantt chart.
|
105
|
+
gif_config:
|
106
|
+
Configuration for creating the GIF.
|
107
|
+
gantt_chart_wrapper_config:
|
108
|
+
Configuration for the Gantt chart wrapper function.
|
109
|
+
video_config:
|
110
|
+
Configuration for creating the video.
|
111
|
+
plot_function:
|
112
|
+
The function used to plot the Gantt chart when creating the GIF
|
113
|
+
or video. Created using the :func:`get_partial_gantt_chart_plotter`
|
114
|
+
function.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
dispatcher:
|
118
|
+
The :class:`Dispatcher` class that will be tracked using a
|
119
|
+
:class:`HistoryObserver`.
|
120
|
+
partial_gantt_chart_plotter_config:
|
121
|
+
Configuration for the Gantt chart wrapper function through the
|
122
|
+
:class:`PartialGanttChartPlotterConfig` class. Defaults to
|
123
|
+
``None``. Valid keys are:
|
124
|
+
|
125
|
+
- title: The title of the Gantt chart.
|
126
|
+
- cmap: The name of the colormap to use.
|
127
|
+
- show_available_operations: Whether to show available
|
128
|
+
operations in each step.
|
129
|
+
|
130
|
+
If ``title`` or ``cmap`` are not provided here and
|
131
|
+
``infer_gantt_chart_config`` is set to ``True``, the values from
|
132
|
+
``gantt_chart_config`` will be used if they are present.
|
133
|
+
|
134
|
+
.. seealso::
|
135
|
+
|
136
|
+
- :class:`PartialGanttChartPlotterConfig`
|
137
|
+
- :func:`get_partial_gantt_chart_plotter`
|
138
|
+
- :class:`PartialGanttChartPlotter`
|
139
|
+
|
140
|
+
gif_config:
|
141
|
+
Configuration for creating the GIF. Defaults to ``None``.
|
142
|
+
Valid keys are:
|
143
|
+
|
144
|
+
- gif_path: The path to save the GIF.
|
145
|
+
- fps: The frames per second of the GIF.
|
146
|
+
- remove_frames: Whether to remove the frames after creating
|
147
|
+
the GIF.
|
148
|
+
- frames_dir: The directory to store the frames.
|
149
|
+
- plot_current_time: Whether to plot the current time in the
|
150
|
+
Gantt chart.
|
151
|
+
video_config:
|
152
|
+
Configuration for creating the video. Defaults to ``None``.
|
153
|
+
Valid keys are:
|
154
|
+
|
155
|
+
- video_path: The path to save the video.
|
156
|
+
- fps: The frames per second of the video.
|
157
|
+
- remove_frames: Whether to remove the frames after creating
|
158
|
+
the video.
|
159
|
+
- frames_dir: The directory to store the frames.
|
160
|
+
- plot_current_time: Whether to plot the current time in the
|
161
|
+
Gantt chart.
|
162
|
+
"""
|
163
|
+
|
164
|
+
def __init__(
|
165
|
+
self,
|
166
|
+
dispatcher: Dispatcher,
|
167
|
+
partial_gantt_chart_plotter_config: Optional[
|
168
|
+
PartialGanttChartPlotterConfig
|
169
|
+
] = None,
|
170
|
+
gif_config: Optional[GifConfig] = None,
|
171
|
+
video_config: Optional[VideoConfig] = None,
|
172
|
+
):
|
173
|
+
if gif_config is None:
|
174
|
+
gif_config = {}
|
175
|
+
if partial_gantt_chart_plotter_config is None:
|
176
|
+
partial_gantt_chart_plotter_config = {}
|
177
|
+
if video_config is None:
|
178
|
+
video_config = {}
|
179
|
+
|
180
|
+
self.gif_config = gif_config
|
181
|
+
self.gannt_chart_wrapper_config = partial_gantt_chart_plotter_config
|
182
|
+
self.video_config = video_config
|
183
|
+
self.history_observer: HistoryObserver = (
|
184
|
+
dispatcher.create_or_get_observer(HistoryObserver)
|
185
|
+
)
|
186
|
+
self.partial_gantt_chart_plotter = get_partial_gantt_chart_plotter(
|
187
|
+
**self.gannt_chart_wrapper_config
|
188
|
+
)
|
189
|
+
|
190
|
+
@property
|
191
|
+
def instance(self):
|
192
|
+
"""The instance being scheduled."""
|
193
|
+
return self.history_observer.dispatcher.instance
|
194
|
+
|
195
|
+
@property
|
196
|
+
def schedule(self):
|
197
|
+
"""The current schedule."""
|
198
|
+
return self.history_observer.dispatcher.schedule
|
199
|
+
|
200
|
+
@property
|
201
|
+
def dispatcher(self):
|
202
|
+
"""The dispatcher being observed."""
|
203
|
+
return self.history_observer.dispatcher
|
204
|
+
|
205
|
+
def plot_gantt_chart(self) -> plt.Figure:
|
206
|
+
"""Plots the current Gantt chart of the schedule.
|
207
|
+
|
208
|
+
Returns:
|
209
|
+
The figure of the plotted Gantt chart.
|
210
|
+
"""
|
211
|
+
a = self.partial_gantt_chart_plotter(
|
212
|
+
self.schedule,
|
213
|
+
None,
|
214
|
+
self.dispatcher.available_operations(),
|
215
|
+
self.dispatcher.current_time(),
|
216
|
+
)
|
217
|
+
return a
|
218
|
+
|
219
|
+
def create_gif(self) -> None:
|
220
|
+
"""Creates a GIF of the schedule being built using the recorded
|
221
|
+
history.
|
222
|
+
|
223
|
+
This method uses the history of scheduled operations recorded by the
|
224
|
+
:class:`HistoryTracker` to create a GIF that shows the progression of
|
225
|
+
the scheduling process.
|
226
|
+
|
227
|
+
The GIF creation process involves:
|
228
|
+
|
229
|
+
- Using the history of scheduled operations to generate frames for
|
230
|
+
each step of the schedule.
|
231
|
+
- Creating a GIF from these frames.
|
232
|
+
- Optionally, removing the frames after the GIF is created.
|
233
|
+
|
234
|
+
The configuration for the GIF creation can be customized through the
|
235
|
+
``gif_config`` attribute.
|
236
|
+
"""
|
237
|
+
create_gantt_chart_gif(
|
238
|
+
instance=self.history_observer.dispatcher.instance,
|
239
|
+
schedule_history=self.history_observer.history,
|
240
|
+
plot_function=self.partial_gantt_chart_plotter,
|
241
|
+
**self.gif_config
|
242
|
+
)
|
243
|
+
|
244
|
+
def create_video(self) -> None:
|
245
|
+
"""Creates a video of the schedule being built using the recorded
|
246
|
+
history.
|
247
|
+
|
248
|
+
This method uses the history of scheduled operations recorded by the
|
249
|
+
:class:`HistoryTracker` to create a video that shows the progression
|
250
|
+
of the scheduling process.
|
251
|
+
"""
|
252
|
+
create_gantt_chart_video(
|
253
|
+
instance=self.history_observer.dispatcher.instance,
|
254
|
+
schedule_history=self.history_observer.history,
|
255
|
+
plot_function=self.partial_gantt_chart_plotter,
|
256
|
+
**self.video_config
|
257
|
+
)
|