关于模拟退火算法的介绍在知乎,优快云都有很多前辈给出了自己的介绍,我认为都讲得很好。其实模拟退火算法应用于一维搜索的话,以概率为1收敛于最优,而且早熟收敛发生的概率很低。和粒子群相比,收敛速度慢,依赖于降温的速度,但是粒子群实在是太容易收敛到局部最优了,而且一旦到了局部最优就跳不出来了,因为粒子群算法是没有变异的。
综合下来,我觉得遗传算法和模拟退火算法都比较优秀,在一维搜索的表现都比较好。当然,每种算法都有存在的价值,这几种算法我现在都只应用在了一维搜索上。我一开始了解这些算法的目的是为了求六自由度平台的正解问题,之后如果我真的写了,再去考虑吧。毕竟是一个六输入六输出,我要考虑一波怎么去写。
下面给出模拟退火算法的C++代码:
//模拟退火算法
#include "iostream"
#include "algorithm"
#include "vector"
#include "random"
#include "iterator"
#include "cmath"
#define MAX_COUNT 50000
using namespace std;
double fitness_function(double x)//求此函数的最大值
{
//return x*x*sin(3 * x)*cos(2 * x);
//return -x*(x - 1);//适应函数
return x + 10 * sin(5 * x) + 7 * cos(4 * x);
}
class Anneal
{
public:
Anneal() = default;
Anneal(const Anneal& a)
{
temp = a.temp;
rate = a.rate;
pre = a.pre;
cur = a.cur;
}
~Anneal() {};
double temp = 200;
double rate = 0.98;
double pre;
double cur;
};
int main()
{
static uniform_real_distribution<double> u(0, 1);//随机数生成范围
static default_random_engine e;//随机数生成引擎
static uniform_real_distribution<double> uu(-10, 10);//随机数生成范围
static default_random_engine ee;//随机数生成引擎
Anneal a;
a.pre = fitness_function(uu(ee));
for (int i = 0; i < MAX_COUNT; i++)
{
a.cur = fitness_function(uu(ee));
if (a.cur >= a.pre)
a.pre = a.cur;
else
{
double delta = a.cur - a.pre;//注意这是负数
if (u(e) < exp(delta/a.temp))//指数为负,因此一定在0到1间变化
a.pre = a.cur;
}
a.temp *= a.rate;
cout << a.pre << endl;
}
while (1);
return 0;
}