模拟退火算法

例子1:实现最小值的求解,对于求一元方程的最优解

原文:链接https://blog.csdn.net/i_csdn_water/article/details/108171231?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%A8%A1%E6%8B%9F%E9%80%80%E7%81%AB%E7%AE%97%E6%B3%95%E5%8F%AF%E8%A7%86%E5%8C%96&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-4-108171231.pc_search_insert_js_new&spm=1018.2226.3001.4187

#本功能实现最小值的求解,对于求一元方程的最优解#

from matplotlib import pyplot as plt
import numpy as np
import random
import math
plt.ion()#这里需要把matplotlib改为交互状态

#目标函数
def f(x):
    #只有x一个变量
    return 11*np.sin(x)+7*np.cos(5*x)##注意这里要是np.sin

class SA2():
    def __init__(self,hi=3,lo=-3,alf=0.95,T=100):
        '''
        初始化
        :param hi: 产生随机变量x的最大范围
        :param lo: 产生随机变量x的最小范围
        :param alf: 降温系数
        :param T: 初始温度
        '''
        #初始值设定
        #目标函数

        self.hi=hi#产生变量的最大范围
        self.lo=lo#产生变量的最小范围
        self.alf=alf#降温系数
        self.T=T#初始温度

    # 可视化函数(开始清楚一次然后重复的画)
    def visual(self,x):
        #清除当前轴
        plt.cla()
        #初始化画布上的轴(x_min,x_max,y_min,y_max)
        plt.axis([self.lo - 1, self.hi + 1, -20, 20])
        #图上坐标的x轴变量
        m = np.arange(self.lo, self.hi, 0.0001)
        #画函数图像
        plt.plot(m, f(m))
        # print(x)
        # print(f(x))
        #画函数上的点,这个点是去找最小值的点
        plt.plot(x, f(x), marker='o', color='black', markersize='4')
        plt.title('temperature={}'.format(self.T))
        plt.pause(0.1)  # 0.1s


    # 新解的随机产生
    def new(self,x):
        x1 = x + self.T * random.uniform(-1, 1)
        if (x1 <= self.hi) & (x1 >= self.lo):
            return x1
        elif x1 < self.lo:#如果在区间的左边,探索左边有没有比区间局部最小值更小的解
            rand = random.uniform(-1, 1)
            return rand * self.lo + (1 - rand) * x
        else:#如果在区间的左边,探索右边有没有比区间局部最小值更小的解
            rand = random.uniform(-1, 1)
            return rand *self.hi + (1 - rand) * x

    # p函数
    def p(self,x, x1):
        return math.exp(-abs(f(x) - f(x1)) / self.T)

    def test(self):
       #随机生成x,范围在(-3,3)之间
        x = random.uniform(self.lo,self.hi)
        while self.T > 0.0001:
            #
            self.visual(x)
            for i in range(500):
                x1 = self.new(x)
                if f(x1) <= f(x):
                    x = x1
                else:
                    if random.random() <= self.p(x, x1):
                        x = x1
                    else:
                        continue
            self.T = self.T * self.alf
        print('最小值为:{}'.format(f(x)))


if __name__ == '__main__':
    sa2=SA2()
    sa2.test()

例子2:实现最小值求解,对于二元方程的最优解

原文:链接https://blog.csdn.net/weixin_48241292/article/details/109468947?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163281216716780264076497%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163281216716780264076497&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-109468947.pc_search_insert_js_new&utm_term=%E6%A8%A1%E6%8B%9F%E9%80%80%E7%81%AB%E7%AE%97%E6%B3%95&spm=1018.2226.3001.4187

import math
from random import  random
import numpy as np


#模拟退火算法比较设用于已确定一定边界,求解参数
def func(x_1,x_2):
    '''
    优化函数(用模拟退火求他的最小)
    :param x1: 参数1
    :param x2: 参数2
    :return:
    '''
    res=4*x_1**2-2.1*x_1**4+x_1**6/3+x_1*x_2-4*x_2**2+4*x_2**4
    return res;

#x为公式里的x1,y为公式里面的x2
class SA:
    def __init__(self,func,iter=100,T0=100,Tf=0.01,alpha=0.99):
        '''
        初始化参数
        :param func: 函数
        :param iter: 内循环迭代次数,默认=100
        :param T0: 初始温度=100
        :param Tf: 温度终值Tf0.01
        :param alpha:降温系数,alpha=0.99s
        '''
        self.func=func
        self.iter=iter
        self.alpha=alpha
        self.T0=T0
        self.Tf=Tf
        self.T=T0
        # 随机产生iter个x1,x1和x2的绝对值不超过5(包含整数5和-5)
        self.x1=np.array([random()*11-5 for i in range(iter)])
        #随机产生iter个x2
        self.x2=np.array([random()*11-5 for i in range(iter)])
        self.most_best=[]
        self.history = {'f': [], 'T': []}


    def generate_new(self, x1, x2):
        '''
        残生新解的过程
        :param x1: 参数1
        :param x2: 参数2
        :return:
        '''
        while True:
            x1_new=x1+self.T*(random()-random())
            x2_new=x2+self.T*(random()-random())
            if(-5<=x1_new<=5)&(-5<=x2_new<=5):
                break
        return x1_new,x2_new
    def best(self):#获取最有目标数值
        f_list=[]
        #f_list储存函数的结果
        f_list=self.func(self.x1,self.x2)

        #获取函数结果的最小值
        f_best=min(f_list)

        #获取函数结果的最小值下标
        idx=np.argmin(f_list,axis=0)

        return f_best,idx

    def Metrospolis(self,f,f_new):
        '''

        :param f: 旧的函数最小
        :param f_new: 新的x1,x2生成的函数值
        :return:
        '''
        #f_new <= f
        if f_new <= f:
            return 1
        else:
            p = math.exp((f - f_new) / self.T)
            if random() < p:
                return 1
            else:
                return 0

    def genNew(self):
        for i in range(self.iter):
            # 产生新解
            x1_new, x2_new = self.generate_new(self.x1[i], self.x2[i])
            # 产生新函数值
            f_new = self.func(x1_new, x2_new)
            if self.Metrospolis(self.f[i], f_new):  # 判断是否接受新值
                self.x1[i] = x1_new  # 如果接受新值,则把新值的x,y存入x数组和y数组
                self.x2[i] = x2_new
                self.point .set_data(self.x1[i], self.x2[i], f_new)


    def run(self):
        count=0
        #当当前温度小于终止温度的阈值,循环
        while self.T>self.Tf:
            # f为迭代一次后的值
            self.f=self.func(self.x1,self.x2)
            #迭代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.x1[idx]}, y={self.x2[idx]}")


if __name__ == '__main__':
    sa=SA(func)

    sa.run()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值