使用模拟退火 遗传算法 粒子群算法求解TSP问题
城市坐标
data = [
1 565.0 575.0; 2 25.0 185.0; 3 345.0 750.0;
4 945.0 685.0; 5 845.0 655.0; 6 880.0 660.0;
7 25.0 230.0; 8 525.0 1000.0; 9 580.0 1175.0;
10 650.0 1130.0; 11 1605.0 620.0; 12 1220.0 580.0;
13 1465.0 200.0; 14 1530.0 5.0; 15 845.0 680.0;
16 725.0 370.0; 17 145.0 665.0; 18 415.0 635.0;
19 510.0 875.0; 20 560.0 365.0; 21 300.0 465.0;
22 520.0 585.0; 23 480.0 415.0; 24 835.0 625.0;
25 975.0 580.0; 26 1215.0 245.0; 27 1320.0 315.0;
28 1250.0 400.0; 29 660.0 180.0; 30 410.0 250.0;
31 420.0 555.0; 32 575.0 665.0; 33 1150.0 1160.0;
34 700.0 580.0; 35 685.0 595.0; 36 685.0 610.0;
37 770.0 610.0; 38 795.0 645.0; 39 720.0 635.0;
40 760.0 650.0; 41 475.0 960.0; 42 95.0 260.0;
43 875.0 920.0; 44 700.0 500.0; 45 555.0 815.0;
46 830.0 485.0; 47 1170.0 65.0; 48 830.0 610.0;
49 605.0 625.0; 50 595.0 360.0; 51 1340.0 725.0;
52 1740.0 245.0;
];
模拟退火
clear;clc;
dbstop if error
data(:,1) = []; % 除去第一列的城市编号
n = size(data,1);
alpha = 0.99;
ITER = 1000;
Tstart = 100;
Tend = 3;
t = Tstart;
%计算距离矩阵
tempA = repmat(data(:,1),1,n);
tempB = repmat(data(:,2),1,n);
tempC = tempA';
tempD = tempB';
dist = sqrt((tempA-tempC).^2+(tempB-tempD).^2);
clear tempA tempB tempC tempD
%
resnew = 1:n;
resstep = resnew;
resstepbest = resnew;
resbest = resnew;
%
valnew = 0;
for i = 1:n-1
valnew = valnew+dist(resstep(i),resstep(i+1));
end
valnew = valnew+dist(resstep(1),resstep(end));
valstep = valnew;
valbest = valnew;
valstepbest = valnew;
while 1
for Times = 1:ITER
%随机产生扰动
if rand<0.5
%双交换
while 1
% temp = randi([1,n],1,2);
temp = ceil([rand(1),rand(1)].*n);
temp = sort(temp);
if temp(2)~=n
break;
end
end
%交换位置
tempA = resnew(1:temp(1));
tempB = resnew(temp(1)+1:temp(2));
tempB= fliplr(tempB);
tempC = resnew(temp(2)+1:end);
resstep = [tempA,tempB,tempC];
else
%三交换
% temp = randi([1,n],1,3);
temp = ceil([rand(1),rand(1),rand(1)].*n);
temp = sort(temp);
tempA = resnew(1:temp(1));
tempB = resnew(temp(1)+1:temp(2));
tempC = resnew(temp(2)+1:temp(3));
tempD = resnew(temp(3)+1:end);
resstep = [tempA,tempC,tempB,tempD];
end
%计算目标函数值
valstep = 0;
for i = 1:n-1
valstep = valstep+dist(resstep(i),resstep(i+1));
end
valstep = valstep+dist(resstep(1),resstep(end));
%比较函数值 若resstep比resbest小,接受resstep
if valstep<valbest
valnew = valstep;
valbest = valstep;
resbest = resstep;
resnew = resstep;
elseif rand<exp((valnew-valstep)./t)
%以一定概率接受
resnew = resstep;
valnew =valstep;
end
end
resstepbest(end+1,:) = resbest;
valstepbest(end+1) = valbest;
t = t*alpha;
if t<Tend
break;
end
end
len = length(valstepbest);
plot(1:len,valstepbest)
遗传算法
main.m
clear;clc;
dbstop if error
data(:,1) = []; % 除去第一列的城市编号
D.DNALEN = size(data,1);
D.POP_SIZE = 100;%初始种群大小
D.ITER = 1000;
D.CROSSOVER_RATE = 0.9;
D.MUTATE_RATE = 0.05;
%计算距离矩阵
tempA = repmat(data(:,1),1,D.DNALEN);
tempB = repmat(data(:,2),1,D.DNALEN);
tempC = tempA';
tempD = tempB';
D.DIST = sqrt((tempA-tempC).^2+(tempB-tempD).^2);
clear tempA tempB tempC tempD
%生成初始解 使用蒙特卡洛模拟求
% pop = cell(D.POP_SIZE,1);
% for i = 1:D.POP_SIZE
% pop{i,1} = randperm(D.DNALEN);
% end
mont = 100;
pop = cell(D.POP_SIZE,1);
for i = 1:D.POP_SIZE
popcopy = cell(D.POP_SIZE,1);
for j = 1:mont
popcopy{j,1} = randperm(D.DNALEN);
end
v = getfts(popcopy,D);
r = find(v == max(v));
pop{i,1} = popcopy{r(1),1};
end
%开始迭代
resstepbest = cell(D.ITER,1);
valstepbest = zeros(D.ITER,1);
D.fts = getfts(pop,D);
for Times = 1:D.ITER
%选择样本
pop1 = select(pop,D);
%交叉
pop2 = crossover(pop1,D);
%变异
pop3 = mutata(pop2,D);
%计算适应度
D.fts = getfts(pop3,D);
pop = pop3;
row = find(D.fts==max(D.fts));
resstepbest{Times,1} = pop{row(1),1};
valstepbest(Times) = D.fts(row(1));
end
valstepbest = 1./valstepbest;
select.m
function pop1 = select(pop,D)
pop1 = cell(D.POP_SIZE,1);
fts = D.fts;
fts = (fts-min(fts))/(max(fts)-min(fts));
fts = fts./sum(fts);
fts = cumsum(fts,1);
for i = 1:D.POP_SIZE
j = 1;
temp = rand(1);
while fts(j)<temp
j = j+1;
end
pop1{i,1} = pop{j,1};
end
crossover.m
function pop1 = crossover(pop,D)
child = {};
for i = 1:D.POP_SIZE
%如果随机数小于交叉概率则交叉
popcopy = pop;
if rand()<D.CROSSOVER_RATE
selectpop = randi([1,D.POP_SIZE],1,1);
selectpoint = randi([1,D.DNALEN],1,2);
selectpoint = sort(selectpoint);
selectsection = pop{i,1}(selectpoint(1):selectpoint(2));
len = length(selectsection);
col = zeros(1,len);
for j = 1:len
[~,col(j)] = find(pop{selectpop,1}==selectsection(j));
end
popcopy{selectpop,1}(col) = [];
child{end+1,1} = [popcopy{selectpop,1},selectsection];
end
end
t = 1;
pop1 = [pop;child];
mutata.m
function pop1 = mutata(pop,D)
for i = 1:size(pop,1)
if rand()<D.MUTATE_RATE
selectpoint = randi([1,D.DNALEN],1,2);
temp = pop{i,1}(selectpoint(1));
pop{i,1}(selectpoint(1)) = pop{i,1}(selectpoint(2));
pop{i,1}(selectpoint(2)) = temp;
end
end
pop1 = pop;
getfts.m
function fts = getfts(popu,DD)
fts = zeros(size(popu,1),1);
for i = 1:size(popu,1)
pop = popu{i,1};
sum = 0;
for j = 1:DD.DNALEN-1
sum = sum+DD.DIST(pop(j),pop(j+1));
end
sum = sum+DD.DIST(pop(1)+pop(end));
fts(i) = sum;
end
fts = 1./fts;
粒子群算法
粒子群算法优化离散问题需要重新定义速度和位置本文可能某处有错误没能得到理想解
clear;clc;
dbstop if error
data(:,1) = []; % 除去第一列的城市编号
n = size(data,1);%城市个数
tempA = repmat(data(:,1),1,n);
tempB = repmat(data(:,2),1,n);
tempC = tempA';
tempD = tempB';
D.dist = sqrt((tempA-tempC).^2+(tempB-tempD).^2);
clear tempA tempB tempC tempD
%参数设定
D.N = 1000;%粒子个数
D.c1 = 0.8;%自我认知因子
D.c2 = 0.8;%社会学系因子
D.w = 0.5;%惯性权重
D.ITER = 100;%迭代次数
%生成初始解
resnew = cell(D.N,1);%初始可行解
speed = cell(D.N,n);%初始速度交换序
% for i = 1:D.N
% for j = 1:n
% speed{i,j} = [j,j];
% end
% end
for i = 1:D.N
resnew{i,1} = randperm(n);%随机生成解
end
%
respbest = resnew;
valpbest = zeros(D.N,1);
valgbest = -1;
%计算适应度
for i = 1:size(respbest,1)
valpbest(i,1) = getfts(respbest{i,1},D);
if valpbest(i,1)>valgbest
valgbest = valpbest(i,1);
resgbest = respbest{i,1};
end
end
valstepbest = zeros(D.ITER,1);
for Times = 1:D.ITER
for i = 1:D.N%更新N个粒子中每一个粒子
%首先计算粒子当前位置与局部最优解的差,结果为一个交换序ss1
ss1 = getchangearray(respbest{i,1},resnew{i,1});
ss2 = getchangearray(resgbest,resnew{i,1});
temp = mix(speed(i,:),ss1,ss2,D);
speed(i,:) = cell(1,n);
for j = 1:size(temp,2)
speed(i,j) = temp(1,j);
end
resnew{i,1} = updatepos(resnew{i,1},speed(i,:));
ftsi = getfts(resnew{i,1},D);
if ftsi>valgbest
valgbest = ftsi;
resgbest = resnew{i,1};
valpbest(i) = ftsi;
respbest{i,1} = resnew{i,1};
elseif ftsi>valpbest
valpbest(i) = ftsi;
respbest{i,1} = resnew{i,1};
end
end
valstepbest(Times) = 1./valgbest;
end
getchangearray.m
function array = getchangearray(a,b)
%计算交换序a-b
array = cell(1,length(a)-1);
for i = 1:length(a)
check = b(i);
[~,col] = find(a==check);
array{1,i} = [i,col];
temp = b(i);
b(col) = b(i);
b(i) = temp;
end
mix.m
function arr = mix(a,b,c,D)
%输入abc为1*?的元胞数组,每个元素为1*2的行向量,D为参数矩阵,要用D.w D.c1 D.c2
%过程第一步:删去每个数组里[i,i]这样的元素
%第二步:分别以D.w D.c1 D.c2的概率在abc 里抽取元素
%第三步:把抽取的元素拼接起来形成一个1*?的元胞数组
%输出:1*?的元胞数组
arr = {};
% len = size(a,2);
% if isempty(a)
% for i = 1:len
% if rand(1)<D.w
% arr{1,end+1} = a{1,i};
% end
% end
% else
% %剔除a中空的元素
% for i = len:-1:1
% if isempty(a{1,i})
% a(i)=[];
% end
% end
% for i = 1:len
% if rand(1)<D.w
% arr{1,end+1} = a{1,i};
% end
% end
% end
len = size(a,2);
%剔除a中空的元素
for i = len:-1:1
if isempty(a{1,i})
a(i)=[];
end
end
len = size(a,2);
for i = 1:len
if rand(1)<D.w
arr{1,end+1} = a{1,i};
end
end
%剔除bc 中相同元素
len = size(b,2);
for i = len:-1:1
if b{1,i}(1)==b{1,i}(2)
b(i) = [];
end
if c{1,i}(1) == c{1,i}(2)
c(i) = [];
end
end
%挑选bc中元素
for i = 1:size(b,2)
if rand(1)<rand(1)*D.c1
arr{1,end+1} = b{1,i};
end
end
for i = 1:size(c,2)
if rand(1)<rand(1)*D.c2
arr{1,end+1} = c{1,i};
end
end
len = size(arr,2);
t = 52;
if len>t
a = len-t;
for i = 1:a
temp = randi([1,size(arr,2)],1,1);
arr(temp) = [];
end
end
updatepos.m
function a = updatepos(resnew,speed)
%输入:resnew为可行解,speed为状态转移列表
len = size(speed,2);
for i = len:-1:1
if isempty(speed{1,i})
speed(i)=[];
end
end
len = size(speed,2);
for i = 1:len
temp = resnew(1,speed{1,i}(1));
resnew(1,speed{1,i}(1)) = resnew(1,speed{1,i}(2));
resnew(1,speed{1,i}(2)) = temp;
end
a = resnew;
getfts.m
function fts = getfts(a,D)
fts = 0;
for i = 1:length(a)-1
fts = fts+D.dist(a(i),a(i+1));
end
fts = fts+D.dist(a(1),a(end));
fts = 1/fts;