实验6 蚁群算法求解tsp问题

340 阅读7分钟

传送门(所有的实验都使用python实现)

实验1 BP神经网络实验

实验2 som网实验

实验3 hopfield实现八皇后问题

实验4 模糊搜索算法预测薄冰厚度

实验5 遗传算法求解tsp问题

实验6 蚁群算法求解tsp问题

实验7 粒子群优化算法求解tsp问题

实验8 分布估计算法求解背包问题

实验9 模拟退火算法求解背包问题

实验10 禁忌搜索算法求解tsp问题

 

一、实验目的

理解并使用蚁群算法

二、实验内容

实现基于蚁群算法的旅行商路线寻找

三、实验环境

使用Python3.0 在 eclipse进行编辑

四、实验步骤

1、输入介绍:

    城市总数目为30,每个城市的坐标以(x,y)表示,x,y的取值均为0~30的随机数。

2、初始群体设定:

随机产生n条长度为m的数组。n代表个体数目,m代表城市个数。在本次实验中设定n=10,m=30。且同一个体中的m个数互不相同,因为每个城市只经过一次。

3、信息素强度初始化:

根据使用贪心算法所得到的路径len,初始化每条边信息素含量为m/len;本次实验计算可得len=300,m=30,故初始化每条边信息素含量为0.1;

   

4、路线寻找:

    每只蚂蚁随机选择一个出发点,根据下面公式计算下个点的概率,并采用轮盘赌方式决定。决定的过程中不断更新禁忌表。

 

5.  信息素更新:

当所有蚂蚁成功行走出路线后,采用下列公式对于每条边进行信息素更新。为使得信息素更新明显,设置信息素强度Q=10000,挥发率p=0.1;

6.终止条件

    分别进行5,20,50,100次迭代后终止。

 

运行截图:

 

5次迭代总距离:193.52

 

 

 

 

 

 

 

20次迭代总距离:143.708

 

 

 

 

50次迭代总距离:150.60

 

 

 

100次迭代总距离:140.136

五、总结

信息素强度的设置会直接影响到算法的迭代次数与效率,若强度设置的过低就会导致挥发速度比蚂蚁更新速度还快,最后导致最优路线上的信息素丢失,失去最优解。若强度设置过高,会影响启发式信息的比重,找到的解并非较优解。经过多次实验,我设置信息素强度为1万。

    与遗传算法比较,个人觉得蚁群算法的效率高于遗传算法,遗传算法中的随机因素太多,导致最优解的寻找比较久,蚁群算法对于路径的寻找虽然有轮盘赌的随机因素,但是信息素和启发式信息的影响有起到一定的纠正作用。

python源码

#coding:gbk
import random
import math
import matplotlib.pyplot as plt
global n,m,best,Q;
global br;
best = 10000;           #best记录最优距离,初始化无限大
n=10;m=30;          #n:样本个数    m:城市个数
road = [[0]*(m) for i in range(n)]   #开辟n*m的数组记录每个只蚂蚁行走的路线
tau = [[0]*(m) for i in range(n)]   #禁忌表
con = [[0]*(m) for i in range(m)]     #记录信息素浓度
dis =  [[0]*(m) for i in range(m)]     #邻接矩阵记录两点间的距离
game = [0.0]*m;                        #轮盘赌的概率
value = [0.0]*n;                        #value数组记录每只蚂蚁的路线长度
way =[0]*m;                          #way数组记录最优解路线
class no:                       #该类表示每个点的坐标
    def __init__(self,x,y):
        self.x=x;
        self.y=y;
p=[];
def draw(t):              #该函数用于描绘路线图
    x=[0]*(m+1);y=[0]*(m+1);
    for i in range(m):
        x[i] =p[t[i]].x;
        y[i] =p[t[i]].y;
    x[m] =p[t[0]].x;
    y[m] =p[t[0]].y;
    plt.plot(x,y,color='r',marker='*' ); 
    plt.show();
