Implementation of Dijkstra's algorithm with python

Introduction

I implemented Dijkstra's algorithm in python. I'm not used to posting, but I intend to write it as clearly as possible (a lie)

Having recently studied graph theory at university, I suddenly wanted to find the shortest path lol The code is dirty, but I hope it helps someone!

What is Dijkstra's algorithm?

Dijkstra's algorithm is an algorithm that finds the "minimum weight path". The basic idea of Dijkstra's algorithm is as follows.

  1. Divide the route with the smallest weight that has been searched for vertices into a confirmed part and an undetermined part.
  2. Update the route to the undetermined part using the value of the edge between the confirmed part.
  3. Increase the vertices of the path with the smallest weight that has been determined sequentially one by one.
  4. Perform the above operations until you know the shortest distances of all vertices.

If you don't know what you're talking about, I recommend watching the video below! Explanation of Dijkstra's algorithm of Yobinori

Tried to make it

I will introduce the code at once.

dijkstra.py


import heapq
class Map:  #Define Map class
    def __init__(self,start,goal):
        self.__start = start
        self.__goal = goal
        self.v_list =[] #[(0,s),(1,a)](weight,label) 
        self.e_list = {}  #Edge dictionary
        self.dic_v_list = []
        self.dic_e_list ={}

    #Initialize
    def add_list(self,cross_streets,load):
        for i in range(len(cross_streets)):
            if cross_streets[i]==self.__start:
                self.v_list.append((0,cross_streets[i]))
            else:
                self.v_list.append((float('inf'),cross_streets[i])) #float('inf')Is infinite(∞,'a')
        
        if self.__start <= self.__goal:
            self.e_list = load
        else:
            #(1,2):If there is 5(2,1):Add 5 to the dictionary
            for ld in load:
                self.e_list.update({(ld[1],ld[0]):load[ld]})
    
    #Function to add a way
    def load_add(self,weight,label): 
        #Determine if it is a start
        if weight != 0:
            #Find the same path as the label ex. label:2→(1,2,4)
            loads = [(k1,k2,val) for (k1,k2), val in self.e_list.items() if k2 ==label]
            #Find all paths that contain the specified label
            for load in loads:
                #Find the corresponding vertex and calculate the new weight
                for (v0,v1) in [(v0,v1) for (v0,v1) in self.dic_v_list if v1==load[0]]:
                        #Determine if the argument weight is equal to the path + vertex weight
                        if weight == v0+load[2]:
                            self.dic_e_list.update([((load[0],load[1]),load[2])])

    #Follow the path in reverse
    def back_calculation(self):
        #Substitute goal
        label=[self.__goal]
        #Follow the path from goal to start
        while label[len(label)-1] != self.__start:
            load = [(k1,k2,val) for (k1,k2), val in self.dic_e_list.items() if k2 == label[len(label)-1]] #k is, for example, s,a,b
            label.append(load[0][0])
        return label

    def dijkstra(self):
        #Loop until there are no vertices
        while len(self.v_list) > 0:
            #Find the minimum
            heapq.heapify(self.v_list)
            (weight, label) = heapq.heappop(self.v_list)

            #Seeking an adjacent road
            loads = [(k1,k2,val) for (k1,k2), val in self.e_list.items() if k1 == label]

            for load in loads:
                #Find matching weights in a list of pairs
                for (v0,v1) in [(v0,v1) for (v0,v1) in self.v_list if v1==load[1]]:   
                        #Update weights
                        if weight + load[2] <= v0:
                            list_count = self.v_list.index((v0,v1)) #Substitute the element number of the list
                            self.v_list[list_count] = (weight + load[2],v1)
            #Added fixed vertices and paths
            self.dic_v_list.append((weight,label))
            self.load_add(weight,label)

    def serach(self):
        self.dijkstra()
        return self.back_calculation()

cross_streets = [1,2,3,4,5,6,7,8]  #All intersections(vertex)List of
load = {(1,3):5,(1,2):1,(1,4):4,(2,4):2,(3,5):2,(4,5):5,(4,6):6,(5,8):1,(5,7):3,(6,7):2,(8,7):4} #All roads(Edge)Dictionary
map = Map(7,1)  #Create a Map instance
map.add_list(cross_streets,load) #Make a map
print(map.serach())

Commentary

* Only important parts will be explained.

v_list is a tuple type list of labels and vertices, and e_list is a dictionary type of edges. (For example, if the length of the side between s-t is 10, it is expressed as {(s, t): 10}) dic_v_list and dic_e_list store vertices and edges with fixed minimum weight distances.

class Map:  #Define Map class
    def __init__(self,start,goal):
        self.__start = start
        self.__goal = goal
        self.v_list =[] #[(0,s),(1,a)](label,vertex) 
        self.e_list = {}  #Edge dictionary
        self.dic_v_list = []
        self.dic_e_list ={}

The vertices and paths are passed as follows:

cross_streets = [1,2,3,4,5,6,7,8]  #All intersections(vertex)List of
load = {(1,3):5,(1,2):1,(1,4):4,(2,4):2,(3,5):2,(4,5):5,(4,6):6,(5,8):1,(5,7):3,(6,7):2,(8,7):4} #All roads(Edge)Dictionary
map = Map(7,1)

