蚁群算法求解TSP问题

一、问题概况

使用蚁群算法求解 30 个城市的 TSP 问题,城市位置如下:

(41, 94)

(37, 84)

(54, 67)

(25, 62)

(7, 64)

(2, 99)

(68, 58)

(71, 44)

(54, 62)

(83, 69)

(64, 63)

(18, 54)

(22, 60)

(83, 46)

(91, 38)

(25, 38)

(24, 42)

(58, 69)

(71, 71)

(74, 78)

(87, 76)

(18, 40)

(13, 40)

(82, 7)

(62, 32)

(58, 35)

(45, 21)

(41, 26)

(44, 35)

(3, 50)

分别实现(1)蚁周模型(2)蚁量模型

二、实验步骤及思想

蚁周模型实验步骤:

(1)导入必要的库:from cv2 import distanceTransform,导入opencv库的distinctTransform函数,用于距离变换,import numpy as np导入numpy库,用于数值计算,import matplotlib.pyplot as plt导入matplotlib库用于绘图

(2)计算城市间距离:calc_distance(city1,city2)函数:计算两个城市间距离,使用欧式距离计算公式,calc_distances(cities)函数:计算所有城市之间的距离矩阵,返回一个二维数组,表示各个城市之间的距离。

(3)定义蚁周模型类AntColony:
初始化方法__init_.():初始化蚁周模型的参数,包括城市间距离矩阵、信息素矩阵、蚂蚁数量、迭代次数、信息素衰减系数、信息素重要性系数和启发式因子系数等。run()方法:运行蚁群算法,通过迭代更新信息素矩阵和搜索最优路径。spread_pheromone()方法:根据蚂蚁路径更新信息素矩阵。gen_path_dist()方法:计算路径长度。gen_all_paths()方法:生成所有蚂蚁的路径。gen_path()方法:生成一只蚂蚁的路径。pick_city()方法:选择下一个城市。get_shortest()方法:更新最短路径。

(4)定义城市位置:定义了一组城市的坐标。
(5)计算距离矩阵:使用calc_distances()函数计算城市之间的距离矩阵。
(6)设置参数:设置了蚂蚁数量(20)、迭代次数(1000)、信息素衰减系数(0.1)、信息素重要性系数(1)和启发式因子系数(2)等参数。
(7)创建蚁周模型实例并运行:创建了AntColony类的实例,并调用run()方法运行   蚁群算法,得到最短路径和最短路径长度。
(8)输出结果:输出了最短路径和最短路径长度。
(9)绘制最短路径图像:使用plot_path()函数绘制了最短路径的图像。10.绘制迭代次数图像:使用plot_convergence()函数绘制了迭代次数和最短路径长度的关系图像。

蚁量模型实验步骤:

(1)计算城市之间的距离:使用欧几里得距离计算两个城市之间的距离。根据所有城市的坐标,计算出城市间的距离矩阵。
(2)蚁量模型类(AntColony):初始化:初始化蚁群模型的参数,包括城市间距离矩阵、信息素矩阵、蚂蚁数量、迭代次数、信息素衰减系数等。irun方法:运行蚁群算法,迭代更新信息素、选择路径,并记录最短路径及其长度spread_pheromone方法:根据蚂蚁路径更新信息素矩阵。gen.path.dist方法:计算蚂蚁路径的长度。gen.a11.paths方法:生成所有蚂蚁的路径。igen_path方法:生成一只蚂蚁的路径。pick.city方法:选择下一个城市。
get.shortest方法:更新最短路径。
(3)定义城市位置:给定了30个城市的坐标。
(4)设置算法参数:设置了蚂蚁数量(2)、迭代次数(1000)、信息素衰减系数(0.1)、信息素重要性系数(1)、信息素挥发系数(0.1)等参数。
(5)创建蚁群模型实例:使用城市距离矩阵和参数创建一个蚁群模型实例。
(6)运行蚁群算法:调用模型实例的run.方法来运行蚁群算法,得到最短路径及其长度。

