模拟退火算法

TSP问题

例题一:一位旅行者从一出发点出发,要求经过31个城市(目标点的坐标已给出),并且每个点只能经过一次,最终经过所有点后回到起点。
要求:为旅行者制定一条最短路径。

%%%%%%%%%%%%%%%%%%%%%%模拟退火算法解决TSP问题%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic          %用来记录程序运行时间的
clear all;                      %清除所有变量
close all;                      %清图
clc;                            %清屏
C=[1304 2312;         % 城市坐标
    3639 1315;
    4177 2244;
    3712 1399;
    3488 1535;
    3326 1556;
    3238 1229;
    4196 1044;
    4312 790;
    4386 570;
    3007 1970;
    2562 1756;
    2788 1491;
    2381 1676;
    1332 695;
    3715 1678;
    3918 2179;
    4061 2370;
    3780 2212;
    3676 2578;
    4029 2838;
    4263 2931;
    3429 1980;
    3507 2376;
    3394 2643;
    3439 3201;
    2935 3240;
    3140 3550;
    2545 2357;
    2778 2826;
    2370 2975];                  %31个城市坐标
n=size(C,1);                     %城市数目,即c的行数
T=1000;                           %初始温度
L=100;                           %迭代次数
K=0.99;                          %衰减参数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%城市坐标结构体%%%%%%%%%%%%%%%%%%%%%%%%%%
city=struct([]);                %结构体变量,类似python中的字典
for i=1:n             %city(i)的值为第i座城市的坐标
    city(i).x=C(i,1);
    city(i).y=C(i,2);
end
l=1;                             %统计迭代次数
len(l)=func3(city,n);       %每次迭代后的路线总长度
 
while T>0.001                    %终止温度
    %%%%%%%%%%%%%%%%多次迭代扰动,温度降低之前多次实验%%%%%%%%%%%%%%%
    for i=1:L            
        %%%%%%%%%%%%%%%%%%%计算原路线总距离%%%%%%%%%%%%%%%%%%%%%%%%%
        len1=func3(city,n);         
        %%%%%%%%%%%%%%%%%%%%%%%%%产生随机扰动%%%%%%%%%%%%%%%%%%%%%%%
        %%%%%%%%%%%%%%%%随机置换两个不同的城市的坐标%%%%%%%%%%%%%%%%%
        p1=floor(1+n*rand());           %朝负无穷方向取整,如floor(-1.3)=-2,ceil相反
        p2=floor(1+n*rand());            
        while p1==p2
            p1=floor(1+n*rand());
            p2=floor(1+n*rand());
        end
        %%%%%%%%%%%%%置换两地%%%%%%%%%%%%
        tmp_city=city;
        tmp=tmp_city(p1);
        tmp_city(p1)=tmp_city(p2);
        tmp_city(p2)=tmp;         

        %%%%%%%%%%%%%%%%%%%%%%%%计算新路线总距离%%%%%%%%%%%%%%%%%%%%
        len2=func3(tmp_city,n);     
        %%%%%%%%%%%%%%%%%%新老距离的差值,相当于能量%%%%%%%%%%%%%%%%%
        delta_e=len2-len1;
        %%%%%%%%%%%%新路线好于旧路线,用新路线代替旧路线%%%%%%%%%%%%%%  
        if delta_e<0        
            city=tmp_city;
        else
            %%%%%%%%%%%%%%%%%%依概率选择是否接受新解%%%%%%%%%%%%%%%%%
            if exp(-delta_e/T)>rand()
                city=tmp_city;      
            end
        end
    end
    l=l+1;      %迭代次数
    %%%%%%%%%%%%%%%%%%%%%%%%%计算新路线距离%%%%%%%%%%%%%%%%%%%%%%%%%%
    len(l)=func3(city,n); 
    %%%%%%%%%%%%%%%%%%%%%%%%%%%温度不断下降%%%%%%%%%%%%%%%%%%%%%%%%%%
     T=T*K;   
%     for i=1:n-1
%         plot([city(i).x,city(i+1).x],[city(i).y,city(i+1).y],'bo-');
%         hold on;
%     end
%     plot([city(n).x,city(1).x],[city(n).y,city(1).y],'ro-');
%     title(['优化最短距离:',num2str(len(l))]);
%     hold off;
%     pause(0.005);
end

%%%%%%%%%%%%%%%%%%%%%%%%第一幅图%%%%%%%%%%%%%%%%%%
figure(1);
for i=1:n-1
    plot([city(i).x,city(i+1).x],[city(i).y,city(i+1).y],'bo-');
    hold on;
