python闭环最短路径_深度学习经典算法 | 蚁群算法解析

蚁群算法基本思想

蚁群算法的基本原理来源于自然界中蚂蚁觅食的最短路径问题。根据昆虫学家的观察,发现自然界的蚂蚁虽然视觉不发达,但它可以在没有任何提示的情况下找到从食物源到巢穴的最短路径,并且能在环境发生变化(如原有路径上有了障碍物)后,自适应地搜索新的最佳路径。蚂蚁是如何做到这一点的呢?

原来,蚂蚁在寻找食物源时,能在其走过的路径上释放一种蚂蚁特有的分泌物一信息激素一也可称之为信息素,使得一定范围内的其他蚂蚁能够察觉到并由此影响它们以后的行为。当一些路径上通过的蚂蚁越来越多时,其留下的信息素也越来越多,以致信息素强度增大(当然,随时间的推移会逐渐减弱),所以蚂蚁选择该路径的概率也越高,从而更增加了该路径的信息素强度,这种选择过程被称之为蚂蚁的自催化行为。由于其原理是一种正反馈机制.因此,也可将蚂蚁王国理解为所谓的增强型学习系统。

在自然界中,蚁群的这种寻找路径的过程表现为一种正反馈过程,“蚁群算法”就是模仿生物学蚂蚁群觅食寻找最优路径原理衍生出来的。

蚁群算法数学模型

应该说前面介绍的蚁群算法只是一种算法思想,要是想真正应用该算法,还需要针对一个特定问题, 建立相应的数学模型。现仍以经典的TSP问题为例,来进一步阐述如何基于蚁群算法来求解实际问题。

对于TSP问题,为不失一般性,设整个蚂蚁群体中蚂蚁的数量为m,城市的数量为n,城市i与城市j之间的距离为

(i,j=1,2,…,n),t时刻城市i与城市j连接路径上的信息素浓度为

(t)。初始时刻,蚂蚁被放置在不同的城市里,且各城市间连接路径上的信息素浓度相同,不妨设

(0)=

(0)。然后蚂蚁将按一定概率选择线路,不妨设

为t时刻蚂蚁k从城市i转移到城市j的概率。我们知道,“蚂蚁TSP”策略会受到两方面的左右,首先是访问某城市的期望,另外便是其他蚂蚁释放的信息素浓度,所以定义:

其中,

为启发函数,表示蚂蚁从城市i转移到城市j的期望程度:

(k=1, 2, …, m)为蚂蚁k待访问城市集合,开始时,

中有n一1个元素,即包括除了蚂蚁k出发城市的其他多有城市, 随着时间的推移,

中的元素越来越少,直至为空;a为信息素重要程度因子,简称信息度因子。其值越大,表示信息影响强度越大;

为启发函数重要程度因子,简称启发函数因子,其值越大,表明启发函数影响越大。

