multimodalrouter 0.1.0__tar.gz → 0.1.2__tar.gz
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.
Potentially problematic release.
This version of multimodalrouter might be problematic. Click here for more details.
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/MANIFEST.in +1 -0
- {multimodalrouter-0.1.0/src/multiModalRouter.egg-info → multimodalrouter-0.1.2}/PKG-INFO +4 -1
- multimodalrouter-0.1.2/docs/cli.md +78 -0
- multimodalrouter-0.1.2/docs/examples/demoData.csv +1 -0
- multimodalrouter-0.1.2/docs/examples/flightRouter/data/fullDataset.csv +101 -0
- multimodalrouter-0.1.2/docs/examples/flightRouter/main.py +37 -0
- multimodalrouter-0.1.2/docs/examples/mazePathfinder/data/createMaze.py +64 -0
- multimodalrouter-0.1.2/docs/examples/mazePathfinder/data/maze.csv +198 -0
- multimodalrouter-0.1.2/docs/examples/mazePathfinder/main.py +59 -0
- multimodalrouter-0.1.2/docs/graph.md +514 -0
- multimodalrouter-0.1.2/docs/installation.md +44 -0
- multimodalrouter-0.1.2/docs/solvedMaze1.png +0 -0
- multimodalrouter-0.1.2/docs/utils.md +1 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/pyproject.toml +7 -1
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2/src/multiModalRouter.egg-info}/PKG-INFO +4 -1
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/SOURCES.txt +11 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/requires.txt +3 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/LICENSE.md +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/README.md +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/setup.cfg +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/dependency_links.txt +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/entry_points.txt +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/top_level.txt +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/__init__.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/graph/__init__.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/graph/dataclasses.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/graph/graph.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/router/__init__.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/router/build.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/router/route.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/utils/__init__.py +0 -0
- {multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/utils/preprocessor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multimodalrouter
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: A graph-based routing library for dynamic routing.
|
|
5
5
|
Author-email: Tobias Karusseit <karusseittobi@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -14,6 +14,7 @@ License: MIT License
|
|
|
14
14
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
Project-URL: Repository, https://github.com/K-T0BIAS/MultiModalRouter
|
|
17
18
|
Requires-Python: >=3.11
|
|
18
19
|
Description-Content-Type: text/markdown
|
|
19
20
|
License-File: LICENSE.md
|
|
@@ -41,6 +42,8 @@ Requires-Dist: typing_extensions>=4.15.0
|
|
|
41
42
|
Requires-Dist: tzdata>=2025.2
|
|
42
43
|
Provides-Extra: torch
|
|
43
44
|
Requires-Dist: torch>=2.8.0; extra == "torch"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
44
47
|
Dynamic: license-file
|
|
45
48
|
|
|
46
49
|
# Multi Modal Router
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
[HOME](../README.md)
|
|
2
|
+
|
|
3
|
+
# command line interface
|
|
4
|
+
|
|
5
|
+
If you don't want to always write new scripts to build the graph or to find routes, you can simply use the command line interface.
|
|
6
|
+
|
|
7
|
+
## building a graph from the terminal
|
|
8
|
+
|
|
9
|
+
**this assumes that your data has been preprocessed into the correct format**
|
|
10
|
+
|
|
11
|
+
> from your terminal run:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
multimodalrouter-build hubType1 transportMode1 pathToDataset1 --maxDist 123 --extraMetrics metric1 metric2 --drivingEnabled --Dir pathToSomeDir
|
|
15
|
+
```
|
|
16
|
+
### args
|
|
17
|
+
|
|
18
|
+
- `hub type`,`transport mode`,`dataset path` = the first arguments in your cli should be these three. They must follow this order to be parsed correctly
|
|
19
|
+
- `hub type` = the name the hubs from this dataset will get
|
|
20
|
+
- `transport mode` = the mode of transport unique to this hub
|
|
21
|
+
- `dataset path` = ideally the absolute path to the dataset that contains this `hub type`
|
|
22
|
+
- NOTE: you can add as many hub types and datasets at once as you want just make sure the order is always; type1 mode1 path1 type2 ...
|
|
23
|
+
- `--maxDist` = the float value that limits the maximum length a driving edge can have (this is irrelevant id `--enableDriving` isn't set)
|
|
24
|
+
- `extraMetrics` = a list of keys that the graph will scan your data for and add the values to any edge where the key exists in the data (NOTE: each key should be present in at least one dataset, the number of extra metrics is not limited)
|
|
25
|
+
- `--drivingEnabled` = if this flag is added the graph will try to build connections between hubs for any hub that is closer than the `--maxDist` to anoter hub (check [here](../README.md#important-considerations-for-your-usecase) to see if your data allows this)
|
|
26
|
+
- `--Dir` = put the target directory of the save file here. (if this is not set the graph will be saved to a default dir)
|
|
27
|
+
|
|
28
|
+
### example
|
|
29
|
+
|
|
30
|
+
> create a new dir for the garph and edit the `--Dir` if you want the graph in a easy to access directory otherwise keep as is
|
|
31
|
+
|
|
32
|
+
> NOTE: this example assumes you are still in the project dir. If not please adapt the dataset path accordingly
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
multimodalrouter-build airport plane ./docs/examples/flightRouter/data/fullDataset.csv --maxDist 100 --drivingEnabled
|
|
36
|
+
--extraMetrics source_name destination_name
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**output:**
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Building graph...
|
|
43
|
+
Generating airport Hubs: 100hub [00:00, 186995.27hub/s]
|
|
44
|
+
Graph built and saved.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## finding a route
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
multimodalrouter-route --start lat1 lng1 --end lat2 lng2 --allowedModes car plane --maxSegments 123 --verbose
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> NOTE: if you have higher dimensional coordinates you can simply add them here aswell
|
|
54
|
+
|
|
55
|
+
### agrs
|
|
56
|
+
|
|
57
|
+
- `--start` = the start coordinates for the route (doesn't have to be exact to the `Hub` it will find the closest hub to the point. Also the coordinates do not have to be in dgrees, but rather fit with the coordinate system of your data. Read more [here](./graph.md#advanced-options))
|
|
58
|
+
- `--end` = the end coordinates of the route: (same features as for `--start` apply)
|
|
59
|
+
- `--allowedModes` = a filter that discards edges that use a transport mode that is not in this list. (default= ['car'])
|
|
60
|
+
- `--maxSegments` = an interger value of the maximum number of hubs a route can have. (e.g.: to avoid very deep searches when long routes are not logically feasable) (default = 10)
|
|
61
|
+
- `--verbose` = if this flag is set the output route will contain the [edgeMetadata](./graph.md#edgemetadata) for every leg of the route (default=false when flag not set)
|
|
62
|
+
|
|
63
|
+
### example
|
|
64
|
+
|
|
65
|
+
> NOTE: this example assumes you build the graph from the [previous example](#example).
|
|
66
|
+
> if you changed the save path this script wont find it (**this will hopefully be fixed in the future**).
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
multimodalrouter-route --start 60.866699 -162.272996 --end 60.872747 -162.5247 --allowedModes plane car --maxSegments 10 --verbose
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**output:**
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
Start: ATT
|
|
76
|
+
Edge: (transportMode=plane, metrics={'distance': 13.641155702721523, 'source_name': 'Atmautluak Airport', 'destination_name': 'Kasigluk Airport'})
|
|
77
|
+
-> KUK
|
|
78
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
source,destination,distance,source_lat,source_lng,destination_lat,destination_lng
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
type_x,source_name,source_lat,source_lng,source,type_y,destination_name,destination_lat,destination_lng,destination,distance
|
|
2
|
+
small_airport,Nunapitchuk Airport,60.905591,-162.440454,NUP,medium_airport,Bethel Airport,60.77980042,-161.8379974,BET,35.50891861257026
|
|
3
|
+
small_airport,Nunapitchuk Airport,60.905591,-162.440454,NUP,small_airport,Atmautluak Airport,60.866699,-162.272996,ATT,10.038962939026435
|
|
4
|
+
seaplane_base,Port Protection Seaplane Base,56.328800201416,-133.61000061035,PPV,medium_airport,Ketchikan International Airport,55.35559845,-131.7140045,KTN,160.3721674641772
|
|
5
|
+
small_airport,Atmautluak Airport,60.866699,-162.272996,ATT,small_airport,Kasigluk Airport,60.872747,-162.5247,KUK,13.641155702721525
|
|
6
|
+
small_airport,Atmautluak Airport,60.866699,-162.272996,ATT,medium_airport,Bethel Airport,60.77980042,-161.8379974,BET,25.48337320882719
|
|
7
|
+
small_airport,Ouzinkie Airport,57.942094,-152.464314,KOZ,small_airport,Port Lions Airport,57.884905,-152.847719,ORI,23.522288770693002
|
|
8
|
+
small_airport,Ouzinkie Airport,57.942094,-152.464314,KOZ,medium_airport,Kodiak Airport,57.75,-152.4940033,ADQ,21.432013590596263
|
|
9
|
+
small_airport,Tununak Airport,60.569638,-165.246649,TNK,small_airport,Mertarvik Airport,60.81037,-164.499511,WWT,48.68780922120069
|
|
10
|
+
small_airport,Tununak Airport,60.569638,-165.246649,TNK,small_airport,Mertarvik Airport,60.81037,-164.499511,WWT,48.68780922120069
|
|
11
|
+
small_airport,Minto Al Wright Airport,65.147991,-149.368658,MNT,medium_airport,Fairbanks International Airport,64.815102,-147.856003,FAI,80.18507978147673
|
|
12
|
+
seaplane_base,Whale Pass Seaplane Float Harbor Facility,56.116299,-133.121994,WWP,seaplane_base,Naukati Bay Seaplane Base,55.849602,-133.227994,NKI,30.379585733808945
|
|
13
|
+
small_airport,Chuathbaluk Airport,61.579102,-159.216003,CHU,small_airport,Crooked Creek Airport,61.870315,-158.137636,CKD,65.38238505420615
|
|
14
|
+
small_airport,Levelock Airport,59.12606,-156.860906,KLL,small_airport,Igiugig Airport,59.324001,-155.901993,IGG,58.828992456169594
|
|
15
|
+
small_airport,Tuntutuliak Airport,60.351243,-162.654476,WTL,small_airport,Kongiganak Airport,59.9608,-162.880997,KKH,45.188440482713354
|
|
16
|
+
small_airport,Tuntutuliak Airport,60.351243,-162.654476,WTL,medium_airport,Bethel Airport,60.77980042,-161.8379974,BET,65.2786595888185
|
|
17
|
+
small_airport,Chignik Lake Airport,56.2550010681,-158.774993896,KCQ,small_airport,Perryville Airport,55.9065,-159.16091,KPV,45.55296472659558
|
|
18
|
+
small_airport,Ulawa Airport,-9.86054358262,161.979546547,RNA,large_airport,Honiara International Airport,-9.428,160.054993,HIR,216.38820067708903
|
|
19
|
+
small_airport,Ulawa Airport,-9.86054358262,161.979546547,RNA,small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,66.11653988838862
|
|
20
|
+
small_airport,Uru Harbour Airport,-8.87333,161.011002,ATD,large_airport,Honiara International Airport,-9.428,160.054993,HIR,121.73124157936162
|
|
21
|
+
small_airport,Bellona/Anua Airport,-11.3022222222,159.798333333,BNY,large_airport,Honiara International Airport,-9.428,160.054993,HIR,210.28617119708878
|
|
22
|
+
small_airport,Bellona/Anua Airport,-11.3022222222,159.798333333,BNY,small_airport,Rennell/Tingoa Airport,-11.55,160.062778,RNL,39.87237198952627
|
|
23
|
+
small_airport,Choiseul Bay Airport,-6.711944,156.396111,CHY,small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,162.5049617838888
|
|
24
|
+
small_airport,Fera/Maringe Airport,-8.1075,159.576996,FRE,large_airport,Honiara International Airport,-9.428,160.054993,HIR,155.94596147929755
|
|
25
|
+
small_airport,Fera/Maringe Airport,-8.1075,159.576996,FRE,small_airport,Suavanao Airport,-7.58556,158.731003,VAO,109.78386316421907
|
|
26
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Bauerfield International Airport,-17.699301,168.320007,VLI,1281.5410455884694
|
|
27
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Uru Harbour Airport,-8.87333,161.011002,ATD,121.73124157936162
|
|
28
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Brisbane International Airport,-27.38419914245605,153.11700439453125,BNE,2125.197199470748
|
|
29
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Bellona/Anua Airport,-11.3022222222,159.798333333,BNY,210.28617119708878
|
|
30
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Choiseul Bay Airport,-6.711944,156.396111,CHY,503.4301040975509
|
|
31
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Sege Airport,-8.57889,157.876007,EGM,257.25669923971793
|
|
32
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Fera/Maringe Airport,-8.1075,159.576996,FRE,155.94596147929755
|
|
33
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,380.58997472323
|
|
34
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,231.62836439151877
|
|
35
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Kaghau Airport,-7.3305,157.585,KGE,358.07676558742975
|
|
36
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,medium_airport,Munda Airport,-8.32797,157.263,MUA,330.2196835379018
|
|
37
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,medium_airport,Nadi International Airport,-17.755399703979492,177.4429931640625,NAN,2092.93698138901
|
|
38
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Santa Ana Airport,-10.847994,162.454108,NNB,306.4114913331019
|
|
39
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Ramata Airport,-8.168060302734375,157.64300537109375,RBV,299.78875699036024
|
|
40
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Ulawa Airport,-9.86054358262,161.979546547,RNA,216.38820067708903
|
|
41
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Rennell/Tingoa Airport,-11.55,160.062778,RNL,235.95716942961073
|
|
42
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Marau Airport,-9.86166954041,160.824996948,RUS,97.21320359785862
|
|
43
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Santa Cruz/Graciosa Bay/Luova Airport,-10.7203,165.794998,SCZ,644.616728255269
|
|
44
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,small_airport,Suavanao Airport,-7.58556,158.731003,VAO,251.33538811065654
|
|
45
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Bauerfield International Airport,-17.699301,168.320007,VLI,1281.5410455884694
|
|
46
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Bauerfield International Airport,-17.699301,168.320007,VLI,1281.5410455884694
|
|
47
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,medium_airport,Nadi International Airport,-17.755399703979492,177.4429931640625,NAN,2092.93698138901
|
|
48
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,1407.7980052392509
|
|
49
|
+
large_airport,Honiara International Airport,-9.428,160.054993,HIR,large_airport,Brisbane International Airport,-27.38419914245605,153.11700439453125,BNE,2125.197199470748
|
|
50
|
+
small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,large_airport,Honiara International Airport,-9.428,160.054993,HIR,231.62836439151877
|
|
51
|
+
small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,small_airport,Santa Ana Airport,-10.847994,162.454108,NNB,75.19751316811372
|
|
52
|
+
small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,small_airport,Ulawa Airport,-9.86054358262,161.979546547,RNA,66.11653988838862
|
|
53
|
+
small_airport,Santa Cruz/Graciosa Bay/Luova Airport,-10.7203,165.794998,SCZ,large_airport,Honiara International Airport,-9.428,160.054993,HIR,644.616728255269
|
|
54
|
+
medium_airport,Munda Airport,-8.32797,157.263,MUA,small_airport,Sege Airport,-8.57889,157.876007,EGM,72.96767843412853
|
|
55
|
+
medium_airport,Munda Airport,-8.32797,157.263,MUA,small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,50.82722405648163
|
|
56
|
+
medium_airport,Munda Airport,-8.32797,157.263,MUA,large_airport,Honiara International Airport,-9.428,160.054993,HIR,330.2196835379018
|
|
57
|
+
medium_airport,Munda Airport,-8.32797,157.263,MUA,small_airport,Kaghau Airport,-7.3305,157.585,KGE,116.44735467761112
|
|
58
|
+
small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,small_airport,Choiseul Bay Airport,-6.711944,156.396111,CHY,162.5049617838888
|
|
59
|
+
small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,small_airport,Sege Airport,-8.57889,157.876007,EGM,123.52564099929795
|
|
60
|
+
small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,large_airport,Honiara International Airport,-9.428,160.054993,HIR,380.58997472323
|
|
61
|
+
small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,medium_airport,Munda Airport,-8.32797,157.263,MUA,50.82722405648163
|
|
62
|
+
small_airport,Rennell/Tingoa Airport,-11.55,160.062778,RNL,small_airport,Bellona/Anua Airport,-11.3022222222,159.798333333,BNY,39.87237198952627
|
|
63
|
+
small_airport,Rennell/Tingoa Airport,-11.55,160.062778,RNL,large_airport,Honiara International Airport,-9.428,160.054993,HIR,235.95716942961073
|
|
64
|
+
small_airport,Sege Airport,-8.57889,157.876007,EGM,small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,123.52564099929795
|
|
65
|
+
small_airport,Sege Airport,-8.57889,157.876007,EGM,large_airport,Honiara International Airport,-9.428,160.054993,HIR,257.25669923971793
|
|
66
|
+
small_airport,Sege Airport,-8.57889,157.876007,EGM,small_airport,Ramata Airport,-8.168060302734375,157.64300537109375,RBV,52.38204651861383
|
|
67
|
+
small_airport,Sege Airport,-8.57889,157.876007,EGM,small_airport,Suavanao Airport,-7.58556,158.731003,VAO,145.1191154079397
|
|
68
|
+
small_airport,Santa Ana Airport,-10.847994,162.454108,NNB,large_airport,Honiara International Airport,-9.428,160.054993,HIR,306.4114913331019
|
|
69
|
+
small_airport,Santa Ana Airport,-10.847994,162.454108,NNB,small_airport,Ngorangora Airport,-10.4497003555,161.897994995,IRA,75.19751316811372
|
|
70
|
+
small_airport,Marau Airport,-9.86166954041,160.824996948,RUS,large_airport,Honiara International Airport,-9.428,160.054993,HIR,97.21320359785862
|
|
71
|
+
small_airport,Suavanao Airport,-7.58556,158.731003,VAO,large_airport,Honiara International Airport,-9.428,160.054993,HIR,251.33538811065654
|
|
72
|
+
small_airport,Kaghau Airport,-7.3305,157.585,KGE,small_airport,Nusatupe Airport,-8.09778022766,156.863998413,GZO,116.57914877867566
|
|
73
|
+
small_airport,Kaghau Airport,-7.3305,157.585,KGE,medium_airport,Munda Airport,-8.32797,157.263,MUA,116.44735467761112
|
|
74
|
+
small_airport,Ramata Airport,-8.168060302734375,157.64300537109375,RBV,large_airport,Honiara International Airport,-9.428,160.054993,HIR,299.78875699036024
|
|
75
|
+
small_airport,Ramata Airport,-8.168060302734375,157.64300537109375,RBV,medium_airport,Munda Airport,-8.32797,157.263,MUA,45.44094741444411
|
|
76
|
+
seaplane_base,Naukati Bay Seaplane Base,55.849602,-133.227994,NKI,seaplane_base,Edna Bay Seaplane Base,55.949653,-133.661012,EDA,29.19724206748465
|
|
77
|
+
seaplane_base,Amook Bay Seaplane Base,57.4715003967,-153.815002441,AOS,seaplane_base,Zachar Bay Seaplane Base,57.553001,-153.746052,KZB,9.954218423033408
|
|
78
|
+
medium_airport,Nauru International Airport,-0.547458,166.919006,INU,large_airport,Brisbane International Airport,-27.38419914245605,153.11700439453125,BNE,3327.7632640151937
|
|
79
|
+
medium_airport,Nauru International Airport,-0.547458,166.919006,INU,medium_airport,Marshall Islands International Airport,7.06476,171.272003,MAJ,974.4960347944631
|
|
80
|
+
medium_airport,Nauru International Airport,-0.547458,166.919006,INU,medium_airport,Bonriki International Airport,1.38164,173.147003,TRW,724.9332999884076
|
|
81
|
+
medium_airport,Buka Airport,-5.422319889068604,154.67300415039062,BUA,medium_airport,Tokua Airport,-4.34046,152.380005,RAB,281.08421413197493
|
|
82
|
+
medium_airport,Buka Airport,-5.422319889068604,154.67300415039062,BUA,small_airport,Londolovit Airport,-3.04361009598,152.628997803,LNV,348.3233345946322
|
|
83
|
+
medium_airport,Buka Airport,-5.422319889068604,154.67300415039062,BUA,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,935.3716267807029
|
|
84
|
+
medium_airport,Buka Airport,-5.422319889068604,154.67300415039062,BUA,medium_airport,Tokua Airport,-4.34046,152.380005,RAB,281.08421413197493
|
|
85
|
+
small_airport,Bulolo Airport,-7.216286671410001,146.649541855,BUL,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,255.4701324460494
|
|
86
|
+
medium_airport,Chimbu Airport,-6.024290084838867,144.9709930419922,CMU,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,453.79316712547796
|
|
87
|
+
medium_airport,Daru Airport,-9.08676,143.207993,DAU,medium_airport,Nadzab Airport,-6.569803,146.725977,LAE,478.00303964492326
|
|
88
|
+
medium_airport,Daru Airport,-9.08676,143.207993,DAU,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,442.0739733579925
|
|
89
|
+
medium_airport,Daru Airport,-9.08676,143.207993,DAU,small_airport,Kiunga Airport,-6.1257100105285645,141.28199768066406,UNG,391.7380630804866
|
|
90
|
+
medium_airport,Daru Airport,-9.08676,143.207993,DAU,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,442.0739733579925
|
|
91
|
+
medium_airport,Goroka Airport,-6.081689834590001,145.391998291,GKA,medium_airport,Mount Hagen Kagamuga Airport,-5.828212,144.299412,HGU,124.07803210978558
|
|
92
|
+
medium_airport,Goroka Airport,-6.081689834590001,145.391998291,GKA,medium_airport,Nadzab Airport,-6.569803,146.725977,LAE,157.10150462058704
|
|
93
|
+
medium_airport,Goroka Airport,-6.081689834590001,145.391998291,GKA,medium_airport,Madang Airport,-5.20707988739,145.789001465,MAG,106.7138992902682
|
|
94
|
+
medium_airport,Goroka Airport,-6.081689834590001,145.391998291,GKA,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,424.5928070950016
|
|
95
|
+
medium_airport,Goroka Airport,-6.081689834590001,145.391998291,GKA,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,424.5928070950016
|
|
96
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,small_airport,Losuia Airport,-8.505820274353027,151.08099365234375,LSA,216.85910026596767
|
|
97
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,small_airport,Misima Island Airport,-10.6892004013,152.837997437,MIS,276.9706342250573
|
|
98
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,medium_airport,Girua Airport,-8.80453968048,148.309005737,PNP,278.16980437426656
|
|
99
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,354.5183966398174
|
|
100
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,small_airport,Misima Island Airport,-10.6892004013,152.837997437,MIS,276.9706342250573
|
|
101
|
+
medium_airport,Gurney Airport,-10.3114995956,150.333999634,GUR,large_airport,Port Moresby Jacksons International Airport,-9.44338035583496,147.22000122070312,POM,354.5183966398174
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# demo.py
|
|
2
|
+
# Copyright (c) 2025 Tobias Karusseit
|
|
3
|
+
# Licensed under the MIT License. See LICENSE file in the project root for full license information
|
|
4
|
+
|
|
5
|
+
from multimodalrouter import RouteGraph
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
path = os.path.dirname(os.path.abspath(__file__))
|
|
10
|
+
# initialize the graph
|
|
11
|
+
graph = RouteGraph(
|
|
12
|
+
maxDistance=50,
|
|
13
|
+
transportModes={"airport": "plane", },
|
|
14
|
+
dataPaths={"airport": os.path.join(path, "data", "fullDataset.csv")},
|
|
15
|
+
compressed=False,
|
|
16
|
+
)
|
|
17
|
+
# build the graph
|
|
18
|
+
graph.build()
|
|
19
|
+
# set start and end points
|
|
20
|
+
start = [60.866699,-162.272996] # Atmautluak Airport
|
|
21
|
+
end = [60.872747,-162.5247] #Kasigluk Airport
|
|
22
|
+
|
|
23
|
+
start_hub = graph.findClosestHub(["airport"], start) # find the hubs
|
|
24
|
+
end_hub = graph.findClosestHub(["airport"], end)
|
|
25
|
+
# find the route
|
|
26
|
+
route = graph.find_shortest_path(
|
|
27
|
+
start_hub.id,
|
|
28
|
+
end_hub.id,
|
|
29
|
+
allowed_modes=["plane","car"],
|
|
30
|
+
verbose=True
|
|
31
|
+
)
|
|
32
|
+
# print the route
|
|
33
|
+
print(route.flatPath if route else "No route found")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == "__main__":
|
|
37
|
+
main()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# demo.py
|
|
2
|
+
# Copyright (c) 2025 Tobias Karusseit
|
|
3
|
+
# Licensed under the MIT License. See LICENSE file in the project root for full license information
|
|
4
|
+
|
|
5
|
+
import random
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
# simple cell class for the maze
|
|
9
|
+
class Cell:
|
|
10
|
+
def __init__(self, x, y):
|
|
11
|
+
self.id = f"cell-{x,y}"
|
|
12
|
+
self.x = x
|
|
13
|
+
self.y = y
|
|
14
|
+
self.visited = False
|
|
15
|
+
self.connected = []
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
# init a 10x10 maze
|
|
19
|
+
mazeHeight = 10
|
|
20
|
+
mazeWidth = 10
|
|
21
|
+
# init the cells
|
|
22
|
+
cells = [Cell(x, y) for x, y in [(x, y) for x in range(mazeWidth) for y in range(mazeHeight)]]
|
|
23
|
+
cellStack = []
|
|
24
|
+
# random choose one cell and init the stack
|
|
25
|
+
random.shuffle(cells)
|
|
26
|
+
cellStack.append(cells.pop())
|
|
27
|
+
# build the maze
|
|
28
|
+
while cellStack:
|
|
29
|
+
currentCell = cellStack[-1] # peek at the current cell
|
|
30
|
+
# get all not et visited neighbors
|
|
31
|
+
neighbors = [
|
|
32
|
+
c for c in cells if not c.visited and (
|
|
33
|
+
(c.x == currentCell.x + 1 and c.y == currentCell.y) or
|
|
34
|
+
(c.x == currentCell.x - 1 and c.y == currentCell.y) or
|
|
35
|
+
(c.y == currentCell.y + 1 and c.x == currentCell.x) or
|
|
36
|
+
(c.y == currentCell.y - 1 and c.x == currentCell.x)
|
|
37
|
+
)
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
if neighbors:
|
|
41
|
+
# select a random neighbor
|
|
42
|
+
random.shuffle(neighbors)
|
|
43
|
+
neighbor = neighbors.pop()
|
|
44
|
+
# connect the cells (remove walls)
|
|
45
|
+
currentCell.connected.append(neighbor)
|
|
46
|
+
neighbor.connected.append(currentCell)
|
|
47
|
+
# mark the neighbor as visited
|
|
48
|
+
neighbor.visited = True
|
|
49
|
+
# add the neighbor to the stack
|
|
50
|
+
cellStack.append(neighbor)
|
|
51
|
+
else:
|
|
52
|
+
# remove the current cell from the stack since no paths exist for it
|
|
53
|
+
cellStack.pop()
|
|
54
|
+
|
|
55
|
+
# init the dataframe
|
|
56
|
+
data = pd.DataFrame(columns=["source", "destination", "distance", "source_lat", "source_lng", "destination_lat", "destination_lng"])
|
|
57
|
+
# add the edges to the dataframe
|
|
58
|
+
for cell in cells:
|
|
59
|
+
for neighbor in cell.connected:
|
|
60
|
+
data.loc[len(data)] = [cell.id, neighbor.id, 1, cell.x, cell.y, neighbor.x, neighbor.y]
|
|
61
|
+
# save the dataframe
|
|
62
|
+
data.to_csv("docs/examples/mazePathfinder/data/maze.csv", index=False)
|
|
63
|
+
|
|
64
|
+
if __name__ == "__main__": main()
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
source,destination,distance,source_lat,source_lng,destination_lat,destination_lng
|
|
2
|
+
"cell-(6, 9)","cell-(5, 9)",1,6,9,5,9
|
|
3
|
+
"cell-(6, 9)","cell-(7, 9)",1,6,9,7,9
|
|
4
|
+
"cell-(6, 6)","cell-(5, 6)",1,6,6,5,6
|
|
5
|
+
"cell-(6, 6)","cell-(7, 6)",1,6,6,7,6
|
|
6
|
+
"cell-(7, 5)","cell-(8, 5)",1,7,5,8,5
|
|
7
|
+
"cell-(7, 5)","cell-(6, 5)",1,7,5,6,5
|
|
8
|
+
"cell-(1, 5)","cell-(2, 5)",1,1,5,2,5
|
|
9
|
+
"cell-(1, 5)","cell-(0, 5)",1,1,5,0,5
|
|
10
|
+
"cell-(8, 5)","cell-(9, 5)",1,8,5,9,5
|
|
11
|
+
"cell-(8, 5)","cell-(7, 5)",1,8,5,7,5
|
|
12
|
+
"cell-(6, 3)","cell-(6, 4)",1,6,3,6,4
|
|
13
|
+
"cell-(6, 3)","cell-(5, 3)",1,6,3,5,3
|
|
14
|
+
"cell-(3, 3)","cell-(2, 3)",1,3,3,2,3
|
|
15
|
+
"cell-(3, 3)","cell-(3, 4)",1,3,3,3,4
|
|
16
|
+
"cell-(9, 6)","cell-(8, 6)",1,9,6,8,6
|
|
17
|
+
"cell-(9, 6)","cell-(9, 5)",1,9,6,9,5
|
|
18
|
+
"cell-(9, 6)","cell-(9, 7)",1,9,6,9,7
|
|
19
|
+
"cell-(6, 5)","cell-(7, 5)",1,6,5,7,5
|
|
20
|
+
"cell-(6, 2)","cell-(7, 2)",1,6,2,7,2
|
|
21
|
+
"cell-(6, 2)","cell-(5, 2)",1,6,2,5,2
|
|
22
|
+
"cell-(8, 3)","cell-(7, 3)",1,8,3,7,3
|
|
23
|
+
"cell-(8, 3)","cell-(8, 2)",1,8,3,8,2
|
|
24
|
+
"cell-(6, 7)","cell-(7, 7)",1,6,7,7,7
|
|
25
|
+
"cell-(6, 7)","cell-(6, 8)",1,6,7,6,8
|
|
26
|
+
"cell-(9, 7)","cell-(9, 6)",1,9,7,9,6
|
|
27
|
+
"cell-(9, 7)","cell-(8, 7)",1,9,7,8,7
|
|
28
|
+
"cell-(2, 9)","cell-(3, 9)",1,2,9,3,9
|
|
29
|
+
"cell-(2, 9)","cell-(2, 8)",1,2,9,2,8
|
|
30
|
+
"cell-(4, 4)","cell-(3, 4)",1,4,4,3,4
|
|
31
|
+
"cell-(4, 4)","cell-(4, 3)",1,4,4,4,3
|
|
32
|
+
"cell-(9, 8)","cell-(9, 9)",1,9,8,9,9
|
|
33
|
+
"cell-(9, 8)","cell-(8, 8)",1,9,8,8,8
|
|
34
|
+
"cell-(2, 7)","cell-(2, 8)",1,2,7,2,8
|
|
35
|
+
"cell-(2, 7)","cell-(1, 7)",1,2,7,1,7
|
|
36
|
+
"cell-(7, 4)","cell-(8, 4)",1,7,4,8,4
|
|
37
|
+
"cell-(7, 4)","cell-(6, 4)",1,7,4,6,4
|
|
38
|
+
"cell-(3, 0)","cell-(2, 0)",1,3,0,2,0
|
|
39
|
+
"cell-(3, 0)","cell-(4, 0)",1,3,0,4,0
|
|
40
|
+
"cell-(8, 0)","cell-(7, 0)",1,8,0,7,0
|
|
41
|
+
"cell-(8, 0)","cell-(9, 0)",1,8,0,9,0
|
|
42
|
+
"cell-(2, 3)","cell-(2, 4)",1,2,3,2,4
|
|
43
|
+
"cell-(2, 3)","cell-(3, 3)",1,2,3,3,3
|
|
44
|
+
"cell-(5, 7)","cell-(5, 8)",1,5,7,5,8
|
|
45
|
+
"cell-(5, 7)","cell-(4, 7)",1,5,7,4,7
|
|
46
|
+
"cell-(1, 3)","cell-(1, 2)",1,1,3,1,2
|
|
47
|
+
"cell-(1, 3)","cell-(0, 3)",1,1,3,0,3
|
|
48
|
+
"cell-(4, 7)","cell-(5, 7)",1,4,7,5,7
|
|
49
|
+
"cell-(4, 7)","cell-(4, 6)",1,4,7,4,6
|
|
50
|
+
"cell-(3, 1)","cell-(4, 1)",1,3,1,4,1
|
|
51
|
+
"cell-(3, 1)","cell-(3, 2)",1,3,1,3,2
|
|
52
|
+
"cell-(2, 2)","cell-(3, 2)",1,2,2,3,2
|
|
53
|
+
"cell-(2, 2)","cell-(1, 2)",1,2,2,1,2
|
|
54
|
+
"cell-(5, 3)","cell-(6, 3)",1,5,3,6,3
|
|
55
|
+
"cell-(5, 3)","cell-(5, 4)",1,5,3,5,4
|
|
56
|
+
"cell-(5, 0)","cell-(4, 0)",1,5,0,4,0
|
|
57
|
+
"cell-(0, 4)","cell-(0, 5)",1,0,4,0,5
|
|
58
|
+
"cell-(0, 4)","cell-(1, 4)",1,0,4,1,4
|
|
59
|
+
"cell-(8, 7)","cell-(9, 7)",1,8,7,9,7
|
|
60
|
+
"cell-(7, 8)","cell-(8, 8)",1,7,8,8,8
|
|
61
|
+
"cell-(7, 8)","cell-(7, 7)",1,7,8,7,7
|
|
62
|
+
"cell-(9, 1)","cell-(9, 0)",1,9,1,9,0
|
|
63
|
+
"cell-(9, 1)","cell-(9, 2)",1,9,1,9,2
|
|
64
|
+
"cell-(4, 9)","cell-(4, 8)",1,4,9,4,8
|
|
65
|
+
"cell-(4, 9)","cell-(3, 9)",1,4,9,3,9
|
|
66
|
+
"cell-(4, 9)","cell-(5, 9)",1,4,9,5,9
|
|
67
|
+
"cell-(0, 2)","cell-(0, 3)",1,0,2,0,3
|
|
68
|
+
"cell-(0, 2)","cell-(0, 1)",1,0,2,0,1
|
|
69
|
+
"cell-(5, 1)","cell-(5, 2)",1,5,1,5,2
|
|
70
|
+
"cell-(5, 1)","cell-(6, 1)",1,5,1,6,1
|
|
71
|
+
"cell-(4, 2)","cell-(4, 3)",1,4,2,4,3
|
|
72
|
+
"cell-(4, 2)","cell-(4, 1)",1,4,2,4,1
|
|
73
|
+
"cell-(2, 0)","cell-(2, 1)",1,2,0,2,1
|
|
74
|
+
"cell-(2, 0)","cell-(3, 0)",1,2,0,3,0
|
|
75
|
+
"cell-(2, 0)","cell-(1, 0)",1,2,0,1,0
|
|
76
|
+
"cell-(2, 8)","cell-(2, 9)",1,2,8,2,9
|
|
77
|
+
"cell-(2, 8)","cell-(2, 7)",1,2,8,2,7
|
|
78
|
+
"cell-(1, 8)","cell-(0, 8)",1,1,8,0,8
|
|
79
|
+
"cell-(1, 8)","cell-(1, 9)",1,1,8,1,9
|
|
80
|
+
"cell-(7, 7)","cell-(7, 8)",1,7,7,7,8
|
|
81
|
+
"cell-(7, 7)","cell-(6, 7)",1,7,7,6,7
|
|
82
|
+
"cell-(8, 9)","cell-(7, 9)",1,8,9,7,9
|
|
83
|
+
"cell-(8, 9)","cell-(9, 9)",1,8,9,9,9
|
|
84
|
+
"cell-(4, 3)","cell-(4, 4)",1,4,3,4,4
|
|
85
|
+
"cell-(4, 3)","cell-(4, 2)",1,4,3,4,2
|
|
86
|
+
"cell-(8, 2)","cell-(8, 3)",1,8,2,8,3
|
|
87
|
+
"cell-(8, 2)","cell-(8, 1)",1,8,2,8,1
|
|
88
|
+
"cell-(6, 0)","cell-(6, 1)",1,6,0,6,1
|
|
89
|
+
"cell-(6, 0)","cell-(7, 0)",1,6,0,7,0
|
|
90
|
+
"cell-(0, 7)","cell-(1, 7)",1,0,7,1,7
|
|
91
|
+
"cell-(0, 7)","cell-(0, 8)",1,0,7,0,8
|
|
92
|
+
"cell-(0, 7)","cell-(0, 6)",1,0,7,0,6
|
|
93
|
+
"cell-(1, 1)","cell-(0, 1)",1,1,1,0,1
|
|
94
|
+
"cell-(1, 1)","cell-(2, 1)",1,1,1,2,1
|
|
95
|
+
"cell-(6, 8)","cell-(6, 7)",1,6,8,6,7
|
|
96
|
+
"cell-(6, 8)","cell-(5, 8)",1,6,8,5,8
|
|
97
|
+
"cell-(0, 6)","cell-(0, 7)",1,0,6,0,7
|
|
98
|
+
"cell-(0, 6)","cell-(1, 6)",1,0,6,1,6
|
|
99
|
+
"cell-(4, 0)","cell-(3, 0)",1,4,0,3,0
|
|
100
|
+
"cell-(4, 0)","cell-(5, 0)",1,4,0,5,0
|
|
101
|
+
"cell-(6, 4)","cell-(7, 4)",1,6,4,7,4
|
|
102
|
+
"cell-(6, 4)","cell-(6, 3)",1,6,4,6,3
|
|
103
|
+
"cell-(4, 8)","cell-(3, 8)",1,4,8,3,8
|
|
104
|
+
"cell-(4, 8)","cell-(4, 9)",1,4,8,4,9
|
|
105
|
+
"cell-(5, 8)","cell-(6, 8)",1,5,8,6,8
|
|
106
|
+
"cell-(5, 8)","cell-(5, 7)",1,5,8,5,7
|
|
107
|
+
"cell-(9, 3)","cell-(9, 2)",1,9,3,9,2
|
|
108
|
+
"cell-(9, 3)","cell-(9, 4)",1,9,3,9,4
|
|
109
|
+
"cell-(0, 3)","cell-(1, 3)",1,0,3,1,3
|
|
110
|
+
"cell-(0, 3)","cell-(0, 2)",1,0,3,0,2
|
|
111
|
+
"cell-(9, 4)","cell-(9, 3)",1,9,4,9,3
|
|
112
|
+
"cell-(9, 4)","cell-(8, 4)",1,9,4,8,4
|
|
113
|
+
"cell-(9, 0)","cell-(8, 0)",1,9,0,8,0
|
|
114
|
+
"cell-(9, 0)","cell-(9, 1)",1,9,0,9,1
|
|
115
|
+
"cell-(1, 6)","cell-(0, 6)",1,1,6,0,6
|
|
116
|
+
"cell-(1, 6)","cell-(2, 6)",1,1,6,2,6
|
|
117
|
+
"cell-(7, 9)","cell-(6, 9)",1,7,9,6,9
|
|
118
|
+
"cell-(7, 9)","cell-(8, 9)",1,7,9,8,9
|
|
119
|
+
"cell-(3, 7)","cell-(3, 6)",1,3,7,3,6
|
|
120
|
+
"cell-(3, 7)","cell-(3, 8)",1,3,7,3,8
|
|
121
|
+
"cell-(7, 6)","cell-(6, 6)",1,7,6,6,6
|
|
122
|
+
"cell-(7, 6)","cell-(8, 6)",1,7,6,8,6
|
|
123
|
+
"cell-(1, 9)","cell-(1, 8)",1,1,9,1,8
|
|
124
|
+
"cell-(1, 9)","cell-(0, 9)",1,1,9,0,9
|
|
125
|
+
"cell-(9, 2)","cell-(9, 1)",1,9,2,9,1
|
|
126
|
+
"cell-(9, 2)","cell-(9, 3)",1,9,2,9,3
|
|
127
|
+
"cell-(8, 4)","cell-(9, 4)",1,8,4,9,4
|
|
128
|
+
"cell-(8, 4)","cell-(7, 4)",1,8,4,7,4
|
|
129
|
+
"cell-(7, 2)","cell-(7, 1)",1,7,2,7,1
|
|
130
|
+
"cell-(7, 2)","cell-(6, 2)",1,7,2,6,2
|
|
131
|
+
"cell-(5, 4)","cell-(5, 3)",1,5,4,5,3
|
|
132
|
+
"cell-(5, 4)","cell-(5, 5)",1,5,4,5,5
|
|
133
|
+
"cell-(4, 5)","cell-(5, 5)",1,4,5,5,5
|
|
134
|
+
"cell-(4, 5)","cell-(3, 5)",1,4,5,3,5
|
|
135
|
+
"cell-(4, 6)","cell-(4, 7)",1,4,6,4,7
|
|
136
|
+
"cell-(4, 6)","cell-(5, 6)",1,4,6,5,6
|
|
137
|
+
"cell-(3, 5)","cell-(4, 5)",1,3,5,4,5
|
|
138
|
+
"cell-(3, 5)","cell-(3, 6)",1,3,5,3,6
|
|
139
|
+
"cell-(1, 2)","cell-(2, 2)",1,1,2,2,2
|
|
140
|
+
"cell-(1, 2)","cell-(1, 3)",1,1,2,1,3
|
|
141
|
+
"cell-(2, 1)","cell-(1, 1)",1,2,1,1,1
|
|
142
|
+
"cell-(2, 1)","cell-(2, 0)",1,2,1,2,0
|
|
143
|
+
"cell-(3, 2)","cell-(3, 1)",1,3,2,3,1
|
|
144
|
+
"cell-(3, 2)","cell-(2, 2)",1,3,2,2,2
|
|
145
|
+
"cell-(7, 0)","cell-(6, 0)",1,7,0,6,0
|
|
146
|
+
"cell-(7, 0)","cell-(8, 0)",1,7,0,8,0
|
|
147
|
+
"cell-(2, 5)","cell-(2, 6)",1,2,5,2,6
|
|
148
|
+
"cell-(2, 5)","cell-(1, 5)",1,2,5,1,5
|
|
149
|
+
"cell-(7, 1)","cell-(8, 1)",1,7,1,8,1
|
|
150
|
+
"cell-(7, 1)","cell-(7, 2)",1,7,1,7,2
|
|
151
|
+
"cell-(5, 5)","cell-(5, 4)",1,5,5,5,4
|
|
152
|
+
"cell-(5, 5)","cell-(4, 5)",1,5,5,4,5
|
|
153
|
+
"cell-(4, 1)","cell-(4, 2)",1,4,1,4,2
|
|
154
|
+
"cell-(4, 1)","cell-(3, 1)",1,4,1,3,1
|
|
155
|
+
"cell-(2, 4)","cell-(1, 4)",1,2,4,1,4
|
|
156
|
+
"cell-(2, 4)","cell-(2, 3)",1,2,4,2,3
|
|
157
|
+
"cell-(8, 1)","cell-(8, 2)",1,8,1,8,2
|
|
158
|
+
"cell-(8, 1)","cell-(7, 1)",1,8,1,7,1
|
|
159
|
+
"cell-(1, 0)","cell-(2, 0)",1,1,0,2,0
|
|
160
|
+
"cell-(1, 0)","cell-(0, 0)",1,1,0,0,0
|
|
161
|
+
"cell-(5, 9)","cell-(4, 9)",1,5,9,4,9
|
|
162
|
+
"cell-(5, 9)","cell-(6, 9)",1,5,9,6,9
|
|
163
|
+
"cell-(8, 6)","cell-(7, 6)",1,8,6,7,6
|
|
164
|
+
"cell-(8, 6)","cell-(9, 6)",1,8,6,9,6
|
|
165
|
+
"cell-(8, 8)","cell-(9, 8)",1,8,8,9,8
|
|
166
|
+
"cell-(8, 8)","cell-(7, 8)",1,8,8,7,8
|
|
167
|
+
"cell-(6, 1)","cell-(5, 1)",1,6,1,5,1
|
|
168
|
+
"cell-(6, 1)","cell-(6, 0)",1,6,1,6,0
|
|
169
|
+
"cell-(9, 5)","cell-(9, 6)",1,9,5,9,6
|
|
170
|
+
"cell-(9, 5)","cell-(8, 5)",1,9,5,8,5
|
|
171
|
+
"cell-(3, 6)","cell-(3, 5)",1,3,6,3,5
|
|
172
|
+
"cell-(3, 6)","cell-(3, 7)",1,3,6,3,7
|
|
173
|
+
"cell-(5, 2)","cell-(6, 2)",1,5,2,6,2
|
|
174
|
+
"cell-(5, 2)","cell-(5, 1)",1,5,2,5,1
|
|
175
|
+
"cell-(5, 6)","cell-(4, 6)",1,5,6,4,6
|
|
176
|
+
"cell-(5, 6)","cell-(6, 6)",1,5,6,6,6
|
|
177
|
+
"cell-(3, 9)","cell-(4, 9)",1,3,9,4,9
|
|
178
|
+
"cell-(3, 9)","cell-(2, 9)",1,3,9,2,9
|
|
179
|
+
"cell-(3, 8)","cell-(3, 7)",1,3,8,3,7
|
|
180
|
+
"cell-(3, 8)","cell-(4, 8)",1,3,8,4,8
|
|
181
|
+
"cell-(9, 9)","cell-(8, 9)",1,9,9,8,9
|
|
182
|
+
"cell-(9, 9)","cell-(9, 8)",1,9,9,9,8
|
|
183
|
+
"cell-(2, 6)","cell-(1, 6)",1,2,6,1,6
|
|
184
|
+
"cell-(2, 6)","cell-(2, 5)",1,2,6,2,5
|
|
185
|
+
"cell-(0, 1)","cell-(0, 2)",1,0,1,0,2
|
|
186
|
+
"cell-(0, 1)","cell-(1, 1)",1,0,1,1,1
|
|
187
|
+
"cell-(0, 5)","cell-(1, 5)",1,0,5,1,5
|
|
188
|
+
"cell-(0, 5)","cell-(0, 4)",1,0,5,0,4
|
|
189
|
+
"cell-(1, 4)","cell-(0, 4)",1,1,4,0,4
|
|
190
|
+
"cell-(1, 4)","cell-(2, 4)",1,1,4,2,4
|
|
191
|
+
"cell-(1, 7)","cell-(2, 7)",1,1,7,2,7
|
|
192
|
+
"cell-(1, 7)","cell-(0, 7)",1,1,7,0,7
|
|
193
|
+
"cell-(0, 8)","cell-(0, 7)",1,0,8,0,7
|
|
194
|
+
"cell-(0, 8)","cell-(1, 8)",1,0,8,1,8
|
|
195
|
+
"cell-(0, 9)","cell-(1, 9)",1,0,9,1,9
|
|
196
|
+
"cell-(3, 4)","cell-(3, 3)",1,3,4,3,3
|
|
197
|
+
"cell-(3, 4)","cell-(4, 4)",1,3,4,4,4
|
|
198
|
+
"cell-(0, 0)","cell-(1, 0)",1,0,0,1,0
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# demo.py
|
|
2
|
+
# Copyright (c) 2025 Tobias Karusseit
|
|
3
|
+
# Licensed under the MIT License. See LICENSE file in the project root for full license information
|
|
4
|
+
|
|
5
|
+
from multimodalrouter import RouteGraph
|
|
6
|
+
import os
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
try:
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise ImportError("matplotlib is not installed. Please install matplotlib to use this example.")
|
|
14
|
+
|
|
15
|
+
path = os.path.dirname(os.path.abspath(__file__))
|
|
16
|
+
# init the maze df for the plot
|
|
17
|
+
mazeDf = pd.read_csv(os.path.join(path, "data", "maze.csv"))
|
|
18
|
+
# init the plot
|
|
19
|
+
plt.figure(figsize=(10,10))
|
|
20
|
+
# draw the maze
|
|
21
|
+
for _, row in mazeDf.iterrows():
|
|
22
|
+
plt.plot([row.source_lat, row.destination_lat],
|
|
23
|
+
[row.source_lng, row.destination_lng],
|
|
24
|
+
"k-") # black line for edge
|
|
25
|
+
|
|
26
|
+
# initialize the graph
|
|
27
|
+
graph = RouteGraph(
|
|
28
|
+
maxDistance=50,
|
|
29
|
+
transportModes={"cell": "walk", },
|
|
30
|
+
dataPaths={"cell": os.path.join(path, "data", "maze.csv")},
|
|
31
|
+
compressed=False,
|
|
32
|
+
drivingEnabled=False
|
|
33
|
+
)
|
|
34
|
+
# build the graph
|
|
35
|
+
graph.build()
|
|
36
|
+
# find the shortest route
|
|
37
|
+
route = graph.find_shortest_path(
|
|
38
|
+
start_id="cell-(0, 0)",
|
|
39
|
+
end_id="cell-(0, 9)",
|
|
40
|
+
allowed_modes=["walk"],
|
|
41
|
+
verbose=True,
|
|
42
|
+
max_segments=100
|
|
43
|
+
)
|
|
44
|
+
# print the route
|
|
45
|
+
print(route.flatPath if route else "No route found")
|
|
46
|
+
# make the route blue in the plot
|
|
47
|
+
s_prev = None
|
|
48
|
+
for s, _, _ in route.path:
|
|
49
|
+
if s_prev is not None:
|
|
50
|
+
h1 = graph.getHubById(s_prev)
|
|
51
|
+
h2 = graph.getHubById(s)
|
|
52
|
+
plt.plot([h1.coords[0], h2.coords[0]],
|
|
53
|
+
[h1.coords[1], h2.coords[1]],
|
|
54
|
+
"b-")
|
|
55
|
+
s_prev = s
|
|
56
|
+
# display the plot
|
|
57
|
+
plt.show()
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__": main()
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
[HOME](../README.md)
|
|
2
|
+
|
|
3
|
+
[graph](#routegraph)
|
|
4
|
+
|
|
5
|
+
- [advanced options](#advanced-options)
|
|
6
|
+
- [custom distance metrics](#swap-distance-method)
|
|
7
|
+
- [higher dimensional graphs](#higher-dimensional-graphs)
|
|
8
|
+
|
|
9
|
+
[dataclasses](#dataclasses)
|
|
10
|
+
|
|
11
|
+
[Hub](#Hub)
|
|
12
|
+
|
|
13
|
+
[EdgeMetadata](#edgemetadata)
|
|
14
|
+
|
|
15
|
+
[Route](#route)
|
|
16
|
+
|
|
17
|
+
# RouteGraph
|
|
18
|
+
|
|
19
|
+
The `RouteGraph` is the central class of the package implemented as a dynamic (cyclic) directed graph. It defines all graph building and routing related functions.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Functionality
|
|
23
|
+
|
|
24
|
+
### initialization
|
|
25
|
+
|
|
26
|
+
This creates a new graph with no `Hubs` or `Edges`.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
maxDistance: float,
|
|
32
|
+
transportModes: dict[str, str],
|
|
33
|
+
dataPaths: dict[str, str] = {},
|
|
34
|
+
compressed: bool = False,
|
|
35
|
+
extraMetricsKeys: list[str] = [],
|
|
36
|
+
drivingEnabled: bool = True,
|
|
37
|
+
sourceCoordKeys: list[str] = ["source_lat", "source_lng"],
|
|
38
|
+
destCoordKeys: list[str] = ["destination_lat", "destination_lng"],
|
|
39
|
+
):
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### args
|
|
43
|
+
|
|
44
|
+
Terminology:
|
|
45
|
+
|
|
46
|
+
> Hub Type: hub types are the user defined names for their hubs. e.g. when having data for flights you have `airports`, thus you may want to define the hubs for the airports as type `airport`. (Hub Types can be anything you want to name them)
|
|
47
|
+
|
|
48
|
+
- ``maxDistance``: float = The maximum distance a driving edge is allowed to span
|
|
49
|
+
- ``transportModes``: dict[str, str] = a dictionary that assigns Hub Types to their mode of travel. E.g.
|
|
50
|
+
```python
|
|
51
|
+
transportModes = {
|
|
52
|
+
'airport': 'fly',# here hub type airport is assigned its primary mode of travel as fly
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
- ``dataPaths``: dict[str, str] = a dictionary that stores the paths to datasets realtive to their Hub Types. E.g.:
|
|
56
|
+
```python
|
|
57
|
+
dataPaths = {
|
|
58
|
+
# hub type: path to dataset
|
|
59
|
+
'airport': '~/MUltiModalRouter/data/AirportDataset.parquet'
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
- ``compressed``: bool = wheter to save this graph in compressed files or not (NOTE: this is not used at the moment so just skip)
|
|
63
|
+
- ``extraMetricsKeys``: list[str] = a list of metrics the graph will search for in the datasets when building edges (NOTE: default metrics must still be present)
|
|
64
|
+
Example:
|
|
65
|
+
```python
|
|
66
|
+
# given at least one dataset with the col 'time'
|
|
67
|
+
|
|
68
|
+
extraMetricsKeys = ['time']
|
|
69
|
+
```
|
|
70
|
+
When the graph finds this key in a dataset it will then add this metric (here `time`) to all edges that come from hubs stored inside this dataset
|
|
71
|
+
|
|
72
|
+
- ``drivingEnabled``: bool = whether the graph should connect all possible hubs that have $distance(a,b) \leq maxDistance$ (default=True)
|
|
73
|
+
- `sourecCoordKeys`: list[str] = a list of keys from your data that contains the column names from your source coordinates. (NOTE: if you have more than one dataset you can just put all source keys into this list as long as the same keys arent for any other metric somewhere else)
|
|
74
|
+
- `destCoordKeys`: list[str] = a list of keys from your data that contains the column names of the destination coordinates. (same conditions as for source apply)
|
|
75
|
+
|
|
76
|
+
> NOTE: the source and dest coord keys are matched to the correct datasets automatically you can just bundle them all together in one list
|
|
77
|
+
|
|
78
|
+
#### example
|
|
79
|
+
|
|
80
|
+
Init a graph with Hubs: `airport`, `trainstation`
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from multimodalrouter import RouteGraph
|
|
84
|
+
|
|
85
|
+
graph = RouteGraph(
|
|
86
|
+
maxDistance = 50,
|
|
87
|
+
transportModes = {
|
|
88
|
+
'airport': 'plane',
|
|
89
|
+
'trainstation': 'train'
|
|
90
|
+
},
|
|
91
|
+
dataPaths = {
|
|
92
|
+
'airport': pathToAirportData,
|
|
93
|
+
'trainstation': pathToTrainData
|
|
94
|
+
}
|
|
95
|
+
# time and cost must each be present in at least one dataset
|
|
96
|
+
extraMetricsKeys = ['time', 'cost'],
|
|
97
|
+
# default is True so this is not necessary
|
|
98
|
+
drivingEnabled = True,
|
|
99
|
+
)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The resulting graph will be able to build `HUbs` for both `train stations` and `airports`. It will also use the extra metrics in all edges where the data is present
|
|
103
|
+
|
|
104
|
+
### build
|
|
105
|
+
|
|
106
|
+
After a graph is initialized it doesn't contain any actual nodes or edges yet. To create the nodes and edges the graph has to be build.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
def build(self):
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### example
|
|
113
|
+
|
|
114
|
+
click [here](#example) to see how to init the graph
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# with the graph from the previous example
|
|
118
|
+
|
|
119
|
+
graph.build()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
After this finishes the graph is build and ready for routing
|
|
123
|
+
|
|
124
|
+
### routing / finding the shortest Path form A to B
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
def find_shortest_path(
|
|
128
|
+
self,
|
|
129
|
+
start_id: str,
|
|
130
|
+
end_id: str,
|
|
131
|
+
allowed_modes: list[str],
|
|
132
|
+
optimization_metric: OptimizationMetric | str = OptimizationMetric.DISTANCE,
|
|
133
|
+
max_segments: int = 10,
|
|
134
|
+
verbose: bool = False
|
|
135
|
+
) -> Route | None:
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### args
|
|
139
|
+
|
|
140
|
+
- start_id: str = the Hub.id of the starting hub (e.g. the source field for this hub in your data -> for `airports` likely the iata code) (for coordinate searches see [here](#searching-with-coordinates))
|
|
141
|
+
- end_id: str = the Hub.id of the traget Hub
|
|
142
|
+
- allowed_modes: list[str] = a list of transport modes that are allowed in the path (all edges with different modes are excluded)(The modes are set during the graph [initailization](#args))
|
|
143
|
+
- optimization_metric: str = the metric by which the pathfinder will determine the length of the path (must be numeric and present in all searched edges) (default = `distance`) (metrics where also set during [initialization](#args))
|
|
144
|
+
- max_segments: int = the maximum number of hubs the route is allowed to include (default = 10 to avoid massive searches but should be setvrealtive to the graph size and density)
|
|
145
|
+
- verbose: bool = whether you want to store all edges and their data in the route or just the hub names (default=False)
|
|
146
|
+
|
|
147
|
+
**returns** : [Route](#route) or None if no route was found
|
|
148
|
+
|
|
149
|
+
### save
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
def save(
|
|
153
|
+
self,
|
|
154
|
+
filepath: str = os.path.join(os.getcwd(), "..", "..", "..", "data"),
|
|
155
|
+
compressed: bool = False):
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The `save` method will create a save file from the last garph state. Depending on the `arguments` the file will either be stored as `.dill` or `.zlib`.
|
|
159
|
+
A save file contains the complete statedict of the RouteGraph instance except attributes that could break the pickling process (e.g. ``threading.Lock``).
|
|
160
|
+
|
|
161
|
+
#### args
|
|
162
|
+
|
|
163
|
+
- filepath: str = the directory that the savefile will be stored in (defaults to `MultiModalRouter/data`)
|
|
164
|
+
- compressed: bool = whether to compress the output into `.zlib` or store as `.dill`
|
|
165
|
+
|
|
166
|
+
#### example
|
|
167
|
+
|
|
168
|
+
Saving a graph to a custom dir, in a `.dill` file
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
...
|
|
172
|
+
graph.save(filepath=customDir)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### load
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
@staticmethod
|
|
179
|
+
def load(
|
|
180
|
+
filepath: str,
|
|
181
|
+
compressed: bool = False
|
|
182
|
+
) -> "RouteGraph":
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The load method is a static method that allows you to load a graph from its save file into a new graph object.
|
|
186
|
+
The resulting graph object is fully initialized and can be used as is.
|
|
187
|
+
|
|
188
|
+
#### args
|
|
189
|
+
|
|
190
|
+
- filepath: str = the full path to your save file
|
|
191
|
+
- compressed: bool = set this to `True` if your graph was saved to a `.zlib` compressed file (default=`False`)
|
|
192
|
+
|
|
193
|
+
#### example
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from multimodalrouter import RouteGraph
|
|
197
|
+
# load a .dill file from 'pathToMyGraph'
|
|
198
|
+
myGraph = RouteGraph.load(filepath=pathToMyGraph)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The `myGraph` object is now fully loaded and can be used to its full extend.
|
|
202
|
+
|
|
203
|
+
### searching with coordinates
|
|
204
|
+
|
|
205
|
+
Since searching by hub id is not always possible the graph has a helper that finds a hub closest to a coordinate tuple.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
def findClosestHub(
|
|
209
|
+
self,
|
|
210
|
+
allowedHubTypes: list[str],
|
|
211
|
+
coords: list[float],
|
|
212
|
+
) -> Hub | None:
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### args
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
- allowedHubTypes: list[str] = a list that defines which hubs should be searched (e.g. ['airport','trainstation'])
|
|
219
|
+
**NOTE:** if you set this to `None` all hubs will be included in
|
|
220
|
+
the search
|
|
221
|
+
- coords: list[float] = the coordinates of the hub. (not limited to 2 dimensions)
|
|
222
|
+
|
|
223
|
+
> NOTE: the coords must not necessarily be in degrees or any other meaningfull metric aslong as your data provides distances and you turn of enableDrive when building the graph or you do [this](./graph.md#advanced-options)
|
|
224
|
+
|
|
225
|
+
> NOTE: it is entirely possible to setup the graph with custom coordinate systems and distances
|
|
226
|
+
|
|
227
|
+
#### example
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
coordinates = 100.0, 100.0
|
|
231
|
+
closestHub = graph.findClosestHub(
|
|
232
|
+
allowedHUbTypes = None, # include all types in search
|
|
233
|
+
*coordinates,
|
|
234
|
+
)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
> NOTE: you can now use `closestHub.id` in the [search](#routing--finding-the-shortest-path-form-a-to-b)
|
|
238
|
+
|
|
239
|
+
### getting hubs by id
|
|
240
|
+
|
|
241
|
+
If you want to inspect a hub and you know its `id` you can get it from the graph as follows
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
def getHub(
|
|
245
|
+
self,
|
|
246
|
+
hubType: str,
|
|
247
|
+
id: str
|
|
248
|
+
) -> Hub | None:
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
or
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
def getHubById(
|
|
255
|
+
self,
|
|
256
|
+
id: str
|
|
257
|
+
) -> Hub | None:
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### args
|
|
261
|
+
|
|
262
|
+
- hubType: str = the type of the target hub
|
|
263
|
+
- id: str = the id of the target hub
|
|
264
|
+
|
|
265
|
+
**returns:** the Hub or if not found None
|
|
266
|
+
|
|
267
|
+
### manually adding Hubs
|
|
268
|
+
|
|
269
|
+
If you want to add a new Hub to a graph without building use this:
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
def addHub(self, hub: Hub):
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
This will add your Hub to the garph and if its already present it will fail silently
|
|
276
|
+
|
|
277
|
+
### args
|
|
278
|
+
|
|
279
|
+
- hub: Hub = the Hub you want to add
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
### advanced options
|
|
285
|
+
|
|
286
|
+
#### swap distance method
|
|
287
|
+
|
|
288
|
+
When your dataset comes with neither distances nor a coordinate system in degrees you can mount your own distance function. This way you will still be able to build the default driving edges etc.
|
|
289
|
+
|
|
290
|
+
#### example
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
from multimodalrouter import RouteGraph
|
|
294
|
+
import types
|
|
295
|
+
# define your own distance metric (NOTE the arguments must be the same as here)
|
|
296
|
+
def myDistancMetric(self, hub1: list[Hub], hub2: list[Hub]):
|
|
297
|
+
... # here you could for example calculate the euclidean distance
|
|
298
|
+
return distances # np.array or list
|
|
299
|
+
|
|
300
|
+
# create a normal graph object
|
|
301
|
+
specialGraph = RouteGraph(**kwargs)
|
|
302
|
+
# swap the distance method
|
|
303
|
+
specialGraph._hubToHubDistances = types.MethodType(myDistanceMetric, specialGraph)
|
|
304
|
+
# continue as you would normally
|
|
305
|
+
graph.build()
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### NOTES
|
|
309
|
+
|
|
310
|
+
- Naturally you can do the same thing for the preprocessor to calculate the transport mode based distances in the preprocessessing step.
|
|
311
|
+
|
|
312
|
+
#### higher dimensional graphs
|
|
313
|
+
|
|
314
|
+
To build graphs from higher dimensional data a few things have to be done differently. As an example I will use the following datasets
|
|
315
|
+
|
|
316
|
+
| source | destination | sdim1 | sdim2 | sdim3 | ddim1 | ddim2 | ddim3 | distance |
|
|
317
|
+
|--------|-------------|-------|-------|-------|-------|-------|-------|----------|
|
|
318
|
+
| A | B | 0 | 0 | 0 | 1 | 2 | 2 | 3 |
|
|
319
|
+
| C | A | 2 | 4 | 4 | 0 | 0 | 0 | 6 |
|
|
320
|
+
| B | C | 1 | 2 | 2 | 2 | 4 | 4 | 3 |
|
|
321
|
+
|
|
322
|
+
| source | destination | adim1 | adim2 | adim3 | bdim1 | bdim2 | bdim3 | distance |
|
|
323
|
+
|--------|-------------|-------|-------|-------|-------|-------|-------|----------|
|
|
324
|
+
| a | b | 0 | 0 | 0 | 3 | 4 | 0 | 5 |
|
|
325
|
+
| a | c | 0 | 0 | 0 | 0 | 4 | 0 | 4 |
|
|
326
|
+
| c | b | 0 | 4 | 0 | 3 | 4 | 0 | 3 |
|
|
327
|
+
|
|
328
|
+
With these tow 3D datasets you can build a graph as follows:
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
sourceKeys = ['sdim1', 'sdim2', 'sdim3', 'adim1', 'adim2', 'adim3']
|
|
332
|
+
destinationKexs = ['ddim2', 'ddim2', 'ddim3', 'bdim1', 'bdim2', 'bdim3']
|
|
333
|
+
|
|
334
|
+
from multimodalrouter import RouteGraph
|
|
335
|
+
|
|
336
|
+
# create a graph
|
|
337
|
+
|
|
338
|
+
nDimGraph = RouteGraph(
|
|
339
|
+
maxDistance = 3,
|
|
340
|
+
transportModes = {
|
|
341
|
+
'T1': 'mode1',
|
|
342
|
+
'T2': 'mode2'
|
|
343
|
+
},
|
|
344
|
+
dataPaths = {
|
|
345
|
+
'T1': path1, # path to the data from 1st table
|
|
346
|
+
'T2': path2 # path to the data from 2nd table
|
|
347
|
+
},
|
|
348
|
+
drivingEnabled = False, # add your own driving func to enable this
|
|
349
|
+
sourceCoordKeys = sourceKeys, # the keys from the sources
|
|
350
|
+
destCoordKeys = destinationKeys, # the kexs from the destinations
|
|
351
|
+
)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
> Now everything else works as normal but with three coordinates
|
|
355
|
+
|
|
356
|
+
#### Notes:
|
|
357
|
+
|
|
358
|
+
> To enable driving add your own distance function like [this](#swap-distance-method)
|
|
359
|
+
|
|
360
|
+
> It is theoretically possible to combine hubs from differnt dimensions as long as a distance metric is given or the distance is pre calculated
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
---
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Dataclasses
|
|
368
|
+
|
|
369
|
+
### Hub
|
|
370
|
+
|
|
371
|
+
Hubs are the nodes of the [RouteGraph](#routegraph) and store all outgoing connections alongside the relevant [EdgeMetadata](#edgemetadata)
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
def __init__(
|
|
375
|
+
self,
|
|
376
|
+
coords: list[float],
|
|
377
|
+
id: str,
|
|
378
|
+
hubType: str
|
|
379
|
+
):
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### fields
|
|
383
|
+
|
|
384
|
+
- coords: list[float]: the coordinates of the `Hub`. (NOTE: this can be any ndim coordinate aslong as it fits with the rest)
|
|
385
|
+
- id: str = a string id like iata code UNLOCODE or whatever you want (NOTE: must be unique for the hubType)
|
|
386
|
+
- hubType: str = the type of hub this will be (e.g. `airport`, `trainstation`,...)
|
|
387
|
+
|
|
388
|
+
#### adding edges
|
|
389
|
+
|
|
390
|
+
```python
|
|
391
|
+
def addOutgoing(
|
|
392
|
+
self,
|
|
393
|
+
mode: str,
|
|
394
|
+
dest_id: str,
|
|
395
|
+
metrics: EdgeMetadata):
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### args
|
|
399
|
+
|
|
400
|
+
- mode: str = the mode of transport along this edge (e.g. `plane`, `car`,...)
|
|
401
|
+
- dest_id: str = the id of the destination Hub
|
|
402
|
+
- metrics: [EdgeMetadata](#edgemetadata) = the edge object that stores the metrics for this connection
|
|
403
|
+
|
|
404
|
+
#### getting the edge metrics
|
|
405
|
+
|
|
406
|
+
Get the edgeMetadata from this Hub to another, with a given transport mode
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
def getMetrics(
|
|
410
|
+
self,
|
|
411
|
+
mode: str,
|
|
412
|
+
dest_id: str
|
|
413
|
+
)-> EdgeMetadata:
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
#### args
|
|
417
|
+
|
|
418
|
+
- mode: str = the mode of transport along the edge
|
|
419
|
+
- dest_id: str = the id of the destination Hub
|
|
420
|
+
|
|
421
|
+
**returns:** the edgeMetadata or None if this edge doesn't exist
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
---
|
|
425
|
+
### EdgeMetadata
|
|
426
|
+
|
|
427
|
+
These objects store data about one edge such as the `transport mode` and metrics like `distance` etc.
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
def __init__(
|
|
431
|
+
self,
|
|
432
|
+
transportMode: str = None,
|
|
433
|
+
**metrics):
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### args
|
|
437
|
+
|
|
438
|
+
- transportMode: str = the transpot mode across this edge
|
|
439
|
+
- **metrics: dict = a dictionary of edge metrics like `distance`, `time` etc
|
|
440
|
+
|
|
441
|
+
#### example
|
|
442
|
+
|
|
443
|
+
create data for an edge that is traversed via `plane`, has a `distance` of `100.0` and `cost` of `250.0`
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
edgeData = EdgeMetadata(
|
|
447
|
+
transportMode = 'plane',
|
|
448
|
+
**{'distance': 100.0, 'cost': '250.0'}
|
|
449
|
+
)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### get a specific metric
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
def getMetric(
|
|
456
|
+
self,
|
|
457
|
+
metric: OptimizationMetric | str
|
|
458
|
+
):
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### args
|
|
462
|
+
|
|
463
|
+
- metric: str = the name of the metric you want to retrieve
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
### Route
|
|
469
|
+
|
|
470
|
+
A dataclass to store all route related data; like Hubs and edges.
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
#### fields
|
|
474
|
+
|
|
475
|
+
```python
|
|
476
|
+
path: list[tuple[str, str]]
|
|
477
|
+
totalMetrics: EdgeMetadata
|
|
478
|
+
optimizedMetric: OptimizationMetric
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
#### properties
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
```
|
|
486
|
+
@property
|
|
487
|
+
def flatPath(
|
|
488
|
+
self,
|
|
489
|
+
toStr=True):
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
By calling `route.flatPath` you will get the string representation of the route
|
|
493
|
+
|
|
494
|
+
#### example output
|
|
495
|
+
|
|
496
|
+
> NOTE: this is a verbose route from `-1.680000, 29.258334` to `3.490000, 35.840000`, connected through airports with data from [open flights](https://openflights.org/data.php)
|
|
497
|
+
|
|
498
|
+
```text
|
|
499
|
+
Start: GOM
|
|
500
|
+
Edge: (transportMode=plane, metrics={'distance': 85.9251874180552})
|
|
501
|
+
-> BKY
|
|
502
|
+
Edge: (transportMode=drive, metrics={'distance': np.float32(20.288797)})
|
|
503
|
+
-> KME
|
|
504
|
+
Edge: (transportMode=plane, metrics={'distance': 147.44185301830063})
|
|
505
|
+
-> KGL
|
|
506
|
+
Edge: (transportMode=plane, metrics={'distance': 757.9567739118678})
|
|
507
|
+
-> NBO
|
|
508
|
+
Edge: (transportMode=plane, metrics={'distance': 515.1466233682448})
|
|
509
|
+
-> LOK
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[HOME](../README.md)
|
|
2
|
+
|
|
3
|
+
# Installation Guide
|
|
4
|
+
|
|
5
|
+
## Step 1
|
|
6
|
+
|
|
7
|
+
First check if your data comes with precomputed distances and if you are going to want to use the default [driving connections](./graph.md) when building your graph.
|
|
8
|
+
Depending on your choices you will need to install the library with torch. To see what your use case requires check the table below and copy the command.
|
|
9
|
+
|
|
10
|
+
| data has distances | use driving edges | installation mode |
|
|
11
|
+
|--------------------|-------------------|-------------------------------------|
|
|
12
|
+
| YES | YES |`pip install .[torch]`|
|
|
13
|
+
| YES | NO |`pip install .[torch]`|
|
|
14
|
+
| NO | YES |`pip install .[torch]`|
|
|
15
|
+
| NO | NO | `pip install .` |
|
|
16
|
+
|
|
17
|
+
## Step 2
|
|
18
|
+
|
|
19
|
+
> RUN your command from the root of this project
|
|
20
|
+
|
|
21
|
+
## Step 3
|
|
22
|
+
|
|
23
|
+
The library should now be installed to check you can test with this:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
python -c "import multimodalrouter; print(dir(multimodalrouter))"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The result should look similar to this
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
[
|
|
33
|
+
'EdgeMetadata',
|
|
34
|
+
'Hub',
|
|
35
|
+
'OptimizationMetric',
|
|
36
|
+
'Route',
|
|
37
|
+
'RouteGraph',
|
|
38
|
+
'VerboseRoute',
|
|
39
|
+
'...',
|
|
40
|
+
'preprocessor',
|
|
41
|
+
'utils'
|
|
42
|
+
]
|
|
43
|
+
```
|
|
44
|
+
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[HOME](../README.md)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "multimodalrouter"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "A graph-based routing library for dynamic routing."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE.md" }
|
|
@@ -38,9 +38,15 @@ dependencies = [
|
|
|
38
38
|
|
|
39
39
|
requires-python = ">=3.11"
|
|
40
40
|
|
|
41
|
+
[project.urls]
|
|
42
|
+
Repository = "https://github.com/K-T0BIAS/MultiModalRouter"
|
|
43
|
+
|
|
41
44
|
|
|
42
45
|
[project.optional-dependencies]
|
|
43
46
|
torch = ["torch>=2.8.0"]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=8.0"
|
|
49
|
+
]
|
|
44
50
|
|
|
45
51
|
[tool.setuptools]
|
|
46
52
|
package-dir = {"" = "src"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multimodalrouter
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: A graph-based routing library for dynamic routing.
|
|
5
5
|
Author-email: Tobias Karusseit <karusseittobi@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -14,6 +14,7 @@ License: MIT License
|
|
|
14
14
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
Project-URL: Repository, https://github.com/K-T0BIAS/MultiModalRouter
|
|
17
18
|
Requires-Python: >=3.11
|
|
18
19
|
Description-Content-Type: text/markdown
|
|
19
20
|
License-File: LICENSE.md
|
|
@@ -41,6 +42,8 @@ Requires-Dist: typing_extensions>=4.15.0
|
|
|
41
42
|
Requires-Dist: tzdata>=2025.2
|
|
42
43
|
Provides-Extra: torch
|
|
43
44
|
Requires-Dist: torch>=2.8.0; extra == "torch"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
44
47
|
Dynamic: license-file
|
|
45
48
|
|
|
46
49
|
# Multi Modal Router
|
|
@@ -2,6 +2,17 @@ LICENSE.md
|
|
|
2
2
|
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
4
|
pyproject.toml
|
|
5
|
+
docs/cli.md
|
|
6
|
+
docs/graph.md
|
|
7
|
+
docs/installation.md
|
|
8
|
+
docs/solvedMaze1.png
|
|
9
|
+
docs/utils.md
|
|
10
|
+
docs/examples/demoData.csv
|
|
11
|
+
docs/examples/flightRouter/main.py
|
|
12
|
+
docs/examples/flightRouter/data/fullDataset.csv
|
|
13
|
+
docs/examples/mazePathfinder/main.py
|
|
14
|
+
docs/examples/mazePathfinder/data/createMaze.py
|
|
15
|
+
docs/examples/mazePathfinder/data/maze.csv
|
|
5
16
|
src/multiModalRouter.egg-info/PKG-INFO
|
|
6
17
|
src/multiModalRouter.egg-info/SOURCES.txt
|
|
7
18
|
src/multiModalRouter.egg-info/dependency_links.txt
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multiModalRouter.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{multimodalrouter-0.1.0 → multimodalrouter-0.1.2}/src/multimodalrouter/utils/preprocessor.py
RENAMED
|
File without changes
|