end
plot([city(n).x,city(1).x],[city(n).y,city(1).y],'ro-');
title(['优化最短距离:',num2str(len(l))])
hold off;
%%%%%%%%%%%%%%%%%%%%%%第二幅图%%%%%%%%%%%%%%%%%%%
figure(2);
plot(len)
% plot(C(:,1),C(:,2),'bo-')以C的第1列为横坐标,第二列为纵坐标
xlabel('迭代次数')
ylabel('目标函数值')
title('路径长变化曲线')
toc

函数极值问题

例题二:求解一元函数y=sin(5*pi *x)/x的最小值,自变量x范围[1,2];
①用代码求解
②用工具箱求解

1.用代码求解

%% II. 一元函数优化
x = 1:0.01:2;
y = sin(5*pi*x) ./ x;
plot(x,y,'linewidth',1.5)        %%%线宽设置1.5
ylim([-1.5, 1.5])
xlabel('x')
ylabel('y')
title('y = sin(5*pi*x) / x')
hold on
%%
% 1. 标记出最大值点
[maxVal,maxIndex] = max(y);
plot(x(maxIndex), maxVal, 'r*','linewidth',2)
text(x(maxIndex), maxVal, {['    X: ' num2str(x(maxIndex))];['    Y: ' num2str(maxVal)]})
hold on
 
%%
% 2. 标记出最小值点
[minVal,minIndex] = min(y);
plot(x(minIndex), minVal, 'ks','linewidth',2)
text(x(minIndex), minVal, {['    X: ' num2str(x(minIndex))];['    Y: ' num2str(minVal)]})

效果:
在这里插入图片描述
2.工具箱求解

%%%%%%%%%%%%%%%%先构造一个cost函数%%%%%%%%%%%%%
function costVal = cost( x )
 
%一元函数优化:
 
costVal = sin(5*pi*x) / x;  %求最小值
 
% costVal = -1 * sin(5*pi*x) / x; %用模拟退火求最大值,可以加个负号或者弄个倒数
  
end

在这里插入图片描述
可视化输出:
在这里插入图片描述
注意:直接用fminbnd解出来是局部最优解
在这里插入图片描述

指派问题

例题三:每行代表A、B、C、D、E每个人单独做甲、乙、丙、丁、戊五个工作的时间。每列代表每个工作分别由每个人完成需要的时间。 即:矩阵中位于(i,j)的元素是第i个人做第j个工作的时间。 试问怎么安排最合理?

示意图

% MarkoveLength 马尔科夫链长度
% DecayScale 温度衰减参数
clc
clear all
MarkoveLength=1000;     %迭代次数
DecayScale=0.9;       % 衰减参数α
Temperature=1000;    % initial temperature
t = 1;    % final temperature
          % 指派矩阵,每个人做每件事所需要的时间
assingnMatrix=[17   14  2   10  1   20;
                5   8  4  18   12    9;
                1   12   2   10  1   20;
                20  6   15  9   7    11;
                17  15  13   10  10  20
                12   7   20  12   9  10];
n=length(assingnMatrix);              
   %% 给出一个初始解
x=[1,2,3,4,5,6];
totalCost = 0;
for i=1:n
    totalCost=totalCost+assingnMatrix(i,x(i));%计算初始解的时间
end
 
BestCost=totalCost;
BestAssign=x;
while (Temperature > t || abs(deltaCost)<2)
    for i = 1:MarkoveLength
        %%%%%%进行扰动%%%%%%%%%%
        r = randperm(6,2); %产生两个随机数,用来交换x中的任务分配顺序
        r1=r(1);
    r2=r(2);
    temp=x(r1);
    x(r1)=x(r2);
    x(r2)=temp;
    %%%%%%%%扰动结束%%%%%%%%%
        %  计算
        totalCost=0;
        for k=1:n
            totalCost=totalCost+assingnMatrix(k,x(k));
        end
        % 判断时间是否优化
        deltaCost=totalCost-BestCost;%f(x')-f(x)
        if deltaCost <= 0
            BestCost = totalCost; % 若时间减少则无条件接受
            BestAssign=x;
        else
            if (rand()<exp(-deltaCost/Temperature))
                BestCost = totalCost;  %否则在一定概率下接受
                BestAssign=x;
            end
        end
    end
    Temperature=Temperature*DecayScale;
end
disp(BestCost);              %最少花费时间
disp(assingnMatrix);          %指派矩阵
disp(BestAssign);               %对应的指派方案

关于如何打出箭头,等等特殊符号


链接1 链接2

总结:
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值