Source code for challenges.graph

# noinspection PyShadowingBuiltins
[docs]class Node: def __init__(self, id): """ Create a node. Not for direct usage. To create node and edges use: * Graph.create_node() * Graph.create_edge() """ self._id = id self._incoming = [] self._outgoing = [] @property def id(self): """ Return the nodes id.""" return self._id @property def incoming(self): """ Return the incoming EDGES of the node. """ return self._incoming @property def outgoing(self): """ Return the outgoing EDGES of the node. """ return self._outgoing
[docs] def add_edge(self, edge): """ Add an edge to the node. Not for direct usage. To create node and edges use: * Graph.create_node() * Graph.create_edge() """ if self is edge.head: self._incoming.append(edge) elif self is edge.tail: self._outgoing.append(edge) else: raise ValueError( 'The node is neither head nor tail of the edge.' )
[docs] def antecessors(self): """ Return the incoming NODES of the node. The tail nodes of all incoming edges. """ return (edge.tail for edge in self.incoming)
[docs] def successors(self): """ Return the outgoing NODES of the node. The head nodes of all outgoing edges. """ return (edge.head for edge in self.outgoing)
def __str__(self): """ Return a human readable string representation of the node. """ pre = str([edge.tail.id for edge in self.incoming]) post = str([edge.head.id for edge in self.outgoing]) return '{}->({})->{}'.format(pre, self.id, post) def __repr__(self): """ Return a human readable string representation of the node. """ return self.__str__()
[docs]class Edge: def __init__(self, tail, head): """ Create an edge. Not for direct usage. To create node and edges use: * Graph.create_node() * Graph.create_edge() """ self._tail = tail self._head = head @property def tail(self): """ Return the tail node. """ return self._tail @property def head(self): """ Return the head node. """ return self._head def __str__(self): """ Return a human readable string representation of the edge. """ return '({})->({})'.format(self.tail.id, self.head.id)
# noinspection PyShadowingBuiltins
[docs]class Graph: def __init__(self): self._nodes = {}
[docs] def create_node(self, id): """Add a standalone node to the graph and return it. If a node of this id already exists, it is just returned. """ if id not in self._nodes: self._nodes[id] = Node(id) return self._nodes[id]
[docs] def create_edge(self, tail, head): """Add an edge and return it. Create nodes as necessary. :tail: Node or id of node :head: Node or id of node """ if isinstance(tail, Node): tail_node = tail else: tail_node = self.create_node(tail) if isinstance(head, Node): head_node = head else: head_node = self.create_node(head) edge = Edge(tail_node, head_node) tail_node.add_edge(edge) head_node.add_edge(edge) return edge
[docs] def node(self, id): """Return a node by id.""" return self._nodes[id]
[docs] def nodes(self): """Return all nodes sorted by node id.""" return list(self._nodes[key] for key in sorted(self._nodes))
[docs] def keys(self): """Return keys of nodes in sorted order.""" return sorted(self._nodes)
[docs] def count(self): """Return count of nodes.""" return len(self._nodes)