模拟退火算法
- 若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 }
浙公网安备 33010602011771号