在蚂蚁遍历城市的过程中,与实际情况相似的是,在蚂蚁释放信息素的同时,各个城市间连接路径上的信息素的强度也在通过挥发等方式逐渐消失。为了描述这一特征,不妨令p(0

其中,

为第k只蚂蚁在城市i与城市j连接路径上释放信息素而增加的信息素浓度;

为所有蚂蚁在城市i与城市j连接路径上释放信息素而增加的信息素浓度。

一般

的值可由ant cycle system模型进行计算:

其中,Q为信息素常数,表示蚂蚁循环一次所释放的信息素总量;

为第k只蚂蚁经过路径的总长度。

蚁群算法流程

用蚁群算法求解TSP问题的算法流程如下图所示,具体每步的含义如下:步骤1:对相关参数进行初始化,包括蚁初始化群规模、信息素因子、启发函数因子、信息素、挥发因子、信息素常数、最大迭代次数等,以及将数据读人程序,并对数据进行基本的处理,如将城市的坐标位置,转为城市间的矩阵。

步骤2:随机将蚂蚁放于不同的出发点,对每个蚂蚁计算其下一个访问城市,直至所更新信息素表有蚂蚁访问完所有城市。

步骤3:计算各个蚂蚁经过的路径长度

,记录当前迭代次数中的最优解,同时对各个城市连接路径上的信息素浓度进行更新。

步骤4:判断是否达到最大迭代次数,若否,则返回步骤2,否则终止程序。

步骤5:输出程序结果,并根据需要输出程序寻优过程中的相关指标,如运行时间、收敛迭代次数等。

python简单实现

import numpy as np

import matplotlib.pyplot as plt

# 建立“蚂蚁”类

class Ant(object):

def __init__(self, path):

self.path = path # 蚂蚁当前迭代整体路径

self.length = self.calc_length(path) # 蚂蚁当前迭代整体路径长度

def calc_length(self, path_): # path=[A, B, C, D, A]注意路径闭环

length_ = 0

for i in range(len(path_)-1):

delta = (path_[i].x - path_[i+1].x, path_[i].y - path_[i+1].y)

length_ += np.linalg.norm(delta)

return length_

@staticmethod

def calc_len(A, B): # 静态方法,计算城市A与城市B之间的距离

return np.linalg.norm((A.x - B.x, A.y - B.y))

# 建立“城市”类

class City(object):

def __init__(self, x, y):

self.x = x

self.y = y

# 建立“路径”类

class Path(object):

def __init__(self, A): # A为起始城市

self.path = [A, A]

def add_path(self, B): # 追加路径信息,方便计算整体路径长度

self.path.append(B)

self.path[-1], self.path[-2] = self.path[-2], self.path[-1]

# 构建“蚁群算法”的主体

class ACO(object):

def __init__(self, ant_num=50, maxIter=300, alpha=1, beta=5, rho=0.1, Q=1):

self.ants_num = ant_num # 蚂蚁个数

self.maxIter = maxIter # 蚁群最大迭代次数

self.alpha = alpha # 信息启发式因子

self.beta = beta # 期望启发式因子

self.rho = rho # 信息素挥发速度

self.Q = Q # 信息素强度

###########################

self.deal_data('coordinates.dat') # 提取所有城市的坐标信息

###########################

self.path_seed = np.zeros(self.ants_num).astype(int) # 记录一次迭代过程中每个蚂蚁的初始城市下标

self.ants_info = np.zeros((self.maxIter, self.ants_num)) # 记录每次迭代后所有蚂蚁的路径长度信息

self.best_path = np.zeros(self.maxIter) # 记录每次迭代后整个蚁群的“历史”最短路径长度

###########################

self.solve() # 完成算法的迭代更新

self.display() # 数据可视化展示

def deal_data(self, filename):

with open(filename, 'rt') as f:

temp_list = list(line.split() for line in f) # 临时存储提取出来的坐标信息

self.cities_num = len(temp_list) # 1. 获取城市个数

self.cities = list(City(float(item[0]), float(item[1])) for item in temp_list) # 2. 构建城市列表

self.city_dist_mat = np.zeros((self.cities_num, self.cities_num)) # 3. 构建城市距离矩阵

for i in range(self.cities_num):

A = self.cities[i]

for j in range(i, self.cities_num):

B = self.cities[j]

self.city_dist_mat[i][j] = self.city_dist_mat[j][i] = Ant.calc_len(A, B)

self.phero_mat = np.ones((self.cities_num, self.cities_num)) # 4. 初始化信息素矩阵

# self.phero_upper_bound = self.phero_mat.max() * 1.2 ###信息素浓度上限

self.eta_mat = 1/(self.city_dist_mat + np.diag([np.inf]*self.cities_num)) # 5. 初始化启发函数矩阵

def solve(self):

iterNum = 0 # 当前迭代次数

while iterNum < self.maxIter:

self.random_seed() # 使整个蚁群产生随机的起始点

delta_phero_mat = np.zeros((self.cities_num, self.cities_num)) # 初始化每次迭代后信息素矩阵的增量

##########################################################################

for i in range(self.ants_num):

city_index1 = self.path_seed[i] # 每只蚂蚁访问的第一个城市下标

ant_path = Path(self.cities[city_index1]) # 记录每只蚂蚁访问过的城市

tabu = [city_index1] # 记录每只蚂蚁访问过的城市下标,禁忌城市下标列表

non_tabu = list(set(range(self.cities_num)) - set(tabu))

for j in range(self.cities_num-1): # 对余下的城市进行访问

up_proba = np.zeros(self.cities_num-len(tabu)) # 初始化状态迁移概率的分子

for k in range(self.cities_num-len(tabu)):

up_proba[k] = np.power(self.phero_mat[city_index1][non_tabu[k]], self.alpha) * \

np.power(self.eta_mat[city_index1][non_tabu[k]], self.beta)

proba = up_proba/sum(up_proba) # 每条可能子路径上的状态迁移概率

while True: # 提取出下一个城市的下标

random_num = np.random.rand()

index_need = np.where(proba > random_num)[0]

if len(index_need) > 0:

city_index2 = non_tabu[index_need[0]]

break

ant_path.add_path(self.cities[city_index2])

tabu.append(city_index2)

non_tabu = list(set(range(self.cities_num)) - set(tabu))

city_index1 = city_index2

self.ants_info[iterNum][i] = Ant(ant_path.path).length

if iterNum == 0 and i == 0: # 完成对最佳路径城市的记录

self.best_cities = ant_path.path

else:

if self.ants_info[iterNum][i] < Ant(self.best_cities).length: self.best_cities = ant_path.path

tabu.append(tabu[0]) # 每次迭代完成后,使禁忌城市下标列表形成完整闭环

for l in range(self.cities_num):

delta_phero_mat[tabu[l]][tabu[l+1]] += self.Q/self.ants_info[iterNum][i]

self.best_path[iterNum] = Ant(self.best_cities).length

self.update_phero_mat(delta_phero_mat) # 更新信息素矩阵

iterNum += 1

def update_phero_mat(self, delta):

self.phero_mat = (1 - self.rho) * self.phero_mat + delta

# self.phero_mat = np.where(self.phero_mat > self.phero_upper_bound, self.phero_upper_bound, self.phero_mat) # 判断是否超过浓度上限

def random_seed(self): # 产生随机的起始点下表,尽量保证所有蚂蚁的起始点不同

if self.ants_num <= self.cities_num: # 蚂蚁数 <= 城市数

self.path_seed[:] = np.random.permutation(range(self.cities_num))[:self.ants_num]

else: # 蚂蚁数 > 城市数

self.path_seed[:self.cities_num] = np.random.permutation(range(self.cities_num))

temp_index = self.cities_num

while temp_index + self.cities_num <= self.ants_num:

self.path_seed[temp_index:temp_index + self.cities_num] = np.random.permutation(range(self.cities_num))

temp_index += self.cities_num

temp_left = self.ants_num % self.cities_num

if temp_left != 0:

self.path_seed[temp_index:] = np.random.permutation(range(self.cities_num))[:temp_left]

def display(self): # 数据可视化展示

plt.figure(figsize=(6, 10))

plt.subplot(211)

plt.plot(self.ants_info, 'g.')

plt.plot(self.best_path, 'r-', label='history_best')

plt.xlabel('Iteration')

plt.ylabel('length')

plt.legend()

plt.subplot(212)

plt.plot(list(city.x for city in self.best_cities), list(city.y for city in self.best_cities), 'g-')

plt.plot(list(city.x for city in self.best_cities), list(city.y for city in self.best_cities), 'r.')

plt.xlabel('x')

plt.ylabel('y')

plt.savefig('ACO.png', dpi=500)

plt.show()

plt.close()

ACO()

输出:

参考文献

[2]《matlab在数学建模中的应用》

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

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

相关文章

c语言整形除法是五舍六入吗,四舍六入五成双 - C/C++论坛 - 51CTO技术论坛_中国领先的IT技术社区...

复制内容到剪贴板代码:#includeusing namespace std;#define FLENGTH 1000; //宏定义保留3位小数double fun(double ldBuf); //四舍六入五成双函数int main(void){double ldTemp9.824963;double ldRet;//大于5ldTemp9.824963;ldRet fun(ldTemp);printf("%.…

苹果的热榜:积分墙背后的隐秘世界

电影《楚门的世界》中描述过这样的故事&#xff1a;楚门这个快乐单纯的青年&#xff0c;一直以为自己是平凡小镇上普通的保险推销员。直到有一天他发现这世界上的一切都是为他精心安排的。他会遇到谁、在他身上将要发生什么事件&#xff0c;都是按照剧本被人操纵的。甚至连他的…

剑指offer之字符串的全排列

1 问题 求字符串的全排列&#xff0c;比如字符串abc&#xff0c;它的全排列如下 abc, acb, bac, bca, cad, cba 2 思路 我们先固定第一个字符&#xff0c;这里的第一个字符肯定是这个字符串里面字符串的全子集&#xff08;不包含重复&#xff09;&#xff0c;abc字符串&…

OC基础学习

1.OC简介 ➢ C语言的基础上&#xff0c;增加了一层最小的面向对象语法 ➢ 完全兼容C语言 ➢ 可以在OC代码中混入C语言代码&#xff0c;甚至是C代码 ➢ 可以使用OC开发Mac OS X平台和iOS平台的应用程序 2.OC关键字 ➢ 基本上所有关键字都是以开头 ➢ 下面列举一些常见的关键字&a…

关中断是否禁止任务调度?关中断能作为互斥吗?

本文引自链接http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_16830.html?WebShieldDRSessionVerifyCOR6tnpfsOXExxEAO6Z6 今天再看《嵌入式软件系统教程》&#xff08;&#xff08;美&#xff09;西蒙 著&#xff0c;陈向群 等译&#xff09; &#xff0c;里面讲到关中断会…

solidity编写eth智能合约之contract 创建合约(二)

环境说明&#xff1a; Ide&#xff1a;在线remix Solidity IDE 语言&#xff1a;solidity solidity 版本号&#xff1a;0.4.20 Tip&#xff1a;如果一点都不懂的建议从头开始看 运行结果截图我不赘述&#xff0c;所有合约代码均通过个人检测。请按照标准进行操作&#xff0c;如…

为什么HttpContextAccessor要这么设计?

前言周五在群里面有小伙伴问&#xff0c;ASP.NET Core这个HttpContextAccessor为什么改成了这个样子&#xff1f;在印象中&#xff0c;这已经是第三次遇到有小伙伴问这个问题了&#xff0c;特意来写一篇记录&#xff0c;来回答一下这个问题。聊一聊历史关于HttpContext其实我们…

AJAX与SQL Server(一)

本实例演示利用Ajax技术,通过asp文件,从SQL Server数据库中读取数据。 1、新建一个网站。 2、在网站目录下新建一个txt文档,改名为datasource.asp,内容为: <%@Language="vbscript" Codepage="65001"%> <% response.expires=-1 sql="…

元素周期表排列的规律_中考化学:金属活动性顺序表和元素周期表规律总结

在我们初三学年的化学学习中&#xff0c;有两大重要规律需要同学们牢牢记住&#xff0c;这也是贯穿我们化学始终的化学规律&#xff0c;那就是金属活动性顺序表和化学元素周期表规律。一、金属活动性顺序表:金属活动性顺序由强至弱: K Ca na Mg Al Zn Fe Sn Pb(H)Cu Hg Ag Pt A…

基于c语言单片机秒表课程设计,基于c语言单片机秒表课程设计要点.doc

课程设计报告课程名称&#xff1a;单片机原理及应用报告题目&#xff1a;秒表学生姓名&#xff1a;所在学院&#xff1a;信息科学与工程学院专业班级&#xff1a;学生学号&#xff1a;指导教师&#xff1a;2013 年 12 月 25 日课程设计任务书报告题目秒表完成时间学生姓名专业班…

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input

作者原创&#xff0c;转载请注明转载地址 第一次遇到该异常&#xff0c;在网上搜了很长时间也没找到解决答案&#xff0c;特此记录 1.异常展示&#xff1a; com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input at [Source: java.io.…

linux shell之cut命令

1 cut简单介绍 我们一般用的就是获取文本一行的的第几个到第几个字符 2 常见使用 1) cut -c start-end file 这里就是获取start到end之间的字符 比如我们这里有文本1.txt cat 1.txt chenyu cut -c 1-3 1.txt che 2) cut -c start file 这里的start就是第start个字符&…

solidity modifier函数修改器 智能合约开发知识浅学(三)

环境说明&#xff1a; Ide&#xff1a;在线remix Solidity IDE 语言&#xff1a;solidity solidity 版本号&#xff1a;0.4.20 Tip&#xff1a;如果一点都不懂的建议从头开始看 运行结果截图我不赘述&#xff0c;所有合约代码均通过个人检测。请按照标准进行操作&#xff0c;如…

汇编语言学习——完整版

简介 我为什么要学汇编 因为想在寒假手写一下操作系统玩玩&#xff0c;所以提前学一学汇编&#xff0c;到时候放假就可以直接上手写了。 什么是汇编语言 由于处理器只能理解机器语言指令&#xff0c;即 0 和 1 组成的字符串。然而&#xff0c;机器语言对软件开发来说过于晦…

百度网盘超级会员,年卡低至198元!百度官方直充,会员实时生效!

大家都喜欢用百度网盘来存储文件、照片&#xff0c;还用百度网盘分享文档&#xff0c;但没有会员的&#xff0c;容量就太小&#xff0c;传输速度也受限&#xff0c;还是咬牙充个会员吧&#xff01;幻海优品是一家正规的会员充值平台&#xff0c;价格很实惠&#xff01;百度网盘…

C#服务器编程:WebService、Ajax与回调函数(一)

