zoukankan      html  css  js  c++  java
  • 7.Bolzmann机解决旅行商问题

    # -*- coding: utf-8 -*-
    # Filename : Boltzmann.py
    
    import operator
    from numpy import *
    import copy
    import matplotlib.pyplot as plt
    
    
    class BoltzmannNet(object):
        def __init__(self):
            self.dataMat = []
            self.MAX_ITER = 2000
            self.T0 = 1000
            self.Lambda = 0.97
            self.iteration = 0
            self.dist = []
            self.pathindx = []
            self.bestdist = 0
            self.bestpath = []
    
        # 加载数据文件
        def loadDataSet(self, fileName):
            numFeat = len(open(fileName).readline().split('	')) - 1
            dataMat = [];
            fr = open(fileName)
            for line in fr.readlines():
                lineArr = []
                curLine = line.strip().split('	')
                lineArr.append(float(curLine[0]));
                lineArr.append(float(curLine[1]));
                dataMat.append(lineArr)
            self.dataMat = mat(dataMat)
    
        def distEclud(self, matA, matB):  # 计算矩阵各向量之间的距离--欧氏距离
            ma, na = shape(matA);
            mb, nb = shape(matB);
            rtnmat = zeros((ma, nb))
            for i in range(ma):
                for j in range(nb):
                    rtnmat[i, j] = linalg.norm(matA[i, :] - matB[:, j].T)
            return rtnmat
    
        # 计算路径长度
        def pathLen(self, dist, path):
            N = len(path)
            plen = 0;
            for i in range(0, N - 1):  # 长度为N的向量,包含从1-N的整数
                plen += dist[path[i], path[i + 1]]
            plen += dist[path[0], path[N - 1]]
            return plen
    
        # 路径交换函数
        def changePath(self, old_path):
            N = len(old_path)
            if random.rand() < 0.25:  # 产生两个位置,并交换
                chpos = floor(random.rand(1, 2) * N).tolist()[0]
                new_path = copy.deepcopy(old_path)
                new_path[int(chpos[0])] = old_path[int(chpos[1])]
                new_path[int(chpos[1])] = old_path[int(chpos[0])]
            else:  # 产生三个位置,交换a-b和b-c段
                d = ceil(random.rand(1, 3) * N).tolist()[0];
                d.sort()  # 随机生成路径
                a = int(d[0]);
                b = int(d[1]);
                c = int(d[2])
                if a != b and b != c:
                    new_path = copy.deepcopy(old_path)
                    new_path[a:c - 1] = old_path[b - 1:c - 1] + old_path[a:b - 1]
                else:
                    new_path = self.changePath(old_path)
            return new_path
    
        # 玻尔兹曼函数
        def boltzmann(self, newl, oldl, T):
            return exp(-(newl - oldl) / T)
    
        # 初始化网络
        def initBMNet(self, m, n, distMat):  # 构造一个初始可行解
            self.pathindx = list(range(m))
            random.shuffle(self.pathindx);  # 随机生成每个路径
            self.dist.append(self.pathLen(distMat, self.pathindx))  # 每个路径对应的距离
            return self.T0, self.pathindx, m
    
        # 训练样本
        def train(self):
            [m, n] = shape(self.dataMat)
            distMat = self.distEclud(self.dataMat, self.dataMat.T)  # 转换为邻接矩阵(距离矩阵)
            # T:当前温度,curpath当前路径索引    MAX_M内循环最大迭代次数
            [T, curpath, MAX_M] = self.initBMNet(m, n, distMat)
            step = 0;  # 初始化外循环迭代
            while step <= self.MAX_ITER:  # 外循环
                m = 0;  # 内循环计数器
                while m <= MAX_M:  # 内循环
                    curdist = self.pathLen(distMat, curpath)  # 计算当前路径距离
                    newpath = self.changePath(curpath)  # 产生新路径
                    newdist = self.pathLen(distMat, newpath)  # 计算新路径距离
                    if (curdist > newdist):  # 如果新路径优于原路径,选择新路径作为下一状态
                        curpath = newpath
                        self.pathindx.append(curpath)
                        self.dist.append(newdist)
                        self.iteration += 1
                    else:  # 如果新路径比原路径差,则执行随机操作
                        if random.rand() < self.boltzmann(newdist, curdist, T):
                            curpath = newpath
                            self.pathindx.append(curpath)
                            self.dist.append(newdist)
                            self.iteration += 1
                    m += 1
                step += 1
                T = T * self.Lambda  # 降温
            # 计算最优值
            self.bestdist = min(self.dist)
            indxes = argmin(self.dist)
            self.bestpath = self.pathindx[indxes]
    
        # 绘制路径
        def drawPath(self, plt, color='b'):
            m, n = shape(self.dataMat)
            px = (self.dataMat[self.bestpath, 0]).tolist()
            py = (self.dataMat[self.bestpath, 1]).tolist()
            px.append(px[0]);
            py.append(py[0])
            plt.plot(px, py, color)
    
        # 绘制散点
        def drawScatter(self, plt):
            px = (self.dataMat[:, 0]).tolist()
            py = (self.dataMat[:, 1]).tolist()
            plt.scatter(px, py, c='green', marker='o', s=60)
            i = 65
            for x, y in zip(px, py):
                plt.annotate(str(chr(i)), xy=(x[0] + 40, y[0]), color='black')
                i += 1
    
        # 绘制趋势线
        def TrendLine(self, plt, color='b'):
            plt.plot(range(len(self.dist)), self.dist, color)
    
    bmNet = BoltzmannNet()
    bmNet.loadDataSet(r"D:BoltzmanndataSet25.txt")
    bmNet.train()
    bmNet.drawScatter(plt)
    bmNet.drawPath(plt)
    plt.show()
    
    #绘制误差算法收敛曲线
    plt.show()

  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/xiaochi/p/11131005.html
Copyright © 2011-2022 走看看