【学习笔记】我命由天不由我之随机化庇佑 —— 爬山法 和 模拟退火法

以下均假设最优解是在最低点。

爬山法

爬山算法是一种局部择优的方法,采用启发式方法,是对深度优先搜索的一种改进,它利用反馈信息帮助生成解的决策。

直白地讲,就是当目前无法直接到达最优解,但是可以判断两个解哪个更优的时候,根据一些反馈信息生成一个新的可能解。

因此,爬山算法每次在当前找到的最优方案 xxx 附近寻找一个新方案。如果这个新的解 x′x'x 更优,那么转移到 x′x'x,否则不变。

这种算法对于单峰函数显然可行。

Q:既然都知道是单峰函数了为什么不三分呢?

A:你说的对!直接三分好了。

B:我要是知道是单峰函数,我还在这里骗分???

爬山算法会引入『温度参数』 TTT

类比的说,爬山就是一个醉汉喝得狂醉然后再山上裸奔蹦迪。

他知道该回家了(不然就要跪搓衣板),然后每次会往他认为最低的地方狂奔过去(中途不刹车)。

显然他可能一次恰好奔到山脚然后下山回家,也有可能奔过了到另一座山顶上去了。

不过没关系,醉汉奔过头了还会存在奔回来的可能。

但显然这个过程很没用。仿佛醉汉回家全靠天公作美。

所以在暴走过程中,他会经受山顶寒风的摧残,酒精作用渐渐消减,他变得越发清晰。

他就变得谨慎一点,每次少奔一点以达到山脚最低点位置。

这就要引入『降温参数』来起到缓缓冷静的作用。

关于『降温参数』,一般是 [0.985,0.999][0.985,0.999][0.985,0.999] 中选,这样才能做到慢慢消减。

显然如果存在多个”转折“时,爬山就很容易进入局部最优解,而非全局最优解。

随着头脑逐渐清醒,醉汉蹦出局部最优解的期望就会更小,很有可能一直跳不过去某个坡。

在这里插入图片描述

模拟退火

为什么会有上面情况的产生呢?

其实是因为爬山法的写法,只有在新解优于当前解的时候,我们才会接受新解并移动到相应位置。

根据这种情况,我们知道其实偶尔新解不好我们也要去接受,这样才会存在跳出这个坡的可能。

这就是模拟退火了。

模拟退火相较于爬山就只是多了一个随机接受非最优解的部分,大大增加了找到全局最优解得可能。

以下是追根溯源,由物理和化学知识迁移到信息学上应用:

我们知道在分子和原子的世界中,能量越大,意味着分子和原子越不稳定,当能量越低时,原子越稳定。

『退火』是物理学术语,指对物体加温在冷却的过程。

模拟退火算法来源于晶体冷却的过程,如果固体不处于最低能量状态,给固体加热再冷却,随着温度缓慢下降,固体中的原子按照一定形状排列,形成高密度、低能量的有规则晶体(即全局最优解)。

而如果温度下降过快,可能导致原子缺少足够的时间排列成晶体的结构,结果产生了具有较高能量的非晶体(即局部最优解)。

因此就可以根据退火的过程,给其再增加一点能量,然后再冷却,如果增加能量,跳出了局部最优解,那么本次退火就是成功的。

模拟退火由两个部分组成:Metropolis\text{Metropolis}Metropolis 算法和退火过程。

Metropolis\text{Metropolis}Metropolis 算法就是如何在局部最优解的情况下让其跳出来,是退火的基础。

Metropolis\text{Metropolis}Metropolis 提出的以概率来接受新状态的重要性采样方法,而非使用完全确定的规则,称为Metropolis\text{Metropolis}Metropolis 准则,计算量较低。

在这里插入图片描述

假设我们从 AAA 开始求解。先跳到 BBB,然后发现 BBB 更优,绝对接受。BBB 又跳到 CCC,绝对接受。CCC 跳到 DDD ,哎呀更差了呢!此时我们以一定的概率选择是否接受;假设接受,DDD 又跳到 EEE 发现比之前跳到的所有位置都优,直接接受,EEE 继续跳……\dots\dots ;不接受,就还停在 CCC 又开始随机下一个解。

