python_使用Floyd算法计算深圳地铁历年最短路径

from itertools import permutations

from utils.read_write import readJson,  writeOneJSON
import pandas as pd

subway_dict = []
transfer_dict = []
def getRoute(year):
    src = r'D:\data\地铁数据\SZ_Metro\min_way\route_time\\'
    try :
        yearStop = pd.read_csv(src + 'route_time_length_{}.csv'.format(year),usecols=[0,6,7,10],encoding='gbk')
    except Exception as e:
        yearStop = pd.read_csv(src + 'route_time_length_{}.csv'.format(year), usecols=[0, 6, 7, 10], encoding='utf-8')
    for feature in yearStop.itertuples(index=False):
        line = str(int(getattr(feature,'Layer').split('号')[0]))
        SStation = getattr(feature,'SStation')
        EStation = getattr(feature,'EStation')
        Length_Dow = getattr(feature,'Length_Dow')
        start = line+'-'+SStation
        end = line+'-'+EStation
        subway_dict.append([start,end,Length_Dow])

transfer = {}

src = 'D:\学习文件\项目文件\方舆地铁分析系统\data\SZ_Metro_LineSUM_Stoppoint\\'
def getTransfer(year):
    #  站点编号	站点名称		线路  	是否换乘站
    station = pd.read_csv('D:\data\地铁数据\SZ_Metro\metro_station_2020.txt', sep='\t',
                            usecols=[1, 2, 4, 5],
                            encoding='gbk')
    yearStop = readJson(src + 'SZ_Metro_LineSUM_Stoppoint_{}_GCJ02.json'.format(year))
    features = yearStop['features']
    for feature in features:
        properties = feature['properties']
        CName = properties['CName']
        change = station[station['站点名称'] == CName]
        if change.shape[0]>0:
            changeS = change.iat[0, 3]
            if changeS == '是':
                NAME = properties['NAME']
                linename = str(int(NAME.split('-')[0]))
                line_station = linename+'-'+CName
                if CName not in transfer.keys():
                    transfer[CName] = []
                transfer[CName].append(line_station)
    # 列举排列结果[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
    data4 = list(permutations([i for i in range(0,4)],2))
    for key in transfer.keys():
        data = transfer[key]
        if  len(data) ==2 :
            transfer_dict.append([data[1],data[0],120])
            transfer_dict.append([data[0], data[1],120])
        elif len(data) ==3:
            transfer_dict.append([data[1], data[0],180])
            transfer_dict.append([data[0], data[1],180])
            transfer_dict.append([data[0], data[2],180])
            transfer_dict.append([data[2], data[0],180])
            transfer_dict.append([data[1], data[2],180])
            transfer_dict.append([data[2], data[1],180])
        elif len(data) ==4:
            for one in data4:
                transfer_dict.append([data[one[0]], data[one[1]],240])

# print(transfer_dict)

'''
弗洛伊德算法(Floyd算法)
'''
class Vertex:
    def __init__(self, key):
        self.id = key
        self.connectedTo = {}

    def addNeighbor(self, nbr, weight=0):
        self.connectedTo[nbr] = weight

    def __str__(self):
        return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self, nbr):
        return self.connectedTo[nbr]


class Graph:
    def __init__(self):
        self.vertList = {}
        self.numVertices = 0

    def addVertex(self, key):
        self.numVertices = self.numVertices + 1
        newVertex = Vertex(key)
        self.vertList[key] = newVertex
        return newVertex

    def getVertex(self, n):
        if n in self.vertList:
            return self.vertList[n]
        else:
            return None

    def __contains__(self, n):
        return n in self.vertList

    def addEdge(self, f, t, cost=0):
        if f not in self.vertList:
            nv = self.addVertex(f)
        if t not in self.vertList:
            nv = self.addVertex(t)
        self.vertList[f].addNeighbor(self.vertList[t], cost)

    def getVertices(self):
        return self.vertList.keys()

    def __iter__(self):
        return iter(self.vertList.values())


def Floyd(Graph, ShortestPath):
    global path

    NodeNum = len(Graph)

    lastShortestDistance = [[0 for i in range(NodeNum)] for j in range(NodeNum)]

    currentShortestDistance = [[0 for i in range(NodeNum)] for j in range(NodeNum)]

    path = [[0 for i in range(NodeNum)] for j in range(NodeNum)]
    for i in range(NodeNum):
        for j in range(NodeNum):
            path[i][j] = j

    for i in range(NodeNum):
        for j in range(NodeNum):
            lastShortestDistance[i][j] = Graph[i][j]
            currentShortestDistance[i][j] = lastShortestDistance[i][j]

    for k in range(NodeNum):
        for i in range(NodeNum):
            for j in range(NodeNum):
                if lastShortestDistance[i][j] > lastShortestDistance[i][k] + lastShortestDistance[k][j]:
                    currentShortestDistance[i][j] = lastShortestDistance[i][k] + lastShortestDistance[k][j]
                    path[i][j] = path[i][k]
            lastShortestDistance = currentShortestDistance

    for i in range(NodeNum):
        for j in range(NodeNum):
            # if i==j:
            #     ShortestPath[i][j]=0
            # else:
            ShortestPath[i][j] = currentShortestDistance[i][j]

    print("path is: ", path)
    print("shortestPath is: ", ShortestPath)
    # print(currentShortestDistance)
    return None

def printPath(i, j, shortestPath, path):
    print(zhandian[i] + "----" + zhandian[j] + "\n最短时间:" + str(shortestPath[i][j]) + "s\n路径:\n" + zhandian[i])
    temp = path[i][j]
    odName = zhandian[i] + "_" + zhandian[j]
    jsonData = {}
    routeSplitData = [zhandian[i]]
    while (temp != j):
        routeSplitData.append(zhandian[temp])
        print("-->" + zhandian[temp])
        temp = path[temp][j]
    routeSplitData.append(zhandian[j])
    jsonData[odName] = routeSplitData
    mainJson.append(jsonData)
    print("-->" + zhandian[j])

if __name__ == "__main__":
    save = 'D:\data\地铁数据\SZ_Metro\min_way\min_route_floyd\\'
    mainJson = []
    for i in range(2020,2021):
        year = str(i)
        getRoute(year)
        getTransfer(year)
        g = Graph()
        vel = 10  # 地铁的速度 m/s
        for x in subway_dict:
            g.addEdge(x[0], x[1], int(float(x[2]) / vel))  # 由距离得到时间
            g.addEdge(x[1], x[0], int(float(x[2]) / vel))  # 双向都有
        for x in transfer_dict:
            g.addEdge(x[0], x[1], int(float(x[2]))) # 换站给的直接就是时间
        # print(len(g.getVertices()))  #打印图中顶点数
        # print(g.getVertices()) #打印图中所有的顶()点
        zhandian = []
        for i in g.getVertices():
            zhandian.append(i)
        zhandian = tuple(list(zhandian))
        x = float('inf')
        matrix = [[x for i in range(338)] for i in range(338)]
        for i in range(338):
            matrix[i][i] = 0
        for v in g:  # 对图中的每一个顶点,获取与它有连接关系的顶点
            # print(v)
            for w in v.getConnections():
                # print("( %s , %s )" % (v.getId(), w.getId()))
                # print("Time:%s" % v.getWeight(w)) #获取相邻两个顶点之间的时间s
                # print(zhandian.index(w.getId()))
                time = v.getWeight(w)
                matrix[zhandian.index(v.getId())][zhandian.index(w.getId())] = time
                # matrix[i][j]=time
                # j+=1
            # i+=1
            # pass
        # 除了每一个顶点到自身的距离不对外,其它路径啥的都没问题

        # graph=[[0,1,1,10],[1,0,10,10],[1,10,0,1],[10,10,1,0]]
        # graph=[[0,5,7,0,3],[5,0,0,4,8],[7,0,0,2,1],[0,4,2,0,6],[3,8,1,6,0]] #图的邻接表示
        # graph=[[0,12,0,0,0,16,14],[12,0,10,0,0,7,0],[0,10,0,3,5,6,0],[0,0,3,0,4,0,0],[0,0,5,4,0,2,8],[16,7,6,0,2,0,9],[14,0,0,0,8,9,0]]
        graph = matrix
        nodeNum = len(graph)
        shortestPath = [[0 for i in range(nodeNum)] for j in range(nodeNum)]
        print("计算时间比较长,请耐心等待几分钟!")
        Floyd(graph, shortestPath)

        # while True:
        #     try:
        #         start = input("请输入起点: ")
        #         s = zhandian.index(start)
        #     except:
        #         start = input("请重新输入起点:")
        #         s = zhandian.index(start)
        #     try:
        #         end = input("请输入终点: ")
        #         e = zhandian.index(end)
        #     except:
        #         end = input("请重新输入终点: ")
        #         e = zhandian.index(end)
        #     if s < e:
        #         printPath(s, e, shortestPath, path)
        #     else:
        #         printPath(e, s, shortestPath, path)
        allStation = []
        yearStop = readJson(src + 'SZ_Metro_LineSUM_Stoppoint_{}_GCJ02.json'.format(year))
        features = yearStop['features']
        for feature in features:
            properties = feature['properties']
            CName = properties['CName']
            NAME = properties['NAME']
            linename = str(int(NAME.split('-')[0]))
            line_station = linename + '-' + CName
            allStation.append(line_station)
        for start in allStation:
            for end in allStation:
                if start != end:
                    s = zhandian.index(start)
                    e = zhandian.index(end)
                    printPath(s, e, shortestPath, path)
        writeOneJSON(mainJson, save + year + '.json')

如需数据示例或帮忙请私聊我!

猜你喜欢

转载自blog.csdn.net/qq_30803353/article/details/106130351