2023年第四届“华数杯”数学建模思路 - 案例:退火算法

## 0 赛题思路

(赛题出来以后第一时间在CSDN分享)

https://blog.csdn.net/dc_sinor?type=blog

1 退火算法原理

1.1 物理背景

在热力学上,退火(annealing)现象指物体逐渐降温的物理现象,温度愈低,物体的能量状态会低;够低后,液体开始冷凝与结晶,在结晶状态时,系统的能量状态最低。大自然在缓慢降温(亦即,退火)时,可“找到”最低能量状态:结晶。但是,如果过程过急过快,快速降温(亦称「淬炼」,quenching)时,会导致不是最低能态的非晶形。

如下图所示,首先(左图)物体处于非晶体状态。我们将固体加温至充分高(中图),再让其徐徐冷却,也就退火(右图)。加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小(此时物体以晶体形态呈现)。

在这里插入图片描述

1.2 背后的数学模型

如果你对退火的物理意义还是晕晕的,没关系我们还有更为简单的理解方式。想象一下如果我们现在有下面这样一个函数,现在想求函数的(全局)最优解。如果采用Greedy策略,那么从A点开始试探,如果函数值继续减少,那么试探过程就会继续。而当到达点B时,显然我们的探求过程就结束了(因为无论朝哪个方向努力,结果只会越来越大)。最终我们只能找打一个局部最后解B。

在这里插入图片描述

根据Metropolis准则,粒子在温度T时趋于平衡的概率为exp(-ΔE/(kT)),其中E为温度T时的内能,ΔE为其改变数,k为Boltzmann常数。Metropolis准则常表示为
在这里插入图片描述

Metropolis准则表明,在温度为T时,出现能量差为dE的降温的概率为P(dE),表示为:P(dE) = exp( dE/(kT) )。其中k是一个常数,exp表示自然指数,且dE<0。所以P和T正相关。这条公式就表示:温度越高,出现一次能量差为dE的降温的概率就越大;温度越低,则出现降温的概率就越小。又由于dE总是小于0(因为退火的过程是温度逐渐下降的过程),因此dE/kT < 0 ,所以P(dE)的函数取值范围是(0,1) 。随着温度T的降低,P(dE)会逐渐降低。

我们将一次向较差解的移动看做一次温度跳变过程,我们以概率P(dE)来接受这样的移动。也就是说,在用固体退火模拟组合优化问题,将内能E模拟为目标函数值 f,温度T演化成控制参数 t,即得到解组合优化问题的模拟退火演算法:由初始解 i 和控制参数初值 t 开始,对当前解重复“产生新解→计算目标函数差→接受或丢弃”的迭代,并逐步衰减 t 值,算法终止时的当前解即为所得近似最优解,这是基于蒙特卡罗迭代求解法的一种启发式随机搜索过程。退火过程由冷却进度表(Cooling Schedule)控制,包括控制参数的初值 t 及其衰减因子Δt 、每个 t 值时的迭代次数L和停止条件S。

2 退火算法实现

2.1 算法流程

(1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点), 每个T值的迭代次数L
(2) 对k=1,……,L做第(3)至第6步:
(3) 产生新解S′
(4) 计算增量Δt′=C(S′)-C(S),其中C(S)为评价函数
(5) 若Δt′<0则接受S′作为新的当前解,否则以概率exp(-Δt′/T)接受S′作为新的当前解.
(6) 如果满足终止条件则输出当前解作为最优解,结束程序。
终止条件通常取为连续若干个新解都没有被接受时终止算法。
(7) T逐渐减少,且T->0,然后转第2
在这里插入图片描述

2.2算法实现

import numpy as np
import matplotlib.pyplot as plt
import random

