scgraph 3.5.0__tar.gz → 3.6.0b2__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.
Files changed (32) hide show
  1. scgraph-3.6.0b2/CMakeLists.txt +48 -0
  2. {scgraph-3.5.0 → scgraph-3.6.0b2}/PKG-INFO +32 -21
  3. {scgraph-3.5.0 → scgraph-3.6.0b2}/README.md +32 -21
  4. {scgraph-3.5.0 → scgraph-3.6.0b2}/pyproject.toml +23 -4
  5. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/__init__.py +33 -22
  6. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/contraction_hierarchies.py +51 -30
  7. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/bindings/graph_bindings.cpp +46 -38
  8. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/contraction_hierarchies.cpp +46 -16
  9. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/contraction_hierarchies.hpp +13 -3
  10. scgraph-3.6.0b2/scgraph/cpp/src/graph.cpp +1245 -0
  11. scgraph-3.6.0b2/scgraph/cpp/src/graph.hpp +63 -0
  12. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/graph_reducer.cpp +22 -19
  13. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/graph_reducer.hpp +2 -1
  14. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/graph_utils.cpp +93 -17
  15. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/graph_utils.hpp +13 -4
  16. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/transit_node_routing.cpp +123 -75
  17. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/transit_node_routing.hpp +5 -2
  18. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/geograph.py +231 -257
  19. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/graph.py +485 -166
  20. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/graph_reducer.py +163 -82
  21. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/graph_utils.py +77 -22
  22. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/grid.py +43 -9
  23. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/transit_node_routing.py +74 -38
  24. scgraph-3.5.0/CMakeLists.txt +0 -92
  25. scgraph-3.5.0/scgraph/cpp/src/graph.cpp +0 -778
  26. scgraph-3.5.0/scgraph/cpp/src/graph.hpp +0 -61
  27. {scgraph-3.5.0 → scgraph-3.6.0b2}/LICENSE +0 -0
  28. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/cpp/src/bmssp.hpp +0 -0
  29. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/helpers/__init__.py +0 -0
  30. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/helpers/geojson.py +0 -0
  31. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/helpers/visvalingam.py +0 -0
  32. {scgraph-3.5.0 → scgraph-3.6.0b2}/scgraph/utils.py +0 -0
@@ -0,0 +1,48 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+
3
+ # -----------------------------
4
+ # Define The Project
5
+ # -----------------------------
6
+ project(scgraph LANGUAGES CXX)
7
+
8
+ # -----------------------------
9
+ # Find Packages
10
+ # -----------------------------
11
+ find_package(Python 3.10 REQUIRED COMPONENTS Interpreter Development.Module)
12
+ find_package(nanobind CONFIG REQUIRED)
13
+
14
+ # -----------------------------
15
+ # Set C++ standard
16
+ # -----------------------------
17
+ set(CMAKE_CXX_STANDARD 20)
18
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
19
+
20
+ # -----------------------------
21
+ # OPTIMIZATION FLAGS
22
+ # -----------------------------
23
+ set(CMAKE_BUILD_TYPE Release)
24
+ if(MSVC)
25
+ set(CMAKE_CXX_FLAGS_RELEASE "/O2 /DNDEBUG")
26
+ else()
27
+ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fno-math-errno -fomit-frame-pointer")
28
+ endif()
29
+
30
+ # -----------------------------
31
+ # Graph module
32
+ # -----------------------------
33
+ nanobind_add_module(
34
+ cpp
35
+ STABLE_ABI
36
+ scgraph/cpp/bindings/graph_bindings.cpp
37
+ scgraph/cpp/src/graph.cpp
38
+ scgraph/cpp/src/graph_utils.cpp
39
+ scgraph/cpp/src/graph_reducer.cpp
40
+ scgraph/cpp/src/contraction_hierarchies.cpp
41
+ scgraph/cpp/src/transit_node_routing.cpp
42
+ )
43
+ install(TARGETS cpp DESTINATION scgraph)
44
+
45
+ # -----------------------------
46
+ # Install Python package files
47
+ # -----------------------------
48
+ install(DIRECTORY scgraph DESTINATION . FILES_MATCHING PATTERN "*.py")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scgraph
3
- Version: 3.5.0
3
+ Version: 3.6.0b2
4
4
  Summary: Determine an approximate distance and route between two points on earth.
