edsger 0.0.13__tar.gz → 0.0.15__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 (58) hide show
  1. {edsger-0.0.13 → edsger-0.0.15}/.github/workflows/publish.yml +2 -4
  2. edsger-0.0.15/.github/workflows/tests.yml +29 -0
  3. edsger-0.0.15/PKG-INFO +277 -0
  4. edsger-0.0.15/README.md +243 -0
  5. {edsger-0.0.13 → edsger-0.0.15}/docs/source/conf.py +2 -3
  6. {edsger-0.0.13 → edsger-0.0.15}/docs/source/edsger.rst +3 -3
  7. edsger-0.0.15/docs/source/index.rst +22 -0
  8. edsger-0.0.15/docs/source/installation.rst +90 -0
  9. edsger-0.0.15/docs/source/introduction.rst +7 -0
  10. {edsger-0.0.13 → edsger-0.0.15}/requirements-dev.txt +4 -1
  11. {edsger-0.0.13 → edsger-0.0.15}/scripts/dijkstra_dimacs.py +5 -7
  12. edsger-0.0.15/src/edsger/_version.py +1 -0
  13. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/commons.c +1607 -983
  14. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/commons.pxd +7 -6
  15. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/commons.pyx +6 -5
  16. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/dijkstra.c +2692 -2062
  17. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/dijkstra.pyx +7 -7
  18. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/networks.py +134 -2
  19. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/path.py +246 -100
  20. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/path_tracking.c +1803 -1167
  21. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/path_tracking.pyx +18 -9
  22. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/pq_4ary_dec_0b.c +2536 -1906
  23. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/pq_4ary_dec_0b.pxd +6 -5
  24. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/pq_4ary_dec_0b.pyx +6 -6
  25. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/spiess_florian.c +2854 -2223
  26. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/spiess_florian.pyx +7 -7
  27. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/star.c +1991 -1361
  28. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/star.pyx +7 -1
  29. edsger-0.0.15/src/edsger/utils.py +63 -0
  30. edsger-0.0.15/src/edsger.egg-info/PKG-INFO +277 -0
  31. {edsger-0.0.13 → edsger-0.0.15}/src/edsger.egg-info/SOURCES.txt +3 -0
  32. {edsger-0.0.13 → edsger-0.0.15}/src/edsger.egg-info/requires.txt +0 -5
  33. {edsger-0.0.13 → edsger-0.0.15}/tests/test_dijkstra.py +2 -1
  34. {edsger-0.0.13 → edsger-0.0.15}/tests/test_path.py +6 -8
  35. {edsger-0.0.13 → edsger-0.0.15}/tests/test_path_tracking.py +0 -1
  36. edsger-0.0.13/PKG-INFO +0 -48
  37. edsger-0.0.13/README.md +0 -10
  38. edsger-0.0.13/docs/source/index.rst +0 -27
  39. edsger-0.0.13/src/edsger/_version.py +0 -1
  40. edsger-0.0.13/src/edsger/utils.py +0 -17
  41. edsger-0.0.13/src/edsger.egg-info/PKG-INFO +0 -48
  42. {edsger-0.0.13 → edsger-0.0.15}/.gitignore +0 -0
  43. {edsger-0.0.13 → edsger-0.0.15}/AUTHORS.rst +0 -0
  44. {edsger-0.0.13 → edsger-0.0.15}/CHANGELOG.rst +0 -0
  45. {edsger-0.0.13 → edsger-0.0.15}/CONTRIBUTING.rst +0 -0
  46. {edsger-0.0.13 → edsger-0.0.15}/LICENSE +0 -0
  47. {edsger-0.0.13 → edsger-0.0.15}/MANIFEST.in +0 -0
  48. {edsger-0.0.13 → edsger-0.0.15}/docs/Makefile +0 -0
  49. {edsger-0.0.13 → edsger-0.0.15}/pyproject.toml +0 -0
  50. {edsger-0.0.13 → edsger-0.0.15}/requirements.txt +0 -0
  51. {edsger-0.0.13 → edsger-0.0.15}/setup.cfg +0 -0
  52. {edsger-0.0.13 → edsger-0.0.15}/setup.py +0 -0
  53. {edsger-0.0.13 → edsger-0.0.15}/src/edsger/__init__.py +0 -0
  54. {edsger-0.0.13 → edsger-0.0.15}/src/edsger.egg-info/dependency_links.txt +0 -0
  55. {edsger-0.0.13 → edsger-0.0.15}/src/edsger.egg-info/not-zip-safe +0 -0
  56. {edsger-0.0.13 → edsger-0.0.15}/src/edsger.egg-info/top_level.txt +0 -0
  57. {edsger-0.0.13 → edsger-0.0.15}/tests/test_pq_4ary_dec_0b.py +0 -0
  58. {edsger-0.0.13 → edsger-0.0.15}/tests/test_spiess_florian.py +0 -0
