job-shop-lib 0.1.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. job_shop_lib-0.1.0/LICENSE +21 -0
  2. job_shop_lib-0.1.0/PKG-INFO +363 -0
  3. job_shop_lib-0.1.0/README.md +341 -0
  4. job_shop_lib-0.1.0/job_shop_lib/__init__.py +20 -0
  5. job_shop_lib-0.1.0/job_shop_lib/base_solver.py +37 -0
  6. job_shop_lib-0.1.0/job_shop_lib/benchmarking/__init__.py +78 -0
  7. job_shop_lib-0.1.0/job_shop_lib/benchmarking/benchmark_instances.json +1 -0
  8. job_shop_lib-0.1.0/job_shop_lib/benchmarking/load_benchmark.py +142 -0
  9. job_shop_lib-0.1.0/job_shop_lib/cp_sat/__init__.py +5 -0
  10. job_shop_lib-0.1.0/job_shop_lib/cp_sat/ortools_solver.py +201 -0
  11. job_shop_lib-0.1.0/job_shop_lib/dispatching/__init__.py +49 -0
  12. job_shop_lib-0.1.0/job_shop_lib/dispatching/dispatcher.py +269 -0
  13. job_shop_lib-0.1.0/job_shop_lib/dispatching/dispatching_rule_solver.py +111 -0
  14. job_shop_lib-0.1.0/job_shop_lib/dispatching/dispatching_rules.py +160 -0
  15. job_shop_lib-0.1.0/job_shop_lib/dispatching/factories.py +206 -0
  16. job_shop_lib-0.1.0/job_shop_lib/dispatching/pruning_functions.py +116 -0
  17. job_shop_lib-0.1.0/job_shop_lib/exceptions.py +26 -0
  18. job_shop_lib-0.1.0/job_shop_lib/generators/__init__.py +7 -0
  19. job_shop_lib-0.1.0/job_shop_lib/generators/basic_generator.py +197 -0
  20. job_shop_lib-0.1.0/job_shop_lib/graphs/__init__.py +52 -0
  21. job_shop_lib-0.1.0/job_shop_lib/graphs/build_agent_task_graph.py +209 -0
  22. job_shop_lib-0.1.0/job_shop_lib/graphs/build_disjunctive_graph.py +78 -0
  23. job_shop_lib-0.1.0/job_shop_lib/graphs/constants.py +21 -0
  24. job_shop_lib-0.1.0/job_shop_lib/graphs/job_shop_graph.py +159 -0
  25. job_shop_lib-0.1.0/job_shop_lib/graphs/node.py +147 -0
  26. job_shop_lib-0.1.0/job_shop_lib/job_shop_instance.py +355 -0
  27. job_shop_lib-0.1.0/job_shop_lib/operation.py +120 -0
  28. job_shop_lib-0.1.0/job_shop_lib/schedule.py +180 -0
  29. job_shop_lib-0.1.0/job_shop_lib/scheduled_operation.py +97 -0
  30. job_shop_lib-0.1.0/job_shop_lib/visualization/__init__.py +25 -0
  31. job_shop_lib-0.1.0/job_shop_lib/visualization/agent_task_graph.py +257 -0
  32. job_shop_lib-0.1.0/job_shop_lib/visualization/create_gif.py +191 -0
  33. job_shop_lib-0.1.0/job_shop_lib/visualization/disjunctive_graph.py +206 -0
  34. job_shop_lib-0.1.0/job_shop_lib/visualization/gantt_chart.py +147 -0
  35. job_shop_lib-0.1.0/pyproject.toml +60 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Pablo Ariño
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,363 @@
1
+ Metadata-Version: 2.1
2
+ Name: job-shop-lib
3
+ Version: 0.1.0
4
+ Summary: An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP)
5
+ License: MIT
6
+ Author: Pabloo22
7
+ Author-email: pablete.arino@gmail.com
8
+ Requires-Python: >=3.10,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Provides-Extra: pygraphviz
15
+ Requires-Dist: imageio (>=2.34.0,<3.0.0)
16
+ Requires-Dist: matplotlib (>=3.8.3,<4.0.0)
17
+ Requires-Dist: networkx (>=3.2.1,<4.0.0)
18
+ Requires-Dist: ortools (>=9.8.3296,<10.0.0)
19
+ Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
20
+ Requires-Dist: pygraphviz (>=1.12,<2.0) ; extra == "pygraphviz"
21
+ Description-Content-Type: text/markdown
22
+
23
+ <div align="center">
24
+
25
+ <img src="images/logo_with_transparent_background.png" height="150px">
26
+
27
+ <h1>Job Shop Library</h1>
28
+
29
+ [![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)
30
+ ![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue)
31
+ [![Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
33
+
34
+ </div>
35
+
36
+
37
+
38
+ An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP) with a special focus on graph representations.
39
+
40
+ It provides intuitive data structures to represent instances and solutions, as well as solvers and visualization tools:
41
+
42
+ ## Quick Start
43
+
44
+ ### Create a Job Shop Instance
45
+
46
+ You can create a Job Shop Instance by defining the jobs and operations. An operation is defined by the machine(s) it is processed on and the duration (processing time).
47
+
48
+ ```python
49
+ from job_shop_lib import JobShopInstance, Operation
50
+
51
+
52
+ job_1 = [Operation(machines=0, duration=1), Operation(1, 1), Operation(2, 7)]
53
+ job_2 = [Operation(1, 5), Operation(2, 1), Operation(0, 1)]
54
+ job_3 = [Operation(2, 1), Operation(0, 3), Operation(1, 2)]
55
+
56
+ jobs = [job_1, job_2, job_3]
57
+
58
+ instance = JobShopInstance(
59
+ jobs,
60
+ name="Example",
61
+ # Any extra parameters are stored inside the
62
+ # metadata attribute as a dictionary:
63
+ lower_bound=7,
64
+ )
65
+ ```
66
+
67
+ ### Load a Benchmark Instance
68
+
69
+ You can load a benchmark instance from the library:
70
+
71
+ ```python
72
+ from job_shop_lib.benchmarking import load_benchmark_instance
73
+
74
+ ft06 = load_benchmark_instance("ft06")
75
+ ```
76
+
77
+ The module `benchmarks` contains functions to load the instances from the file and return them as `JobShopInstance` objects without having to download them
78
+ manually. The instances are stored in [benchmark_instances.json](job_shop_lib/benchmarks/benchmark_instances.json).
79
+
80
+ The contributions to this benchmark dataset are as follows:
81
+
82
+ - `abz5-9`: This subset, comprising five instances, was introduced by Adams et
83
+ al. (1988).
84
+
85
+ - `ft06`, `ft10`, `ft20`: These three instances are attributed to the work of
86
+ Fisher and Thompson, as detailed in their 1963 work.
87
+
88
+ - `la01-40`: A collection of forty instances, this group was contributed by
89
+ Lawrence, as referenced in his 1984 report.
90
+
91
+ - `orb01-10`: Ten instances in this category were provided by Applegate and
92
+ Cook, as seen in their 1991 study.
93
+
94
+ - `swb01-20`: This segment, encompassing twenty instances, was contributed by
95
+ Storer et al., as per their 1992 article.
96
+
97
+ - `yn1-4`: Yamada and Nakano are credited with the addition of four instances
98
+ in this group, as found in their 1992 paper.
99
+
100
+ - `ta01-80`: The largest contribution, consisting of eighty instances, was
101
+ made by Taillard, as documented in his 1993 paper.
102
+
103
+ The metadata from these instances has been updated using data from:
104
+
105
+ Thomas Weise. jsspInstancesAndResults. Accessed in January 2024.
106
+ Available at: https://github.com/thomasWeise/jsspInstancesAndResults
107
+
108
+ It includes the following information:
109
+ - "optimum" (`int` | `None`): The optimal makespan for the instance.
110
+ - "lower_bound" (`int`): The best lower bound known for the makespan. If
111
+ optimality is known, it is equal to the optimum.
112
+ - "upper_bound" (`int`): The best upper bound known for the makespan. If
113
+ optimality is known, it is equal to the optimum.
114
+ - "reference" (`str`): The paper or source where the instance was first
115
+ introduced.
116
+
117
+ ```python
118
+ >>> ft06.metadata
119
+ {'optimum': 55,
120
+ 'upper_bound': 55,
121
+ 'lower_bound': 55,
122
+ 'reference': "J.F. Muth, G.L. Thompson. 'Industrial scheduling.', Englewood Cliffs, NJ, Prentice-Hall, 1963."}
123
+ ```
124
+
125
+ ### Generate a Random Instance
126
+
127
+ You can also generate a random instance with the `InstanceGenerator` class.
128
+
129
+ ```python
130
+ from job_shop_lib.generators import BasicGenerator
131
+
132
+ generator = BasicGenerator(
133
+ duration_range=(5, 10), seed=42, num_jobs=5, num_machines=5
134
+ )
135
+ random_instance = generator.generate()
136
+ ```
137
+
138
+ This class can also work as an iterator to generate multiple instances:
139
+
140
+ ```python
141
+ generator = InstanceGenerator(iteration_limit=100, seed=42)
142
+ instances = []
143
+ for instance in generator:
144
+ instances.append(instance)
145
+
146
+ # Or simply:
147
+ instances = list(generator)
148
+ ```
149
+
150
+ ### Solve an Instance with the OR-Tools' Constraint-Programming SAT Solver
151
+
152
+ Every solver is a `Callable` that receives a `JobShopInstance` and returns a `Schedule` object.
153
+
154
+ ```python
155
+ import matplotlib.pyplot as plt
156
+
157
+ from job_shop_lib.cp_sat import ORToolsSolver
158
+ from job_shop_lib.visualization import plot_gantt_chart
159
+
160
+ solver = ORToolsSolver(max_time_in_seconds=10)
161
+ ft06_schedule = solver(ft06)
162
+
163
+ fig, ax = plot_gantt_chart(ft06_schedule)
164
+ plt.show()
165
+ ```
166
+ ![Example Gannt Chart](images/ft06_solution.png)
167
+
168
+ ### Solve an Instance with a Dispatching Rule Solver
169
+
170
+ A dispatching rule is a heuristic guideline used to prioritize and sequence jobs on various machines. Supported dispatching rules are:
171
+
172
+ ```python
173
+ class DispatchingRule(str, Enum):
174
+ SHORTEST_PROCESSING_TIME = "shortest_processing_time"
175
+ FIRST_COME_FIRST_SERVED = "first_come_first_served"
176
+ MOST_WORK_REMAINING = "most_work_remaining"
177
+ MOST_OPERATION_REMAINING = "most_operation_remaining"
178
+ RANDOM = "random"
179
+ ```
180
+
181
+ We can visualize the solution with a `DispatchingRuleSolver` as a gif:
182
+
183
+ ```python
184
+ from job_shop_lib.visualization import create_gif, get_plot_function
185
+ from job_shop_lib.solvers import DispatchingRuleSolver, DispatchingRule
186
+
187
+ plt.style.use("ggplot")
188
+
189
+ mwkr_solver = DispatchingRuleSolver("most_work_remaining")
190
+ plot_function = get_plot_function(title="Solution with Most Work Remaining Rule")
191
+ create_gif(
192
+ gif_path="ft06_optimized.gif",
193
+ instance=ft06,
194
+ solver=mwkr_solver,
195
+ plot_function=plot_function,
196
+ fps=4,
197
+ )
198
+ ```
199
+
200
+ ![Example Gif](examples/ft06_optimized.gif)
201
+
202
+ The dashed red line represents the current time step, which is computed as the earliest time when the next operation can start.
203
+
204
+ > [!TIP]
205
+ > You can change the style of the gantt chart with `plt.style.use("name-of-the-style")`.
206
+ > Personally, I consider the `ggplot` style to be the cleanest.
207
+
208
+ ### Representing Instances as Graphs
209
+
210
+ One of the main purposes of this library is to provide an easy way to encode instances as graphs. This can be very useful, not only for visualization purposes but also for developing Graph Neural Network-based algorithms.
211
+
212
+ A graph is represented by the `JobShopGraph` class, which internally stores a `networkx.DiGraph` object.
213
+
214
+ #### Disjunctive Graph
215
+
216
+ The disjunctive graph is created by first adding nodes representing each operation in the jobs, along with two special nodes: a source $S$ and a sink $T$. Each operation node is linked to the next operation in its job sequence by **conjunctive edges**, forming a path from the source to the sink. These edges represent the order in which operations of a single job must be performed.
217
+
218
+ Additionally, the graph includes **disjunctive edges** between operations that use the same machine but belong to different jobs. These edges are bidirectional, indicating that either of the connected operations can be performed first. The disjunctive edges thus represent the scheduling choices available: the order in which operations sharing a machine can be processed. Solving the Job Shop Scheduling problem involves choosing a direction for each disjunctive edge such that the overall processing time is minimized.
219
+
220
+ ```python
221
+ from job_shop_lib.visualization import plot_disjunctive_graph
222
+
223
+ fig = plot_disjunctive_graph(instance)
224
+ plt.show()
225
+ ```
226
+
227
+ ![Example Disjunctive Graph](images/example_disjunctive_graph.png)
228
+
229
+
230
+ The `JobShopGraph` class provides easy access to the nodes, for example, to get all the nodes of a specific type:
231
+
232
+ ```python
233
+ from job_shop_lib.graphs import build_disjunctive_graph
234
+
235
+ disjunctive_graph = build_disjunctive_graph(instance)
236
+
237
+ >>> disjunctive_graph.nodes_by_type
238
+ defaultdict(list,
239
+ {<NodeType.OPERATION: 1>: [Node(node_type=OPERATION, value=O(m=0, d=1, j=0, p=0), id=0),
240
+ Node(node_type=OPERATION, value=O(m=1, d=1, j=0, p=1), id=1),
241
+ Node(node_type=OPERATION, value=O(m=2, d=7, j=0, p=2), id=2),
242
+ Node(node_type=OPERATION, value=O(m=1, d=5, j=1, p=0), id=3),
243
+ Node(node_type=OPERATION, value=O(m=2, d=1, j=1, p=1), id=4),
244
+ Node(node_type=OPERATION, value=O(m=0, d=1, j=1, p=2), id=5),
245
+ Node(node_type=OPERATION, value=O(m=2, d=1, j=2, p=0), id=6),
246
+ Node(node_type=OPERATION, value=O(m=0, d=3, j=2, p=1), id=7),
247
+ Node(node_type=OPERATION, value=O(m=1, d=2, j=2, p=2), id=8)],
248
+ <NodeType.SOURCE: 5>: [Node(node_type=SOURCE, value=None, id=9)],
249
+ <NodeType.SINK: 6>: [Node(node_type=SINK, value=None, id=10)]})
250
+ ```
251
+
252
+ Other attributes include:
253
+ - `nodes`: A list of all nodes in the graph.
254
+ - `nodes_by_machine`: A nested list mapping each machine to its associated operation nodes, aiding in machine-specific analysis.
255
+ - `nodes_by_job`: Similar to `nodes_by_machine`, but maps jobs to their operation nodes, useful for job-specific traversal.
256
+
257
+ #### Agent-Task Graph
258
+
259
+ Introduced in the paper "ScheduleNet: Learn to solve multi-agent scheduling problems with reinforcement learning" by [Park et al. (2021)](https://arxiv.org/abs/2106.03051), the Agent-Task Graph is a graph that represents the scheduling problem as a multi-agent reinforcement learning problem.
260
+
261
+ In contrast to the disjunctive graph, instead of connecting operations
262
+ that share the same resources directly by disjunctive edges, operation
263
+ nodes are connected with machine ones.
264
+
265
+ All machine nodes are connected between them, and all operation nodes
266
+ from the same job are connected by non-directed edges too.
267
+
268
+ ```python
269
+ from job_shop_lib.graphs import (
270
+ build_complete_agent_task_graph,
271
+ build_agent_task_graph_with_jobs,
272
+ build_agent_task_graph,
273
+ )
274
+ from job_shop_lib.visualization import plot_agent_task_graph
275
+
276
+ complete_agent_task_graph = build_complete_agent_task_graph(instance)
277
+
278
+ fig = plot_agent_task_graph(complete_agent_task_graph)
279
+ plt.show()
280
+ ```
281
+
282
+ <div align="center">
283
+ <img src="examples/agent_task_graph.png" width="300">
284
+ </div>
285
+ <br>
286
+
287
+ ----
288
+
289
+ For more details, check the [examples](examples) folder.
290
+
291
+ ## Installation
292
+
293
+ In the future, the library will be available on PyPI. For now, you can install it from the source code.
294
+
295
+ ### For development
296
+
297
+ #### With Poetry
298
+
299
+ 1. Clone the repository.
300
+
301
+ 2. Install [poetry](https://python-poetry.org/docs/) if you don't have it already:
302
+ ```bash
303
+ pip install poetry==1.7
304
+ ```
305
+ 3. Create the virtual environment:
306
+ ```bash
307
+ poetry shell
308
+ ```
309
+ 4. Install dependencies:
310
+ ```bash
311
+ poetry install --with notebooks --with test --with lint --all-extras
312
+ ```
313
+ or equivalently:
314
+ ```bash
315
+ make poetry_install_all
316
+ ```
317
+
318
+ #### With PyPI
319
+
320
+ If you don't want to use Poetry, you can install the library directly from the source code:
321
+
322
+ ```bash
323
+ git clone https://github.com/Pabloo22/job_shop_lib.git
324
+ cd job_shop_lib
325
+ pip install -e .
326
+ ```
327
+
328
+ ## License
329
+
330
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
331
+
332
+
333
+ ## References
334
+
335
+ - J. Adams, E. Balas, and D. Zawack, "The shifting bottleneck procedure
336
+ for job shop scheduling," Management Science, vol. 34, no. 3,
337
+ pp. 391–401, 1988.
338
+
339
+ - J.F. Muth and G.L. Thompson, Industrial scheduling. Englewood Cliffs,
340
+ NJ: Prentice-Hall, 1963.
341
+
342
+ - S. Lawrence, "Resource constrained project scheduling: An experimental
343
+ investigation of heuristic scheduling techniques (Supplement),"
344
+ Carnegie-Mellon University, Graduate School of Industrial
345
+ Administration, Pittsburgh, Pennsylvania, 1984.
346
+
347
+ - D. Applegate and W. Cook, "A computational study of job-shop
348
+ scheduling," ORSA Journal on Computer, vol. 3, no. 2, pp. 149–156,
349
+ 1991.
350
+
351
+ - R.H. Storer, S.D. Wu, and R. Vaccari, "New search spaces for
352
+ sequencing problems with applications to job-shop scheduling,"
353
+ Management Science, vol. 38, no. 10, pp. 1495–1509, 1992.
354
+
355
+ - T. Yamada and R. Nakano, "A genetic algorithm applicable to
356
+ large-scale job-shop problems," in Proceedings of the Second
357
+ International Workshop on Parallel Problem Solving from Nature
358
+ (PPSN'2), Brussels, Belgium, pp. 281–290, 1992.
359
+
360
+ - E. Taillard, "Benchmarks for basic scheduling problems," European
361
+ Journal of Operational Research, vol. 64, no. 2, pp. 278–285, 1993.
362
+
363
+ - Park, Junyoung, Sanjar Bakhtiyar, and Jinkyoo Park. "ScheduleNet: Learn to solve multi-agent scheduling problems with reinforcement learning." arXiv preprint arXiv:2106.03051, 2021.