至于这个接受概率是多少呢?已经有前人计算出来了。x:x:x: 当前最优解,x′:x':x: 产生的新解
P={1E(x′)<E(x)e−E(x′)−E(x)TE(x′)≥E(x)P=\begin{cases}1\quad\quad\quad\quad\quad\quad E(x')<E(x)\\e^{-\frac{E(x')-E(x)}{T}}\quad\quad\ E(x')\ge E(x)\end{cases} P={1E(x)<E(x)eTE(x)E(x) E(x)E(x)
从这个式子我们可以看出,如果新解更优,那么百分之百绝对接受;否则我们会以 PPP 的概率接受。

Metropolis\text{Metropolis}Metropolis 算法虽然说是模拟退火算法的基础,但直接使用的话可能导致寻找解得速度太慢,以至于无法过题。

为了确保在有限的时间收敛,必须设定控制算法收敛的参数。

在上面的公式中,可以调节的参数就是『温度参数』TTT

  • TTT 如果过大,就会导致退火太快,迭代次数不够,最后停留在局部最优值就会结束迭代。
  • TTT 如果较小,则计算时间会增加。

实际应用中采用退火温度表,在退火初期采用较大的 TTT 值,随着退火的进行,逐步降低:

  • 初始的温度 T0T_0T0 应选的足够高,使的所有转移状态都被接受。初始温度越高,获得高质量的解的概率越大,但耗费的时间也越长。

  • 退火速率。

    • 指数式下降:Tn=λTn,n=1,2,3,...T_n=\lambda T_n,n=1,2,3,...Tn=λTn,n=1,2,3,...λ\lambdaλ 即是爬山算法里面的『降温参数』,选取的值同样遵守 <1<1<1 又逼近 111 原则。

      这种方式最常见,且对每一温度,有足够的转移尝试,但其收敛速度比较慢。

    • 其它方式:

      • Tn=T0log⁡(1+t)T_n=\frac{T_0}{\log(1+t)}Tn=log(1+t)T0
      • Tn=T01+tT_n=\frac{T_0}{1+t}Tn=1+tT0
  • 终止温度。当 T0T_0T0 迭代到终止温度时就会结束退火。一般设为 eps=1e-kk∈Z+k\in \Z^+kZ+)。

一般针对数据进行『温度参数』TTT,『降温参数』Δ\DeltaΔ 的调参,在本地手造大数据跑,自己抉择。

对时间和正确性的平衡选取。

有的时候可以用 #include <ctime> 库里面自带的 clock() 函数计时,也可以自己定一个跑的次数。

( clock() / (1.0 * CLOCKS_PER_SEC) ) <= TIME
//返回的是多少秒 所以TIME是个 <1 的浮点数

需要注意是:

  • 初始温度 T0T_0T0 的选取对算法结果有一定的影响,最好是多次运行对结果进行综合判断。
  • 在算法运行初期,温度下降快,避免接受过多的差结果。当运行时间增加,温度下降减缓,以便于更快稳定结果。
  • 当迭代次数增加到一定次数时,结果可能已经达到稳定,但是距离算法结束还有一段时间。在设计程序时应该加入适当的输出条件,满足输出条件即可结束程序。

最后给出流程图总结:又淘了一张好图

img

显然,模拟退火也不一定是对的,这个概率接受就很概率。但对比爬山得到最优解的概率肯定是大大增加的。

例题

Strange function

hdu2899

TTT 次询问,每次给定 yyy

f(x)=6x7+8x6+7x3+5x2−yx(0≤x≤100)f(x)=6x^7+8x^6+7x^3+5x^2-yx\quad(0\le x\le 100)f(x)=6x7+8x6+7x3+5x2yx(0x100) 的最小值。

