job-shop-lib 1.0.0a1__py3-none-any.whl → 1.0.0a3__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. job_shop_lib/_job_shop_instance.py +18 -20
  2. job_shop_lib/_operation.py +30 -24
  3. job_shop_lib/_schedule.py +17 -16
  4. job_shop_lib/_scheduled_operation.py +10 -12
  5. job_shop_lib/constraint_programming/_ortools_solver.py +31 -16
  6. job_shop_lib/dispatching/__init__.py +4 -0
  7. job_shop_lib/dispatching/_dispatcher.py +24 -32
  8. job_shop_lib/dispatching/_factories.py +8 -0
  9. job_shop_lib/dispatching/_ready_operation_filters.py +80 -0
  10. job_shop_lib/dispatching/feature_observers/__init__.py +34 -2
  11. job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +54 -14
  12. job_shop_lib/dispatching/feature_observers/_duration_observer.py +15 -2
  13. job_shop_lib/dispatching/feature_observers/_earliest_start_time_observer.py +62 -10
  14. job_shop_lib/dispatching/feature_observers/_factory.py +5 -1
  15. job_shop_lib/dispatching/feature_observers/_feature_observer.py +87 -16
  16. job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +32 -2
  17. job_shop_lib/dispatching/feature_observers/_is_ready_observer.py +3 -3
  18. job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py +9 -5
  19. job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py +7 -2
  20. job_shop_lib/dispatching/feature_observers/_remaining_operations_observer.py +1 -1
  21. job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +66 -43
  22. job_shop_lib/dispatching/rules/_dispatching_rules_functions.py +9 -9
  23. job_shop_lib/graphs/__init__.py +2 -0
  24. job_shop_lib/graphs/_build_agent_task_graph.py +2 -2
  25. job_shop_lib/graphs/_constants.py +18 -1
  26. job_shop_lib/graphs/_job_shop_graph.py +36 -20
  27. job_shop_lib/graphs/_node.py +60 -52
  28. job_shop_lib/graphs/graph_updaters/__init__.py +11 -1
  29. job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +1 -1
  30. job_shop_lib/visualization/__init__.py +5 -5
  31. job_shop_lib/visualization/_gantt_chart_creator.py +5 -5
  32. job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py +63 -36
  33. job_shop_lib/visualization/{_gantt_chart.py → _plot_gantt_chart.py} +78 -14
  34. {job_shop_lib-1.0.0a1.dist-info → job_shop_lib-1.0.0a3.dist-info}/METADATA +15 -3
  35. {job_shop_lib-1.0.0a1.dist-info → job_shop_lib-1.0.0a3.dist-info}/RECORD +37 -37
  36. {job_shop_lib-1.0.0a1.dist-info → job_shop_lib-1.0.0a3.dist-info}/WHEEL +1 -1
  37. {job_shop_lib-1.0.0a1.dist-info → job_shop_lib-1.0.0a3.dist-info}/LICENSE +0 -0
@@ -3,8 +3,7 @@
3
3
  import os
4
4
  import pathlib
5
5
  import shutil
6
- from collections.abc import Callable
7
- from typing import Sequence
6
+ from typing import Sequence, Protocol
8
7
 
9
8
  import imageio
10
9
  import matplotlib.pyplot as plt
@@ -23,19 +22,49 @@ from job_shop_lib.dispatching import (
23
22
  HistoryObserver,
24
23
  )
25
24
  from job_shop_lib.dispatching.rules import DispatchingRuleSolver
26
- from job_shop_lib.visualization._gantt_chart import plot_gantt_chart
27
-
25
+ from job_shop_lib.visualization._plot_gantt_chart import plot_gantt_chart
26
+
27
+
28
+ # This class serves as a more meaningful type hint than simply:
29
+ # PlotFunction = Callable[
30
+ # [Schedule, int | None, list[Operation] | None, int | None], Figure
31
+ # ]
32
+ # That's why it doesn't have more methods or attributes. It is a protocol
33
+ # for functions, not for classes.
34
+ # pylint: disable=too-few-public-methods
35
+ class PartialGanttChartPlotter(Protocol):
36
+ """A protocol for a function that plots an uncompleted Gantt chart
37
+ for a schedule.
38
+
39
+ This kind of functions are created using the
40
+ :func:`plot_gantt_chart_wrapper` function.
41
+
42
+ The function should take the following arguments:
43
+
44
+ - schedule: The schedule to plot.
45
+ - makespan: The makespan of the schedule if known. Can be used to fix the
46
+ x-axis limits.
47
+ - available_operations: A list of available operations. If ``None``,
48
+ the available operations are not shown.
49
+ - current_time: The current time in the schedule. If provided, a red
50
+ vertical line is plotted at this time.
51
+ """
28
52
 
29
- PlotFunction = Callable[
30
- [Schedule, int | None, list[Operation] | None, int | None], Figure
31
- ]
53
+ def __call__(
54
+ self,
55
+ schedule: Schedule,
56
+ makespan: int | None = None,
57
+ available_operations: list[Operation] | None = None,
58
+ current_time: int | None = None,
59
+ ) -> Figure:
60
+ pass
32
61
 
