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

【学习笔记】模拟退火

时间:2023-10-18 21:25:33浏览次数:40  
标签:int nowans 笔记 学习 新解 模拟退火 1e 最优

快一年前写的东西了。从洛谷上搬过来滴。

以下是正文。

简介

模拟退火 Simulate Anneal 是一种随机化算法。用于求解方案数量极大(甚至是无穷的)而且不是一个单峰函数的问题。

模拟退火的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法是一种通用的优化算法,其物理退火过程由加温过程、等温过程、冷却过程这三部分组成。

算法思路

对于问题随机出一个新解,如果更优,以 \(100\%\) 的概率接受;如果不优,以一个与 新解和最优解的差 和 当前时间 相关的概率接受它。

这样执行很多遍,逐渐由局部最优解扩展至全局最优解,答案区间逐步缩小、稳定。

实现过程

降温

模拟退火有三个参数:初始温度 \(B\) ,中止温度 \(E\) ,降温系数 \(W\) 。

其中, \(B\) 为较大数( \(1e3,1e4\) 左右), \(E\) 略大于 \(0\) (\(1e-8,1e-12\) 左右), \(W\) 略小于 \(0\) 。

开始时使温度 \(T=B\) ,\(T\) 不断乘上 \(W\) ,直到 \(T<E\) 为止。

大致过程如下:

可以看出,随着温度的降低,解逐渐稳定下来,并逐渐集中在最优解附近。

新解

在当前解的基础上生成一个新解,根据题目具体情况选定。一般 \(T\) 越大,变化情况越大。当然不方便实现的时候不用这么搞。


如果新解更优,则接受新解;

其他情况:

设原来的最优解为 \(a\) ,新解 \(b\) ,差 \(c\) 。

显然, \(T\) 越高、\(c\) 越大时概率大是最合理的。概率一般取

\[e^{-{\frac{c}{x\times T}}} \]

其中 \(x\) 为随机数。注意合理选择 \(x\) 的范围。一般不需要。

调参

常用的有以下几种:

  • 暴力对拍。

  • 换随机数种子。

  • 多跑几遍模拟退火。形如:while(clock()-t<0.99*CLOCKS_PER_SEC) 不跑到 \(0.99s\) 就不停下来。当然 0.99 是卡的太紧了。

例题

P2210 Haywire

模拟退火计算全排列中交换的两个数,每次 \(O(n)\) 算出新解,再依据概率决定是否更新即可。模拟退火注意多跑几遍。参数可以使用 \(B=10000,E=1e-12,W=0.99\) 。

#define int long long
int a[15][5],b[15],n,nowans=0x3f3f3f3f3f3f3f3f;
const double B=10000,E=1e-12,W=0.999;
//nowans:全局最优解
int f(){//计算需要的干草堆
    int ans=0;
    for(int i=1;i<=n;i++) for(int j=1;j<=3;j++) ans+=abs(b[i]-b[a[i][j]]);
    return ans;
}
void solve(){
    int t=clock();
    while(clock()-t<0.9*CLOCKS_PER_SEC){//能跑多少遍就跑多少遍
        for(double j=B;j>=E;j*=W){
            int x=0,y=0;
            do{
                x=1+rand()%n;
                y=1+rand()%n;
            }while (x==y);//不同的数交换
            swap(b[x],b[y]);//提前交换
            int tmp=f()/2;
            if(tmp<=nowans) nowans=tmp;
            else if(exp((nowans-tmp)*1.0/j)<rand()*1.0/RAND_MAX) swap(b[x],b[y]);
            //如果当前不交换,就把提前交换的换回去
        }
    }
}
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=3;j++) cin>>a[i][j];
        b[i]=i;//初始化全排列
    }
    solve();
    cout<<nowans;
    return 0;
}

P3878 分金币

因为要分成两部分,所以可以划分 \(a_1\) 到 \(a_{(n+1)/2}\) 为一段,剩下为另一段。

与上一题一样,随机交换两个数, \(O(n)\) 算新解,再依据概率决定是否更新即可。模拟退火注意多跑几遍。参数可以使用 \(B=1000,E=1e-10,W=0.9\) ,每组数据跑 \(500\) 遍。

