最优化算法(一)

python 同时被 3 个专栏收录
5 篇文章 0 订阅
1 篇文章 0 订阅
1 篇文章 0 订阅

最优化算法(一)————模拟退火算法



前言

模拟退火算法顾名思义就是参考材料退火时内部分子结构发生变化而演变来的一种寻优思路。

优点是可以跳出局部最优陷阱,缺点是运算较慢

一、材料退火介绍?

退火是一种金属热处理工艺,指的是将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却。目的是降低硬度,改善切削加工性;降低残余应力,稳定尺寸,减少变形与裂纹倾向;细化晶粒,调整组织,消除组织缺陷。准确的说,退火是一种对材料的热处理工艺,包括金属材料、非金属材料。而且新材料的退火目的也与传统金属退火存在异同。

那退火的原理是什么呢??
退火的前提是把材料放在高温环境中一段时间,导致材料的温度升高,也就是材料内部的分子运动愈发剧烈。退火的过程就是让内部分子一次又一次达到能量最小的相对稳态的过程,模拟退火算法也是如此。在追求着能量最低的原则下让寻优的点作相对无序的运动。

二、具体思路

1.流程图

模拟退火算法流程图如下:

在这里插入图片描述
流程图中所表示的新解更优顾名思义就是更符合我们的需求,比如求最小值的时候,1<2,固然认为1是最优解,但如果我们的函数是一个不规则的波形,拥有极多个极点,这种通过一步步迭代的做法显然是不可取的。所以新解更优的判断,不应该仅限制在解更小,而应该类似于材料退火的内部分子结构一样;即使T0时刻的能量是100J,T1时刻大概率是<100J,但这也有小概率是>100J。
模拟退火算法的主要思路就在于此,更改判断准则后流程图如下:
在这里插入图片描述

	#这里的流程图都是拿一次降温为例的

2.初始值的设定

关键值参数名作用影响
内循环迭代次数iter控制每次降温循环次数过大:慢;过小;可能找不到优化解就结束
初始温度T0材料加温到什么温度过大:慢;过小;可能找不到优化解就结束
终止温度Tf材料降温到什么温度结束过小:慢;过大;可能找不到优化解就结束(大于0)
降温系数alpha每次循环之后降温的速度过小:慢;过大;可能找不到优化解就结束

3.程序仿真

代码如下(示例):

'''模拟退火算法练习'''
import math
import numpy as np
from random import random
import matplotlib.pyplot as plt


def func(x, y, z):  # 函数优化问题(三维函数)
    res = 4 * x ** 2 - 2.1 * x ** 4 + x ** 6 / 3 + x * y - 4 * y ** 2 + 4 * y ** 4 + z * x * y + z * x + z * y - z ** 2 + abs(np.sin(z) * np.cos(x-y+z) * np.exp(-z) * z)
    return res


class SA:
    def __init__(self, func, iter=100, T0=100, Tf=0.001, alpha=0.99):
        self.func = func
        self.iter = iter  # 内循环迭代次数,即为L =100
        self.alpha = alpha  # 降温系数,alpha=0.99
        self.T0 = T0  # 初始温度T0为100
        self.Tf = Tf  # 温度终值Tf为0.01
        self.T = T0  # 当前温度
        self.x = [random() * 11 - 5 for i in range(iter)]  # 随机生成100个x的值(设定x的取值范围为-5~5)
        self.y = [random() * 11 - 5 for i in range(iter)]  # 随机生成100个y的值(设定y的取值范围为-5~5)
        self.z = [random() * 21 - 10 for i in range(iter)]  # 随机生成100个y的值(设定z的取值范围为-10~10"""为什么*11而不是10,因为*10-5的话,最后的取值为[-5,5),而不是要求的[-5,5]"""
        self.most_best = []
        self.history = {'f': [], 'T': []}

    def generate_new(self, x, y, z):  # 扰动产生新解的过程
        while True:
            x_new = x + self.T * (random() - random())
            y_new = y + self.T * (random() - random())
            z_new = z + self.T * (random() - random())
            if (-5 <= x_new <= 5) & (-5 <= y_new <= 5) & (-10 <= z_new <= 10):
                break  # 重复得到新解,直到产生的新解满足约束条件
        return x_new, y_new, z_new

    def Metrospolis(self, f, f_new):  # Metropolis准则
        if f_new <= f:
            return 1
        else:
            p = math.exp((f - f_new) / self.T)
            if random() < p:
                return 1
            else:
                return 0

    def best(self):  # 获取最优目标函数值
        f_list = []  # f_list数组保存每次迭代之后的值
        for i in range(self.iter):
            f = self.func(self.x[i], self.y[i], self.z[i])
            f_list.append(f)
        f_best = min(f_list)
        idx = f_list.index(f_best)
        return f_best, idx  # f_best,idx分别为在该温度下,迭代L次之后目标函数的最优解和最优解的下标

    def run(self):
        count = 0
        # 外循环迭代,当前温度小于终止温度的阈值
        while self.T > self.Tf:

            # 内循环迭代100for i in range(self.iter):
                f = self.func(self.x[i], self.y[i], self.z[i])  # f为迭代一次后的值
                x_new, y_new, z_new = self.generate_new(self.x[i], self.y[i], self.z[i])  # 产生新解
                f_new = self.func(x_new, y_new, z_new)  # 产生新值
                if self.Metrospolis(f, f_new):  # 判断是否接受新值
                    self.x[i] = x_new  # 如果接受新值,则把新值的x,y存入x数组和y数组
                    self.y[i] = y_new
                    self.z[i] = z_new
            # 迭代L次记录在该温度下最优解
            ft, _ = self.best()
            self.history['f'].append(ft)
            self.history['T'].append(self.T)
            # 温度按照一定的比例下降(冷却)
            self.T = self.T * self.alpha
            count += 1
            # 得到最优解
        f_best, idx = self.best()
        print(f"F={f_best}, x={self.x[idx]}, y={self.y[idx]}, z={self.z[idx]}")


sa = SA(func)
sa.run()
plt.plot(sa.history['T'], sa.history['f'])
plt.title('SA')
plt.xlabel('T')  # 当前温度
plt.ylabel('f')  # 当前最优解
plt.gca().invert_xaxis()
plt.show()






总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了模拟退火算法的使用,而最优化算法还有很多其他的算法值得学习和思考,学习算法的目的在于应用算法,更在于思考属于自己的算法或者对某个算法的更新。

附上整体流程图:
在这里插入图片描述

  • 1
    点赞
  • 1
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 岁月 设计师:pinMode 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值