一、原理介绍
模拟退火算法(Simulated Annealing)是一种通用的优化算法,最初由Kirkpatrick于1983年提出,灵感来源于固体物理学中原子的退火过程。简单来说,模拟退火算法是模拟金属从高温状态到低温状态冷却过程中的微观行为,使得金属的内部结构由无序转变为有序的过程。在优化问题中,可以将最优解看作一个结构有序的状态,而将优化过程看作从初始状态到最优状态迭代过程的退火过程。
模拟退火算法的核心思想是利用概率跳出局部最优解,以期望更好的全局解。模拟退火算法按照一定的比例降低温度,从而使搜索范围减小,最终找到全局最优解的概率逐渐增大,随着时间的推移,概率逐渐趋近于1。
二、优点分析
三、缺点分析
四、代码示例
算法核心代码
/**
* 模拟退火算法
* @param func 目标函数
* @param neighbor 邻域函数
* @param t0 初始温度
* @param tn 最小温度
* @param alpha 降温速率
* @param maxIter 最大迭代次数
*/
double simulatedAnnealing(function)> func, function(vector)> neighbor,
double t0 = 1e4, double tn = 1e-4, double alpha = 0.99, int maxIter = 10000) {
double t = t0; // 当前温度
vector c = {0, 0}; // 初始解
double best = func(c); // 初始解的目标函数值
for (int i = 0; i < maxIter; i++) {
vector nc = neighbor(c); // 产生新解
double delta = func(nc) - best; // 计算目标函数的值差
if (delta < 0) { // 新解更优
c = nc;
best = func(nc);
} else { // 根据一定概率接受劣解
double p = exp(-delta / t); // 接受概率
double r = ((double) rand() / RAND_MAX); // 随机数
if (r < p) {
c = nc;
}
}
t *= alpha; // 降温
if (t < tn) {
break; // 温度达到最小值,退出迭代
}
}
return best;
}
一个简单的例子
/**
* 实现一个简单的例子:在二维平面上寻找离原点最远的点
*/
double distance(vector p) { // 目标函数:点到原点的距离
return sqrt(p[0] * p[0] + p[1] * p[1]);
}
vector perturb(vector p) { // 邻域函数:随机扰动点的坐标
return {p[0] + ((double) rand() / RAND_MAX - 0.5) * 2.0, p[1] + ((double) rand() / RAND_MAX - 0.5) * 2.0};
}
int main() {
srand(time(NULL)); // 初始化随机数生成器
double ans = simulatedAnnealing(distance, perturb, 1e3, 1e-3, 0.99, 1000);
cout << ans << endl;
return 0;
}