python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python蚁群算法

Python实现蚁群优化算法的示例代码

作者:微小冷

蚁群算法是一种源于大自然生物世界的新的仿生进化算法,本文主要介绍了Python如何实现蚁群算法,文中通过示例代码具有一定的参考价值,感兴趣的小伙伴们可以了解一下

蚁群算法

蚁群算法是Colori A等人在1991年提出的,通过模仿蚂蚁觅食行为,抽象出信息素这一奖惩机制,从而赋予蚂蚁智能Agent的身份,使之得以在最佳路线问题中大展身手。

现有一群蚂蚁想从A0​点走到An​点,假设两点中间有多条路径可以选择,蚂蚁不知道哪条路更近,所以最开始无论选择哪条路,机会都是相等的。但是,当某一条路有蚂蚁走过之后,就会留下信息素,如果每一只蚂蚁的速度是恒定的,那么路程越短,蚂蚁在这条路上往返也就越快,反过来说,单位时间内,越短的路会有更多的蚂蚁走过,从而留下的信息素就会越多,这就是蚁群算法的基本原理了。

当不同路径均留下信息素后,蚂蚁们再行选择路线就不是等概率的了,他们会有更大的概率选择信息素更浓的路线。随着时间的推演,信息素也会挥发,从而蚂蚁们不断更新他们的路线,这个过程就是蚁群优化(Ant Clony Optimization, ACO)。

蚂蚁的基本变量

很显然,蚁群算法的前提是来一群蚂蚁对象,而蚂蚁作为一个智能体,至少要有一些记忆,需要记住以下内容

而经过初始化之后,这个蚂蚁必须得来到某个城市,所以需要一个随机选择城市的函数,下面就是一个蚂蚁所必备的初始化流程

import numpy as np
from functools import reduce
class Ant(object):
    def __init__(self, nCity, graph, pheromone):
        self.nCity = nCity          # 城市数
        self.graph = graph          # 城市地图
        self.pheromone = pheromone  # 信息素地图
        self.cityEnabled = [True] * nCity  # 尚未到达的城市标记
        self.nMove = 0              # 移动步数
        self.dTotal = 0.0           # 已经走过的距离
        self.initData()             # 初始化出生点
    # 随机选择城市
    def randCity(self):
        return np.random.randint(0,self.nCity-1) 
    # 初始化
    def initData(self):
        self.nowCity = self.randCity()          # 随机选择一个城市
        self.path = [self.nowCity]              # 保存当前走过的城市
        self.cityEnabled[self.nowCity] = False  # 当前城市不再探索
        self.nMove = 1                          # 初始时的移动计数

蚂蚁的优化流程

某只蚂蚁在初始化之后,就要通过它敏锐的“嗅觉”选择下一个城市,直到走完所有城市为止。而选择城市时,需要用到信息素地图作为判断依据。信息素浓度为p,两点距离为d,则蚂蚁前往该城市的概率为

其中,α和β分别叫做信息素启发因子和期望启发因子,故而在Ant类中新建方法:

# 计算到达第i个城市的概率
def getOneProb(self, i):
    ALPHA = 1.0
    BETA = 2.0
    dis = self.graph[self.nowCity][i]
    phe = self.pheromone[self.nowCity][i]
    # 计算移动到该城市的概率
    if not self.cityEnabled[i]: return 0  
    else: return pow(phe, ALPHA) * pow(1/dis, BETA)

有了这个,就可以得到去所有城市的概率,然后随机则取

def choiceNext(self):
    # 前往所有城市的概率
    pSlct = [self.getOneProb(i) for i in range(self.nCity)]
    pSum = np.cumsum(pSlct)
    # 生成一个随机数,这个随机数在pSum中落入的区间就是选择的城市
    pTemp = np.random.uniform(0.0, pSum[-1])
    return  np.searchsorted(pSum, pTemp)

在选中接下来前往的城市之后,就要动身前往

# 移动到新的城市
def moveTo(self, city):
    self.path.append(city)          # 添加目标城市
    self.cityEnabled[city] = False  # 目标城市不可再探索
    # 总路程增加当前城市到目标城市的距离
    self.dTotal += self.graph[self.nowCity][city]  
    self.nowCity = city             # 更新当前城市
    self.nMove += 1                 # 移动次数

