首页 > 其他分享 >模拟退火学习笔记

模拟退火学习笔记

时间:2024-07-28 09:00:51浏览次数:9  
标签:int 退火 重物 笔记 学习 模拟退火 SA 温度

模拟退火学习笔记

前言

不知道为啥突然有闲情学这个...

模拟退火 (Simulated Annealing) , 简称 \(SA\) .

是一种基于随机化的算法,无门槛,主要是为了骗分...

不是正解!!!!

根据 爬山算法 的过程,我们发现:对于一个当前最优解附近的非最优解,爬山算法直接舍去了这个解。而很多情况下,我们需要去接受这个非最优解从而跳出这个局部最优解,即为模拟退火算法。

关于退火

什么是退火?

退火是一种金属热处理工艺,指的是将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却。目的是降低硬度,改善切削加工性;消除残余应力,稳定尺寸,减少变形与裂纹倾向;细化晶粒,调整组织,消除组织缺陷。准确的说,退火是一种对材料的热处理工艺,包括金属材料、非金属材料。而且新材料的退火目的也与传统金属退火存在异同。

贺的百度百科

设 \(E| \{x_i\} |\) 表示某一物质体系在微观状态 \(\{x_i\}\) 下的内能,对于给定温度 \(T\) , 若体系处于热平衡态时, \(E |\{x_i\}|\) 服从 Boltzmann 分布:

\[f = c(T) \times e ^ {- \frac{E|\{x_i\}|}{k \times T}} \]

其中 \(k\) 为 Boltzmann 常数。
\(T\) 下降, \(E\) 随之下降。只要温度下降足够慢,体系可以长久保持热平衡态。

当我们退火时,刚开始的时候温度高,分子运动剧烈,变化率较高;

然而对于温度降下来之后,分子逐渐趋于稳定,于是分子变化比较小。

模拟退火,就是模拟的这个过程。

具体实现

当然,什么都不能摆脱随机化。

我们设初始温度 \(T_0 > 1000\) , 降温系数 \(\zeta = \{0.996 , 0.995 , \dots\}\) , 末尾温度 \(T_k > 0\) , 在 \(10 ^ {-15}\) 左右 .

对于我们的新横坐标来说,显然他要有局部的特性,并随时间的延长,温度下降,转移地方要更加稳定,就是离旧的横坐标近一点,因此在随机时要有 \(T\) 这个自变量。

然而对于我们新的这个值 \(y\) , 旧的值为 \(x\) , \(\Delta = y - x\)

退火的过程、转移的概率如下:

\[P(x , y) = \begin{cases} 1 \ , \ \Delta < 0 \\ e ^ {- \frac{\Delta}{T}} \ , \ \Delta > 0 \end{cases}\]

为什么会存在第二种转移呢?

是为了跳出局部最优解,可能进入新的更优解的地方。

贴图:

具体实现 [JSOI2004] 平衡点 / 吊打XXX

题目描述

如图,有 \(n\) 个重物,每个重物系在一条足够长的绳子上。

每条绳子自上而下穿过桌面上的洞,然后系在一起。图中 \(x\) 处就是公共的绳结。假设绳子是完全弹性的(即不会造成能量损失),桌子足够高(重物不会垂到地上),且忽略所有的摩擦,求绳结 \(x\) 最终平衡于何处。

注意:桌面上的洞都比绳结 \(x\) 小得多,所以即使某个重物特别重,绳结 \(x\) 也不可能穿过桌面上的洞掉下来,最多是卡在某个洞口处。

\(1\le n\le 1000\)

\(-10000\le x_i,y_i\le10000, 0<w_i\le1000\)】

题解

假设平衡点坐标为 \((X , Y)\)

那么对于一个重物(坐标为 \(x_i , y_i\) )贡献的重力势能为:

\(E = \sqrt{(X - x_i) ^ 2 + (Y - y_i) ^ 2} \times w_i\)

我们是需要将所有的势能和最小化即可。

注意因为我们为了让答案尽可能的对, \(SA\) 过程要跑很多遍。

CODE
#include <bits/stdc++.h>
using namespace std ;
#define int long long 
const int N = 2e5 + 100 ; 
inline int read() {
	int x = 0 , f = 1 ; 
	char c = getchar() ; 
	
	while (c < '0' || c > '9') {
		if (c == '-') f = -f ; 
		
		c = getchar() ; 
	}
	
	while (c >= '0' && c <= '9') {
		x = x * 10 + c - '0' ; 
		c = getchar() ; 
	}
	
	return x * f ; 
}

struct Physics {
	int x , y , gravity ; 
} a[N] ; 
int n ; double first , second , ans = 1000000000 , averx , avery ; 

void Energy(double x , double y , double & statics) {
	statics = 0 ; 
 
	for (int i = 1 ; i <= n ; ++ i) {
		statics += sqrt((x - a[i].x) * (x - a[i].x) + (y - a[i].y) * (y - a[i].y)) * a[i].gravity ; 
	}
}

void SA() {
	double T = 3000 ; 
	double x = first , y = second , now , delta_E ; 
	while (T > 1e-16) {
		x = first + (rand() * 2ll - RAND_MAX) * T ; 
		y = second + (rand() * 2ll - RAND_MAX) * T ; 
		Energy(x , y , now) ; delta_E = now - ans ; 

		if (delta_E < 0) {
			ans = now , first = x , second = y ; 
		} else if (exp(- delta_E / T) * RAND_MAX > rand()) {
			first = x , second = y ; 
		}

		T *= 0.996 ; 
	}
}

