模拟退火(SA)模板

退役很久了,今天看一篇paper用SA算法代替随机梯度优化神经网络,故学习一波SA算法。

因为网上的资料很多,所以这里就不多说啦。

详情可以看https://www.cnblogs.com/rvalue/p/8678318.html

高中生太强啦

这里放一个模板~

题目链接:https://www.luogu.org/problemnew/show/P1337

P1337 [JSOI2004]平衡点 / 吊打XXX

题目描述

如图:有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。

问绳结X最终平衡于何处。

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

输入输出格式

输入格式:

 

文件的第一行为一个正整数n(1≤n≤1000),表示重物和洞的数目。接下来的n行,每行是3个整数:Xi.Yi.Wi,分别表示第i个洞的坐标以及第 i个重物的重量。(-10000≤x,y≤10000, 0<w≤1000 )

 

输出格式:

 

你的程序必须输出两个浮点数(保留小数点后三位),分别表示处于最终平衡状态时绳结X的横坐标和纵坐标。两个数以一个空格隔开。

 

输入输出样例

输入样例#1: 复制

3
0 0 1
0 2 1
1 1 1

输出样例#1: 复制

0.577 1.000

说明

[JSOI]

 

代码:

#include <bits/stdc++.h>

using namespace std;
const int N = 1e4+10;

struct Point
{
    double x,y;
    Point(double x=0,double y=0)
    {
        this->x=x;
        this->y=y;
    }
}p[N];
int n;
double g[N];
Point ans;
double minAns=DBL_MAX;
double Rand()
{
     return double(rand())/double(RAND_MAX);
}
double Sqr(double a)
{
    return a*a;
}
double Eulc(Point A,Point B)
{
    return sqrt(Sqr(A.x-B.x)+Sqr(A.y-B.y));
}

double Calc(Point A)
{
    double ans=0;
    for(int i=0;i<n;i++)
        ans+=Eulc(A,p[i])*g[i];
    if(ans<minAns)
    {
        ::ans=A;
        minAns=ans;
    }
    return ans;
}

bool Accept(double delta,double tmp)
{
    return delta<0||Rand()<exp(-delta/tmp);
}

Point SimulatedAnnealing(Point init,double initT,double dec,double endT)
{
    double tmp=initT;
    Point now = init;
    double nowAns=Calc(now);
    while(tmp>endT)
    {
        Point next = Point(now.x+tmp*(2*Rand()-1),now.y+tmp*(2*Rand()-1));
        double ans = Calc(next);
        if(Accept(ans-nowAns,tmp))
        {
            nowAns=ans;
            now=next;
        }
        tmp*=dec;
    }
    for(int i=0;i<10000;i++)
    {
        Point rnc = Point(ans.x+tmp*(2*Rand()-1),ans.y+tmp*(2*Rand()-1));
        Calc(rnc);
    }
    return now;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        Point init;
        init.x=init.y=0.0;
        for(int i=0;i<n;i++)
            {
                scanf("%lf %lf %lf",&p[i].x,&p[i].y,&g[i]);
                init.x+=p[i].x,init.y+=p[i].y;
            }
        init.x/=n,init.y/=n;
        SimulatedAnnealing(init,1e5,1-7e-3,1e-3);
        printf("%.3lf %.3lf\n",ans.x,ans.y);
    }
    return 0;
}

能不能AC全看脸,启发式算法为了逼近全局最优解,其中包含有随机值。

当然实际使用中,我们往往并不需要最优解,而只要一个逼近最优解的值就行了。

以下是一个简单的matlab模拟退火代码模板: ```matlab function [xmin, fmin] = sim_anneal(obj_fun, x0, options) % Simulated Annealing Algorithm for Function Minimization % obj_fun - function handle: objective function to be minimized % x0 - vector: initial guess for minimum (1xn) % options - structure: various parameters for the algorithm % options.t0 - initial temperature % options.alpha - cooling rate % options.stopping_temp - minimum temperature at which annealing stops % options.max_iter - maximum number of iterations % options.display - flag for displaying progress % Initialize parameters t = options.t0; x = x0; [fmin, xmin] = obj_fun(x); i = 1; while t > options.stopping_temp && i < options.max_iter % Generate new candidate solution xnew = x + randn(size(x)); % Gaussian perturbation % Evaluate objective at new candidate solution [fnew, ~] = obj_fun(xnew); % Determine whether to accept new solution dE = fnew - fmin; % Change in objective function if dE < 0 || rand() < exp(-dE/t) % Accept new solution x = xnew; fmin = fnew; end % Update temperature and iteration counter t = options.alpha * t; i = i + 1; % Display progress if options.display fprintf('Iteration %d: Temperature = %g, Objective = %g\n', i, t, fmin); end end end ``` 这个函数接受一个指定目标函数的函数句柄、一个初始解向量和一个设置参数结构体。算法随后在一系列的迭代中搜索全局最小值,并返回最小解向量和最小函数值。你可以通过设定结构体的不同参数来调整算法的表现,例如初始温度、冷却速率、停止温度以及最大迭代次数等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值