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

333 阅读5分钟

传送门(所有的实验都使用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个数互不相同,因为每个城市只经过一次。

4、适应度计算

    根据两点之间的距离公式可得n与m的距离

   

    将城市之间的相邻距离相加,总和越小的个体适应度越高。

 

5、选择算子

    采用最优保存策略,最优的个体直接覆盖最差个体,且这两个个体不参与交叉变异运算。

6.交叉算子

    采用有序交叉法,产生新个体。

7.变异

    对于变异的个体,在序列上随机出a,b两点,并将两点之间的序列倒置。

8.终止条件

    分别进行100,500,2000,10000次进化后终止。

 

 

 

 

 

运行截图:

 

100次进化:总距离:240.883

 

500次进化总距离:172.05

 

 

2000次进化总距离:143.708

 

 

 

 

10000次进化总距离:142.136

五、总结

   

种群的初始个体数目设置的越多,产生的个体种类就越多,进而在比较少的进化次数中就能找到较优解,但是单次进化的时间会变长。此外变异因子不同值也会影响进化的进程。在本次实验中可以看到刚开始最优解变化很快,到2000次时开始趋于稳定。

Python源码

#coding:gbk
import random
import math
import matplotlib.pyplot as plt
global n,m,pc,pm,best;
pc = 0.9;pm=0.2;     #pc为交配概率 pm为变异概率
best = 10000;           #best记录最优距离,初始化无限大
n=10;m=30;          #n:样本个数    m:城市个数
dna = [[0]*(m) for i in range(n)]   #开辟n*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  variation(x):   # 变异操作函数
    x1 = [0]*m;
    for i in range(m):
        x1[i] = x[i];
    a =random.randint(0,m-1);    #随机出两个点进行倒置
    b = random.randint(0,m-1);
    if(a > b): a,b=b,a;
    le = b-a+1;
    for i in range(le):
        x[a+i]=x1[b-i];
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   init():        #初始化函数 随机产生初始个体
    vis = [0]*m;
    num=0;
    for i in range(n):
        for j in range(m):
            vis[j] = 0;
        for j in range(m):      
            num = random.randint(0,m-1);
            while(vis[num] == 1):
                num = random.randint(0,m-1);
            vis[num]=1;dna[i][j]=num;
def get_value(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 find(x,a,b,num):     #交叉算子运算时判断是否出现重复的城市id 
    for i in range(a,b+1):
        if(num[i] == x):
            return i;
    return -1;
    
def swap(x, y):         #有序交叉法
    x1 =  [0]*m;  y1 =  [0]*m;
    for i in range(m):
        x1[i]=x[i];y1[i]=y[i];
    a =  random.randint(0,m-1);    #随机产生两个点
    b = random.randint(0,m-1);
    if(a > b): a,b=b,a;
    for i in range(a):      #交叉运算
        x1[i]=y[i];y1[i]=x[i];
    for i in range(b+1,m):
        x1[i]=y[i];y1[i]=x[i];
    ob = 0;
    for i in range(m):       #判断交叉的合法性并进行维护,直到交叉成功
        if(i>= a and i<= b):
            continue;
        ob = find(x1[i],a,b,x1);
        while(ob != -1):
            x1[i] = y1[ob];
            ob = find(x1[i],a,b,x1);
    for i in range(m):     #操作同上,维护另一新个体的交叉合法性。
        if(i>= a and i<= b):
            continue;
        ob = find(y1[i],a,b,y1);
        while(ob != -1):
            y1[i] = x1[ob];
            ob = find(y1[i],a,b,y1);
    for i in range(m):
        x[i]=x1[i];y[i]=y1[i];
     
def slove():         #总执行函数
    global best;    #记录最短距离
    for i in range(n):
        value[i]=get_value(dna[i]);
    max_id = value.index(max(value));   #最优解与最差解个体的id被记录
    min_id = value.index(min(value));
    if(value[min_id] < best):
        best = value[min_id];
        for i in range(m):
            way[i] = dna[min_id][i];
    value[max_id] = value[min_id];  #最优解覆盖最差解
    fa = -1;
    for i in range(m):            
        dna[max_id][i]=dna[min_id][i];
    for i in range(n):                #开始交配
        if(random.random()> pc or i == max_id or i == min_id):
            continue;
        if(fa == -1):
            fa = i;
        else :
            swap(dna[fa], dna[i]);
            fa = -1;
    for i in range(n):              #变异运算
        if(random.random()> pm or i == max_id or i == min_id):
            continue;
        variation(dna[i]);

mycol();            #数据输入    
init();                 #群体初始化
for i in range(1000):      #控制进化次数
    slove();
draw(way);                      #画图描绘路线
print(round(best,3));       #打印距离
print(way);                     #打印路线,以序列表示
        

 

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