nextroute 1.8.1__cp38-cp38-macosx_14_0_arm64.whl → 1.12.3__cp38-cp38-macosx_14_0_arm64.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.
- nextroute/__about__.py +1 -1
- nextroute/bin/nextroute.exe +0 -0
- nextroute/options.py +49 -1
- nextroute/schema/input.py +35 -4
- {nextroute-1.8.1.dist-info → nextroute-1.12.3.dist-info}/METADATA +3 -2
- {nextroute-1.8.1.dist-info → nextroute-1.12.3.dist-info}/RECORD +10 -10
- {nextroute-1.8.1.dist-info → nextroute-1.12.3.dist-info}/WHEEL +1 -1
- tests/solve_golden/main.py +15 -11
- {nextroute-1.8.1.dist-info → nextroute-1.12.3.dist-info}/LICENSE +0 -0
- {nextroute-1.8.1.dist-info → nextroute-1.12.3.dist-info}/top_level.txt +0 -0
nextroute/__about__.py
CHANGED
nextroute/bin/nextroute.exe
CHANGED
|
Binary file
|
nextroute/options.py
CHANGED
|
@@ -16,6 +16,8 @@ from nextroute.base_model import BaseModel
|
|
|
16
16
|
_DURATIONS_ARGS = [
|
|
17
17
|
"-check.duration",
|
|
18
18
|
"-solve.duration",
|
|
19
|
+
"-solve.plateau.duration",
|
|
20
|
+
"-solve.plateau.delay",
|
|
19
21
|
]
|
|
20
22
|
|
|
21
23
|
# Arguments that require a string enum.
|
|
@@ -79,16 +81,20 @@ class Options(BaseModel):
|
|
|
79
81
|
MODEL_OBJECTIVES_CAPACITIES: str = ""
|
|
80
82
|
"""
|
|
81
83
|
Capacity objective, provide triple for each resource
|
|
82
|
-
`name
|
|
84
|
+
`name=default;factor=1.0;offset=0.0`.
|
|
83
85
|
"""
|
|
84
86
|
MODEL_OBJECTIVES_CLUSTER: float = 0.0
|
|
85
87
|
"""Factor to weigh the cluster objective."""
|
|
88
|
+
MODEL_OBJECTIVES_DISTANCE: float = 0.0
|
|
89
|
+
"""Factor to weigh the distance objective."""
|
|
86
90
|
MODEL_OBJECTIVES_EARLYARRIVALPENALTY: float = 1.0
|
|
87
91
|
"""Factor to weigh the early arrival objective."""
|
|
88
92
|
MODEL_OBJECTIVES_LATEARRIVALPENALTY: float = 1.0
|
|
89
93
|
"""Factor to weigh the late arrival objective."""
|
|
90
94
|
MODEL_OBJECTIVES_MINSTOPS: float = 1.0
|
|
91
95
|
"""Factor to weigh the min stops objective."""
|
|
96
|
+
MODEL_OBJECTIVES_STOPBALANCE: float = 0.0
|
|
97
|
+
"""Factor to weigh the stop balance objective."""
|
|
92
98
|
MODEL_OBJECTIVES_TRAVELDURATION: float = 0.0
|
|
93
99
|
"""Factor to weigh the travel duration objective."""
|
|
94
100
|
MODEL_OBJECTIVES_UNPLANNEDPENALTY: float = 1.0
|
|
@@ -105,6 +111,8 @@ class Options(BaseModel):
|
|
|
105
111
|
"""Ignore the initial solution."""
|
|
106
112
|
MODEL_PROPERTIES_DISABLE_STOPDURATIONMULTIPLIERS: bool = False
|
|
107
113
|
"""Ignore the stop duration multipliers defined on vehicles."""
|
|
114
|
+
MODEL_PROPERTIES_MAXIMUMTIMEHORIZON: int = 15552000
|
|
115
|
+
"""Maximum time horizon for the model in seconds."""
|
|
108
116
|
MODEL_VALIDATE_DISABLE_RESOURCES: bool = False
|
|
109
117
|
"""Disable the resources validation."""
|
|
110
118
|
MODEL_VALIDATE_DISABLE_STARTTIME: bool = False
|
|
@@ -125,8 +133,48 @@ class Options(BaseModel):
|
|
|
125
133
|
Maximum number of parallel runs, -1 results in using all available
|
|
126
134
|
resources.
|
|
127
135
|
"""
|
|
136
|
+
SOLVE_PLATEAU_DELAY: float = 0.0
|
|
137
|
+
"""Delay before starting to monitor for a plateau."""
|
|
138
|
+
SOLVE_PLATEAU_ABSOLUTETHRESHOLD: float = -1
|
|
139
|
+
"""Absolute threshold for significant improvement."""
|
|
140
|
+
SOLVE_PLATEAU_DURATION: float = 0.0
|
|
141
|
+
"""Maximum duration, in seconds, without (significant) improvement."""
|
|
142
|
+
SOLVE_PLATEAU_ITERATIONS: int = 0
|
|
143
|
+
"""Maximum number of iterations without (significant) improvement."""
|
|
144
|
+
SOLVE_PLATEAU_RELATIVETHRESHOLD: float = 0.0
|
|
145
|
+
"""Relative threshold for significant improvement."""
|
|
128
146
|
SOLVE_RUNDETERMINISTICALLY: bool = False
|
|
129
147
|
"""Run the parallel solver deterministically."""
|
|
148
|
+
SOLVE_SOLVER_PLANGROUPSIZE_DELTA: int = 0
|
|
149
|
+
"""Delta for the plan group size parameter."""
|
|
150
|
+
SOLVE_SOLVER_PLANGROUPSIZE_DELTAAFTERITERATIONS: int = 1000000000
|
|
151
|
+
"""Delta after each iteration for the plan group size parameter."""
|
|
152
|
+
SOLVE_SOLVER_PLANGROUPSIZE_MAXVALUE: int = 2
|
|
153
|
+
"""Maximum value for the plan group size parameter."""
|
|
154
|
+
SOLVE_SOLVER_PLANGROUPSIZE_MINVALUE: int = 2
|
|
155
|
+
"""Minimum value for the plan group size parameter."""
|
|
156
|
+
SOLVE_SOLVER_PLANGROUPSIZE_SNAPBACKAFTERIMPROVEMENT: bool = True
|
|
157
|
+
"""Snap back to start value after improvement of best solution for the plan group size parameter."""
|
|
158
|
+
SOLVE_SOLVER_PLANGROUPSIZE_STARTVALUE: int = 2
|
|
159
|
+
"""Start value for the plan group size parameter."""
|
|
160
|
+
SOLVE_SOLVER_PLANGROUPSIZE_ZIGZAG: bool = True
|
|
161
|
+
"""Zigzag between min and max value like a jig saw for the plan group size parameter."""
|
|
162
|
+
SOLVE_SOLVER_UNPLANUNITS_DELTA: int = 2
|
|
163
|
+
"""Delta for the unplan units parameter."""
|
|
164
|
+
SOLVE_SOLVER_UNPLANUNITS_DELTAAFTERITERATIONS: int = 125
|
|
165
|
+
"""Delta after each iteration for the unplan units parameter."""
|
|
166
|
+
SOLVE_SOLVER_UNPLANUNITS_MAXVALUE: int = -1
|
|
167
|
+
"""Maximum value for the unplan units parameter."""
|
|
168
|
+
SOLVE_SOLVER_UNPLANUNITS_MINVALUE: int = 2
|
|
169
|
+
"""Minimum value for the unplan units parameter."""
|
|
170
|
+
SOLVE_SOLVER_UNPLANUNITS_SNAPBACKAFTERIMPROVEMENT: bool = True
|
|
171
|
+
"""Snap back to start value after improvement of best solution for the unplan units parameter."""
|
|
172
|
+
SOLVE_SOLVER_UNPLANUNITS_STARTVALUE: int = 2
|
|
173
|
+
"""Start value for the unplan units parameter."""
|
|
174
|
+
SOLVE_SOLVER_UNPLANUNITS_ZIGZAG: bool = True
|
|
175
|
+
"""Zigzag between min and max value like a jig saw for the unplan units parameter."""
|
|
176
|
+
SOLVE_SOLVER_UNPLANWEIGHTS: str = "Vehicle:3,Island:1,Location:293"
|
|
177
|
+
"""Unplan heuristic weights parameter."""
|
|
130
178
|
SOLVE_STARTSOLUTIONS: int = -1
|
|
131
179
|
"""
|
|
132
180
|
Number of solutions to generate on top of those passed in; one solution
|
nextroute/schema/input.py
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
Defines the input class.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any, List, Optional, Union
|
|
8
9
|
|
|
9
10
|
from nextroute.base_model import BaseModel
|
|
10
11
|
from nextroute.schema.stop import AlternateStop, Stop, StopDefaults
|
|
@@ -30,6 +31,30 @@ class DurationGroup(BaseModel):
|
|
|
30
31
|
"""Stop IDs contained in the group."""
|
|
31
32
|
|
|
32
33
|
|
|
34
|
+
class MatrixTimeFrame(BaseModel):
|
|
35
|
+
"""Represents a time-dependent duration matrix or scaling factor."""
|
|
36
|
+
|
|
37
|
+
start_time: datetime
|
|
38
|
+
"""Start time of the time frame."""
|
|
39
|
+
end_time: datetime
|
|
40
|
+
"""End time of the time frame."""
|
|
41
|
+
matrix: Optional[List[List[float]]] = None
|
|
42
|
+
"""Duration matrix for the time frame."""
|
|
43
|
+
scaling_factor: Optional[float] = None
|
|
44
|
+
"""Scaling factor for the time frame."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class TimeDependentMatrix(BaseModel):
|
|
48
|
+
"""Represents time-dependent duration matrices."""
|
|
49
|
+
|
|
50
|
+
vehicle_ids: Optional[List[str]] = None
|
|
51
|
+
"""Vehicle IDs for which the duration matrix is defined."""
|
|
52
|
+
default_matrix: List[List[float]]
|
|
53
|
+
"""Default duration matrix."""
|
|
54
|
+
matrix_time_frames: Optional[List[MatrixTimeFrame]] = None
|
|
55
|
+
"""Time-dependent duration matrices."""
|
|
56
|
+
|
|
57
|
+
|
|
33
58
|
class Input(BaseModel):
|
|
34
59
|
"""Input schema for Nextroute."""
|
|
35
60
|
|
|
@@ -46,10 +71,16 @@ class Input(BaseModel):
|
|
|
46
71
|
"""Default values for vehicles and stops."""
|
|
47
72
|
distance_matrix: Optional[List[List[float]]] = None
|
|
48
73
|
"""Matrix of travel distances in meters between stops."""
|
|
49
|
-
|
|
74
|
+
duration_groups: Optional[List[DurationGroup]] = None
|
|
50
75
|
"""Duration in seconds added when approaching the group."""
|
|
51
|
-
duration_matrix: Optional[
|
|
52
|
-
|
|
76
|
+
duration_matrix: Optional[
|
|
77
|
+
Union[
|
|
78
|
+
List[List[float]],
|
|
79
|
+
TimeDependentMatrix,
|
|
80
|
+
List[TimeDependentMatrix],
|
|
81
|
+
]
|
|
82
|
+
] = None
|
|
83
|
+
"""Matrix of travel durations in seconds between stops as a single matrix or duration matrices."""
|
|
53
84
|
options: Optional[Any] = None
|
|
54
85
|
"""Arbitrary options."""
|
|
55
86
|
stop_groups: Optional[List[List[str]]] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nextroute
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.3
|
|
4
4
|
Summary: Nextroute is an engine for solving Vehicle Routing Problems (VRPs).
|
|
5
5
|
Author-email: Nextmv <tech@nextmv.io>
|
|
6
6
|
Maintainer-email: Nextmv <tech@nextmv.io>
|
|
@@ -104,6 +104,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
104
104
|
Classifier: Programming Language :: Python :: 3.10
|
|
105
105
|
Classifier: Programming Language :: Python :: 3.11
|
|
106
106
|
Classifier: Programming Language :: Python :: 3.12
|
|
107
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
107
108
|
Requires-Python: >=3.8
|
|
108
109
|
Description-Content-Type: text/markdown
|
|
109
110
|
License-File: LICENSE
|
|
@@ -197,7 +198,7 @@ file.
|
|
|
197
198
|
|
|
198
199
|
For further information on how to get started, features, deployment, etc.,
|
|
199
200
|
please refer to the [official
|
|
200
|
-
documentation](https://www.nextmv.io/docs/vehicle-routing).
|
|
201
|
+
documentation](https://www.nextmv.io/docs/vehicle-routing/get-started).
|
|
201
202
|
|
|
202
203
|
### Go
|
|
203
204
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
nextroute/__about__.py,sha256=
|
|
1
|
+
nextroute/__about__.py,sha256=H71OIfyHAXJOiG4wuGcoP506V3in6aScHaOMWCJknuM,57
|
|
2
2
|
nextroute/__init__.py,sha256=wBHS73T_Mm2MfcEx4chZCI1QMbV-a1D7bw7megFLgb4,529
|
|
3
3
|
nextroute/base_model.py,sha256=Jl205oJZvndkY8rIomZD2k5YhlGgRBn_2I1BKwQ8Vkk,541
|
|
4
|
-
nextroute/options.py,sha256=
|
|
4
|
+
nextroute/options.py,sha256=tZcTLIjsx-6fq9Q9Y-Z8syKbPqGyR3GV6vfpWvVmzLQ,10280
|
|
5
5
|
nextroute/solve.py,sha256=It1kDEdFk_AXX-gEUjvQbc7C-0ma9bEPRbnC_bHMsUU,4192
|
|
6
6
|
nextroute/version.py,sha256=aA_wmIifNRCzxBigX4cSz1Y2CdXvuBNIiY7Nem5UqRA,325
|
|
7
|
-
nextroute/bin/nextroute.exe,sha256=
|
|
7
|
+
nextroute/bin/nextroute.exe,sha256=UrjmdA8fjj-s06wT5a6eI85RORVDbtEzB8JdK527r7c,14994304
|
|
8
8
|
nextroute/check/__init__.py,sha256=Hrw5LUqdMeaBEsoIrJmWDhmAKAzGuzDnoBExwNWJvlU,1303
|
|
9
9
|
nextroute/check/schema.py,sha256=hBC0Usw4_rEJHsWDxDtIi0-d6byXt8f9eYqBE9hqiCc,5853
|
|
10
10
|
nextroute/schema/__init__.py,sha256=KSlnpJQMnCDq5IXyiltt9CiafcxUH40B3FdE1fc5wdI,1167
|
|
11
|
-
nextroute/schema/input.py,sha256=
|
|
11
|
+
nextroute/schema/input.py,sha256=uidXX_hpv1KpiIUCc_XhiiQf69vxiav9DsXfiLtpD2s,2856
|
|
12
12
|
nextroute/schema/location.py,sha256=hihllMU3IXxQHugGC4Wn_TzDPr5zm4xqVqRsKanwrmA,301
|
|
13
13
|
nextroute/schema/output.py,sha256=rJv_PpP0X0MdLTRa2tbDsLLbGhTRi43hGmMNmzvNZEw,4810
|
|
14
14
|
nextroute/schema/statistics.py,sha256=lNlb1mcpR6xWQclG-fkDMnFoy-sEKpXKk80zU1TKrpQ,3600
|
|
@@ -18,9 +18,9 @@ tests/schema/__init__.py,sha256=MRZbyX5fYnxsXV0YP6lf32c5YYMo3NsEFqPwdwf5W18,32
|
|
|
18
18
|
tests/schema/test_input.py,sha256=kNIlUFqCkvvQieuJIo7-6C_NB9PZqZ72NpGwUWtDZcA,1851
|
|
19
19
|
tests/schema/test_output.py,sha256=i0VreVBXamC-Pk-z7X3W9APjmjfG8iOPAt2jxP4hDQA,11579
|
|
20
20
|
tests/solve_golden/__init__.py,sha256=MRZbyX5fYnxsXV0YP6lf32c5YYMo3NsEFqPwdwf5W18,32
|
|
21
|
-
tests/solve_golden/main.py,sha256=
|
|
22
|
-
nextroute-1.
|
|
23
|
-
nextroute-1.
|
|
24
|
-
nextroute-1.
|
|
25
|
-
nextroute-1.
|
|
26
|
-
nextroute-1.
|
|
21
|
+
tests/solve_golden/main.py,sha256=VScx0kPD8ihGR5bSIpLrPTIxRh7mkk9YQ9g0eg8XZMc,1738
|
|
22
|
+
nextroute-1.12.3.dist-info/LICENSE,sha256=ElKAl6B15yj4LTFL_Dh1hje431kMHut2urxo5nheRWs,4107
|
|
23
|
+
nextroute-1.12.3.dist-info/METADATA,sha256=tB7ipov9kgEDYAuBkcA9595NCSBnlR37Kmfj6simJeo,15590
|
|
24
|
+
nextroute-1.12.3.dist-info/WHEEL,sha256=7oHrrmTB-AnaDl8j1Eeuo7QImBG4q2CMfROfSJb1CuE,107
|
|
25
|
+
nextroute-1.12.3.dist-info/top_level.txt,sha256=KNsuo1j7tr-QvBFS_ELmo68OmJ-orEZiOXqstGLJDXA,16
|
|
26
|
+
nextroute-1.12.3.dist-info/RECORD,,
|
tests/solve_golden/main.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# This script is copied to the `src` root so that the `nextroute` import is
|
|
2
2
|
# resolved. It is fed an input via stdin and is meant to write the output to
|
|
3
3
|
# stdout.
|
|
4
|
-
from typing import Any, Dict
|
|
5
|
-
|
|
6
4
|
import nextmv
|
|
7
5
|
|
|
8
6
|
import nextroute
|
|
@@ -16,8 +14,8 @@ def main() -> None:
|
|
|
16
14
|
nextmv.Parameter("output", str, "", "Path to output file. Default is stdout.", False),
|
|
17
15
|
]
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
for name, default_value in
|
|
17
|
+
default_options = nextroute.Options()
|
|
18
|
+
for name, default_value in default_options.to_dict().items():
|
|
21
19
|
parameters.append(nextmv.Parameter(name.lower(), type(default_value), default_value, name, False))
|
|
22
20
|
|
|
23
21
|
options = nextmv.Options(*parameters)
|
|
@@ -28,18 +26,24 @@ def main() -> None:
|
|
|
28
26
|
nextmv.log(f" - stops: {len(input.data.get('stops', []))}")
|
|
29
27
|
nextmv.log(f" - vehicles: {len(input.data.get('vehicles', []))}")
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
model = DecisionModel()
|
|
30
|
+
output = model.solve(input)
|
|
32
31
|
nextmv.write_local(output, path=options.output)
|
|
33
32
|
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
class DecisionModel(nextmv.Model):
|
|
35
|
+
def solve(self, input: nextmv.Input) -> nextmv.Output:
|
|
36
|
+
"""Solves the given problem and returns the solution."""
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
nextroute_input = nextroute.schema.Input.from_dict(input.data)
|
|
39
|
+
nextroute_options = nextroute.Options.extract_from_dict(input.options.to_dict())
|
|
40
|
+
nextroute_output = nextroute.solve(nextroute_input, nextroute_options)
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
return nextmv.Output(
|
|
43
|
+
options=input.options,
|
|
44
|
+
solution=nextroute_output.solutions[0].to_dict(),
|
|
45
|
+
statistics=nextroute_output.statistics.to_dict(),
|
|
46
|
+
)
|
|
43
47
|
|
|
44
48
|
|
|
45
49
|
if __name__ == "__main__":
|
|
File without changes
|
|
File without changes
|