2018.09.28 模拟退火算法研究日志

2018.09.28 模拟退火算法研究日志

本周研究模拟退火算法,这也是一个启发式求最优解的方法。这个算法可以被优化,比如结合遗传算法减少迭代次数。

模拟退火算法

百度百科对模拟退火算法的解释是:

模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。

它的基本思想是:

模拟退火其实也是一种贪心算法,但是它的搜索过程引入了随机因素。在迭代更新可行解时,以一定的概率来接受一个比当前解要差的解,因此有可能会跳出这个局部的最优解,达到全局的最优解。

在这里插入图片描述

如上图,模拟退火算法从A点出发,快速定位到B点,这是一个局部最优点而不是全局最优,根据算法,它按概率(刚开始时概率较大,而后逐步减小)接收劣于B的点,模拟退火算法会逐步搜索到C点(该点也是局部最优),再用同样的方法搜索到D点。此时,由于接受该点为最优的概率远高于跳出概率(接受劣于D的点的概率),且迭代次数逐渐接近最初定义的次数最大值,所以会有极大概率接受D为全局最优解,算法停止。

有关接受劣等数据的概率,同时应用退火过程的热力学公式如下:

p ( d E ) = e d E k T p(dE)=e^{\frac{dE}{kT}} p(dE)=ekTdE

其中,k是波尔兹曼常数,但是在算法中通常简化为k=1,而初始化温度充分大,温度下限充分小,能够更快得到全剧最优点。

能量差计算公式入下:

d E = Δ f = f ( x n e w ) − f ( x ) dE=\Delta f=f(x_{new})-f(x) dE=Δf=f(xnew)f(x)

x_new为迭代更新后的点。

模拟退火算法描述

过程如下:

  1. 初始化:初始温度 T T T(充分大),温度下限 T m i n T_{min} Tmin(充分小),初始化解状态 x x x(是算法迭代的起点),每一个 T T T值的迭代次数 L L L
  2. l = 1 , 2 , ⋯   , L l=1,2,\cdots,L l=1,2,,L做以下步骤:
      2.1 产生新解 x n e w x_{new} xnew:( x n e w = x + Δ x x_{new}=x+\Delta x xnew=x+Δx);
      2.2 计算能量增量 Δ f = f ( x n e w ) − f ( x ) \Delta f=f(x_{new})-f(x) Δf=f(xnew)f(x),其中 f ( x ) f(x) f(x)为优化目标;
      2.3 若 Δ f &lt; 0 \Delta f&lt;0 Δf<0(若寻找最大值, Δ f &gt; 0 \Delta f&gt;0 Δf>0)则接受 x n e w x_{new} xnew作为新的当前解,否则以概率 e − Δ f k T e^{\frac{-\Delta f}{kT}} ekTΔf接受 x n e w x_{new} xnew作为新的当前解;
      2.4 如果满足终止条件则输出当前解作为最优解,结束程序。(终止条件通常取为连续若干个新解都没有被接受时终止算法)
  3. T逐渐减少,且 T &gt; T m i n T&gt;T_{min} T>Tmin,然后转到第二步;否则退出算法。

2018.10.21模拟退火算法研究日志

很久没有研究算法啦,这几天接了一个项目,蛮忙的,现在总算完成了。从今天开始,继续研究拖到现在的算法。

模拟退火算法实例——以求最小值为例

设函数 f ( x ) = ( x − 2 ) × ( x + 3 ) × ( x + 8 ) × ( x − 9 ) f(x)=(x-2)\times(x+3)\times(x+8)\times(x-9) f(x)=(x2)×(x+3)×(x+8)×(x9),求其最小值。

首先,我们先了解一下该函数图形的模样:

在这里插入图片描述

用Java实现该算法过程:

import java.math.BigDecimal;
import java.util.Random;
import static java.lang.Math.exp;

public class Main {

    public static void main(String[] args) {
        double initT=1000.0;             //初识温度
        double minT=1.0;                 //温度下限
        int iterL=1000;             //每个T值的迭代次数
        double delta=0.95;          //温度衰减系数
        int k=1;                    //波尔兹曼常数

        Funcion func = new Funcion();
        double x = func.randomDouble();
        System.out.println("初始解为: "+x);
        double T = initT;       //当前温度为初始温度
        Random random = new Random();

        while(T>minT){
            for(int times=0;times<iterL;times++){
                //产生新值
                double delta_x=-1+random.nextDouble()*2;
                double x_new = x+delta_x;
                if(x_new>=-10&&x_new<=10){
                    if(func.function_value(x)<func.function_value(x_new)){
                        double difference = func.function_value(x_new)-func.function_value(x);      //delta f(x)两函数的差
                        double  probability = random.nextDouble();      //以概率接受值
                        if(probability<exp(-(difference/(k*T)))){
                            x=x_new;
                        }
                    }else {
                        x=x_new;
                    }
                }
            }
            T = T*delta;        //减小T;
        }

        //输出
        BigDecimal decimal=new BigDecimal(func.function_value(x));
        double out=decimal.setScale(4,BigDecimal.ROUND_HALF_UP).doubleValue();
        BigDecimal decimal_x=new BigDecimal(x);
        double out_x=decimal_x.setScale(4,BigDecimal.ROUND_HALF_UP).doubleValue();
        System.out.println("经过多次迭代");
        System.out.println("最优解:"+out_x);
        System.out.println("函数最小值:"+out);
    }


}

class Funcion{
    //函数值
    public double function_value(double x){
        return (x-2)*(x+3)*(x+8)*(x-9);
    }

    //最大温度和最小温度之间产生一个随机浮点数,精确到小数点后4位
    public double randomDouble(){
        Random random = new Random();
        double x = -10+random.nextDouble()+random.nextInt(19);      //[-10,10]
        // 新建格式化器,设置格式
        BigDecimal decimal=new BigDecimal(x);
        // 将数据四舍五入为4位小数的double值
        double out=decimal.setScale(4,BigDecimal.ROUND_HALF_UP).doubleValue();
        return out;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值