目 录 1、结果展示 2、WebService 3、回调函数 本实例演示借助WebService、Ajax技术和回调函数,从MSSQL数据库中获取所需数据,并用JavaScript语言将数据结果显示到网页地图上。 1、结果展示 2、WebService (1)在工具箱的Ajax Extentions下面找到ScriptManager控件,拖…

SyntaxHighlighter行号显示错误问题解决方案

SyntaxHighlighter是根据代码中的换行符分配行号的。但是&#xff0c;如果一行代码或者注释比较长&#xff0c;在页面显示时需要分成多行显示&#xff0c;会出现行号对不上的问题&#xff0c;像这样&#xff1a; 通过设置CSS强制不换行&#xff0c;可以保证行号显示正常&#x…

mysql 一对多 关联一条最新的数据_不得不会的mysql锁

6. 多表之间的关系如图&#xff0c;实际业务数据库中的表之间都是有关系的&#xff0c;我们接下来主要要学习的就是如何分析表关系及建立表关系。分类表create table category( cid varchar(32) primary key, cname varchar(100) );商品表create table product( pid varchar(3…

[鉴权/授权].Net6下Jwt与RefreshToken的结合

微信公众号&#xff1a;趣编程ACE关注可了解.NET日常开发技巧。如需源码&#xff0c;请公众号留言 源码;上文回顾【鉴权/授权】一步一步实现一个简易JWT鉴权【鉴权/授权】自定义一个身份认证Handler【鉴权/授权】基于角色的简单授权认证如何基于JWT实现RefreshToken在前面的几篇…

C#访问postgresql数据库类MyPostDB的实现

为了访问PostgreSQL数据库&#xff0c;需要从pgfoundry网站&#xff0c;下载Npgsql .Net Data Provider for Postgresql的组件。 访问 URL&#xff1a;http://pgfoundry.org/frs/?group_id1000140&#xff0c;请按照自己的VS及.NET版本下载相应的版本。下载后解压缩zip文件&am…