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

7 bridges of Koenigsberg

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

Simple Graph with an isolated node

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: ["f"]

Graphs as a Python Class

Simple Graph with with a loop

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:

(a, c, e) is a obtuse path in our graph, equally well as (a,c,e,b). (a,c,e,b,c,d) is a course but not a simple path, because the node c appears double.

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:

Simple Graph with with a loop extended

              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

Simple Graph with with a loop

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:

Simple Graph with with a loop extended

              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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel