使用遗传算法解决中国TSP问题

本文介绍遗传算法基本流程,包括编码、初始化种群、评估适应度、选择、交叉和变异等步骤,并给出相应Python代码。通过中国34个城市经纬度数据实验,得出个体数量、迭代次数、交叉和变异概率的适宜范围,还进行城市选择及可视化操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

遗传算法基本流程:

编码:即不同的城市 0-33(34个城市)

初始化种群:要产生较好的初始化结果,所以我采用的是先随机选择开始点,再选择与这个点最近的点作为下一个点(为保证初始化的多样性,最近的点由十余次搜索以内产生,进行十步以上搜索时有概率中止搜索操作)

python代码:

for i in range(INDINUM):
        init=[]
        allcity=list(allcities)
        add=allcity[int(citynum*random())]
        init.append(add)
        allcity.remove(add)
        for i in range(citynum-1):
            mindist=10000
            add=-1
            findtime=0
            for city in allcity:
                dist=dist2(x[city],x[init[-1]],y[city],y[init[-1]])
                if dist<mindist:
                    mindist=dist
                    add=city
                findtime+=1
                if findtime>(citynum//3) and random()<0.1:
                    break
            init.append(add)
            allcity.remove(add)
        m.append(init)

评估适应度:对距离取倒数,为了增加优秀个体的优势,又减去了一个常数

python代码:

def dist2(x1,x2,y1,y2):
    return ((x1-x2)**2)+((y1-y2)**2)
def evaluate(m,x,y):
    sums=sqrt(dist2(x[m[0]],x[m[-1]],y[m[0]],y[m[-1]]))
    size=len(m)-1
    for ii in range(size):
        sums+=sqrt(dist2(x[m[ii]],x[m[ii+1]],y[m[ii]],y[m[ii+1]]))
    score=(10000/sums)-40#increase weight of good ones
    if score<0:
        score=0.1
    return score

选择:根据适应度加权平均选择

PYTHON代码:

        preserve=[(evas/sum(eva)) for evas in eva]

        #preserve
        new=[]
        new.append(list(m[eva.index(max(eva))]))
        for i in range(INDINUM-2):
            point=random()
            for ii in range(INDINUM):
                point-=preserve[ii]
                if point<0:
                    new.append(list(m[ii]))
                    break
        new.append(best)

        m=deepcopy(new) 

交叉:A与B交叉:以A片段插入B为例:先从B中去除掉片段(除第一个)的元素,再从片段首的位置插入B

#cross
        for i in range(INDINUM//2):
            crosspart=[]
            if random()<crossrate:
                crosslen=randint(citynum//3,citynum//2)
                crosspart.append(m[i*2][-crosslen:])
                crosspart.append(m[i*2+1][-crosslen:])

                #cross the second one
                for cp in crosspart[0][1:]:
                    m[i*2+1].remove(cp)
                ff=m[i*2+1].index(crosspart[0][0])
                crosspart[0]=crosspart[0][1:]
                crosspart[0].reverse()
                for cp in crosspart[0]:
                    m[i*2+1].insert(ff+1,cp)

                #cross the first one
                for cp in crosspart[1][1:]:
                    m[i*2].remove(cp)
                ff=m[i*2].index(crosspart[1][0])
                crosspart[1]=crosspart[1][1:]
                crosspart[1].reverse()
                for cp in crosspart[1]:
                    m[i*2].insert(ff+1,cp)

变异:交换操作,迭代达到一定次数后增加变异的概率

#mutation(exchange)
        for i in range(INDINUM):    
            if random()<mutationrate:
                a=randint(0,citynum-1)
                b=randint(0,citynum-1)
            
                if a!=b:
                    tmp=list(m[i])
                    rank0=evaluate(m[i],x,y)
                    tmp[a],tmp[b]=tmp[b],tmp[a]
                    rank1=evaluate(tmp,x,y)
                    if rank1+throttle>rank0:
                        m[i][a],m[i][b]=m[i][b],m[i][a]

经个人实验,个体数量选择500-2000为宜,相应迭代次数约为800-400,交叉概率设为0.6后期0.3,变异概率设为0.1后期0.6

 

实验数据为中国34个城市的经纬度数据

    with open('data.txt','r') as fp:
        for line in fp.readlines():
            name.append(line.split(',')[0])
            x.append(float(line.split(',')[1]))
            y.append(float(line.split(',')[2].strip()))

较好的一次实验结果:

实验二为程序的城市选择以及可视化操作,个人使用tkinter进行gui编写,matplotlib进行可视化输出

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值