(7)输出结果:打印输出最短路径及其长度。
(8)绘制结果图像:绘制了迭代次数与最短路径长度之间的关系图。绘制了最短路径图像,展示了城市及其连接的路径。

三、全部代码实现

蚁周模型:结果在430-440之间,每次代码运行结果都不一样


import numpy as np
import matplotlib.pyplot as plt

# 计算两个城市之间的欧几里得距离
def calc_distance(city1, city2):
    return np.linalg.norm(np.array(city1) - np.array(city2))

# 计算所有城市之间的距离矩阵
def calc_distances(cities):
    n_cities = len(cities)
    distances = np.zeros((n_cities, n_cities))
    for i in range(n_cities):
        for j in range(i + 1, n_cities):
            distances[i][j] = distances[j][i] = calc_distance(cities[i], cities[j])
    return distances

# 蚁量模型类
class AntColony:
    def __init__(self, distances, n_ants, n_iterations, decay, alpha=1, beta=5, rho=0.1, Q=1):
        """
        初始化蚁量模型

        参数:
            distances (numpy.ndarray): 城市间距离矩阵
            n_ants (int): 蚂蚁数量
            n_iterations (int): 迭代次数
            decay (float): 信息素衰减系数
            alpha (float): 信息素重要性系数
            beta (float): 启发式因子系数
            rho (float): 信息素挥发系数
            Q (float): 信息素增加强度
        """
        self.distances = distances  # 城市间距离矩阵
        self.pheromone = np.ones_like(distances) / len(distances)  # 信息素矩阵
        self.n_ants = n_ants  # 蚂蚁数量
        self.n_iterations = n_iterations  # 迭代次数
        self.decay = decay  # 信息素衰减系数
        self.alpha = alpha  # 信息素重要性系数
        self.beta = beta  # 启发式因子系数
        self.rho = rho  # 信息素挥发系数
        self.Q = Q  # 信息素增加强度
        self.shortest_path_lengths = []  # 用于记录每次迭代后的最短路径长度

    # 运行蚁群算法
    def run(self):
        """
        运行蚁群算法,并返回最短路径和其长度

        返回:
            tuple: 包含最短路径和其长度的元组
        """
        shortest_path = None
        shortest_path_length = np.inf
        for _ in range(self.n_iterations):
            all_paths = self.gen_all_paths()  # 生成所有蚂蚁的路径
            self.spread_pheromone(all_paths)  # 更新信息素矩阵
            shortest_path, shortest_path_length = self.get_shortest(all_paths, shortest_path, shortest_path_length)  # 更新最短路径
            self.pheromone *= (1 - self.rho)  # 信息素挥发
            self.shortest_path_lengths.append(shortest_path_length)  # 记录最短路径长度
        return shortest_path, shortest_path_length

    # 更新信息素矩阵
    def spread_pheromone(self, all_paths):
        """
        根据蚂蚁路径更新信息素矩阵

        参数:
            all_paths (list): 包含所有蚂蚁路径的列表
        """
        for path in all_paths:
            for move in path:
                self.pheromone[move] += self.Q / self.distances[move]

    # 计算路径长度
    def gen_path_dist(self, path):
        """
        计算路径长度

        参数:
            path (list): 蚂蚁路径

        返回:
            float: 蚂蚁路径长度
        """
        total = 0
        for move in path:
            total += self.distances[move]
        return total

    # 生成所有蚂蚁的路径
    def gen_all_paths(self):
        """
        生成所有蚂蚁的路径

        返回:
            list: 包含所有蚂蚁路径的列表
        """
        all_paths = []
        for _ in range(self.n_ants):
            path = self.gen_path()  # 生成一只蚂蚁的路径
            all_paths.append(path)
        return all_paths

    # 生成一只蚂蚁的路径
    def gen_path(self):
        """
        生成一只蚂蚁的路径

        返回:
            list: 蚂蚁路径
        """
        n_cities = len(self.distances)
        path = []
        visited = set()
        start = np.random.randint(n_cities)  # 随机选择起始城市
        visited.add(start)
        prev = start
        for _ in range(n_cities - 1):
            next_city = self.pick_city(prev, visited)  # 选择下一个城市
            path.append((prev, next_city))
            prev = next_city
            visited.add(next_city)
        path.append((prev, start))  # 返回起始城市
        return path

    # 选择下一个城市
    def pick_city(self, prev, visited):
        """
        选择下一个城市

        参数:
            prev (int): 上一个城市的索引
            visited (set): 已访问的城市集合

        返回:
            int: 下一个城市的索引
        """
        pheromone = np.copy(self.pheromone[prev])
        pheromone[list(visited)] = 0
        row = pheromone ** self.alpha * (1.0 / (self.distances[prev] + 1e-6) ** self.beta)  # 添加一个很小的值以防止除零错误
        norm_row = row / row.sum()
        next_city = np.random.choice(range(len(self.distances)), 1, p=norm_row)[0]  # 根据概率选择下一个城市
        return next_city

    # 更新最短路径
    def get_shortest(self, all_paths, shortest_path, shortest_path_length):
        """
        更新最短路径

        参数:
            all_paths (list): 包含所有蚂蚁路径的列表
            shortest_path (list): 当前已知的最短路径
            shortest_path_length (float): 当前已知的最短路径长度

        返回:
            tuple: 包含更新后的最短路径和其长度的元组
        """
        for path in all_paths:
            path_dist = self.gen_path_dist(path)
            if path_dist < shortest_path_length:
                shortest_path = path
                shortest_path_length = path_dist
        return shortest_path, shortest_path_length

