job-shop-lib 1.0.0b1__py3-none-any.whl → 1.0.0b3__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- job_shop_lib/__init__.py +1 -1
- job_shop_lib/dispatching/__init__.py +4 -3
- job_shop_lib/dispatching/_optimal_operations_observer.py +115 -0
- job_shop_lib/dispatching/rules/__init__.py +37 -1
- job_shop_lib/dispatching/rules/_dispatching_rule_solver.py +27 -5
- job_shop_lib/graphs/__init__.py +3 -3
- job_shop_lib/reinforcement_learning/__init__.py +6 -1
- job_shop_lib/reinforcement_learning/_utils.py +39 -3
- job_shop_lib/visualization/graphs/__init__.py +1 -1
- {job_shop_lib-1.0.0b1.dist-info → job_shop_lib-1.0.0b3.dist-info}/METADATA +3 -3
- {job_shop_lib-1.0.0b1.dist-info → job_shop_lib-1.0.0b3.dist-info}/RECORD +13 -12
- {job_shop_lib-1.0.0b1.dist-info → job_shop_lib-1.0.0b3.dist-info}/LICENSE +0 -0
- {job_shop_lib-1.0.0b1.dist-info → job_shop_lib-1.0.0b3.dist-info}/WHEEL +0 -0
job_shop_lib/__init__.py
CHANGED
@@ -8,6 +8,7 @@ Problem step-by-step.
|
|
8
8
|
DispatcherObserver
|
9
9
|
HistoryObserver
|
10
10
|
UnscheduledOperationsObserver
|
11
|
+
OptimalOperationsObserver
|
11
12
|
ReadyOperationsFilter
|
12
13
|
DispatcherObserverConfig
|
13
14
|
filter_dominated_operations
|
@@ -25,9 +26,8 @@ from ._dispatcher import Dispatcher, DispatcherObserver
|
|
25
26
|
from ._history_observer import (
|
26
27
|
HistoryObserver,
|
27
28
|
)
|
28
|
-
from ._unscheduled_operations_observer import
|
29
|
-
|
30
|
-
)
|
29
|
+
from ._unscheduled_operations_observer import UnscheduledOperationsObserver
|
30
|
+
from ._optimal_operations_observer import OptimalOperationsObserver
|
31
31
|
from ._ready_operation_filters import (
|
32
32
|
filter_dominated_operations,
|
33
33
|
filter_non_immediate_machines,
|
@@ -57,4 +57,5 @@ __all__ = [
|
|
57
57
|
"ReadyOperationsFilter",
|
58
58
|
"filter_non_idle_machines",
|
59
59
|
"filter_non_immediate_operations",
|
60
|
+
"OptimalOperationsObserver",
|
60
61
|
]
|
@@ -0,0 +1,115 @@
|
|
1
|
+
"""Home of the `OptimalOperationsObserver` class."""
|
2
|
+
|
3
|
+
from typing import List, Set, Dict
|
4
|
+
from job_shop_lib.dispatching import DispatcherObserver, Dispatcher
|
5
|
+
from job_shop_lib import Schedule, Operation, ScheduledOperation
|
6
|
+
from job_shop_lib.exceptions import ValidationError
|
7
|
+
|
8
|
+
|
9
|
+
class OptimalOperationsObserver(DispatcherObserver):
|
10
|
+
"""Observer that identifies which available operations are optimal based on
|
11
|
+
a reference schedule.
|
12
|
+
|
13
|
+
This observer compares the available operations at each step with a
|
14
|
+
reference schedule to determine which operations would lead to the optimal
|
15
|
+
solution. It can be used for training purposes or to analyze decision
|
16
|
+
making in dispatching algorithms.
|
17
|
+
|
18
|
+
Attributes:
|
19
|
+
optimal_operations: Set of operations that are considered optimal
|
20
|
+
based on the reference schedule.
|
21
|
+
reference_schedule: The reference schedule used to determine optimal
|
22
|
+
operations.
|
23
|
+
_operation_to_scheduled: Dictionary mapping operations to their
|
24
|
+
scheduled versions in the reference schedule.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
dispatcher: The dispatcher instance to observe.
|
28
|
+
reference_schedule: A complete schedule that represents the optimal
|
29
|
+
or reference solution.
|
30
|
+
subscribe: If True, automatically subscribes to the dispatcher.
|
31
|
+
|
32
|
+
Raises:
|
33
|
+
ValidationError: If the reference schedule is incomplete or if it
|
34
|
+
doesn't match the dispatcher's instance.
|
35
|
+
"""
|
36
|
+
|
37
|
+
_is_singleton = False
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
dispatcher: Dispatcher,
|
42
|
+
reference_schedule: Schedule,
|
43
|
+
*,
|
44
|
+
subscribe: bool = True,
|
45
|
+
):
|
46
|
+
super().__init__(dispatcher, subscribe=subscribe)
|
47
|
+
|
48
|
+
if not reference_schedule.is_complete():
|
49
|
+
raise ValidationError("Reference schedule must be complete.")
|
50
|
+
|
51
|
+
if reference_schedule.instance != dispatcher.instance:
|
52
|
+
raise ValidationError(
|
53
|
+
"Reference schedule instance does not match dispatcher "
|
54
|
+
"instance."
|
55
|
+
)
|
56
|
+
|
57
|
+
self.reference_schedule = reference_schedule
|
58
|
+
self.optimal_available: Set[Operation] = set()
|
59
|
+
self._operation_to_scheduled: Dict[Operation, ScheduledOperation] = {}
|
60
|
+
self._machine_next_operation_index: List[int] = [0] * len(
|
61
|
+
reference_schedule.schedule
|
62
|
+
)
|
63
|
+
|
64
|
+
self._build_operation_mapping()
|
65
|
+
self._update_optimal_operations()
|
66
|
+
|
67
|
+
def _build_operation_mapping(self) -> None:
|
68
|
+
"""Builds a mapping from operations to their scheduled versions in
|
69
|
+
the reference schedule."""
|
70
|
+
for machine_schedule in self.reference_schedule.schedule:
|
71
|
+
for scheduled_op in machine_schedule:
|
72
|
+
self._operation_to_scheduled[scheduled_op.operation] = (
|
73
|
+
scheduled_op
|
74
|
+
)
|
75
|
+
|
76
|
+
def _update_optimal_operations(self) -> None:
|
77
|
+
"""Updates the set of optimal operations based on current state.
|
78
|
+
|
79
|
+
An operation is considered optimal if it is the next unscheduled
|
80
|
+
operation in its machine's sequence according to the reference
|
81
|
+
schedule.
|
82
|
+
"""
|
83
|
+
self.optimal_available.clear()
|
84
|
+
available_operations = self.dispatcher.available_operations()
|
85
|
+
|
86
|
+
if not available_operations:
|
87
|
+
return
|
88
|
+
|
89
|
+
for operation in available_operations:
|
90
|
+
scheduled_op = self._operation_to_scheduled[operation]
|
91
|
+
machine_index = scheduled_op.machine_id
|
92
|
+
next_index = self._machine_next_operation_index[machine_index]
|
93
|
+
|
94
|
+
if (
|
95
|
+
scheduled_op
|
96
|
+
== self.reference_schedule.schedule[machine_index][next_index]
|
97
|
+
):
|
98
|
+
self.optimal_available.add(operation)
|
99
|
+
|
100
|
+
def update(self, scheduled_operation: ScheduledOperation) -> None:
|
101
|
+
"""Updates the optimal operations after an operation is scheduled.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
scheduled_operation: The operation that was just scheduled.
|
105
|
+
"""
|
106
|
+
self._machine_next_operation_index[scheduled_operation.machine_id] += 1
|
107
|
+
self._update_optimal_operations()
|
108
|
+
|
109
|
+
def reset(self) -> None:
|
110
|
+
"""Resets the observer to its initial state."""
|
111
|
+
self._machine_next_operation_index = [0] * len(
|
112
|
+
self.dispatcher.schedule.schedule
|
113
|
+
)
|
114
|
+
self.optimal_available.clear()
|
115
|
+
self._update_optimal_operations()
|
@@ -1,4 +1,40 @@
|
|
1
|
-
"""Contains the dispatching rules for the job shop scheduling problem.
|
1
|
+
"""Contains the dispatching rules for the job shop scheduling problem.
|
2
|
+
|
3
|
+
Main objects:
|
4
|
+
|
5
|
+
.. autosummary::
|
6
|
+
|
7
|
+
DispatchingRuleSolver
|
8
|
+
dispatching_rule_factory
|
9
|
+
DispatchingRuleType
|
10
|
+
MachineChooserType
|
11
|
+
dispatching_rule_factory
|
12
|
+
machine_chooser_factory
|
13
|
+
|
14
|
+
Dispatching rules:
|
15
|
+
|
16
|
+
.. autosummary::
|
17
|
+
|
18
|
+
shortest_processing_time_rule
|
19
|
+
first_come_first_served_rule
|
20
|
+
most_work_remaining_rule
|
21
|
+
most_operations_remaining_rule
|
22
|
+
random_operation_rule
|
23
|
+
score_based_rule
|
24
|
+
score_based_rule_with_tie_breaker
|
25
|
+
observer_based_most_work_remaining_rule
|
26
|
+
|
27
|
+
Dispatching rule scorers:
|
28
|
+
|
29
|
+
.. autosummary::
|
30
|
+
|
31
|
+
shortest_processing_time_score
|
32
|
+
first_come_first_served_score
|
33
|
+
MostWorkRemainingScorer
|
34
|
+
most_operations_remaining_score
|
35
|
+
random_score
|
36
|
+
|
37
|
+
"""
|
2
38
|
|
3
39
|
from ._dispatching_rules_functions import (
|
4
40
|
shortest_processing_time_rule,
|
@@ -30,14 +30,14 @@ class DispatchingRuleSolver(BaseSolver):
|
|
30
30
|
Used to choose the machine where the operation will be dispatched
|
31
31
|
to. It is only used if the operation can be dispatched to multiple
|
32
32
|
machines.
|
33
|
-
|
34
|
-
The
|
33
|
+
ready_operations_filter:
|
34
|
+
The ready operations filter to use. It is used to initialize the
|
35
35
|
dispatcher object internally when calling the solve method.
|
36
36
|
|
37
37
|
Args:
|
38
38
|
dispatching_rule:
|
39
39
|
The dispatching rule to use. It can be a string with the name
|
40
|
-
of the dispatching rule, a class
|
40
|
+
of the dispatching rule, a :class:`DispatchingRuleType` member,
|
41
41
|
or a callable that takes a dispatcher and returns the operation to
|
42
42
|
be dispatched next.
|
43
43
|
machine_chooser:
|
@@ -110,8 +110,30 @@ class DispatchingRuleSolver(BaseSolver):
|
|
110
110
|
instance: JobShopInstance,
|
111
111
|
dispatcher: Optional[Dispatcher] = None,
|
112
112
|
) -> Schedule:
|
113
|
-
"""
|
114
|
-
|
113
|
+
"""Solves the instance using the dispatching rule and machine chooser
|
114
|
+
algorithms.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
instance:
|
118
|
+
The job shop instance to be solved.
|
119
|
+
dispatcher:
|
120
|
+
The dispatcher object that will be used to dispatch the
|
121
|
+
operations. If not provided, a new dispatcher will be created
|
122
|
+
using the ready operations filter provided in the constructor.
|
123
|
+
|
124
|
+
Returns:
|
125
|
+
The schedule obtained after solving the instance.
|
126
|
+
|
127
|
+
.. tip::
|
128
|
+
Another way to use the solver is by calling it as a function. This
|
129
|
+
will call the ``solve`` method internally and will add metadata to
|
130
|
+
the schedule. For example:
|
131
|
+
|
132
|
+
.. code-block:: python
|
133
|
+
|
134
|
+
solver = DispatchingRuleSolver()
|
135
|
+
schedule = solver(instance)
|
136
|
+
"""
|
115
137
|
if dispatcher is None:
|
116
138
|
dispatcher = Dispatcher(
|
117
139
|
instance, ready_operations_filter=self.ready_operations_filter
|
job_shop_lib/graphs/__init__.py
CHANGED
@@ -8,9 +8,9 @@ The main classes and functions available in this package are:
|
|
8
8
|
NodeType
|
9
9
|
build_disjunctive_graph
|
10
10
|
build_solved_disjunctive_graph
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
build_resource_task_graph
|
12
|
+
build_complete_resource_task_graph
|
13
|
+
build_resource_task_graph_with_jobs
|
14
14
|
|
15
15
|
"""
|
16
16
|
|
@@ -12,6 +12,7 @@
|
|
12
12
|
IdleTimeReward
|
13
13
|
RenderConfig
|
14
14
|
add_padding
|
15
|
+
create_edge_type_dict
|
15
16
|
|
16
17
|
"""
|
17
18
|
|
@@ -27,7 +28,10 @@ from job_shop_lib.reinforcement_learning._reward_observers import (
|
|
27
28
|
IdleTimeReward,
|
28
29
|
)
|
29
30
|
|
30
|
-
from job_shop_lib.reinforcement_learning._utils import
|
31
|
+
from job_shop_lib.reinforcement_learning._utils import (
|
32
|
+
add_padding,
|
33
|
+
create_edge_type_dict,
|
34
|
+
)
|
31
35
|
|
32
36
|
from job_shop_lib.reinforcement_learning._single_job_shop_graph_env import (
|
33
37
|
SingleJobShopGraphEnv,
|
@@ -47,4 +51,5 @@ __all__ = [
|
|
47
51
|
"ObservationDict",
|
48
52
|
"add_padding",
|
49
53
|
"MultiJobShopGraphEnv",
|
54
|
+
"create_edge_type_dict",
|
50
55
|
]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"""Utility functions for reinforcement learning."""
|
2
2
|
|
3
|
-
from typing import TypeVar, Any,
|
3
|
+
from typing import TypeVar, Any, Type, Literal
|
4
4
|
|
5
5
|
import numpy as np
|
6
6
|
from numpy.typing import NDArray
|
@@ -12,9 +12,9 @@ T = TypeVar("T", bound=np.number)
|
|
12
12
|
|
13
13
|
def add_padding(
|
14
14
|
array: NDArray[Any],
|
15
|
-
output_shape:
|
15
|
+
output_shape: tuple[int, ...],
|
16
16
|
padding_value: float = -1,
|
17
|
-
dtype:
|
17
|
+
dtype: Type[T] | None = None,
|
18
18
|
) -> NDArray[T]:
|
19
19
|
"""Adds padding to the array.
|
20
20
|
|
@@ -90,6 +90,42 @@ def add_padding(
|
|
90
90
|
return padded_array
|
91
91
|
|
92
92
|
|
93
|
+
def create_edge_type_dict(
|
94
|
+
edge_index: NDArray[T], type_ranges: dict[str, tuple[int, int]]
|
95
|
+
) -> dict[tuple[str, Literal["to"], str], NDArray[T]]:
|
96
|
+
"""Organizes edges based on node types.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
edge_index:
|
100
|
+
numpy array of shape (2, E) where E is number of edges
|
101
|
+
type_ranges: dict[str, tuple[int, int]]
|
102
|
+
Dictionary mapping type names to their corresponding index ranges
|
103
|
+
[start, end) in the ``edge_index`` array.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
A dictionary with keys (type_i, "to", type_j) and values as edge
|
107
|
+
indices
|
108
|
+
"""
|
109
|
+
edge_index_dict: dict[tuple[str, Literal["to"], str], NDArray] = {}
|
110
|
+
for type_name_i, (start_i, end_i) in type_ranges.items():
|
111
|
+
for type_name_j, (start_j, end_j) in type_ranges.items():
|
112
|
+
key: tuple[str, Literal["to"], str] = (
|
113
|
+
type_name_i,
|
114
|
+
"to",
|
115
|
+
type_name_j,
|
116
|
+
)
|
117
|
+
# Find edges where source is in type_i and target is in type_j
|
118
|
+
mask = (
|
119
|
+
(edge_index[0] >= start_i)
|
120
|
+
& (edge_index[0] < end_i)
|
121
|
+
& (edge_index[1] >= start_j)
|
122
|
+
& (edge_index[1] < end_j)
|
123
|
+
)
|
124
|
+
edge_index_dict[key] = edge_index[:, mask]
|
125
|
+
|
126
|
+
return edge_index_dict
|
127
|
+
|
128
|
+
|
93
129
|
if __name__ == "__main__":
|
94
130
|
import doctest
|
95
131
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: job-shop-lib
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.0b3
|
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
|
@@ -57,10 +57,10 @@ 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
|
60
|
+
Version 1.0.0 is currently in beta stage and can be installed with:
|
61
61
|
|
62
62
|
```bash
|
63
|
-
pip install job-shop-lib==1.0.
|
63
|
+
pip install job-shop-lib==1.0.0b3
|
64
64
|
```
|
65
65
|
|
66
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)). There is a [documentation page](https://job-shop-lib.readthedocs.io/en/latest/) for versions 1.0.0a3 and onward.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
job_shop_lib/__init__.py,sha256=
|
1
|
+
job_shop_lib/__init__.py,sha256=fj4EeaNf1NTAbpB0EH9OnhS_MjP1MCe03Xr6JNrLC_g,643
|
2
2
|
job_shop_lib/_base_solver.py,sha256=p17XmtufNc9Y481cqZUT45pEkUmmW1HWG53dfhIBJH8,1363
|
3
3
|
job_shop_lib/_job_shop_instance.py,sha256=hNQGSJj0rEQpS-YhzwWmM6QzCWp6r--89jkghSgLvUs,18380
|
4
4
|
job_shop_lib/_operation.py,sha256=hx2atpP8LPj9fvxpZIfhBFr9Uq6JP-MKAX5JzTvFXso,3847
|
@@ -9,11 +9,12 @@ job_shop_lib/benchmarking/_load_benchmark.py,sha256=Jb6HYGKkub-3uU3l3NreRPE0PU6f
|
|
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=vz_Kg_CmvZ13yGgqi-hZuFkosJR1v449xNaAZV3PhsE,10501
|
12
|
-
job_shop_lib/dispatching/__init__.py,sha256=
|
12
|
+
job_shop_lib/dispatching/__init__.py,sha256=SXVd0Zh6xTp-lNT7c463pii3l168NCZYf-5uOwBI1Fc,1770
|
13
13
|
job_shop_lib/dispatching/_dispatcher.py,sha256=HW333xJoupufSUCg-pfaR_4KoQHjQMd4SBXJj-vgE7Y,22349
|
14
14
|
job_shop_lib/dispatching/_dispatcher_observer_config.py,sha256=RaUkLxYCHG8Tx2tPgFyOBa8FAcbREZdKuTyLsyaYvhA,2473
|
15
15
|
job_shop_lib/dispatching/_factories.py,sha256=1McCm3iJGdGDZerAe6MTWsthpbomuYb3crTKg_5lfyM,4678
|
16
16
|
job_shop_lib/dispatching/_history_observer.py,sha256=dixJe83quzGNwG0u0k2uES7GsLw0zWCjX0MOUD4VTRU,634
|
17
|
+
job_shop_lib/dispatching/_optimal_operations_observer.py,sha256=HTbmc9EaagM3UA6IIUaj7O0Fq3hCrjONhfonHIZnCE0,4376
|
17
18
|
job_shop_lib/dispatching/_ready_operation_filters.py,sha256=H2-CPL0BKDvpLM2zvDGr9eC849qLgbxsVDHgPAHtNgc,5754
|
18
19
|
job_shop_lib/dispatching/_unscheduled_operations_observer.py,sha256=3E0ePesDdWdNs6520znnOBW3eiegJj5bZg9Tmb0xoSA,2705
|
19
20
|
job_shop_lib/dispatching/feature_observers/__init__.py,sha256=EuJLvSpJpoXUK8A4UuC2k6Mpa293ZR3oCnnvYivIBtU,2240
|
@@ -27,9 +28,9 @@ job_shop_lib/dispatching/feature_observers/_is_ready_observer.py,sha256=aP5CpwmC
|
|
27
28
|
job_shop_lib/dispatching/feature_observers/_is_scheduled_observer.py,sha256=OcuMUB9_By6ZMtX-1_3z-xaxGbP85a5Zv0ywAv7XxWQ,1491
|
28
29
|
job_shop_lib/dispatching/feature_observers/_position_in_job_observer.py,sha256=WRknpQBKXs6h6cXLFJW7ZCvjtU8CPL-iXXNPw3g-mLE,1303
|
29
30
|
job_shop_lib/dispatching/feature_observers/_remaining_operations_observer.py,sha256=5V87lCrJUabEe8AkTGXPu5yS8OGxeN8L3-xNyHmdmLs,1441
|
30
|
-
job_shop_lib/dispatching/rules/__init__.py,sha256=
|
31
|
+
job_shop_lib/dispatching/rules/__init__.py,sha256=g3PGvMLMa3WMgNhGSW3S_xkHqoHpW8hr_9JqOfR7Xrk,2140
|
31
32
|
job_shop_lib/dispatching/rules/_dispatching_rule_factory.py,sha256=0Hht2i_aGS5hgwPxh_59-ZtNQxgSOwEFclukXH6Ib9U,2942
|
32
|
-
job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=
|
33
|
+
job_shop_lib/dispatching/rules/_dispatching_rule_solver.py,sha256=9-UE0HiHCeFXFGqB85cSfduLCEm5k5bJkmIujP-_irg,7321
|
33
34
|
job_shop_lib/dispatching/rules/_dispatching_rules_functions.py,sha256=wfBdiKqEQQ8C5Gg_mrWWSuWncPwUkFacjeAQ8D4n9Wc,7648
|
34
35
|
job_shop_lib/dispatching/rules/_machine_chooser_factory.py,sha256=QqYXQr7Cp6WsqhLa1oHvR1vnbG8IFmYvxM44dQeLeSE,2362
|
35
36
|
job_shop_lib/dispatching/rules/_utils.py,sha256=DFDpRoHb56Rtn01vfN69Bq0X3F8P1EtM6trHx9aXg3U,4643
|
@@ -39,7 +40,7 @@ job_shop_lib/generation/_general_instance_generator.py,sha256=e-NDkH-NoCwa14oADj
|
|
39
40
|
job_shop_lib/generation/_instance_generator.py,sha256=VV0OKX4JgFq3I1EY6s3LrOdPjM3v4lH6S1hkUebTkFQ,4615
|
40
41
|
job_shop_lib/generation/_transformations.py,sha256=X-hTAJVIHZ3bmF1rqS0zCit8r5SGpHpV8Fcl92fejow,5336
|
41
42
|
job_shop_lib/generation/_utils.py,sha256=cBhGILE0FE3TqvWoHqpaFEffO8D2fb869pF-BdMlYsg,3617
|
42
|
-
job_shop_lib/graphs/__init__.py,sha256=
|
43
|
+
job_shop_lib/graphs/__init__.py,sha256=RI9vGUR_89X34UoHpl1HYZpxT8JOWg8dwZTe5ImDCVg,1849
|
43
44
|
job_shop_lib/graphs/_build_disjunctive_graph.py,sha256=UbUYdeQaaeEqLchcKJGHEFGl4wElfGLb1o_R-u8wqnA,5120
|
44
45
|
job_shop_lib/graphs/_build_resource_task_graphs.py,sha256=GHUHkUNPxVf1miScgPPMe2YqlXFEMxIy5cDhNw7OZ1E,6954
|
45
46
|
job_shop_lib/graphs/_constants.py,sha256=K-GeVvh_DTWpo1KOX1clmxWS_pkUJbq19yOBmrCVIxI,1086
|
@@ -49,21 +50,21 @@ job_shop_lib/graphs/graph_updaters/__init__.py,sha256=UhnZL55e3cAv7hVetB6bRmIOn8
|
|
49
50
|
job_shop_lib/graphs/graph_updaters/_graph_updater.py,sha256=j1f7iWsa62GVszK2BPaMxnKBCEGWa9owm8g4VWUje8w,1967
|
50
51
|
job_shop_lib/graphs/graph_updaters/_residual_graph_updater.py,sha256=SfgmDyMwfW56OBjJPaU76c42IsX5qx9j-eMtrv0DjKk,6047
|
51
52
|
job_shop_lib/graphs/graph_updaters/_utils.py,sha256=X5YfwJA1CCgpm1r9C036Gal2CkDh2SSak7wl7TbdjHw,704
|
52
|
-
job_shop_lib/reinforcement_learning/__init__.py,sha256=
|
53
|
+
job_shop_lib/reinforcement_learning/__init__.py,sha256=IohAO2-eAdgeAsNG2czRhI5Eu9jKPnDnB8Z-ne_L1as,1124
|
53
54
|
job_shop_lib/reinforcement_learning/_multi_job_shop_graph_env.py,sha256=ib1Y6cItVvId4PfesiQ0XKbh9y6h8LVhD0gYDO4wSlk,15732
|
54
55
|
job_shop_lib/reinforcement_learning/_reward_observers.py,sha256=iWHccnujeAKyTQn2ilQ4BhcEccoSTyJqQ5yOiP5GG_Y,2984
|
55
56
|
job_shop_lib/reinforcement_learning/_single_job_shop_graph_env.py,sha256=DZnXeXmzMGKq-vwFhxukmSDN1UyrkUfbnjpjFtC9_Bs,15845
|
56
57
|
job_shop_lib/reinforcement_learning/_types_and_constants.py,sha256=xozdM_Wabdbe9e1a769p5980OSNBwQqc9yyaSGW2ODQ,1743
|
57
|
-
job_shop_lib/reinforcement_learning/_utils.py,sha256=
|
58
|
+
job_shop_lib/reinforcement_learning/_utils.py,sha256=PZWUZVc_Du90PYvKeTxe0dLkCuK3KwQ3D5I54kk5x0U,3808
|
58
59
|
job_shop_lib/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
60
|
job_shop_lib/visualization/gantt/__init__.py,sha256=HGXwRgDuMAldqU0JBdiZCd5e79XBz1r96qHeDVlzE54,1145
|
60
61
|
job_shop_lib/visualization/gantt/_gantt_chart_creator.py,sha256=LTsVhpB1Fb_2o08HRZPPXSekwzR7fyTSC6h549XMqhU,8638
|
61
62
|
job_shop_lib/visualization/gantt/_gantt_chart_video_and_gif_creation.py,sha256=CcHcvafYrTy7UaScM_wp9QlLOgKiTIKV7tFkttMgoLU,14474
|
62
63
|
job_shop_lib/visualization/gantt/_plot_gantt_chart.py,sha256=9-NSSNsVcW8gYLZtAuFeYURqi8cHNkVYufosKtbKFOI,6881
|
63
|
-
job_shop_lib/visualization/graphs/__init__.py,sha256=
|
64
|
+
job_shop_lib/visualization/graphs/__init__.py,sha256=282hZFg07EyQu4HVt4GzFfYnY6ZF376IMjnWZ5eg0ZQ,611
|
64
65
|
job_shop_lib/visualization/graphs/_plot_disjunctive_graph.py,sha256=4VBMYiFXXkCGSnGYN9iqNtWrbLJQxAMHojPHhAbdA0s,14387
|
65
66
|
job_shop_lib/visualization/graphs/_plot_resource_task_graph.py,sha256=RgJqHS5hJh3KkyaLbtpG_bER981BFRwGpflz7I7gS64,13271
|
66
|
-
job_shop_lib-1.0.
|
67
|
-
job_shop_lib-1.0.
|
68
|
-
job_shop_lib-1.0.
|
69
|
-
job_shop_lib-1.0.
|
67
|
+
job_shop_lib-1.0.0b3.dist-info/LICENSE,sha256=9mggivMGd5taAu3xbmBway-VQZMBzurBGHofFopvUsQ,1069
|
68
|
+
job_shop_lib-1.0.0b3.dist-info/METADATA,sha256=m-NzkaDXbblEXE7O-iQEYOdQQCPDvj6LiRcJKqenpHg,16424
|
69
|
+
job_shop_lib-1.0.0b3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
70
|
+
job_shop_lib-1.0.0b3.dist-info/RECORD,,
|
File without changes
|
File without changes
|