job-shop-lib 0.1.2__tar.gz → 0.2.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/PKG-INFO +30 -41
  2. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/README.md +28 -39
  3. job_shop_lib-0.2.0/job_shop_lib/generators/transformations.py +164 -0
  4. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/pyproject.toml +2 -2
  5. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/LICENSE +0 -0
  6. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/__init__.py +0 -0
  7. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/base_solver.py +0 -0
  8. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/benchmarking/__init__.py +0 -0
  9. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/benchmarking/benchmark_instances.json +0 -0
  10. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/benchmarking/load_benchmark.py +0 -0
  11. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/cp_sat/__init__.py +0 -0
  12. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/cp_sat/ortools_solver.py +0 -0
  13. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/__init__.py +0 -0
  14. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/dispatcher.py +0 -0
  15. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/dispatching_rule_solver.py +0 -0
  16. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/dispatching_rules.py +0 -0
  17. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/factories.py +0 -0
  18. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/dispatching/pruning_functions.py +0 -0
  19. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/exceptions.py +0 -0
  20. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/generators/__init__.py +0 -0
  21. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/generators/basic_generator.py +0 -0
  22. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/__init__.py +0 -0
  23. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/build_agent_task_graph.py +0 -0
  24. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/build_disjunctive_graph.py +0 -0
  25. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/constants.py +0 -0
  26. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/job_shop_graph.py +0 -0
  27. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/graphs/node.py +0 -0
  28. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/job_shop_instance.py +0 -0
  29. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/operation.py +0 -0
  30. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/schedule.py +0 -0
  31. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/scheduled_operation.py +0 -0
  32. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/visualization/__init__.py +0 -0
  33. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/visualization/agent_task_graph.py +0 -0
  34. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/visualization/create_gif.py +0 -0
  35. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/job_shop_lib/visualization/disjunctive_graph.py +0 -0
  36. {job_shop_lib-0.1.2 → job_shop_lib-0.2.0}/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.1.2
3
+ Version: 0.2.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
@@ -16,7 +16,7 @@ Requires-Dist: imageio (>=2,<3)
16
16
  Requires-Dist: matplotlib (>=3,<4)
17
17
  Requires-Dist: networkx (>=3,<4)
18
18
  Requires-Dist: ortools (>=9,<10)
19
- Requires-Dist: pyarrow (>=14.0.0,<15.0.0)
19
+ Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
20
20
  Requires-Dist: pygraphviz (>=1.12,<2.0) ; extra == "pygraphviz"
21
21
  Description-Content-Type: text/markdown
22
22
 
@@ -33,13 +33,21 @@ Description-Content-Type: text/markdown
33
33
 
34
34
  </div>
35
35
 
36
+ An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP) with a special focus on graph representations.
36
37
 
38
+ It provides intuitive data structures to represent instances and solutions, as well as solvers and visualization tools.
37
39
 
