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)
基于矩阵运算实现的图算法,有以下几点优势: