Python实现蚁群优化算法,求解旅行商问题

news2024/11/15 9:53:31

文章目录

    • 蚁群算法
    • 蚂蚁的基本变量
    • 蚂蚁的优化流程
    • 蚁群优化
    • 验证与可视化

蚁群算法

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

现有一群蚂蚁想从 A 0 A_0 A0点走到 A n A_n 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 p p,两点距离为 d d d,则蚂蚁前往该城市的概率为

p α / d β p^\alpha/d^\beta pα/dβ

其中, α \alpha α β \beta β分别叫做信息素启发因子和期望启发因子,故而在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

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

蚁群优化

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

G i j = ( x i − x j ) 2 + ( y i − y j ) 2 G_{ij} = \sqrt{(x_i-x_j)^2+(y_i-y_j)^2} Gij=(xixj)2+(yiyj)2

另一方面,蚁群优化过程中,信息素更新至关重要,其值受到两个因素影响,一是蚂蚁走过会使之增加,二则是时间流逝会使之挥发,故而需要有一个挥发系数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()

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/834893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows环境下Node.js二进制版安装教程

文章目录 前言一 下载Node.js二 设置环境变量三 配置全局安装和缓存路径四 设置仓库 前言 新版的Node.js已自带npm&#xff0c;就在Node.js下载完成解压后的文件内&#xff0c;的node_modules包中。 npm的作用&#xff1a;是对Node.js依赖的包进行管理&#xff0c;类似maven。…

使用 CausalPy 进行因果推理

这篇文章通过一个实际的例子简要介绍了因果推理&#xff0c;这个例子来自于《The Brave and True》一书&#xff0c;我们使用 CausalPy 来实现。 因果推理是从观察数据中估计因果效应的过程。对于任何给定的个体&#xff0c;我们只能观察到一种结果。另一种结果对我们来说是隐藏…

蓝牙ble tips2-UUID GATT(service和CHARACTERISTIC) profile相关概念介绍

服务和特性 低功耗蓝牙设备之间通信&#xff0c;都是基于服务和特性。一个蓝牙设备中可以包含若干个服务&#xff0c;一个服务中可以包含若干个特性&#xff0c;每一个服务或者特性都要有一个UUID。蓝牙的数据交互都是基于一个个特性进行的&#xff0c;数据交互的方式有五种&a…

超全面的高精度行星减速机结构、原理、功能以及优势解析

行星减速机是运动控制系统中连接伺服电机和应用负载的一种机械传动组件&#xff0c;具有高减速比、良好的传动特性、结构紧凑、体积小、重量轻、可靠性高、低噪音等优点&#xff0c;广泛用于电机、汽车、机器人及各种工业机械中&#xff0c;以实现高效率和稳定性。 一、什么是…

Ubuntu20.04安装ROS Noetic 版本安装记录

用的是VMWare的20.04的Ubuntu虚拟机&#xff0c;打算安装一下Noetic 版本的ROS学习一下。B站有个视频可以参考一下&#xff1a;在Ubuntu20.04上安装ROS机器人操作系统-Noetic但是基本也是参考中文文档安装&#xff0c;步骤相比网上的教程更权威Ubuntu install of ROS Noetic&am…

LeetCode--HOT100题(20)

目录 题目描述&#xff1a;48. 旋转图像&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;48. 旋转图像&#xff08;中等&#xff09; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#x…

echarts图表渐变色 + 每个柱子不同颜色设置

echarts柱状图&#xff0c;默认所有柱子都是同一个颜色&#xff0c;显示效果差强人意&#xff0c;本文介绍如果修改成为每个柱子添加不同的颜色&#xff0c;以及如何添加渐变色&#xff0c;丰富图表的显示鲜果。先看效果&#xff1a; 每个柱子颜色不同 每个柱子都有自己的渐变…

【论文阅读】基于 NeRF 的 3D 重建的批判性分析

【论文阅读】基于 NeRF 的 3D 重建的批判性分析 Abstract1. Introduction2. The State of the Art2.1. Photogrammetric-Based Methods2.2. NeRF-Based Methods 3. Analysis and Evaluation Methodology3.1. Proposed Methodology3.2. Metrics3.3. Testing Objects 4. Comparis…

HTML5(H5)的前生今世

目录 概述HTML5与其他HTML的区别CSS3与其他CSS版本的区别总结 概述 HTML5是一种用于构建和呈现网页的最新标准。它是HTML&#xff08;超文本标记语言&#xff09;的第五个版本&#xff0c;于2014年由万维网联盟&#xff08;W3C&#xff09;正式推出。HTML5的前身可以追溯到互联…

[MAUI 项目实战] 手势控制音乐播放器: 动画

吸附动画 还记的上一章节所描述的拖拽物&#xff08;pan&#xff09;和坑&#xff08;pit&#xff09;吗&#xff1f;“”吸附“”这是一个非常拟物的过程&#xff0c;当拖拽物品接近坑区域的边缘时&#xff0c;物体就会由于重力或是引力作用会滑落&#xff0c;吸附在坑里。 …

MINIO安装(centos7)

步骤1&#xff1a;安装wget 在开始安装MinIO之前&#xff0c;需要安装wget命令行工具。可以使用以下命令在CentOS系统中安装wget&#xff1a; sudo yum install wget 步骤2&#xff1a;下载MinIO wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio 将下…

最新[新手入门教程] JDK8u381的下载安装以及环境变量的配置

JAVA从入门到精通 各位新手们大家好&#xff0c;今天来为大家介绍一下JDK8u381的下载安装以及环境变量的配置 【前言】 1.是不是不知道什么是Java&#xff1f; 官方定义&#xff1a; Java是一门面向对象的高级编程语言&#xff0c;不仅吸收了C语言的各种优点&#x…

硬盘格式化后能恢复数据吗?这4个方法可以帮到你!

“前几天一不小心对硬盘进行了格式化操作&#xff0c;但是我很多重要的文件都保存在里面了呀&#xff01;硬盘格式化之后还能进行恢复吗&#xff1f;快帮帮我&#xff01;” 硬盘格式化会将存储在硬盘上的数据全部清除&#xff0c;并将文件系统重置为初始状态。那么&#xff0c…

根据省市区名字发送请求

思路 选择对应的区域其实是按照表格中的省市区的名字进行匹配 读取文件后对应的字典为&#xff1a; {台湾: {},新疆: {},港澳: {中国澳门: [凼仔岛, nan]},西藏: {昌都地区: [卡若区], 那曲地区: [nan]} } 字典解释例如 市区为空&#xff0c;就是选择省下面的全部市和区 区为空…

租赁小程序系统:为您的租赁业务带来便利与效率

租赁小程序开发适合的产品有很多种&#xff0c;下面我将介绍一些常见的产品。   租赁共享单车&#xff1a;共享单车在城市里越来越受欢迎&#xff0c;租赁小程序可以方便用户查找附近的共享单车、预订、支付和解锁等操作。   租房&#xff1a;租赁小程序可以帮助房东发布房…

2023最难就业年

跟大家正式介绍一下我自己。 本人曾在阿里&#xff0c;硅谷工作&#xff0c;百万年薪&#xff0c;大概15的工作经验&#xff0c;八年面试官经验。 前端&#xff0c;后端&#xff0c;产品&#xff0c;测试&#xff0c;运维&#xff0c;PM&#xff0c;架构&#xff0c;运营等岗…

支持北斗三、抗干扰、无高度限制的动态高精度测速北斗定位模块

为室外位置服务提供经纬度信息的GPS模块、北斗定位模块多数受限于速度&#xff0c;在高动态环境下&#xff0c;无法为车载&#xff0c;船载&#xff0c;机载等设备提供精准位置信息。为满足高动态及高速应用场景的位置服务需求&#xff0c;现SKYLAB推出一款支持北斗三&#xff…

时间复杂度接近O(n)的三种排序算法

1.桶排序 桶排序&#xff0c;顾名思义&#xff0c;会用到“桶”&#xff0c;核心思想是将要排序的数据分到几个有 序的桶里&#xff0c;每个桶内的数据再单独进行排序。桶内排完序之后&#xff0c;再把每个桶内的数据按照顺序依次 取出&#xff0c;组成的序列就是有序的了。 …

UnrealEngine - 网络同步入门

1 网络同步机制 UE 提供了强大的网络同步机制&#xff1a; RPC &#xff1a;可以在本地调用&#xff0c;对端执行属性同步&#xff1a;标记一个属性为 UPROPERTY(Replicated) 就可以自动将其修改后的值同步到客户端移动复制&#xff1a;Actor 开启了移动复制后会自动复制位置…

区块链实验室(14) - 编译FISCO-BCOS

FISCO-BCOS是一种区块链平台&#xff0c;与Hyperledger和Ethereum有些不同&#xff0c;详见FISCO BCOS 区块链 编译FISCO BCOS源码的目的是修改或者新增其中功能模块&#xff0c;进行对比实验&#xff0c;验证新想法、新创意的效果。编译的步骤很简单&#xff0c;按技术文档一…