int n,nowans,a[1005];
const double B=1000,E=1e-10,W=0.9;
int f(){//计算当前分办下的金币之差
    int sum1=0,sum2=0;
    for(int i=1;i<=(n+1)/2;i++) sum1+=a[i];
    for(int i=(n+1)/2+1;i<=n;i++) sum2+=a[i];
    return sum1>sum2?sum1-sum2:sum2-sum1;
}
void solve(){
    for(double i=B;i>=E;i*=W){
        int x=0,y=0;
        x=rand()%n+1,y=rand()%n+1;
        swap(a[x],a[y]);//提前交换
        int ans=f();
        if(ans<nowans) nowans=ans;
        else if(exp((nowans-ans)/i)<(double(rand())/RAND_MAX)) swap(a[x],a[y]);
        //如果当前不交换,就把提前交换的换回去
    }
}
signed main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        nowans=0x3f3f3f3f;
        int tis=500;//运行500遍
        while(tis--) solve();
        cout<<nowans<<'\n';
    }
    return 0;
}

标签:int,nowans,笔记,学习,新解,模拟退火,1e,最优
From: https://www.cnblogs.com/FReQuenter5156/p/simulate_anneal.html

相关文章

  • 【图论】二分图的判定 学习笔记
    二分图的判定记无向图\(G=(V,E)\),若存在点集\(A,B\)满足:\(A\cupB=V\)\(A\capB=\varnothing\)\(\foralle=(u,v)\inE\),满足\(u,v\)不同时在\(A\)或\(B\)中。则称图\(G\)为二分图,\(A,B\)分别称作二分图的左部与右部。二分图的判定定理下面三......
  • 论文学习:AGCRN
    AdaptiveGraphConvolutionalRecurrentNetworkforTrafficForecasting用于交通预测的自适应图卷积循环网络会议:NIPS2020作者:LeiBai, LinaYao, CanLi, XianzhiWang, CanWang论文地址:https://dl.acm.org/doi/10.5555/3495724.3497218代码地址:https://github.com/......
  • 算法笔记-有效括号序列题解
    描述给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列。括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。数据范围:字符串长度0≤n≤10000要求:空间复杂度O(n),时间复杂......
  • 《机器学习与优化》PDF高质量正版电子书
    下载:https://pan.quark.cn/s/5fb461be1a45......
  • 【笔记】问题控制与管理&故障、问题、已知错误、变更请求之间的逻辑关系&问题管理流程
    【笔记】问题控制与管理&故障、问题、已知错误、变更请求之间的逻辑关系问题控制与管理与故障管理的尽可能快地恢复服多的目标不同,问题管理是要防止再次发生故障**例如你制作了一个报表,用户填写了问题数据进去,因此报错提示了,让用户换个数据或者和用户说不要这样填写的方法就算......
  • EFCore学习笔记 - 主键
    主键1、自增主键简单,但是不满足分布式,并发性能差long、int等类型主键,默认为自增自增字段的代码中不能为Id赋值,必须保持默认值0,否则运行的时候就会报错因为是数据库生成的值,所以SaveChanges()后会自动把主键的值更新到Id例子:插入帖子后,自动重定向......
  • EF Core学习笔记 - 配置
    约定配置1、主要规则表名采用DbContext中对应的DbSet的属性名数据表列的名字采用实体类属性的名字,列的数据类型采用喝实体类属性类型最兼容的类型,可以自定义设置数据表列的可空性取决于对应实体类属性的可空性名字为Id的属性为主键如果主键为short,int或者lo......
  • 2023/10/18 学习笔记
    VLAN网络vlan——虚拟局域网由于交换机所有的端口都在同一个广播域,只要发送广播会产生大量的垃圾信息,同时会有安全隐患(病毒)。解决这个问题有两种方法:物理解决:需要在交换机之间安装路由器(成本太大)逻辑解决:使用vlan虚拟网络技术vlan的优势:控制广播增强网络安全......
  • 【笔记】数据库、网络故障与恢复
    【笔记】数据库故障与恢复数据库故障主要分:事务故障、系统故障和介质故障事务故障是指事务在运行至正常终点前被终止,此时数据库可能出现不正确的状态。是由于事务程序内部错误而引起的,有些可以预期,如金额不足等,有些不可以预期,如非法输入、运算溢出等。类似于手动执行回滚恢......
  • 程序设计语言学习1
    一、解释与编译解释器:翻译时不生成独立的目标程序,解释程序和源程序都参与程序运行过程编译器:翻译时独立生成目标程序,源程序和编译程序不再参与目标程序的运行过程二、程序设计语言的成分顺序、选择、循环结构......