用模拟退火求最优化问题python实现

用模拟退火求解 y = 0.1x*sin(x)的最小值问题

import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
import matplotlib.animation as animation

class SA(object):
    def __init__(self, func):
        self.max_T = 100     #起始温度
        self.min_T = 0.002   #最小温度
        self.search_num = 50 #每轮搜索的次数
        self.t = 1           #用于计数
        self.best_x = None
        self.best_y = None
        self.T = self.max_T
        self.func = func
        self.low = -20       #定义域
        self.high = 20
        self.best_xs = []
        self.best_ys = []

    def update_value(self, x, y, x_new, y_new):
        """更新x, y"""
        P = np.exp(-np.abs(self.func(x_new) - self.func(x))/ self.T)  #Metropolis准则
        # print(P)
        if (np.random.random() < P) or (y_new < y):
            y = y_new
            x = x_new
        if y < self.best_y:
            self.best_y = y
            self.best_x = x
            self.best_xs.append(x)
            self.best_ys.append(y)
        return x, y

    def run(self):
        """主函数"""
        x = np.random.uniform(self.low, self.high)
        y = self.func(x)
        self.best_x = x
        self.best_y = y
        x_new = x
        y_new = y
        while self.T >= self.min_T: # 在达到最小温度前一直循环
            for n in range(self.search_num):   # 在每个温度点搜寻50次
                delta_x = np.random.uniform(-0.5, 0.5)  #寻找x附近x_new的步长,可理解为learning_rate
                x_temp = x + delta_x
                if (x_temp < self.high) and (x_temp > self.low):
                    x_new = x_temp
                    y_new = self.func(x_new)
                    x, y =self.update_value(x, y, x_new, y_new)
            self.t += 1
            self.T = self.max_T/(1 + self.t)
            # print(self.best_x)
            # print(self.best_y)

            # ax.scatter(self.best_x, self.best_y, c = 'b', cmap = 'rainbow')

def update_points(num, x , y):
    """更新数据点用于画动图"""
    points.set_data(x[num], y[num])
    return points,

if __name__ == '__main__':
    def func(x):
        y =   0.1 * x * np.sin(x)
        return y
    x = np.linspace(-20, 20, 1000)
    y = func(x)
    fig = plt.figure(figsize = (9, 6))
    plt.plot(x, y, c = 'r')
    ax = plt.gca()
    sa = SA(func)
    sa.run()
    points, = ax.plot([], [], 'ro')
    ani = animation.FuncAnimation(fig, update_points, range(len(sa.best_xs)), fargs=(sa.best_xs, sa.best_ys), interval= 50)
    """
    fig : 当前画布
    update_points : 每一帧调用的函数,第一个参数为 frame
    frames : 帧 传入可迭代对象
    fargs : 传入update_point的其他参数
    interval : 每帧之间的时间, 理解为gif播放速度
    """

    ani.save('./samples/sa1.gif')
    plt.show()

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值