- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
旅行商问题(TSP). 一个商人欲从自己所在的城市出发,到若干个城市推销商品,然后回到其所在的城市。如何选择一条周游路线,使得商人经过每个城市一次且仅一次后回到起点,并使他所走过的路径最短?
TSP 即Travelling Salesman Problem. 中文翻译过来就是旅行商问题.
旅行商问题是一个典型的NP难问题。NP指的是Non-deterministic Polynomial,即多项式复杂程度的非确定性问题。由于该问题的组合特性,旅行商问题已成为测试新算法的标准问题,如模拟退火、神经网络和演化算法等都用旅行商问题作为测试用例。旅行商问题的一个实例可由一个距离矩阵所给定.
用遗传算法求解旅行商问题时,适应函数可以取为目标函数或目标函数的一个简单变换,选择策略可以是轮盘赌选择,所以算法设计的重点主要集中在以下三个方面:
下面讨论周游路线常用的几种表示及其相应的遗传算子.
主要有3种编码表示 。
近邻表示将一条周游路线表示成 \(n\) 个城市 的一个排列 \(Π=(Π_1,Π_2,...,Π_n)\) , \(Π_i=j\) 当且仅当周游路线中从城市 \(i\) 到达的下一个城市为 \(j\) . 。
例如,排列 。
\((2~4~8~3~9~7~1~5~6 )\) 。
表示周游路线为 \(1-2-4-3-8-5-9-6-7-1.\) 。
显然,每一条周游路线都对应一个近邻表示,但任一近邻排列却不一定对应于一条周游路线 .
例如,排列 。
\((2~4~8~1~9~3~5~7~6)\) 。
导致了不完全回路 \(1-2-4-1\) ,因而无法对应一条周游路线。所以周游路线的近邻表示就没有必要再往下介绍.
次序表示将一条周游路线表示为 \(n\) 个城市的有序表,其中,表中的第 \(i\) 个元素在 \(1\) 到 \(n-i+1\) 取值。该表的一个优点是每一个次序表示都对应于一条合法的周游路线.
次序表示的基本思想是:取 \(n\) 个城市的某个排列 \((Π_1,Π_2,...,Π_n)\) 作为参照排列,通常取 \((1,2,...,n)\) 作为参照排列,然后将周游路线中的城市按照其在参照排列中的次序记录下来,形成一个具有 \(n\) 个元素的有序表.具体做法如下:
对给定的一条路径 \(Π_1-Π_2-...-Π_n\) ,首先记录城市 \(Π_1\) 在参照排列 \((p_1,p_2,...,p_n)\) 中的次序 \(i_1\) ,将 \(Π_1\) 从 \((p_1,p_2,...,p_n)\) 中删除得 \(n-1\) 个城市的参照排列 \((q_1,q_2,...,q_k),k=n-1\) ,再记录城市 \(Π_2\) 在参照排列 \((q_1,q_2,...,q_k),k=n-1\) 中的次序 \(i_2\) ,然后将城市 \(Π_2\) 从 \((q_1,q_2,...,q_k),k=n-1\) 中删除得 \(n-2\) 个城市的参照排列 \((r_1,r_2,...,r_k), k=n-2\) ,以此类推,直到城市 \(Π_n\) 的次序 \(i_n\) 记录下来为止。有序表 \((i_1,i_2,...,i_n)\) 称为路径 \(Π_1-Π_2-...-Π_n\) 的次序表示。注意 \(i_j\) 的取值范围为 \(1 \le i_j \le n-j+1\) . 。
例如,若取 \((1,2,...,9)\) 作为参照排列,那么路径 。
\(1-2-4-3-8-5-9-6-7\) 。
的次序表示为 。
\((1~1~2~1~4~1~3~1~1)\) . 。
虽然次序表示具有可以使用传统杂交算子的优点,但实验表明在次序表示与传统的杂交算子相结合所得到的结果并不理想 .
路径表示也许是周游路径最自然的一种表示。例如,一条周游路线 。
\(5-1-7-8-9-4-6-2-3-5\) 。
可表示为排列 \((5~1~7~8~9~4~6~2~3)\) ,这里将排列看成一个首尾相接的圆形排列.
本次案例对周游路线的编码采用路径表示的方案 .
路径表示的杂交算子主要有以下几个:
部分映射杂交算子通过从一个父体中选择一个子序列,并尽可能多地保持另一个父体中城市的次序和位置的方式产生 后代。具体过程如下:
对给定的两个父体 \(p_1,p_2\) ,部分映射杂交首先随机地在父体上选择两个杂交点,然后交换父体 \(p_1,p_2\) 在这两点之间的中间段得到两个后代 \(o_1,o_2\) ,这一交换同时定义了一个部分映射。这时, \(o_1,o_2\) 上除了这两点之间的城市外,其他的城市尚未确定。对 \(o_1,o_2\) 中尚未确定的城市,分别保留各自父体 中与中间段无冲突的城市,对与中间段有冲突的城市,则执行部分映射,直到与中间段无冲突为止,再将该城市填入相应的位置即可.
例如,给定下列两个父体,随机地选择两个杂交点 (以"|"标记), 。
\(p_1=(2~6~4~|~7~3~5~8~|~9~1),\) 。
\(p_2=(4~5~2~|~1~8~7~6~|~9~3),\) 。
将 \(p_1,p_2\) 在这两点之间 的中间段交换得 。
\(o_1=(\#~\#~\#~|~1~8~7~6~|~\#~\#),\) 。
\(o_2=(\#~\#~\#~|~7~3~5~8~|~\#~\#),\) 。
其中, \(\#\) 表示待定城市。这一交换所确定的部分映射为 。
\(1<->7,\) 。
\(8<->3,\) 。
\(7<->5,\) 。
\(6<->8.\) 。
然后,再从各自父体中填入与中间段无冲突的城市得 。
\(o_1=(2~\#~4~|~1~8~7~6~|~9~\#),\) 。
\(o_2=(4~\#~2~|~7~3~5~8~|~9~\#),\) 。
对 \(o_1,o_2\) 中与中间段有冲突的 \(\#\) 部分,执行部分映射,直到无冲突为止。例如, \(o_1\) 中的第一个 \(\#\) 初始为6,但6与中间段中的城市冲突,部分映射将6映射到8,但8仍与中间段冲突,部分映射到3,3与中间段不冲突,这时第一个 \(\#\) 填入3.类似地可以确定其他的 \(\#\) 部分,最后所得到的 \(o_1,o_2\) 如下:
\(o_1=(2~3~4~|~1~8~7~6~|~9~5),\) 。
\(o_2=(4~1~2~|~7~3~5~8~|~9~6),\) 。
部分映射杂交实现起来比较麻烦,跳来跳去的,所以本次案例不适用部分映射杂交 .
次序杂交算子通过从一个父体中选择一个子序列,并保持另一个父体中城市的相对次序的方式产生后代。具体操作如下:
对给定的两个父体 \(p_1,p_2\) ,次序杂交首先随机地再父体上选择两个杂交点,分别保留父体 \(p_1,p_2\) 在这两个杂交点之间的中间段得到两个后代 \(o_1,o_2\) .这时 \(o_1,o_2\) 上除了这两个中间段中的城市外,其他的城市尚未确定。对 \(o_1\) 中尚未确定的城市,首先将 \(p_2\) 中的城市从第二个杂交点开始按其相对次序列出,然后将该序列中在 \(o_1\) 中间段中出现的城市删除,再将剩余子序列从第二个杂交点填入 \(o_1\) 的相应位置即可。同样的方式可得 \(o_2\) . 。
例如,给定下列两个父体,随机地选择两个杂交点, 。
\(p_1=(2~6~4~|~7~3~5~8|~9~1),\) 。
\(p_2=(4~5~2~|~1~8~7~6~|~9~3),\) 。
保留 \(p_1,p_2\) 上两个杂交点之间的中间段得 。
\(o_1=(\#~\#~\#~|~7~3~5~8~|~\#~\#),\) 。
\(o_2=(\#~\#~\#~|~1~8~7~6~|~\#~\#),\) 。
其中, \(\#\) 表示待定城市。然后从第二个杂交点 开始,将 \(p_2\) 中的城市按原次序列出得 。
\(9-3-4-5-2-1-8-7-6,\) 。
从中删除 \(o_1\) 中间段中的城市得 。
\(9-4-2-1-6.\) 。
将该子序列从第二个杂交点开始依次填入到 \(o_1\) 中得 。
\(o_1=(2~1~6~|~7~3~5~8~|~9~4),\) 。
类似可得 。
\(o_2=(4~3~5~|~1~8~7~6~|~9~2).\) 。
本次案例使用的杂交算子就是次序杂交 .
循环杂交算子如下产生后代:后代中的每个城市是某个父体相应位置的城市。具体过程如下:
对给定的两个父体 \(p_1=(u_1,u_2,...,u_n)\) , \(p_2=(v_1,v_2,...,v_n)\) ,先确定后代 \(o_1\) 中来自于父体 \(p_1\) 中的城市。假定 \(p_1\) 中的第一个城市 \(u_1\) 在 \(o_1\) 中,即将 \(o_1\) 中的第一个位置填入 \(u_1\) ,那么 \(o_1\) 中的城市 \(v_1\) 不可能来自 \(p_2\) ,必来自于 \(p_1\) .假设 \(v1=u_1\) ,若 \(u_i\) 还没填入 \(o_1\) 中,则在 \(o_1\) 的第 \(i\) 个位置上填入 \(u_i\) .同样, \(o_1\) 中的城市 \(v_i\) 不可能来自 \(p_2\) ,必来自于 \(p_1\) .假设 \(v_i=u_i\) ,若 \(u_j\) 还没有填入 \(o_1\) 中,则在 \(o_1\) 的第 \(j\) 个位置上填入 \(u_j\) .这样继续下去直到将某个 \(u_k\) 填入到 \(o_1\) 后, \(p_2\) 中与其相应的城市 \(v_k\) 也已经填入到 \(o_1\) 为止,这就构成一个循环。再将 \(p_2\) 中尚未在 \(o_1\) 中出现的城市直接填入到 \(o_1\) 中相应的位置即可。类似可得后代 \(o_2\) . 。
例如,给定下列两个父体:
\(p_1=(2~6~4~7~3~5~8~9~1),\) 。
\(p_2=(4~5~2~1~8~7~6~9~3),\) 。
先从 \(p_1\) 中取第一个城市2作为 \(o_1\) 的第一个城市得 。
\(o_1=(2~\#~\#~\#~\#~\#~\#~\#~\#).\) 。
\(p_1\) 中城市2对应 \(p_2\) 中的城市4,而4还没有填入到 \(o_1\) 中,将4填入到 \(o_1\) 中得 。
\(o_1=(2~\#~4~\#~\#~\#~\#~\#~\#).\) 。
\(p_1\) 中城市4对应 \(p_2\) 中的城市2,但2已经填入 \(o_1\) 中了,这完成了一个循环。将 \(p_2\) 中尚未在 \(o_1\) 中出现的城市直接填入到 \(o_1\) 中相应的位置后得 。
\(o_1=(2~5~4~1~8~7~6~9~3).\) 。
类似可得 。
\(o_2=(4~6~2~7~3~5~8~9~1).\) 。
基于位置杂交类似于次序杂交,唯一的区别在于:在基于位置杂交中,不是选取父体的一个连续的子序列,而是随机地选取一些位置,再按次序杂交的方式产生后代.
例如,给定下列两个父体:
\(p_1=(2~6~4~7~3~5~8~9~1),\) 。
\(p_2=(4~5~2~1~8~7~6~9~3),\) 。
假定随机地选取的位置为2,3,6,8.保留 \(p_1,p_2\) 上这些位置的城市得 。
\(o_1=(\#~6~4~\#~\#~5~\#~9~\#),\) 。
\(o_2=(\#~5~2~\#~\#~7~\#~9~\#),\) 。
然后从最后一个选取位置的后面开始,将 \(p_2\) 中的城市按原次序列出得 。
\(3-4-5-2-1-8-7-6-9,\) 。
从中删除 \(o_1\) 中已经选取的城市得 。
\(3-2-1-8-7.\) 。
将该子序列从最后一个选取位置的后面开始依次填入 \(o_1\) 中得 。
\(o_1=(2~6~4~1~8~5~7~9~3),\) 。
\(o_2=(6~5~2~4~3~7~8~9~1).\) 。
路径表示的变异算子有下面几个:
倒位变异的过程如下:
首先在父体上随机地选择两个城市,然后将这两个城市之间的子序列反转.
例如,设有父体 。
\((1~2~3~4~5~6~7~8~9).\) 。
假定随机地选择的两个城市为3, 7,则对该个体进行倒位变异后得 。
\((1~2~7~6~5~4~3~8~9).\) 。
插入变异的过程如下:
首先在父体中随机地选择一个城市,然后在该城市插入到某个随机的位置上.
例如,设有父体 。
\((1~2~3~4~5~6~7~8~9).\) 。
假定随机地选择的城市为2,随机地选择位置为6,那么将城市2插入到第6个位置上得 。
\((1~3~4~5~6~2~7~8~9).\) 。
要注意的是,当将所选择的城市插入到所选择的位置上时,有两种城市移动方式。若所选择的城市在要插入的位置的左边,则所选择城市到插入位置之间的城市(包括插入位置上的城市)向左移动一个位置,否则向右移动一个位置.
移位变异的过程如下:
首先在父体中随机地选择一个连续子序列,然后将该子序列插入到某个随机的位置上.
例如,设有父体 。
\((1~2~3~4~5~6~7~8~9).\) 。
假定随机地选择的子序列为4 5 6,随机地选择的位置是8,那么经移位变异后得 。
\((1~2~3~7~8~4~5~6~9).\) 。
互换变异随机地选择两个城市,并将这两个城市互换.
例如,设有父体 。
\((1~2~3~4~5~6~7~8~9).\) 。
随机地选择的两个城市为3,7,那么经互换变异后得 。
\((1~2~7~4~5~6~3~8~9).\) 。
本次案例采用的变异算子是互换变异 .
本次使用 Matlab 来实现遗传算法解决旅行商问题。其中,所涉及到的各子函数放到附录中.
程序目录结构如下:
%% 遗传算法解决旅行商问题
%% 清屏
clear; close; clc;
%% 加载数据
city = xlsread('./resources/city.xlsx'); % 加载Excel表格数据
%% 参数初始化
% 主要的参数
popsize = 200; % 种群大小
pc = 0.9; % 交叉概率
pm = 0.05; % 变异概率
gen = 1000; % 迭代次数
% 次要的参数
D = Distance(city); % 城市距离矩阵
[citycount, ~] = size(city); % 记录城市个数
best_fitvalue = zeros(gen, 1); % 记录每一代最优的适应值
minlen = zeros(gen, 1); % 记录每一代路径最小值
%% 初始化种群
pop = initpop(popsize, citycount);
%% 开始迭代
for it = 1:gen
fitvalue = fitness(pop, D); % 计算适应值
[best_fitvalue(it), best_index] = max(fitvalue); % 记录适应值最高的值与下标
best_solution = pop(best_index, :); % 记录当前代的最优个体
minlen(it) = decode(best_solution, D, citycount); % 记录每一代的最短路径
newpop = parent_selection(pop, fitvalue); % 父体选择
newpop = crossover(newpop, pc); % 交叉
newpop = mutation(newpop, pm); % 变异
pop = newpop; % 更新种群
pop(mod(ceil(rand * citycount), citycount)+1, :) = best_solution; % 保留最优个体
end
%% 画图
figure(1)
for i = 2:citycount
plot([city(best_solution(i-1), 1), city(best_solution(i), 1)], ...
[city(best_solution(i-1), 2), city(best_solution(i), 2)], 'bo-');
hold on;
end
plot([city(best_solution(citycount), 1), city(best_solution(1), 1)], ...
[city(best_solution(citycount), 2), city(best_solution(1), 2)], 'ro-');
title(['优化最短距离:', num2str(min(minlen))]);
figure(2)
plot(best_fitvalue);
xlabel('迭代次数')
ylabel('目标函数值')
title('适应值变化曲线')
figure(3)
plot(minlen);
xlabel('迭代次数')
ylabel('目标函数值')
title('最短路径变化曲线')
%% 打印周游路线
disp('周游路线:')
words = num2str(best_solution(1));
for i = 2:citycount
words = append(words, '->', num2str(best_solution(i)));
end
words = append(words, '->', num2str(best_solution(1)));
disp(words);
效果图:
从图1中可以看到优化最短路径为0.11798(单位自己换算,一开始用的点是经纬度表示的)周游路线已绘出,没有交叉的小圈,基本上是最优解了;图2是适应值变化曲线,这个是记录每一代的最优个体的适应值,一直在波动,很符合遗传算法的随机性;图3记录的是每一代的最短路径,基本在第800代左右收敛到最优解;命令窗口也将周游路线打印出来,得本次运行的最短路线为 。
6->7->3->2->5->9->11->13->15->17->19->20->18->16->14->12->10->8->1->4->6.
function D = Distance(city)
%Distance - 计算两个城市之间的距离
%
% Syntax: D = Distance(city)
%
% Long 返回的是一个距离矩阵,记录每两个城市之间的距离
[n, ~] = size(city);
D = ones(n, n);
for i = 1:n
for j = i:n
D(i, j) = sqrt((city(i, 1) - city(j, 1)).^2 + (city(i, 2) - city(j, 2)).^2);
D(j, i) = D(i, j);
end
end
end
function path_len = decode(code, D, n)
%decode - 对种群个体解码
%
% Syntax: path_len = decode(code, D, n)
%
% Long 返回的是路径长度,一个1*1的矩阵(变量)
path_len = 0;
for j = 2:n
path_len = path_len + D(code(j-1), code(j));
end
path_len = path_len + D(code(n), code(1));
end
function pop = initpop(popsize, citycount)
%initpop - 初始化种群
%
% Syntax: pop = initpop(popsize, citycount)
%
% Long 返回一个popsize*citycount的矩阵
pop = ones(popsize, citycount);
for i = 1:popsize
pop(i, :) = randperm(citycount);
end
end
function fitvalue = fitness(pop, D)
%fitness - 计算适应值
%
% Syntax: fitvalue = fitness(pop, D)
%
% Long 返回的是px行1列的矩阵,记录的是当前种群pop的每一个个体的适应值
[px, py] = size(pop);
fitvalue = zeros(px, 1);
for i = 1:px
fitvalue(i) = decode(pop(i, :), D, py);
end
fitvalue = 1./fitvalue;
fitvalue = fitvalue./sum(fitvalue); % 适应值归一化
end
function newpop = parent_selection(pop, fitvalue)
%parent_selection - 父体选择
%
% Syntax: newpop = parent_selection(pop, fitvalue)
%
% Long 返回和pop一样大小的矩阵,新种群,采用轮盘赌选择策略
[px, py] = size(pop);
newpop = zeros(px, py);
%% 设计轮盘
p = cumsum(fitvalue); % 在计算适应值函数中已经做好归一化
%% 转动轮盘
r = sort(rand(px, 1));
j = 1;
for i = 1:px
while r(i) > p(j)
j = j + 1;
end
% r(i) <= p(j)
newpop(i, :) = pop(j, :);
end
end
function newpop = crossover(pop, pc)
%crossover - 交叉
%
% Syntax: newpop = crossover(pop, pc)
%
% Long description
[px, ~] = size(pop);
newpop = pop;
for i = 2:2:px
if rand <= pc
[newpop(i, :), newpop(i-1, :)] = sub_crossover(pop(i, :), pop(i-1, :));
end
end
end
function [newcode1, newcode2] = sub_crossover(code1, code2)
%sub_crossover - 子交叉函数
%
% Syntax: [newcode1, newcode2] = sub_crossover(code1, code2)
%
% Long 采用次序杂交的方式进行杂交
newcode1 = code1;
newcode2 = code2;
n = length(code1);
front = -1;
rear = -1;
while front < 1 || rear <= front || rear >= n
front = ceil(rand * n);
rear = ceil(rand * n);
end
p2 = code2;
p1 = code1;
for i = front:rear
p2(p2 == code1(i)) = [];
p1(p1 == code2(i)) = [];
end
j = 1;
for i = 1:n
if i < front || i > rear
newcode1(i) = p2(j);
newcode2(i) = p1(j);
j = j + 1;
end
end
end
function newpop = mutation(pop, pm)
%mutation - 变异
%
% Syntax: newpop = mutation(pop, pm)
%
% Long 采用互换变异算子
[px, py] = size(pop);
newpop = pop;
cnt = ceil(rand*py/2); % 确定变异点的个数
pos = mod(ceil(rand(px, cnt) * py), py) + 1; % 变异点的位置
for i = 1:px
if rand <= pm
for j = 2:2:cnt
temp = newpop(i, pos(i, j));
newpop(i, pos(i, j)) = newpop(i, pos(i, j-1));
newpop(i, pos(i, j-1)) = temp;
end
end
end
end
>>> city
city =
109.4177 24.3085
109.4443 24.3086
109.4394 24.3089
109.4226 24.3090
109.4471 24.3092
109.4277 24.3093
109.4347 24.3101
109.4168 24.3102
109.4470 24.3167
109.4175 24.3186
109.4469 24.3230
109.4197 24.3240
109.4467 24.3285
109.4218 24.3313
109.4465 24.3350
109.4205 24.3372
109.4462 24.3392
109.4209 24.3397
109.4413 24.3415
109.4356 24.3418
下面是我在bilibli发布的视频讲解链接: Cukor丘克-遗传算法解决旅行商问题 。
最后此篇关于遗传算法解决旅行商问题(TSP)的文章就讲到这里了,如果你想了解更多关于遗传算法解决旅行商问题(TSP)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
遗传算法解决旅行商问题 作者:Cukor丘克 环境:MatlabR2020a + vscode 问题描述 旅行商问题(TSP). 一个商人欲从自己所在的城市出发,到
完全有向图上的旅行商问题是否存在多项式时间算法? 最佳答案 不太可能。如果有的话,您可以采用任何图形并添加所有具有非常高权重的缺失边。这将允许解决问题的标准版本,已知该问题是 NP 难的。 关于gra
我正在使用 R 中的 TSP 包解决旅行推销员问题,但试图实现预定的起点和终点。 该软件包显然允许设置旅程的起点,如下所述: How to specify a starting city using
我是 Java 新手,正在尝试获取多个城市之间的最短路径。 从某个点(城市)开始,经过所有其他城市,结束在同一城市 从 JSON 文件解析日期: { "city": "City1", "latitud
我需要编写诸如旅行推销员问题之类的程序,但带有节点。我需要获得较少错位的金额。 我不知道如何使用玻尔兹曼常数实现模拟退火算法。 我已经编写了第一部分的代码: `导入java.util.ArrayLis
为学校做一个项目,我们实现最近邻启发式算法(我已经完成了),以及旅行推销员问题,我们进行详尽的搜索(然后我们分析算法、它们的时间复杂度等)。我们的老师说要四处寻找用于穷举搜索部分的代码(或修改),而不
我正在使用 C 语言中的蚁群优化来解决 TSP 问题。我认为我的实现是正确的,但我的程序不起作用。我知道我的代码中存在内存问题,因为当我运行程序时,控制台会写“核心已转储”。我使用 gdb 来查找错误
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 3 年前。 Improve th
在其他帖子中,Networkx 被建议为“我的 friend ”。但是对于 TSP 问题的特定解决方案,似乎没有现成的可用函数。即 Creating undirected graphs in Pyth
我正在使用一段代码来使用动态编程实现 TSP。我找到了这段代码,但无法弄清楚 compute() 函数及其工作原理。我不知道变量是什么,也不知道它是如何计算路径的。非常感谢任何帮助。 #include
我正在努力实现一个基于模拟退火的程序来解决旅行商问题。我得到的所有解决方案都不令人满意,我不知道如何改进我的实现。显然我不是在关注基准测试,而只是在寻找视觉上可接受的最短路径。如果有人可以启发我,我将
我正在尝试用机票解决旅行商问题,所以主要思想是从一个机场开始,只访问所有机场一次,然后返回原点。 举个例子:从洛杉矶国际机场出发访问 LV、CA、NY结束 LAX。 这是一个经典的图形问题,我们可以将
我想问一下如何在自组织映射 (SOM) 中实现 TSP。 SOM 算法/工作如何获取 TSP 路径的结果? 最佳答案 旅行商问题 (TSP) 是一个优化问题。有许多算法试图解决 TSP,包括像遗传算法
TSP 的成本函数如何运作?假设我有一个距离为 100 的游览,我稍微更改了游览,对原始游览进行了 4 次更改,现在它的距离为 50。 成本函数会给我 4,因为那是变化的数量;还是 50,因为距离的变
我正在尝试解决一个包含大约 10,000 个城市的非常大的 TSP。为了并行化我的任务,我想将这些城市划分为集群并为每个集群解决 TSP。 我想要一种可以将我的城市分成集群的方法(基于城市密度/该集群
我一直在尝试弄清楚如何使用回溯来解决 TSP。如何计算“成本”? 矩阵: ∞ 20 30 10 11 15 ∞ 16 4 2 3 5 ∞ 2 4 19 6
解决 TSP 问题的最常见启发式方法(特别是 Kernighan–Lin 启发式方法)需要处理随机生成的路线并从中改进解决方案。然而,我想出的唯一方法是生成顶点的随机排列并检查它是否是一个解决方案。
我正在尝试使用分支定界算法解决 TSP。 我必须建立一个包含成本的矩阵,但我遇到了这个问题:我有坐标为 x 和 y 的城市。 旅行的费用是 ceil(ceil(sqrt((x1-x2)^2+(y1-y
我希望在 Java 中实现模拟退火算法,以找到 Travelling Salesman Problem 的最佳路径。 ,到目前为止,我已经实现了蛮力,并希望修改该代码以使用模拟退火。显然,蛮力和模拟退
我无法理解为什么该算法不返回 TSP 的最短路径。 vector tsp(int n, vector >& cost) { long nsub = 1 > opt(nsub, vector(n)
我是一名优秀的程序员,十分优秀!