模拟退火算法

  • f( Y(i+1) ) <= f( Y(i) )  (即移动后得到更优解),则总是接受该移动;
  • f( Y(i+1) ) > f( Y(i) )  (即移动后的解比当前解要差),则以一定的概率接受移动,而且这个概率随着时间推移逐渐降低(逐渐降低才能趋向稳定)相当于上图中,从B移向BC之间的小波峰时,每次右移(即接受一个更糟糕值)的概率在逐渐降低。如果这个坡特别长,那么很有可能最终我们并不会翻过这个坡。如果它不太长,这很有可能会翻过它,这取决于衰减 t 值的设定。

  • 二、模拟退火算法

     

     

    模拟退火算法是受上述概率公式规律的启发,做如下的操作:多次迭代搜索全局最优解,每次迭代的参数T都适当减小。开始时,T设为一个较大的值,此时接受质量差的解的概率大,使得有较多的机会跳离局部最优,这时内层循环类似于一个单纯的随机搜索。然后逐渐减小T值,使得接受质量差的解的概率越来越小,接受质量好的解的概率越来越大。到算法结束时,T值变得很小,使得模拟退火的最后阶段类似于普通的爬山法:如果新解比当前解更好,则总是接受它。下面是算法伪代码:

     

     

    void sa()

     

     

    {

     

     

       i = 0;

     

     

       初始化T;

     

     

       随机选择一当前点Vc;

     

     

       do {

     

     

                  do {

     

     

                         在Vc邻域内选择一新点Vn;

     

     

                         if ( eva l(Vn) > eva l(Vc) )

     

     

                           Vc = Vn;

     

     

                         else {

     

     

                                p =

     

     

                                x = random[0, 1];

     

     

                                if (p > x)

     

     

                                  Vc = Vn;

     

     

                         }

     

     

                  }while(不满足终止条件);

     

     

                  T按一定规则减小;

     

     

                  i++;

     

     

           }while(不满足停机条件);

     

     

    }

     

     

    模拟退火算法在实现时,要确定四个特殊的条件:

     

     

    (1)初始“温度”T的值是多少?初始温度T=1000,100还是其它值呢?

     

     

    (2)温度应衰减多少或者多大因子?是每次减少5,还是%1?

     

     

    (3)如何选取终止条件?是执行一定数目的迭代还是使用其它规则?

     

     

    (4)如何选择停机条件,即“凝固”温度是多少?

  • 这是一道判断距离的题目,代码写的十分的完美,所以暂且放在这里用于以后学习
 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6 using namespace std;
 7 
 8 const int maxn = 21;
 9 int n;
10 double x[maxn], y[maxn];
11 double dist[maxn][maxn];
12 
13 struct Path{
14     int path[maxn];
15 
16     Path(){
17         for(int i = 0; i < n; i++) path[i] = i;
18     }
19 
20     Path(const Path& p){
21         memcpy(path, p.path, sizeof path);
22         swap(path[rand() % n], path[rand() % n]);
23     }
24 
25     double dist(){
26         double ans = 0;
27         for(int i = 1; i < n; i++){
28             ans += ::dist[path[i - 1]][path[i]];
29         }
30         return ans;
31     }
32 };
33 
34 
35 
36 bool accept(double delta, double temper){
37     if(delta <= 0) return true;
38     return rand() <= exp((-delta) / temper) * RAND_MAX;
39 } 
40 
41 double solve(){
42     const double max_temper = 10000;
43     const double dec = 0.999;
44     double temp = max_temper;
45     Path p;
46     while(temp > 0.01){
47         Path p2(p);
48         if(accept(p2.dist() - p.dist(), temp)) p = p2;
49         temp *= dec;
50     }
51     return p.dist();
52 }
53 
54 int main(){
55     srand(19260817U);
56     cin >> n;
57     for(int i = 0; i < n; i++) {
58         scanf("%lf%lf", x + i, y + i);
59     }
60     for(int i = 0; i < n; i++){
61         dist[i][i] = 0;
62         for(int j = i + 1; j < n; j++){
63             dist[i][j] = dist[j][i] = hypot(x[i] - x[j], y[i] - y[j]);
64         }
65     }
66     double ans = 1./0;
67     int T = 155;
68     while(T--){
69         ans = min(ans, solve());
70     }
71     printf("%.2lf", ans);
72 } 

 

posted @ 2017-08-09 23:11  大水标  阅读(246)  评论(0)    收藏  举报