""" A Python Class A simple Python graph class, demonstrating the essential facts and functionalities of graphs. """ class Graph(object): def __init__(self, graph_dict={}): """ initializes a graph object """ self.__graph_dict = graph_dict def vertices(self): """ returns the vertices of a graph """ return list(self.__graph_dict.keys()) def edges(self): """ returns the edges of a graph """ return self.__generate_edges() def add_vertex(self, vertex): """ If the vertex "vertex" is not in self.__graph_dict, a key "vertex" with an empty list as a value is added to the dictionary. Otherwise nothing has to be done. """ if vertex not in self.__graph_dict: self.__graph_dict[vertex] = [] def add_edge(self, edge): """ assumes that edge is of type set, tuple or list; between two vertices can be multiple edges! """ edge = set(edge) vertex1 = edge.pop() if edge: # not a loop vertex2 = edge.pop() else: # a loop vertex2 = vertex1 if vertex1 in self.__graph_dict: self.__graph_dict[vertex1].append(vertex2) else: self.__graph_dict[vertex1] = [vertex2] def __generate_edges(self): """ A static method generating the edges of the graph "graph". Edges are represented as sets with one (a loop back to the vertex) or two vertices """ edges = [] for vertex in self.__graph_dict: for neighbour in self.__graph_dict[vertex]: if {neighbour, vertex} not in edges: edges.append({vertex, neighbour}) return edges def __str__(self): """ String representation of a graph """ res = "Knoten: " for k in self.__graph_dict: res += str(k) + " " res += "\nKanten: " for edge in self.__generate_edges(): res += str(edge) + " " return res def find_isolated_vertices(self): """ returns a list of isolated vertices. """ graph = self.__graph_dict isolated = [] for vertex in graph: if not graph[vertex]: isolated += [vertex] return isolated def find_path(self, start_vertex, end_vertex, path=[]): """ find a path from start_vertex to end_vertex in graph """ graph = self.__graph_dict path = path + [start_vertex] if start_vertex == end_vertex: return path if start_vertex not in graph: return None for vertex in graph[start_vertex]: if vertex not in path: extended_path = self.find_path(vertex, end_vertex, path) if extended_path: return extended_path return None def find_all_paths(self, start_vertex, end_vertex, path=[]): """ find all paths from start_vertex to end_vertex in graph """ graph = self.__graph_dict path = path + [start_vertex] if start_vertex == end_vertex: return [path] if start_vertex not in graph: return [] paths = [] for vertex in graph[start_vertex]: if vertex not in path: extended_paths = self.find_all_paths(vertex, end_vertex, path) for p in extended_paths: paths.append(p) return paths if __name__ == "__main__": g = { 1 : [2], 2 : [1,3,6], 3 : [2,4,7], 4 : [3,5,8], 5 : [4,9], 6 : [2,7], 7 : [3,6,8], 8 : [4,7,9], 9 : [5,8,10], 10: [9] } graph = Graph(g) print(graph) print("Kanten des Graphen: ") print(graph.edges()) print("""Ein Pfad von "1" nach "8":""") print(graph.find_path(1,8)) print("""Alle Pfade von "1" nach "10":""") print(graph.find_all_paths(1,10)) print("Isolierten Knoten hnizufügen '11':") graph.add_vertex(11) print(graph) print("Eine Schleife um den Knoten 7 hinzufügen: ") graph.add_edge((7,)) # alternativ auch: # graph.add_edge({7}) print(graph) print(graph)