【Python】禁忌搜索算法求解最短路径问题(含python代码实现)

禁忌搜索算法

参考B站视频教程,原文链接:人工智能导论实验演示 - 15. 禁忌搜索求解最短路径问题

1 基本流程

禁忌搜索算法在初始化的时候,在搜索空间随机生成一个初始解 i,禁忌表H置空,当前解i记为历史最优解 s,然后进入迭代的搜索过程。在每一次迭代中,都从当前的解i出发,在当前禁忌表H的限制下,构造出解i的邻域A,然后从A中选出适应值最好的解 j 来替换解 i,同时更新禁忌表H。在解 j 替换解 i 之后,如果解 i 的质量得到改善,那么历史最优的解 s 将被解 i 替换;否则,s 保持不变,即使解 i 虽然暂时变差了,但是由于扩大了搜索空间,仍有利于跳出局部最优。得到了新的当前解 i 之后,算法返回迭代的开始继续进行,直到找到最优解或者运行了一定的迭代次数等终止条件的时候结束算法。

img

2 相关术语

领域

所谓邻域,简单的说即是给定点附近其他点的集合. 在距离空间中,邻域一般被定义为以给定点为圆心的一个圆;而在组合优化问题中,邻域一般定义为由给定 转化规则对给定的问题域上每结点进行转化所得到的问题域上结点的集合。

领域动作

邻域动作是一个函数,通过这个函数,对当前解 s s s ,产生其相应的邻居解集合。例如: 对于一个 bool 型问题,其当前解为: s = 1001 s=1001 s=1001 ,当将邻域动作定义为采 转其中一个 bit 时,得到的邻居解的集合 N (   s ) = { 0001 , 1101 , 1011 , 1000 } N(\mathrm{~s})=\{0001,1101,1011,1000\} N( s)={0001,1101,1011,1000} ,其中 N ( s ) ∈ S \mathrm{N}(\mathrm{s}) \in \mathrm{S} N(s)S ,同理,当将邻域动作定义为互换相邻 bit 时,得到的邻居解的集合 N ( s ) = { 0101 , 1001 , 1010 } N(s)=\{0101,1001,1010\} N(s)={0101,1001,1010}

禁忌表

包括禁忌对象和禁忌长度。

候选集合

侯选集合由邻域中的邻居组成。常规的方法是从邻域中选择若干个目标值或评价值最佳的邻居入选。

禁忌对象

禁忌算法中,由于我们要避免一些操作的重复进行,就要将一些元素放到禁忌表中以禁止对这些元素进行操作,这些元素就是我们指的禁忌对象。

禁忌长度

禁念长度是被禁对像不允许选取的迭代次数。一般是给被禁对象 x x x 一个数 (禁忌长度) t t t ,要求对象 x x x t t t 步迭代内被禁,在禁念表中采用 t a b u ( x ) = t t a b u(x)=t tabu(x)=t 记 亿,每迭代一步,该项指标做运算 tabu ⁡ ( x ) = t − 1 \operatorname{tabu}(\mathrm{x})=\mathrm{t}-1 tabu(x)=t1 ,直到 tabu ⁡ ( x ) = 0 \operatorname{tabu}(x)=0 tabu(x)=0 时解禁。于是,我们可将所有元素分成两类,被禁元素和自由元素。禁忌长度 t t t 的选取可 以有多种方法,例如 t = t= t= 常数,或 t = [ n ] t=[\sqrt{n } ] t=[n ] ,其中 n n n 为邻域中邻居的个数; 这种规则容易在算法中实现。

评价函数

评价函数是候选集合元素选取的一个评价公式,候选集合的元素通过评价函数值来选取。以目标函数作为评价价函数是比较容易理解的。目标值是一个非常直观的 指标,但有时为了方便或易于计算,会采用其他函数来取代目标函数。

特赦规则

在禁忌搜索算法的迭代过程中,会出现侯选集中的全部对象都被禁忌,或有一对象被禁,但若解禁则其目标值将有非常大的下降情况。在这样的情况下,为了达到全局最优,我们会让一些禁忌对象重新可选。这种方法称为特赦,相应的规则称为特赦规则。

3 算法流程

img

4 代码实现

4.1 导入库

导入 math 模块, random 模块, pandas 模块和 matplotlib 模块。

import math
import random
import pandas as pd
import matplotlib. pyplot as plt
%matplotlib inline

4.2 定义评价函数

函数计算路径的距离,作为搜索的评价函数。

def calFitness(line,dis_matrix):
	dis_sum =0
	dis =0
	for i in range(len(line)):
    if i<len(line)-1:
        dis=dis_matrix.loc[[line[i],line[i+l]] # 计算距离
        dis_sum dis_sum+dis
    else:
        disdis_matrix.loc[line[i],line[O]]
        dis_sum dis_sum+dis
    return round (dis_sum,1)

4.3 定义领域随机搜索函数

def traversal_search(line,dis_matrix,tabu_list):
	# 邻域随机遍历搜素
	traversal=0# 搜索次数
	traversal_list = [] # 存储局部搜素生成的解也充当局部禁忌表
	traversal,_value = [] # 存储局部解对应路径距高
	while traversal <traversalMlax:
		posl,pos2=random.randint(0,len(1ine)l),random.randint(0,len(1ine)-1)#交换,点
# 复制当前路径,并交换生成新路径
        new_line = line.copy()
        new_line[pos1],new_line[pos2]=nes_line[po2],new_line[pos1]
        new_value-calFitness(new_line,dis_matrix) # 当前路径距离
        # 新生成路径不在全局禁忌表和局部禁忌表中,为有效搜索,否则继续搜索
        if (new_line not in traversal_list)&(new_line not in tabu_list):
            traversal_list.append (new_line)
            traversal_value.append(new_value)
            traversal +=1
    return min(traversal_value),traversal_list[traversal_value.index(min(traversal_value))]

4.4 定义贪心搜索函数

image-20221021185651549

4.5 定义参数

image-20221021185709684

4.6 初始化城市数据,计算城市之间距离

image-20221021185736557

4.7 使用贪心搜索构造初始解并可视化

image-20221021185756158

4.8 存储最优解,更新禁忌表,循环迭代,输出最优解并可视化

image-20221021185817907

image-20221021185848760

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值