遗传算法&灰狼算法求解TSP问题(附matlab代码)

TSP问额

TSP(Traveling Salesman Problem,旅行推销员问题)是一个著名的组合优化问题,它要求在给定一系列城市和每对城市之间的距离(或成本)时,找到一条最短的路径,使得每个城市恰好访问一次,并最终回到起始城市。TSP问题是一个NP困难问题,可以用各种算法来尝试解决,包括穷举搜索、动态规划、回溯算法、启发式算法和近似算法等。TSP问题具有广泛的应用,例如物流规划、电路板布线、旅游路径规划、DNA测序、微芯片芯片布线等。其难点在于当城市数量增加时,解空间呈指数级增长,寻找最优解变得更加困难。
TSP问题
本文拟采用基因遗传算法和灰狼算法求解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,仅供参考。

  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值