def  mycol():                           #城市坐标输入
        p.append(no( 8 , 20 ));
        p.append(no( 28 , 6 )); p.append(no( 27 , 24 )); p.append(no( 25 , 20 )); p.append(no( 5 , 14 )); p.append(no( 18 , 4 )); p.append(no( 21 , 22 ));
        p.append(no( 19 , 17 )); p.append(no( 28 , 22 )); p.append(no( 16 , 18 )); p.append(no( 28 , 28 )); p.append(no( 11 , 28 )); p.append(no( 29 , 28 ));
        p.append(no( 15 , 22 )); p.append(no( 25 , 24 )); p.append(no( 9 , 22 )); p.append(no( 17 , 16 )); p.append(no( 12 , 16 )); p.append(no( 5 , 21 ));
        p.append(no( 6 , 6 )); p.append(no( 12 , 21 )); p.append(no( 11 , 28 )); p.append(no( 20 , 22 )); p.append(no( 17 , 10 )); p.append(no( 18 , 6 ));
        p.append(no( 18 , 9 )); p.append(no( 25 , 24 )); p.append(no( 24 , 11 )); p.append(no( 25 , 12 )); p.append(no( 0 , 28 ));
def  get_dis(a,b):       #返回ab两城市的距离
    return   math.sqrt((p[a].x-p[b].x) *(p[a].x-p[b].x) +(p[a].y-p[b].y) *(p[a].y-p[b].y));
def get_value(t):        #计算蚂蚁t的路线长度
    ans = 0.0;
    for i in range(1,m):     #两点距离公式
        ans += math.sqrt((p[t[i]].x-p[t[i-1]].x) *(p[t[i]].x-p[t[i-1]].x)  +(p[t[i]].y-p[t[i-1]].y) *(p[t[i]].y-p[t[i-1]].y));
    ans +=  math.sqrt((p[t[0]].x-p[t[m-1]].x) * (p[t[0]].x-p[t[m-1]].x)  +(p[t[0]].y-p[t[m-1]].y) *(p[t[0]].y-p[t[m-1]].y));
    return ans;
def init():            #初始化函数
    for i in range(m):
        for j in range(m):
            con[i][j] = 0.1;             #初始化所有信息素为0.03
            dis[i][j]=get_dis(i,j);
def rws():                                      #轮盘赌函数
    num = random.random();
    r = 0.0;
    for i in range(m):
        r += game[i];
        if(r >= num): return i;
    return m-1;
def move(x,loc):              #蚂蚁xloc位置爬行到下一个点
    tol=0.0
    pk = [0.0]*m;
    for i in range(m):
        if(tau[x][i] != 1and dis[loc][i] !=0):    #概率计算
                pk[i] = con[loc][i]*(1/dis[loc][i])*(1/dis[loc][i]);
        else:
            pk[i]=0;
        tol += pk[i];
    if(tol == 0):           #启发式信息的总和为0,br标记迭代结束
        tol=1;br=0;       
    for i in range(m):    #分配轮盘赌的概率
        game[i] =pk[i]/tol;
    return rws();       #返回轮盘赌的选择
def slove():
    global best,br;
    for i in range(n):
        for j in range(m):
            tau[i][j] = 0;       #初始化禁忌表
    for i in range(n):
        num = random.randint(0,m-1);    #随机选择出发地点
        tau[i][num]=1;   road[i][0] = num;
    for k in range(m-1):
        for i in range(n):
            ob = move(i,road[i][k]);      #向前移动一步
            tau[i][ob]=1;road[i][k+1] = ob;     #更新禁忌表
    if(br == 0):          #br=0说明迭代已经到达终点,函数结束
        return;
    for i in range(n):               #计算每只蚂蚁路径长度
        value[i]=get_value(road[i]);
        if(value[i] < best):       #更新记录最优解
            best = value[i];
            for j in range(m):
                way[j]= road[i][j];     
            
    for i in range(m):               #挥发过程,每次挥发0.1
        for j in range(m):
            con[i][j]*=0.9;
    for i in range(n):               #信息素更新
        for j in range(m-1):
            a=road[i][j];  b=road[i][j+1];
            con[a][b] += Q/value[i];                #Q为信息素强度
    for i in range(m-1):
            a=road[i][m-1];  b=road[i][0];
            con[a][b] += Q/value[i];
        
mycol();            #数据输入    
init();                 #数据初始化
Q=10000;        #信息素强度设置
br = 1;             #迭代开始标记
for i in range(100):      #控制迭代次数
    if(br == 0):
        break;
    slove();
print(round(best,3));       #打印最优解距离,保留三位小数
draw(way);                      #画图描绘路线
print(way);                     #打印路线,以序列表示
        

本文已参与「新人创作礼」活动,一起开启掘金创作之路