class SA(object):

    def __init__(self, interval, tab='min', T_max=10000, T_min=1, iterMax=1000, rate=0.95):
        self.interval = interval                                    # 给定状态空间 - 即待求解空间
        self.T_max = T_max                                          # 初始退火温度 - 温度上限
        self.T_min = T_min                                          # 截止退火温度 - 温度下限
        self.iterMax = iterMax                                      # 定温内部迭代次数
        self.rate = rate                                            # 退火降温速度
        #############################################################
        self.x_seed = random.uniform(interval[0], interval[1])      # 解空间内的种子
        self.tab = tab.strip()                                      # 求解最大值还是最小值的标签: 'min' - 最小值;'max' - 最大值
        #############################################################
        self.solve()                                                # 完成主体的求解过程
        self.display()                                              # 数据可视化展示

    def solve(self):
        temp = 'deal_' + self.tab                                   # 采用反射方法提取对应的函数
        if hasattr(self, temp):
            deal = getattr(self, temp)
        else:
            exit('>>>tab标签传参有误:"min"|"max"<<<')
        x1 = self.x_seed
        T = self.T_max
        while T >= self.T_min:
            for i in range(self.iterMax):
                f1 = self.func(x1)
                delta_x = random.random() * 2 - 1
                if x1 + delta_x >= self.interval[0] and x1 + delta_x <= self.interval[1]:   # 将随机解束缚在给定状态空间内
                    x2 = x1 + delta_x
                else:
                    x2 = x1 - delta_x
                f2 = self.func(x2)
                delta_f = f2 - f1
                x1 = deal(x1, x2, delta_f, T)
            T *= self.rate
        self.x_solu = x1                                            # 提取最终退火解

    def func(self, x):                                              # 状态产生函数 - 即待求解函数
        value = np.sin(x**2) * (x**2 - 5*x)
        return value

    def p_min(self, delta, T):                                      # 计算最小值时,容忍解的状态迁移概率
        probability = np.exp(-delta/T)
        return probability

    def p_max(self, delta, T):
        probability = np.exp(delta/T)                               # 计算最大值时,容忍解的状态迁移概率
        return probability

    def deal_min(self, x1, x2, delta, T):
        if delta < 0:                                               # 更优解
            return x2
        else:                                                       # 容忍解
            P = self.p_min(delta, T)
            if P > random.random(): return x2
            else: return x1

    def deal_max(self, x1, x2, delta, T):
        if delta > 0:                                               # 更优解
            return x2
        else:                                                       # 容忍解
            P = self.p_max(delta, T)
            if P > random.random(): return x2
            else: return x1

    def display(self):
        print('seed: {}\nsolution: {}'.format(self.x_seed, self.x_solu))
        plt.figure(figsize=(6, 4))
        x = np.linspace(self.interval[0], self.interval[1], 300)
        y = self.func(x)
        plt.plot(x, y, 'g-', label='function')
        plt.plot(self.x_seed, self.func(self.x_seed), 'bo', label='seed')
        plt.plot(self.x_solu, self.func(self.x_solu), 'r*', label='solution')
        plt.title('solution = {}'.format(self.x_solu))
        plt.xlabel('x')
        plt.ylabel('y')
        plt.legend()
        plt.savefig('SA.png', dpi=500)
        plt.show()
        plt.close()


if __name__ == '__main__':
    SA([-5, 5], 'max')

实现结果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ 数组作为函数参数

数组元素和数组名都可以作为函数的参数以实现函数间数据的传递和共享。 可以用数组元素作为调用函数时的实参&#xff0c;这与使用该类型的一个变量&#xff08;或对象&#xff09;作实参是完全相同的。 如果使用数组名作为函数的参数&#xff0c;则实参和形参都应该是数组名…

企业上云实施路线图

企业上云步骤主要分为规划、设计、实施、验证、运维五个阶段。https://articles.e-works.net.cn/cloud/article144684.htm

XXL-JOB定时任务框架(Oracle定制版)

特点 xxl-job是一个轻量级、易扩展的分布式任务调度平台&#xff0c;能够快速开发和简单学习。开放源代码并被多家公司线上产品使用&#xff0c;开箱即用。尽管其确实非常好用&#xff0c;但我在工作中使用的是Oracle数据库&#xff0c;因为xxl-job是针对MySQL设计的&#xff…

group normalization

1、 Theory look for this link for more information, actually only this image can illustrate the group normalization.you can ignore the rest of this artical. 2、 Code check this link for detailed about the formulation and the theory of the group normalzi…

问题解决和批判性思维是软件工程的重要核心

软件工程的重心在于问题解决和批判性思维&#xff08;合理设计和架构降低复杂度&#xff09;&#xff0c;而非仅局限于编程。 许多人误以为软件工程就只是编程&#xff0c;即用编程语言编写指令&#xff0c;让计算机按照这些指令行事。但实际上&#xff0c;软件工程的内涵远超…

git 公钥密钥 生成与查看

1.什么是公钥 很多服务器都是需要认证的&#xff0c;ssh认证是其中的一种。在客户端生成公钥&#xff0c;把生成的公钥添加到服务器&#xff0c;你以后连接服务器就不用每次都输入用户名和密码了。 很多git服务器都是用ssh认证方式&#xff0c;你需要把你生成的公钥发送给代码仓…

模板方法模式(Template Method)

模板方法模式是一种行为设计模式&#xff0c;在超类中定义了一个算法的框架&#xff0c;而将一些步骤的实现延迟到子类中&#xff0c;使得子类可重定义该算法的特定步骤。 Template Method is a behavior design pattern. It defines an algorithm framework in the superclas…

Docker容器技术

前言 容器技术、虚拟化技术已经成为一种被大家广泛认可的服务器资源共享方式&#xff0c;容器技术可以在按需构建操作系统实例的过程当中为系统管理员提供极大的灵活性。由于hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题&#xff0c;因此容器技术&#xff0…

