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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. job_shop_lib/_job_shop_instance.py +119 -55
  2. job_shop_lib/_operation.py +18 -7
  3. job_shop_lib/_schedule.py +13 -15
  4. job_shop_lib/_scheduled_operation.py +17 -18
  5. job_shop_lib/dispatching/__init__.py +4 -0
  6. job_shop_lib/dispatching/_dispatcher.py +36 -47
  7. job_shop_lib/dispatching/_dispatcher_observer_config.py +15 -2
  8. job_shop_lib/dispatching/_factories.py +10 -2
  9. job_shop_lib/dispatching/_ready_operation_filters.py +80 -0
  10. job_shop_lib/dispatching/feature_observers/_composite_feature_observer.py +0 -1
  11. job_shop_lib/dispatching/feature_observers/_factory.py +21 -18
  12. job_shop_lib/dispatching/feature_observers/_is_completed_observer.py +1 -0
  13. job_shop_lib/dispatching/feature_observers/_is_ready_observer.py +1 -1
  14. job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +44 -25
  15. job_shop_lib/dispatching/rules/_dispatching_rules_functions.py +9 -9
  16. job_shop_lib/generation/_general_instance_generator.py +33 -34
  17. job_shop_lib/generation/_instance_generator.py +14 -17
  18. job_shop_lib/generation/_transformations.py +11 -8
  19. job_shop_lib/graphs/__init__.py +3 -0
  20. job_shop_lib/graphs/_build_disjunctive_graph.py +41 -3
  21. job_shop_lib/graphs/graph_updaters/_graph_updater.py +11 -13
  22. job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py +17 -20
  23. job_shop_lib/reinforcement_learning/__init__.py +16 -7
  24. job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py +69 -57
  25. job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py +43 -32
  26. job_shop_lib/reinforcement_learning/_types_and_constants.py +2 -2
  27. job_shop_lib/visualization/__init__.py +29 -10
  28. job_shop_lib/visualization/_gantt_chart_creator.py +122 -84
  29. job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py +68 -37
  30. job_shop_lib/visualization/_plot_disjunctive_graph.py +382 -0
  31. job_shop_lib/visualization/{_gantt_chart.py → _plot_gantt_chart.py} +78 -14
  32. {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/METADATA +15 -3
  33. {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/RECORD +36 -36
  34. {job_shop_lib-1.0.0a2.dist-info → job_shop_lib-1.0.0a4.dist-info}/WHEEL +1 -1
  35. job_shop_lib/visualization/_disjunctive_graph.py +0 -210
  36. /job_shop_lib/visualization/{_agent_task_graph.py → _plot_agent_task_graph.py} +0 -0
  37. {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=Q0ml3C36tmcBskBo8MyaZWILJPbdvHjJcvXzD_YfLsU,16475
4
- job_shop_lib/_operation.py,sha256=lJ4srQs82cYhUYuBxqkfKr9MuZoG0X2x0z3M1_QXkAs,3360
5
- job_shop_lib/_schedule.py,sha256=H6PREUE9KCC0DtrQV8y9MB8S4sh3qnDwby5Y4WVDfzg,11333
6
- job_shop_lib/_scheduled_operation.py,sha256=ptqYRW39EvG5tnk4DLQGFCOkbGTTYIQJhUMcuLSbdSA,2812
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=QV7qy-y0sSoKp_FslTm7sdqczYzpq0YctzKQ36l0ykg,1510
13
- job_shop_lib/dispatching/_dispatcher.py,sha256=PCSBpYAF6QPXWrjwkBQXTxOdGdq6Y1Uqw8esQTW05TQ,21357
14
- job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=l_lbaw9JJ5icVOmDAzAL6G5t6wG25bQLpRedN1bys8c,1932
15
- job_shop_lib/dispatching/_factories.py,sha256=UAZLq7d_-puzMYteiAbbhkcW5ucKO-lo3bj8pCCEnOA,4229
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=q8Xv4kp_2GsvEMC5mlTuJXivAz_b8bbrqo5sXaS3PJU,3110
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
26
- job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=KYDUO3Zz1wgkClZ64i5-az6W-SFpi8rckAlv4Zjcii4,1260
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=Nb3EPSIdnbeqKaIf5ufE2zxQsNpNkZxmYa0Eh1jnCnw,5537
33
- job_shop_lib/dispatching/rules/_dispatching_rules_functions.py,sha256=Wb9fQIfePvCJi4RqJ59UrRSnYufgQw5nQ_Am8M6-JOI,7569
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=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=Kbd3N1rKcXm6IHTo99En-oX85vqVobv2bFBCyAht2mE,12949
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=jXC188u5AnSWcO1lRZEzZAPZTXbqlYSPhYc7LMc0itU,1094
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.py,sha256=B9sn4XrEUqgQhRKju-1VUG5R67AZXRu7jbrtA8VcndU,4412
61
- job_shop_lib/visualization/_gantt_chart_creator.py,sha256=qFhCfk3oC3uF7Mau3lrNhH-34sfHXvkqEXbsDzrIbBk,7721
62
- job_shop_lib/visualization/_gantt_chart_video_and_gif_creation.py,sha256=GQhQF2YzSRQT_DdUjJYHFKMZMjk_hPrYjQU5PpedNvs,13213
63
- job_shop_lib-1.0.0a2.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
64
- job_shop_lib-1.0.0a2.dist-info/METADATA,sha256=IVDNFeNtFCpjUzIGXkEn0uQ3aBgJLSLXHuJKEgpBajI,14810
65
- job_shop_lib-1.0.0a2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
66
- job_shop_lib-1.0.0a2.dist-info/RECORD,,
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,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -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.")