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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. job_shop_lib/_job_shop_instance.py +104 -38
  2. job_shop_lib/_operation.py +12 -3
  3. job_shop_lib/_schedule.py +10 -12
  4. job_shop_lib/_scheduled_operation.py +15 -16
  5. job_shop_lib/dispatching/_dispatcher.py +12 -15
  6. job_shop_lib/dispatching/_dispatcher_observer_config.py +15 -2
  7. job_shop_lib/dispatching/_factories.py +2 -2
  8. job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +0 -1
  9. job_shop_lib/dispatching/feature_observers/_factory.py +21 -18
  10. job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +1 -0
  11. job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +1 -1
  12. job_shop_lib/generation/_general_instance_generator.py +33 -34
  13. job_shop_lib/generation/_instance_generator.py +14 -17
  14. job_shop_lib/generation/_transformations.py +11 -8
  15. job_shop_lib/graphs/__init__.py +3 -0
  16. job_shop_lib/graphs/_build_disjunctive_graph.py +41 -3
  17. job_shop_lib/graphs/graph_updaters/_graph_updater.py +11 -13
  18. job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py +17 -20
  19. job_shop_lib/reinforcement_learning/__init__.py +16 -7
  20. job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py +69 -57
  21. job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +42 -31
  22. job_shop_lib/reinforcement_learning/_types_and_constants.py +2 -2
  23. job_shop_lib/visualization/__init__.py +24 -5
  24. job_shop_lib/visualization/_gantt_chart_creator.py +118 -80
  25. job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py +15 -11
  26. job_shop_lib/visualization/_plot_disjunctive_graph.py +382 -0
  27. {job_shop_lib-1.0.0a3.dist-info → job_shop_lib-1.0.0a4.dist-info}/METADATA +5 -5
  28. {job_shop_lib-1.0.0a3.dist-info → job_shop_lib-1.0.0a4.dist-info}/RECORD +31 -31
  29. job_shop_lib/visualization/_disjunctive_graph.py +0 -210
  30. /job_shop_lib/visualization/{_agent_task_graph.py → _plot_agent_task_graph.py} +0 -0
  31. {job_shop_lib-1.0.0a3.dist-info → job_shop_lib-1.0.0a4.dist-info}/LICENSE +0 -0
  32. {job_shop_lib-1.0.0a3.dist-info → job_shop_lib-1.0.0a4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,382 @@
1
+ """Module for visualizing the disjunctive graph of a job shop instance."""
2
+
3
+ import functools
4
+ from typing import Any
5
+ from collections.abc import Callable, Sequence, Iterable
6
+ import warnings
7
+ import copy
8
+
9
+ import matplotlib
10
+ import matplotlib.pyplot as plt
11
+ import networkx as nx
12
+ from networkx.drawing.nx_agraph import graphviz_layout
13
+
14
+ from job_shop_lib import JobShopInstance
15
+ from job_shop_lib.graphs import (
16
+ JobShopGraph,
17
+ EdgeType,
18
+ NodeType,
19
+ Node,
20
+ build_disjunctive_graph,
21
+ )
22
+ from job_shop_lib.exceptions import ValidationError
23
+
24
+
25
+ Layout = Callable[[nx.Graph], dict[str, tuple[float, float]]]
26
+
27
+
28
+ def duration_labeler(node: Node) -> str:
29
+ """Returns a label for the node with the processing time.
30
+
31
+ In the form ``"$p_{ij}=duration$"``, where $i$ is the job id and $j$ is
32
+ the position in the job.
33
+
34
+ Args:
35
+ node:
36
+ The operation node to label. See
37
+ :class:`~job_shop_lib.graphs.Node`.
38
+ """
39
+ return (
40
+ f"$p_{{{node.operation.job_id + 1}"
41
+ f"{node.operation.position_in_job + 1}}}={node.operation.duration}$"
42
+ )
43
+
44
+
45
+ # This function could be improved by a function extraction refactoring
46
+ # (see `plot_gantt_chart`
47
+ # function as a reference in how to do it). That would solve the
48
+ # "too many locals" warning. However, this refactoring is not a priority at
49
+ # the moment. To compensate, sections are separated by comments.
50
+ # For the "too many arguments" warning no satisfactory solution was
51
+ # found. I believe is still better than using `**kwargs` and losing the
52
+ # function signature or adding a dataclass for configuration (it would add
53
+ # unnecessary complexity). A TypedDict could be used too, but the default
54
+ # values would not be explicit.
55
+ # pylint: disable=too-many-arguments, too-many-locals, too-many-statements
56
+ # pylint: disable=too-many-branches, line-too-long
57
+ def plot_disjunctive_graph(
58
+ job_shop: JobShopGraph | JobShopInstance,
59
+ *,
60
+ title: str | None = None,
61
+ figsize: tuple[float, float] = (6, 4),
62
+ node_size: int = 1600,
63
+ edge_width: int = 2,
64
+ font_size: int = 10,
65
+ arrow_size: int = 35,
66
+ alpha: float = 0.95,
67
+ operation_node_labeler: Callable[[Node], str] = duration_labeler,
68
+ node_font_color: str = "white",
69
+ color_map: str = "Dark2_r",
70
+ disjunctive_edge_color: str = "red",
71
+ conjunctive_edge_color: str = "black",
72
+ layout: Layout | None = None,
73
+ draw_disjunctive_edges: bool | str = True,
74
+ conjunctive_edges_additional_params: dict[str, Any] | None = None,
75
+ disjunctive_edges_additional_params: dict[str, Any] | None = None,
76
+ conjunctive_patch_label: str = "Conjunctive edges",
77
+ disjunctive_patch_label: str = "Disjunctive edges",
78
+ legend_text: str = "$p_{ij}=$duration of $O_{ij}$",
79
+ show_machine_colors_in_legend: bool = True,
80
+ machine_labels: Sequence[str] | None = None,
81
+ legend_location: str = "upper left",
82
+ legend_bbox_to_anchor: tuple[float, float] = (1.01, 1),
83
+ start_node_label: str = "$S$",
84
+ end_node_label: str = "$T$",
85
+ font_family: str = "sans-serif",
86
+ ) -> tuple[plt.Figure, plt.Axes]:
87
+ r"""Plots the disjunctive graph of the given job shop instance or graph.
88
+
89
+ Args:
90
+ job_shop:
91
+ The job shop instance or graph to plot. Can be either a
92
+ :class:`JobShopGraph` or a :class:`JobShopInstance`. If a job shop
93
+ instance is given, the disjunctive graph is built before plotting
94
+ using the :func:`~job_shop_lib.graphs.build_disjunctive_graph`.
95
+ title:
96
+ The title of the graph (default is ``"Disjunctive Graph
97
+ Visualization: {job_shop.instance.name}"``).
98
+ figsize:
99
+ The size of the figure (default is (6, 4)).
100
+ node_size:
101
+ The size of the nodes (default is 1600).
102
+ edge_width:
103
+ The width of the edges (default is 2).
104
+ font_size:
105
+ The font size of the node labels (default is 10).
106
+ arrow_size:
107
+ The size of the arrows (default is 35).
108
+ alpha:
109
+ The transparency level of the nodes and edges (default is 0.95).
110
+ operation_node_labeler:
111
+ A function that formats labels for operation nodes. Receives a
112
+ :class:`~job_shop_lib.graphs.Node` and returns a string.
113
+ The default is :func:`duration_labeler`, which labels the nodes
114
+ with their duration.
115
+ node_font_color:
116
+ The color of the node labels (default is ``"white"``).
117
+ color_map:
118
+ The color map to use for the nodes (default is ``"Dark2_r"``).
119
+ disjunctive_edge_color:
120
+ The color of the disjunctive edges (default is ``"red"``).
121
+ conjunctive_edge_color:
122
+ The color of the conjunctive edges (default is ``"black"``).
123
+ layout:
124
+ The layout of the graph (default is ``graphviz_layout`` with
125
+ ``prog="dot"`` and ``args="-Grankdir=LR"``). If not available,
126
+ the spring layout is used. To install pygraphviz, check
127
+ `pygraphviz documentation
128
+ <https://pygraphviz.github.io/documentation/stable/install.html>`_.
129
+ draw_disjunctive_edges:
130
+ Whether to draw disjunctive edges (default is ``True``). If
131
+ ``False``, only conjunctive edges are drawn. If ``"single_edge",``
132
+ the disjunctive edges are drawn as undirected edges by removing one
133
+ of the directions. If using this last option is recommended to set
134
+ the "arrowstyle" parameter to ``"-"`` or ``"<->"`` in the
135
+ ``disjunctive_edges_additional_params`` to make the edges look
136
+ better. See `matplotlib documentation on arrow styles <https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.ArrowStyle.html#matplotlib.patches.ArrowStyle>`_
137
+ and `nx.draw_networkx_edges <https://networkx.org/documentation/stable/reference/generated/networkx.drawing.nx_pylab.draw_networkx_edges.html>`_
138
+ for more information.
139
+ conjunctive_edges_additional_params:
140
+ Additional parameters to pass to the conjunctive edges when
141
+ drawing them (default is ``None``). See the documentation of
142
+ `nx.draw_networkx_edges <https://networkx.org/documentation/stable/reference/generated/networkx.drawing.nx_pylab.draw_networkx_edges.html>`_
143
+ for more information. The parameters that are explicitly set by
144
+ this function and should not be part of this dictionary are
145
+ ``edgelist``, ``pos``, ``width``, ``edge_color``, and
146
+ ``arrowsize``.
147
+ disjunctive_edges_additional_params:
148
+ Same as ``conjunctive_edges_additional_params``, but for
149
+ disjunctive edges (default is ``None``).
150
+ conjunctive_patch_label:
151
+ The label for the conjunctive edges in the legend (default is
152
+ ``"Conjunctive edges"``).
153
+ disjunctive_patch_label:
154
+ The label for the disjunctive edges in the legend (default is
155
+ ``"Disjunctive edges"``).
156
+ legend_text:
157
+ Text to display in the legend after the conjunctive and
158
+ disjunctive edges labels (default is
159
+ ``"$p_{ij}=$duration of $O_{ij}$"``).
160
+ show_machine_colors_in_legend:
161
+ Whether to show the colors of the machines in the legend
162
+ (default is ``True``).
163
+ machine_labels:
164
+ The labels for the machines (default is
165
+ ``[f"Machine {i}" for i in range(num_machines)]``). Not used if
166
+ ``show_machine_colors_in_legend`` is ``False``.
167
+ legend_location:
168
+ The location of the legend (default is "upper left").
169
+ legend_bbox_to_anchor:
170
+ The anchor of the legend box (default is ``(1.01, 1)``).
171
+ start_node_label:
172
+ The label for the start node (default is ``"$S$"``).
173
+ end_node_label:
174
+ The label for the end node (default is ``"$T$"``).
175
+ font_family:
176
+ The font family of the node labels (default is ``"sans-serif"``).
177
+
178
+ Returns:
179
+ A matplotlib Figure object representing the disjunctive graph.
180
+
181
+ Example:
182
+
183
+ .. code-block:: python
184
+
185
+ job_shop_instance = JobShopInstance(...) # or a JobShopGraph
186
+ fig = plot_disjunctive_graph(job_shop_instance)
187
+
188
+ """ # noqa: E501
189
+
190
+ if isinstance(job_shop, JobShopInstance):
191
+ job_shop_graph = build_disjunctive_graph(job_shop)
192
+ else:
193
+ job_shop_graph = job_shop
194
+
195
+ # Set up the plot
196
+ # ----------------
197
+ plt.figure(figsize=figsize)
198
+ if title is None:
199
+ title = (
200
+ f"Disjunctive Graph Visualization: {job_shop_graph.instance.name}"
201
+ )
202
+ plt.title(title)
203
+
204
+ # Set up the layout
205
+ # -----------------
206
+ if layout is None:
207
+ layout = functools.partial(
208
+ graphviz_layout, prog="dot", args="-Grankdir=LR"
209
+ )
210
+
211
+ temp_graph = copy.deepcopy(job_shop_graph.graph)
212
+ # Remove disjunctive edges to get a better layout
213
+ temp_graph.remove_edges_from(
214
+ [
215
+ (u, v)
216
+ for u, v, d in job_shop_graph.graph.edges(data=True)
217
+ if d["type"] == EdgeType.DISJUNCTIVE
218
+ ]
219
+ )
220
+
221
+ try:
222
+ pos = layout(temp_graph)
223
+ except ImportError:
224
+ warnings.warn(
225
+ "Default layout requires pygraphviz http://pygraphviz.github.io/. "
226
+ "Using spring layout instead.",
227
+ )
228
+ pos = nx.spring_layout(temp_graph)
229
+
230
+ # Draw nodes
231
+ # ----------
232
+ node_colors = [
233
+ _get_node_color(node)
234
+ for node in job_shop_graph.nodes
235
+ if not job_shop_graph.is_removed(node.node_id)
236
+ ]
237
+ cmap_func = matplotlib.colormaps.get_cmap(color_map)
238
+ nx.draw_networkx_nodes(
239
+ job_shop_graph.graph,
240
+ pos,
241
+ node_size=node_size,
242
+ node_color=node_colors,
243
+ alpha=alpha,
244
+ cmap=cmap_func,
245
+ )
246
+
247
+ # Draw edges
248
+ # ----------
249
+ conjunctive_edges = [
250
+ (u, v)
251
+ for u, v, d in job_shop_graph.graph.edges(data=True)
252
+ if d["type"] == EdgeType.CONJUNCTIVE
253
+ ]
254
+ disjunctive_edges: Iterable[tuple[int, int]] = [
255
+ (u, v)
256
+ for u, v, d in job_shop_graph.graph.edges(data=True)
257
+ if d["type"] == EdgeType.DISJUNCTIVE
258
+ ]
259
+ if conjunctive_edges_additional_params is None:
260
+ conjunctive_edges_additional_params = {}
261
+ if disjunctive_edges_additional_params is None:
262
+ disjunctive_edges_additional_params = {}
263
+
264
+ nx.draw_networkx_edges(
265
+ job_shop_graph.graph,
266
+ pos,
267
+ edgelist=conjunctive_edges,
268
+ width=edge_width,
269
+ edge_color=conjunctive_edge_color,
270
+ arrowsize=arrow_size,
271
+ **conjunctive_edges_additional_params,
272
+ )
273
+
274
+ if draw_disjunctive_edges:
275
+ if draw_disjunctive_edges == "single_edge":
276
+ # Filter the disjunctive edges to remove one of the directions
277
+ disjunctive_edges_filtered = set()
278
+ for u, v in disjunctive_edges:
279
+ if u > v:
280
+ u, v = v, u
281
+ disjunctive_edges_filtered.add((u, v))
282
+ disjunctive_edges = disjunctive_edges_filtered
283
+ nx.draw_networkx_edges(
284
+ job_shop_graph.graph,
285
+ pos,
286
+ edgelist=disjunctive_edges,
287
+ width=edge_width,
288
+ edge_color=disjunctive_edge_color,
289
+ arrowsize=arrow_size,
290
+ **disjunctive_edges_additional_params,
291
+ )
292
+
293
+ # Draw node labels
294
+ # ----------------
295
+ operation_nodes = job_shop_graph.nodes_by_type[NodeType.OPERATION]
296
+ labels = {}
297
+ source_node = job_shop_graph.nodes_by_type[NodeType.SOURCE][0]
298
+ labels[source_node] = start_node_label
299
+
300
+ sink_node = job_shop_graph.nodes_by_type[NodeType.SINK][0]
301
+ labels[sink_node] = end_node_label
302
+ machine_colors: dict[int, tuple[float, float, float, float]] = {}
303
+ for operation_node in operation_nodes:
304
+ if job_shop_graph.is_removed(operation_node.node_id):
305
+ continue
306
+ labels[operation_node] = operation_node_labeler(operation_node)
307
+ machine_id = operation_node.operation.machine_id
308
+ if machine_id not in machine_colors:
309
+ machine_colors[machine_id] = cmap_func(
310
+ (_get_node_color(operation_node) + 1)
311
+ / job_shop_graph.instance.num_machines
312
+ )
313
+
314
+ nx.draw_networkx_labels(
315
+ job_shop_graph.graph,
316
+ pos,
317
+ labels=labels,
318
+ font_color=node_font_color,
319
+ font_size=font_size,
320
+ font_family=font_family,
321
+ )
322
+ # Final touches
323
+ # -------------
324
+ plt.axis("off")
325
+ plt.tight_layout()
326
+ # Create a legend to indicate the meaning of the edge colors
327
+ conjunctive_patch = matplotlib.patches.Patch(
328
+ color=conjunctive_edge_color, label=conjunctive_patch_label
329
+ )
330
+ disjunctive_patch = matplotlib.patches.Patch(
331
+ color=disjunctive_edge_color, label=disjunctive_patch_label
332
+ )
333
+ handles = [conjunctive_patch, disjunctive_patch]
334
+
335
+ # Add machine colors to the legend
336
+ if show_machine_colors_in_legend:
337
+ machine_patches = [
338
+ matplotlib.patches.Patch(
339
+ color=color,
340
+ label=(
341
+ machine_labels[machine_id]
342
+ if machine_labels is not None
343
+ else f"Machine {machine_id}"
344
+ ),
345
+ )
346
+ for machine_id, color in machine_colors.items()
347
+ ]
348
+ handles.extend(machine_patches)
349
+
350
+ # Add to the legend the meaning of m and d
351
+ if legend_text:
352
+ extra = matplotlib.patches.Rectangle(
353
+ (0, 0),
354
+ 1,
355
+ 1,
356
+ fc="w",
357
+ fill=False,
358
+ edgecolor="none",
359
+ linewidth=0,
360
+ label=legend_text,
361
+ )
362
+ handles.append(extra)
363
+
364
+ plt.legend(
365
+ handles=handles,
366
+ loc=legend_location,
367
+ bbox_to_anchor=legend_bbox_to_anchor,
368
+ borderaxespad=0.0,
369
+ )
370
+ return plt.gcf(), plt.gca()
371
+
372
+
373
+ def _get_node_color(node: Node) -> int:
374
+ """Returns the color of the node."""
375
+ if node.node_type == NodeType.SOURCE:
376
+ return -1
377
+ if node.node_type == NodeType.SINK:
378
+ return -1
379
+ if node.node_type == NodeType.OPERATION:
380
+ return node.operation.machine_id
381
+
382
+ raise ValidationError("Invalid node type.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: job-shop-lib
3
- Version: 1.0.0a3
3
+ Version: 1.0.0a4
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
@@ -40,7 +40,7 @@ JobShopLib is a Python package for creating, solving, and visualizing Job Shop S
40
40
 
41
41
  It follows a modular design, allowing users to easily extend the library with new solvers, dispatching rules, visualization functions, etc.
42
42
 
43
- See the [documentation](https://job-shop-lib.readthedocs.io/en/latest/) for more details about the latest version (1.0.0a2).
43
+ See the [documentation](https://job-shop-lib.readthedocs.io/en/latest/) for more details about the latest version.
44
44
 
45
45
  ## Installation :package:
46
46
 
@@ -57,13 +57,13 @@ pip install job-shop-lib
57
57
  See [this](https://colab.research.google.com/drive/1XV_Rvq1F2ns6DFG8uNj66q_rcowwTZ4H?usp=sharing) Google Colab notebook for a quick start guide!
58
58
 
59
59
 
60
- Version 1.0.0 is currently in beta stage and can be installed with:
60
+ Version 1.0.0 is currently in alpha stage and can be installed with:
61
61
 
62
62
  ```bash
63
- pip install job-shop-lib==1.0.0a3
63
+ pip install job-shop-lib==1.0.0a4
64
64
  ```
65
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/).
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 familiarize 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
67
 
68
68
  <!-- end installation -->
69
69
 
@@ -1,66 +1,66 @@
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=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
3
+ job_shop_lib/_job_shop_instance.py,sha256=hc_rYHv0RRvcBmQLtXcSTZJ_YQxKBfhoSEcTNvf8Oio,18319
4
+ job_shop_lib/_operation.py,sha256=6YgAuqFQgvoGIYTkdsBh-b8mVlc0i9AIw8cqmiTXeHE,3809
5
+ job_shop_lib/_schedule.py,sha256=QQ7orbpd00pTjJvsh8bNuRSEFJLst8B8GaCSB8JPXTY,11251
6
+ job_shop_lib/_scheduled_operation.py,sha256=krjGn47VwsC7bXUTqlUq8Y-DpiSE9q2z8bqwgJVpAZo,2697
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
11
  job_shop_lib/constraint_programming/_ortools_solver.py,sha256=gRoImEBUa8_io-TzbSS-3f0CJ7UwacU5Lrz0bsDqibo,10462
12
12
  job_shop_lib/dispatching/__init__.py,sha256=2VQYWNSyuDx3zzrDPCEzs5VJd2AIJvF7vA7LwK5z2V4,1648
13
- job_shop_lib/dispatching/_dispatcher.py,sha256=o0BqZBub9flPAHX59qBHV2RETQg7n31xHe6owg9Ki7U,21305
14
- job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=l_lbaw9JJ5icVOmDAzAL6G5t6wG25bQLpRedN1bys8c,1932
15
- job_shop_lib/dispatching/_factories.py,sha256=MYnjuK9NOVU9n98mrNu5Z0svBIYBCTDbVGzUX9rDWsQ,4594
13
+ job_shop_lib/dispatching/_dispatcher.py,sha256=5B2KA0-nHLeFsZ1KxZxwLJ2muknzQVhwqUV4pFlo6bw,21218
14
+ job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=034m83TsZXAb89nPxGRZm--0KSaGA9tJnr-7aYQs6tU,2479
15
+ job_shop_lib/dispatching/_factories.py,sha256=njS5yUd5K74ceAUFcqofUlx0efMvfJB6twdZdrCqhfE,4596
16
16
  job_shop_lib/dispatching/_history_observer.py,sha256=Vl8rQaxekUeEB-AyNxyC3c76zQakeh-rdri2iDnZvXw,610
17
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
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
20
+ job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py,sha256=HnvNQTXvCX5HAqBdYqzY-cPjeP0VcUxP6OTXvIlMulk,7876
21
21
  job_shop_lib/dispatching/feature_observers/_duration_observer.py,sha256=fbkUIVScF1iNjdVCYr1ImQm53TfahvVnGXhsRAsgdzY,4129
22
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
23
+ job_shop_lib/dispatching/feature_observers/_factory.py,sha256=PLbpiJDPQRcicxyrIaBeyWnJRPlMVLJixzB44C0SXYE,3171
24
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
25
+ job_shop_lib/dispatching/feature_observers/_is_completed_observer.py,sha256=wG84zhmIWEXZjgT883Vz-onJZYpB7SJb2FsznEbkPQw,4592
26
26
  job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=wy_pA-1wmnzVjhq92mdsT2JJHYbfsm79mcMgSgYUCOs,1264
27
27
  job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py,sha256=OcuMUB9_By6ZMtX-1_3z-xaxGbP85a5Zv0ywAv7XxWQ,1491
28
28
  job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py,sha256=WRknpQBKXs6h6cXLFJW7ZCvjtU8CPL-iXXNPw3g-mLE,1303
29
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=YgcxDUx9RqwfTxWtoKesngYVFDsHiWtsm1BAUrAyerY,6353
32
+ job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=goO3wl5NY9mjRr6d3KBaImA7gpseFDawdZdRhkIM5bM,6349
33
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
37
37
  job_shop_lib/generation/__init__.py,sha256=hUqjnE0bEoknuUwFoLUWjBH26qTTCGsJAW4gscAbiQ8,294
38
- job_shop_lib/generation/_general_instance_generator.py,sha256=8DG70qT2TUTyPp-3Q1DHWo3DhtUvyB4Yo_u0eAa5CIc,7431
39
- job_shop_lib/generation/_instance_generator.py,sha256=fPcbNoyk0t1JtJpBMiwk3SlyPkWYNkYS7-Vs8qH_eDM,4642
40
- job_shop_lib/generation/_transformations.py,sha256=FI2qHrETATJUrQP3-RYhZAQ5boyEZ0CF2StDbacBej8,5290
41
- job_shop_lib/graphs/__init__.py,sha256=ALZNmvCi5XveMneVJ2VQpQ5msYwIqFWFloiwyFtJhAo,1709
38
+ job_shop_lib/generation/_general_instance_generator.py,sha256=uqSYzP6vW1SgmaRrTP1svjq-nPQXNJeXcKVW6gp9sdI,7318
39
+ job_shop_lib/generation/_instance_generator.py,sha256=e_A7lSV5IMG2vPeANp50S5bg19XrhiQ9rvzOP-US1l0,4504
40
+ job_shop_lib/generation/_transformations.py,sha256=ZigQTBsS3xgB2FhBu9MpsFs7A-_VY3840V_RtOIhCBk,5296
41
+ job_shop_lib/graphs/__init__.py,sha256=GEtrWjbeFEFpvNytlvqEU6ZUPZP7qX-71N659f9r2u8,1818
42
42
  job_shop_lib/graphs/_build_agent_task_graph.py,sha256=6mvWJ7fFD5CmxkTuXEwY7f_-qxjKdNgFmWk4a4mgiD8,7132
43
- job_shop_lib/graphs/_build_disjunctive_graph.py,sha256=z1jiuTTaWPJZj-vSZdo064quGx4LEDKjtZIb1FieZW4,3705
43
+ job_shop_lib/graphs/_build_disjunctive_graph.py,sha256=UbUYdeQaaeEqLchcKJGHEFGl4wElfGLb1o_R-u8wqnA,5120
44
44
  job_shop_lib/graphs/_constants.py,sha256=K-GeVvh_DTWpo1KOX1clmxWS_pkUJbq19yOBmrCVIxI,1086
45
45
  job_shop_lib/graphs/_job_shop_graph.py,sha256=Fv0TOwtmjqdhH-A_TBH0wSzQkGgqTyc7vvEcfzbQiwA,10681
46
46
  job_shop_lib/graphs/_node.py,sha256=hGgdnD9wlsTbkaDizFZMsxPXa2-m91iBNLu0vtkVbxw,6034
47
47
  job_shop_lib/graphs/graph_updaters/__init__.py,sha256=UhnZL55e3cAv7hVetB6bRmIOn8BDhG2bsbrdRoHtxLY,516
48
- job_shop_lib/graphs/graph_updaters/_graph_updater.py,sha256=H8PtBj4gv6y5wQKOstF2CSnLsFjO1YeVHpzvYK3vMRM,2053
49
- job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py,sha256=kPuBmion70-GAQsyFal8gHylHvZSoBJae9eF8iGOkvA,6097
48
+ job_shop_lib/graphs/graph_updaters/_graph_updater.py,sha256=j1f7iWsa62GVszK2BPaMxnKBCEGWa9owm8g4VWUje8w,1967
49
+ job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py,sha256=Sli9YpbtKlAvjEQxbc6gS1kOZneBD7RPqm_DagtJFe4,6009
50
50
  job_shop_lib/graphs/graph_updaters/_utils.py,sha256=X5YfwJA1CCgpm1r9C036Gal2CkDh2SSak7wl7TbdjHw,704
51
- job_shop_lib/reinforcement_learning/__init__.py,sha256=QVFo9e1X-tpanZkGdcCPV_WobQ2EZ_y5uoYSJ36XrQI,957
52
- job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py,sha256=jKMcWYBvz1kwlw00Xe1x9HqhFkMMqlh-Y95NmeBL3-0,15129
51
+ job_shop_lib/reinforcement_learning/__init__.py,sha256=gOY-C6BMeFr3084MKMMbW0CoK7gMsaOYNsgnYuepswQ,1033
52
+ job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py,sha256=N28SslcKBguhILQxisc7NIuR3XVnMrj1dzBSEKA8AdE,14865
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=ByQQ1fCCpji0VAjKTcbBOGST-3MF6oq2naAtdElJUh8,12953
55
- job_shop_lib/reinforcement_learning/_types_and_constants.py,sha256=CY849lbv6UXy40KRcMJT3WxvGWrLqcfysu65LPkTfg8,1715
54
+ job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py,sha256=_qZ69kvgpBUoRJDL0SYDxj3Lq6_8HT3MDaxJndqgon0,12970
55
+ job_shop_lib/reinforcement_learning/_types_and_constants.py,sha256=5lvjXihMrj2ziLlquLXQxtwzjLM5yo7Ny8kPo-aCmlQ,1737
56
56
  job_shop_lib/reinforcement_learning/_utils.py,sha256=ilI089Bs8CRlfRV_yH6XH8oypTDtRa7hS-H4iRCC5lU,2497
57
- job_shop_lib/visualization/__init__.py,sha256=SVxg7Dt3azETfI0IvUtLtCBsirXQWirdjEjOQ2d5eWU,1137
58
- job_shop_lib/visualization/_agent_task_graph.py,sha256=AaBTD_S34WjrsZnL_iMAplR_f67RahZi7x58SOvp-q0,8834
59
- job_shop_lib/visualization/_disjunctive_graph.py,sha256=pg4KG9BfQbnBPnXYgbyPGe0AuHSmhYqPeqWYAf_spWQ,5905
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
57
+ job_shop_lib/visualization/__init__.py,sha256=K85MQdAbsguvoH99NX9sxZP458jDXSljpzQiS_4-dlU,1587
58
+ job_shop_lib/visualization/_gantt_chart_creator.py,sha256=p7W7OaLoHO5xdlNaJXQVBweszb2bNuM6oP9TAhNgwss,8600
59
+ job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py,sha256=aPy7y0oZlEQUzoYQnagiRi_2C-80WY29HR2KpekS6wQ,14384
60
+ job_shop_lib/visualization/_plot_agent_task_graph.py,sha256=AaBTD_S34WjrsZnL_iMAplR_f67RahZi7x58SOvp-q0,8834
61
+ job_shop_lib/visualization/_plot_disjunctive_graph.py,sha256=Vo3c2oHQ8YkLbwrDr76zh4yzCuQk-gkVeyWN-7Zj71o,14279
62
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,,
63
+ job_shop_lib-1.0.0a4.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
64
+ job_shop_lib-1.0.0a4.dist-info/METADATA,sha256=14EToNDww1XMWqiMJguxDG6ER1ApNGnowyjBR5CC8vY,15656
65
+ job_shop_lib-1.0.0a4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
+ job_shop_lib-1.0.0a4.dist-info/RECORD,,