#include <bits/stdc++.h>
using namespace std;
double y;
const double eps = 1e-8; //终止温度
const double delta = 0.997; //温度变化率
mt19937 wwl(time(0));
uniform_real_distribution < double > range( 0, 100 );double f( double x ) {return 6 * pow(x, 7) + 8 * pow(x, 6) + 7 * pow(x, 3) + 5 * pow(x, 2) - y * x;
}double solve() {double T = 100, x = range( wwl ); //初始温度 以及初始随机解double now = f(x), ans = now;int Time = 8e5; //防止超时的卡点次数while( T > eps and Time -- ) { //要么降温完成 要么被卡时double tx = x + (rand() * 2 - RAND_MAX) * T; //随机扰动产生新解if( 0 <= tx and tx <= 100 ) {double nxt = f(tx);ans = min( ans, nxt );if( nxt < now ) //新状态更小 直接接受x = tx, now = nxt;else if( rand() < exp( ( now - nxt ) / T ) * RAND_MAX ) //在一定概率内仍接受这个解x = tx, now = nxt;}T *= delta; //降温}return ans;
}int main() {int T;scanf( "%d", &T );while( T -- ) {scanf( "%lf", &y );printf( "%.4f\n", solve() );}return 0;
}

[JSOI2004]平衡点 / 吊打XXX

洛谷链接

#include <bits/stdc++.h>
using namespace std;
#define delta 0.996
#define maxn 1005
#define eps 1e-15
struct node { int x, y, w; }g[maxn];
int n;double energy( double x, double y ) {double ans = 0, dx, dy;for( int i = 1;i <= n;i ++ ) {dx = x - g[i].x, dy = y - g[i].y;ans += sqrt( dx * dx + dy * dy ) * g[i].w;}return ans;
}double ansx, ansy, ans, x, y, now;
void Simulate_Anneal() {double T = 5e4;while( T > eps ) {double tx = x + (rand() * 2 - RAND_MAX) * T;double ty = y + (rand() * 2 - RAND_MAX) * T;double tw = energy( tx, ty );if( tw < ans ) ans = tw, ansx = tx, ansy = ty;if( tw < now ) x = tx, y = ty, now = tw;else if( rand() < exp( ( now - tw ) / T ) * RAND_MAX )x = tx, y = ty;T *= delta;}
}signed main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ )scanf( "%d %d %d", &g[i].x, &g[i].y, &g[i].w );for( int i = 1;i <= n;i ++ ) x += g[i].x, y += g[i].y;x /= n, y /= n;ansx = x, ansy = y;now = ans = energy( x, y );Simulate_Anneal();Simulate_Anneal();Simulate_Anneal();Simulate_Anneal();printf( "%.3f %.3f\n", ansx, ansy );return 0;
}

Haywire

洛谷链接

#include <bits/stdc++.h>
using namespace std;
#define TIME 0.9
#define eps 1e-10
#define delta 0.998
#define maxn 15
int n;
int p[maxn];
int f[maxn][5];int energy() {int ans = 0;for( int i = 1;i <= n;i ++ )for( int j = 1;j <= 3;j ++ )ans += fabs( p[i] - p[f[i][j]] );return ans;
}int main() {mt19937 wwl(time(NULL));scanf( "%d", &n );uniform_int_distribution < int > id( 1, n );for( int i = 1;i <= n;i ++ )for( int j = 1;j <= 3;j ++ )scanf( "%d", &f[i][j] );iota( p + 1, p + n + 1, 1 );int ans = energy();while( ( clock() / (1.0 * CLOCKS_PER_SEC) ) <= TIME ) {for( int i = 1;i <= n;i ++ ) p[i] = i;double T = 1e5; int x, y;while( T > eps ) {do { x = id( wwl ), y = id( wwl ); }while( x == y );swap( p[x], p[y] );int now = energy();if( now < ans ) ans = now;else if( rand() > exp( ( now - ans ) / T ) * RAND_MAX )swap( p[x], p[y] );T *= delta;}}printf( "%d\n", ans / 2 );return 0;
}

学习参考博客:

https://www.cnblogs.com/flashhu/p/8884132.html

https://blog.csdn.net/weixin_42398658/article/details/84031235

https://zhuanlan.zhihu.com/p/266874840?utm_source=qq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Strange Memory Gym - 102832F

