pgraph-python 0.6.4__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pgraph/PGraph.py +4298 -867
- pgraph/__init__.py +33 -1
- pgraph/_plot.py +70 -0
- pgraph/exporters.py +502 -0
- pgraph_python-1.0.0.dist-info/METADATA +277 -0
- pgraph_python-1.0.0.dist-info/RECORD +8 -0
- {pgraph_python-0.6.4.dist-info → pgraph_python-1.0.0.dist-info}/WHEEL +1 -1
- pgraph_python-0.6.4.dist-info/METADATA +0 -176
- pgraph_python-0.6.4.dist-info/RECORD +0 -6
- {pgraph_python-0.6.4.dist-info → pgraph_python-1.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pgraph-python
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Graphs for Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/petercorke/pgraph-python
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/petercorke/pgraph-python/issues
|
|
7
|
+
Project-URL: Documentation, https://petercorke.github.io/pgraph-python
|
|
8
|
+
Project-URL: GitHub Source, https://github.com/petercorke/pgraph-python
|
|
9
|
+
Project-URL: Changelog, https://github.com/petercorke/pgraph-python/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Coverage, https://codecov.io/gh/petercorke/pgraph-python
|
|
11
|
+
Author-email: Peter Corke <rvc@petercorke.com>
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: Laplacian matrix,a* search,adjacency matrix,directed graph,graph,optimal path,plotting,python,undirected graph
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: matplotlib
|
|
26
|
+
Requires-Dist: numpy>=2.0
|
|
27
|
+
Requires-Dist: spatialmath-python
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
32
|
+
Provides-Extra: docs
|
|
33
|
+
Requires-Dist: recommonmark; extra == 'docs'
|
|
34
|
+
Requires-Dist: sphinx; extra == 'docs'
|
|
35
|
+
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
|
|
36
|
+
Requires-Dist: sphinx-codeautolink; extra == 'docs'
|
|
37
|
+
Requires-Dist: sphinx-copybutton; extra == 'docs'
|
|
38
|
+
Requires-Dist: sphinx-pyrunblock; extra == 'docs'
|
|
39
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# PGraph: graphs for Python
|
|
43
|
+
|
|
44
|
+
<div align="center">
|
|
45
|
+
<img src="https://raw.githubusercontent.com/petercorke/pgraph-python/main/docs/figs/pgraph_logo.png" width="450" alt="pgraph logo">
|
|
46
|
+
<br>
|
|
47
|
+
<strong>Graphs for Python</strong>
|
|
48
|
+
<br><br>
|
|
49
|
+
|
|
50
|
+
[](https://pypi.org/project/pgraph-python/)
|
|
51
|
+
[](https://petercorke.github.io/pgraph-python)
|
|
52
|
+
|
|
53
|
+
<p>
|
|
54
|
+
<a href="https://github.com/petercorke/pgraph-python">GitHub</a> •
|
|
55
|
+
<a href="https://github.com/petercorke/pgraph-python/wiki">Wiki</a> •
|
|
56
|
+
<a href="https://github.com/petercorke/pgraph-python/blob/main/CHANGELOG.md">Changelog</a>
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### Status & Project Health
|
|
63
|
+
[](https://github.com/petercorke/pgraph-python/actions/workflows/ci.yml)
|
|
64
|
+
[](https://pepy.tech/projects/pgraph-python)
|
|
65
|
+

|
|
66
|
+
[](https://codecov.io/gh/petercorke/pgraph-python)
|
|
67
|
+
[](https://app.codacy.com/gh/petercorke/pgraph-python/dashboard)
|
|
68
|
+
[](https://opensource.org/licenses/MIT)
|
|
69
|
+
|
|
70
|
+
### Ecosystem & Dependencies
|
|
71
|
+
[](https://github.com/petercorke/robotics-toolbox-python)
|
|
72
|
+
[](https://qcr.github.io)
|
|
73
|
+
|
|
74
|
+
[](https://numpy.org)
|
|
75
|
+
[](https://matplotlib.org)
|
|
76
|
+
[](https://github.com/petercorke/spatialmath-python)
|
|
77
|
+
|
|
78
|
+
This pure-Python package provides classes for directed and undirected graphs: vertices
|
|
79
|
+
connected by edges, with edge costs and path planning. Self-loops and
|
|
80
|
+
parallel edges are permitted. Performance is good enough to support bundle adjustment, pose-graph SLAM and path planning over thousands of vertices.
|
|
81
|
+
|
|
82
|
+
Vertices can optionally be *embedded*: given a coordinate in a space of any
|
|
83
|
+
dimension. Edge costs are then computed from the vertex positions using a
|
|
84
|
+
distance metric (Euclidean, Manhattan, SE(2), or your own), the vertex nearest
|
|
85
|
+
a point can be found, `A*` uses the metric as its heuristic, and the graph can
|
|
86
|
+
be plotted, or exported with its layout preserved.
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
pip install pgraph-python
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This needs Python 3.9 or later. The dependencies, NumPy, Matplotlib and Spatial Maths, are installed with it.
|
|
95
|
+
|
|
96
|
+
## Examples
|
|
97
|
+
|
|
98
|
+
### A small example: routing through towns in Queensland
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from pgraph import UGraph
|
|
104
|
+
import json
|
|
105
|
+
|
|
106
|
+
# load the places and routes
|
|
107
|
+
with open('queensland.json', 'r') as f:
|
|
108
|
+
data = json.load(f)
|
|
109
|
+
|
|
110
|
+
# build the graph
|
|
111
|
+
g = UGraph()
|
|
112
|
+
for name, info in data['places'].items():
|
|
113
|
+
g.add_vertex(name=name, coord=info['utm'])
|
|
114
|
+
for route in data['routes']:
|
|
115
|
+
g.add_edge(route['start'], route['end'], cost=route['distance'])
|
|
116
|
+
|
|
117
|
+
# plan a path from Hughenden to Brisbane
|
|
118
|
+
p, length, _ = g.path_Astar('Hughenden', 'Brisbane')
|
|
119
|
+
g.plot(block=False) # plot it
|
|
120
|
+
g.highlight_path(p) # overlay the path
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The data file and the complete example are in the notebook [`examples/roads.ipynb`](https://github.com/petercorke/pgraph-python/blob/main/examples/roads.ipynb).
|
|
124
|
+
|
|
125
|
+
### A bigger example: routing through central London
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
A directed graph of the road network of central London, taken from [OpenStreetMap](https://www.openstreetmap.org/copyright), and the shortest drive between Buckingham Palace and Tower Bridge, there (solid) and back (dashed). The two routes differ in length, 5,515 m and 5,948 m, because of the one-way streets. The notebook [`examples/london.ipynb`](https://github.com/petercorke/pgraph-python/blob/main/examples/london.ipynb) builds the graph from the map data, keeps the part of it that can be driven around in, and plans with `A*`. This graph has over 4,000 vertices.
|
|
130
|
+
|
|
131
|
+
Map data © OpenStreetMap contributors, available under the [Open Database License](https://www.openstreetmap.org/copyright).
|
|
132
|
+
|
|
133
|
+
## Using pgraph
|
|
134
|
+
|
|
135
|
+
Full details are given in the [online documentation](https://petercorke.github.io/pgraph-python). For an AI assistant there is a short summary, [llms.txt](https://petercorke.github.io/pgraph-python/llms.txt), and the complete documentation as one file, [llms-full.txt](https://petercorke.github.io/pgraph-python/llms-full.txt).
|
|
136
|
+
|
|
137
|
+
### Properties and methods of the graph
|
|
138
|
+
|
|
139
|
+
Graphs belong to the class `UGraph` or `DGraph` for undirected or directed graphs respectively. The graph is essentially a container for the vertices.
|
|
140
|
+
|
|
141
|
+
- `g.add_vertex()` add a vertex
|
|
142
|
+
- `g.n` the number of vertices
|
|
143
|
+
- `g` is an iterator over vertices, can be used as `for vertex in g:`
|
|
144
|
+
- `g[i]` reference a vertex by its index or name
|
|
145
|
+
|
|
146
|
+
***
|
|
147
|
+
- `g.add_edge()` connect two vertices
|
|
148
|
+
- `g.edges()` all edges in the graph
|
|
149
|
+
- `g.plot()` plots the vertices and edges
|
|
150
|
+
- `g.nc` the number of graph components, 1 if fully connected
|
|
151
|
+
- `g.component(c)` the vertices in component number `c`, numbered from 0
|
|
152
|
+
- `g.samecomponent(v1, v2)` predicate for vertices belonging to the same component
|
|
153
|
+
|
|
154
|
+
***
|
|
155
|
+
- `g.path_BFS()` breadth-first search, the path with the fewest edges
|
|
156
|
+
- `g.path_UCS()` uniform-cost search, the cheapest path
|
|
157
|
+
- `g.path_Astar()` A* search, the cheapest path using a heuristic
|
|
158
|
+
|
|
159
|
+
***
|
|
160
|
+
- `g.closest(point)` the vertex nearest to a point
|
|
161
|
+
- `g.near(point, radius)` the vertices within a distance of a point
|
|
162
|
+
- `g.within(box)` the vertices inside a box
|
|
163
|
+
- `g.subgraph(vertices)` the part of the graph that those vertices induce, as a new graph
|
|
164
|
+
- `g.coordinates()` the vertex coordinates as a matrix, a column per vertex
|
|
165
|
+
- `g.build_kdtree()` an optional spatial index (needs scipy) that makes `closest` and `near` faster on a large graph
|
|
166
|
+
- `g.metric` the distance metric: `"L2"` (the default), `"L1"`, `"SE2"`, `SE2Metric(weight)` that weights the angle of a pose, or a function of your own
|
|
167
|
+
|
|
168
|
+
***
|
|
169
|
+
- `g.adjacency()` adjacency matrix
|
|
170
|
+
- `g.laplacian()` Laplacian matrix
|
|
171
|
+
- `g.incidence()` incidence matrix
|
|
172
|
+
|
|
173
|
+
***
|
|
174
|
+
- `g.copy()` a deep copy; a graph can also be pickled
|
|
175
|
+
- `g.export()` write the graph as GraphViz DOT, Mermaid, GraphML, ELK, or an image (which needs GraphViz)
|
|
176
|
+
- `g.validate()` check that the graph's records agree with each other
|
|
177
|
+
|
|
178
|
+
### Properties and methods of a vertex
|
|
179
|
+
Vertices are instances of the class `Vertex`, for both undirected and directed graphs.
|
|
180
|
+
|
|
181
|
+
- `v.coord` the coordinate vector for embedded graph (optional)
|
|
182
|
+
- `v.name` the name of the vertex (optional)
|
|
183
|
+
- `v.label` the number of the component that the vertex belongs to
|
|
184
|
+
- `v.adjacent()` is a list of the adjacent vertices (`neighbours()` and `neighbors()` are the same)
|
|
185
|
+
|
|
186
|
+
Vertices can be named and referenced by name.
|
|
187
|
+
|
|
188
|
+
### Properties and methods of an edge
|
|
189
|
+
Edges are instances of the class `Edge`.
|
|
190
|
+
Each edge references a pair of vertices, the graph lists all of its edges in `g.edges()`, and the vertices reference the edges.
|
|
191
|
+
|
|
192
|
+
- `e.cost` cost of edge for planning methods
|
|
193
|
+
- `e.next(v)` vertex on edge `e` that is not `v`
|
|
194
|
+
- `e.v1`, `e.v2` the two vertices that define the edge `e`
|
|
195
|
+
|
|
196
|
+
### Modifying a graph
|
|
197
|
+
|
|
198
|
+
- `g.remove_vertex(v)` or `v.remove()` remove vertex `v`
|
|
199
|
+
- `g.remove_edge(e)` or `e.remove()` remove edge `e`
|
|
200
|
+
|
|
201
|
+
### Subclassing `pgraph` classes
|
|
202
|
+
|
|
203
|
+
Consider a user class `Foo` that we would like to connect using a graph _overlay_, i.e.
|
|
204
|
+
instances of `Foo` become vertices in a graph.
|
|
205
|
+
|
|
206
|
+
- Have it subclass `Vertex`
|
|
207
|
+
- Then place instances of `Foo` into the graph using `add_vertex` and create edges as required
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from pgraph import UGraph, Vertex
|
|
211
|
+
|
|
212
|
+
class Foo(Vertex):
|
|
213
|
+
# foo stuff goes here
|
|
214
|
+
def say_hi(self):
|
|
215
|
+
print(f"hi from {self.name}")
|
|
216
|
+
|
|
217
|
+
f1 = Foo(name="f1")
|
|
218
|
+
f2 = Foo(name="f2")
|
|
219
|
+
|
|
220
|
+
g = UGraph() # create a new undirected graph
|
|
221
|
+
g.add_vertex(f1)
|
|
222
|
+
g.add_vertex(f2)
|
|
223
|
+
|
|
224
|
+
f1.connect(f2, cost=3)
|
|
225
|
+
for f in f1.adjacent():
|
|
226
|
+
f.say_hi() # say hi to the neighbours
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Or tell the graph which classes to make, with `UGraph(vertex_class=Foo, edge_class=Bar)`, and `g.add_vertex()` and `g.add_edge()` create instances of them, so they never need to be constructed by hand.
|
|
230
|
+
|
|
231
|
+
## Performance
|
|
232
|
+
|
|
233
|
+
Timings of the key operations on random geometric graphs, each vertex joined to its 4 nearest neighbours, of 100, 1,000 and 10,000 vertices, measured with [`examples/benchmark.py`](https://github.com/petercorke/pgraph-python/blob/main/examples/benchmark.py) on an Apple M4 with Python 3.12 and NumPy 2.5. The path times are the median of 10 random start and goal pairs. The last column is the exponent *b* in time ∝ N<sup>*b*</sup> between the smallest and the largest graph for the quantity shown, so 0 is constant, 1 is linear and 2 is quadratic. The adjacency, Laplacian and incidence matrices are dense, so they are only formed up to 1,000 vertices.
|
|
234
|
+
|
|
235
|
+
### Undirected graphs
|
|
236
|
+
|
|
237
|
+
| Operation | per | N=100 | N=1,000 | N=10,000 | growth exponent |
|
|
238
|
+
| :----------------------------------- | :---------- | -----: | ------: | -------: | --------------: |
|
|
239
|
+
| add a vertex | µs / vertex | 0.83 | 0.877 | 0.896 | 0.0 |
|
|
240
|
+
| add an edge (cost from the metric) | µs / edge | 1.54 | 1.64 | 1.72 | 0.0 |
|
|
241
|
+
| copy the graph | ms | 0.819 | 8.36 | 155 | 1.1 |
|
|
242
|
+
| pickle and unpickle the graph | ms | 0.462 | 4.87 | 90.4 | 1.1 |
|
|
243
|
+
| number of components, after a change | ms | 0.03 | 0.338 | 4.09 | 1.1 |
|
|
244
|
+
| number of components, unchanged | µs | 0.083 | 0.083 | 0.083 | 0.0 |
|
|
245
|
+
| remove a vertex | µs | 6.67 | 18 | 74.2 | 0.5 |
|
|
246
|
+
| closest vertex to a point | µs / query | 73.7 | 734 | 7,069 | 1.0 |
|
|
247
|
+
| adjacency matrix | ms | 0.11 | 1.53 | – | 1.1 |
|
|
248
|
+
| Laplacian matrix | ms | 0.122 | 2.93 | – | 1.4 |
|
|
249
|
+
| incidence matrix | ms | 0.0568 | 1.37 | – | 1.4 |
|
|
250
|
+
| path, breadth-first | ms / query | 0.0385 | 0.32 | 4.77 | 1.0 |
|
|
251
|
+
| path, uniform cost | ms / query | 0.0848 | 0.865 | 10.4 | 1.0 |
|
|
252
|
+
| path, A* | ms / query | 0.0521 | 0.306 | 2.71 | 0.9 |
|
|
253
|
+
|
|
254
|
+
### Directed graphs
|
|
255
|
+
|
|
256
|
+
| Operation | per | N=100 | N=1,000 | N=10,000 | growth exponent |
|
|
257
|
+
| :----------------------------------- | :---------- | -----: | ------: | -------: | --------------: |
|
|
258
|
+
| add a vertex | µs / vertex | 0.769 | 0.797 | 0.856 | 0.0 |
|
|
259
|
+
| add an edge (cost from the metric) | µs / edge | 1.55 | 1.66 | 1.7 | 0.0 |
|
|
260
|
+
| copy the graph | ms | 1.14 | 12.6 | 215 | 1.1 |
|
|
261
|
+
| pickle and unpickle the graph | ms | 0.586 | 6.88 | 169 | 1.2 |
|
|
262
|
+
| number of components, after a change | ms | 0.0419 | 0.49 | 6.35 | 1.1 |
|
|
263
|
+
| number of components, unchanged | µs | 0.083 | 0.083 | 0.083 | 0.0 |
|
|
264
|
+
| remove a vertex | µs | 8.33 | 24 | 74.7 | 0.5 |
|
|
265
|
+
| closest vertex to a point | µs / query | 69.4 | 703 | 7,242 | 1.0 |
|
|
266
|
+
| adjacency matrix | ms | 0.0816 | 1.27 | – | 1.2 |
|
|
267
|
+
| Laplacian matrix | ms | 0.093 | 2.81 | – | 1.5 |
|
|
268
|
+
| incidence matrix | ms | 0.0885 | 2.23 | – | 1.4 |
|
|
269
|
+
| path, breadth-first | ms / query | 0.0332 | 0.412 | 4.36 | 1.1 |
|
|
270
|
+
| path, uniform cost | ms / query | 0.0607 | 0.944 | 8.26 | 1.1 |
|
|
271
|
+
| path, A* | ms / query | 0.0487 | 0.728 | 3.57 | 0.9 |
|
|
272
|
+
|
|
273
|
+
## History
|
|
274
|
+
|
|
275
|
+
This is a re-engineered version of [PGraph.m](https://github.com/petercorke/spatialmath-matlab/blob/main/PGraph.m) which ships as part of the [Spatial Math Toolbox for MATLAB](https://github.com/petercorke/spatialmath-matlab). That class was used to support bundle adjustment, pose-graph SLAM and various planners such as PRM, RRT and Lattice.
|
|
276
|
+
|
|
277
|
+
The Python version was designed from the start to work with directed and undirected graphs, whereas directed graphs were a late addition to the MATLAB version. Semantics are similar but not identical. In particular the use of subclassing rather than references to _user data_ is encouraged.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pgraph/PGraph.py,sha256=EGdRqL4QJbm17EVLRkkDS1FYjYXaZ_t08FtsV1v9tfU,205175
|
|
2
|
+
pgraph/__init__.py,sha256=1f9fRElgPIj2A-rl6OFCaFfC9tYrAxAHmx0fipZ1spQ,735
|
|
3
|
+
pgraph/_plot.py,sha256=K5ihZKAJs5mzpgLvORetGA-90TtofVYxd9VxE60l0p0,2595
|
|
4
|
+
pgraph/exporters.py,sha256=0tME2iE01TwGET1RR2uo8cuTfvnepJK_1OXjbfKVmno,16864
|
|
5
|
+
pgraph_python-1.0.0.dist-info/METADATA,sha256=bnOwDiI_tzLVVCX4M-pd0fad8_vp73p21P6RhHCKeSA,15952
|
|
6
|
+
pgraph_python-1.0.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
7
|
+
pgraph_python-1.0.0.dist-info/licenses/LICENSE,sha256=niCzY_CzbIMKuUZlUkGimjrKp0vkLAtcwFmoSuSKrdw,1068
|
|
8
|
+
pgraph_python-1.0.0.dist-info/RECORD,,
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pgraph-python
|
|
3
|
-
Version: 0.6.4
|
|
4
|
-
Summary: Mathematical graphs for Python
|
|
5
|
-
Project-URL: Homepage, https://github.com/petercorke/pgraph-python
|
|
6
|
-
Project-URL: Bug Tracker, https://github.com/petercorke/pgraph-python/issues
|
|
7
|
-
Project-URL: Documentation, https://petercorke.github.io/pgraph-python
|
|
8
|
-
Project-URL: GitHub Source, https://github.com/petercorke/pgraph-python
|
|
9
|
-
Project-URL: Changelog, https://github.com/petercorke/pgraph-python/blob/main/CHANGELOG.md
|
|
10
|
-
Project-URL: Coverage, https://codecov.io/gh/petercorke/pgraph-python
|
|
11
|
-
Author-email: Peter Corke <rvc@petercorke.com>
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Keywords: Laplacian matrix,a* search,adjacency matrix,directed graph,graph,optimal path,plotting,python,undirected graph
|
|
14
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
-
Classifier: Intended Audience :: Developers
|
|
16
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
-
Requires-Python: >=3.7
|
|
24
|
-
Requires-Dist: matplotlib
|
|
25
|
-
Requires-Dist: numpy>=1.18.0
|
|
26
|
-
Requires-Dist: scipy
|
|
27
|
-
Requires-Dist: spatialmath-python
|
|
28
|
-
Provides-Extra: dev
|
|
29
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
30
|
-
Requires-Dist: pytest-cov; extra == 'dev'
|
|
31
|
-
Provides-Extra: docs
|
|
32
|
-
Requires-Dist: recommonmark; extra == 'docs'
|
|
33
|
-
Requires-Dist: sphinx; extra == 'docs'
|
|
34
|
-
Requires-Dist: sphinx-autorun; extra == 'docs'
|
|
35
|
-
Requires-Dist: sphinx-favicon; extra == 'docs'
|
|
36
|
-
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
37
|
-
Description-Content-Type: text/markdown
|
|
38
|
-
|
|
39
|
-
# PGraph: graphs for Python
|
|
40
|
-
|
|
41
|
-
[](https://github.com/petercorke/robotics-toolbox-python)
|
|
42
|
-
[](https://github.com/petercorke/spatialmath-python)
|
|
43
|
-
[](https://qcr.github.io)
|
|
44
|
-
|
|
45
|
-
[](https://pypi.python.org/pypi/pgraph-python/)
|
|
46
|
-
[](https://pypi.python.org/pypi/pgraph-python/)
|
|
47
|
-
[](https://github.com/petercorke/pgraph-python/blob/main/LICENSE)
|
|
48
|
-
|
|
49
|
-
[](https://github.com/petercorke/pgraph-python/actions?query=workflow%3ACI)
|
|
50
|
-
[](https://codecov.io/gh/petercorke/pgraph-python)
|
|
51
|
-

|
|
52
|
-
|
|
53
|
-
- [GitHub repository](https://github.com/petercorke/pgraph-python)
|
|
54
|
-
- [Wiki (examples and details)](https://github.com/petercorke/pgraph-python/wiki)
|
|
55
|
-
- [Documentation](https://petercorke.github.io/pgraph-python)
|
|
56
|
-
- [Changelog](https://github.com/petercorke/pgraph-python/blob/main/CHANGELOG.md)
|
|
57
|
-
- Dependencies: [`numpy`](https://numpy.org) [`spatialmath`](https://github.com/bdaiinstitute/spatialmath-python)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
This Python package allows the manipulation of directed and non-directed graphs. Also supports embedded graphs. It is suitable for graphs with thousands of nodes.
|
|
61
|
-
|
|
62
|
-

|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
from pgraph import *
|
|
66
|
-
import json
|
|
67
|
-
|
|
68
|
-
# load places and routes
|
|
69
|
-
with open('places.json', 'r') as f:
|
|
70
|
-
places = json.loads(f.read())
|
|
71
|
-
with open('routes.json', 'r') as f:
|
|
72
|
-
routes = json.loads(f.read())
|
|
73
|
-
|
|
74
|
-
# build the graph
|
|
75
|
-
g = UGraph()
|
|
76
|
-
|
|
77
|
-
for name, info in places.items():
|
|
78
|
-
g.add_vertex(name=name, coord=info["utm"])
|
|
79
|
-
|
|
80
|
-
for route in routes:
|
|
81
|
-
g.add_edge(route[0], route[1], cost=route[2])
|
|
82
|
-
|
|
83
|
-
# plan a path from Hughenden to Brisbane
|
|
84
|
-
p = g.path_Astar('Hughenden', 'Brisbane')
|
|
85
|
-
g.plot(block=False) # plot it
|
|
86
|
-
g.highlight_path(p) # overlay the path
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Properties and methods of the graph
|
|
90
|
-
Graphs belong to the class `UGraph` or `DGraph` for undirected or directed graphs respectively. The graph is essentially a container for the vertices.
|
|
91
|
-
|
|
92
|
-
- `g.add_vertex()` add a vertex
|
|
93
|
-
- `g.n` the number of vertices
|
|
94
|
-
- `g` is an iterator over vertices, can be used as `for vertex in g:`
|
|
95
|
-
- `g[i]` reference a vertex by its index or name
|
|
96
|
-
|
|
97
|
-
***
|
|
98
|
-
- `g.add_edge()` connect two vertices
|
|
99
|
-
- `g.edges()` all edges in the graph
|
|
100
|
-
- `g.plot()` plots the vertices and edges
|
|
101
|
-
- `g.nc` the number of graph components, 1 if fully connected
|
|
102
|
-
- `g.component(v)` the component that vertex `v` belongs to
|
|
103
|
-
|
|
104
|
-
***
|
|
105
|
-
- `g.path_BFS()` breadth-first search
|
|
106
|
-
- `g.path_Astar()` A* search
|
|
107
|
-
|
|
108
|
-
***
|
|
109
|
-
- `g.adjacency()` adjacency matrix
|
|
110
|
-
- `g.Laplacian()` Laplacian matrix
|
|
111
|
-
- `g.incidence()` incidence matrix
|
|
112
|
-
|
|
113
|
-
### Properties and methods of a vertex
|
|
114
|
-
Vertices belong to the class `UVertex` (for undirected graphs) or `DVertex` (for directed graphs), which are each subclasses of `Vertex`.
|
|
115
|
-
|
|
116
|
-
- `v.coord` the coordinate vector for embedded graph (optional)
|
|
117
|
-
- `v.name` the name of the vertex (optional)
|
|
118
|
-
- `v.neighbours()` is a list of the neighbouring vertices
|
|
119
|
-
- `v1.samecomponent(v2)` predicate for vertices belonging to the same component
|
|
120
|
-
|
|
121
|
-
Vertices can be named and referenced by name.
|
|
122
|
-
|
|
123
|
-
### Properties and methods of an edge
|
|
124
|
-
Edges are instances of the class `Edge`.
|
|
125
|
-
Edges are not referenced by the graph object, each edge references a pair of vertices, and the vertices reference the edges. For a directed graph only the start vertex of an edge references the edge object, whereas for an undirected graph both vertices reference the edge object.
|
|
126
|
-
|
|
127
|
-
- `e.cost` cost of edge for planning methods
|
|
128
|
-
- `e.next(v)` vertex on edge `e` that is not `v`
|
|
129
|
-
- `e.v1`, `e.v2` the two vertices that define the edge `e`
|
|
130
|
-
|
|
131
|
-
## Modifying a graph
|
|
132
|
-
|
|
133
|
-
- `g.remove(v)` remove vertex `v`
|
|
134
|
-
- `e.remove()` remove edge `e`
|
|
135
|
-
|
|
136
|
-
## Subclasing pgraph classes
|
|
137
|
-
|
|
138
|
-
Consider a user class `Foo` that we would like to connect using a graph _overlay_, ie.
|
|
139
|
-
instances of `Foo` becomes vertices in a graph.
|
|
140
|
-
|
|
141
|
-
- Have it subclass either `DVertex` or `UVertex` depending on graph type
|
|
142
|
-
- Then place instances of `Foo` into the graph using `add_vertex` and create edges as required
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
class Foo(UVertex):
|
|
146
|
-
# foo stuff goes here
|
|
147
|
-
|
|
148
|
-
f1 = Foo(...)
|
|
149
|
-
f2 = Foo(...)
|
|
150
|
-
|
|
151
|
-
g = UGraph() # create a new undirected graph
|
|
152
|
-
g.add_vertex(f1)
|
|
153
|
-
g.add_vertex(f2)
|
|
154
|
-
|
|
155
|
-
f1.connect(f2, cost=3)
|
|
156
|
-
for f in f1.neighbours():
|
|
157
|
-
# say hi to the neighbours
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## Under the hood
|
|
161
|
-
|
|
162
|
-
The key objects and their interactions are shown below.
|
|
163
|
-
|
|
164
|
-

|
|
165
|
-
|
|
166
|
-
## MATLAB version
|
|
167
|
-
|
|
168
|
-
This is a re-engineered version of [PGraph.m](https://github.com/petercorke/spatialmath-matlab/blob/main/PGraph.m) which ships as part of the [Spatial Math Toolbox for MATLAB](https://github.com/petercorke/spatialmath-matlab). This class is used to support bundle adjustment, pose-graph SLAM and various planners such as PRM, RRT and Lattice.
|
|
169
|
-
|
|
170
|
-
The Python version was designed from the start to work with directed and undirected graphs, whereas directed graphs were a late addition to the MATLAB version. Semantics are similar but not identical. In particular the use of subclassing rather than references to
|
|
171
|
-
_user data_ is encouraged.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
pgraph/PGraph.py,sha256=vAVCAolCRybMaowkdw7Oz_jn3xj7655rbbw2jF793pA,60135
|
|
2
|
-
pgraph/__init__.py,sha256=J2sLjUeac_R5eSJncN1RvkkDkgxA8ko8dDan5CP-Tp8,65
|
|
3
|
-
pgraph_python-0.6.4.dist-info/METADATA,sha256=QNOIuH6DNtU0x1Du-vNjlj6Lrywfvw8dPR_2zxd20n4,7528
|
|
4
|
-
pgraph_python-0.6.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
5
|
-
pgraph_python-0.6.4.dist-info/licenses/LICENSE,sha256=niCzY_CzbIMKuUZlUkGimjrKp0vkLAtcwFmoSuSKrdw,1068
|
|
6
|
-
pgraph_python-0.6.4.dist-info/RECORD,,
|
|
File without changes
|