# 定义城市位置
cities = [(41, 94), (37, 84), (54, 67), (25, 62), (7, 64), (2, 99),
          (68, 58), (71, 44), (54, 62), (83, 69), (64, 63), (18, 54),
          (22, 60), (83, 46), (91, 38), (25, 38), (24, 42), (58, 69),
          (71, 71), (74, 78), (87, 76), (18, 40), (13, 40), (82, 7),
          (62, 32), (58, 35), (45, 21), (41, 26), (44, 35), (3, 50)]

# 计算距离矩阵
distances = calc_distances(cities)

# 参数设置
n_ants = 20  # 蚂蚁数量
n_iterations = 1000  # 迭代次数
decay = 0.1  # 信息素衰减系数
alpha = 1  # 信息素重要性系数
beta = 2  # 启发式因子系数
rho = 0.1  # 信息素挥发系数
Q = 1  # 信息素增加强度

# 创建蚁量模型实例并运行
ant_colony = AntColony(distances, n_ants, n_iterations, decay, alpha, beta, rho, Q)
shortest_path, shortest_path_length = ant_colony.run()

# 输出结果
print("最短路径:", shortest_path)
print("最短路径长度:", shortest_path_length)

# 绘制迭代次数与最短路径长度之间的关系图
plt.plot(range(1, n_iterations + 1), ant_colony.shortest_path_lengths)
plt.xlabel('Iterations')
plt.ylabel('Shortest Path Length')
plt.title('Shortest Path Length over Iterations')
plt.grid(True)
plt.show()

# 定义函数绘制最短路径图
def plot_path(cities, path):
    """
    绘制最短路径图

    参数:
        cities (list): 所有城市的坐标列表
        path (list): 最短路径
    """
    # 获取路径中的城市坐标
    path_cities = [cities[i] for i, _ in path]
    path_cities.append(path_cities[0])  # 将路径首尾相连形成闭环

    # 提取 x 和 y 坐标
    x, y = zip(*path_cities)

    # 绘制城市
    plt.scatter(x, y, color='red')

    # 绘制路径
    for i in range(len(path_cities) - 1):
        plt.plot([path_cities[i][0], path_cities[i + 1][0]], [path_cities[i][1], path_cities[i + 1][1]], color='blue')

    plt.xlabel('X')
    plt.ylabel('Y')
    plt.title('Shortest Path')
    plt.show()

# 绘制最短路径
plot_path(cities, shortest_path)

蚁量模型:


import numpy as np
import matplotlib.pyplot as plt