5
5
  Author-Email: Connor Makowski <conmak@mit.edu>
6
6
  License-Expression: MIT
@@ -11,7 +11,7 @@ Project-URL: Homepage, https://github.com/connor-makowski/scgraph
11
11
  Project-URL: Bug Tracker, https://github.com/connor-makowski/scgraph/issues
12
12
  Project-URL: Documentation, https://connor-makowski.github.io/scgraph/scgraph.html
13
13
  Requires-Python: >=3.11
14
- Requires-Dist: geokdtree==1.2.4
14
+ Requires-Dist: geokdtree>=1.3.0
15
15
  Requires-Dist: bmsspy<3.0.0,>=2.2.1
16
16
  Requires-Dist: requests<3.0.0,>=2.32.0
17
17
  Provides-Extra: dev
@@ -68,18 +68,33 @@ If you use SCGraph in your research, please cite:
68
68
  pip install scgraph
69
69
  ```
70
70
 
71
- A C++ extension is compiled automatically if a C++ compiler is available (~10x speedup on core algorithms). To verify: `from scgraph.utils import cpp_check; cpp_check()`.
71
+ ### Pure Python Installation (Skip Binary Builds)
72
72
 
73
- To skip the C++ build:
73
+ If you want to install `scgraph` in pure Python mode without compiling or using binary extensions (or in environments without a C++ compiler):
74
74
 
75
- ```bash
76
- # macOS / Linux / WSL2
77
- export SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON" && pip install scgraph
78
- # Windows (PowerShell)
79
- $env:SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON"; pip install scgraph
80
- # Windows (CMD)
81
- set SKBUILD_CMAKE_ARGS=-DSKIP_CPP_BUILD=ON && pip install scgraph
82
- ```
75
+ - **Linux / macOS / WSL2**:
76
+ ```bash
77
+ SCGRAPH_NO_BUILD=1 pip install --no-binary scgraph scgraph
78
+ ```
79
+ Or with `uv`:
80
+ ```bash
81
+ SCGRAPH_NO_BUILD=1 uv pip install --no-binary scgraph scgraph
82
+ ```
83
+
84
+ - **Windows (PowerShell)**:
85
+ ```powershell
86
+ $env:SCGRAPH_NO_BUILD="1"
87
+ pip install --no-binary scgraph scgraph
88
+ ```
89
+
90
+ - **Windows (CMD)**:
91
+ ```cmd
92
+ set SCGRAPH_NO_BUILD=1
93
+ pip install --no-binary scgraph scgraph
94
+ ```
95
+
96
+ #### Automatic Fallback
97
+ When building from source, if a C++ compiler is not available or compilation fails, `scgraph` will automatically fall back to a pure Python implementation.
83
98
 
84
99
  ---
85
100
 
@@ -200,9 +215,10 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
200
215
 
201
216
  | `algorithm_fn` | Description | Time Complexity |
202
217
  |---|---|---|
203
- | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights (default) | O((n+m) log n) |
218
+ | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights | O((n+m) log n) |
204
219
  | `'bidirectional_dijkstra'` | Bidirectional Dijkstra; simultaneous search from origin and destination | O((n+m) log n) |
205
220
  | `'dijkstra_buckets'` | Dijkstra with buckets (Dial's algorithm); efficient for non-negative weights (ideally >= 1) | O(n+m+W) |
221
+ | `'bidirectional_buckets'` | Bidirectional Dijkstra (default for geographs) with buckets (Dial's algorithm); efficient for non-negative weights | O(n+m+W) |
206
222
  | `'dijkstra_negative'` | Dijkstra with cycle detection; supports negative weights | O(n·m) |
207
223
  | `'a_star'` | A* with optional heuristic; faster than Dijkstra with a good heuristic | O((n+m) log n) |
208
224
  | `'bellman_ford'` | Bellman-Ford; supports negative weights, slower than Dijkstra | O(n·m) |
@@ -215,7 +231,7 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
215
231
 
216
232
  | Scenario | Recommended Approach |
217
233
  |---|---|
218
- | Single query | `dijkstra` (default) or `bidirectional_dijkstra` |
234
+ | Single query | `dijkstra`, `bidirectional_buckets` or `bidirectional_dijkstra` |
219
235
  | Sparse networks (road/rail/maritime) | Reduce with `geograph.reduce()` for 2–4x faster queries |
220
236
  | Weights generally >= 1 | `dijkstra_buckets` |
221
237
  | Repeated queries from one origin | `cached_shortest_path` |
@@ -410,15 +426,10 @@ output = marnet_geograph.get_shortest_path(
410
426
 
411
427
  | `node_addition_type` | Description |
412
428
  |---|---|
413
- | `'kdclosest'` | Closest node via KD-tree (default, fastest) |
414
- | `'closest'` | Closest node via brute force |
415
- | `'quadrant'` | Closest node in each of 4 quadrants |
429
+ | `'closest'` / `'kdclosest'` | Closest node via GeoKDTree (default) |
430
+ | `'quadrant'` / `'kdquadrant'` | Closest node in each quadrant via GeoKDTree |
416
431
  | `'all'` | All nodes within the bound |
417
432
 
418
- | `node_addition_math` | Description |
419
- |---|---|
420
- | `'euclidean'` | Fast planar distance (default) |
421
- | `'haversine'` | Accurate great-circle distance |
422
433
 
423
434
  ---
424
435
 
@@ -40,18 +40,33 @@ If you use SCGraph in your research, please cite:
40
40
  pip install scgraph
41
41
  ```
