TSP问额
TSP(Traveling Salesman Problem,旅行推销员问题)是一个著名的组合优化问题,它要求在给定一系列城市和每对城市之间的距离(或成本)时,找到一条最短的路径,使得每个城市恰好访问一次,并最终回到起始城市。TSP问题是一个NP困难问题,可以用各种算法来尝试解决,包括穷举搜索、动态规划、回溯算法、启发式算法和近似算法等。TSP问题具有广泛的应用,例如物流规划、电路板布线、旅游路径规划、DNA测序、微芯片芯片布线等。其难点在于当城市数量增加时,解空间呈指数级增长,寻找最优解变得更加困难。
本文拟采用基因遗传算法和灰狼算法求解TSP问题,仅仅作为一个小demo供读者参考,难以解决实际大规模问题。
遗传算法
算法简介
遗传算法(Genetic Algorithm, GA)是一种启发式算法,用于解决优化问题。它模拟了自然界中的生物进化原理,通过计算机程序模拟了生物种群的进化过程,通过对种群中个体的选择、交叉和变异等操作,逐步优化种群中的个体,以找到符合特定优化目标的解。以下是遗传算法的基本步骤:
(1)初始化:随机初始化一组候选解构成的种群。每个候选解通常表示为一个染色体,染色体由基因组成。
(2)选择:通过某种选择策略,选择种群中适应度较高的个体作为父代,用于产生下一代。
(3)交叉(杂交):通过交换父代的染色体片段,生成新的个体。
(4)变异:对新生成的个体进行随机变异操作,引入新的遗传信息。
(5)适应度评估:根据特定的目标函数,评估生成的新个体的适应度表现。
(6)替代:用新生成的个体替代原种群中适应度较低的个体。
(7)终止条件检查:检查是否满足终止条件,如达到最大迭代次数或者找到了满意的解。
(8)迭代:如果终止条件不满足,重复步骤2~7。
遗传算法适用于离散空间和连续空间中的优化问题,在很多应用领域都取得了较好的效果,例如组合优化、函数优化、路径规划、机器学习等。
代码实现
% 随机生成10个城市的坐标
nCities = 10;
cities = [58.4294,34.4566;95.2754,95.4353;
38.6753,26.5246;74.0775,96.9618;
54.5800,87.7577;10.7555,14.3218;
84.3180,14.8688;26.4752,31.0668;
40.2882,35.7375;26.3201,76.2672];
% 计算城市间距离矩阵
distances = squareform(pdist(cities));
% 遗传算法参数
populationSize = 100;
generations = 1000;
% 初始化种群
population = zeros(populationSize, nCities);
for i = 1:populationSize
population(i,:) = randperm(nCities);
end
% 适应度函数 (路径总距离)
fitness = @(chromosome) sum(distances(chromosome, chromosome([2:end 1])));
% 遗传算法循环
for generation = 1:generations
if mod(generation,100)==0
end
% 计算适应度
fitnessValues = fitness(population);
% 选择
[~, indices] = sort(fitnessValues);
parents = population(indices(1:2),:);
% 交叉
crossoverPoint = randi(nCities-1);
offspring1 = [parents(1,1:crossoverPoint) parents(2,crossoverPoint+1:end)];
offspring2 = [parents(2,1:crossoverPoint) parents(1,crossoverPoint+1:end)];
% 修复重复城市 (简单交换)
[~,ia,~] = unique(offspring1);
offspring1(setdiff(1:nCities,ia)) = setdiff(1:nCities,offspring1);
[~,ia,~] = unique(offspring2);
offspring2(setdiff(1:nCities,ia)) = setdiff(1:nCities,offspring2);
% 更新种群
population(end-1,:) = offspring1;
population(end,:) = offspring2;
end
function [newBestPath, newBestFitness] = two_opt(bestPath, ~, distances)
nCities = size(distances, 1); % 城市数目
improved = true;
while improved
improved = false;
for i = 1:nCities-2
for k = i+2:nCities
if k == nCities && i == 1
continue; % 不允许形成环路
end
L1 = distances(bestPath(i), bestPath(i+1)) + distances(bestPath(k), bestPath(mod(k+1-1, nCities)+1));
L2 = distances(bestPath(i), bestPath(k)) + distances(bestPath(i+1), bestPath(mod(k+1-1, nCities)+1));
% 如果有改进,则翻转路径
if L2 < L1
bestPath(i+1:k) = bestPath(k:-1:i+1);
improved = true;
end
end
end
end
newBestPath = bestPath; % 更新后的最佳路径
% 计算新的最优适应度
pathLength = sum(distances(newBestPath, newBestPath([2:end 1])));
newBestFitness = 1 / sum(pathLength); % 因为适应度是路径长度的倒数
end
% 计算路径距离
function totalDistance = computeTotalDistance(distances, path)
nCities = length(path);
totalDistance = 0;
for i = 1:nCities-1
totalDistance = totalDistance + distances(path(i), path(i+1));
end
% 添加路径的最后一段距离(回到起点)
totalDistance = totalDistance + distances(path(nCities), path(1));
end
% 最优路径
[bestFitness, bestIndex] = min(fitnessValues);
bestPath = population(bestIndex,:);
[bestPath, bestFitness] = two_opt(bestPath, bestFitness, distances);
totalDistance = computeTotalDistance(distances, bestPath);
disp([bestFitness, bestPath])
% 绘制结果
figure;
plot(cities(:,1), cities(:,2), 'o', 'MarkerSize', 8, 'MarkerFaceColor', 'b'); % 绘制城市位置
hold on;
% 绘制首尾相连路径
path = [bestPath bestPath(1)]; % 添加起点到路径的末尾,形成闭环
plot(cities(path,1), cities(path,2), 'r-', 'LineWidth', 2); % 绘制路径
plot(cities(bestPath(1),1), cities(bestPath(1),2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'b'); % 特殊标记起点
% 美化
title(sprintf('TSP 遗传算法 - 最佳距离: %.2f', totalDistance)); % 更新标题,包含最佳距离
xlabel('X');
ylabel('Y');
grid on; % 显示网格
hold off;
% 可选步骤: 添加城市编号
for i = 1:length(bestPath)
text(cities(i,1), cities(i,2), [' ' num2str(i)], 'VerticalAlignment','bottom','HorizontalAlignment','right')
end
结果展示
灰狼算法
算法简介
灰狼算法(Grey Wolf Optimizer, GWO)是一种基于群体智能的元启发式算法,灵感来自灰狼群体中的社会行为。由米尔扎赫尔·马赫迪(Mirjalili S)于2014年提出。灰狼算法主要用于解决优化问题,包括连续优化问题、离散优化问题和多目标优化问题。灰狼算法的基本思想是模拟灰狼群体中的社会行为,并借鉴了灰狼的领袖、副领袖和普通狼的行为特征。灰狼算法的执行过程如下:
(1)初始化群体:随机初始化一定数量的灰狼个体,每个个体代表问题的一个潜在解。
(2)确定领导者:根据目标函数值确定当前群体中的 alpha(最优个体)、beta(次优个体)和delta(第三优个体)。这些灰狼代表了搜索空间中的最优解。
(3)更新位置:根据当前领导者的位置,其他的个体更新自己的位置。通过模拟群体中的寻食行为,个体根据 alpha、beta 和 delta 的位置更新自己的位置。这一步代表了灰狼群体中的社会行为。
(4)迭代:重复执行步骤2和步骤3,直到满足终止条件(如达到最大迭代次数)。
代码实现
% MATLAB 灰狼算法求解 TSP 问题
% 初始化城市坐标和距离矩阵
nCities = 10;
cities = [58.4294,34.4566;95.2754,95.4353;
38.6753,26.5246;74.0775,96.9618;
54.5800,87.7577;10.7555,14.3218;
84.3180,14.8688;26.4752,31.0668;
40.2882,35.7375;26.3201,76.2672];
distances = squareform(pdist(cities));
dist(cities)
% 算法参数
wolf_count = 20; % 狼群的数量
iterations = 100; % 迭代次数
alpha = [];
alpha_dist = inf; % 阿尔法(Alpha)狼的距离设置为无穷大
% 初始化狼群
wolves = zeros(wolf_count, nCities);
for i = 1:wolf_count
wolves(i,:) = randperm(nCities);
end
% 灰狼算法主循环
for iter = 1:iterations
% 计算每匹狼的适应度(路径距离)
fitnesses = zeros(wolf_count, 1);
for i = 1:wolf_count
fitnesses(i) = sum(distances(sub2ind(size(distances),wolves(i,:),[wolves(i,2:end) wolves(i,1)])));
end
% 更新 Alpha, Beta, Delta 狼
[sorted_fitness, sorted_idx] = sort(fitnesses);
if sorted_fitness(1) < alpha_dist
alpha_dist = sorted_fitness(1);
alpha = wolves(sorted_idx(1), :);
end
% 更新狼群位置
for i = 1:wolf_count
% 对于TSP问题,灰狼算法的位置更新策略需要定制,下面使用简单随机交换的方式进行更新
for swapIteration = 1:2 % 每次迭代2次交换
city1 = randi(nCities);
city2 = randi(nCities);
while city1 == city2 % 确保我们有2个不同的城市
city2 = randi(nCities);
end
% 交换两个城市的位置
wolves(i, [city1 city2]) = wolves(i, [city2 city1]);
end
% 计算更新后的适应度
new_fitness = sum(distances(sub2ind(size(distances),wolves(i,:),[wolves(i,2:end) wolves(i,1)])));
% 如果新路径更短,则保留新位置,否则回滚
if new_fitness < fitnesses(i)
fitnesses(i) = new_fitness;
else
% 回滚交换
wolves(i, [city1 city2]) = wolves(i, [city2 city1]);
end
end
end
% 输出最佳解
bestPath = alpha;
bestFitness = 1 / alpha_dist; % 路径长度的倒数作为适应度
function [newBestPath, newBestFitness] = two_opt(bestPath, ~, distances)
nCities = size(distances, 1); % 城市数目
improved = true;
while improved
improved = false;
for i = 1:nCities-2
for k = i+2:nCities
if k == nCities && i == 1
continue; % 不允许形成环路
end
L1 = distances(bestPath(i), bestPath(i+1)) + distances(bestPath(k), bestPath(mod(k+1-1, nCities)+1));
L2 = distances(bestPath(i), bestPath(k)) + distances(bestPath(i+1), bestPath(mod(k+1-1, nCities)+1));
% 如果有改进,则翻转路径
if L2 < L1
bestPath(i+1:k) = bestPath(k:-1:i+1);
improved = true;
end
end
end
end
newBestPath = bestPath; % 更新后的最佳路径
% 计算新的最优适应度
pathLength = sum(distances(newBestPath, newBestPath([2:end 1])));
disp(pathLength)
newBestFitness = 1 / sum(pathLength); % 因为适应度是路径长度的倒数
end
function totalDistance = computeTotalDistance(distances, path)
nCities = length(path);
totalDistance = 0;
for i = 1:nCities-1
totalDistance = totalDistance + distances(path(i), path(i+1));
end
% 添加路径的最后一段距离(回到起点)
totalDistance = totalDistance + distances(path(nCities), path(1));
end
% 输出结果
disp(['Best Fitness: ', num2str(bestFitness)]);
disp(['Best Path: ', num2str(bestPath)]);
[bestPath, bestFitness] = two_opt(bestPath, bestFitness, distances);
totalDistance = computeTotalDistance(distances, bestPath);
disp(bestPath)
% 结果可视化
figure;
plot(cities(:,1), cities(:,2), 'o', 'MarkerSize', 8, 'MarkerFaceColor', 'g'); % 绘制城市位置
hold on;
% 绘制首尾相连路径
path = [bestPath bestPath(1)]; % 添加起点到路径的末尾,形成闭环
plot(cities(path,1), cities(path,2), 'black-', 'LineWidth', 2); % 绘制路径
plot(cities(bestPath(1),1), cities(bestPath(1),2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g'); % 特殊标记起点
% 美化
title(sprintf('TSP 灰狼算法 - 最佳距离: %.2f', totalDistance)); % 更新标题,包含最佳距离
xlabel('X');
ylabel('Y');
grid on; % 显示网格
hold off;
% 可选步骤: 添加城市编号
for i = 1:length(bestPath)
text(cities(i,1), cities(i,2), [' ' num2str(i)], 'VerticalAlignment','bottom','HorizontalAlignment','right')
end
结果展示
本文小节
本文简单介绍了TSP、遗传算法以及灰狼算法,并提供了两种智能算法求解TSP问题的matlab源代码,但都只是简单demo,仅供参考。