一、问题概况
使用蚁群算法求解 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)
四、结果图
蚁周模型:
路径图
最优路径图
蚁量模型:
路径图
最优路径图
如果你觉得对你有所帮助的话就点点关注和收藏吧
希望对您有所帮助。