Python爬虫遇到重定向问题解决办法汇总

在进行Python爬虫任务时&#xff0c;遇到重定向问题是常见的问题之一。重定向是指在发送请求时&#xff0c;服务器会返回一个新的URL&#xff0c;将请求重新定向到该URL。为了帮助您解决这个问题&#xff0c;本文将提供一些实用的解决办法&#xff0c;并给出相关的代码示例&…

【H5移动端】常用的移动端方案合集-键盘呼起、全面屏适配、图片大小显示、300ms点击延迟、首屏优化(不定期补充~)

文章目录 前言键盘呼起问题靠近底部的输入项被键盘遮挡底部按钮被顶上去 全面屏适配图片大小显示问题解决300ms延迟首屏优化 前言 这篇文章总结了我在工作中做H5遇到的一些问题&#xff0c;包括我是怎么解决的。可能不是当下的最优解&#xff0c;但是能保证解决问题。 单位适…

五、JVM-垃圾回收算法

常见的回收算法&#xff1a;标记清除算法、复制算法、标记-整理算法、分代收集算法 1、标记清除算法 第一步&#xff1a;标记&#xff08;找出内存中需要回收的对象&#xff0c;并且把它们标记出来&#xff09; 第二步&#xff1a;清除 &#xff08;清除掉被标记需要回收的对…

【Redis】——RDB快照

Redis 是内存数据库&#xff0c;但是它为数据的持久化提供了两个技术&#xff0c;一个是AOF日志&#xff0c;另一个是RDB快照&#xff1a; AOF 文件的内容是操作命令&#xff1b;RDB 文件的内容是二进制数据。 RDB 快照就是记录某一个瞬间的内存数据&#xff0c;记录的是实际…

Linux 命令学习:

1. vim 使用&#xff1a; 一般流程就是&#xff1a; vi XXXX文件路径 //进入文件&#xff0c;此时处在命令模式&#xff08;即&#xff0c;vim认为我们现在键盘输入的不是字符&#xff0c;而是命令&#xff09; i // 键盘输入 i 字符&#xff0c;进入输入模式&#xff…

【C语言】静态关键字static的用法(详解)

&#x1f388;个人主页&#xff1a;库库的里昂 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;C语言初阶 ✨其他专栏&#xff1a;代码小游戏 &#x1f91d;希望作者的文章能对你有所帮助&#xff0c;有不足的地方请在评论…

Python导出SqlServerl数据字典为excel

sql代码 SELECTtableName D.name ,tableIntroduce isnull(F.value, ),sort A.colorder,fieldName A.name,catogary B.name,bytes A.Length,lengths COLUMNPROPERTY(A.id, A.name, PRECISION),scales isnull(COLUMNPROPERTY(A.id, A.name, Scale), 0),isOrNotNull Cas…

Spring Cloud +UniApp 智慧工地云平台源码,智能监控和AI分析系统,危大工程管理、视频监控管理、项目人员管理、绿色施工管理

一套智慧工地云平台源码&#xff0c;PC管理端APP端平板端可视化数据大屏端源码 智慧工地可视化系统利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;通过工地中台、三维建模服务、视频AI分析服务等技术支撑&#xff0c;实现智慧工地高精度动态仿…

【css】css隐藏元素

display:none&#xff1a;可以隐藏元素。该元素将被隐藏&#xff0c;并且页面将显示为好像该元素不在其中。visibility:hidden&#xff1a; 可以隐藏元素。但是&#xff0c;该元素仍将占用与之前相同的空间。元素将被隐藏&#xff0c;但仍会影响布局。 代码&#xff1a; <!…

一次redis缓存不均衡优化经验

背景 高并发接口&#xff0c;引入redis作为缓存之后&#xff0c;运行一段时间发现redis各个节点在高峰时段的访问量严重不均衡&#xff0c;有的节点访问量7000次/s&#xff0c;有的节点访问量500次/s 此种现象虽然暂时不影响系统使用&#xff0c;但是始终是个安全隐患&#x…

谈谈python编程语言

目录 1.什么是python 2.python的发展历史 3.python的具体应用领域 4.就业前景 1.什么是python Python是一种高级编程语言&#xff0c;它具有简单易学、可读性强和功能丰富的特点。Python由Guido van Rossum于1991年开发&#xff0c;并成为一种通用的编程语言。 以下是一些Py…

Mac 创建和删除 Automator 工作流程,设置 Terminal 快捷键

1. 创建 Automator 流程 本文以创建一个快捷键启动 Terminal 的自动操作为示例。 点击打开 自动操作&#xff1b; 点击 新建文稿 点击 快速操作 选择 运行 AppleScript 填入以下内容 保存名为 “Open Terminal” 打开 设置 > 键盘&#xff0c;选择 键盘快捷键 以此选择 服…