This is the function that finds the most important path with the least weight in this program. The flow is as follows. ⑴ Use heapq to find the vertex with the smallest weight. Then take it out with heapq.pop. ⑵ Store the side extending from the extracted vertex in load as a list type. (3) Compare the weights of the vertices connected to each side, and update if the weights can be updated. (4) Add the confirmed vertices and edges to dic_v_list and dic_e_list.

In other words, this function is responsible for "finding the vertices with the least weight" and "updating the weights of adjacent vertices".

    def dijkstra(self):
        #Loop until there are no vertices
        while len(self.v_list) > 0:
            #Find the minimum
            heapq.heapify(self.v_list)
            (weight, label) = heapq.heappop(self.v_list)

            #Seeking an adjacent road
            loads = [(k1,k2,val) for (k1,k2), val in self.e_list.items() if k1 == label]

            for load in loads:
                #Find matching weights in a list of pairs
                for (v0,v1) in [(v0,v1) for (v0,v1) in self.v_list if v1==load[1]]:   
                        #Update weights
                        if weight + load[2] <= v0:
                            list_count = self.v_list.index((v0,v1)) #Substitute the element number of the list
                            self.v_list[list_count] = (weight + load[2],v1)
            #Added fixed vertices and paths
            self.dic_v_list.append((weight,label))
            self.load_add(weight,label)

The rest are all extra functions. (Omit explanation)

Execution result

Try it with the following graph. グラフ2.png

They are arranged in order from goal to start, but you have successfully executed the answer.

#original data:Start 7,Goal 1
cross_streets = [1,2,3,4,5,6,7,8]  #All intersections(vertex)List of
load = {(1,3):5,(1,2):1,(1,4):4,(2,4):2,(3,5):2,(4,5):5,(4,6):6,(5,8):1,(5,7):3,(6,7):2,(8,7):4} #All roads(Edge)Dictionary
map = Map(7,1)
#Execution result
[1, 3, 5, 7]

#Of course it holds even if it is reversed
cross_streets = [1,2,3,4,5,6,7,8]  #All intersections(vertex)List of
load = {(1,3):5,(1,2):1,(1,4):4,(2,4):2,(3,5):2,(4,5):5,(4,6):6,(5,8):1,(5,7):3,(6,7):2,(8,7):4} #All roads(Edge)Dictionary
map = Map(1,7)
#Execution result
[7, 5, 3, 1]

Recommended Posts

Implementation of Dijkstra's algorithm with python
[Python3] Dijkstra's algorithm with 14 lines
Algorithm learned with Python 8th: Evaluation of algorithm
Non-recursive implementation of extended Euclidean algorithm (Python)
Algorithm in Python (Dijkstra's algorithm)
Algorithm learned with Python 13th: Tower of Hanoi
Implementation of TRIE tree with Python and LOUDS
Find the shortest path with the Python Dijkstra's algorithm
Python implementation of particle filters
Implementation of quicksort in Python
Implementation of Bulk Update with mongo-go-driver
Sorting algorithm and implementation in Python
Python implementation of self-organizing particle filters
Python algorithm
Implementation of life game in Python
Getting Started with Python Basics of Python
Life game with Python! (Conway's Game of Life)
10 functions of "language with battery" python
[With simple explanation] Scratch implementation of deep Boltzmann machine with Python ②
[With simple explanation] Scratch implementation of deep Boltzmann machine with Python ①
Implementation of original sorting in Python
Coexistence of Python2 and 3 with CircleCI (1.0)
Basic study of OpenCV with Python
Crawling with Python and Twitter API 2-Implementation of user search function
PRML Chapter 8 Product Sum Algorithm Python Implementation
Basics of binarized image processing with Python
[Examples of improving Python] Learning Python with Codecademy
Algorithm learned with Python 10th: Binary search
Algorithm learned with Python 5th: Fibonacci sequence
Algorithm learned with Python 9th: Linear search
Execute Python script with cron of TS-220
Ant book in python: Sec.2-5 Dijkstra's algorithm
Algorithm learned with Python 7th: Year conversion
Clogged with python update of GCP console ①
Algorithm learned with Python 4th: Prime numbers
Search the maze with the python A * algorithm
Algorithm learned with Python 2nd: Vending machine
Algorithm learned with Python 19th: Sorting (heapsort)
Machine learning algorithm (implementation of multi-class classification)
UnicodeEncodeError struggle with standard output of python3
Explanation and implementation of Decomposable Attention algorithm
Algorithm learned with Python 6th: Leap year
1. Statistics learned with Python 1-3. Calculation of various statistics (statistics)
Drawing with Matrix-Reinventor of Python Image Processing-
Recommendation of Altair! Data visualization with Python
Algorithm learned with Python 3rd: Radix conversion
Let's develop an investment algorithm with Python 1
Algorithm learned with Python 12th: Maze search
Comparison of matrix transpose speeds with Python
Python implementation of continuous hidden Markov model
Algorithm learned with Python 11th: Tree structure
Introduction of Python
Statistics with python
Python memorandum (algorithm)
Python with Go
Twilio with Python
Integrate with Python
Play with 2016-Python
AES256 with python
Tested with Python
Basics of Python ①