模拟退火——一种玄学算法

模拟退火介绍

模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。

来自百度百科

什么乱七八糟的

说白了就是求最小解。

看来学习此算法,还要学习炼钢(玩匠魂的就当我没说)。

\Huge \color{red} \textbf{注意!模拟退火找的是最小解!}

过程

选定一个温度

炼钢当然要有温度啦!(好像匠魂冶炼炉不需要设定温度,不管他了)。

我们姑且设这个温度为 T ( T emperature )。

大于边界值的处理

随机变化坐标,变化幅度为 T

计算新解与当前解的差 δ

如果新解比当前解优(δ>0),就用新解替换当前解。

否则以 eDET 的概率用新解替换当前解。

温度乘上一个小于1的系数,即降温。

参考资料:SuperJvRuo 的博客

至于那个概率的底数为什么是e,因为概率统计中常用的正态分布中经常以e为底。(纯属猜测,就当我胡说八道吧)

洛谷不能上传svg,这是我在这里转换的。

代码实现

const double eps=1e-14;
double xans,yans;
double ans=1e14;
void simulate_anneal(double delta,int t){
	double xx=xans;
	double yy=yans;
	while(t>eps){
		double xtemp=xans+(rand()*2-RAND_MAX)*t;
		double ytemp=yans+(rand()*2-RAND_MAX)*t;
		double new_ans=f(xtemp,ytemp);
		double DE=new_ans-ans;
		if(DE<0){
			xx=xtemp;
			yy=ytemp;
			xans=xx;
			yans=yy;
			ans=new_ans;
		}
		else if(exp(-DE/t)*RAND_MAX>rand()){
			xx=xtemp;
			yy=ytemp;
		}
		t*=delta;
	}
}

依旧参考了上述博客。

eps的设定是为了防止浮点数误差。

ans设定的初始值无所谓,只要够大就行。(因为找的是最小解)。

提示

跑模拟退火记得要多跑几次。应为模拟退火是玄学算法(使用了rand),如果自己脸不干净很容易\color{red}\textbf{WA}

其他做法

如果单纯求最小值(极值),可以使用费马定理/罗尔定理(某些题不适用)。

xf函数的极值(最小值,最大值,拐点),则f(x)=0

推荐

如果你想了解更多,可以看洛谷日报

posted @   蒟蒻xiezheyuan  阅读(188)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示