job-shop-lib 1.0.0a2__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.
- job_shop_lib/_job_shop_instance.py +119 -55
- job_shop_lib/_operation.py +18 -7
- job_shop_lib/_schedule.py +13 -15
- job_shop_lib/_scheduled_operation.py +17 -18
- job_shop_lib/dispatching/__init__.py +4 -0
- job_shop_lib/dispatching/_dispatcher.py +36 -47
- job_shop_lib/dispatching/_dispatcher_observer_config.py +15 -2
- job_shop_lib/dispatching/_factories.py +10 -2
- job_shop_lib/dispatching/_ready_operation_filters.py +80 -0
- job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +0 -1
- job_shop_lib/dispatching/feature_observers/_factory.py +21 -18
- job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +1 -0
- job_shop_lib/dispatching/feature_observers/_is_ready_observer.py +1 -1
- job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +44 -25
- job_shop_lib/dispatching/rules/_dispatching_rules_functions.py +9 -9
- job_shop_lib/generation/_general_instance_generator.py +33 -34
- job_shop_lib/generation/_instance_generator.py +14 -17
- job_shop_lib/generation/_transformations.py +11 -8
- job_shop_lib/graphs/__init__.py +3 -0
- job_shop_lib/graphs/_build_disjunctive_graph.py +41 -3
- job_shop_lib/graphs/graph_updaters/_graph_updater.py +11 -13
- job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py +17 -20
- job_shop_lib/reinforcement_learning/__init__.py +16 -7
- job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py +69 -57
- job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +43 -32
- job_shop_lib/reinforcement_learning/_types_and_constants.py +2 -2
- job_shop_lib/visualization/__init__.py +29 -10
- job_shop_lib/visualization/_gantt_chart_creator.py +122 -84
- job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py +68 -37
- job_shop_lib/visualization/_plot_disjunctive_graph.py +382 -0
- job_shop_lib/visualization/{_gantt_chart.py → _plot_gantt_chart.py} +78 -14
- {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/METADATA +15 -3
- {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/RECORD +36 -36
- {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/WHEEL +1 -1
- job_shop_lib/visualization/_disjunctive_graph.py +0 -210
- /job_shop_lib/visualization/{_agent_task_graph.py → _plot_agent_task_graph.py} +0 -0
- {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/LICENSE +0 -0
@@ -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=
|
4
|
-
job_shop_lib/_operation.py,sha256=
|
5
|
-
job_shop_lib/_schedule.py,sha256=
|
6
|
-
job_shop_lib/_scheduled_operation.py,sha256=
|
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
|
-
job_shop_lib/dispatching/__init__.py,sha256=
|
13
|
-
job_shop_lib/dispatching/_dispatcher.py,sha256=
|
14
|
-
job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=
|
15
|
-
job_shop_lib/dispatching/_factories.py,sha256=
|
12
|
+
job_shop_lib/dispatching/__init__.py,sha256=2VQYWNSyuDx3zzrDPCEzs5VJd2AIJvF7vA7LwK5z2V4,1648
|
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
|
-
job_shop_lib/dispatching/_ready_operation_filters.py,sha256=
|
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=
|
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=
|
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=
|
26
|
-
job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=
|
25
|
+
job_shop_lib/dispatching/feature_observers/_is_completed_observer.py,sha256=wG84zhmIWEXZjgT883Vz-onJZYpB7SJb2FsznEbkPQw,4592
|
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=
|
33
|
-
job_shop_lib/dispatching/rules/_dispatching_rules_functions.py,sha256=
|
32
|
+
job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=goO3wl5NY9mjRr6d3KBaImA7gpseFDawdZdRhkIM5bM,6349
|
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=
|
39
|
-
job_shop_lib/generation/_instance_generator.py,sha256=
|
40
|
-
job_shop_lib/generation/_transformations.py,sha256=
|
41
|
-
job_shop_lib/graphs/__init__.py,sha256=
|
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=
|
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=
|
49
|
-
job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py,sha256=
|
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=
|
52
|
-
job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py,sha256=
|
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=
|
55
|
-
job_shop_lib/reinforcement_learning/_types_and_constants.py,sha256=
|
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=
|
58
|
-
job_shop_lib/visualization/
|
59
|
-
job_shop_lib/visualization/
|
60
|
-
job_shop_lib/visualization/
|
61
|
-
job_shop_lib/visualization/
|
62
|
-
job_shop_lib/visualization/
|
63
|
-
job_shop_lib-1.0.
|
64
|
-
job_shop_lib-1.0.
|
65
|
-
job_shop_lib-1.0.
|
66
|
-
job_shop_lib-1.0.
|
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
|
+
job_shop_lib/visualization/_plot_gantt_chart.py,sha256=1WCJ5Gjl3dwA-w4Jn9suIg-ZGR28yYUAy8Jp-IiyvfI,6842
|
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,,
|
@@ -1,210 +0,0 @@
|
|
1
|
-
"""Module for visualizing the disjunctive graph of a job shop instance."""
|
2
|
-
|
3
|
-
import functools
|
4
|
-
from typing import Optional, Callable
|
5
|
-
import warnings
|
6
|
-
import copy
|
7
|
-
|
8
|
-
import matplotlib
|
9
|
-
import matplotlib.pyplot as plt
|
10
|
-
import networkx as nx
|
11
|
-
from networkx.drawing.nx_agraph import graphviz_layout
|
12
|
-
|
13
|
-
from job_shop_lib import JobShopInstance
|
14
|
-
from job_shop_lib.graphs import (
|
15
|
-
JobShopGraph,
|
16
|
-
EdgeType,
|
17
|
-
NodeType,
|
18
|
-
Node,
|
19
|
-
build_disjunctive_graph,
|
20
|
-
)
|
21
|
-
|
22
|
-
|
23
|
-
Layout = Callable[[nx.Graph], dict[str, tuple[float, float]]]
|
24
|
-
|
25
|
-
|
26
|
-
# This function could be improved by a function extraction refactoring
|
27
|
-
# (see `plot_gantt_chart`
|
28
|
-
# function as a reference in how to do it). That would solve the
|
29
|
-
# "too many locals" warning. However, this refactoring is not a priority at
|
30
|
-
# the moment. To compensate, sections are separated by comments.
|
31
|
-
# For the "too many arguments" warning no satisfactory solution was
|
32
|
-
# found. I believe is still better than using `**kwargs` and losing the
|
33
|
-
# function signature or adding a dataclass for configuration (it would add
|
34
|
-
# unnecessary complexity).
|
35
|
-
# pylint: disable=too-many-arguments, too-many-locals
|
36
|
-
def plot_disjunctive_graph(
|
37
|
-
job_shop: JobShopGraph | JobShopInstance,
|
38
|
-
figsize: tuple[float, float] = (6, 4),
|
39
|
-
node_size: int = 1600,
|
40
|
-
title: Optional[str] = None,
|
41
|
-
layout: Optional[Layout] = None,
|
42
|
-
edge_width: int = 2,
|
43
|
-
font_size: int = 10,
|
44
|
-
arrow_size: int = 35,
|
45
|
-
alpha=0.95,
|
46
|
-
node_font_color: str = "white",
|
47
|
-
color_map: str = "Dark2_r",
|
48
|
-
draw_disjunctive_edges: bool = True,
|
49
|
-
) -> plt.Figure:
|
50
|
-
"""Returns a plot of the disjunctive graph of the instance."""
|
51
|
-
|
52
|
-
if isinstance(job_shop, JobShopInstance):
|
53
|
-
job_shop_graph = build_disjunctive_graph(job_shop)
|
54
|
-
else:
|
55
|
-
job_shop_graph = job_shop
|
56
|
-
|
57
|
-
# Set up the plot
|
58
|
-
# ----------------
|
59
|
-
plt.figure(figsize=figsize)
|
60
|
-
if title is None:
|
61
|
-
title = (
|
62
|
-
f"Disjunctive Graph Visualization: {job_shop_graph.instance.name}"
|
63
|
-
)
|
64
|
-
plt.title(title)
|
65
|
-
|
66
|
-
# Set up the layout
|
67
|
-
# -----------------
|
68
|
-
if layout is None:
|
69
|
-
layout = functools.partial(
|
70
|
-
graphviz_layout, prog="dot", args="-Grankdir=LR"
|
71
|
-
)
|
72
|
-
|
73
|
-
temp_graph = copy.deepcopy(job_shop_graph.graph)
|
74
|
-
# Remove disjunctive edges to get a better layout
|
75
|
-
temp_graph.remove_edges_from(
|
76
|
-
[
|
77
|
-
(u, v)
|
78
|
-
for u, v, d in job_shop_graph.graph.edges(data=True)
|
79
|
-
if d["type"] == EdgeType.DISJUNCTIVE
|
80
|
-
]
|
81
|
-
)
|
82
|
-
|
83
|
-
try:
|
84
|
-
pos = layout(temp_graph)
|
85
|
-
except ImportError:
|
86
|
-
warnings.warn(
|
87
|
-
"Default layout requires pygraphviz http://pygraphviz.github.io/. "
|
88
|
-
"Using spring layout instead.",
|
89
|
-
)
|
90
|
-
pos = nx.spring_layout(temp_graph)
|
91
|
-
|
92
|
-
# Draw nodes
|
93
|
-
# ----------
|
94
|
-
node_colors = [
|
95
|
-
_get_node_color(node)
|
96
|
-
for node in job_shop_graph.nodes
|
97
|
-
if not job_shop_graph.is_removed(node.node_id)
|
98
|
-
]
|
99
|
-
|
100
|
-
nx.draw_networkx_nodes(
|
101
|
-
job_shop_graph.graph,
|
102
|
-
pos,
|
103
|
-
node_size=node_size,
|
104
|
-
node_color=node_colors,
|
105
|
-
alpha=alpha,
|
106
|
-
cmap=matplotlib.colormaps.get_cmap(color_map),
|
107
|
-
)
|
108
|
-
|
109
|
-
# Draw edges
|
110
|
-
# ----------
|
111
|
-
conjunctive_edges = [
|
112
|
-
(u, v)
|
113
|
-
for u, v, d in job_shop_graph.graph.edges(data=True)
|
114
|
-
if d["type"] == EdgeType.CONJUNCTIVE
|
115
|
-
]
|
116
|
-
disjunctive_edges = [
|
117
|
-
(u, v)
|
118
|
-
for u, v, d in job_shop_graph.graph.edges(data=True)
|
119
|
-
if d["type"] == EdgeType.DISJUNCTIVE
|
120
|
-
]
|
121
|
-
|
122
|
-
nx.draw_networkx_edges(
|
123
|
-
job_shop_graph.graph,
|
124
|
-
pos,
|
125
|
-
edgelist=conjunctive_edges,
|
126
|
-
width=edge_width,
|
127
|
-
edge_color="black",
|
128
|
-
arrowsize=arrow_size,
|
129
|
-
)
|
130
|
-
|
131
|
-
if draw_disjunctive_edges:
|
132
|
-
nx.draw_networkx_edges(
|
133
|
-
job_shop_graph.graph,
|
134
|
-
pos,
|
135
|
-
edgelist=disjunctive_edges,
|
136
|
-
width=edge_width,
|
137
|
-
edge_color="red",
|
138
|
-
arrowsize=arrow_size,
|
139
|
-
)
|
140
|
-
|
141
|
-
# Draw node labels
|
142
|
-
# ----------------
|
143
|
-
operation_nodes = job_shop_graph.nodes_by_type[NodeType.OPERATION]
|
144
|
-
|
145
|
-
labels = {}
|
146
|
-
source_node = job_shop_graph.nodes_by_type[NodeType.SOURCE][0]
|
147
|
-
labels[source_node] = "S"
|
148
|
-
|
149
|
-
sink_node = job_shop_graph.nodes_by_type[NodeType.SINK][0]
|
150
|
-
labels[sink_node] = "T"
|
151
|
-
for operation_node in operation_nodes:
|
152
|
-
if job_shop_graph.is_removed(operation_node.node_id):
|
153
|
-
continue
|
154
|
-
labels[operation_node] = (
|
155
|
-
f"m={operation_node.operation.machine_id}\n"
|
156
|
-
f"d={operation_node.operation.duration}"
|
157
|
-
)
|
158
|
-
|
159
|
-
nx.draw_networkx_labels(
|
160
|
-
job_shop_graph.graph,
|
161
|
-
pos,
|
162
|
-
labels=labels,
|
163
|
-
font_color=node_font_color,
|
164
|
-
font_size=font_size,
|
165
|
-
font_family="sans-serif",
|
166
|
-
)
|
167
|
-
|
168
|
-
# Final touches
|
169
|
-
# -------------
|
170
|
-
plt.axis("off")
|
171
|
-
plt.tight_layout()
|
172
|
-
# Create a legend to indicate the meaning of the edge colors
|
173
|
-
conjunctive_patch = matplotlib.patches.Patch(
|
174
|
-
color="black", label="conjunctive edges"
|
175
|
-
)
|
176
|
-
disjunctive_patch = matplotlib.patches.Patch(
|
177
|
-
color="red", label="disjunctive edges"
|
178
|
-
)
|
179
|
-
|
180
|
-
# Add to the legend the meaning of m and d
|
181
|
-
text = "m = machine_id\nd = duration"
|
182
|
-
extra = matplotlib.patches.Rectangle(
|
183
|
-
(0, 0),
|
184
|
-
1,
|
185
|
-
1,
|
186
|
-
fc="w",
|
187
|
-
fill=False,
|
188
|
-
edgecolor="none",
|
189
|
-
linewidth=0,
|
190
|
-
label=text,
|
191
|
-
)
|
192
|
-
plt.legend(
|
193
|
-
handles=[conjunctive_patch, disjunctive_patch, extra],
|
194
|
-
loc="upper left",
|
195
|
-
bbox_to_anchor=(1.05, 1),
|
196
|
-
borderaxespad=0.0,
|
197
|
-
)
|
198
|
-
return plt.gcf()
|
199
|
-
|
200
|
-
|
201
|
-
def _get_node_color(node: Node) -> int:
|
202
|
-
"""Returns the color of the node."""
|
203
|
-
if node.node_type == NodeType.SOURCE:
|
204
|
-
return -1
|
205
|
-
if node.node_type == NodeType.SINK:
|
206
|
-
return -1
|
207
|
-
if node.node_type == NodeType.OPERATION:
|
208
|
-
return node.operation.machine_id
|
209
|
-
|
210
|
-
raise ValueError("Invalid node type.")
|
File without changes
|
File without changes
|