33
62
 
34
- def plot_gantt_chart_wrapper(
63
+ def get_partial_gantt_chart_plotter(
35
64
  title: str | None = None,
36
65
  cmap: str = "viridis",
37
66
  show_available_operations: bool = False,
38
- ) -> PlotFunction:
67
+ ) -> PartialGanttChartPlotter:
39
68
  """Returns a function that plots a Gantt chart for an unfinished schedule.
40
69
 
41
70
  Args:
@@ -47,12 +76,13 @@ def plot_gantt_chart_wrapper(
47
76
  Returns:
48
77
  A function that plots a Gantt chart for a schedule. The function takes
49
78
  the following arguments:
79
+
50
80
  - schedule: The schedule to plot.
51
81
  - makespan: The makespan of the schedule.
52
82
  - available_operations: A list of available operations. If None,
53
- the available operations are not shown.
83
+ the available operations are not shown.
54
84
  - current_time: The current time in the schedule. If provided, a
55
- red vertical line is plotted at this time.
85
+ red vertical line is plotted at this time.
56
86
 
57
87
  """
58
88
 
@@ -97,33 +127,30 @@ def plot_gantt_chart_wrapper(
97
127
  # Most of the arguments are optional with default values. There is no way to
98
128
  # reduce the number of arguments without losing functionality.
99
129
  # pylint: disable=too-many-arguments
100
- def create_gif(
101
- gif_path: str | None,
130
+ def create_gantt_chart_gif(
102
131
  instance: JobShopInstance,
132
+ gif_path: str | None = None,
103
133
  solver: DispatchingRuleSolver | None = None,
104
- plot_function: PlotFunction | None = None,
134
+ plot_function: PartialGanttChartPlotter | None = None,
105
135
  fps: int = 1,
106
136
  remove_frames: bool = True,
107
137
  frames_dir: str | None = None,
108
138
  plot_current_time: bool = True,
109
139
  schedule_history: Sequence[ScheduledOperation] | None = None,
110
140
  ) -> None:
111
- """Creates a GIF of the schedule being built by the given solver.
112
-
113
- Deprecated since version 0.6.0: Use `create_gif_or_video` instead.
141
+ """Creates a GIF of the schedule being built.
114
142
 
115
143
  Args:
116
- gif_path:
117
- The path to save the GIF file. It should end with ".gif". If not
118
- provided, the name of the instance is used. It will be made an
119
- optional argument in version 1.0.0.
120
144
  instance:
121
145
  The instance of the job shop problem to be scheduled.
146
+ gif_path:
147
+ The path to save the GIF file. It should end with ".gif". If not
148
+ provided, the name of the instance is used.
122
149
  solver:
123
150
  The dispatching rule solver to use. If not provided, the history
124
151
  of scheduled operations should be provided.
125
152
  plot_function:
126
- A function that plots a Gantt chart for a schedule. It
153
+ A :class:`PlotFunction` that plots a Gantt chart for a schedule. It
127
154
  should take a `Schedule` object and the makespan of the schedule as
128
155
  input and return a `Figure` object. If not provided, a default
129
156
  function is used.
@@ -133,7 +160,7 @@ def create_gif(
133
160
  Whether to remove the frames after creating the GIF.
134
161
  frames_dir:
135
162
  The directory to save the frames in. If not provided,
136
- `gif_path.replace(".gif", "") + "_frames"` is used.
163
+ ``gif_path.replace(".gif", "") + "_frames"`` is used.
137
164
  plot_current_time:
138
165
  Whether to plot a vertical line at the current time.
139
166
  schedule_history:
@@ -144,7 +171,7 @@ def create_gif(
144
171
  gif_path = f"{instance.name}_gantt_chart.gif"
145
172
 
146
173
  if plot_function is None:
147
- plot_function = plot_gantt_chart_wrapper()
174
+ plot_function = get_partial_gantt_chart_plotter()
148
175
 
149
176
  if frames_dir is None:
150
177
  # Use the name of the GIF file as the directory name
@@ -173,14 +200,14 @@ def create_gantt_chart_video(
173
200
  instance: JobShopInstance,
174
201
  video_path: str | None = None,
175
202
  solver: DispatchingRuleSolver | None = None,
176
- plot_function: PlotFunction | None = None,
203
+ plot_function: PartialGanttChartPlotter | None = None,
177
204
  fps: int = 1,
178
205
  remove_frames: bool = True,
179
206
  frames_dir: str | None = None,
180
207
  plot_current_time: bool = True,
181
208
  schedule_history: Sequence[ScheduledOperation] | None = None,
182
209
  ) -> None:
183
- """Creates a GIF of the schedule being built by the given solver.
210
+ """Creates a video of the schedule being built.
184
211
 
185
212
  Args:
186
213
  instance:
@@ -192,16 +219,16 @@ def create_gantt_chart_video(
192
219
  of scheduled operations should be provided.
193
220
  plot_function:
194
221
  A function that plots a Gantt chart for a schedule. It
195
- should take a `Schedule` object and the makespan of the schedule as
196
- input and return a `Figure` object. If not provided, a default
197
- function is used.
222
+ should take a :class:`Schedule` object and the makespan of the
223
+ schedule as input and return a ``Figure`` object. If not provided,
224
+ a default function is used.
198
225
  fps:
199
- The number of frames per second in the GIF.
226
+ The number of frames per second in the video.
200
227
  remove_frames:
201
- Whether to remove the frames after creating the GIF.
228
+ Whether to remove the frames after creating the video.
202
229
  frames_dir:
203
230
  The directory to save the frames in. If not provided,
204
- `name_without_the_extension` + "_frames"` is used.
231
+ ``name_without_the_extension + "_frames"`` is used.
205
232
  plot_current_time:
206
233
  Whether to plot a vertical line at the current time.
207
234
  schedule_history:
@@ -212,7 +239,7 @@ def create_gantt_chart_video(
212
239
  video_path = f"{instance.name}_gantt_chart.mp4"
213
240
 
214
241
  if plot_function is None:
215
- plot_function = plot_gantt_chart_wrapper()
242
+ plot_function = get_partial_gantt_chart_plotter()
216
243
 
217
244
  if frames_dir is None:
218
245
  extension = video_path.split(".")[-1]
@@ -238,7 +265,7 @@ def create_gantt_chart_frames(
238
265
  frames_dir: str,
239
266
  instance: JobShopInstance,
240
267
  solver: DispatchingRuleSolver | None,
241
- plot_function: PlotFunction,
268
+ plot_function: PartialGanttChartPlotter,
242
269
  plot_current_time: bool = True,
243
270
  schedule_history: Sequence[ScheduledOperation] | None = None,
244
271
  ) -> None:
@@ -263,7 +290,7 @@ def create_gantt_chart_frames(
263
290
  """
264
291
  if solver is not None and schedule_history is None:
265
292
  dispatcher = Dispatcher(
266
- instance, ready_operations_filter=solver.pruning_function
293
+ instance, ready_operations_filter=solver.ready_operations_filter
267
294
  )
268
295
  history_tracker = HistoryObserver(dispatcher)
269
296
  makespan = solver.solve(instance, dispatcher).makespan()
@@ -295,7 +322,7 @@ def create_gantt_chart_frames(
295
322
  fig = plot_function(
296
323
  dispatcher.schedule,
297
324
  makespan,
298
- dispatcher.ready_operations(),
325
+ dispatcher.available_operations(),
299
326
  current_time,
300
327
  )
301
328
  _save_frame(fig, frames_dir, i)
@@ -20,16 +20,39 @@ def plot_gantt_chart(
20
20
  cmap_name: str = "viridis",
21
21
  xlim: int | None = None,
22
22
  number_of_x_ticks: int = 15,
23
+ job_labels: None | list[str] = None,
24
+ machine_labels: None | list[str] = None,
25
+ legend_title: str = "",
26
+ x_label: str = "Time units",
27
+ y_label: str = "Machines",
23
28
  ) -> tuple[Figure, plt.Axes]:
24
29
  """Plots a Gantt chart for the schedule.
25
30
 
31
+ This function generates a Gantt chart that visualizes the schedule of jobs
32
+ across multiple machines. Each job is represented with a unique color,
33
+ and operations are plotted as bars on the corresponding machines over time.
34
+
35
+ The Gantt chart helps to understand the flow of jobs on machines and
36
+ visualize the makespan of the schedule, i.e., the time it takes to
37
+ complete all jobs.
38
+
39
+ The Gantt chart includes:
40
+
41
+ - X-axis: Time units, representing the progression of the schedule.
42
+ - Y-axis: Machines, which are assigned jobs at various time slots.
43
+ - Legend: A list of jobs, labeled and color-coded for clarity.
44
+
45
+ .. note::
46
+ The last tick on the x-axis always represents the makespan for easy
47
+ identification of the completion time.
48
+
26
49
  Args:
27
50
  schedule:
28
51
  The schedule to plot.
29
52
  title:
30
53
  The title of the plot. If not provided, the title:
31
- `f"Gantt Chart for {schedule.instance.name} instance"`
32
- is used.
54
+ ``f"Gantt Chart for {schedule.instance.name} instance"``
55
+ is used. To remove the title, provide an empty string.
33
56
  cmap_name:
34
57
  The name of the colormap to use. Default is "viridis".
35
58
  xlim:
@@ -37,21 +60,45 @@ def plot_gantt_chart(
37
60
  the schedule is used.
38
61
  number_of_x_ticks:
39
62
  The number of ticks to use in the x-axis.
63
+ job_labels:
64
+ A list of labels for each job. If ``None``, the labels are
65
+ automatically generated as "Job 0", "Job 1", etc.
66
+ machine_labels:
67
+ A list of labels for each machine. If ``None``, the labels are
68
+ automatically generated as "0", "1", etc.
69
+ legend_title:
70
+ The title of the legend. If not provided, the legend will not have
71
+ a title.
72
+ x_label:
73
+ The label for the x-axis. Default is "Time units". To remove the
74
+ label, provide an empty string.
75
+ y_label:
76
+ The label for the y-axis. Default is "Machines". To remove the
77
+ label, provide an empty string.
78
+
79
+ Returns:
80
+ - A ``matplotlib.figure.Figure`` object.
81
+ - A ``matplotlib.axes.Axes`` object where the Gantt chart is plotted.
40
82
  """
41
- fig, ax = _initialize_plot(schedule, title)
42
- legend_handles = _plot_machine_schedules(schedule, ax, cmap_name)
43
- _configure_legend(ax, legend_handles)
44
- _configure_axes(schedule, ax, xlim, number_of_x_ticks)
83
+ fig, ax = _initialize_plot(schedule, title, x_label, y_label)
84
+ legend_handles = _plot_machine_schedules(
85
+ schedule, ax, cmap_name, job_labels
86
+ )
87
+ _configure_legend(ax, legend_handles, legend_title)
88
+ _configure_axes(schedule, ax, xlim, number_of_x_ticks, machine_labels)
45
89
  return fig, ax
46
90
 
47
91
 
48
92
  def _initialize_plot(
49
- schedule: Schedule, title: str | None
93
+ schedule: Schedule,
94
+ title: str | None,
95
+ x_label: str = "Time units",
96
+ y_label: str = "Machines",
50
97
  ) -> tuple[Figure, plt.Axes]:
51
98
  """Initializes the plot."""
52
99
  fig, ax = plt.subplots()
53
- ax.set_xlabel("Time units")
54
- ax.set_ylabel("Machines")
100
+ ax.set_xlabel(x_label)
101
+ ax.set_ylabel(y_label)
55
102
  ax.grid(True, which="both", axis="x", linestyle="--", linewidth=0.5)
56
103
  ax.yaxis.grid(False)
57
104
  if title is None:
@@ -61,7 +108,10 @@ def _initialize_plot(
61
108
 
62
109
 
63
110
  def _plot_machine_schedules(
64
- schedule: Schedule, ax: plt.Axes, cmap_name: str
111
+ schedule: Schedule,
112
+ ax: plt.Axes,
113
+ cmap_name: str,
114
+ job_labels: list[str] | None,
65
115
  ) -> dict[int, Patch]:
66
116
  """Plots the schedules for each machine."""
67
117
  max_job_id = schedule.instance.num_jobs - 1
@@ -81,12 +131,20 @@ def _plot_machine_schedules(
81
131
  )
82
132
  if scheduled_op.job_id not in legend_handles:
83
133
  legend_handles[scheduled_op.job_id] = Patch(
84
- facecolor=color, label=f"Job {scheduled_op.job_id}"
134
+ facecolor=color,
135
+ label=_get_job_label(job_labels, scheduled_op.job_id),
85
136
  )
86
137
 
87
138
  return legend_handles
88
139
 
89
140
 
141
+ def _get_job_label(job_labels: list[str] | None, job_id: int) -> str:
142
+ """Returns the label for the job."""
143
+ if job_labels is None:
144
+ return f"Job {job_id}"
145
+ return job_labels[job_id]
146
+
147
+
90
148
  def _plot_scheduled_operation(
91
149
  ax: plt.Axes,
92
150
  scheduled_op: ScheduledOperation,
@@ -103,7 +161,9 @@ def _plot_scheduled_operation(
103
161
  )
104
162
 
105
163
 
106
- def _configure_legend(ax: plt.Axes, legend_handles: dict[int, Patch]):
164
+ def _configure_legend(
165
+ ax: plt.Axes, legend_handles: dict[int, Patch], legend_title: str
166
+ ):
107
167
  """Configures the legend for the plot."""
108
168
  sorted_legend_handles = [
109
169
  legend_handles[job_id] for job_id in sorted(legend_handles)
@@ -111,7 +171,8 @@ def _configure_legend(ax: plt.Axes, legend_handles: dict[int, Patch]):
111
171
  ax.legend(
112
172
  handles=sorted_legend_handles,
113
173
  loc="upper left",
114
- bbox_to_anchor=(1.01, 1),
174
+ bbox_to_anchor=(1, 1),
175
+ title=legend_title,
115
176
  )
116
177
 
117
178
 
@@ -120,6 +181,7 @@ def _configure_axes(
120
181
  ax: plt.Axes,
121
182
  xlim: Optional[int],
122
183
  number_of_x_ticks: int,
184
+ machine_labels: list[str] | None,
123
185
  ):
124
186
  """Sets the limits and labels for the axes."""
125
187
  num_machines = len(schedule.schedule)
@@ -132,7 +194,9 @@ def _configure_axes(
132
194
  for i in range(num_machines)
133
195
  ]
134
196
  )
135
- ax.set_yticklabels([str(i) for i in range(num_machines)])
197
+ if machine_labels is None:
198
+ machine_labels = [str(i) for i in range(num_machines)]
199
+ ax.set_yticklabels(machine_labels)
136
200
  makespan = schedule.makespan()
137
201
  xlim = xlim if xlim is not None else makespan
138
202
  ax.set_xlim(0, xlim)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: job-shop-lib
3
- Version: 1.0.0a1
3
+ Version: 1.0.0a3
4
4
  Summary: An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP)
5
5
  License: MIT
6
6
  Author: Pabloo22
@@ -29,6 +29,7 @@ Description-Content-Type: text/markdown
29
29
  <h1>JobShopLib</h1>
30
30
 
31
31
  [![Tests](https://github.com/Pabloo22/job_shop_lib/actions/workflows/tests.yaml/badge.svg)](https://github.com/Pabloo22/job_shop_lib/actions/workflows/tests.yaml)
32
+ [![Documentation Status](https://readthedocs.org/projects/job-shop-lib/badge/?version=latest)](https://job-shop-lib.readthedocs.io/en/latest/?badge=latest)
32
33
  ![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue)
33
34
  [![Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
34
35
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -39,7 +40,7 @@ JobShopLib is a Python package for creating, solving, and visualizing Job Shop S
39
40
 
40
41
  It follows a modular design, allowing users to easily extend the library with new solvers, dispatching rules, visualization functions, etc.
41
42
 
42
- See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
43
+ See the [documentation](https://job-shop-lib.readthedocs.io/en/latest/) for more details about the latest version (1.0.0a2).
43
44
 
44
45
  ## Installation :package:
45
46
 
@@ -47,12 +48,23 @@ See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcoww
47
48
 
48
49
  JobShopLib is distributed on [PyPI](https://pypi.org/project/job-shop-lib/) and it supports Python 3.10+.
49
50
 
50
- You can install the latest version using `pip`:
51
+ You can install the latest stable version (version 0.5.1) using `pip`:
51
52
 
52
53
  ```bash
53
54
  pip install job-shop-lib
54
55
  ```
55
56
 
57
+ See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
58
+
59
+
60
+ Version 1.0.0 is currently in beta stage and can be installed with:
61
+
62
+ ```bash
63
+ pip install job-shop-lib==1.0.0a3
64
+ ```
65
+
66
+ Although this version is not stable and may contain breaking changes in subsequent releases, it is recommended to install it to access the new reinforcement learning environments and familiare yourself with new changes (see the [latest pull requests](https://github.com/Pabloo22/job_shop_lib/pulls?q=is%3Apr+is%3Aclosed)). This version is the first one with a [documentation page](https://job-shop-lib.readthedocs.io/en/latest/).
67
+
56
68
  <!-- end installation -->
57
69
 
58
70
  <!-- key features -->
@@ -1,36 +1,36 @@
1
1
  job_shop_lib/__init__.py,sha256=Ci5ipn-zciO88C5aX5Wx-UN8iBTbpde3dSSg02ZcfwM,597
2
2
  job_shop_lib/_base_solver.py,sha256=p17XmtufNc9Y481cqZUT45pEkUmmW1HWG53dfhIBJH8,1363
3
- job_shop_lib/_job_shop_instance.py,sha256=Q0ml3C36tmcBskBo8MyaZWILJPbdvHjJcvXzD_YfLsU,16475
4
- job_shop_lib/_operation.py,sha256=8Wj8ZLpxmHw4lJJbLCZoTpFhLaap9MSzwOA5VOJQ-DY,3099
5
- job_shop_lib/_schedule.py,sha256=2QjhU21pZr7Gl6qEVJ9kXujx-bSrvaTdyZvjGbrQqzs,11193
6
- job_shop_lib/_scheduled_operation.py,sha256=w7jKhgJ4dQycJ5wSItAd_B9gH5ipcoqy5KxtHFxWTP0,2775
3
+ job_shop_lib/_job_shop_instance.py,sha256=Ubmm10DWO9SmhCOFsvEqeww7XFn-60JWTPDA40FOWZE,16434
4
+ job_shop_lib/_operation.py,sha256=wAYijQtKPPPuXQo9648tYV1GFUU9XGiXIRQgPsCbYtM,3404
5
+ job_shop_lib/_schedule.py,sha256=McDpisMyygxhw349Hxe4N3mCnugr8B5dVNCGN6sSYKg,11371
6
+ job_shop_lib/_scheduled_operation.py,sha256=a1LW2LQvpH1WTxpE2x792_glp5M_gInCf70fuBiheqc,2828
7
7
  job_shop_lib/benchmarking/__init__.py,sha256=BYCrJUNr_uk2c0xIbDt07OnUMhQx8Dudkukx3TFWxgw,3271
8
8
  job_shop_lib/benchmarking/_load_benchmark.py,sha256=-cgyx0Kn6uAc3KdGFSQb6eUVQjQggmpVKOH9qusNkXI,2930
9
9
  job_shop_lib/benchmarking/benchmark_instances.json,sha256=F9EvyzFwVxiKAN6rQTsrMhsKstmyUmroyWduM7a00KQ,464841
10
10
  job_shop_lib/constraint_programming/__init__.py,sha256=kKQRUxxS_nVFUdXGnf4bQOD9mqrXxZZWElS753A4YiA,454
11
- job_shop_lib/constraint_programming/_ortools_solver.py,sha256=U6kkk2pHsAgKLOhEjl6R1FFLy-i5_5sxBHaXezMR1tI,9860
12
- job_shop_lib/dispatching/__init__.py,sha256=QV7qy-y0sSoKp_FslTm7sdqczYzpq0YctzKQ36l0ykg,1510
13
- job_shop_lib/dispatching/_dispatcher.py,sha256=PCSBpYAF6QPXWrjwkBQXTxOdGdq6Y1Uqw8esQTW05TQ,21357
11
+ job_shop_lib/constraint_programming/_ortools_solver.py,sha256=gRoImEBUa8_io-TzbSS-3f0CJ7UwacU5Lrz0bsDqibo,10462
12
+ job_shop_lib/dispatching/__init__.py,sha256=2VQYWNSyuDx3zzrDPCEzs5VJd2AIJvF7vA7LwK5z2V4,1648
13
+ job_shop_lib/dispatching/_dispatcher.py,sha256=o0BqZBub9flPAHX59qBHV2RETQg7n31xHe6owg9Ki7U,21305
14
14
  job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=l_lbaw9JJ5icVOmDAzAL6G5t6wG25bQLpRedN1bys8c,1932
15
- job_shop_lib/dispatching/_factories.py,sha256=UAZLq7d_-puzMYteiAbbhkcW5ucKO-lo3bj8pCCEnOA,4229
15
+ job_shop_lib/dispatching/_factories.py,sha256=MYnjuK9NOVU9n98mrNu5Z0svBIYBCTDbVGzUX9rDWsQ,4594
16
16
  job_shop_lib/dispatching/_history_observer.py,sha256=Vl8rQaxekUeEB-AyNxyC3c76zQakeh-rdri2iDnZvXw,610
17
- job_shop_lib/dispatching/_ready_operation_filters.py,sha256=q8Xv4kp_2GsvEMC5mlTuJXivAz_b8bbrqo5sXaS3PJU,3110
17
+ job_shop_lib/dispatching/_ready_operation_filters.py,sha256=Mywt57h8Nlj6XrptWakVt9n1Tq4jsneZFQEgjLMxJgw,5731
18
18
  job_shop_lib/dispatching/_unscheduled_operations_observer.py,sha256=LNEzqOWqEf6fvtkQrDmDWFEhCfA75OgEtzdomzbxYII,2683
19
- job_shop_lib/dispatching/feature_observers/__init__.py,sha256=oPrhxw65znMhLugMqUD-1swNi8MufejQbHKiMxtgCU0,1103
20
- job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py,sha256=SqZ7Th97p1SkmHz2O_xdPCoqiPNwEs71n_iSkCO3FQM,6397
21
- job_shop_lib/dispatching/feature_observers/_duration_observer.py,sha256=RfWXtxXvS4lakIRWPa1tD0I_UGgb7-h4-tTVvA_x4tA,3490
22
- job_shop_lib/dispatching/feature_observers/_earliest_start_time_observer.py,sha256=iBkfGxG9-peO8shJKTl2P59YFq63aX_Z4XUvOL6m79g,8912
23
- job_shop_lib/dispatching/feature_observers/_factory.py,sha256=3nlLDzdf_UJqmNO1Om69ygxj-9mF4kfPBp0rFFUC_a0,2773
24
- job_shop_lib/dispatching/feature_observers/_feature_observer.py,sha256=N-UhOsw3VbasKucuZlAJyF-k0O7CiwtGFez39xOF66Q,5174
25
- job_shop_lib/dispatching/feature_observers/_is_completed_observer.py,sha256=_ZSmHt1ZtLNXBipaeSOXwgY14WWN3tIm9sx8WY4-zBw,3448
26
- job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=iRr2MsCAglb6dO5fhHKSD7Z2ZHRjYqXK7E8bimAfpOY,1244
27
- job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py,sha256=PeLxPVLJX_TP4TG8ViEQFR8WS43wIp6CqyuapM8lIt8,1477
28
- job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py,sha256=hvztjuajYRx-CnmflWqN4lG06pJelZIRZmarjPK9Afo,1107
29
- job_shop_lib/dispatching/feature_observers/_remaining_operations_observer.py,sha256=kNvRVbxsx5SI2nMc9ZbmcPd5wDaxiljhkXpk6biV2rI,1442
19
+ job_shop_lib/dispatching/feature_observers/__init__.py,sha256=EuJLvSpJpoXUK8A4UuC2k6Mpa293ZR3oCnnvYivIBtU,2240
20
+ job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py,sha256=DOS961MtWaDk2gxjOLA_75SyT6Nmn3IKuNtYO8odk8s,7938
21
+ job_shop_lib/dispatching/feature_observers/_duration_observer.py,sha256=fbkUIVScF1iNjdVCYr1ImQm53TfahvVnGXhsRAsgdzY,4129
22
+ job_shop_lib/dispatching/feature_observers/_earliest_start_time_observer.py,sha256=SOdXs-uzTzcLqOsmpbKvf-OGlGXOMVVJL9zgVVVDvF8,11442
23
+ job_shop_lib/dispatching/feature_observers/_factory.py,sha256=b5YyzdnorijtWUNrYWs4sf-G17eDxw8oYrol1rzMN1Q,2919
24
+ job_shop_lib/dispatching/feature_observers/_feature_observer.py,sha256=crbqG1KrmUOfG4z7shHNzhUg7-uSP4_RWxyOi-RRWmE,8635
25
+ job_shop_lib/dispatching/feature_observers/_is_completed_observer.py,sha256=wKmlASLjodztAB2ypTsi0XFLZ3h1ltzvsa9BpPrbksU,4581
26
+ job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=wy_pA-1wmnzVjhq92mdsT2JJHYbfsm79mcMgSgYUCOs,1264
27
+ job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py,sha256=OcuMUB9_By6ZMtX-1_3z-xaxGbP85a5Zv0ywAv7XxWQ,1491
28
+ job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py,sha256=WRknpQBKXs6h6cXLFJW7ZCvjtU8CPL-iXXNPw3g-mLE,1303
29
+ job_shop_lib/dispatching/feature_observers/_remaining_operations_observer.py,sha256=5V87lCrJUabEe8AkTGXPu5yS8OGxeN8L3-xNyHmdmLs,1441
30
30
  job_shop_lib/dispatching/rules/__init__.py,sha256=p1rkqf66L62uvAOM1ZxNV8xHoh7SuYjHi_8ZNBvPIjg,1450
31
31
  job_shop_lib/dispatching/rules/_dispatching_rule_factory.py,sha256=5fNpv90fAoR6rcE6NeJOWiB7ir-FVnoONIhHtKJ9H0E,2904
32
- job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=r-z3AHwbYNRRnrifoz1gmKASpWqxrUQoxvyfara92KM,5331
33
- job_shop_lib/dispatching/rules/_dispatching_rules_functions.py,sha256=Wb9fQIfePvCJi4RqJ59UrRSnYufgQw5nQ_Am8M6-JOI,7569
32
+ job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=YgcxDUx9RqwfTxWtoKesngYVFDsHiWtsm1BAUrAyerY,6353
33
+ job_shop_lib/dispatching/rules/_dispatching_rules_functions.py,sha256=yRJXYH6QSxDCIK8vqNUfMCMpzWmr3j_camAR72Z6D9Q,7605
34
34
  job_shop_lib/dispatching/rules/_machine_chooser_factory.py,sha256=xsJ8nJwPDBi-sfLJRQF_BBQDbyXDfopD1U-efXffQAE,2331
35
35
  job_shop_lib/dispatching/rules/_utils.py,sha256=X8vET2p1D3RyoB9mFfsfRgmilcTmxPssKYyJQ2zEt0Q,4605
36
36
  job_shop_lib/exceptions.py,sha256=ARzpoZJCvRIvOesCiqqFSRxkv6w9WwEXx0aBP-l2IKA,1597
@@ -38,29 +38,29 @@ job_shop_lib/generation/__init__.py,sha256=hUqjnE0bEoknuUwFoLUWjBH26qTTCGsJAW4gs
38
38
  job_shop_lib/generation/_general_instance_generator.py,sha256=8DG70qT2TUTyPp-3Q1DHWo3DhtUvyB4Yo_u0eAa5CIc,7431
39
39
  job_shop_lib/generation/_instance_generator.py,sha256=fPcbNoyk0t1JtJpBMiwk3SlyPkWYNkYS7-Vs8qH_eDM,4642
40
40
  job_shop_lib/generation/_transformations.py,sha256=FI2qHrETATJUrQP3-RYhZAQ5boyEZ0CF2StDbacBej8,5290
41
- job_shop_lib/graphs/__init__.py,sha256=Kzw__atE5q_bbLf-vDwqya453RP-CfgV7RlURbdOfSc,1646
42
- job_shop_lib/graphs/_build_agent_task_graph.py,sha256=ktj-oNLUPmWHfL81EVyaoF4hXClWYfnN7oG2Nn4pOsg,7128
41
+ job_shop_lib/graphs/__init__.py,sha256=ALZNmvCi5XveMneVJ2VQpQ5msYwIqFWFloiwyFtJhAo,1709
42
+ job_shop_lib/graphs/_build_agent_task_graph.py,sha256=6mvWJ7fFD5CmxkTuXEwY7f_-qxjKdNgFmWk4a4mgiD8,7132
43
43
  job_shop_lib/graphs/_build_disjunctive_graph.py,sha256=z1jiuTTaWPJZj-vSZdo064quGx4LEDKjtZIb1FieZW4,3705
44
- job_shop_lib/graphs/_constants.py,sha256=dqPF--okue5sF70Iv-YR14QKFx4pxPwT2dL1Rh5jylM,374
45
- job_shop_lib/graphs/_job_shop_graph.py,sha256=QmYj-DptmV3Mca0JHplPa1YPt6D4zDSdIwclKK15Ib0,9938
46
- job_shop_lib/graphs/_node.py,sha256=FcV92cH1RK6xv8qK3d4QaCRzB-C2kY0MtVeWNgsdi6U,5769
47
- job_shop_lib/graphs/graph_updaters/__init__.py,sha256=utejVUdKNa3g_6HpfTKanv-9K9sVFlRnqhWpRPGxEHU,358
44
+ job_shop_lib/graphs/_constants.py,sha256=K-GeVvh_DTWpo1KOX1clmxWS_pkUJbq19yOBmrCVIxI,1086
45
+ job_shop_lib/graphs/_job_shop_graph.py,sha256=Fv0TOwtmjqdhH-A_TBH0wSzQkGgqTyc7vvEcfzbQiwA,10681
46
+ job_shop_lib/graphs/_node.py,sha256=hGgdnD9wlsTbkaDizFZMsxPXa2-m91iBNLu0vtkVbxw,6034
47
+ job_shop_lib/graphs/graph_updaters/__init__.py,sha256=UhnZL55e3cAv7hVetB6bRmIOn8BDhG2bsbrdRoHtxLY,516
48
48
  job_shop_lib/graphs/graph_updaters/_graph_updater.py,sha256=H8PtBj4gv6y5wQKOstF2CSnLsFjO1YeVHpzvYK3vMRM,2053
49
49
  job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py,sha256=kPuBmion70-GAQsyFal8gHylHvZSoBJae9eF8iGOkvA,6097
50
50
  job_shop_lib/graphs/graph_updaters/_utils.py,sha256=X5YfwJA1CCgpm1r9C036Gal2CkDh2SSak7wl7TbdjHw,704
51
51
  job_shop_lib/reinforcement_learning/__init__.py,sha256=QVFo9e1X-tpanZkGdcCPV_WobQ2EZ_y5uoYSJ36XrQI,957
52
52
  job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py,sha256=jKMcWYBvz1kwlw00Xe1x9HqhFkMMqlh-Y95NmeBL3-0,15129
53
53
  job_shop_lib/reinforcement_learning/_reward_observers.py,sha256=4Kdyn9Jlp_1sBtVr6raF-ZFtcnKxwyCLykfX53TmuhU,2959
54
- job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py,sha256=Kbd3N1rKcXm6IHTo99En-oX85vqVobv2bFBCyAht2mE,12949
54
+ job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py,sha256=ByQQ1fCCpji0VAjKTcbBOGST-3MF6oq2naAtdElJUh8,12953
55
55
  job_shop_lib/reinforcement_learning/_types_and_constants.py,sha256=CY849lbv6UXy40KRcMJT3WxvGWrLqcfysu65LPkTfg8,1715
56
56
  job_shop_lib/reinforcement_learning/_utils.py,sha256=ilI089Bs8CRlfRV_yH6XH8oypTDtRa7hS-H4iRCC5lU,2497
57
- job_shop_lib/visualization/__init__.py,sha256=jXC188u5AnSWcO1lRZEzZAPZTXbqlYSPhYc7LMc0itU,1094
57
+ job_shop_lib/visualization/__init__.py,sha256=SVxg7Dt3azETfI0IvUtLtCBsirXQWirdjEjOQ2d5eWU,1137
58
58
  job_shop_lib/visualization/_agent_task_graph.py,sha256=AaBTD_S34WjrsZnL_iMAplR_f67RahZi7x58SOvp-q0,8834
59
59
  job_shop_lib/visualization/_disjunctive_graph.py,sha256=pg4KG9BfQbnBPnXYgbyPGe0AuHSmhYqPeqWYAf_spWQ,5905
60
- job_shop_lib/visualization/_gantt_chart.py,sha256=B9sn4XrEUqgQhRKju-1VUG5R67AZXRu7jbrtA8VcndU,4412
61
- job_shop_lib/visualization/_gantt_chart_creator.py,sha256=qFhCfk3oC3uF7Mau3lrNhH-34sfHXvkqEXbsDzrIbBk,7721
62
- job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py,sha256=XXRLpC05E3zY4SIytdFP2QuxmGA95VohUVmzoFzEt7Q,13206
63
- job_shop_lib-1.0.0a1.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
64
- job_shop_lib-1.0.0a1.dist-info/METADATA,sha256=h5mdFHRaXbnL7F4lMjGNVE5-TSx35rvAG8SlzX3wWiU,14810
65
- job_shop_lib-1.0.0a1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
66
- job_shop_lib-1.0.0a1.dist-info/RECORD,,
60
+ job_shop_lib/visualization/_gantt_chart_creator.py,sha256=xw7lfd1HIm7r5j2kDxgBdrgSickCslpUcm7QFrNXmtg,7763
61
+ job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py,sha256=IpKe2oZbrW4fvsdnRtuFWfXN-FdfwkYVdTAq3av9mKE,14249
62
+ job_shop_lib/visualization/_plot_gantt_chart.py,sha256=1WCJ5Gjl3dwA-w4Jn9suIg-ZGR28yYUAy8Jp-IiyvfI,6842
63
+ job_shop_lib-1.0.0a3.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
64
+ job_shop_lib-1.0.0a3.dist-info/METADATA,sha256=fJ7RYm8yUkmZvG5moRO5QUVDw0_ACIcqb7gxiuqLrQo,15663
65
+ job_shop_lib-1.0.0a3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
+ job_shop_lib-1.0.0a3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any