遗传算法和禁忌搜索解TSP

Posted hellobigorange

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遗传算法和禁忌搜索解TSP相关的知识,希望对你有一定的参考价值。

原始数据

计算从城市1出发,通过每个城市,最终回到城市1的最短距离,及路径

city_list = [[1, (1150.0, 1760.0)], [2, (630.0, 1660.0)], [3, (40.0, 2090.0)], [4, (750.0, 1100.0)],
             [5, (750.0, 2030.0)], [6, (1030.0, 2070.0)], [7, (1650.0, 650.0)], [8, (1490.0, 1630.0)],
             [9, (790.0, 2260.0)], [10, (710.0, 1310.0)], [11, (840.0, 550.0)], [12, (1170.0, 2300.0)],
             [13, (970.0, 1340.0)], [14, (510.0, 700.0)], [15, (750.0, 900.0)], [16, (1280.0, 1200.0)],
             [17, (230.0, 590.0)], [18, (460.0, 860.0)], [19, (1040.0, 950.0)], [20, (590.0, 1390.0)],
             [21, (830.0, 1770.0)], [22, (490.0, 500.0)], [23, (1840.0, 1240.0)], [24, (1260.0, 1500.0)],
             [25, (1280.0, 790.0)], [26, (490.0, 2130.0)], [27, (1460.0, 1420.0)], [28, (1260.0, 1910.0)],
             [29, (360.0, 1980.0)]]

路径开头和结尾都是1,只要全排列2,…,29看怎么排列路径最短即可。

遗传算法

遗传算法_geatpy
写好代价函数和参数,直接调用geatpy包。

代码

# -*- coding: utf-8 -*-
"""MyProblem.py"""
import geatpy as ea
import numpy as np

city_list = [[1, (1150.0, 1760.0)], [2, (630.0, 1660.0)], [3, (40.0, 2090.0)], [4, (750.0, 1100.0)],
             [5, (750.0, 2030.0)], [6, (1030.0, 2070.0)], [7, (1650.0, 650.0)], [8, (1490.0, 1630.0)],
             [9, (790.0, 2260.0)], [10, (710.0, 1310.0)], [11, (840.0, 550.0)], [12, (1170.0, 2300.0)],
             [13, (970.0, 1340.0)], [14, (510.0, 700.0)], [15, (750.0, 900.0)], [16, (1280.0, 1200.0)],
             [17, (230.0, 590.0)], [18, (460.0, 860.0)], [19, (1040.0, 950.0)], [20, (590.0, 1390.0)],
             [21, (830.0, 1770.0)], [22, (490.0, 500.0)], [23, (1840.0, 1240.0)], [24, (1260.0, 1500.0)],
             [25, (1280.0, 790.0)], [26, (490.0, 2130.0)], [27, (1460.0, 1420.0)], [28, (1260.0, 1910.0)],
             [29, (360.0, 1980.0)]]


x_point_list = [i[1][0] for i in city_list] # x坐标
y_point_list = [i[1][1] for i in city_list] # y坐标


# 计算两城市间的距离
def city_distance(city1, city2):
    distance = ((float(x_point_list[city1] - x_point_list[city2])) ** 2 + (
        float(y_point_list[city1] - y_point_list[city2])) ** 2) ** 0.5
    return distance


# 计算线路路径长度
def aim_func(road_list):
    current_point = 0
    dist = 0
    for i in road_list:
        next_point = i - 1
        dist += city_distance(current_point, next_point)
        current_point = i - 1
    dist += city_distance(current_point, 0)
    return dist


class MyProblem(ea.Problem):  # 继承Problem父类
    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = len(city_list) - 1  # 初始化Dim(决策变量维数)
        varTypes = [1] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的实数;1表示是离散的整数)
        lb = [2] * Dim  # 决策变量下界
        ub = [Dim + 1] * Dim  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界,1表示包含上边界;0表示不包含上边界
        ubin = [1] * Dim  # 决策变量上边界

        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)

    def aimFunc(self, pop):  # 目标函数
        X = pop.Phen
        f = np.array([aim_func(road_list) for road_list in X]).reshape(X.shape[0], 1)
        pop.ObjV = f  # 计算目标函数值,赋值给pop种群对象的ObjV属性

