1. 程式人生 > >模擬退火演算法(初步)

模擬退火演算法(初步)

關於模擬退火演算法的介紹在知乎,CSDN都有很多前輩給出了自己的介紹,我認為都講得很好。其實模擬退火演算法應用於一維搜尋的話,以概率為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;
}