@@ -2,8 +2,6 @@ name: ci-publish # Publish Python distribution to PyPI
2
2
 
3
3
  on:
4
4
  push:
5
- branches:
6
- - push
7
5
  tags:
8
6
  - 'v[0-9]+.[0-9]+.[0-9]+'
9
7
  jobs:
@@ -54,7 +52,7 @@ jobs:
54
52
  - name: Run build
55
53
  run: python -m build --sdist
56
54
 
57
- - uses: actions/upload-artifact@v3
55
+ - uses: actions/upload-artifact@v4
58
56
  with:
59
57
  path: ./dist/*.tar.gz
60
58
 
@@ -95,7 +93,7 @@ jobs:
95
93
 
96
94
  steps:
97
95
  - name: Download all the dists
98
- uses: actions/download-artifact@v3
96
+ uses: actions/download-artifact@v4
99
97
  with:
100
98
  name: artifact
101
99
  path: ./dist/
@@ -0,0 +1,29 @@
1
+ name: ci-test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - release
7
+
8
+ jobs:
9
+ test:
10
+ strategy:
11
+ matrix:
12
+ os: [ os: [ubuntu-22.04, windows-2022, macos-14]
13
+ ]
14
+ python-version: ["3.11"]
15
+ runs-on: ${{ matrix.os }}
16
+ steps:
17
+ - uses: actions/checkout@v3
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: |
29
+ python -m pytest tests
edsger-0.0.15/PKG-INFO ADDED
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.2
2
+ Name: edsger
3
+ Version: 0.0.15
4
+ Summary: Graph algorithms in Cython.
5
+ Author-email: François Pacull <francois.pacull@architecture-performance.fr>
6
+ Maintainer-email: François Pacull <francois.pacull@architecture-performance.fr>
7
+ License: MIT License
8
+ Project-URL: Repository, https://github.com/aetperf/Edsger
9
+ Keywords: python,graph,shortest path,Dijkstra
10
+ Platform: any
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ License-File: AUTHORS.rst
20
+ Requires-Dist: setuptools
21
+ Requires-Dist: setuptools_scm
22
+ Requires-Dist: numpy>=1.26
23
+ Requires-Dist: Cython>=3
24
+ Requires-Dist: pandas
25
+ Provides-Extra: dev
26
+ Requires-Dist: black; extra == "dev"
27
+ Provides-Extra: test
28
+ Requires-Dist: pytest; extra == "test"
29
+ Requires-Dist: scipy<1.11; extra == "test"
30
+ Provides-Extra: doc
31
+ Requires-Dist: sphinx; extra == "doc"
32
+ Requires-Dist: sphinx_design; extra == "doc"
33
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
34
+
35
+
36
+ ![Tests Status](https://github.com/aetperf/edsger/actions/workflows/tests.yml/badge.svg?branch=release)
37
+ ![PyPI](https://img.shields.io/pypi/v/edsger)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+
40
+ # Edsger
41
+
42
+ *Graph algorithms in Cython*
43
+
44
+ Welcome to our Python library for graph algorithms. So far, the library only includes Dijkstra's algorithm but we should add a range of common path algorithms later. It is also open-source and easy to integrate with other Python libraries. To get started, simply install the library using pip, and import it into your Python project.
45
+
46
+ ## Installation
47
+
48
+ ### Install from PyPI
49
+
50
+ To install Edsger, simply use pip:
51
+
52
+ ```sh
53
+ pip install edsger
54
+ ```
55
+
56
+ ### Install from source
57
+
58
+ If you want to install from source, you can clone the repository and install it using pip:
59
+
60
+ ```sh
61
+ git clone git@github.com:aetperf/Edsger.git
62
+ cd Edsger
63
+ pip install .
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ ### Dijkstra's algorithm
69
+
70
+ 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.
71
+
72
+ ```python
73
+ import pandas as pd
74
+
75
+ from edsger.path import Dijkstra
76
+
77
+ # Create a DataFrame with the edges of the graph
78
+ edges = pd.DataFrame({
79
+ 'tail': [0, 0, 1, 2, 2, 3],
80
+ 'head': [1, 2, 2, 3, 4, 4],
81
+ 'weight': [1, 4, 2, 1, 3, 1]
82
+ })
83
+ edges
84
+ ```
85
+
86
+ | | tail | head | weight |
87
+ |---:|-------:|-------:|---------:|
88
+ | 0 | 0 | 1 | 1 |
89
+ | 1 | 0 | 2 | 4 |
90
+ | 2 | 1 | 2 | 2 |
91
+ | 3 | 2 | 3 | 1 |
92
+ | 4 | 2 | 4 | 3 |
93
+ | 5 | 3 | 4 | 1 |
94
+
95
+
96
+ ```python
97
+ # Initialize the Dijkstra object
98
+ dijkstra = Dijkstra(edges)
99
+
100
+ # Run the algorithm from a source vertex
101
+ shortest_paths = dijkstra.run(vertex_idx=0)
102
+ print("Shortest paths:", shortest_paths)
103
+ ```
104
+
105
+ Shortest paths: [0. 1. 3. 4. 5.]
106
+
107
+ 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.
108
+
109
+ It is also possible to use a graph with different column names for the tail, head and weight values. The column names can be specified using the `tail`, `head` and `weight` arguments:
110
+
111
+ ```python
112
+ other_edges = pd.DataFrame({
113
+ 'from': [0, 0, 1, 2, 2, 3],
114
+ 'to': [1, 2, 2, 3, 4, 4],
115
+ 'travel_time': [1, 4, 2, 1, 3, 1]
116
+ })
117
+ other_dijkstra = Dijkstra(edges, tail='from', head='to', weight='travel_time')
118
+ ```
119
+
120
+ #### Orientation
121
+
122
+ The `orientation` argument (a string with a default value of `'out'`) specifies the orientation of the algorithm. It can be either `'out'` for single source shortest paths or `'in'` for single target shortest path.
123
+
124
+ ```python
125
+ dijkstra = Dijkstra(edges, orientation='in')
126
+
127
+ # Run the algorithm to a target vertex
128
+ shortest_paths = dijkstra.run(vertex_idx=0)
129
+ print("Shortest paths:", shortest_paths)
130
+ ```
131
+
132
+ Shortest paths: [ 0. inf inf inf inf]
133
+
134
+ #### Run multiple times
135
+
136
+ Once the Dijkstra is instanciated with a given graph and orientation, the `run` method can be called multiple times with different source vertices.
137
+
138
+ ```python
139
+ # Run the algorithm to another target vertex
140
+ shortest_paths = dijkstra.run(vertex_idx=4)
141
+ print("Shortest paths:", shortest_paths)
142
+ ```
143
+
144
+ Shortest paths: [5. 4. 2. 1. 0.]
145
+
146
+ #### Check edges
147
+
148
+ The `check_edges` argument (a boolean with a default value of `False`) validates the given graph. When set to `True`, it ensures the DataFrame is well-formed by:
149
+
150
+ - Checking for the presence of required columns for edge tail, head and weigh values
151
+ - Verifying that the data types are correct (integer for tail and head, integer or float for weight)
152
+ - Ensuring there are no missing or invalid values (e.g. negative weights)
153
+
154
+ If any of these checks fail, an appropriate error is raised.
155
+
156
+ ```python
157
+ invalid_edges = pd.DataFrame({
158
+ 'tail': [0, 0, 1, 2, 2, 3],
159
+ 'head': [1, 2, 2, 3, 4, 4],
160
+ 'weight': [1, 4, 2, -1, 3, 1]
161
+ })
162
+ dijkstra = Dijkstra(invalid_edges, check_edges=True)
163
+ ```
164
+
165
+ ValueError: edges['weight'] should be nonnegative
166
+
167
+ #### Permute
168
+
169
+ Finally, the `permute` argument (boolean with a default value of `False`) allows to permute the IDs of the nodes. If set to `True`, the node IDs will be reindexed to start from 0 and be contiguous for the inner computations, and the output will be reindexed to the original IDs, loading the same result as if the IDs were not permuted. The permutation may save memory and computation time for large graphs, for example if a significant ratio of the nodes are not actually used in the graph.
170
+
171
+ ```python
172
+ SHIFT = 1000
173
+
174
+ shifted_edges = pd.DataFrame({
175
+ 'tail': [0, 0, 1, 2, 2, 3],
176
+ 'head': [1, 2, 2, 3, 4, 4],
177
+ 'weight': [1, 4, 2, 1, 3, 1]
178
+ })
179
+ shifted_edges["tail"] += SHIFT
180
+ shifted_edges["head"] += SHIFT
181
+ shifted_edges.head(3)
182
+ ```
183
+
184
+ | | tail | head | weight |
185
+ |---:|-------:|-------:|---------:|
186
+ | 0 | 1000 | 1001 | 1 |
187
+ | 1 | 1000 | 1002 | 4 |
188
+ | 2 | 1001 | 1002 | 2 |
189
+
190
+
191
+
192
+ ```python
193
+ dijkstra = Dijkstra(shifted_edges, permute=True)
194
+ shortest_paths = dijkstra.run(vertex_idx=0 + SHIFT)
195
+ print("Shortest paths:", shortest_paths)
196
+ ```
197
+
198
+ Shortest paths: [inf inf inf ... 3. 4. 5.]
199
+
200
+ ```python
201
+ shortest_paths[-5:]
202
+ ```
203
+
204
+ array([0., 1., 3., 4., 5.])
205
+
206
+ #### Run method options
207
+
208
+ The `run` method can take the following arguments besides the source/target vertex index:
209
+
210
+ - `path_tracking` : bool, optional (default=False)
211
+
212
+ Whether to track the shortest path(s) from/to the source/target vertex to all other vertices in the graph.
213
+
214
+ ```python
215
+ dijkstra = Dijkstra(edges)
216
+ shortest_paths = dijkstra.run(vertex_idx=0, path_tracking=True)
217
+ dijkstra.get_path(vertex_idx=4)
218
+ ```
219
+
220
+ array([4, 3, 2, 1, 0], dtype=uint32)
221
+
222
+ ```python
223
+ dijkstra.get_path(vertex_idx=0)
224
+ ```
225
+
226
+ array([0], dtype=uint32)
227
+
228
+ 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.
229
+
230
+ - `return_inf` : bool, optional (default=True)
231
+
232
+ Whether to return path lengths as infinity (np.inf) when no path exists.
233
+
234
+ ```python
235
+ dijkstra = Dijkstra(edges, orientation='in')
236
+ shortest_paths = dijkstra.run(vertex_idx=0, return_inf=False)
237
+ shortest_paths
238
+ ```
239
+
240
+ array([0.00000000e+000, 1.79769313e+308, 1.79769313e+308, 1.79769313e+308,
241
+ 1.79769313e+308])
242
+
243
+ The value 1.79769313e+308 actually used in the code is the largest number that can be represented in the floating point format (`np.float64`).
244
+
245
+ - `return_series` : bool, optional (default=False)
246
+
247
+ Instead of returning a NumPy array, the `run` method may return a Pandas Series object with the path lengths as values and the vertex indices as the index.
248
+
249
+ ```python
250
+ shortest_paths = dijkstra.run(vertex_idx=4, return_series=True)
251
+ shortest_paths
252
+ ```
253
+
254
+ | vertex_idx | path_length |
255
+ |-------------:|--------------:|
256
+ | 0 | 5 |
257
+ | 1 | 4 |
258
+ | 2 | 2 |
259
+ | 3 | 1 |
260
+ | 4 | 0 |
261
+
262
+
263
+ - `heap_length_ratio` : float, optional (default=1.0)
264
+
265
+ This is an experimental parameter that controls the size of the heap used in the algorithm. The heap is a static array that is used to store the vertices that may be visited next. A value of 1.0 means that the heap is the same size as the number of vertices, so there is no risk of overflow. Be aware that there is no guarantee that the algorithm will work with a heap length ratio smaller that 1. The lowest ratio that works for a given graph depends on the graph structure and the source vertex. For a rather sparse graph, a small ratio may work, but for a dense graph, a ratio of 1.0 is required.
266
+
267
+ ## Contributing
268
+
269
+ We welcome contributions to the Edsger library. If you have any suggestions, bug reports, or feature requests, please open an issue on our [GitHub repository](https://github.com/aetperf/Edsger).
270
+
271
+ ### License
272
+
273
+ Edsger is licensed under the MIT License. See the LICENSE file for more details.
274
+
275
+ ### Contact
276
+
277
+ For any questions or inquiries, please contact François Pacull at [francois.pacull@architecture-performance.fr](mailto:francois.pacull@architecture-performance.fr).
@@ -0,0 +1,243 @@
1
+
2
+ ![Tests Status](https://github.com/aetperf/edsger/actions/workflows/tests.yml/badge.svg?branch=release)
3
+ ![PyPI](https://img.shields.io/pypi/v/edsger)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ # Edsger
7
+
8
+ *Graph algorithms in Cython*
9
+
10
+ Welcome to our Python library for graph algorithms. So far, the library only includes Dijkstra's algorithm but we should add a range of common path algorithms later. It is also open-source and easy to integrate with other Python libraries. To get started, simply install the library using pip, and import it into your Python project.
11
+
12
+ ## Installation
13
+
14
+ ### Install from PyPI
15
+
16
+ To install Edsger, simply use pip:
17
+
18
+ ```sh
19
+ pip install edsger
20
+ ```
21
+
22
+ ### Install from source
23
+
24
+ If you want to install from source, you can clone the repository and install it using pip:
25
+
26
+ ```sh
27
+ git clone git@github.com:aetperf/Edsger.git
28
+ cd Edsger
29
+ pip install .
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ### Dijkstra's algorithm
35
+
36
+ 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.
37
+
38
+ ```python
39
+ import pandas as pd
40
+
41
+ from edsger.path import Dijkstra
42
+
43
+ # Create a DataFrame with the edges of the graph
44
+ edges = pd.DataFrame({
45
+ 'tail': [0, 0, 1, 2, 2, 3],
46
+ 'head': [1, 2, 2, 3, 4, 4],
47
+ 'weight': [1, 4, 2, 1, 3, 1]
48
+ })
49
+ edges
50
+ ```
51
+
52
+ | | tail | head | weight |
53
+ |---:|-------:|-------:|---------:|
54
+ | 0 | 0 | 1 | 1 |
55
+ | 1 | 0 | 2 | 4 |
56
+ | 2 | 1 | 2 | 2 |
57
+ | 3 | 2 | 3 | 1 |
58
+ | 4 | 2 | 4 | 3 |
59
+ | 5 | 3 | 4 | 1 |
60
+
61
+
62
+ ```python
63
+ # Initialize the Dijkstra object
64
+ dijkstra = Dijkstra(edges)
65
+
66
+ # Run the algorithm from a source vertex
67
+ shortest_paths = dijkstra.run(vertex_idx=0)
68
+ print("Shortest paths:", shortest_paths)
69
+ ```
70
+
71
+ Shortest paths: [0. 1. 3. 4. 5.]
72
+
73
+ 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
+
75
+ It is also possible to use a graph with different column names for the tail, head and weight values. The column names can be specified using the `tail`, `head` and `weight` arguments:
76
+
77
+ ```python
78
+ other_edges = pd.DataFrame({
79
+ 'from': [0, 0, 1, 2, 2, 3],
80
+ 'to': [1, 2, 2, 3, 4, 4],
81
+ 'travel_time': [1, 4, 2, 1, 3, 1]
82
+ })
83
+ other_dijkstra = Dijkstra(edges, tail='from', head='to', weight='travel_time')
84
+ ```
85
+
86
+ #### Orientation
87
+
88
+ The `orientation` argument (a string with a default value of `'out'`) specifies the orientation of the algorithm. It can be either `'out'` for single source shortest paths or `'in'` for single target shortest path.
89
+
90
+ ```python
91
+ dijkstra = Dijkstra(edges, orientation='in')
92
+
93
+ # Run the algorithm to a target vertex
94
+ shortest_paths = dijkstra.run(vertex_idx=0)
95
+ print("Shortest paths:", shortest_paths)
96
+ ```
97
+
98
+ Shortest paths: [ 0. inf inf inf inf]
99
+
100
+ #### Run multiple times
101
+
102
+ Once the Dijkstra is instanciated with a given graph and orientation, the `run` method can be called multiple times with different source vertices.
103
+
104
+ ```python
105
+ # Run the algorithm to another target vertex
106
+ shortest_paths = dijkstra.run(vertex_idx=4)
107
+ print("Shortest paths:", shortest_paths)
108
+ ```
109
+
110
+ Shortest paths: [5. 4. 2. 1. 0.]
111
+
112
+ #### Check edges
113
+
114
+ The `check_edges` argument (a boolean with a default value of `False`) validates the given graph. When set to `True`, it ensures the DataFrame is well-formed by:
115
+
116
+ - Checking for the presence of required columns for edge tail, head and weigh values
117
+ - Verifying that the data types are correct (integer for tail and head, integer or float for weight)
118
+ - Ensuring there are no missing or invalid values (e.g. negative weights)
119
+
120
+ If any of these checks fail, an appropriate error is raised.
121
+
122
+ ```python
123
+ invalid_edges = pd.DataFrame({
124
+ 'tail': [0, 0, 1, 2, 2, 3],
125
+ 'head': [1, 2, 2, 3, 4, 4],
126
+ 'weight': [1, 4, 2, -1, 3, 1]
127
+ })
128
+ dijkstra = Dijkstra(invalid_edges, check_edges=True)
129
+ ```
130
+
131
+ ValueError: edges['weight'] should be nonnegative
132
+
133
+ #### Permute
134
+
135
+ Finally, the `permute` argument (boolean with a default value of `False`) allows to permute the IDs of the nodes. If set to `True`, the node IDs will be reindexed to start from 0 and be contiguous for the inner computations, and the output will be reindexed to the original IDs, loading the same result as if the IDs were not permuted. The permutation may save memory and computation time for large graphs, for example if a significant ratio of the nodes are not actually used in the graph.
136
+
137
+ ```python
138
+ SHIFT = 1000
139
+
140
+ shifted_edges = pd.DataFrame({
141
+ 'tail': [0, 0, 1, 2, 2, 3],
142
+ 'head': [1, 2, 2, 3, 4, 4],
143
+ 'weight': [1, 4, 2, 1, 3, 1]
144
+ })
145
+ shifted_edges["tail"] += SHIFT
146
+ shifted_edges["head"] += SHIFT
147
+ shifted_edges.head(3)
148
+ ```
149
+
150
+ | | tail | head | weight |
151
+ |---:|-------:|-------:|---------:|
152
+ | 0 | 1000 | 1001 | 1 |
153
+ | 1 | 1000 | 1002 | 4 |
154
+ | 2 | 1001 | 1002 | 2 |
155
+
156
+
157
+
158
+ ```python
159
+ dijkstra = Dijkstra(shifted_edges, permute=True)
160
+ shortest_paths = dijkstra.run(vertex_idx=0 + SHIFT)
161
+ print("Shortest paths:", shortest_paths)
162
+ ```
163
+
164
+ Shortest paths: [inf inf inf ... 3. 4. 5.]
165
+
166
+ ```python
167
+ shortest_paths[-5:]
168
+ ```
169
+
170
+ array([0., 1., 3., 4., 5.])
171
+
172
+ #### Run method options
173
+
174
+ The `run` method can take the following arguments besides the source/target vertex index:
175
+
176
+ - `path_tracking` : bool, optional (default=False)
177
+
178
+ Whether to track the shortest path(s) from/to the source/target vertex to all other vertices in the graph.
179
+
180
+ ```python
181
+ dijkstra = Dijkstra(edges)
182
+ shortest_paths = dijkstra.run(vertex_idx=0, path_tracking=True)
183
+ dijkstra.get_path(vertex_idx=4)
184
+ ```
185
+
186
+ array([4, 3, 2, 1, 0], dtype=uint32)
187
+
188
+ ```python
189
+ dijkstra.get_path(vertex_idx=0)
190
+ ```
191
+
192
+ array([0], dtype=uint32)
193
+
194
+ 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.
195
+
196
+ - `return_inf` : bool, optional (default=True)
197
+
198
+ Whether to return path lengths as infinity (np.inf) when no path exists.
199
+
200
+ ```python
201
+ dijkstra = Dijkstra(edges, orientation='in')
202
+ shortest_paths = dijkstra.run(vertex_idx=0, return_inf=False)
203
+ shortest_paths
204
+ ```
205
+
206
+ array([0.00000000e+000, 1.79769313e+308, 1.79769313e+308, 1.79769313e+308,
207
+ 1.79769313e+308])
208
+
209
+ The value 1.79769313e+308 actually used in the code is the largest number that can be represented in the floating point format (`np.float64`).
210
+
211
+ - `return_series` : bool, optional (default=False)
212
+
213
+ Instead of returning a NumPy array, the `run` method may return a Pandas Series object with the path lengths as values and the vertex indices as the index.
214
+
215
+ ```python
216
+ shortest_paths = dijkstra.run(vertex_idx=4, return_series=True)
217
+ shortest_paths
218
+ ```
219
+
220
+ | vertex_idx | path_length |
221
+ |-------------:|--------------:|
222
+ | 0 | 5 |
223
+ | 1 | 4 |
224
+ | 2 | 2 |
225
+ | 3 | 1 |
226
+ | 4 | 0 |
227
+
228
+
229
+ - `heap_length_ratio` : float, optional (default=1.0)
230
+
231
+ This is an experimental parameter that controls the size of the heap used in the algorithm. The heap is a static array that is used to store the vertices that may be visited next. A value of 1.0 means that the heap is the same size as the number of vertices, so there is no risk of overflow. Be aware that there is no guarantee that the algorithm will work with a heap length ratio smaller that 1. The lowest ratio that works for a given graph depends on the graph structure and the source vertex. For a rather sparse graph, a small ratio may work, but for a dense graph, a ratio of 1.0 is required.
232
+
233
+ ## Contributing
234
+
235
+ We welcome contributions to the Edsger library. If you have any suggestions, bug reports, or feature requests, please open an issue on our [GitHub repository](https://github.com/aetperf/Edsger).
236
+
237
+ ### License
238
+
239
+ Edsger is licensed under the MIT License. See the LICENSE file for more details.
240
+
241
+ ### Contact
242
+
243
+ For any questions or inquiries, please contact François Pacull at [francois.pacull@architecture-performance.fr](mailto:francois.pacull@architecture-performance.fr).
@@ -19,7 +19,7 @@ sys.path.insert(0, os.path.abspath("../../src/edsger/"))
19
19
  # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
20
20
 
21
21
  project = "Edsger"
22
- copyright = "2023, Architecture & Performance"
22
+ copyright = "2024, Architecture & Performance"
23
23
  author = "Francois Pacull"
24
24
 
25
25
  # -- General configuration ---------------------------------------------------
@@ -31,8 +31,7 @@ exclude_patterns = ["*.pyx"]
31
31
  # -- Options for HTML output -------------------------------------------------
32
32
  # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
33
33
 
34
- html_theme = "sphinx_rtd_theme"
35
- # html_theme = "furo"
34
+ html_theme = "furo"
36
35
  html_static_path = ["_static"]
37
36
 
38
37
  # Add any Sphinx extension module names here, as strings. They can be
@@ -1,5 +1,5 @@
1
- edsger package
2
- ==============
1
+ edsger API
2
+ ==========
3
3
 
4
4
  edsger.path module
5
5
  ------------------
@@ -9,4 +9,4 @@ edsger.path module
9
9
  :undoc-members:
10
10
  :show-inheritance:
11
11
  :exclude-members:
12
- HyperpathGenerating
12
+ HyperpathGenerating
@@ -0,0 +1,22 @@
1
+ :github_url: https://github.com/aetperf/Edsger
2
+
3
+ ======
4
+ Edsger
5
+ ======
6
+
7
+ *Graph algorithms in Cython*
8
+
9
+ Welcome to our Python library for graph algorithms. So far, the library only includes Dijkstra's algorithm but we should add a range of common path algorithms later. It is also open-source and easy to integrate with other Python libraries. To get started, simply install the library using pip, and import it into your Python project.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ The latest release of Edsger can be installed from
15
+ `PyPI <https://pypi.org/project/edsger/>`_ using::
16
+
17
+ pip install edsger
18
+
19
+ You may also install directly from GitHub, using the following command. This
20
+ can be used to obtain the most recent version of Edsger::
21
+
22
+ pip install 'edsger @ git+https://github.com/aetperf/Edsger'