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

传送门(所有的实验都使用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);                     #打印路线,以序列表示
        

  • 25
    点赞
  • 196
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blaze Jack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值