# 计算两个城市之间的欧几里得距离
def calc_distance(city1, city2):
    return np.linalg.norm(np.array(city1) - np.array(city2))

# 计算所有城市之间的距离矩阵
def calc_distances(cities):
    n_cities = len(cities)
    distances = np.zeros((n_cities, n_cities))
    for i in range(n_cities):
        for j in range(i + 1, n_cities):
            distances[i][j] = distances[j][i] = calc_distance(cities[i], cities[j])
    return distances

# 蚁量模型类
class AntColony:
    def __init__(self, distances, n_ants, n_iterations, decay, alpha=1, beta=5, rho=0.1, Q=1):
        """
        初始化蚁量模型

        参数:
            distances (numpy.ndarray): 城市间距离矩阵
            n_ants (int): 蚂蚁数量
            n_iterations (int): 迭代次数
            decay (float): 信息素衰减系数
            alpha (float): 信息素重要性系数
            beta (float): 启发式因子系数
            rho (float): 信息素挥发系数
            Q (float): 信息素增加强度
        """
        self.distances = distances  # 城市间距离矩阵
        self.pheromone = np.ones_like(distances) / len(distances)  # 信息素矩阵
        self.n_ants = n_ants  # 蚂蚁数量
        self.n_iterations = n_iterations  # 迭代次数
        self.decay = decay  # 信息素衰减系数
        self.alpha = alpha  # 信息素重要性系数
        self.beta = beta  # 启发式因子系数
        self.rho = rho  # 信息素挥发系数
        self.Q = Q  # 信息素增加强度
        self.shortest_path_lengths = []  # 用于记录每次迭代后的最短路径长度

    # 运行蚁群算法
    def run(self):
        """
        运行蚁群算法,并返回最短路径和其长度

        返回:
            tuple: 包含最短路径和其长度的元组
        """
        shortest_path = None
        shortest_path_length = np.inf
        for _ in range(self.n_iterations):
            all_paths = self.gen_all_paths()  # 生成所有蚂蚁的路径
            self.spread_pheromone(all_paths)  # 更新信息素矩阵
            shortest_path, shortest_path_length = self.get_shortest(all_paths, shortest_path, shortest_path_length)  # 更新最短路径
            self.pheromone *= (1 - self.rho)  # 信息素挥发
            self.shortest_path_lengths.append(shortest_path_length)  # 记录最短路径长度
        return shortest_path, shortest_path_length

    # 更新信息素矩阵
    def spread_pheromone(self, all_paths):
        """
        根据蚂蚁路径更新信息素矩阵

        参数:
            all_paths (list): 包含所有蚂蚁路径的列表
        """
        for path in all_paths:
            for move in path:
                self.pheromone[move] += self.Q / self.distances[move]

    # 计算路径长度
    def gen_path_dist(self, path):
        """
        计算路径长度

        参数:
            path (list): 蚂蚁路径

        返回:
            float: 蚂蚁路径长度
        """
        total = 0
        for move in path:
            total += self.distances[move]
        return total

    # 生成所有蚂蚁的路径
    def gen_all_paths(self):
        """
        生成所有蚂蚁的路径

        返回:
            list: 包含所有蚂蚁路径的列表
        """
        all_paths = []
        for _ in range(self.n_ants):
            path = self.gen_path()  # 生成一只蚂蚁的路径
            all_paths.append(path)
        return all_paths

    # 生成一只蚂蚁的路径
    def gen_path(self):
        """
        生成一只蚂蚁的路径

        返回:
            list: 蚂蚁路径
        """
        n_cities = len(self.distances)
        path = []
        visited = set()
        start = np.random.randint(n_cities)  # 随机选择起始城市
        visited.add(start)
        prev = start
        for _ in range(n_cities - 1):
            next_city = self.pick_city(prev, visited)  # 选择下一个城市
            path.append((prev, next_city))
            prev = next_city
            visited.add(next_city)
        path.append((prev, start))  # 返回起始城市
        return path

    # 选择下一个城市
    def pick_city(self, prev, visited):
        """
        选择下一个城市

        参数:
            prev (int): 上一个城市的索引
            visited (set): 已访问的城市集合

        返回:
            int: 下一个城市的索引
        """
        pheromone = np.copy(self.pheromone[prev])
        pheromone[list(visited)] = 0
        row = pheromone ** self.alpha * (1.0 / (self.distances[prev] + 1e-6) ** self.beta)  # 添加一个很小的值以防止除零错误
        norm_row = row / row.sum()
        next_city = np.random.choice(range(len(self.distances)), 1, p=norm_row)[0]  # 根据概率选择下一个城市
        return next_city

    # 更新最短路径
    def get_shortest(self, all_paths, shortest_path, shortest_path_length):
        """
        更新最短路径

        参数:
            all_paths (list): 包含所有蚂蚁路径的列表
            shortest_path (list): 当前已知的最短路径
            shortest_path_length (float): 当前已知的最短路径长度

        返回:
            tuple: 包含更新后的最短路径和其长度的元组
        """
        for path in all_paths:
            path_dist = self.gen_path_dist(path)
            if path_dist < shortest_path_length:
                shortest_path = path
                shortest_path_length = path_dist
        return shortest_path, shortest_path_length