42
42
 
43
- A C++ extension is compiled automatically if a C++ compiler is available (~10x speedup on core algorithms). To verify: `from scgraph.utils import cpp_check; cpp_check()`.
44
-
45
- To skip the C++ build:
46
-
47
- ```bash
48
- # macOS / Linux / WSL2
49
- export SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON" && pip install scgraph
50
- # Windows (PowerShell)
51
- $env:SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON"; pip install scgraph
52
- # Windows (CMD)
53
- set SKBUILD_CMAKE_ARGS=-DSKIP_CPP_BUILD=ON && pip install scgraph
54
- ```
43
+ ### Pure Python Installation (Skip Binary Builds)
44
+
45
+ If you want to install `scgraph` in pure Python mode without compiling or using binary extensions (or in environments without a C++ compiler):
46
+
47
+ - **Linux / macOS / WSL2**:
48
+ ```bash
49
+ SCGRAPH_NO_BUILD=1 pip install --no-binary scgraph scgraph
50
+ ```
51
+ Or with `uv`:
52
+ ```bash
53
+ SCGRAPH_NO_BUILD=1 uv pip install --no-binary scgraph scgraph
54
+ ```
55
+
56
+ - **Windows (PowerShell)**:
57
+ ```powershell
58
+ $env:SCGRAPH_NO_BUILD="1"
59
+ pip install --no-binary scgraph scgraph
60
+ ```
61
+
62
+ - **Windows (CMD)**:
63
+ ```cmd
64
+ set SCGRAPH_NO_BUILD=1
65
+ pip install --no-binary scgraph scgraph
66
+ ```
67
+
68
+ #### Automatic Fallback
69
+ When building from source, if a C++ compiler is not available or compilation fails, `scgraph` will automatically fall back to a pure Python implementation.
55
70
 
56
71
  ---
57
72
 
@@ -172,9 +187,10 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
172
187
 
173
188
  | `algorithm_fn` | Description | Time Complexity |
174
189
  |---|---|---|
175
- | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights (default) | O((n+m) log n) |
190
+ | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights | O((n+m) log n) |
176
191
  | `'bidirectional_dijkstra'` | Bidirectional Dijkstra; simultaneous search from origin and destination | O((n+m) log n) |