Strange Memory Gym - 102832F 题意&#xff1a; 有一颗n个节点的树&#xff0c;求下面公式的值&#xff1a; 题解&#xff1a; a ⊕ b c 可以推出a ⊕ c b 那么ai⊕ajalca(i,j)a_{lca(i,j)}alca(i,j)​,可以得到&#xff1a;ai⊕alca(i,j)a_{lca(i,j)}alca(i,j)​aj,ai就…

.net core 使用RSA获取私钥证书并签名

以前我们使用RSA加密主要是使用RSACryptoServiceProvider这个类&#xff0c;在.NET Core中也有这个类&#xff0c;但是这个类并不支持跨平台&#xff0c;所以如果你是用这个类来进行加/解密在windows上运行是完全没有错误的&#xff0c;但是只要你一放到Linux下就会出现异常。查…

CDN流量调度问题(2021CCPC华为云挑战赛)

CDN流量调度问题 题意&#xff1a; 有n个线路&#xff0c;每个线路的任务量为a[i],初始状态下&#xff0c;每个线路起初只有一个节点&#xff0c;每个线路完成任务所需时间为 现在你要给每个线路增加节点&#xff0c;所有增加的节点总数不超过m&#xff0c;第i个线路增加节点…

.NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容

.NET Core 3.0 Preview 3已经推出&#xff0c;它包含了一系列关于ASP.NET Core的新的更新。下面是该预览版的更新列表&#xff1a;Razor组件改进:单项目模板 新的Razer扩展Endpoint路由集成预呈现Razor类库中的Razor组件改进事件处理 Forms & validation运行时编译Worker服…

世界五星级大厨经典菜品集

本blog只是记录C学习以来掉过的一些坑&#xff0c;写下来防止自己下一次再犯&#xff0c;顺便分享 持续更新&#xff0c;到死为止菜品特套1&#xff1a;vector.size() ~ 的使用菜品特套2&#xff1a;if-else的缩进菜品特套3&#xff1a;int范围边界的1ll使用菜品特套4&#xff…

ASP.NET Core 使用 Google 验证码(Google reCAPTCHA)

关心最多的问题&#xff0c;不FQ能不能用&#xff0c;答案是能。Google官方提供额外的域名来提供服务&#xff0c;国内可以正常使用。一. 前言验证码在我们实际的生活场景中非常常见&#xff0c;可以防止恶意破解密码、刷票、论坛灌水、刷注册等等。现在的网站基本都有使用验证…

P4173 残缺的字符串

P4173 残缺的字符串 题意&#xff1a; 有A&#xff0c;B两个串&#xff0c;每个串都有通配符&#xff0c;问A为模板串&#xff0c;对于 B 的每一个位置 i&#xff0c;从这个位置开始连续 m 个字符形成的子串是否可能与 A 串完全匹配&#xff1f; 题解&#xff1a; 我们定义…

FFT/NTT卷积神级副本

干货满满的良心博客传送至只有小怪的村庄——请开始你的逆天之路A&#xff1a;P1919B&#xff1a;P4157刷怪升级——转战玄灵大陆C&#xff1a;P6300D&#xff1a;P3763E&#xff1a;P3321F&#xff1a;P5641G&#xff1a;P4986H&#xff1a;P4721——获得知识药剂一瓶——分治…

程会玩 | 在.NET Core里操作Git

点击上方蓝字关注“汪宇杰博客”Git是很多程序员的首选源代码版本控制工具&#xff0c;我最近也从TFVC切换到了Git&#xff0c;受益匪浅。今天我就来带大家看看如何在.NET Core里操作Git。为啥要这么做首先&#xff0c;这件事情的意义&#xff0c;并不是闲的蛋疼。我们确实有很…

一个实时收集MySql变更记录的组件CanalSharp.AspNetCore

一、关于CanalSharpCanalSharp 是阿里巴巴开源项目 Canal 的 .NET 客户端。为 .NET 开发者提供一个更友好的使用 Canal 的方式。Canal 是mysql数据库binlog的增量订阅&消费组件。CanalSharp 是 Canal 的 .NET 客户端&#xff0c;它与 Canal 是采用的Socket来进行通信的&…

[Abp vNext 源码分析] - 1. 框架启动流程分析

