job-shop-lib 0.4.0__py3-none-any.whl → 0.5.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/dispatching/dispatcher.py +219 -51
- job_shop_lib/dispatching/feature_observers/__init__.py +28 -0
- job_shop_lib/dispatching/feature_observers/composite_feature_observer.py +87 -0
- job_shop_lib/dispatching/feature_observers/duration_observer.py +95 -0
- job_shop_lib/dispatching/feature_observers/earliest_start_time_observer.py +156 -0
- job_shop_lib/dispatching/feature_observers/factory.py +58 -0
- job_shop_lib/dispatching/feature_observers/feature_observer.py +113 -0
- job_shop_lib/dispatching/feature_observers/is_completed_observer.py +98 -0
- job_shop_lib/dispatching/feature_observers/is_ready_observer.py +40 -0
- job_shop_lib/dispatching/feature_observers/is_scheduled_observer.py +34 -0
- job_shop_lib/dispatching/feature_observers/position_in_job_observer.py +39 -0
- job_shop_lib/dispatching/feature_observers/remaining_operations_observer.py +54 -0
- job_shop_lib/graphs/build_disjunctive_graph.py +20 -0
- job_shop_lib/job_shop_instance.py +101 -0
- job_shop_lib/visualization/create_gif.py +47 -38
- job_shop_lib/visualization/gantt_chart.py +1 -1
- {job_shop_lib-0.4.0.dist-info → job_shop_lib-0.5.0.dist-info}/METADATA +9 -5
- {job_shop_lib-0.4.0.dist-info → job_shop_lib-0.5.0.dist-info}/RECORD +20 -9
- {job_shop_lib-0.4.0.dist-info → job_shop_lib-0.5.0.dist-info}/LICENSE +0 -0
- {job_shop_lib-0.4.0.dist-info → job_shop_lib-0.5.0.dist-info}/WHEEL +0 -0
@@ -27,7 +27,8 @@ def create_gif(
|
|
27
27
|
instance: JobShopInstance,
|
28
28
|
solver: DispatchingRuleSolver,
|
29
29
|
plot_function: (
|
30
|
-
Callable[[Schedule, int, list[Operation] | None
|
30
|
+
Callable[[Schedule, int, list[Operation] | None, int | None], Figure]
|
31
|
+
| None
|
31
32
|
) = None,
|
32
33
|
fps: int = 1,
|
33
34
|
remove_frames: bool = True,
|
@@ -80,50 +81,59 @@ def plot_gantt_chart_wrapper(
|
|
80
81
|
title: str | None = None,
|
81
82
|
cmap: str = "viridis",
|
82
83
|
show_available_operations: bool = False,
|
83
|
-
) -> Callable[[Schedule, int, list[Operation] | None], Figure]:
|
84
|
+
) -> Callable[[Schedule, int, list[Operation] | None, int | None], Figure]:
|
84
85
|
"""Returns a function that plots a Gantt chart for an unfinished schedule.
|
85
86
|
|
86
87
|
Args:
|
87
88
|
title: The title of the Gantt chart.
|
88
89
|
cmap: The name of the colormap to use.
|
90
|
+
show_available_operations:
|
91
|
+
Whether to show the available operations in the Gantt chart.
|
89
92
|
|
90
93
|
Returns:
|
91
94
|
A function that plots a Gantt chart for a schedule. The function takes
|
92
|
-
|
93
|
-
|
95
|
+
the following arguments:
|
96
|
+
- schedule: The schedule to plot.
|
97
|
+
- makespan: The makespan of the schedule.
|
98
|
+
- available_operations: A list of available operations. If None,
|
99
|
+
the available operations are not shown.
|
100
|
+
- current_time: The current time in the schedule. If provided, a
|
101
|
+
red vertical line is plotted at this time.
|
94
102
|
"""
|
95
103
|
|
96
104
|
def plot_function(
|
97
105
|
schedule: Schedule,
|
98
106
|
makespan: int,
|
99
107
|
available_operations: list | None = None,
|
108
|
+
current_time: int | None = None,
|
100
109
|
) -> Figure:
|
101
110
|
fig, ax = plot_gantt_chart(
|
102
111
|
schedule, title=title, cmap_name=cmap, xlim=makespan
|
103
112
|
)
|
104
113
|
|
105
|
-
if
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
114
|
+
if show_available_operations and available_operations is not None:
|
115
|
+
|
116
|
+
operations_text = "\n".join(
|
117
|
+
str(operation) for operation in available_operations
|
118
|
+
)
|
119
|
+
text = f"Available operations:\n{operations_text}"
|
120
|
+
# Print the available operations at the bottom right corner
|
121
|
+
# of the Gantt chart
|
122
|
+
fig.text(
|
123
|
+
1.25,
|
124
|
+
0.05,
|
125
|
+
text,
|
126
|
+
ha="right",
|
127
|
+
va="bottom",
|
128
|
+
transform=ax.transAxes,
|
129
|
+
bbox={
|
130
|
+
"facecolor": "white",
|
131
|
+
"alpha": 0.5,
|
132
|
+
"boxstyle": "round,pad=0.5",
|
133
|
+
},
|
134
|
+
)
|
135
|
+
if current_time is not None:
|
136
|
+
ax.axvline(current_time, color="red", linestyle="--")
|
127
137
|
return fig
|
128
138
|
|
129
139
|
return plot_function
|
@@ -133,7 +143,9 @@ def create_gantt_chart_frames(
|
|
133
143
|
frames_dir: str,
|
134
144
|
instance: JobShopInstance,
|
135
145
|
solver: DispatchingRuleSolver,
|
136
|
-
plot_function: Callable[
|
146
|
+
plot_function: Callable[
|
147
|
+
[Schedule, int, list[Operation] | None, int | None], Figure
|
148
|
+
],
|
137
149
|
plot_current_time: bool = True,
|
138
150
|
) -> None:
|
139
151
|
"""Creates frames of the Gantt chart for the schedule being built.
|
@@ -150,7 +162,8 @@ def create_gantt_chart_frames(
|
|
150
162
|
should take a `Schedule` object and the makespan of the schedule as
|
151
163
|
input and return a `Figure` object.
|
152
164
|
plot_current_time:
|
153
|
-
Whether to plot a vertical line at the current time.
|
165
|
+
Whether to plot a vertical line at the current time.
|
166
|
+
"""
|
154
167
|
dispatcher = Dispatcher(instance, pruning_function=solver.pruning_function)
|
155
168
|
history_tracker = HistoryTracker(dispatcher)
|
156
169
|
makespan = solver.solve(instance, dispatcher).makespan()
|
@@ -160,23 +173,19 @@ def create_gantt_chart_frames(
|
|
160
173
|
dispatcher.dispatch(
|
161
174
|
scheduled_operation.operation, scheduled_operation.machine_id
|
162
175
|
)
|
176
|
+
current_time = (
|
177
|
+
None if not plot_current_time else dispatcher.current_time()
|
178
|
+
)
|
163
179
|
fig = plot_function(
|
164
180
|
dispatcher.schedule,
|
165
181
|
makespan,
|
166
182
|
dispatcher.available_operations(),
|
183
|
+
current_time,
|
167
184
|
)
|
168
|
-
|
169
|
-
None if not plot_current_time else dispatcher.current_time()
|
170
|
-
)
|
171
|
-
_save_frame(fig, frames_dir, i, current_time)
|
172
|
-
|
185
|
+
_save_frame(fig, frames_dir, i)
|
173
186
|
|
174
|
-
def _save_frame(
|
175
|
-
figure: Figure, frames_dir: str, number: int, current_time: int | None
|
176
|
-
) -> None:
|
177
|
-
if current_time is not None:
|
178
|
-
figure.gca().axvline(current_time, color="red", linestyle="--")
|
179
187
|
|
188
|
+
def _save_frame(figure: Figure, frames_dir: str, number: int) -> None:
|
180
189
|
figure.savefig(f"{frames_dir}/frame_{number:02d}.png", bbox_inches="tight")
|
181
190
|
plt.close(figure)
|
182
191
|
|
@@ -65,7 +65,7 @@ def _plot_machine_schedules(
|
|
65
65
|
) -> dict[int, Patch]:
|
66
66
|
"""Plots the schedules for each machine."""
|
67
67
|
max_job_id = schedule.instance.num_jobs - 1
|
68
|
-
cmap = plt.
|
68
|
+
cmap = plt.get_cmap(cmap_name, max_job_id + 1)
|
69
69
|
norm = Normalize(vmin=0, vmax=max_job_id)
|
70
70
|
legend_handles = {}
|
71
71
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: job-shop-lib
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
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
|
@@ -15,7 +15,8 @@ Provides-Extra: pygraphviz
|
|
15
15
|
Requires-Dist: imageio (>=2,<3)
|
16
16
|
Requires-Dist: matplotlib (>=3,<4)
|
17
17
|
Requires-Dist: networkx (>=3,<4)
|
18
|
-
Requires-Dist:
|
18
|
+
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
19
|
+
Requires-Dist: ortools (>=9.9,<9.10)
|
19
20
|
Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
|
20
21
|
Requires-Dist: pygraphviz (>=1.12,<2.0) ; extra == "pygraphviz"
|
21
22
|
Description-Content-Type: text/markdown
|
@@ -83,7 +84,7 @@ ft06 = load_benchmark_instance("ft06")
|
|
83
84
|
```
|
84
85
|
|
85
86
|
The module `benchmarks` contains functions to load the instances from the file and return them as `JobShopInstance` objects without having to download them
|
86
|
-
manually.
|
87
|
+
manually.
|
87
88
|
|
88
89
|
The contributions to this benchmark dataset are as follows:
|
89
90
|
|
@@ -171,13 +172,15 @@ class DispatchingRule(str, Enum):
|
|
171
172
|
We can visualize the solution with a `DispatchingRuleSolver` as a gif:
|
172
173
|
|
173
174
|
```python
|
174
|
-
from job_shop_lib.visualization import create_gif,
|
175
|
+
from job_shop_lib.visualization import create_gif, plot_gantt_chart_wrapper
|
175
176
|
from job_shop_lib.dispatching import DispatchingRuleSolver, DispatchingRule
|
176
177
|
|
177
178
|
plt.style.use("ggplot")
|
178
179
|
|
179
180
|
mwkr_solver = DispatchingRuleSolver("most_work_remaining")
|
180
|
-
plot_function =
|
181
|
+
plot_function = plot_gantt_chart_wrapper(
|
182
|
+
title="Solution with Most Work Remaining Rule"
|
183
|
+
)
|
181
184
|
create_gif(
|
182
185
|
gif_path="ft06_optimized.gif",
|
183
186
|
instance=ft06,
|
@@ -350,3 +353,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
350
353
|
Journal of Operational Research, vol. 64, no. 2, pp. 278–285, 1993.
|
351
354
|
|
352
355
|
- Park, Junyoung, Sanjar Bakhtiyar, and Jinkyoo Park. "ScheduleNet: Learn to solve multi-agent scheduling problems with reinforcement learning." arXiv preprint arXiv:2106.03051, 2021.
|
356
|
+
|
@@ -6,10 +6,21 @@ job_shop_lib/benchmarking/load_benchmark.py,sha256=CjiSALutgWcfD-SDU6w9WO3udvPVp
|
|
6
6
|
job_shop_lib/cp_sat/__init__.py,sha256=DqrF9IewFMkVB5BhFOHhlJvG6w6BW4ecxBXySunGLoU,97
|
7
7
|
job_shop_lib/cp_sat/ortools_solver.py,sha256=zsISUQy0dQvn7bmUsAQBCe-V92CFskJHkSfngSP4KSg,8130
|
8
8
|
job_shop_lib/dispatching/__init__.py,sha256=xk6NjndZ4-EH5G_fGSEX4LQEXL53TRYn5dKEb5uFggI,1568
|
9
|
-
job_shop_lib/dispatching/dispatcher.py,sha256=
|
9
|
+
job_shop_lib/dispatching/dispatcher.py,sha256=3WdShJtVMP4ZBeoOIegelTXziJLpEjtonAku21yqr20,19299
|
10
10
|
job_shop_lib/dispatching/dispatching_rule_solver.py,sha256=fbNfSclH6Jw1F-QGY1oxAj9wm2hHhJHGnsF2HateXX8,4669
|
11
11
|
job_shop_lib/dispatching/dispatching_rules.py,sha256=SIDkPx_1uTkM0loEqGMqotLBBSaGi1gH0WS85GXrT_I,5557
|
12
12
|
job_shop_lib/dispatching/factories.py,sha256=ldyIbz3QuLuDkrqbgJXV6YoM6AV6CKyHu8z4hXLG2Vo,7267
|
13
|
+
job_shop_lib/dispatching/feature_observers/__init__.py,sha256=j7GXFCKK0mLjGc3M6bw2vePZaLyou_9BUjlHtAMriHc,1023
|
14
|
+
job_shop_lib/dispatching/feature_observers/composite_feature_observer.py,sha256=wLd5yirDekg_pFrBPWIyxKou8htimvKhtDbz0cJ8SKE,3302
|
15
|
+
job_shop_lib/dispatching/feature_observers/duration_observer.py,sha256=EMSfRsWkx94VeOF6v1f2s73hrEQ696vkFoWVVw5tWZ8,3804
|
16
|
+
job_shop_lib/dispatching/feature_observers/earliest_start_time_observer.py,sha256=pKrxaLOPHMnf-eniDhkPWVzzRpKLnpbXAeORqEmsrp0,6296
|
17
|
+
job_shop_lib/dispatching/feature_observers/factory.py,sha256=XF5spNp8T-dnPPnpWQ5dxuG7vrHLf-Wb8MP1tn4_BXA,1941
|
18
|
+
job_shop_lib/dispatching/feature_observers/feature_observer.py,sha256=q2i50LOhgjaQtu_0-3VlSH64uHcf73JddjcGijeKCVk,3646
|
19
|
+
job_shop_lib/dispatching/feature_observers/is_completed_observer.py,sha256=6UCxp-QLXxbw_1nppQJuG_qZZvjtGugYTxQdPTcIcgo,4086
|
20
|
+
job_shop_lib/dispatching/feature_observers/is_ready_observer.py,sha256=km75Pa8vd55grjvr7X-8e0K9vfxVWfms1ea6kAesKLo,1405
|
21
|
+
job_shop_lib/dispatching/feature_observers/is_scheduled_observer.py,sha256=PeLxPVLJX_TP4TG8ViEQFR8WS43wIp6CqyuapM8lIt8,1477
|
22
|
+
job_shop_lib/dispatching/feature_observers/position_in_job_observer.py,sha256=PEC-WwcyeHL8WOACElImDtAAoaf7MroaD9x5QlQddVE,1344
|
23
|
+
job_shop_lib/dispatching/feature_observers/remaining_operations_observer.py,sha256=yVde9gC0cheFNCoPa1lFgGSmzyew-zOGA98nZpBBw1I,1891
|
13
24
|
job_shop_lib/dispatching/history_tracker.py,sha256=3jSh7pKEGiOcEK6bXK8AQJK4NtASxTknRjmHRKenxt8,649
|
14
25
|
job_shop_lib/dispatching/pruning_functions.py,sha256=d94_uBHuESp4NSf_jBk1q8eBCfTPuU9meiL3StiqJiA,4378
|
15
26
|
job_shop_lib/exceptions.py,sha256=0Wla1lK6E2u1o3t2hJj9hUwyoJ-1ebkXd42GdXFAhV0,899
|
@@ -18,20 +29,20 @@ job_shop_lib/generators/basic_generator.py,sha256=pbRDQWC2mnHU0dbc-T8wkdwVeJPlRn
|
|
18
29
|
job_shop_lib/generators/transformations.py,sha256=FI2qHrETATJUrQP3-RYhZAQ5boyEZ0CF2StDbacBej8,5290
|
19
30
|
job_shop_lib/graphs/__init__.py,sha256=mWyF0MypyYfvFhy2F93BJkFIVsxS_0ZqvPuc29B7TJg,1454
|
20
31
|
job_shop_lib/graphs/build_agent_task_graph.py,sha256=ktj-oNLUPmWHfL81EVyaoF4hXClWYfnN7oG2Nn4pOsg,7128
|
21
|
-
job_shop_lib/graphs/build_disjunctive_graph.py,sha256=
|
32
|
+
job_shop_lib/graphs/build_disjunctive_graph.py,sha256=z1jiuTTaWPJZj-vSZdo064quGx4LEDKjtZIb1FieZW4,3705
|
22
33
|
job_shop_lib/graphs/constants.py,sha256=dqPF--okue5sF70Iv-YR14QKFx4pxPwT2dL1Rh5jylM,374
|
23
34
|
job_shop_lib/graphs/job_shop_graph.py,sha256=B0buqcg7US6UvIRWsoY8_FwqzPa_nVjnBu7hPIrygUo,7404
|
24
35
|
job_shop_lib/graphs/node.py,sha256=FrSndtvqgRbN69jIcU6q1TkBh-LOGg8sxxYjDZqCcf4,5613
|
25
|
-
job_shop_lib/job_shop_instance.py,sha256=
|
36
|
+
job_shop_lib/job_shop_instance.py,sha256=awEZ-xKM4yPlD4gE8SdfQdt68CWX_R3IebeVY8ST4bs,16376
|
26
37
|
job_shop_lib/operation.py,sha256=S61x0xgu09JLwrRp7syd1P2psbl0ByGuK_hHoHp4ng8,3916
|
27
38
|
job_shop_lib/schedule.py,sha256=aODGwMv9slFIqOTCz2hF_EIpXhddz8-iAH5gSzGO5G8,10393
|
28
39
|
job_shop_lib/scheduled_operation.py,sha256=qzXzat1dQBbQ-sLyoG1iXbF9eWbdFeZDFjhAFVavHPk,3526
|
29
40
|
job_shop_lib/visualization/__init__.py,sha256=Kxjk3ERYXPAHR72nkD92gFdJltSLA2kxLZrlZzZJS8o,693
|
30
41
|
job_shop_lib/visualization/agent_task_graph.py,sha256=G-c9eiawz6m9sdnDM1r-ZHz6K-gYDIAreHpb6pkYE7w,8284
|
31
|
-
job_shop_lib/visualization/create_gif.py,sha256=
|
42
|
+
job_shop_lib/visualization/create_gif.py,sha256=aUB_2ChyFNo4KuKiQl2ANYmVB5NFcGb7pxKeqr0CVJQ,7186
|
32
43
|
job_shop_lib/visualization/disjunctive_graph.py,sha256=pg4KG9BfQbnBPnXYgbyPGe0AuHSmhYqPeqWYAf_spWQ,5905
|
33
|
-
job_shop_lib/visualization/gantt_chart.py,sha256=
|
34
|
-
job_shop_lib-0.
|
35
|
-
job_shop_lib-0.
|
36
|
-
job_shop_lib-0.
|
37
|
-
job_shop_lib-0.
|
44
|
+
job_shop_lib/visualization/gantt_chart.py,sha256=B9sn4XrEUqgQhRKju-1VUG5R67AZXRu7jbrtA8VcndU,4412
|
45
|
+
job_shop_lib-0.5.0.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
|
46
|
+
job_shop_lib-0.5.0.dist-info/METADATA,sha256=a_AtBz1LwmfrEoIVWXepewPFx2Pa1QiFJt857kCGncw,12582
|
47
|
+
job_shop_lib-0.5.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
48
|
+
job_shop_lib-0.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|