05蚁群算法

文章介绍了蚁群算法的基本原理,通过模拟蚂蚁寻找食物的过程来优化路径选择。蚁群算法应用于旅行商问题,寻找遍历所有城市的最短路径。Python代码展示了算法的具体实现,包括距离矩阵计算、蚂蚁路径选择和信息素更新等步骤,并提供了动态可视化结果。
摘要由CSDN通过智能技术生成

蚁群算法

原理介绍

  • 1,若蚂蚁从A点出发,速度相同,食物在D点,则它可能随机选择路线ABD或ACD。假设初始时每条路线分配一只蚂蚁,每个时间单位行走一步。图5.1所示为经过8个时间单位时的情形:走路线ABD的蚂蚁到达终点;而走路线ACD的蚂蚁刚好走到C点,为一半路程。如图所示:
    Alt
  • 2,图5.2表示从开始算起,经过16个时间单位时的情形:走路线ABD的蚂蚁到达终点后得到食物又返回了起点A,而走路线ACD的蚂蚁刚好走到D点。
    Alt
  • 3,假设蚂蚁每经过一处所留下的信息素为1个单位,则经过32个时间单位后,所有开始一起出发的蚂蚁都经过不同路径从D点取得了食物。此时ABD的路线往返了2趟,每一处的信息素为4个单位;而ACD的路线往返了一趟,每一处的信息素为2个单位,其比值为2∶1。
  • 4,寻找食物的过程继续进行,则按信息素的指导,蚁群在ABD路线上增派一只蚂蚁(共2只),而ACD路线上仍然为一只蚂蚁。再经过32个时间单位后,两条线路上的信息素单位积累为12和4,比值为3∶1。
  • 5,若按以上规则继续,蚁群在ABD路线上再增派一只蚂蚁(共3只),而ACD路线上仍然为一只蚂蚁。再经过32个时间单位后,两条线路上的信息素单位积累为24和6,比值为4∶1。
  • 6,若继续进行,则按信息素的指导,最终所有的蚂蚁都会放弃ACD路线,而选择ABD路线。这也就是前面所提到的正反馈效应。

蚁群算法求解旅行商

我们的任务是找到一条线路遍历所有城市的路程最短,这就是旅行商问题,城市坐标数据如下:

Alt

蚁群算法流程图

Alt

Python重写

import numpy as np
import pandas as pd
from numpy import random
import matplotlib
import matplotlib.pyplot as plt