唯一需要注意的是,旅行商问题要求走一圈,也就是说,当走遍所有城市之后,要记得把第一个城市和最后一个城市的距离添加到全部路程当中,故其总的搜索流程如下

def run(self):
    self.initData()
    while self.nMove < self.nCity:
        next_city = self.choiceNext()
        self.moveTo(next_city)
    self.dTotal += self.graph[self.path[0]][self.path[-1]]
    return self.dTotal

至此,就实现了一个蚂蚁类。

蚁群优化

有了蚂蚁,那么接下来就要有蚁群,以及适用于蚁群算法的城市网点。设城市坐标序列为xi​和yi​,则根据这组坐标点的个数就是城市数nCity,而城市距离矩阵可表示为

另一方面,蚁群优化过程中,信息素更新至关重要,其值受到两个因素影响,一是蚂蚁走过会使之增加,二则是时间流逝会使之挥发,故而需要有一个挥发系数RHO。信息素更新函数如下

# 更新信息素
RHO = 0.5       # 信息素挥发系数
def updatePheromone(nCity, pheromone, ants):
    # 初始化蚂蚁在两两城市间的信息素, 50行50列
    temp = np.zeros([nCity, nCity])
    # 遍历每只蚂蚁对象
    for ant in ants:
        for i in range(1, nCity):  # 遍历该蚂蚁经过的每个城市
            st, ed = ant.path[i-1], ant.path[i]
            # 在两个城市间留下信息素,浓度与总距离成反比
            temp[st, ed] += Q / ant.dTotal
            temp[ed, st] = temp[st, ed]  # 信息素矩阵轴对称
    return pheromone * RHO + temp

至此,万事俱备,只欠东风,蚁群优化算法的主体程序如下

import copy
# xs, ys为城市的x和y坐标
# nAnts为蚂蚁个数, nIter为迭代次数
def aco(xs, ys, nAnts, nIter):
    nCity = len(xs)
    xMat, yMat = xs-xs.reshape(-1,1), ys-ys.reshape(-1,1)
    graph = np.sqrt(xMat**2 + yMat**2)
    pheromone = np.ones([nCity, nCity]) # 信息素矩阵
    ants = [Ant(nCity, graph, pheromone) for _ in range(nAnts)]
    best = Ant(nCity, graph, pheromone)  # 初始化最优解
    best.dTotal = np.inf
    bestAnts = []           # 输出并保存
    for i in range(nIter):
        for ant in ants:
            ant.pheromone = pheromone
            ant.run()
            # 与当前最优蚂蚁比较步行的总距离
            if ant.dTotal < best.dTotal:
                # 更新最优解
                best = copy.deepcopy(ant)
        print(f"{i},{best.dTotal}")
        # 更新信息素
        pheromone = updatePheromone(nCity, pheromone, ants)
        bestAnts.append(best)
    return bestAnts

验证与可视化

又到了激动人心的验证时刻。根据aco函数的输入参数来看,主要需要一组空间坐标,设置如下

# 每个城市的x和y坐标
xs = np.array([
    178,272,176,171,650,499,267,703,408,437,491,74,532,
    416,626,42,271,359,163,508,229,576,147,560,35,714,
    757,517,64,314,675,690,391,628,87,240,705,699,258,
    428,614,36,360,482,666,597,209,201,492,294])
ys = np.array([
    170,395,198,151,242,556,57,401,305,421,267,105,525,
    381,244,330,395,169,141,380,153,442,528,329,232,48,
    498,265,343,120,165,50,433,63,491,275,348,222,288,
    490,213,524,244,114,104,552,70,425,227,331])
xMat, yMat = xs-xs.reshape(-1,1), ys-ys.reshape(-1,1)
distance_graph = np.sqrt(xMat**2 + yMat**2)

最后main函数为

if __name__ == '__main__':
    bAnts = aco(xs, ys, 50, 300)
    index = bAnts[-1].path
    index = index + [index[0]]
    plt.plot(xs[index], ys[index], marker='*')
    plt.tight_layout()
    plt.show()

最终优化后的蚂蚁路线如下

到此这篇关于Python实现蚁群优化算法的示例代码的文章就介绍到这了,更多相关Python蚁群算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文