# 定义城市位置
cities = [(41, 94), (37, 84), (54, 67), (25, 62), (7, 64), (2, 99),
          (68, 58), (71, 44), (54, 62), (83, 69), (64, 63), (18, 54),
          (22, 60), (83, 46), (91, 38), (25, 38), (24, 42), (58, 69),
          (71, 71), (74, 78), (87, 76), (18, 40), (13, 40), (82, 7),
          (62, 32), (58, 35), (45, 21), (41, 26), (44, 35), (3, 50)]

# 计算距离矩阵
distances = calc_distances(cities)

# 参数设置
n_ants = 20  # 蚂蚁数量
n_iterations = 1000  # 迭代次数
decay = 0.1  # 信息素衰减系数
alpha = 1  # 信息素重要性系数
beta = 2  # 启发式因子系数
rho = 0.1  # 信息素挥发系数
Q = 1  # 信息素增加强度

# 创建蚁量模型实例并运行
ant_colony = AntColony(distances, n_ants, n_iterations, decay, alpha, beta, rho, Q)
shortest_path, shortest_path_length = ant_colony.run()

# 输出结果
print("最短路径:", shortest_path)
print("最短路径长度:", shortest_path_length)

# 绘制迭代次数与最短路径长度之间的关系图
plt.plot(range(1, n_iterations + 1), ant_colony.shortest_path_lengths)
plt.xlabel('Iterations')
plt.ylabel('Shortest Path Length')
plt.title('Shortest Path Length over Iterations')
plt.grid(True)
plt.show()

# 定义函数绘制最短路径图
def plot_path(cities, path):
    """
    绘制最短路径图

    参数:
        cities (list): 所有城市的坐标列表
        path (list): 最短路径
    """
    # 获取路径中的城市坐标
    path_cities = [cities[i] for i, _ in path]
    path_cities.append(path_cities[0])  # 将路径首尾相连形成闭环

    # 提取 x 和 y 坐标
    x, y = zip(*path_cities)

    # 绘制城市
    plt.scatter(x, y, color='red')

    # 绘制路径
    for i in range(len(path_cities) - 1):
        plt.plot([path_cities[i][0], path_cities[i + 1][0]], [path_cities[i][1], path_cities[i + 1][1]], color='blue')

    plt.xlabel('X')
    plt.ylabel('Y')
    plt.title('Shortest Path')
    plt.show()

# 绘制最短路径
plot_path(cities, shortest_path)

四、结果图

蚁周模型:

780793c0f702493c9df2d0c58f8f53b1.png

路径图

138f51d0374b4673978389ccf3baeb01.png

最优路径图

蚁量模型:

a59c4a936ed346a0876f558444442eda.png路径图

c43ca837849d485c8adb73913d391bd9.png

最优路径图

如果你觉得对你有所帮助的话就点点关注和收藏吧

希望对您有所帮助。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值