模拟退火之函数最值

Author Avatar
Tr0y 6月 03, 2017 23:09:35 本文共 520 字
  • 文为知己者书
  • 在其它设备中阅读本文章

利用 Python 实现模拟退火算法解决函数最值问题, 并画出最优函数点

代码

# -*- coding: cp936 -*-
import math
import random
import time,os
from matplotlib.pyplot import *
import numpy as np

class Metal():
    def __init__(self, lower_bound, upper_bound, temperature, descending, formula): 

        self.lower_bound = lower_bound
        self.upper_bound = upper_bound
        self.temperature = temperature
        self.descending = descending
        self.x = self.RandX()
        self.y = 0.0
        self.history_x = []
        self.history_y = []
        self.formula = formula
        self.best = [0,0]
        #self.Cm = cm.get_cmap('Greys')

    def RandX(self):
        """
        获取随机 x
        """
        return random.uniform(self.lower_bound, self.upper_bound)


    def Smelt(self):
        """
        冶炼开始
        """

        x = self.RandX()
        NewY = eval(self.formula)

        dE = NewY - self.y

        if dE >= 0 or math.e ** (dE / self.temperature) > random.uniform(0, 1):
            self.y = NewY
            self.x = x

            if self.best[1] < self.y:
                self.best[0] = self.x
                self.best[1] = self.y
                os.system('cls')
                print '当金属温度为', self.temperature, '℃时,x 到达历史最佳, 为', self.best[0], 'y 为', self.best[1], '\n', '-'*100

            #self.PlotAndSave()  #每次退火都画图的话速度较慢

        self.history_x += [x]
        self.history_y += [NewY]

        self.temperature -= self.descending

    def PlotAndSave(self):
        '''
        冶炼结束时画出每温度下的 x 与 y
        '''
        x = np.arange(self.lower_bound, self.upper_bound, 0.01)
        y = eval(self.formula.replace('math','np'))
        plot(x,y)
        plot(self.x, self.y, 'o')
        #sc = scatter(self.history_x, self.history_y, c = range(len(self.history_x)) , vmin = 0, vmax = len(self.history_x), s=10, cmap = self.Cm)
        #colorbar(sc)
        savefig('Best.jpg')
        close('all')

time.clock()
#------------------------------------------------------------------参数设置------------------------------------------------------------------

lower_bound     = 0     #函数定义域的下限
upper_bound     = 9     #函数定义域的上限
temperature     = 100   #金属初始温度
descending      = 0.01   #降温幅度
formula         = 'x + 10 * math.sin(5 * x) + 7 * math.cos(4 * x)' #函数式

#------------------------------------------------------------------参数设置------------------------------------------------------------------

metal = Metal(lower_bound, upper_bound, temperature, descending, formula)
while metal.temperature > 1:

    t = time.clock()
    minute, second = divmod(t, 60)
    hour, minute = divmod(minute, 60)

    metal.Smelt()

    print '当前金属温度为', metal.temperature, '℃', '此温度下最优 x 为', metal.x, 'y 为', metal.y, ' 花费时间 %02d:%02d:%02ds' %(hour, minute, second), ' '*5,'\r',

print
metal.PlotAndSave()
os.system('pause')

注意

  • 双击运行
  • 降温幅度较小, 会有更大概率得到较优值, 但是相应花费的时间也就越长.
  • 结果截图
    运行结果
    最值

End

What do you think?

本文标题: 模拟退火之函数最值
原始链接: http://www.tr0y.wang/2017/06/03/FireFunction/
发布时间: 2017.06.03-23:09
最后更新: 2018.11.03-20:41
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!