In graph theory, the shortest path problem is the problem of finding a path between two vertices (or nodes) in a graph such that the sum of the weights of its constituent edges is minimized.
import numpy as np from numpy.random import rand def init(dimension): mat = (rand(dimension, dimension) * dimension ** 2) mat[(rand(dimension) * dimension).astype(int), (rand(dimension) * dimension).astype(int)] = np.inf for i in range(dimension): mat[i, i] = 0 return mat #A utility function to find the vertex with minimum distance value, from #the set of vertices not yet included in shortest path tree def minDistance(distances, sptSet, dimension): min = np.inf min_index = 0 for i in range(dimension): if((sptSet[i] == False) and (distances[i] < min)): min = distances[i] min_index = i return min_index def dijkstra(graph, dimension, source = 0): sptSet = [] distances = [] #Initialize all distances as INFINITE and stpSet[] as false for i in range(dimension): distances.append(np.inf) sptSet.append(False) #Distance of source vertex from itself is always 0 distances[source] = 0 #Find shortest path for all vertices for i in range(dimension - 1): #Pick the minimum distance vertex from the set of vertices not #yet processed. u is always equal to src in first iteration. u = minDistance(distances, sptSet, dimension) #Mark the picked vertex as processed sptSet[u] = True for j in range(dimension): if((not sptSet[j]) and (distances[u] + graph[u][j] < distances[j])): distances[j] = distances[u] + graph[u][j] return distances if __name__ == "__main__": dimension = 6 data = init(dimension) data1 = [[0, 7, 9, np.inf, np.inf, 14], [7, 0, 10, 15, np.inf, np.inf], [9, 10, 0, 11, np.inf, 2], [np.inf, 15, 11, 0, 6, 0], [np.inf, np.inf, np.inf, 6, 0, 9], [14, np.inf, 2, np.inf, 9, 0]] data3 = [[0, 4, np.inf, np.inf, np.inf, np.inf, np.inf, 8, np.inf], [4, 0, 8, np.inf, np.inf, np.inf, np.inf, 11, np.inf], [np.inf, 8, 0, 7, np.inf, 4, np.inf, np.inf, 2], [np.inf, np.inf, 7, 0, 9, 14, np.inf, np.inf, np.inf], [np.inf, np.inf, np.inf, 9, 0, 10, np.inf, np.inf, np.inf], [np.inf, np.inf, 4, np.inf, 10, 0, 2, np.inf, np.inf], [np.inf, np.inf, np.inf, 14, np.inf, 2, 0, 1, 6], [8, 11, np.inf, np.inf, np.inf, np.inf, 1, 0, 7], [np.inf, np.inf, 2, np.inf, np.inf, np.inf, 6, 7, 0]] print(dijkstra(data1, dimension, 0))
而起点向量定义如下:
列向量与邻接矩阵A(N*N)的第j列相加,然后取最小值,表示经过k条路径到达第j个结点的最短路径,公式表示如下:
也可以写成:
由此,可以得到通式:
import numpy as np from numpy.random import rand def shortestPath(adjacencyMat, distances, dimension): for it in range(dimension): # for i in range(n): # distances[i] = np.min(distances + adjacencyMat[:, i]) distances = (distances + adjacencyMat).min(axis = 0).reshape(dimension, 1) # print(distances) return distances ####################################################################################################### # distances[v] = |0 if v = startVertex # |np.inf otherwise # # adjacencyMat[u, v] = |k if u -> v, and weight = k # |0 if i == j # |np.inf if u -/> v ####################################################################################################### def init(dimension, startVertex): distances = np.zeros((dimension, 1)) mat = (rand(dimension, dimension) * dimension) mat[(rand(dimension) * dimension).astype(int), (rand(dimension) * dimension).astype(int)] = np.inf for i in range(dimension): distances[i] = np.inf mat[i, i] = 0 distances[startVertex] = 0 return mat, distances if __name__ == "__main__": startVertex = 0 dimension = 4 adjacencyMat, distances = init(dimension, startVertex) adjacencyMat2 = np.array([[0,2,4,2],[np.inf,0,1,0],[3,np.inf,0,np.inf],[1,np.inf,2,0]]) adjacencyMat3 = np.array([[ 0 , 3.08968315, np.inf , np.inf ], [ 0.21511113 , 0 , 1.52008847 , 3.66431105], [ 2.50440191 , np.inf , 0 , 3.35943021], [ 3.84022903 , np.inf , 0.5134998 , 0 ]]) adjacencyMat4 = np.array([[0,1,2,np.inf],[1,0,2,4],[2,2,0,3],[np.inf,4,3,0]]) result = shortestPath(adjacencyMat3, distances, dimension) print(result.T)
基于矩阵运算实现的图算法,有以下几点优势: