python应用——邻接Graph类实现公交换乘系统

一、题目要求

参考提供论文,用书上方式(邻接Graph类或压缩方式)实现问题的解决,将论文中的4路公交换成10路公交,自设连通方式,求解任意公交站点能否换乘?

二、思路

    10*10的矩阵表示公交站之间能否换乘,在原始矩阵中用1代表两路公交经过1次即可换乘,0代表两路公交无共同停靠点。不断做矩阵乘法,比较经过换乘后的矩阵与换乘前有何不同,与原始论文用“1*代表换乘后可连通”的设定不同的是:我采用2,3...代表需要换乘的次数,在若干次换乘后,矩阵不再改变,若此时矩阵中还有0,则该处代表的两个公交站点不可换乘。

三、调用函数及类

# -*-coding:gbk-*-
from numpy import *

class GraphError(Exception):
    pass

class
Graph: #用邻接矩阵实现基本图类
    
def __init__(self, mat, unconn = 0):#两参数:原始矩阵,初始无连接点默认值0
        
vnum = len(mat)#公交路线数目
        
for x in mat:
            if len(x) != vnum:  # 检查是否为方阵
                
raise ValueError("Argument for 'Graph'.")
        self._mat = [mat[i][:] for i in range(vnum)] # 做矩阵的拷贝
        
self._unconn = unconn
        self._vnum = vnum#共三参数:矩阵,无关联特殊值,公交路线数

    
def _invalid(self, v):  # 检查 v 是否超出矩阵范围
        
return 0 > v or v >= self._vnum

    def vertex_num(self):#获得顶点数
        
return self._vnum

    def add_vertex(self):#暂时不支持顶点数添加
        
raise GraphError("Adj-Matrix does not support 'add_vertex'.")

    def add_edge(self, vi, vj, val=1):#将从v1到v2的边加入这个图,权重数va1默认为1
        
if self._invalid(vi) or self._invalid(vj):
            raise GraphError(str(vi) + ' or ' + str(vj) + " is not a valid vertex.")
        self._mat[vi][vj] = val

    def get_edge(self, vi, vj):#得到边的权重
        
if self._invalid(vi) or self._invalid(vj):
            raise GraphError(str(vi) + ' or ' + str(vj) + " is not a valid vertex.")
        return self._mat[vi][vj]

    def out_edges(self, vi):#返回vi行连接节点表
        
if self._invalid(vi):
            raise GraphError(str(vi) + " is not a valid vertex.")
        return self._out_edges(self._mat[vi], self._unconn)

    @staticmethod
    def _out_edges(row, unconn):#构造某行连接节点表[(节点,权重)。。。]
        
edges = []
        for i in range(len(row)):
            if row[i] != unconn:
                edges.append((i, row[i]))
        return edges

    def __str__(self):#转换为字符串形式的输出:矩阵+无关联元素  map将操作运用到序列的每一个元素
        
return "[\n" + "\n".join(map(str, self.mat)) + "\n]\n" \
               + "Unconnected: " + str(self.unconn)

    def findn(self):#自定义寻找换乘次数函数
        
matpast=[self._mat[i][:] for i in range(self._vnum)]
        cishu=2
        panduanwancheng = 0
        while panduanwancheng==0 :
            matnow = zeros((self._vnum, self._vnum))
            panduanwancheng = 1
            for i in range(self._vnum):#注意range是开区间的
                
for j in range(self._vnum):
                    for k in range(self._vnum):
                        matnow[i][j]+=self._mat[i][k]*matpast[k][j]
                    if matnow[i][j]!=0 and matpast[i][j]==0:
                        matnow[i][j]=cishu#需要换乘次数
                        
panduanwancheng = 0
                    if matpast[i][j] != 0:
                        matnow[i][j]=matpast[i][j]
            cishu+=1
            matpast = [matnow[b][:] for b in range(self._vnum)]

        return matnow

 

四、主函数

def main():
    print("************************************验证自定义函数是否正确")
    mat1=[[1,1,0,0],
          [1,1,0,1],
          [1,0,1,0],
          [0,0,0,1]]
    ceshimat=Graph(mat1)
    yanzheng=ceshimat.findn()
    print(yanzheng)
    print("************************************十路公交")
    mat2=[[1,1,0,1,0,1,0,1,1,0],
          [1,1,0,0,1,1,0,1,0,1],
          [0,0,1,1,0,0,1,1,0,1],
          [0,0,1,1,0,0,1,1,0,1],
          [0,0,0,1,1,1,0,1,0,1],
          [0,0,0,1,1,1,0,1,1,1],
          [1,1,1,1,0,0,1,0,0,0],
          [0,0,0,0,1,1,0,1,0,1],
          [0,0,0,0,1,1,0,1,1,1],
          [1,1,0,0,1,1,0,1,1,1]]
    mymat = Graph(mat2)
    answer = mymat.findn()
    print(answer)
    if 0 not in answer:
        print('任意两站可连通')



if __name__=='__main__':
    main()

 

五、运行结果

C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/untitled1/10luhuancheng.py

************************************验证自定义函数是否正确

[[ 1.  1.  0.  2.]

 [ 1.  1.  0.  1.]

 [ 1.  2.  1.  3.]

 [ 0.  0.  0.  1.]]

************************************十路公交

[[ 1.  1.  2.  1.  2.  1.  2.  1.  1.  2.]

 [ 1.  1.  3.  2.  1.  1.  3.  1.  2.  1.]

 [ 2.  2.  1.  1.  2.  2.  1.  1.  2.  1.]

 [ 2.  2.  1.  1.  2.  2.  1.  1.  2.  1.]

 [ 2.  2.  2.  1.  1.  1.  2.  1.  2.  1.]

 [ 2.  2.  2.  1.  1.  1.  2.  1.  1.  1.]

 [ 1.  1.  1.  1.  2.  2.  1.  2.  2.  2.]

 [ 2.  2.  3.  2.  1.  1.  3.  1.  2.  1.]

 [ 2.  2.  3.  2.  1.  1.  3.  1.  1.  1.]

 [ 1.  1.  3.  2.  1.  1.  3.  1.  1.  1.]]

任意两站可连通

 

Process finished with exit code 0

六、结果分析

4路公交运行结果与论文所述相同,对自定义10路公交系统进行处理,结果显示:任意两站之间可连通,且换乘次数不超过3次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值