智能优化算法解TSP问题

使用模拟退火 遗传算法 粒子群算法求解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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值