38
- An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP) with a special focus on graph representations.
40
+ See the [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
41
+
42
+ ## Installation
39
43
 
40
- It provides intuitive data structures to represent instances and solutions, as well as solvers and visualization tools:
44
+ You can install the library from PyPI:
45
+
46
+ ```bash
47
+ pip install job-shop-lib
48
+ ```
41
49
 
42
- ## Quick Start
50
+ ## Quick Start :rocket:
43
51
 
44
52
  ### Create a Job Shop Instance
45
53
 
@@ -79,40 +87,22 @@ manually. The instances are stored in [benchmark_instances.json](job_shop_lib/be
79
87
 
80
88
  The contributions to this benchmark dataset are as follows:
81
89
 
82
- - `abz5-9`: This subset, comprising five instances, was introduced by Adams et
83
- al. (1988).
90
+ - `abz5-9`: by Adams et al. (1988).
84
91
 
85
- - `ft06`, `ft10`, `ft20`: These three instances are attributed to the work of
86
- Fisher and Thompson, as detailed in their 1963 work.
92
+ - `ft06`, `ft10`, `ft20`: by Fisher and Thompson (1963).
87
93
 
88
- - `la01-40`: A collection of forty instances, this group was contributed by
89
- Lawrence, as referenced in his 1984 report.
94
+ - `la01-40`: by Lawrence (1984)
90
95
 
91
- - `orb01-10`: Ten instances in this category were provided by Applegate and
92
- Cook, as seen in their 1991 study.
96
+ - `orb01-10`: by Applegate and Cook (1991).
93
97
 
94
- - `swb01-20`: This segment, encompassing twenty instances, was contributed by
95
- Storer et al., as per their 1992 article.
98
+ - `swb01-20`: by Storer et al. (1992).
96
99
 
97
- - `yn1-4`: Yamada and Nakano are credited with the addition of four instances
98
- in this group, as found in their 1992 paper.
100
+ - `yn1-4`: by Yamada and Nakano (1992).
99
101
 
100
- - `ta01-80`: The largest contribution, consisting of eighty instances, was
101
- made by Taillard, as documented in his 1993 paper.
102
+ - `ta01-80`: by Taillard (1993).
102
103
 
103
104
  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.
105
+ https://github.com/thomasWeise/jsspInstancesAndResults
116
106
 
117
107
  ```python
118
108
  >>> ft06.metadata
@@ -124,7 +114,7 @@ It includes the following information:
124
114
 
125
115
  ### Generate a Random Instance
126
116
 
127
- You can also generate a random instance with the `InstanceGenerator` class.
117
+ You can also generate a random instance with the `BasicGenerator` class.
128
118
 
129
119
  ```python
130
120
  from job_shop_lib.generators import BasicGenerator
@@ -138,7 +128,7 @@ random_instance = generator.generate()
138
128
  This class can also work as an iterator to generate multiple instances:
139
129
 
140
130
  ```python
141
- generator = InstanceGenerator(iteration_limit=100, seed=42)
131
+ generator = BasicGenerator(iteration_limit=100, seed=42)
142
132
  instances = []
143
133
  for instance in generator:
144
134
  instances.append(instance)
@@ -182,7 +172,7 @@ We can visualize the solution with a `DispatchingRuleSolver` as a gif:
182
172
 
183
173
  ```python
184
174
  from job_shop_lib.visualization import create_gif, get_plot_function
185
- from job_shop_lib.solvers import DispatchingRuleSolver, DispatchingRule
175
+ from job_shop_lib.dispatching import DispatchingRuleSolver, DispatchingRule
186
176
 
187
177
  plt.style.use("ggplot")
188
178
 
@@ -227,6 +217,9 @@ plt.show()
227
217
  ![Example Disjunctive Graph](images/example_disjunctive_graph.png)
228
218
 
229
219
 
220
+ > [!WARNING]
221
+ > This plot function requires having the optional dependency [PyGraphViz](https://pygraphviz.github.io/) installed.
222
+
230
223
  The `JobShopGraph` class provides easy access to the nodes, for example, to get all the nodes of a specific type:
231
224
 
232
225
  ```python
@@ -288,13 +281,9 @@ plt.show()
288
281
 
289
282
  For more details, check the [examples](examples) folder.
290
283
 
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
284
+ ## Installation for development
296
285
 
297
- #### With Poetry
286
+ ### With Poetry
298
287
 
299
288
  1. Clone the repository.
300
289
 
@@ -315,7 +304,7 @@ or equivalently:
315
304
  make poetry_install_all
316
305
  ```
317
306
 
318
- #### With PyPI
307
+ ### With PyPI
319
308
 
320
309
  If you don't want to use Poetry, you can install the library directly from the source code:
321
310
 
@@ -11,13 +11,21 @@
11
11
 
12
12
  </div>
13
13
 
14
+ An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP) with a special focus on graph representations.
14
15
 
16
+ It provides intuitive data structures to represent instances and solutions, as well as solvers and visualization tools.
15
17
 
16
- An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP) with a special focus on graph representations.
18
+ See the [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
19
+
20
+ ## Installation
17
21
 
18
- It provides intuitive data structures to represent instances and solutions, as well as solvers and visualization tools:
22
+ You can install the library from PyPI:
23
+
24
+ ```bash
25
+ pip install job-shop-lib
26
+ ```
19
27
 
20
- ## Quick Start
28
+ ## Quick Start :rocket:
21
29
 
22
30
  ### Create a Job Shop Instance
23
31
 
@@ -57,40 +65,22 @@ manually. The instances are stored in [benchmark_instances.json](job_shop_lib/be
57
65
 
58
66
  The contributions to this benchmark dataset are as follows:
59
67
 
60
- - `abz5-9`: This subset, comprising five instances, was introduced by Adams et
61
- al. (1988).
68
+ - `abz5-9`: by Adams et al. (1988).
62
69
 
63
- - `ft06`, `ft10`, `ft20`: These three instances are attributed to the work of
64
- Fisher and Thompson, as detailed in their 1963 work.
70
+ - `ft06`, `ft10`, `ft20`: by Fisher and Thompson (1963).
65
71
 
66
- - `la01-40`: A collection of forty instances, this group was contributed by
67
- Lawrence, as referenced in his 1984 report.
72
+ - `la01-40`: by Lawrence (1984)
68
73
 
69
- - `orb01-10`: Ten instances in this category were provided by Applegate and
70
- Cook, as seen in their 1991 study.
74
+ - `orb01-10`: by Applegate and Cook (1991).
71
75
 
72
- - `swb01-20`: This segment, encompassing twenty instances, was contributed by
73
- Storer et al., as per their 1992 article.
76
+ - `swb01-20`: by Storer et al. (1992).
74
77
 
75
- - `yn1-4`: Yamada and Nakano are credited with the addition of four instances
76
- in this group, as found in their 1992 paper.
78
+ - `yn1-4`: by Yamada and Nakano (1992).
77
79
 
78
- - `ta01-80`: The largest contribution, consisting of eighty instances, was
79
- made by Taillard, as documented in his 1993 paper.
80
+ - `ta01-80`: by Taillard (1993).
80
81
 
81
82
  The metadata from these instances has been updated using data from:
82
-
83
- Thomas Weise. jsspInstancesAndResults. Accessed in January 2024.
84
- Available at: https://github.com/thomasWeise/jsspInstancesAndResults
85
-
86
- It includes the following information:
87
- - "optimum" (`int` | `None`): The optimal makespan for the instance.
88
- - "lower_bound" (`int`): The best lower bound known for the makespan. If
89
- optimality is known, it is equal to the optimum.
90
- - "upper_bound" (`int`): The best upper bound known for the makespan. If
91
- optimality is known, it is equal to the optimum.
92
- - "reference" (`str`): The paper or source where the instance was first
93
- introduced.
83
+ https://github.com/thomasWeise/jsspInstancesAndResults
94
84
 
95
85
  ```python
96
86
  >>> ft06.metadata
@@ -102,7 +92,7 @@ It includes the following information:
102
92
 
103
93
  ### Generate a Random Instance
104
94
 
105
- You can also generate a random instance with the `InstanceGenerator` class.
95
+ You can also generate a random instance with the `BasicGenerator` class.
106
96
 
107
97
  ```python
108
98
  from job_shop_lib.generators import BasicGenerator
@@ -116,7 +106,7 @@ random_instance = generator.generate()
116
106
  This class can also work as an iterator to generate multiple instances:
117
107
 
118
108
  ```python
119
- generator = InstanceGenerator(iteration_limit=100, seed=42)
109
+ generator = BasicGenerator(iteration_limit=100, seed=42)
120
110
  instances = []
121
111
  for instance in generator:
122
112
  instances.append(instance)
@@ -160,7 +150,7 @@ We can visualize the solution with a `DispatchingRuleSolver` as a gif:
160
150
 
161
151
  ```python
162
152
  from job_shop_lib.visualization import create_gif, get_plot_function
163
- from job_shop_lib.solvers import DispatchingRuleSolver, DispatchingRule
153
+ from job_shop_lib.dispatching import DispatchingRuleSolver, DispatchingRule
164
154
 
165
155
  plt.style.use("ggplot")
166
156
 
@@ -205,6 +195,9 @@ plt.show()
205
195
  ![Example Disjunctive Graph](images/example_disjunctive_graph.png)
206
196
 
207
197
 
198
+ > [!WARNING]
199
+ > This plot function requires having the optional dependency [PyGraphViz](https://pygraphviz.github.io/) installed.
200
+
208
201
  The `JobShopGraph` class provides easy access to the nodes, for example, to get all the nodes of a specific type:
209
202
 
210
203
  ```python
@@ -266,13 +259,9 @@ plt.show()
266
259
 
267
260
  For more details, check the [examples](examples) folder.
268
261
 
269
- ## Installation
270
-
271
- In the future, the library will be available on PyPI. For now, you can install it from the source code.
272
-
273
- ### For development
262
+ ## Installation for development
274
263
 
275
- #### With Poetry
264
+ ### With Poetry
276
265
 
277
266
  1. Clone the repository.
278
267
 
@@ -293,7 +282,7 @@ or equivalently:
293
282
  make poetry_install_all
294
283
  ```
295
284
 
296
- #### With PyPI
285
+ ### With PyPI
297
286
 
298
287
  If you don't want to use Poetry, you can install the library directly from the source code:
299
288
 
@@ -0,0 +1,164 @@
1
+ """Classes for generating transformed JobShopInstance objects."""
2
+
3
+ import abc
4
+ import copy
5
+ import random
6
+
7
+ from job_shop_lib import JobShopInstance, Operation
8
+
9
+
10
+ class Transformation(abc.ABC):
11
+ """Base class for transformations applied to JobShopInstance objects."""
12
+
13
+ def __init__(self, suffix: str = ""):
14
+ self.suffix = suffix
15
+ self.counter = 0
16
+
17
+ @abc.abstractmethod
18
+ def apply(self, instance: JobShopInstance) -> JobShopInstance:
19
+ """Applies the transformation to a given JobShopInstance.
20
+
21
+ Args:
22
+ instance: The JobShopInstance to transform.
23
+
24
+ Returns:
25
+ A new JobShopInstance with the transformation applied.
26
+ """
27
+
28
+ def __call__(self, instance: JobShopInstance) -> JobShopInstance:
29
+ instance = self.apply(instance)
30
+ suffix = f"{self.suffix}_id={self.counter}"
31
+ instance.name += suffix
32
+ self.counter += 1
33
+ return instance
34
+
35
+
36
+ # pylint: disable=too-few-public-methods
37
+ class RemoveMachines(Transformation):
38
+ """Removes operations associated with randomly selected machines until
39
+ there are exactly num_machines machines left."""
40
+
41
+ def __init__(self, num_machines: int, suffix: str | None = None):
42
+ if suffix is None:
43
+ suffix = f"_machines={num_machines}"
44
+ super().__init__(suffix=suffix)
45
+ self.num_machines = num_machines
46
+
47
+ def apply(self, instance: JobShopInstance) -> JobShopInstance:
48
+ if instance.num_machines <= self.num_machines:
49
+ return instance # No need to remove machines
50
+
51
+ # Select machine indices to keep
52
+ machines_to_keep = set(
53
+ random.sample(range(instance.num_machines), self.num_machines)
54
+ )
55
+
56
+ # Re-index machines
57
+ machine_reindex_map = {
58
+ old_id: new_id
59
+ for new_id, old_id in enumerate(sorted(machines_to_keep))
60
+ }
61
+
62
+ new_jobs = []
63
+ for job in instance.jobs:
64
+ # Keep operations whose machine_id is in machines_to_keep and
65
+ # re-index them
66
+ new_jobs.append(
67
+ [
68
+ Operation(machine_reindex_map[op.machine_id], op.duration)
69
+ for op in job
70
+ if op.machine_id in machines_to_keep
71
+ ]
72
+ )
73
+
74
+ return JobShopInstance(new_jobs, instance.name)
75
+
76
+
77
+ # pylint: disable=too-few-public-methods
78
+ class AddDurationNoise(Transformation):
79
+ """Adds uniform integer noise to operation durations."""
80
+
81
+ def __init__(
82
+ self,
83
+ min_duration: int = 1,
84
+ max_duration: int = 100,
85
+ noise_level: int = 10,
86
+ suffix: str | None = None,
87
+ ):
88
+ if suffix is None:
89
+ suffix = f"_noise={noise_level}"
90
+ super().__init__(suffix=suffix)
91
+ self.min_duration = min_duration
92
+ self.max_duration = max_duration
93
+ self.noise_level = noise_level
94
+
95
+ def apply(self, instance: JobShopInstance) -> JobShopInstance:
96
+ new_jobs = []
97
+ for job in instance.jobs:
98
+ new_job = []
99
+ for op in job:
100
+ noise = random.randint(-self.noise_level, self.noise_level)
101
+ new_duration = max(
102
+ self.min_duration,
103
+ min(self.max_duration, op.duration + noise),
104
+ )
105
+
106
+ new_job.append(Operation(op.machine_id, new_duration))
107
+ new_jobs.append(new_job)
108
+
109
+ return JobShopInstance(new_jobs, instance.name)
110
+
111
+
112
+ class RemoveJobs(Transformation):
113
+ """Removes jobs randomly until the number of jobs is within a specified
114
+ range."""
115
+
116
+ def __init__(
117
+ self,
118
+ min_jobs: int,
119
+ max_jobs: int,
120
+ target_jobs: int | None = None,
121
+ suffix: str | None = None,
122
+ ):
123
+ """
124
+ Args:
125
+ min_jobs: The minimum number of jobs to remain in the instance.
126
+ max_jobs: The maximum number of jobs to remain in the instance.
127
+ target_jobs: If specified, the number of jobs to remain in the
128
+ instance. Overrides min_jobs and max_jobs.
129
+ """
130
+ if suffix is None:
131
+ suffix = f"_jobs={min_jobs}-{max_jobs}"
132
+ super().__init__(suffix=suffix)
133
+ self.min_jobs = min_jobs
134
+ self.max_jobs = max_jobs
135
+ self.target_jobs = target_jobs
136
+
137
+ def apply(self, instance: JobShopInstance) -> JobShopInstance:
138
+ if self.target_jobs is None:
139
+ target_jobs = random.randint(self.min_jobs, self.max_jobs)
140
+ else:
141
+ target_jobs = self.target_jobs
142
+ new_jobs = copy.deepcopy(instance.jobs)
143
+
144
+ while len(new_jobs) > target_jobs:
145
+ new_jobs.pop(random.randint(0, len(new_jobs) - 1))
146
+
147
+ return JobShopInstance(new_jobs, instance.name)
148
+
149
+ @staticmethod
150
+ def remove_job(
151
+ instance: JobShopInstance, job_index: int
152
+ ) -> JobShopInstance:
153
+ """Removes a specific job from the instance.
154
+
155
+ Args:
156
+ instance: The JobShopInstance from which to remove the job.
157
+ job_index: The index of the job to remove.
158
+
159
+ Returns:
160
+ A new JobShopInstance with the specified job removed.
161
+ """
162
+ new_jobs = copy.deepcopy(instance.jobs)
163
+ new_jobs.pop(job_index)
164
+ return JobShopInstance(new_jobs, instance.name)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "job-shop-lib"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  description = "An easy-to-use and modular Python library for the Job Shop Scheduling Problem (JSSP)"
5
5
  authors = ["Pabloo22 <pablete.arino@gmail.com>"]
6
6
  license = "MIT"
@@ -12,7 +12,7 @@ include = ["benchmarks/benchmark_instances.json"]
12
12
  python = "^3.10"
13
13
  ortools = "^9"
14
14
  matplotlib = "^3"
15
- pyarrow = "^14.0.0" # An optional pandas' dependency that will be required in the future
15
+ pyarrow = "^15.0.0" # An optional pandas' dependency that will be required in the future
16
16
  networkx = "^3"
17
17
  imageio = "^2"
18
18
  pygraphviz = {version = "^1.12", optional = true}
File without changes