• 模拟退火


    模拟退火首先从某个初始候选解开始,当温度大于0时执行循环。

    在循环中,通过随机扰动产生一个新的解,然后求得新解和原解之间的能量差,如果差小于0,则采用新解作为当前解。

    如果差大于0,则采用一个当前温度与能量差成比例的概率来选择是否接受新解。温度越低,接受的概率越小,差值越大,同样接受概率越小。

    是否接受的概率用此公式计算:p=exp(-ΔE/T)。这里ΔE为新解与原解的差,T为当前的温度。

    由于温度随迭代次数逐渐降低,因此获得一个较差的解的概率较小。

    典型的模拟退火算法还使用了蒙特卡洛循环,在温度降低之前,通过多次迭代来找到当前温度下比较好的解。

    这里使用模拟退火解旅行商问题,因为这个问题本身是一个NP难问题,所以也就求不到最优解,不过应该可以求得一个比较好的解,然后再手工优化。

    %% 模拟退火SA
    %------------------------------------------------------
    %------Kermit.L--------------------------------------
    %------------------------------------------------------
    %% 清除历史变量
    clear all;
    close all;
    clc;
    %% 初始化数据
    n = 34;
    temperature_high = 1000;
    temperature_low = 0.005;
    step = 0.99;
    iter = 50*n;
    LatLon=[116.28,39.54; 121.29,31.14; 117.11,39.09; 106.32,29.32; 126.41,45.45;
    125.19,43.52; 123.24,41.50; 111.48,40.49; 114.28,38.02; 112.34,37.52;
    117.00,36.38; 113.42,34.48; 108.54,34.16; 103.49,36.03; 106.16,38.20;
    101.45,36.38; 87.36,43.48; 117.18,31.51; 118.50,32.02; 120.09,30.14;
    113.00,28.11; 115.52,28.41; 114.21,30.37; 104.05,30.39; 106.42,26.35;
    119.18,26.05; 113.15,23.08; 110.20,20.02; 108.20,22.48; 102.41,25.00;
    90.08,29.39; 114.10,22.18; 113.35,22.14; 121.31,25.03];
    x = LatLon(:,1);
    y = LatLon(:,2);
    h = plot([x;x(1)],[y;y(1)],'r*-','markersize',5,'linewidth',2);
    %% 计算距离
    Lon = x/180*pi;
    Lat = y/180*pi;
    N = length(x);
    dis = ones(N);
    R = 6378.140;
    for i = 1:N
    for j = 1:N
    dLat=Lat(i)-Lat(j);
    dLon=Lon(i)-Lon(j);
    dis(i,j)= 2*R*asin(sqrt(sin(dLat/2)^2+sin(dLon/2)^2*cos(Lat(i))*cos(Lat(j))));
    end
    end
    %% SA主程序
    rout_number = randperm(n);
    city_route = city_route(rout_number,dis);
    while temperature_high > temperature_low
    for i = 1:iter
    [New_route_number,New_route] = change(rout_number ,dis) ;
    if New_route < city_route
    city_route = New_route;
    rout_number = New_route_number;
    elseif exp((city_route - New_route)*2/temperature_high) >rand
    city_route = New_route;
    rout_number = New_route_number;
    end
    end 
    temperature_high = temperature_high *step;
    set(h,'xdata',x([rout_number,rout_number(1)]),'ydata',y([rout_number,rout_number(1)]));
    xlabel(sprintf('Distance=%.1f',city_route),'fontsize',13);
    title(sprintf('Temperature = %.1f',temperature_high),'fontsize',13);
    drawnow;
    end

    function [New_route_number,New_route] = change(rout_number ,dis) 
    n = length(rout_number);
    temp1 = ceil(n*rand);
    temp2 = ceil(n*rand);
    tem1 = min(temp1,temp2);
    tem2 = max(temp1,temp2);
    route_tem = fliplr(rout_number(tem1:tem2));
    New_route_number = [rout_number(1:(tem1-1)),route_tem,rout_number((tem2+1):n)];
    New_route = city_route(New_route_number,dis);
    end

    function city_route = city_route(route_number,dis)
    city_route = 0;
    n = length(route_number);
    for i = 1:n - 1
    city_route = city_route + dis(route_number(i),route_number(i+1));
    end
    city_route = city_route + dis(route_number(n),route_number(1));
    end

    http://www.cnblogs.com/tiandsp/category/348031.html参照

  • 相关阅读:
    求解整数集合的交集(腾讯笔试)
    关于屏幕适配之比例布局
    (转)注册JNI函数的两种方式
    正则表达式记录
    当年一个简单可用的多线程断点续传类
    最近用到的几个工具方法
    Android中包含List成员变量的Parcel以及Parcel嵌套写法示例
    java实现计算MD5
    一个用于去除状态栏和虚拟导航栏的BaseActivity
    MVP的模板
  • 原文地址:https://www.cnblogs.com/Kermit-Li/p/4051923.html
Copyright © 2020-2023  润新知