mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-26 00:41:25 -06:00
3bf91eab25
Python 2 has keys()/values()/items(), which return lists, iterkeys()/itervalues()/iteritems(), which return iterators, and viewkeys()/viewvalues()/viewitems() which return views. Python 3 has only keys()/values()/items(), which return views. To get iterators, one can use iter() or a for loop/comprehension; for lists there's the list() constructor. When iterating through the entire dict, without modifying the dict, the difference between Python 2's items() and iteritems() is negligible, especially on small dicts (the main overhead is extra memory, not CPU time). In the interest of simpler code, this patch changes many instances of iteritems() to items(), iterkeys() to keys() etc. In other cases, helpers like six.itervalues are used. Reviewed-By: Christian Heimes <cheimes@redhat.com> Reviewed-By: Jan Cholasta <jcholast@redhat.com>
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
#
|
|
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
|
#
|
|
|
|
|
|
class Graph():
|
|
"""
|
|
Simple oriented graph structure
|
|
|
|
G = (V, E) where G is graph, V set of vertices and E list of edges.
|
|
E = (tail, head) where tail and head are vertices
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.vertices = set()
|
|
self.edges = []
|
|
self._adj = dict()
|
|
|
|
def add_vertex(self, vertex):
|
|
self.vertices.add(vertex)
|
|
self._adj[vertex] = []
|
|
|
|
def add_edge(self, tail, head):
|
|
if tail not in self.vertices:
|
|
raise ValueError("tail is not a vertex")
|
|
if head not in self.vertices:
|
|
raise ValueError("head is not a vertex")
|
|
self.edges.append((tail, head))
|
|
self._adj[tail].append(head)
|
|
|
|
def remove_edge(self, tail, head):
|
|
try:
|
|
self.edges.remove((tail, head))
|
|
except KeyError:
|
|
raise ValueError(
|
|
"graph does not contain edge: (%s, %s)" % (tail, head))
|
|
self._adj[tail].remove(head)
|
|
|
|
def remove_vertex(self, vertex):
|
|
try:
|
|
self.vertices.remove(vertex)
|
|
except KeyError:
|
|
raise ValueError("graph does not contain vertex: %s" % vertex)
|
|
|
|
# delete _adjacencies
|
|
del self._adj[vertex]
|
|
for key, _adj in self._adj.items():
|
|
_adj[:] = [v for v in _adj if v != vertex]
|
|
|
|
# delete edges
|
|
edges = [e for e in self.edges if e[0] != vertex and e[1] != vertex]
|
|
self.edges[:] = edges
|
|
|
|
def get_tails(self, head):
|
|
"""
|
|
Get list of vertices where a vertex is on the right side of an edge
|
|
"""
|
|
return [e[0] for e in self.edges if e[1] == head]
|
|
|
|
def get_heads(self, tail):
|
|
"""
|
|
Get list of vertices where a vertex is on the left side of an edge
|
|
"""
|
|
return [e[1] for e in self.edges if e[0] == tail]
|
|
|
|
def bfs(self, start=None):
|
|
"""
|
|
Breadth-first search traversal of the graph from `start` vertex.
|
|
Return a set of all visited vertices
|
|
"""
|
|
if not start:
|
|
start = list(self.vertices)[0]
|
|
visited = set()
|
|
queue = [start]
|
|
while queue:
|
|
vertex = queue.pop(0)
|
|
if vertex not in visited:
|
|
visited.add(vertex)
|
|
queue.extend(set(self._adj.get(vertex, [])) - visited)
|
|
return visited
|