一、简要说明本篇文章主要剖析与讲解 Abp vNext 在 Web API 项目下的启动流程&#xff0c;让大家了解整个 Abp vNext 框架是如何运作的。总的来说 &#xff0c;Abp vNext 比起 ABP 框架更加精简。因为在 vNext 版本当中&#xff0c;原来归属于 Abp 库的许多内置的基本组件 (组织…

使用 MSIX 打包 DotNetCore 3.0 客户端程序

如何你希望你的 WPF 程序能够以 Windows 的保护机制保护起来&#xff0c;不被轻易反编译的话&#xff0c;那么这篇文章应该能帮到你。介绍MSIX 是微软于去年的 Windows 开发者日峰会 上推出的全新应用打包解决方案。其目的是取代旧式的软件打包方式&#xff0c;可用于 Win32、W…

使用 C# 和 Blazor 进行全栈开发

Blazor 是将 C# 引入浏览器的 Microsoft 试验框架&#xff0c;正好可以填补欠缺的 C# 一环。如今&#xff0c;C# 程序员可以编写桌面、服务器端 Web、云、电话、平板电脑、手表、电视和 IoT 应用程序。Blazor 填补了欠缺的一环&#xff0c;C# 开发人员现在可以直接在用户浏览器…

AWS vs K8s 是新的 Windows vs Linux

作者&#xff1a;Ian Miell是开源程序员、演讲师、作家和博客写手以前……如果你与我一样&#xff0c;年过四十&#xff0c;又在IT行业工作&#xff0c;恐怕还记得每个人使用Windows&#xff0c;一小群但越来越多的人在业余时间埋头编译Linux的年代。Windows用户见此情形会困惑…

Asp.Net Core中的静态文件-12

目录本文出自《从零开始学 ASP.NET CORE MVC》目录 推荐文章&#xff1a;配置 ASP.NET Core 请求(Request)处理管道Asp.Net Core 中的静态文件在这个视频中我们将讨论如何使 ASP.NET Core 应用程序&#xff0c;支持静态文件&#xff0c;如 HTML&#xff0c;图像&#xff0c;CSS…

在.net core 中PetaPoco结合EntityFrameworkCore使用codefirst方法进行开发

在.net core开发过程中&#xff0c;使用最多的就是注入方法。但是在.net core使用PetaPoco时&#xff0c;PetaPoco还不支持进行注入方式进行处理一些问题。今天对PetaPoco进行了一些扩展&#xff0c;可以很方便的将PetaPoco进行注入操作&#xff0c;使用和EF很相似&#xff0c;…

F-Pairwise Modulo

d数组是来算&#xff08;x整除y&#xff09;*y中y比x小的数 s数组是算&#xff08;x整除y&#xff09;*y中y比x大的数 &#xff08;x整除y&#xff09;*y 看x对于前面大于他的数是枚举&#xff0c;对于前面小于他的数是d树状数组储存。 d中 x整除y表示x中有多少个y 所以 …

【微服务学习】Polly:熔断降级组件

何为熔断降级“熔断器如同电力过载保护器。它可以实现快速失败&#xff0c;如果它在一段时间内侦测到许多类似的错误&#xff0c;会强迫其以后的多个调用快速失败&#xff0c;不再访问远程服务器&#xff0c;从而防止应用程序不断地尝试执行可能会失败的操作&#xff0c;使得应…

A - Junk-Mail Filter HDU - 2473

只是这样合并&#xff0c;分割点的时候就不能分了。 这样合并再加上虚拟节点&#xff0c;那么每个你要求的节点就的下面就不连其他节点了&#xff0c;这样就可以进行删除操作了 #include<iostream> #include<algorithm> #include<cstdio> #include<cstr…

为什么不要使用 async void

问题在使用 Abp 框架的后台作业时&#xff0c;当后台作业抛出异常&#xff0c;会导致整个程序崩溃。在 Abp 框架的底层执行后台作业的时候&#xff0c;有 try/catch 语句块用来捕获后台任务执行时的异常&#xff0c;但是在这里没有生效。原始代码如下&#xff1a;public class …