177
192
  | `'dijkstra_buckets'` | Dijkstra with buckets (Dial's algorithm); efficient for non-negative weights (ideally >= 1) | O(n+m+W) |
193
+ | `'bidirectional_buckets'` | Bidirectional Dijkstra (default for geographs) with buckets (Dial's algorithm); efficient for non-negative weights | O(n+m+W) |
178
194
  | `'dijkstra_negative'` | Dijkstra with cycle detection; supports negative weights | O(n·m) |
179
195
  | `'a_star'` | A* with optional heuristic; faster than Dijkstra with a good heuristic | O((n+m) log n) |
180
196
  | `'bellman_ford'` | Bellman-Ford; supports negative weights, slower than Dijkstra | O(n·m) |
@@ -187,7 +203,7 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
187
203
 
188
204
  | Scenario | Recommended Approach |
189
205
  |---|---|
190
- | Single query | `dijkstra` (default) or `bidirectional_dijkstra` |
206
+ | Single query | `dijkstra`, `bidirectional_buckets` or `bidirectional_dijkstra` |
191
207
  | Sparse networks (road/rail/maritime) | Reduce with `geograph.reduce()` for 2–4x faster queries |
192
208
  | Weights generally >= 1 | `dijkstra_buckets` |
193
209
  | Repeated queries from one origin | `cached_shortest_path` |
@@ -382,15 +398,10 @@ output = marnet_geograph.get_shortest_path(
382
398
 
383
399
  | `node_addition_type` | Description |
384
400
  |---|---|
385
- | `'kdclosest'` | Closest node via KD-tree (default, fastest) |
386
- | `'closest'` | Closest node via brute force |
387
- | `'quadrant'` | Closest node in each of 4 quadrants |
401
+ | `'closest'` / `'kdclosest'` | Closest node via GeoKDTree (default) |
402
+ | `'quadrant'` / `'kdquadrant'` | Closest node in each quadrant via GeoKDTree |
388
403
  | `'all'` | All nodes within the bound |
389
404
 
390
- | `node_addition_math` | Description |
391
- |---|---|
392
- | `'euclidean'` | Fast planar distance (default) |
393
- | `'haversine'` | Accurate great-circle distance |
394
405
 
395
406
  ---
396
407
 
@@ -4,15 +4,20 @@ target-version = ['py312']
4
4
  exclude = '/.*(migrations|__pycache__|geographs).*/'
5
5
 
6
6
  [build-system]
7
- requires = ["scikit_build_core", "nanobind"]
7
+ requires = ["scikit-build-core", "nanobind>=3.1.0"]
8
8
  build-backend = "scikit_build_core.build"
9
9
 
10
10
  [tool.scikit-build]
11
11
  build.verbose = false
12
12
  build-dir = "build/{wheel_tag}"
13
13
 
14
+ [[tool.scikit-build.overrides]]
15
+ if.env.SCGRAPH_NO_BUILD = true
16
+ wheel.cmake = false
17
+
14
18
  [[tool.scikit-build.overrides]]
15
19
  if.failed = true
20
+ if.not.env.SCGRAPH_REQUIRE_CPP = true
16
21
  wheel.cmake = false
17
22
 
18
23
  [tool.scikit-build.sdist]
@@ -30,7 +35,7 @@ include = [
30
35
 
31
36
  [project]
32
37
  name = "scgraph"
33
- version = "3.5.0"
38
+ version = "3.6.0b2"
34
39
  description = "Determine an approximate distance and route between two points on earth."
35
40
  authors = [
36
41
  {name="Connor Makowski", email="conmak@mit.edu"}
@@ -44,7 +49,7 @@ classifiers = [
44
49
  "Operating System :: OS Independent",
45
50
  ]
46
51
  dependencies = [
47
- "geokdtree==1.2.4",
52
+ "geokdtree>=1.3.0",
48
53
  "bmsspy>=2.2.1,<3.0.0",
49
54
  "requests>=2.32.0,<3.0.0"
50
55
  ]
@@ -65,6 +70,7 @@ dev = [
65
70
  [tool.pytest.ini_options]
66
71
  testpaths = ["test"]
67
72
  pythonpath = ["test"]
73
+ python_files = ["*_test.py"]
68
74
 
69
75
  [tool.uv]
70
76
  no-build-isolation-package = []
@@ -72,4 +78,17 @@ no-build-isolation-package = []
72
78
  [project.urls]
73
79
  "Homepage" = "https://github.com/connor-makowski/scgraph"
74
80
  "Bug Tracker" = "https://github.com/connor-makowski/scgraph/issues"
75
- "Documentation" = "https://connor-makowski.github.io/scgraph/scgraph.html"
81
+ "Documentation" = "https://connor-makowski.github.io/scgraph/scgraph.html"
82
+
83
+ [tool.cibuildwheel]
84
+ build = "cp311-* cp312-* cp313-* cp314-*"
85
+ skip = "*-win32 *_i686 pp*"
86
+ test-command = "pytest {project}/test"
87
+ test-requires = ["pytest>=9.0.3"]
88
+
89
+ [tool.cibuildwheel.linux]
90
+ manylinux-x86_64-image = "manylinux_2_28"
91
+ manylinux-aarch64-image = "manylinux_2_28"
92
+
93
+ [tool.cibuildwheel.windows]
94
+ repair-wheel-command = ""
@@ -1,4 +1,4 @@
1
- """
1
+ r"""
2
2
  # SCGraph
3
3
  [![PyPI version](https://badge.fury.io/py/scgraph.svg)](https://badge.fury.io/py/scgraph)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -41,18 +41,33 @@ If you use SCGraph in your research, please cite:
41
41
  pip install scgraph
42
42
  ```
43
43
 
44
- A C++ extension is compiled automatically if a C++ compiler is available (~10x speedup on core algorithms). To verify: `from scgraph.utils import cpp_check; cpp_check()`.
44
+ ### Pure Python Installation (Skip Binary Builds)
45
45
 
46
- To skip the C++ build:
46
+ If you want to install `scgraph` in pure Python mode without compiling or using binary extensions (or in environments without a C++ compiler):
47
47
 
48
- ```bash
49
- # macOS / Linux / WSL2
50
- export SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON" && pip install scgraph
51
- # Windows (PowerShell)
52
- $env:SKBUILD_CMAKE_ARGS="-DSKIP_CPP_BUILD=ON"; pip install scgraph
53
- # Windows (CMD)
54
- set SKBUILD_CMAKE_ARGS=-DSKIP_CPP_BUILD=ON && pip install scgraph
55
- ```
48
+ - **Linux / macOS / WSL2**:
49
+ ```bash
50
+ SCGRAPH_NO_BUILD=1 pip install --no-binary scgraph scgraph
51
+ ```
52
+ Or with `uv`:
53
+ ```bash
54
+ SCGRAPH_NO_BUILD=1 uv pip install --no-binary scgraph scgraph
55
+ ```
56
+
57
+ - **Windows (PowerShell)**:
58
+ ```powershell
59
+ $env:SCGRAPH_NO_BUILD="1"
60
+ pip install --no-binary scgraph scgraph
61
+ ```
62
+
63
+ - **Windows (CMD)**:
64
+ ```cmd
65
+ set SCGRAPH_NO_BUILD=1
66
+ pip install --no-binary scgraph scgraph
67
+ ```
68
+
69
+ #### Automatic Fallback
70
+ When building from source, if a C++ compiler is not available or compilation fails, `scgraph` will automatically fall back to a pure Python implementation.
56
71
 
57
72
  ---
58
73
 
@@ -173,9 +188,10 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
173
188
 
174
189
  | `algorithm_fn` | Description | Time Complexity |
175
190
  |---|---|---|
176
- | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights (default) | O((n+m) log n) |
191
+ | `'dijkstra'` | Standard Dijkstra; general purpose, non-negative weights | O((n+m) log n) |
177
192
  | `'bidirectional_dijkstra'` | Bidirectional Dijkstra; simultaneous search from origin and destination | O((n+m) log n) |
178
193
  | `'dijkstra_buckets'` | Dijkstra with buckets (Dial's algorithm); efficient for non-negative weights (ideally >= 1) | O(n+m+W) |
194
+ | `'bidirectional_buckets'` | Bidirectional Dijkstra (default for geographs) with buckets (Dial's algorithm); efficient for non-negative weights | O(n+m+W) |
179
195
  | `'dijkstra_negative'` | Dijkstra with cycle detection; supports negative weights | O(n·m) |
180
196
  | `'a_star'` | A* with optional heuristic; faster than Dijkstra with a good heuristic | O((n+m) log n) |
181
197
  | `'bellman_ford'` | Bellman-Ford; supports negative weights, slower than Dijkstra | O(n·m) |
@@ -188,7 +204,7 @@ All algorithms are available on `Graph` objects and accessible from `GeoGraph` v
188
204
 
189
205
  | Scenario | Recommended Approach |
190
206
  |---|---|
191
- | Single query | `dijkstra` (default) or `bidirectional_dijkstra` |
207
+ | Single query | `dijkstra`, `bidirectional_buckets` or `bidirectional_dijkstra` |
192
208
  | Sparse networks (road/rail/maritime) | Reduce with `geograph.reduce()` for 2–4x faster queries |
193
209
  | Weights generally >= 1 | `dijkstra_buckets` |
194
210
  | Repeated queries from one origin | `cached_shortest_path` |
@@ -383,15 +399,10 @@ output = marnet_geograph.get_shortest_path(
383
399
 
384
400
  | `node_addition_type` | Description |
385
401
  |---|---|
386
- | `'kdclosest'` | Closest node via KD-tree (default, fastest) |
387
- | `'closest'` | Closest node via brute force |
388
- | `'quadrant'` | Closest node in each of 4 quadrants |
402
+ | `'closest'` / `'kdclosest'` | Closest node via GeoKDTree (default) |
403
+ | `'quadrant'` / `'kdquadrant'` | Closest node in each quadrant via GeoKDTree |
389
404
  | `'all'` | All nodes within the bound |
390
405
 
391
- | `node_addition_math` | Description |
392
- |---|---|
393
- | `'euclidean'` | Fast planar distance (default) |
394
- | `'haversine'` | Accurate great-circle distance |
395
406
 
396
407
  ---
397
408
 
@@ -432,7 +443,7 @@ The cache location defaults to the platform-appropriate directory:
432
443
  |---|---|
433
444
  | Linux | `~/.cache/scgraph/` |
434
445
  | macOS | `~/Library/Caches/scgraph/` |
435
- | Windows | `%LOCALAPPDATA%\\scgraph\\` |
446
+ | Windows | `%LOCALAPPDATA%\scgraph\` |
436
447
 
437
448
  ### `load_geograph` Parameters
438
449
 
@@ -817,6 +828,7 @@ Originally inspired by [searoute](https://github.com/genthalili/searoute-py), in
817
828
 
818
829
  """
819
830
 
831
+
820
832
  from scgraph.graph_reducer import algorithm
821
833
 
822
834
  try:
@@ -829,4 +841,3 @@ except ImportError:
829
841
 
830
842
  from scgraph.geograph import GeoGraph
831
843
  from scgraph.grid import GridGraph
832
-
@@ -1,7 +1,11 @@
1
1
  import json
2
- from heapq import heappush, heappop
2
+ from heapq import heappush, heappop, heapify
3
3
  from typing import Callable, Any, Optional, Union
4
- from scgraph.graph_utils import GraphUtils, GraphModifiers
4
+ from scgraph.graph_utils import (
5
+ GraphUtils,
6
+ GraphModifiers,
7
+ normalize_node_input,
8
+ )
5
9
 
6
10
 
7
11
  class CHGraphIO:
@@ -505,7 +509,10 @@ class CHGraphAlgorithms:
505
509
  return neighbors
506
510
 
507
511
  def search(
508
- self, origin_id: int, destination_id: int, length_only: bool = False
512
+ self,
513
+ origin_id: int | set[int] | dict[int, int | float],
514
+ destination_id: int | set[int] | dict[int, int | float],
515
+ length_only: bool = False,
509
516
  ) -> dict[str, Any]:
510
517
  """
511
518
  Function:
@@ -515,11 +522,11 @@ class CHGraphAlgorithms:
515
522
  Required Arguments:
516
523
 
517
524
  - `origin_id`
518
- - Type: int
519
- - What: The id of the origin node
525
+ - Type: int | set[int] | dict[int, int | float]
526
+ - What: The id(s) of the origin node(s) (with optional starting distances)
520
527
  - `destination_id`
521
- - Type: int
522
- - What: The id of the destination node
528
+ - Type: int | set[int] | dict[int, int | float]
529
+ - What: The id(s) of the destination node(s) (with optional exit distances)
523
530
 
524
531
  Optional Arguments:
525
532
 
@@ -531,28 +538,39 @@ class CHGraphAlgorithms:
531
538
  Returns:
532
539
 
533
540
  - A dictionary with the following keys:
534
- - `path`: A list of node ids representing the shortest path (omitted if length_only=True)
541
+ - `path`: A list of node ids representing the shortest path (empty if length_only=True)
535
542
  - `length`: The total length of the shortest path
536
543
  """
537
- if origin_id == destination_id:
538
- return (
539
- {"length": 0}
540
- if length_only
541
- else {"path": [origin_id], "length": 0}
542
- )
544
+ origin_dict = normalize_node_input(origin_id)
545
+ destination_dict = normalize_node_input(destination_id)
546
+
547
+ overlap = set(origin_dict.keys()) & set(destination_dict.keys())
548
+ best_dist = float("inf")
549
+ meeting_node = -1
550
+ if overlap:
551
+ for node in overlap:
552
+ dist = origin_dict[node] + destination_dict[node]
553
+ if dist < best_dist:
554
+ best_dist = dist
555
+ meeting_node = node
543
556
 
544
557
  # Forward search state
545
- forward_distances = {origin_id: 0}
546
- forward_parent = {origin_id: -1}
547
- forward_open_leaves = [(0, origin_id)]
558
+ forward_distances = {node: dist for node, dist in origin_dict.items()}
559
+ forward_parent = {node: -1 for node in origin_dict}
560
+ forward_open_leaves = [
561
+ (dist, node) for node, dist in origin_dict.items()
562
+ ]
563
+ heapify(forward_open_leaves)
548
564
 
549
565
  # Backward search state
550
- backward_distances = {destination_id: 0}
551
- backward_parent = {destination_id: -1}
552
- backward_open_leaves = [(0, destination_id)]
553
-
554
- best_dist = float("inf")
555
- meeting_node = -1
566
+ backward_distances = {
567
+ node: dist for node, dist in destination_dict.items()
568
+ }
569
+ backward_parent = {node: -1 for node in destination_dict}
570
+ backward_open_leaves = [
571
+ (dist, node) for node, dist in destination_dict.items()
572
+ ]
573
+ heapify(backward_open_leaves)
556
574
 
557
575
  while forward_open_leaves or backward_open_leaves:
558
576
  # Forward step
@@ -688,7 +706,7 @@ class CHGraphAlgorithms:
688
706
  raise Exception("No path found between origin and destination")
689
707
 
690
708
  if length_only:
691
- return {"length": best_dist}
709
+ return {"path": [], "length": best_dist}
692
710
 
693
711
  path = self.__reconstruct_ch_path__(
694
712
  origin_id,
@@ -925,7 +943,10 @@ class CHGraph(
925
943
  return self.original_graph
926
944
 
927
945
  def get_shortest_path(
928
- self, origin_id: int, destination_id: int, **kwargs: Any
946
+ self,
947
+ origin_id: int | set[int] | dict[int, int | float],
948
+ destination_id: int | set[int] | dict[int, int | float],
949
+ **kwargs: Any,
929
950
  ) -> dict[str, Any]:
930
951
  """
931
952
  Function:
@@ -935,11 +956,11 @@ class CHGraph(
935
956
  Required Arguments:
936
957
 
937
958
  - `origin_id`
938
- - Type: int
939
- - What: The id of the origin node
959
+ - Type: int | set[int] | dict[int, int | float]
960
+ - What: The origin node id(s), optionally with starting distances
940
961
  - `destination_id`
941
- - Type: int
942
- - What: The id of the destination node
962
+ - Type: int | set[int] | dict[int, int | float]
963
+ - What: The destination node id(s), optionally with exit distances
943
964
 
944
965
  Returns:
945
966
 
@@ -947,4 +968,4 @@ class CHGraph(
947
968
  - `path`: A list of node ids representing the shortest path
948
969
  - `length`: The total length of the shortest path
949
970
  """
950
- return self.search(origin_id, destination_id)
971
+ return self.search(origin_id, destination_id, **kwargs)