edsger 0.1.2__tar.gz → 0.1.3__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.
- {edsger-0.1.2 → edsger-0.1.3}/.github/workflows/publish.yml +27 -44
- {edsger-0.1.2 → edsger-0.1.3}/.github/workflows/tests.yml +11 -10
- {edsger-0.1.2 → edsger-0.1.3}/PKG-INFO +12 -12
- {edsger-0.1.2 → edsger-0.1.3}/README.md +11 -11
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/index.md +3 -1
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/quickstart.md +119 -10
- edsger-0.1.3/src/edsger/_version.py +1 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/commons.c +146 -146
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/dijkstra.c +7058 -2696
- edsger-0.1.3/src/edsger/dijkstra.pyx +1029 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/path.py +145 -37
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/path_tracking.c +146 -146
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/pq_4ary_dec_0b.c +146 -146
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/spiess_florian.c +146 -146
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/star.c +146 -146
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/PKG-INFO +12 -12
- {edsger-0.1.2 → edsger-0.1.3}/tests/test_path.py +181 -0
- edsger-0.1.2/src/edsger/_version.py +0 -1
- edsger-0.1.2/src/edsger/dijkstra.pyx +0 -527
- {edsger-0.1.2 → edsger-0.1.3}/.github/workflows/docs.yml +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/.gitignore +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/.pre-commit-config.yaml +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/.readthedocs.yaml +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/AUTHORS.rst +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/CHANGELOG.rst +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/CONTRIBUTING.rst +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/LICENSE +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/MANIFEST.in +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/Makefile +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/requirements.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/api.md +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/assets/dijkstra_benchmark_comparison.png +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/conf.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/contributing.md +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/docs/source/installation.md +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/pyproject.toml +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/requirements-dev.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/requirements.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/scripts/benchmark_comparison.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/scripts/dijkstra_dimacs.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/scripts/requirements.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/setup.cfg +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/setup.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/.gitignore +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/__init__.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/commons.pxd +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/commons.pyx +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/networks.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/path_tracking.pyx +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/pq_4ary_dec_0b.pxd +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/pq_4ary_dec_0b.pyx +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/prefetch_compat.h +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/spiess_florian.pyx +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/star.pyx +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger/utils.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/SOURCES.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/dependency_links.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/not-zip-safe +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/requires.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/src/edsger.egg-info/top_level.txt +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/tests/test_dijkstra.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/tests/test_path_tracking.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/tests/test_pq_4ary_dec_0b.py +0 -0
- {edsger-0.1.2 → edsger-0.1.3}/tests/test_spiess_florian.py +0 -0
@@ -1,9 +1,10 @@
|
|
1
|
-
name: ci-publish #
|
1
|
+
name: ci-publish # Publish Python distribution to PyPI
|
2
2
|
|
3
3
|
on:
|
4
4
|
push:
|
5
5
|
tags:
|
6
6
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
7
|
+
|
7
8
|
jobs:
|
8
9
|
|
9
10
|
test:
|
@@ -13,45 +14,31 @@ jobs:
|
|
13
14
|
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
14
15
|
runs-on: ${{ matrix.os }}
|
15
16
|
steps:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
python -m pytest tests
|
17
|
+
- uses: actions/checkout@v4
|
18
|
+
- name: Set up Python ${{ matrix.python-version }}
|
19
|
+
uses: actions/setup-python@v4
|
20
|
+
with:
|
21
|
+
python-version: ${{ matrix.python-version }}
|
22
|
+
- name: Install dependencies
|
23
|
+
run: |
|
24
|
+
python -m pip install --upgrade pip
|
25
|
+
pip install -r requirements-dev.txt
|
26
|
+
pip install .
|
27
|
+
- name: Testing
|
28
|
+
run: python -m pytest tests
|
29
29
|
|
30
30
|
build_source_dist:
|
31
31
|
name: Build source distribution
|
32
32
|
runs-on: ubuntu-latest
|
33
33
|
steps:
|
34
34
|
- uses: actions/checkout@v4
|
35
|
-
# - if: github.event.ref_type != 'tag'
|
36
|
-
# run: |
|
37
|
-
# git fetch --prune --unshallow
|
38
|
-
# git tag -d $(git tag --points-at HEAD)
|
39
|
-
- if: github.event.ref_type == 'tag'
|
40
|
-
uses: actions/checkout@v3
|
41
|
-
- if: github.event_name == 'workflow_dispatch'
|
42
|
-
uses: actions/checkout@v3
|
43
|
-
with:
|
44
|
-
fetch-depth: 0
|
45
35
|
- uses: actions/setup-python@v4
|
46
36
|
with:
|
47
37
|
python-version: "3.11"
|
48
|
-
|
49
38
|
- name: Install build
|
50
39
|
run: python -m pip install build
|
51
|
-
|
52
40
|
- name: Run build
|
53
41
|
run: python -m build --sdist
|
54
|
-
|
55
42
|
- uses: actions/upload-artifact@v4
|
56
43
|
with:
|
57
44
|
name: cibw-sdist
|
@@ -66,23 +53,20 @@ jobs:
|
|
66
53
|
|
67
54
|
steps:
|
68
55
|
- uses: actions/checkout@v4
|
69
|
-
|
70
|
-
- uses: actions/setup-python@v3
|
71
|
-
|
56
|
+
- uses: actions/setup-python@v4
|
72
57
|
- name: Install cibuildwheel
|
73
58
|
run: python -m pip install cibuildwheel==2.16.5
|
74
|
-
|
75
59
|
- name: Build wheels
|
60
|
+
env:
|
61
|
+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
|
76
62
|
run: python -m cibuildwheel --output-dir wheelhouse
|
77
|
-
|
78
63
|
- uses: actions/upload-artifact@v4
|
79
64
|
with:
|
80
65
|
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
81
66
|
path: ./wheelhouse/*.whl
|
82
67
|
|
83
68
|
publish-to-pypi:
|
84
|
-
name:
|
85
|
-
Publish Python distribution to PyPI
|
69
|
+
name: Publish Python distribution to PyPI
|
86
70
|
needs:
|
87
71
|
- test
|
88
72
|
- build_source_dist
|
@@ -90,14 +74,13 @@ jobs:
|
|
90
74
|
runs-on: ubuntu-latest
|
91
75
|
environment: release
|
92
76
|
permissions:
|
93
|
-
id-token: write #
|
94
|
-
|
77
|
+
id-token: write # mandatory for trusted publishing
|
95
78
|
steps:
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
79
|
+
- name: Download all the dists
|
80
|
+
uses: actions/download-artifact@v4
|
81
|
+
with:
|
82
|
+
pattern: cibw-*
|
83
|
+
path: ./dist/
|
84
|
+
merge-multiple: true
|
85
|
+
- name: Publish distribution to PyPI
|
86
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
@@ -1,4 +1,4 @@
|
|
1
|
-
name:
|
1
|
+
name: Run tests and upload coverage
|
2
2
|
|
3
3
|
on:
|
4
4
|
push:
|
@@ -7,13 +7,17 @@ on:
|
|
7
7
|
|
8
8
|
jobs:
|
9
9
|
test:
|
10
|
+
name: Run tests and collect coverage
|
10
11
|
strategy:
|
11
12
|
matrix:
|
12
13
|
os: [ubuntu-22.04, windows-2022, macos-14]
|
13
14
|
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
14
15
|
runs-on: ${{ matrix.os }}
|
15
16
|
steps:
|
16
|
-
-
|
17
|
+
- name: Checkout
|
18
|
+
uses: actions/checkout@v4
|
19
|
+
with:
|
20
|
+
fetch-depth: 2
|
17
21
|
- name: Set up Python ${{ matrix.python-version }}
|
18
22
|
uses: actions/setup-python@v5
|
19
23
|
with:
|
@@ -29,13 +33,10 @@ jobs:
|
|
29
33
|
- name: Lint Cython code
|
30
34
|
run: |
|
31
35
|
cython-lint src/edsger/commons.pyx src/edsger/dijkstra.pyx src/edsger/path_tracking.pyx src/edsger/pq_4ary_dec_0b.pyx src/edsger/spiess_florian.pyx src/edsger/star.pyx src/edsger/commons.pxd src/edsger/pq_4ary_dec_0b.pxd
|
32
|
-
- name:
|
36
|
+
- name: Run tests
|
33
37
|
run: |
|
34
|
-
|
35
|
-
- name: Upload
|
36
|
-
uses: codecov/codecov-action@
|
38
|
+
pytest --cov=src/edsger --cov-branch --cov-report=xml tests/
|
39
|
+
- name: Upload results to Codecov
|
40
|
+
uses: codecov/codecov-action@v5
|
37
41
|
with:
|
38
|
-
|
39
|
-
flags: unittests
|
40
|
-
name: codecov-umbrella
|
41
|
-
fail_ci_if_error: false
|
42
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: edsger
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.3
|
4
4
|
Summary: Graph algorithms in Cython.
|
5
5
|
Author-email: François Pacull <francois.pacull@architecture-performance.fr>
|
6
6
|
Maintainer-email: François Pacull <francois.pacull@architecture-performance.fr>
|
@@ -42,7 +42,7 @@ Dynamic: license-file
|
|
42
42
|
|
43
43
|

|
44
44
|
[](https://codecov.io/gh/aetperf/edsger)
|
45
|
-
[](https://pypi.org/project/edsger/)
|
45
|
+
[](https://pypi.org/project/edsger/)
|
46
46
|
[](https://pepy.tech/project/edsger)
|
47
47
|
[](https://pypi.org/project/edsger/)
|
48
48
|
[](https://github.com/psf/black)
|
@@ -75,14 +75,14 @@ edges = pd.DataFrame({
|
|
75
75
|
edges
|
76
76
|
```
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
78
|
+
| | tail | head | weight |
|
79
|
+
|---:|-------:|-------:|---------:|
|
80
|
+
| 0 | 0 | 1 | 1.0 |
|
81
|
+
| 1 | 0 | 2 | 4.0 |
|
82
|
+
| 2 | 1 | 2 | 2.0 |
|
83
|
+
| 3 | 2 | 3 | 1.5 |
|
84
|
+
| 4 | 2 | 4 | 3.0 |
|
85
|
+
| 5 | 3 | 4 | 1.0 |
|
86
86
|
|
87
87
|
```python
|
88
88
|
# Initialize the Dijkstra object
|
@@ -101,9 +101,9 @@ We get the shortest paths from the source node 0 to all other nodes in the graph
|
|
101
101
|
|
102
102
|
Edsger is designed to be **dataframe-friendly**, providing seamless integration with pandas workflows for graph algorithms. Also it is rather efficient. Our benchmarks on the USA road network (23.9M vertices, 57.7M edges) demonstrate nice performance:
|
103
103
|
|
104
|
-
<img src="docs/source/assets/dijkstra_benchmark_comparison.png" alt="Dijkstra Performance Comparison" width="700">
|
104
|
+
<img src="https://raw.githubusercontent.com/aetperf/edsger/release/docs/source/assets/dijkstra_benchmark_comparison.png" alt="Dijkstra Performance Comparison" width="700">
|
105
105
|
|
106
|
-
*Benchmark performed on Intel i9-12900H laptop.*
|
106
|
+
*Benchmark performed on Intel i9-12900H Linux laptop.*
|
107
107
|
|
108
108
|
## Contributing
|
109
109
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|

|
3
3
|
[](https://codecov.io/gh/aetperf/edsger)
|
4
|
-
[](https://pypi.org/project/edsger/)
|
4
|
+
[](https://pypi.org/project/edsger/)
|
5
5
|
[](https://pepy.tech/project/edsger)
|
6
6
|
[](https://pypi.org/project/edsger/)
|
7
7
|
[](https://github.com/psf/black)
|
@@ -34,14 +34,14 @@ edges = pd.DataFrame({
|
|
34
34
|
edges
|
35
35
|
```
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
| | tail | head | weight |
|
38
|
+
|---:|-------:|-------:|---------:|
|
39
|
+
| 0 | 0 | 1 | 1.0 |
|
40
|
+
| 1 | 0 | 2 | 4.0 |
|
41
|
+
| 2 | 1 | 2 | 2.0 |
|
42
|
+
| 3 | 2 | 3 | 1.5 |
|
43
|
+
| 4 | 2 | 4 | 3.0 |
|
44
|
+
| 5 | 3 | 4 | 1.0 |
|
45
45
|
|
46
46
|
```python
|
47
47
|
# Initialize the Dijkstra object
|
@@ -60,9 +60,9 @@ We get the shortest paths from the source node 0 to all other nodes in the graph
|
|
60
60
|
|
61
61
|
Edsger is designed to be **dataframe-friendly**, providing seamless integration with pandas workflows for graph algorithms. Also it is rather efficient. Our benchmarks on the USA road network (23.9M vertices, 57.7M edges) demonstrate nice performance:
|
62
62
|
|
63
|
-
<img src="docs/source/assets/dijkstra_benchmark_comparison.png" alt="Dijkstra Performance Comparison" width="700">
|
63
|
+
<img src="https://raw.githubusercontent.com/aetperf/edsger/release/docs/source/assets/dijkstra_benchmark_comparison.png" alt="Dijkstra Performance Comparison" width="700">
|
64
64
|
|
65
|
-
*Benchmark performed on Intel i9-12900H laptop.*
|
65
|
+
*Benchmark performed on Intel i9-12900H Linux laptop.*
|
66
66
|
|
67
67
|
## Contributing
|
68
68
|
|
@@ -14,7 +14,7 @@ Edsger is designed to be **dataframe-friendly**, providing seamless integration
|
|
14
14
|
|
15
15
|
<img src="assets/dijkstra_benchmark_comparison.png" alt="Dijkstra Performance Comparison" width="700">
|
16
16
|
|
17
|
-
*Benchmark performed on Intel i9-12900H laptop.*
|
17
|
+
*Benchmark performed on Intel i9-12900H Linux laptop.*
|
18
18
|
|
19
19
|
### Pandas Integration Made Simple
|
20
20
|
|
@@ -32,7 +32,9 @@ edges = pd.DataFrame({
|
|
32
32
|
# No conversion needed - use directly!
|
33
33
|
dijkstra = Dijkstra(edges, orientation="out")
|
34
34
|
distances = dijkstra.run(vertex_idx=0)
|
35
|
+
distances
|
35
36
|
```
|
37
|
+
array([0., 1., 2., 3.])
|
36
38
|
|
37
39
|
## Key Features
|
38
40
|
|
@@ -22,7 +22,7 @@ edges = pd.DataFrame({
|
|
22
22
|
'head': [1, 2, 2, 3],
|
23
23
|
'weight': [1.0, 4.0, 2.0, 1.0]
|
24
24
|
})
|
25
|
-
|
25
|
+
edges
|
26
26
|
```
|
27
27
|
|
28
28
|
| | tail | head | weight |
|
@@ -33,6 +33,8 @@ edsges
|
|
33
33
|
| 3 | 2 | 3 | 1 |
|
34
34
|
|
35
35
|
|
36
|
+
Note that it is also possible to use a graph with different column names for the tail, head and weight values, but we need then to specify the name mapping, as described in the following.
|
37
|
+
|
36
38
|
## Dijkstra's Algorithm
|
37
39
|
|
38
40
|
To use Dijkstra's algorithm, you can import the `Dijkstra` class from the `path` module. The function takes a graph and a source node as input, and returns the shortest path from the source node to all other nodes in the graph.
|
@@ -49,14 +51,14 @@ edges = pd.DataFrame({
|
|
49
51
|
edges
|
50
52
|
```
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
| | tail | head | weight |
|
55
|
+
|---:|-------:|-------:|---------:|
|
56
|
+
| 0 | 0 | 1 | 1.0 |
|
57
|
+
| 1 | 0 | 2 | 4.0 |
|
58
|
+
| 2 | 1 | 2 | 2.0 |
|
59
|
+
| 3 | 2 | 3 | 1.5 |
|
60
|
+
| 4 | 2 | 4 | 3.0 |
|
61
|
+
| 5 | 3 | 4 | 1.0 |
|
60
62
|
|
61
63
|
|
62
64
|
```python
|
@@ -72,7 +74,7 @@ print("Shortest paths:", shortest_paths)
|
|
72
74
|
|
73
75
|
We get the shortest paths from the source node 0 to all other nodes in the graph. The output is an array with the shortest path length to each node. A path length is the sum of the weights of the edges in the path.
|
74
76
|
|
75
|
-
|
77
|
+
The column names can be specified using the `tail`, `head` and `weight` arguments:
|
76
78
|
|
77
79
|
```python
|
78
80
|
other_edges = pd.DataFrame({
|
@@ -169,11 +171,116 @@ shortest_paths[-5:]
|
|
169
171
|
|
170
172
|
array([0. , 1. , 3. , 4.5, 5.5])
|
171
173
|
|
174
|
+
### Early Termination
|
175
|
+
|
176
|
+
Early termination is a performance optimization feature that allows Dijkstra's algorithm to stop computing once specific target nodes (termination nodes) have been reached. This can significantly reduce computation time when you only need shortest paths to a subset of vertices in the graph.
|
177
|
+
|
178
|
+
When using early termination, the algorithm will:
|
179
|
+
1. Stop as soon as all specified termination nodes have been visited
|
180
|
+
2. Return **only** the path lengths to the termination nodes (not all vertices)
|
181
|
+
3. Return results in the same order as the termination nodes were specified
|
182
|
+
|
183
|
+
#### Basic Early Termination Example
|
184
|
+
|
185
|
+
```python
|
186
|
+
import pandas as pd
|
187
|
+
from edsger.path import Dijkstra
|
188
|
+
|
189
|
+
# Create a sample graph
|
190
|
+
edges = pd.DataFrame({
|
191
|
+
"tail": [0, 0, 0, 1, 1, 2, 2, 3, 3, 4],
|
192
|
+
"head": [1, 2, 3, 2, 4, 3, 5, 4, 5, 5],
|
193
|
+
"weight": [1.0, 4.0, 2.0, 1.0, 3.0, 1.0, 2.0, 1.0, 1.0, 1.0],
|
194
|
+
})
|
195
|
+
```
|
196
|
+
|
197
|
+
**Without early termination** (computes paths to all vertices):
|
198
|
+
```python
|
199
|
+
dijkstra = Dijkstra(edges, orientation="out")
|
200
|
+
distances = dijkstra.run(vertex_idx=0)
|
201
|
+
print("All distances:", distances)
|
202
|
+
```
|
203
|
+
All distances: [0. 1. 2. 2. 3. 3.]
|
204
|
+
|
205
|
+
**With early termination** (computes paths only to specified nodes):
|
206
|
+
```python
|
207
|
+
# Only compute paths to nodes 3 and 5
|
208
|
+
termination_nodes = [3, 5]
|
209
|
+
distances = dijkstra.run(vertex_idx=0, termination_nodes=termination_nodes)
|
210
|
+
print("Distances to termination nodes:", distances)
|
211
|
+
print("Shape of result:", distances.shape)
|
212
|
+
```
|
213
|
+
Distances to termination nodes: [2. 3.]
|
214
|
+
Shape of result: (2,)
|
215
|
+
|
216
|
+
Notice that:
|
217
|
+
- The result array has length 2 (same as number of termination nodes)
|
218
|
+
- `distances[0] = 2.0` is the shortest path length from vertex 0 to vertex 3
|
219
|
+
- `distances[1] = 3.0` is the shortest path length from vertex 0 to vertex 5
|
220
|
+
|
221
|
+
#### Early Termination with Path Tracking
|
222
|
+
|
223
|
+
Early termination also works with path tracking enabled:
|
224
|
+
|
225
|
+
```python
|
226
|
+
dijkstra = Dijkstra(edges, orientation="out")
|
227
|
+
distances = dijkstra.run(vertex_idx=0, termination_nodes=[3, 5], path_tracking=True)
|
228
|
+
print("Distances:", distances)
|
229
|
+
|
230
|
+
# Get paths to termination nodes
|
231
|
+
path_to_3 = dijkstra.get_path(vertex_idx=3)
|
232
|
+
path_to_5 = dijkstra.get_path(vertex_idx=5)
|
233
|
+
print("Path to vertex 3:", path_to_3)
|
234
|
+
print("Path to vertex 5:", path_to_5)
|
235
|
+
```
|
236
|
+
Distances: [2. 3.]
|
237
|
+
Path to vertex 3: [3 2 1 0]
|
238
|
+
Path to vertex 5: [5 3 2 1 0]
|
239
|
+
|
240
|
+
#### Important Notes
|
241
|
+
|
242
|
+
1. **Return Array Size**: With early termination, the returned array size equals the number of termination nodes, not the total number of vertices in the graph.
|
243
|
+
|
244
|
+
2. **Order Preservation**: Results are returned in the same order as the termination nodes are specified:
|
245
|
+
```python
|
246
|
+
# Termination nodes [3, 5] → results [distance_to_3, distance_to_5]
|
247
|
+
# Termination nodes [5, 3] → results [distance_to_5, distance_to_3]
|
248
|
+
```
|
249
|
+
|
250
|
+
3. **Orientation Support**: Early termination works with both orientations:
|
251
|
+
```python
|
252
|
+
# Single-source shortest paths (from source to termination nodes)
|
253
|
+
dijkstra = Dijkstra(edges, orientation="out")
|
254
|
+
distances = dijkstra.run(vertex_idx=0, termination_nodes=[3, 5])
|
255
|
+
|
256
|
+
# Single-target shortest paths (from termination nodes to target)
|
257
|
+
dijkstra = Dijkstra(edges, orientation="in")
|
258
|
+
distances = dijkstra.run(vertex_idx=5, termination_nodes=[0, 2])
|
259
|
+
```
|
260
|
+
|
261
|
+
4. **Unreachable Nodes**: If a termination node is unreachable, its distance will be infinity:
|
262
|
+
```python
|
263
|
+
# If node 10 is unreachable from node 0
|
264
|
+
distances = dijkstra.run(vertex_idx=0, termination_nodes=[3, 10])
|
265
|
+
# Result: [2.0, inf]
|
266
|
+
```
|
172
267
|
|
173
268
|
### Run Method Options
|
174
269
|
|
175
270
|
The `run` method can take the following arguments besides the source/target vertex index:
|
176
271
|
|
272
|
+
- `termination_nodes` : list or array-like, optional (default=None)
|
273
|
+
|
274
|
+
A list or array of vertex indices where the algorithm should stop early. When specified, the algorithm will terminate as soon as all termination nodes have been reached, and will return only the path lengths to these nodes in the same order they were specified. This can provide significant performance improvements when you only need paths to a subset of vertices.
|
275
|
+
|
276
|
+
```python
|
277
|
+
dijkstra = Dijkstra(edges)
|
278
|
+
# Get distances only to nodes 2 and 4
|
279
|
+
distances = dijkstra.run(vertex_idx=0, termination_nodes=[2, 4])
|
280
|
+
print("Distances to nodes 2 and 4:", distances)
|
281
|
+
```
|
282
|
+
Distances to nodes 2 and 4: [1.5 3.5]
|
283
|
+
|
177
284
|
- `path_tracking` : bool, optional (default=False)
|
178
285
|
|
179
286
|
Whether to track the shortest path(s) from/to the source/target vertex to all other vertices in the graph.
|
@@ -194,6 +301,8 @@ dijkstra.get_path(vertex_idx=0)
|
|
194
301
|
|
195
302
|
The path is returned as an array of vertex indices. This is an ordered list of vertices from the source to the target vertex if `orientation` is `'in'`, and from the target to the source vertex if `orientation` is `'out'`. Both the source and target vertices are included in the path.
|
196
303
|
|
304
|
+
**Note**: When using `termination_nodes` with `path_tracking=True`, you can still retrieve paths to any vertex that was reached during the computation using `get_path()`, even if it wasn't in the termination nodes list.
|
305
|
+
|
197
306
|
- `return_inf` : bool, optional (default=True)
|
198
307
|
|
199
308
|
Whether to return path lengths as infinity (np.inf) when no path exists.
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.3"
|