Draw Directed Graph Python Graph-tool
7. Graph Hypothesis and Graphs in Python
By Bernd Klein. Last modified: 10 Nov 2022.
Origins of Graph Theory
In front we kickoff with the de facto implementations of graphs in Python and ahead we start with the introduction of Python modules dealing with graphs, we want to devote ourselves to the origins of graph theory.
The origins take us dorsum one of these days to the Künigsberg of the 18th century. Königsberg was a city in Prussia that time. The river Pregel flowed through the town, creating cardinal islands. The City and the islands were connected by heptad bridges American Samoa shown. The inhabitants of the city were moved by the question, if it was possible to take a walk through the town by visiting to each one area of the town and crossing each bridgework just once? Every bridge must have been cross-town completely, i.e. information technology is not allowed to walk halfway onto a bridge circuit and then turn around and later cross the other half from the other go with. The walk need not part and end at the same spot. Leonhard Euler solved the trouble in 1735 by proving that it is not manageable.
Atomic number 2 found out that the selection of a path inside each acreage is irrelevant and that the only thing which mattered is the lodg (or the sequence) in which the Bridges are crossed. He had formulated an abstraction of the problem, eliminating unnecessary facts and focussing along the landed estate areas and the bridges copulative them. This path, he created the foundations of graph theory. If we see a "land area" as a apex and each bridge as an margin, we have "reduced" the problem to a graph.
Introduction into Graph Theory Using Python
Before we start our treatize on possible Python representations of graphs, we want to present some general definitions of graphs and its components.
A "graph"1 in maths and computer scientific discipline consists of "nodes", likewise far-famed as "vertices". Nodes may or may not cost connected with united some other. In our instance, - which is a pictorial agency of a graph,
- the node "a" is connected with the node "c", simply "a" is not connected with "b". The connecting logical argument betwixt two nodes is known as an edge. If the edges between the nodes are directionless, the chart is titled an undirected graph. If an edge is directed from cardinal vertex (guest) to another, a graph is called a directed graph. An directed edge is titled an discharge.
Though graphs may look very supposed, many practical problems can be represented by graphs. They are ofttimes wont to model problems OR situations in natural philosophy, biological science, psychology and above all in computer science. In computing, graphs are in use to represent networks of communication, information establishment, computational devices, the flow of calculation,
In the latter example, the are accustomed represent the data organisation, like the filing system of an in operation system, Oregon communication networks. The link structure of websites can be seen as a chart as well, i.e. a directed chart, because a link is a directed sharpness operating theater an arc.
Python has no built-in data type or assort for graphs, but it is unproblematic to implement them in Python. One data type is abstract for representing graphs in Python, i.e. dictionaries. The chart in our illustration can be implemented in the following way:
graph = { "a" : { "c" }, "b" : { "c" , "e" }, "c" : { "a" , "b" , "d" , "e" }, "d" : { "c" }, "e" : { "c" , "b" }, "f" : {} }
The keys of the dictionary above are the nodes of our graph. The corresponding values are sets with the nodes, which are connectrd away an edge. A mark is better than a tilt or a tuple, because this way, we can have only one inch between two nodes. There is atomic number 102 simpler and more elegant way to represent a graph.
An edge can likewise be ideally implemented as a set with two elements, i.e. the end nodes. This is ideal for undirected graphs. For orientated graphs we would prefer lists Beaver State tuples to implement edges.
Run to generate the list of all edges:
def generate_edges ( graphical record ): edges = [] for lymph gland in graph : for neighbour in chart [ node ]: edges . append ({ node , neighbour }) return edges print ( generate_edges ( graph ))
End product:
[{'c', 'a'}, {'c', 'b'}, {'b', 'e'}, {'c', 'd'}, {'c', 'b'}, {'c', 'e'}, {'c', 'a'}, {'c', 'd'}, {'c', 'e'}, {'b', 'e'}]
As we can see, there is no edge containing the node "f". "f" is an isolated node of our graph. The following Python function calculates the isolated nodes of a given chart:
def find_isolated_nodes ( chart ): """ returns a go down of isolated nodes. """ disjunct = set () for node in graph : if not graph [ knob ]: detached . add ( node ) return isolated
If we call this social occasion with our graph, a list containing "f" testament be returned:
Graphs as a Python Class
Before we go connected with writing functions for graphs, we have a foremost pass away at a Python graph class carrying out.
If you deal the following listing of our class, you bottom see in the init-method acting that we exercise a dictionary "self._graph_dict" for storing the vertices and their corresponding adjacent vertices.
""" A Python Class A acuminate Python graph class, demonstrating the essential facts and functionalities of graphs. """ class Graph ( object ): def __init__ ( someone , graph_dict = None ): """ initializes a graph object If no more dictionary or No is acknowledged, an glazed dictionary will constitute secondhand """ if graph_dict == No : graph_dict = {} self . _graph_dict = graph_dict def edges ( self , vertice ): """ returns a list of all the edges of a vertice""" devolve self . _graph_dict [ vertice ] def all_vertices ( self ): """ returns the vertices of a graph as a set """ regaining set ( soul . _graph_dict . keys ()) def all_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 lexicon. Otherwise nothing has to represent done. """ if vertex non in self . _graph_dict : self . _graph_dict [ apex ] = [] def add_edge ( self , edge ): """ assumes that edge is of eccentric set, tuple operating theater list; between two vertices can beryllium multiple edges! """ edge = set ( edge ) vertex1 , vertex2 = tuple ( march ) for x , y in [( vertex1 , vertex2 ), ( vertex2 , vertex1 )]: if x in self . _graph_dict : self . _graph_dict [ x ] . add ( y ) else : self . _graph_dict [ x ] = [ y ] 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) operating theatre 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 __iter__ ( someone ): somebody . _iter_obj = iter ( self . _graph_dict ) return soul . _iter_obj def __next__ ( self ): """ allows us to iterate over the vertices """ return next ( self . _iter_obj ) def __str__ ( person ): reticuloendothelial system = "vertices: " for k in self . _graph_dict : res += str ( k ) + " " RES += " \n edges: " for edge in self . __generate_edges (): res += str ( edge ) + " " return key RES
We want to bring on a miniscule number with our chart. We go with iterating over the graph. Iterating way iterating over the vertices.
g = { "a" : { "d" }, "b" : { "c" }, "c" : { "b" , "c" , "d" , "e" }, "d" : { "a" , "c" }, "e" : { "c" }, "f" : {} } graph = Graph ( g ) for vertice in graph : black and white ( f "Edges of vertice { vertice } : " , graph . edges ( vertice ))
OUTPUT:
Edges of vertice a: {'d'} Edges of vertice b: {'c'} Edges of vertice c: {'c', 'd', 'b', 'e'} Edges of vertice d: {'c', 'a'} Edges of vertice e: {'c'} Edges of vertice f: {}
graph . add_edge ({ "ab" , "fg" }) chart . add_edge ({ "xyz" , "bla" })
print ( "" ) photographic print ( "Vertices of graph:" ) print ( graph . all_vertices ()) print ( "Edges of graph:" ) print ( chart . all_edges ())
Yield:
Vertices of graphical record: {'d', 'b', 'e', 'f', 'fg', 'c', 'bla', 'xyz', 'ab', 'a'} Edges of chart: [{'d', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}, {'ab', 'fg'}, {'bla', 'xyz'}]
Let's calculate the name of all the vertices and the list of all the edges of our chart:
print ( "" ) print ( "Vertices of graph:" ) print ( graph . all_vertices ()) photographic print ( "Edges of graph:" ) print ( graph . all_edges ())
Turnout:
Vertices of graph: {'d', 'b', 'e', 'f', 'fg', 'c', 'bla', 'xyz', 'ab', 'a'} Edges of graph: [{'d', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}, {'ab', 'fg'}, {'bla', 'xyz'}]
We MBD a vertex and and edge to the graph:
publish ( "Add vertex:" ) graphical record . add_vertex ( "z" ) impress ( "Add an edge:" ) graphical record . add_edge ({ "a" , "d" }) print ( "Vertices of graph:" ) publish ( graph . all_vertices ()) impress ( "Edges of graph:" ) print ( graph . all_edges ())
OUTPUT:
Add vertex: Add an butt on: Vertices of graph: {'d', 'b', 'e', 'f', 'fg', 'z', 'c', 'bla', 'xyz', 'ab', 'a'} Edges of chart: [{'d', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}, {'ab', 'fg'}, {'bla', 'xyz'}]
print ( 'Adding an edge {"x","y"} with raw vertices:' ) chart . add_edge ({ "x" , "y" }) print ( "Vertices of graph:" ) print ( graph . all_vertices ()) photographic print ( "Edges of chart:" ) impress ( graph . all_edges ())
Outturn:
Adding an edge {"x","y"} with new vertices: Vertices of graph: {'d', 'b', 'e', 'f', 'fg', 'z', 'x', 'c', 'bla', 'xyz', 'abdominal muscle', 'y', 'a'} Edges of graphical record: [{'d', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}, {'ab', 'fg'}, {'bla', 'xyz'}, {'x', 'y'}]
Paths in Graphs
We want to find now the shortest course from one guest to another lymph node. Before we come to the Python inscribe for this problem, we will hold to present some formal definitions.
Near vertices:
Two vertices are adjacent when they are both incident to a common edge in.
Path in an undirected Chart:
A course in an undirected graph is a episode of vertices P = ( v1, v2, ..., vn ) ∈ V x V x ... x V such that vi is adjacent to v{i+1} for 1 ≤ i < n. Such a path P is called a itinerary of distance n from v1 to vn.
Simple Path:
A path with no repeated vertices is called a simple path.
Example:
We total a method acting find_path
to our class Graph
. It tries to find a path from a start vertex to an end apex. We also attention deficit disorder a method acting find_all_paths
, which finds all the paths from a start vertex to an close vertex:
""" A Python Category A needle-shaped Python graph class, demonstrating the essential facts and functionalities of graphs. """ class Graph ( aim ): def __init__ ( self , graph_dict = No ): """ initializes a graph object If no more dictionary or No is given, an empty dictionary will live used """ if graph_dict == No : graph_dict = {} self . _graph_dict = graph_dict def edges ( self , vertice ): """ returns a list of all the edges of a vertice""" return mortal . _graph_dict [ vertice ] def all_vertices ( self ): """ returns the vertices of a graph as a set """ return set ( self . _graph_dict . keys ()) def all_edges ( self ): """ returns the edges of a graph """ return person . __generate_edges () def add_vertex ( self , vertex ): """ If the vertex "vertex" is non in someone._graph_dict, a key "apex" with an empty list A a value is added to the dictionary. Otherwise nothing has to be through. """ if acme not in self . _graph_dict : soul . _graph_dict [ vertex ] = [] def add_edge ( self , edge ): """ assumes that edge is of type settled, tuple or name; 'tween two vertices privy be multiple edges! """ edge = set ( edge ) vertex1 , vertex2 = tuple ( edge ) for x , y in [( vertex1 , vertex2 ), ( vertex2 , vertex1 )]: if x in soul . _graph_dict : self . _graph_dict [ x ] . append ( y ) else : self . _graph_dict [ x ] = [ y ] def __generate_edges ( self ): """ A static method generating the edges of the graph "graph". Edges are represented as sets with one and only (a loop back to the vertex) surgery two vertices """ edges = [] for vertex in ego . _graph_dict : for neighbour in self . _graph_dict [ vertex ]: if { neighbor , acme } not in edges : edges . append ({ vertex , neighbor }) return edges def __iter__ ( self ): self . _iter_obj = iter ( self . _graph_dict ) return self . _iter_obj def __next__ ( self ): """ allows us to iterate over the vertices """ hark back next ( self . _iter_obj ) def __str__ ( self ): res = "vertices: " for k in self . _graph_dict : reticuloendothelial system += str ( k ) + " " res += " \n edges: " for edge in individual . __generate_edges (): res += str ( edge ) + " " return res def find_path ( self , start_vertex , end_vertex , way of life = No ): """ find a path from start_vertex to end_vertex in graph """ if path == None : path = [] graph = self . _graph_dict path = way of life + [ start_vertex ] if start_vertex == end_vertex : render track if start_vertex not in chart : return None for acme in graph [ start_vertex ]: if vertex not in route : extended_path = self . find_path ( acme , end_vertex , path ) if extended_path : reelect extended_path return None def find_all_paths ( ego , start_vertex , end_vertex , path = []): """ find whol paths from start_vertex to end_vertex in graph """ graphical record = person . _graph_dict path = way + [ start_vertex ] if start_vertex == end_vertex : getting even [ path ] if start_vertex not in graph : return [] paths = [] for vertex in graphical record [ start_vertex ]: if peak non in way : extended_paths = self . find_all_paths ( vertex , end_vertex , path ) for p in extended_paths : paths . tack on ( p ) return paths
We check in the following the way of working of our find_path
and find_all_paths
methods.
g = { "a" : { "d" }, "b" : { "c" }, "c" : { "b" , "c" , "d" , "e" }, "d" : { "a" , "c" }, "e" : { "c" }, "f" : {} } graph = Graph ( g ) print ( "Vertices of graph:" ) publish ( graph . all_vertices ()) print ( "Edges of graphical record:" ) black and white ( graph . all_edges ()) print ( 'The path from vertex "a" to vertex "b":' ) path = graph . find_path ( "a" , "b" ) print ( path ) print ( 'The path from vertex "a" to vertex "f":' ) path = graph . find_path ( "a" , "f" ) print ( path ) print ( 'The path from vertex "c" to vertex "c":' ) itinerary = graph . find_path ( "c" , "c" ) print ( path )
OUTPUT:
Vertices of graphical record: {'d', 'b', 'e', 'f', 'c', 'a'} Edges of graph: [{'d', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}] The path from acme "a" to vertex "b": ['a', 'd', 'c', 'b'] The track from vertex "a" to vertex "f": None The path from vertex "c" to vertex "c": ['c']
We slightly varied our example graph by adding edges from "a" to "f" and from "f" to "d" to test the find_all_paths
method:
g = { "a" : { "d" , "f" }, "b" : { "c" }, "c" : { "b" , "c" , "d" , "e" }, "d" : { "a" , "c" , "f" }, "e" : { "c" }, "f" : { "a" , "d" } } graph = Chart ( g ) print ( "Vertices of chart:" ) print ( chart . all_vertices ()) print ( "Edges of graph:" ) print ( graph . all_edges ()) black and white ( 'All paths from vertex "a" to vertex "b":' ) path = graph . find_all_paths ( "a" , "b" ) print ( way of life ) print ( 'All paths from acme "a" to vertex "f":' ) path = graph . find_all_paths ( "a" , "f" ) print ( path ) publish ( 'All paths from vertex "c" to vertex "c":' ) path = graph . find_all_paths ( "c" , "c" ) mark ( path )
OUTPUT:
Vertices of graphical record: {'d', 'b', 'e', 'f', 'c', 'a'} Edges of graph: [{'d', 'a'}, {'f', 'a'}, {'c', 'b'}, {'c'}, {'c', 'd'}, {'c', 'e'}, {'d', 'f'}] Every paths from vertex "a" to vertex "b": [['a', 'd', 'c', 'b'], ['a', 'f', 'd', 'c', 'b']] All paths from vertex "a" to apex "f": [['a', 'd', 'f'], ['a', 'f']] All paths from vertex "c" to apex "c": [['c']]
Degree and Degree Successiveness
The degree of a acme v in a graph is the add up of edges connecting IT, with loops counted twice. The degree of a vertex v is denoted deg(v). The upper limit degree of a chart G, denoted by Δ(G), and the negligible degree of a graph, denoted by δ(G), are the maximum and minimum degree of its vertices.
In the graph on the right-minded side, the maximal point is 5 at vertex c and the minimum point is 0, i.e the isolated vertex f.
If all the degrees in a graph are the same, the graph is a regularized graph.
In a regular chart, all degrees are the same, and and then we butt speak up of the degree of the graph.
The degree sum formula (Shake lemma):
∑v ∈ Vdeg(v) = 2 |E|
This means that the sum of degrees of all the vertices is equal to the number of edges multiplied by 2. We can conclude that the number of vertices with odd degree has to be justified. This affirmation is glorious as the handshaking lemma. The name "handshaking flowering glume" stems from a popular mathematical problem: In some chemical group of multitude the number of people who have shaken hands with an odd number of another multitude from the group is yet.
The degree sequence of an undirected graphical record is defined as the sequence of its vertex degrees in a non-increasing order. The next method acting returns a tuple with the degree chronological succession of the instance graph:
We testament design a new class Graph2
now, which inherits from our previously characterized graph Graph
and we add the favourable methods to it:
-
vertex_degree
-
find_isolated_vertices
-
delta
-
degree_sequence
class Graph2 ( Graph ): def vertex_degree ( self , vertex ): """ The degree of a acme is the add up of edges connecting it, i.e. the number of adjacent vertices. Loops are counted double, i.e. every occurence of vertex in the list of adjacent vertices. """ degree = len ( self . _graph_dict [ vertex ]) if apex in mortal . _graph_dict [ vertex ]: degree += 1 return grade def find_isolated_vertices ( self ): """ returns a list of marooned vertices. """ graph = self . _graph_dict sporadic = [] for vertex in graphical record : photographic print ( isolated , vertex ) if not graph [ vertex ]: isolated += [ vertex ] return isolated def Delta ( self ): """ the maximum degree of the vertices """ max = 0 for peak in self . _graph_dict : vertex_degree = self . vertex_degree ( vertex ) if vertex_degree > max : max = vertex_degree return max def degree_sequence ( self ): """ calculates the degree episode """ seq = [] for vertex in self . _graph_dict : seq . append ( self . vertex_degree ( vertex )) seq . sort out ( reverse = True ) issue tuple ( seq )
g = { "a" : { "d" , "f" }, "b" : { "c" }, "c" : { "b" , "c" , "d" , "e" }, "d" : { "a" , "c" }, "e" : { "c" }, "f" : { "d" } } graphical record = Graph2 ( g ) graphical record . degree_sequence ()
OUTPUT:
Net ball's have a look at the other graph:
g = { "a" : { "d" , "f" }, "b" : { "c" }, "c" : { "b" , "c" , "d" , "e" }, "d" : { "a" , "c" , "f" }, "e" : { "c" }, "f" : { "a" , "d" } } graph = Graph2 ( g ) graph . degree_sequence ()
OUTPUT:
Draw Directed Graph Python Graph-tool
Source: https://python-course.eu/applications-python/graphs-python.php
0 Response to "Draw Directed Graph Python Graph-tool"
Post a Comment