Skip to content

Commit e4cd49b

Browse files
committed
changes to Edge constructor and connection logic
1 parent c05fc91 commit e4cd49b

File tree

1 file changed

+88
-16
lines changed

1 file changed

+88
-16
lines changed

pgraph/PGraph.py

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,16 @@ def add_edge(self, v1, v2, **kwargs):
175175
:type v1: Vertex subclass
176176
:param v2: second vertex (end if a directed graph)
177177
:type v2: Vertex subclass
178-
:param kwargs: optional arguments to pass to ``connect``
178+
:param kwargs: optional arguments to pass to ``Vertex.connect``
179179
:return: edge
180180
:rtype: Edge
181181
182-
.. note:: This is a graph centric way of creating an edge. The
183-
alternative is the ``connect`` method of a vertex.
182+
Create an edge between a vertex pair and adds it to the graph.
184183
185-
:seealso: :meth:`Edge.connect`
184+
This is a graph centric way of creating an edge. The
185+
alternative is the ``connect`` method of a vertex.
186+
187+
:seealso: :meth:`Edge.connect` :meth:`Vertex.connect`
186188
"""
187189
if isinstance(v1, str):
188190
v1 = self[v1]
@@ -1312,20 +1314,56 @@ class Edge:
13121314
edgelist of _each_ vertex.
13131315
- This class can be inherited to provide user objects with graph capability.
13141316
- Inheritance is an alternative to providing arbitrary user data.
1317+
1318+
An Edge points to a pair of vertices. At ``connect`` time the vertices
1319+
get references back to the Edge object.
1320+
1321+
``graph.add_edge(v1, v2)`` calls ``v1.connect(v2)``
13151322
"""
13161323

1317-
def __init__(self, v1, v2, cost=None, data=None):
1318-
if cost is None:
1319-
try:
1320-
self.cost = np.linalg.norm(v1.coord - v2.coord)
1321-
except TypeError:
1322-
self.cost = None
1323-
else:
1324-
self.cost = cost
1325-
self.data = data
1324+
def __init__(self, v1=None, v2=None, cost=None, data=None):
1325+
"""
1326+
Create an edge object
1327+
1328+
:param v1: start of the edge, defaults to None
1329+
:type v1: Vertex subclass, optional
1330+
:param v2: end of the edge, defaults to None
1331+
:type v2: Vertex subclass, optional
1332+
:param cost: edge cost, defaults to None
1333+
:type cost: any, optional
1334+
:param data: edge data, defaults to None
1335+
:type data: any, optional
1336+
1337+
Creates an edge but does not connect it to the vertices or add it to the
1338+
graph.
1339+
1340+
If vertices are given, and have associated coordinates, the edge cost
1341+
will be computed according to the distance measure associated with the
1342+
graph.
1343+
1344+
``data`` is a way of associating any object with the edge, its value
1345+
can be found as the ``.data`` attribute of the edge. An alternative
1346+
approach is to subclass the ``Edge`` class.
1347+
1348+
.. note:: To compute edge cost from the vertices, the vertices must have
1349+
been added to the graph.
1350+
1351+
:seealso: :meth:`Edge.connect` :meth:`Vertex.connect`
1352+
"""
13261353
self.v1 = v1
13271354
self.v2 = v2
13281355

1356+
self.data = data
1357+
1358+
# try to compute edge cost as metric distance if not given
1359+
if cost is not None:
1360+
self.cost = cost
1361+
elif not (v1 is None or v1.coord is None or v2 is None or v2.coord is None):
1362+
self.cost = v1._graph.metric(v1.coord - v2.coord)
1363+
else:
1364+
self.cost = None
1365+
1366+
13291367
def __repr__(self):
13301368
return str(self)
13311369

@@ -1336,6 +1374,36 @@ def __str__(self):
13361374
s += f" data={self.data}"
13371375
return s
13381376

1377+
def connect(self, v1, v2):
1378+
"""
1379+
Add edge to the graph
1380+
1381+
:param v1: start of the edge
1382+
:type v1: Vertex subclass
1383+
:param v2: end of the edge
1384+
:type v2: Vertex subclass
1385+
1386+
The edge is added to the graph and connects vertices ``v1`` and ``v2``.
1387+
1388+
.. note:: The vertices must already be added to the graph.
1389+
"""
1390+
1391+
if v1._graph is None:
1392+
raise ValueError('vertex v1 does not belong to a graph')
1393+
if v2._graph is None:
1394+
raise ValueError('vertex v2 does not belong to a graph')
1395+
if not v1._graph is v2._graph:
1396+
raise ValueError('vertices must belong to the same graph')
1397+
1398+
# connect edge to its vertices
1399+
self.v1 = v1
1400+
self.v2 = v2
1401+
1402+
# tell the vertices to add edge to their edgelists as appropriate for
1403+
# DGraph or UGraph
1404+
v1.connect(v2, edge=self)
1405+
1406+
13391407
def next(self, vertex):
13401408
"""
13411409
Return other end of an edge
@@ -1459,10 +1527,10 @@ def connect(self, dest, edge=None, cost=None, data=None):
14591527
:param dest: The node to connect to
14601528
:type dest: ``Vertex`` subclass
14611529
:param edge: Use this as the edge object, otherwise a new ``Edge``
1462-
object is created, defaults to None
1530+
object is created from the vertices being connected,
1531+
and the ``cost`` and ``edge`` parameters, defaults to None
14631532
:type edge: ``Edge`` subclass, optional
1464-
:param cost: the cost to traverse this edge, required for planning
1465-
methods, defaults to None
1533+
:param cost: the cost to traverse this edge, defaults to None
14661534
:type cost: float, optional
14671535
:param data: reference to arbitrary data associated with the edge,
14681536
defaults to None
@@ -1478,6 +1546,8 @@ def connect(self, dest, edge=None, cost=None, data=None):
14781546
- If the vertices subclass ``UVertex`` the edge is undirected, and if
14791547
they subclass ``DVertex`` the edge is directed.
14801548
- Vertices must both be of the same ``Vertex`` subclass
1549+
1550+
:seealso: :meth:`Edge`
14811551
"""
14821552

14831553
if not dest.__class__.__bases__[0] is self.__class__.__bases__[0]:
@@ -1486,7 +1556,9 @@ def connect(self, dest, edge=None, cost=None, data=None):
14861556
e = edge
14871557
else:
14881558
e = Edge(self, dest, cost=cost, data=data)
1559+
14891560
self._graph._edgelist.add(e)
1561+
self._graph._connectivitychange = True
14901562
self._connectivitychange = True
14911563

14921564
return e

0 commit comments

Comments
 (0)