inline void solve() {
	SA() ; SA() ; SA() ; SA() ; SA() ; 
	SA() ; SA() ; SA() ; SA() ; SA() ; 
	SA() ; SA() ; SA() ; SA() ; SA() ; 
	SA() ; SA() ; SA() ; SA() ; SA() ; 
	SA() ; SA() ; SA() ; SA() ; SA() ; 
}

double sumx , sumy ; 
signed main() {
	srand((unsigned long long)(new char)) ; 
	n = read() ; 
	for (int i = 1 ; i <= n ; ++ i) {
		a[i] = {read() , read() , read()} ; 
		sumx += a[i].x ; sumy += a[i].y ; 
	}

	averx = 1.0 * sumx / n ; 
	avery = 1.0 * sumy / n ; 

	Energy(averx , avery , ans) ; 
	first = averx , second = avery ; 
	solve() ; 

	printf("%.3lf %.3lf" , first , second) ; 
}

结尾撒花 \(\color{pink}{✿✿ヽ(°▽°)ノ✿}\)

标签:int,退火,重物,笔记,学习,模拟退火,SA,温度
From: https://www.cnblogs.com/hangry/p/18327857

相关文章

  • 深度学习--数据预处理
    数据预处理importosimportpandasaspdimporttorch#创建csv文件os.makedirs(os.path.join('..','data'),exist_ok=True)data_file=os.path.join('..','data','house_tiny.csv')#往文件里写内容withopen(data_file,'w......
  • 为什么老板现在要学习财务
    一、新常态经济。什么是“新常态”?现在企业赚钱越来越难,利润越来越薄,需要通过财务手段来精细化核算和精细化管理,民营企业已进入抠细节、抠成本、抠利润的时代,而财务是支撑企业精细化管理的核心工具。二、大数据时代。经营决策需要数据,数据则主要来自财务部门。财务部门是......
  • websocket学习
    1、使用场景1.实时聊天应用:在线聊天室、即时通讯软件(如微信、QQ等)都广泛使用了WebSocket技术。(多个客户端与服务器进行交互,消息广播,客户端消息监听)2.实时数据更新,如股票行情、天气预报、新闻推送等,网页游戏小广告3.协同编辑,在协同编辑应用中,多个用户需要同时编辑同一份文档......
  • Python学习笔记46:游戏篇之外星人入侵(七)
    前言到目前为止,我们已经完成了游戏窗口的创建,飞船的加载,飞船的移动,发射子弹等功能。很高兴的说一声,基础的游戏功能已经完成一半了,再过几天我们就可以尝试驾驶飞船击毁外星人了。当然,计分,游戏次数,背景音乐,开始启动等按钮的功能需要我们慢慢添加,这些功能不影响游戏的使用,影......
  • Python学习笔记45:游戏篇之外星人入侵(六)
    前言飞船模块的功能基本已经完成。今天继续完成子弹模块的功能。子弹模块子弹和飞船模块,在游戏逻辑中有一种生成与被生成的表面关系,因为子弹在游戏中是由飞船发射的。但是在我们实际抽象的过程中,飞船与子弹并不是is的关系,甚至可以说不是has的关系。因此我们需要将两个对......
  • CMake学习(二)
    CMake(二)1、C++标准指定CMake有一些特殊的变量,它们有的是在底层创建的,或者是在项目代码设置时对CMake有意义的,其中许多变量以CMAKE_开头的在我们自己声明配置变量时,需要尽可能避免采用这种命名方式在这些特殊的变量中,包含有2个比较常用的,CMAKE_CXX_STANDARD和CMAKE_CXX_ST......
  • Verilog编程学习之—呼吸灯
    Verilog编程-呼吸灯1.设计目标用FPGA产生占空比变化的PWM波,控制LED灯由暗变亮的变化。2.设计思路设置PWM波的步长为2us,周期为2ms,每个周期内LED亮的时间由0增加至999,再从999减少至0,依次循环,就可以看到LED灯由暗变亮再由亮变暗的循环过程。可以设置一个占空比寄存器duty_r和一个......
  • CMake学习(一)
    CMake学习(一)1、简介CMake是一个强大的软件构建系统,可以用简单的语句来描述所有平台的安装(编译过程)可以编译源代码、制作程序库、产生适配器(wrapper)、还可以用任意的顺序建构执行档https://cmake.org/2、构建基础项目最基础的CMake项目是由单个源代码文件构建的可执行......
  • 《昇思25天学习打卡营第7天|函数式自动微分》
    函数式自动微分神经网络的训练主要使用反向传播算法,模型预测值(logits)与正确标签(label)送入损失函数(lossfunction)获得loss,然后进行反向传播计算,求得梯度(gradients),最终更新至模型参数(parameters)。自动微分能够计算可导函数在某点处的导数值,是反向传播算法的一般化。自动微分......
  • 《昇思25天学习打卡营第5天|数据变换 Transforms》
    数据变换Transforms通常情况下,直接加载的原始数据并不能直接送入神经网络进行训练,此时我们需要对其进行数据预处理。MindSpore提供不同种类的数据变换(Transforms),配合数据处理Pipeline来实现数据预处理。所有的Transforms均可通过map方法传入,实现对指定数据列的处理......