# -*- coding: utf-8 -*-
"""main.py"""
import geatpy as ea
from MyProblem import *  # 导入自定义问题接口


# 画线路图
def draw_line_pic(route, cost):
    import matplotlib.pyplot as plt
    x = []
    y = []
    route = list(route)
    route.append(1)
    route.insert(0,1)
    for item in route:
        x.append(x_point_list[item-1])
        y.append(y_point_list[item-1])
    plt.plot(x, y)

    plt.scatter(x_point_list, y_point_list, marker="o", c='g')
    plt.scatter(x_point_list[0], y_point_list[0], marker="o", c="r")
    for i in range(len(city_list)):
        plt.text(x_point_list[i], y_point_list[i], str(i+1), ha='center', va='bottom', fontsize=10)
    plt.title("GA_Search: " + str(cost))
    plt.plot([1,2],[1,2])
    plt.show()

for i in range(1):
    print(str(i)+"次")
    """===============================实例化问题对象================================"""
    problem = MyProblem()  # 生成问题对象
    """==================================种群设置=================================="""
    Encoding = 'P'  # 编码方式

    NIND = 500  # 种群规模
    Field = ea.crtfld(Encoding=Encoding, varTypes=problem.varTypes, ranges=problem.ranges, borders=problem.borders)  # 创建区域描述器
    population = ea.Population(Encoding, Field, NIND)  # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)
    """================================算法参数设置================================="""
    myAlgorithm = ea.soea_SEGA_templet(problem, population)  # 实例化一个算法模板对象_精英保留的遗传算法
    myAlgorithm.MAXGEN = 500  # 最大进化代数
    myAlgorithm.mutOper.Pm = 0.8  # 变异概率
    myAlgorithm.logTras = 10  # 设置每隔多少代记录日志,若设置成0则表示不记录日志
    myAlgorithm.verbose = True  # 设置是否打印输出日志信息
    myAlgorithm.drawing = 1  # 设置绘图方式(0:不绘图;1:绘制结果图;2:绘制目标空间过程动画;3:绘制决策空间过程动画)
    """===========================调用算法模板进行种群进化==============--==========="""
    [BestIndi, population] = myAlgorithm.run()  # 执行算法模板,得到最优个体以及最后一代种群
    BestIndi.save()  # 把最优个体的信息保存到文件中
    """==================================输出结果=================================="""
    print('用时:%f 秒' % myAlgorithm.passTime)
    print('评价次数:%d 次' % myAlgorithm.evalsNum)

    if BestIndi.sizes != 0:
        print('最优的目标函数值为:%s' % BestIndi.ObjV[0][0])
        print('最优的控制变量值为:')
        road_list=BestIndi.Phen[::]
        print("最优路径:",road_list)
        draw_line_pic(road_list[0], BestIndi.ObjV[0][0])
        finally_route_list = []
        for i in road_list[0]:
            finally_route_list.append([i, (x_point_list[i - 1], y_point_list[i - 1])]) # 最终路径
    else:
        print('没找到可行解。')

结果

用时:10.537014 秒
评价次数:250000 次
最优的目标函数值为:9076.982920396536
最优的控制变量值为:
最优路径: [1 28 6 12 9 26 3 29 5 21 2 20 10 13 4 15 18 14 17 22 11 19 25 7 23
8 27 16 24 1]

禁忌搜索

代码

结果

以上是关于遗传算法和禁忌搜索解TSP的主要内容,如果未能解决你的问题,请参考以下文章

遗传算法初步

遗传算法

遗传算法中种群规模和个体个数的区别

遗传算法存在问题?

遗传算法在自动组卷中的应用

遗传算法在自动组卷中的应用