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.
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.")