class ACO:
    def __init__(self,m,alpha,beta,rho,G,Q,data):
        '''
        :param m: 蚂蚁个数
        :param alpha: 信息素重要程度
        :param beta: 启发式因子重要程度
        :param rho: 信息素蒸发系数
        :param G: 最大迭代次数
        :param Q: 信息数增加强度系数
        :param data: 坐标矩阵
        '''
        self.m = m
        self.alpha = alpha
        self.beta = beta
        self.rho = rho
        self.G = G
        self.Q = Q
        self.data = data

    # 两点直接距离公式
    def cd(self,x1, x2):
        d = (sum((x1 - x2) ** 2)) ** 0.5
        return d

    def aco(self):
        # 第一步:初始化变量
        n = len(self.data) # 获取城市个数
        D = np.zeros((n,n)) # 城市距离矩阵
        for i in range(n): # 计算距离矩阵
            for j in range(n):
                if i == j:
                    D[i, j] = np.spacing(1)
                elif i < j:
                    D[i, j] = self.cd(self.data[i], self.data[j])
                else:
                    D[i, j] = D[j, i]

        Eta = 1/D # 启发因子,距离倒数
        Tau = np.ones((n,n)) # 信息素矩阵
        Tabu = np.zeros((self.m,n),dtype=np.int32) # 存储并记录路径生成
        R_best = np.zeros((self.G,n),dtype=np.int32) # 各代最佳路线
        L_best = np.zeros(self.G) # 各代最佳路线长度

        fig = plt.figure(figsize=(10, 5.5), dpi=100)
        for nc in range(self.G):
            # 第二步:将m只蚂蚁放到n个城市上
            t1 = random.randint(0,31,(1,round(self.m/n)*n))[0,:self.m] # 初始化m只蚂蚁第一座城市
            Tabu[:,0] = t1
            # 第三步:m只蚂蚁按概率函数选择下一座城市
            for j in range(1,n): # 下一座城市
                for i in range(self.m): # 第m只蚂蚁的选择是?
                    t5 = Tabu[i,:j]
                    arrived = t5 # 取已经访问的城市
                    candidate = np.zeros((n-j),dtype=np.int32) # 待访问的城市
                    p = np.zeros((n-j)) # 待访问的城市的概率分布
                    jc = 0
                    # 对于第m只蚂蚁,找出其未去的城市
                    for k in range(n): # n座城
                        if sum(arrived==k) == 0: # 说明第k个城市没去过
                            candidate[jc] = k
                            jc = jc + 1
                    # 计算待选城市的概率分布
                    for k in range(len(candidate)):
                        a = arrived[-1]  # 当前所在
                        b = candidate[k] # 尚未去的k
                        t2 = Tau[a][b] # 当前蚂蚁所在城市要去下一座未访问的城市k的路段信息素
                        t3 = Eta[a][b] # 当前蚂蚁所在城市要去下一座未访问的城市k的期望,距离倒数
                        p[k] = (t2**self.alpha)*(t3**self.beta) # 期望前往城市的概率公式
                    # 概率归一化
                    p = p/sum(p)
                    # 按概率原则选取下一座城市...??
                    pcum = np.cumsum(p) # 累计概率
                    t4 = random.rand()
                    select = np.where(pcum>t4)[0][0] # 概率选择???
                    to_visit = candidate[select]
                    Tabu[i,j] = to_visit

            if nc > 0:
                Tabu[0] = R_best[nc-1]  # 把上一代最好的路径赋值给第一只蚂蚁,不然不收敛。

            # 第四步:记录本次迭代最佳路线
            L = np.zeros((self.m))
            for i in range(self.m):
                R = Tabu[i] # 第i只蚂蚁的周游路径
                for j in range(n-1):
                    x0 = R[j] # 假设从x0城市去x1城市
                    x1 = R[j+1]
                    L[i] = L[i] + D[x0][x1] # 计算该条路径的总周长
                xx = R[0]
                xn = R[n-1]
                L[i] = L[i] + D[xx][xn] # 回到出发点,累计闭合圈
            L_best[nc] = min(L)
            pos = np.where(L==min(L))[0][0] # 记录该轮最短路径的位置,即第几条路径?
            R_best[nc] = Tabu[pos] # 记录该轮最短路径的位置,即第几条路径.

            # 第五步:更新信息素
            delta_tau = np.zeros((n,n))
            for i in range(self.m):
                for j in range(n-1):
                    x0 = Tabu[i][j] # 当前
                    x1 = Tabu[i][j+1] # 下一个
                    delta_tau[x0][x1] = delta_tau[x0][x1] + self.Q/L[i]
                x00 = Tabu[i][0] # 第i只蚂蚁的第一个位置
                x11 = Tabu[i][-1] # 最后一个位置
                delta_tau[x11][x11] = delta_tau[x11][x00] + self.Q/L[i] # 回来的路径的信息素更新
            Tau = (1-self.rho)*Tau + delta_tau # 信息素更新公式
            # 第六步:禁忌表清零
            Tabu = np.zeros((self.m,n),dtype=np.int32)
            ## 输出结果
            self.move_city(R_best[nc],nc)
        plt.show()

        # return L_best,R_best

    def move_city(self,p,nc):
        matplotlib.rcParams['font.family'] = 'Kaiti'
        plt.rc('legend', fontsize=16)
        plt.ion()  # 打开交互模式
        # fig = plt.figure(figsize=(10, 5.5), dpi=100)
        CK = ['b', 'y', 'g', 'r', 'k', 'c', 'm']
        k = np.random.randint(0, len(CK), 1)
        # p = np.random.permutation(31)  # 从0-31的无序下标

        data = self.data[p]  # 重新打乱数组
        x = data[:, 0]  # x轴
        y = data[:, 1]  # y轴
        start = p[0] # 起点
        stop = p[-1] # 终点
        x = np.append(x,data[stop][0])
        y = np.append(y, data[stop][1])
        x = np.append(x, data[start][0])
        y = np.append(y, data[start][1])
        plt.clf()
        plt.plot(x, y, '%s:d' % CK[k.item()], markerfacecolor='red', markersize=5, linewidth=1.8,
                 label='蚁群算法解旅行商')
        plt.xlabel('迭代次数', fontproperties='Kaiti', fontsize=14)  # 坐标轴标签设置
        plt.ylabel('旅行最短路径', fontproperties='Kaiti', fontsize=14)
        plt.title('蚁群算法最优路径迭代%d'%(nc+1),
                  fontproperties='Kaiti', fontsize=14)
        plt.annotate('起点:(%d,%d)'%(data[start][0],data[start][1]), xy=(data[start][0],data[start][1]),
                     xytext=(data[start][0]-400, data[start][1]+200),
                     fontproperties='Kaiti',
                     fontsize=12, arrowprops=dict(facecolor='green', shrink=1.5, width=1.5, headwidth=5))
        plt.annotate('终点:(%d,%d)' % (data[stop][0], data[stop][1]), xy=(data[stop][0], data[stop][1]),
                     xytext=(data[stop][0]-400, data[stop][1]+200),
                     fontproperties='Kaiti',
                     fontsize=12, arrowprops=dict(facecolor='black', shrink=1.5, width=1.5, headwidth=5))

        plt.grid(True)  # 网格
        plt.legend(loc='upper right')
        plt.pause(0.05)

        plt.ioff()
        # plt.show()




data = pd.read_excel('城市坐标数据.xlsx')
data = np.array(data)
aco = ACO(50,1,5,0.1,50,50,data)
aco.aco()

实验结果

  • 为了绘制实验动态图学习了matplotlib的动态图。非常满意的可视化结果。
    Alt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值