备战数学建模十图论之二边逐次修正法

找最小圈,然后类似破圈法求最小生成树解决最小旅行商为题的方案

import numpy as np
import networkx as nx
from numpy import inf
from matplotlib import pyplot as plt

def ebzcxz(D, H):
    # 计算初始H圈权值
    W = 0
    for i, j in zip(H, H[1:] + [H[0]]):
        W += D[i, j]
    print('初始H圈为:', [i + 1 for i in H], '权值和为;', W)

    # 计算顶点数
    N = D.shape[0]

    # 初始化迭代次数
    k_iter = 1

    while 1:
        # 取出H圈中一对相邻点
        for i1, j1 in zip(H, H[1:] + [H[0]]):
            # 取出H圈中另一对相邻点
            for i2, j2 in zip(H, H[1:] + [H[0]]):
                if (H.index(i2) - H.index(j1)) >= 1:
                    indi1, indj1, indi2, indj2 = H.index(i1), H.index(j1), H.index(i2), H.index(j2)

                    # 计算原H圈和改H圈不同路径位置的权和
                    ## 原H圈
                    origin = 0
                    for k in range(indi1, indi2):
                        origin += D[H[k], H[k + 1]]
                    origin += D[i2, j2]

                    ## 改H圈
                    new = 0
                    for k in range(indi2, indj1, -1):
                        new += D[H[k], H[k - 1]]
                    new += (D[i1, i2] + D[j1, j2])

                    # 改后的权和小于原权和则更新H圈和权
                    if new < origin:
                        W = W - origin + new
                        H = [H[indi1], H[indi2]] + list(reversed(H[indj1:indi2])) + (
                            H[indj2:] if indj2 != 0 else []) + H[:indi1]

                        print('第', k_iter, '次迭代产生的新H圈:', [i + 1 for i in H], '权值和为:', W)
                        k_iter += 1
                        break
            else:
                continue
            break
        else:
            break
def drawMat(A):
    '''
    画无向赋权图
    created by yzy
    2022.8.3
    '''
    # A=np.mat([[0,3,0,2,0],
    #    [3,0,2,1,0],
    #    [0,2,0,0,5],
    #    [2,1,0,0,4],
    #    [0,0,5,4,0]]) #邻接矩阵
    G=nx.Graph(A) #无向赋权图
    pos=nx.shell_layout(G) #布局设置
    w=nx.get_edge_attributes(G,"weight") #获取权重
    nx.draw_networkx(G=G,pos=pos,node_size=260) #画网络图
    nx.draw_networkx_edge_labels(G=G,pos=pos,font_size=12,edge_labels=w) #标注权重
    plt.show()

# 输出距离矩阵D,这里是无向图
D = np.array([
    [0, 56, 35, 2, 51, 60],
    [56, 0, 21, 57, 78, 70],
    [35, 21, 0, 36, 68, 68],
    [2, 57, 36, 0, 51, 61],
    [51, 78, 68, 51, 0, 13],
    [60, 70, 68, 61, 13, 0]
])
H = list(range(D.shape[0]))
ebzcxz(D, H)
drawMat(D)
# 输出距离矩阵D,此处是有向图即U12=25,U21=5
C = np.array([
    [0, 25, 40, 31, 27],
    [5, 0, 17, 30, 25],
    [19, 15, 0, 6, 1],
    [9, 50, 24, 0, 6],
    [22, 8, 7, 10, 0]
])
Q = list(range(C.shape[0]))
ebzcxz(C, Q)
# drawMat(D)画图函数画不了有向图

运行结果为

 

初始H圈为: [1, 2, 3, 4, 5, 6] 权值和为; 237
第 1 次迭代产生的新H圈: [1, 4, 3, 2, 5, 6] 权值和为: 210
第 2 次迭代产生的新H圈: [2, 6, 5, 1, 4, 3] 权值和为: 193
第 3 次迭代产生的新H圈: [5, 4, 1, 3, 2, 6] 权值和为: 192
初始H圈为: [1, 2, 3, 4, 5] 权值和为; 76
第 1 次迭代产生的新H圈: [3, 5, 4, 1, 2] 权值和为: 62

有个地方不完善,求初始圈的方法太固定了,应该多找几种初始圈然后分别二边逐次修正取最优方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值