job-shop-lib 0.5.1__tar.gz → 1.0.0a2__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/PKG-INFO +68 -44
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/README.md +65 -42
- job_shop_lib-1.0.0a2/job_shop_lib/__init__.py +29 -0
- job_shop_lib-0.5.1/job_shop_lib/base_solver.py → job_shop_lib-1.0.0a2/job_shop_lib/_base_solver.py +1 -1
- job_shop_lib-0.5.1/job_shop_lib/job_shop_instance.py → job_shop_lib-1.0.0a2/job_shop_lib/_job_shop_instance.py +9 -4
- job_shop_lib-1.0.0a2/job_shop_lib/_operation.py +99 -0
- job_shop_lib-0.5.1/job_shop_lib/schedule.py → job_shop_lib-1.0.0a2/job_shop_lib/_schedule.py +86 -66
- job_shop_lib-0.5.1/job_shop_lib/scheduled_operation.py → job_shop_lib-1.0.0a2/job_shop_lib/_scheduled_operation.py +19 -45
- job_shop_lib-1.0.0a2/job_shop_lib/benchmarking/__init__.py +101 -0
- job_shop_lib-1.0.0a2/job_shop_lib/benchmarking/_load_benchmark.py +88 -0
- job_shop_lib-1.0.0a2/job_shop_lib/constraint_programming/__init__.py +13 -0
- job_shop_lib-0.5.1/job_shop_lib/cp_sat/ortools_solver.py → job_shop_lib-1.0.0a2/job_shop_lib/constraint_programming/_ortools_solver.py +72 -18
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/__init__.py +56 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/dispatcher.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_dispatcher.py +153 -80
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_dispatcher_observer_config.py +54 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_factories.py +125 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/history_tracker.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_history_observer.py +4 -6
- job_shop_lib-0.5.1/job_shop_lib/dispatching/pruning_functions.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_ready_operation_filters.py +6 -35
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/_unscheduled_operations_observer.py +69 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/__init__.py +66 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +209 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/duration_observer.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_duration_observer.py +20 -18
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_earliest_start_time_observer.py +287 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/factory.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_factory.py +35 -5
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_feature_observer.py +227 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +127 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_is_ready_observer.py +33 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/is_scheduled_observer.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py +9 -5
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/position_in_job_observer.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py +8 -10
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/remaining_operations_observer.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/feature_observers/_remaining_operations_observer.py +8 -26
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/__init__.py +51 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/_dispatching_rule_factory.py +82 -0
- job_shop_lib-0.5.1/job_shop_lib/dispatching/dispatching_rule_solver.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +58 -25
- job_shop_lib-0.5.1/job_shop_lib/dispatching/dispatching_rules.py → job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/_dispatching_rules_functions.py +74 -21
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/_machine_chooser_factory.py +69 -0
- job_shop_lib-1.0.0a2/job_shop_lib/dispatching/rules/_utils.py +127 -0
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/job_shop_lib/exceptions.py +18 -0
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/job_shop_lib/generation/__init__.py +2 -2
- job_shop_lib-0.5.1/job_shop_lib/generation/general_instance_generator.py → job_shop_lib-1.0.0a2/job_shop_lib/generation/_general_instance_generator.py +26 -7
- job_shop_lib-0.5.1/job_shop_lib/generation/instance_generator.py → job_shop_lib-1.0.0a2/job_shop_lib/generation/_instance_generator.py +13 -3
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/job_shop_lib/graphs/__init__.py +19 -6
- job_shop_lib-0.5.1/job_shop_lib/graphs/build_agent_task_graph.py → job_shop_lib-1.0.0a2/job_shop_lib/graphs/_build_agent_task_graph.py +2 -2
- job_shop_lib-1.0.0a2/job_shop_lib/graphs/_constants.py +38 -0
- job_shop_lib-0.5.1/job_shop_lib/graphs/job_shop_graph.py → job_shop_lib-1.0.0a2/job_shop_lib/graphs/_job_shop_graph.py +117 -22
- job_shop_lib-0.5.1/job_shop_lib/graphs/node.py → job_shop_lib-1.0.0a2/job_shop_lib/graphs/_node.py +74 -60
- job_shop_lib-1.0.0a2/job_shop_lib/graphs/graph_updaters/__init__.py +23 -0
- job_shop_lib-1.0.0a2/job_shop_lib/graphs/graph_updaters/_graph_updater.py +59 -0
- job_shop_lib-1.0.0a2/job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py +154 -0
- job_shop_lib-1.0.0a2/job_shop_lib/graphs/graph_updaters/_utils.py +25 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/__init__.py +41 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py +366 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/_reward_observers.py +85 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +337 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/_types_and_constants.py +61 -0
- job_shop_lib-1.0.0a2/job_shop_lib/reinforcement_learning/_utils.py +96 -0
- job_shop_lib-1.0.0a2/job_shop_lib/visualization/__init__.py +41 -0
- job_shop_lib-0.5.1/job_shop_lib/visualization/agent_task_graph.py → job_shop_lib-1.0.0a2/job_shop_lib/visualization/_agent_task_graph.py +28 -9
- job_shop_lib-1.0.0a2/job_shop_lib/visualization/_gantt_chart_creator.py +219 -0
- job_shop_lib-1.0.0a2/job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py +388 -0
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/pyproject.toml +22 -3
- job_shop_lib-0.5.1/job_shop_lib/__init__.py +0 -21
- job_shop_lib-0.5.1/job_shop_lib/benchmarking/__init__.py +0 -78
- job_shop_lib-0.5.1/job_shop_lib/benchmarking/load_benchmark.py +0 -142
- job_shop_lib-0.5.1/job_shop_lib/cp_sat/__init__.py +0 -5
- job_shop_lib-0.5.1/job_shop_lib/dispatching/__init__.py +0 -52
- job_shop_lib-0.5.1/job_shop_lib/dispatching/factories.py +0 -206
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/__init__.py +0 -28
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/composite_feature_observer.py +0 -87
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/earliest_start_time_observer.py +0 -156
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/feature_observer.py +0 -113
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/is_completed_observer.py +0 -98
- job_shop_lib-0.5.1/job_shop_lib/dispatching/feature_observers/is_ready_observer.py +0 -40
- job_shop_lib-0.5.1/job_shop_lib/generators/__init__.py +0 -8
- job_shop_lib-0.5.1/job_shop_lib/generators/basic_generator.py +0 -200
- job_shop_lib-0.5.1/job_shop_lib/generators/transformations.py +0 -164
- job_shop_lib-0.5.1/job_shop_lib/graphs/constants.py +0 -21
- job_shop_lib-0.5.1/job_shop_lib/operation.py +0 -122
- job_shop_lib-0.5.1/job_shop_lib/visualization/__init__.py +0 -25
- job_shop_lib-0.5.1/job_shop_lib/visualization/create_gif.py +0 -209
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/LICENSE +0 -0
- {job_shop_lib-0.5.1 → job_shop_lib-1.0.0a2}/job_shop_lib/benchmarking/benchmark_instances.json +0 -0
- /job_shop_lib-0.5.1/job_shop_lib/generation/transformations.py → /job_shop_lib-1.0.0a2/job_shop_lib/generation/_transformations.py +0 -0
- /job_shop_lib-0.5.1/job_shop_lib/graphs/build_disjunctive_graph.py → /job_shop_lib-1.0.0a2/job_shop_lib/graphs/_build_disjunctive_graph.py +0 -0
- /job_shop_lib-0.5.1/job_shop_lib/visualization/disjunctive_graph.py → /job_shop_lib-1.0.0a2/job_shop_lib/visualization/_disjunctive_graph.py +0 -0
- /job_shop_lib-0.5.1/job_shop_lib/visualization/gantt_chart.py → /job_shop_lib-1.0.0a2/job_shop_lib/visualization/_gantt_chart.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: job-shop-lib
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0a2
|
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
|
@@ -12,7 +12,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
14
14
|
Provides-Extra: pygraphviz
|
15
|
-
Requires-Dist:
|
15
|
+
Requires-Dist: gymnasium (>=0.29.1,<0.30.0)
|
16
|
+
Requires-Dist: imageio[ffmpeg] (>=2.34.1,<3.0.0)
|
16
17
|
Requires-Dist: matplotlib (>=3,<4)
|
17
18
|
Requires-Dist: networkx (>=3,<4)
|
18
19
|
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
@@ -23,9 +24,9 @@ Description-Content-Type: text/markdown
|
|
23
24
|
|
24
25
|
<div align="center">
|
25
26
|
|
26
|
-
<img src="images/
|
27
|
+
<img src="docs/source/images/jslib_minimalist_logo_no_background_fixed.png" height="150px">
|
27
28
|
|
28
|
-
<h1>
|
29
|
+
<h1>JobShopLib</h1>
|
29
30
|
|
30
31
|
[](https://github.com/Pabloo22/job_shop_lib/actions/workflows/tests.yaml)
|
31
32
|

|
@@ -34,25 +35,57 @@ Description-Content-Type: text/markdown
|
|
34
35
|
|
35
36
|
</div>
|
36
37
|
|
37
|
-
|
38
|
+
JobShopLib is a Python package for creating, solving, and visualizing Job Shop Scheduling Problems (JSSP).
|
38
39
|
|
39
|
-
It
|
40
|
+
It follows a modular design, allowing users to easily extend the library with new solvers, dispatching rules, visualization functions, etc.
|
40
41
|
|
41
|
-
See
|
42
|
+
See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
|
42
43
|
|
43
|
-
## Installation
|
44
|
+
## Installation :package:
|
44
45
|
|
45
|
-
|
46
|
+
<!-- start installation -->
|
47
|
+
|
48
|
+
JobShopLib is distributed on [PyPI](https://pypi.org/project/job-shop-lib/) and it supports Python 3.10+.
|
49
|
+
|
50
|
+
You can install the latest version using `pip`:
|
46
51
|
|
47
52
|
```bash
|
48
53
|
pip install job-shop-lib
|
49
54
|
```
|
50
55
|
|
51
|
-
|
56
|
+
<!-- end installation -->
|
57
|
+
|
58
|
+
<!-- key features -->
|
59
|
+
|
60
|
+
## Key Features :star:
|
61
|
+
|
62
|
+
- **Data Structures**: Easily create, manage, and manipulate job shop instances and solutions with user-friendly data structures. See [Getting Started](docs/source/examples/00-Getting-Started.ipynb) and [How Solutions are Represented](docs/source/examples/01-How-Solutions-are-Represented.ipynb).
|
63
|
+
|
64
|
+
- **Benchmark Instances**: Load well-known benchmark instances directly from the library without manual downloading. See [Load Benchmark Instances](docs/source/examples/05-Load-Benchmark-Instances.ipynb).
|
65
|
+
|
66
|
+
- **Random Instance Generation**: Create random instances with customizable sizes and properties or augment existing ones. See [`generation`](job_shop_lib/generation) package.
|
67
|
+
|
68
|
+
- **Multiple Solvers**:
|
69
|
+
- **Constraint Programming Solver**: OR-Tools' CP-SAT solver. See [Solving the Problem](docs/source/examples/02-Solving-the-Problem.ipynb).
|
70
|
+
|
71
|
+
- **Dispatching Rule Solvers**: Use any of the available dispatching rules or create custom ones. See [Dispatching Rules](docs/source/examples/03-Dispatching-Rules.ipynb).
|
72
|
+
|
73
|
+
- **Gantt Charts**: Visualize final schedules and how are they created iteratively by dispatching rule solvers or sequences of scheduling decisions with GIFs or videos. See [Save Gif](docs/source/examples/06-Save-Gif.ipynb).
|
74
|
+
|
75
|
+
- **Graph Representations**:
|
76
|
+
- **Disjunctive Graphs**: Represent and visualize instances as disjunctive graphs. See [Disjunctive Graph](docs/source/examples/04-Disjunctive-Graph.ipynb).
|
77
|
+
- **Agent-Task Graphs**: Encode instances as agent-task graphs (introduced in [ScheduleNet paper](https://arxiv.org/abs/2106.03051)). See [Agent-Task Graph](docs/source/examples/07-Agent-Task-Graph.ipynb).
|
78
|
+
- Build your own custom graphs with the `JobShopGraph` class.
|
79
|
+
|
80
|
+
- **Gymnasium Environments**: Two environments for solving the problem with Graph Neural Networks (GNNs) or any other method, and Reinforcement Learning (RL). See [SingleJobShopGraphEnv](docs/source/examples/09-SingleJobShopGraphEnv.ipynb) and [MultiJobShopGraphEnv](examples/10-MultiJobShopGraphEnv.ipynb).
|
81
|
+
|
82
|
+
<!-- end key features -->
|
83
|
+
|
84
|
+
## Some Examples :rocket:
|
52
85
|
|
53
86
|
### Create a Job Shop Instance
|
54
87
|
|
55
|
-
You can create a
|
88
|
+
You can create a `JobShopInstance` by defining the jobs and operations. An operation is defined by the machine(s) it is processed on and the duration (processing time).
|
56
89
|
|
57
90
|
```python
|
58
91
|
from job_shop_lib import JobShopInstance, Operation
|
@@ -83,7 +116,7 @@ from job_shop_lib.benchmarking import load_benchmark_instance
|
|
83
116
|
ft06 = load_benchmark_instance("ft06")
|
84
117
|
```
|
85
118
|
|
86
|
-
The module `
|
119
|
+
The module `benchmarking` contains functions to load the instances from the file and return them as `JobShopInstance` objects without having to download them
|
87
120
|
manually.
|
88
121
|
|
89
122
|
The contributions to this benchmark dataset are as follows:
|
@@ -115,12 +148,12 @@ https://github.com/thomasWeise/jsspInstancesAndResults
|
|
115
148
|
|
116
149
|
### Generate a Random Instance
|
117
150
|
|
118
|
-
You can also generate a random instance with the `
|
151
|
+
You can also generate a random instance with the `GeneralInstanceGenerator` class.
|
119
152
|
|
120
153
|
```python
|
121
|
-
from job_shop_lib.
|
154
|
+
from job_shop_lib.generation import GeneralInstanceGenerator
|
122
155
|
|
123
|
-
generator =
|
156
|
+
generator = GeneralInstanceGenerator(
|
124
157
|
duration_range=(5, 10), seed=42, num_jobs=5, num_machines=5
|
125
158
|
)
|
126
159
|
random_instance = generator.generate()
|
@@ -129,7 +162,7 @@ random_instance = generator.generate()
|
|
129
162
|
This class can also work as an iterator to generate multiple instances:
|
130
163
|
|
131
164
|
```python
|
132
|
-
generator =
|
165
|
+
generator = GeneralInstanceGenerator(iteration_limit=100, seed=42)
|
133
166
|
instances = []
|
134
167
|
for instance in generator:
|
135
168
|
instances.append(instance)
|
@@ -145,7 +178,7 @@ Every solver is a `Callable` that receives a `JobShopInstance` and returns a `Sc
|
|
145
178
|
```python
|
146
179
|
import matplotlib.pyplot as plt
|
147
180
|
|
148
|
-
from job_shop_lib.
|
181
|
+
from job_shop_lib.constraint_programming import ORToolsSolver
|
149
182
|
from job_shop_lib.visualization import plot_gantt_chart
|
150
183
|
|
151
184
|
solver = ORToolsSolver(max_time_in_seconds=10)
|
@@ -154,7 +187,7 @@ ft06_schedule = solver(ft06)
|
|
154
187
|
fig, ax = plot_gantt_chart(ft06_schedule)
|
155
188
|
plt.show()
|
156
189
|
```
|
157
|
-

|
190
|
+

|
158
191
|
|
159
192
|
### Solve an Instance with a Dispatching Rule Solver
|
160
193
|
|
@@ -190,7 +223,7 @@ create_gif(
|
|
190
223
|
)
|
191
224
|
```
|
192
225
|
|
193
|
-

|
226
|
+

|
194
227
|
|
195
228
|
The dashed red line represents the current time step, which is computed as the earliest time when the next operation can start.
|
196
229
|
|
@@ -217,11 +250,11 @@ fig = plot_disjunctive_graph(instance)
|
|
217
250
|
plt.show()
|
218
251
|
```
|
219
252
|
|
220
|
-

|
253
|
+

|
221
254
|
|
222
255
|
|
223
|
-
> [!
|
224
|
-
>
|
256
|
+
> [!TIP]
|
257
|
+
> Installing the optional dependency [PyGraphViz](https://pygraphviz.github.io/) is recommended.
|
225
258
|
|
226
259
|
The `JobShopGraph` class provides easy access to the nodes, for example, to get all the nodes of a specific type:
|
227
260
|
|
@@ -276,7 +309,7 @@ plt.show()
|
|
276
309
|
```
|
277
310
|
|
278
311
|
<div align="center">
|
279
|
-
<img src="
|
312
|
+
<img src="docs/source/images/agent_task_graph.png" width="300">
|
280
313
|
</div>
|
281
314
|
<br>
|
282
315
|
|
@@ -286,43 +319,34 @@ For more details, check the [examples](examples) folder.
|
|
286
319
|
|
287
320
|
## Installation for development
|
288
321
|
|
289
|
-
|
322
|
+
<!-- start installation development -->
|
290
323
|
|
291
324
|
1. Clone the repository.
|
292
325
|
|
293
|
-
2. Install [poetry](https://python-poetry.org/docs/) if you don't have it already:
|
294
|
-
```bash
|
295
|
-
pip install poetry==1.7
|
296
|
-
```
|
297
|
-
3. Create the virtual environment:
|
298
326
|
```bash
|
299
|
-
|
327
|
+
git clone https://github.com/Pabloo22/job_shop_lib.git
|
328
|
+
cd job_shop_lib
|
300
329
|
```
|
301
|
-
|
330
|
+
|
331
|
+
2. Install [poetry](https://python-poetry.org/docs/) if you don't have it already:
|
332
|
+
|
302
333
|
```bash
|
303
|
-
|
334
|
+
pip install poetry
|
304
335
|
```
|
305
|
-
|
336
|
+
|
337
|
+
3. Install dependencies:
|
306
338
|
```bash
|
307
339
|
make poetry_install_all
|
308
340
|
```
|
309
341
|
|
310
|
-
|
311
|
-
|
312
|
-
If you don't want to use Poetry, you can install the library directly from the source code:
|
313
|
-
|
314
|
-
```bash
|
315
|
-
git clone https://github.com/Pabloo22/job_shop_lib.git
|
316
|
-
cd job_shop_lib
|
317
|
-
pip install -e .
|
318
|
-
```
|
342
|
+
<!-- end installation development -->
|
319
343
|
|
320
|
-
## License
|
344
|
+
## License :scroll:
|
321
345
|
|
322
346
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
323
347
|
|
324
348
|
|
325
|
-
## References
|
349
|
+
## References :books:
|
326
350
|
|
327
351
|
- J. Adams, E. Balas, and D. Zawack, "The shifting bottleneck procedure
|
328
352
|
for job shop scheduling," Management Science, vol. 34, no. 3,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<div align="center">
|
2
2
|
|
3
|
-
<img src="images/
|
3
|
+
<img src="docs/source/images/jslib_minimalist_logo_no_background_fixed.png" height="150px">
|
4
4
|
|
5
|
-
<h1>
|
5
|
+
<h1>JobShopLib</h1>
|
6
6
|
|
7
7
|
[](https://github.com/Pabloo22/job_shop_lib/actions/workflows/tests.yaml)
|
8
8
|

|
@@ -11,25 +11,57 @@
|
|
11
11
|
|
12
12
|
</div>
|
13
13
|
|
14
|
-
|
14
|
+
JobShopLib is a Python package for creating, solving, and visualizing Job Shop Scheduling Problems (JSSP).
|
15
15
|
|
16
|
-
It
|
16
|
+
It follows a modular design, allowing users to easily extend the library with new solvers, dispatching rules, visualization functions, etc.
|
17
17
|
|
18
|
-
See
|
18
|
+
See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
|
19
19
|
|
20
|
-
## Installation
|
20
|
+
## Installation :package:
|
21
21
|
|
22
|
-
|
22
|
+
<!-- start installation -->
|
23
|
+
|
24
|
+
JobShopLib is distributed on [PyPI](https://pypi.org/project/job-shop-lib/) and it supports Python 3.10+.
|
25
|
+
|
26
|
+
You can install the latest version using `pip`:
|
23
27
|
|
24
28
|
```bash
|
25
29
|
pip install job-shop-lib
|
26
30
|
```
|
27
31
|
|
28
|
-
|
32
|
+
<!-- end installation -->
|
33
|
+
|
34
|
+
<!-- key features -->
|
35
|
+
|
36
|
+
## Key Features :star:
|
37
|
+
|
38
|
+
- **Data Structures**: Easily create, manage, and manipulate job shop instances and solutions with user-friendly data structures. See [Getting Started](docs/source/examples/00-Getting-Started.ipynb) and [How Solutions are Represented](docs/source/examples/01-How-Solutions-are-Represented.ipynb).
|
39
|
+
|
40
|
+
- **Benchmark Instances**: Load well-known benchmark instances directly from the library without manual downloading. See [Load Benchmark Instances](docs/source/examples/05-Load-Benchmark-Instances.ipynb).
|
41
|
+
|
42
|
+
- **Random Instance Generation**: Create random instances with customizable sizes and properties or augment existing ones. See [`generation`](job_shop_lib/generation) package.
|
43
|
+
|
44
|
+
- **Multiple Solvers**:
|
45
|
+
- **Constraint Programming Solver**: OR-Tools' CP-SAT solver. See [Solving the Problem](docs/source/examples/02-Solving-the-Problem.ipynb).
|
46
|
+
|
47
|
+
- **Dispatching Rule Solvers**: Use any of the available dispatching rules or create custom ones. See [Dispatching Rules](docs/source/examples/03-Dispatching-Rules.ipynb).
|
48
|
+
|
49
|
+
- **Gantt Charts**: Visualize final schedules and how are they created iteratively by dispatching rule solvers or sequences of scheduling decisions with GIFs or videos. See [Save Gif](docs/source/examples/06-Save-Gif.ipynb).
|
50
|
+
|
51
|
+
- **Graph Representations**:
|
52
|
+
- **Disjunctive Graphs**: Represent and visualize instances as disjunctive graphs. See [Disjunctive Graph](docs/source/examples/04-Disjunctive-Graph.ipynb).
|
53
|
+
- **Agent-Task Graphs**: Encode instances as agent-task graphs (introduced in [ScheduleNet paper](https://arxiv.org/abs/2106.03051)). See [Agent-Task Graph](docs/source/examples/07-Agent-Task-Graph.ipynb).
|
54
|
+
- Build your own custom graphs with the `JobShopGraph` class.
|
55
|
+
|
56
|
+
- **Gymnasium Environments**: Two environments for solving the problem with Graph Neural Networks (GNNs) or any other method, and Reinforcement Learning (RL). See [SingleJobShopGraphEnv](docs/source/examples/09-SingleJobShopGraphEnv.ipynb) and [MultiJobShopGraphEnv](examples/10-MultiJobShopGraphEnv.ipynb).
|
57
|
+
|
58
|
+
<!-- end key features -->
|
59
|
+
|
60
|
+
## Some Examples :rocket:
|
29
61
|
|
30
62
|
### Create a Job Shop Instance
|
31
63
|
|
32
|
-
You can create a
|
64
|
+
You can create a `JobShopInstance` by defining the jobs and operations. An operation is defined by the machine(s) it is processed on and the duration (processing time).
|
33
65
|
|
34
66
|
```python
|
35
67
|
from job_shop_lib import JobShopInstance, Operation
|
@@ -60,7 +92,7 @@ from job_shop_lib.benchmarking import load_benchmark_instance
|
|
60
92
|
ft06 = load_benchmark_instance("ft06")
|
61
93
|
```
|
62
94
|
|
63
|
-
The module `
|
95
|
+
The module `benchmarking` contains functions to load the instances from the file and return them as `JobShopInstance` objects without having to download them
|
64
96
|
manually.
|
65
97
|
|
66
98
|
The contributions to this benchmark dataset are as follows:
|
@@ -92,12 +124,12 @@ https://github.com/thomasWeise/jsspInstancesAndResults
|
|
92
124
|
|
93
125
|
### Generate a Random Instance
|
94
126
|
|
95
|
-
You can also generate a random instance with the `
|
127
|
+
You can also generate a random instance with the `GeneralInstanceGenerator` class.
|
96
128
|
|
97
129
|
```python
|
98
|
-
from job_shop_lib.
|
130
|
+
from job_shop_lib.generation import GeneralInstanceGenerator
|
99
131
|
|
100
|
-
generator =
|
132
|
+
generator = GeneralInstanceGenerator(
|
101
133
|
duration_range=(5, 10), seed=42, num_jobs=5, num_machines=5
|
102
134
|
)
|
103
135
|
random_instance = generator.generate()
|
@@ -106,7 +138,7 @@ random_instance = generator.generate()
|
|
106
138
|
This class can also work as an iterator to generate multiple instances:
|
107
139
|
|
108
140
|
```python
|
109
|
-
generator =
|
141
|
+
generator = GeneralInstanceGenerator(iteration_limit=100, seed=42)
|
110
142
|
instances = []
|
111
143
|
for instance in generator:
|
112
144
|
instances.append(instance)
|
@@ -122,7 +154,7 @@ Every solver is a `Callable` that receives a `JobShopInstance` and returns a `Sc
|
|
122
154
|
```python
|
123
155
|
import matplotlib.pyplot as plt
|
124
156
|
|
125
|
-
from job_shop_lib.
|
157
|
+
from job_shop_lib.constraint_programming import ORToolsSolver
|
126
158
|
from job_shop_lib.visualization import plot_gantt_chart
|
127
159
|
|
128
160
|
solver = ORToolsSolver(max_time_in_seconds=10)
|
@@ -131,7 +163,7 @@ ft06_schedule = solver(ft06)
|
|
131
163
|
fig, ax = plot_gantt_chart(ft06_schedule)
|
132
164
|
plt.show()
|
133
165
|
```
|
134
|
-

|
166
|
+

|
135
167
|
|
136
168
|
### Solve an Instance with a Dispatching Rule Solver
|
137
169
|
|
@@ -167,7 +199,7 @@ create_gif(
|
|
167
199
|
)
|
168
200
|
```
|
169
201
|
|
170
|
-

|
202
|
+

|
171
203
|
|
172
204
|
The dashed red line represents the current time step, which is computed as the earliest time when the next operation can start.
|
173
205
|
|
@@ -194,11 +226,11 @@ fig = plot_disjunctive_graph(instance)
|
|
194
226
|
plt.show()
|
195
227
|
```
|
196
228
|
|
197
|
-

|
229
|
+

|
198
230
|
|
199
231
|
|
200
|
-
> [!
|
201
|
-
>
|
232
|
+
> [!TIP]
|
233
|
+
> Installing the optional dependency [PyGraphViz](https://pygraphviz.github.io/) is recommended.
|
202
234
|
|
203
235
|
The `JobShopGraph` class provides easy access to the nodes, for example, to get all the nodes of a specific type:
|
204
236
|
|
@@ -253,7 +285,7 @@ plt.show()
|
|
253
285
|
```
|
254
286
|
|
255
287
|
<div align="center">
|
256
|
-
<img src="
|
288
|
+
<img src="docs/source/images/agent_task_graph.png" width="300">
|
257
289
|
</div>
|
258
290
|
<br>
|
259
291
|
|
@@ -263,43 +295,34 @@ For more details, check the [examples](examples) folder.
|
|
263
295
|
|
264
296
|
## Installation for development
|
265
297
|
|
266
|
-
|
298
|
+
<!-- start installation development -->
|
267
299
|
|
268
300
|
1. Clone the repository.
|
269
301
|
|
270
|
-
2. Install [poetry](https://python-poetry.org/docs/) if you don't have it already:
|
271
|
-
```bash
|
272
|
-
pip install poetry==1.7
|
273
|
-
```
|
274
|
-
3. Create the virtual environment:
|
275
302
|
```bash
|
276
|
-
|
303
|
+
git clone https://github.com/Pabloo22/job_shop_lib.git
|
304
|
+
cd job_shop_lib
|
277
305
|
```
|
278
|
-
|
306
|
+
|
307
|
+
2. Install [poetry](https://python-poetry.org/docs/) if you don't have it already:
|
308
|
+
|
279
309
|
```bash
|
280
|
-
|
310
|
+
pip install poetry
|
281
311
|
```
|
282
|
-
|
312
|
+
|
313
|
+
3. Install dependencies:
|
283
314
|
```bash
|
284
315
|
make poetry_install_all
|
285
316
|
```
|
286
317
|
|
287
|
-
|
288
|
-
|
289
|
-
If you don't want to use Poetry, you can install the library directly from the source code:
|
290
|
-
|
291
|
-
```bash
|
292
|
-
git clone https://github.com/Pabloo22/job_shop_lib.git
|
293
|
-
cd job_shop_lib
|
294
|
-
pip install -e .
|
295
|
-
```
|
318
|
+
<!-- end installation development -->
|
296
319
|
|
297
|
-
## License
|
320
|
+
## License :scroll:
|
298
321
|
|
299
322
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
300
323
|
|
301
324
|
|
302
|
-
## References
|
325
|
+
## References :books:
|
303
326
|
|
304
327
|
- J. Adams, E. Balas, and D. Zawack, "The shifting bottleneck procedure
|
305
328
|
for job shop scheduling," Management Science, vol. 34, no. 3,
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"""Contains the main data structures and base classes.
|
2
|
+
|
3
|
+
.. autosummary::
|
4
|
+
:nosignatures:
|
5
|
+
|
6
|
+
Operation
|
7
|
+
JobShopInstance
|
8
|
+
ScheduledOperation
|
9
|
+
Schedule
|
10
|
+
Solver
|
11
|
+
BaseSolver
|
12
|
+
|
13
|
+
"""
|
14
|
+
|
15
|
+
from job_shop_lib._operation import Operation
|
16
|
+
from job_shop_lib._job_shop_instance import JobShopInstance
|
17
|
+
from job_shop_lib._scheduled_operation import ScheduledOperation
|
18
|
+
from job_shop_lib._schedule import Schedule
|
19
|
+
from job_shop_lib._base_solver import BaseSolver, Solver
|
20
|
+
|
21
|
+
|
22
|
+
__all__ = [
|
23
|
+
"Operation",
|
24
|
+
"JobShopInstance",
|
25
|
+
"ScheduledOperation",
|
26
|
+
"Schedule",
|
27
|
+
"Solver",
|
28
|
+
"BaseSolver",
|
29
|
+
]
|
job_shop_lib-0.5.1/job_shop_lib/base_solver.py → job_shop_lib-1.0.0a2/job_shop_lib/_base_solver.py
RENAMED
@@ -33,5 +33,5 @@ class BaseSolver(abc.ABC):
|
|
33
33
|
schedule = self.solve(instance)
|
34
34
|
elapsed_time = time_start - time.perf_counter()
|
35
35
|
schedule.metadata["elapsed_time"] = elapsed_time
|
36
|
-
schedule.metadata["solved_by"] =
|
36
|
+
schedule.metadata["solved_by"] = self.__class__.__name__
|
37
37
|
return schedule
|
@@ -7,6 +7,7 @@ import functools
|
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
import numpy as np
|
10
|
+
from numpy.typing import NDArray
|
10
11
|
|
11
12
|
from job_shop_lib import Operation
|
12
13
|
|
@@ -267,7 +268,7 @@ class JobShopInstance:
|
|
267
268
|
]
|
268
269
|
|
269
270
|
@functools.cached_property
|
270
|
-
def durations_matrix_array(self) -> np.
|
271
|
+
def durations_matrix_array(self) -> NDArray[np.float32]:
|
271
272
|
"""Returns the duration matrix of the instance as a numpy array.
|
272
273
|
|
273
274
|
The returned array has shape (num_jobs, max_num_operations_per_job).
|
@@ -284,7 +285,7 @@ class JobShopInstance:
|
|
284
285
|
return self._fill_matrix_with_nans_2d(duration_matrix)
|
285
286
|
|
286
287
|
@functools.cached_property
|
287
|
-
def machines_matrix_array(self) -> np.
|
288
|
+
def machines_matrix_array(self) -> NDArray[np.float32]:
|
288
289
|
"""Returns the machines matrix of the instance as a numpy array.
|
289
290
|
|
290
291
|
The returned array has shape (num_jobs, max_num_operations_per_job,
|
@@ -409,7 +410,9 @@ class JobShopInstance:
|
|
409
410
|
return sum(self.job_durations)
|
410
411
|
|
411
412
|
@staticmethod
|
412
|
-
def _fill_matrix_with_nans_2d(
|
413
|
+
def _fill_matrix_with_nans_2d(
|
414
|
+
matrix: list[list[int]],
|
415
|
+
) -> NDArray[np.float32]:
|
413
416
|
"""Fills a matrix with np.nan values.
|
414
417
|
|
415
418
|
Args:
|
@@ -429,7 +432,9 @@ class JobShopInstance:
|
|
429
432
|
return squared_matrix
|
430
433
|
|
431
434
|
@staticmethod
|
432
|
-
def _fill_matrix_with_nans_3d(
|
435
|
+
def _fill_matrix_with_nans_3d(
|
436
|
+
matrix: list[list[list[int]]],
|
437
|
+
) -> NDArray[np.float32]:
|
433
438
|
"""Fills a 3D matrix with np.nan values.
|
434
439
|
|
435
440
|
Args:
|
@@ -0,0 +1,99 @@
|
|
1
|
+
"""Home of the `Operation` class."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from job_shop_lib.exceptions import UninitializedAttributeError
|
6
|
+
|
7
|
+
|
8
|
+
class Operation:
|
9
|
+
"""Stores machine and duration information for a job operation.
|
10
|
+
|
11
|
+
An operation is a task that must be performed on a machine. It is part of a
|
12
|
+
job and has a duration that represents the time it takes to complete the
|
13
|
+
task.
|
14
|
+
|
15
|
+
Tip:
|
16
|
+
To use custom attributes, such as due dates or priorities, subclass
|
17
|
+
this class and add the desired attributes.
|
18
|
+
|
19
|
+
Note:
|
20
|
+
To increase performance, some solvers such as the CP-SAT solver use
|
21
|
+
only integers to represent the operation's attributes. Should a
|
22
|
+
problem involve operations with non-integer durations, it would be
|
23
|
+
necessary to multiply all durations by a sufficiently large integer so
|
24
|
+
that every duration is an integer.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
machines:
|
28
|
+
A list of machine ids that can perform the operation. If
|
29
|
+
only one machine can perform the operation, it can be passed as
|
30
|
+
an integer.
|
31
|
+
duration:
|
32
|
+
The time it takes to perform the operation.
|
33
|
+
"""
|
34
|
+
|
35
|
+
__slots__ = {
|
36
|
+
"machines": (
|
37
|
+
"A list of machine ids that can perform the operation. If "
|
38
|
+
"only one machine can perform the operation, it can be passed as "
|
39
|
+
"an integer."
|
40
|
+
),
|
41
|
+
"duration": (
|
42
|
+
"The time it takes to perform the operation. Often referred"
|
43
|
+
" to as the processing time."
|
44
|
+
),
|
45
|
+
"job_id": "The id of the job the operation belongs to.",
|
46
|
+
"position_in_job": "The index of the operation in the job.",
|
47
|
+
"operation_id": (
|
48
|
+
"The id of the operation. This is unique within a "
|
49
|
+
":class:`JobShopInstance`."
|
50
|
+
),
|
51
|
+
}
|
52
|
+
|
53
|
+
def __init__(self, machines: int | list[int], duration: int):
|
54
|
+
self.machines = [machines] if isinstance(machines, int) else machines
|
55
|
+
self.duration = duration
|
56
|
+
|
57
|
+
# Defined outside the class by the JobShopInstance class:
|
58
|
+
self.job_id: int = -1
|
59
|
+
self.position_in_job: int = -1
|
60
|
+
self.operation_id: int = -1
|
61
|
+
|
62
|
+
@property
|
63
|
+
def machine_id(self) -> int:
|
64
|
+
"""Returns the id of the machine associated with the operation.
|
65
|
+
|
66
|
+
Raises:
|
67
|
+
UninitializedAttributeError: If the operation has multiple machines
|
68
|
+
in its list.
|
69
|
+
"""
|
70
|
+
if len(self.machines) > 1:
|
71
|
+
raise UninitializedAttributeError(
|
72
|
+
"Operation has multiple machines."
|
73
|
+
)
|
74
|
+
return self.machines[0]
|
75
|
+
|
76
|
+
def is_initialized(self) -> bool:
|
77
|
+
"""Returns whether the operation has been initialized."""
|
78
|
+
return (
|
79
|
+
self.job_id == -1
|
80
|
+
or self.position_in_job == -1
|
81
|
+
or self.operation_id == -1
|
82
|
+
)
|
83
|
+
|
84
|
+
def __hash__(self) -> int:
|
85
|
+
return hash(self.operation_id)
|
86
|
+
|
87
|
+
def __eq__(self, value: object) -> bool:
|
88
|
+
if not isinstance(value, Operation):
|
89
|
+
return False
|
90
|
+
return self.__slots__ == value.__slots__
|
91
|
+
|
92
|
+
def __repr__(self) -> str:
|
93
|
+
machines = (
|
94
|
+
self.machines[0] if len(self.machines) == 1 else self.machines
|
95
|
+
)
|
96
|
+
return (
|
97
|
+
f"O(m={machines}, d={self.duration}, "
|
98
|
+
f"j={self.job_id}, p={self.position_in_job})"
|
99
|
+
)
|