Mathematical Modeling (3): Simulated Annealing Algorithm (SA)

Simulated Annealing Algorithm (SA)

I. Overview

1. Introduction to algorithm

The simulated annealing algorithm (SA) is derived from the principle of solid annealing and is a probability-based algorithm.

The simulated annealing algorithm (SA) is derived from the principle of solid annealing and is a probability-based algorithm. Heating the solid to a sufficiently high temperature and then allowing it to slowly cool down will cause the internal particles of the solid to become disordered as the temperature rises. The internal energy increases and the molecules and atoms become more unstable. As it slowly cools, the particles become more orderly, the energy decreases, and the atoms become more stable. During the cooling (lowering) process, the solid reaches an equilibrium state at each temperature, and finally reaches the ground state at room temperature, and the internal energy is reduced to a minimum.

The simulated annealing algorithm starts from a certain higher initial temperature, and as the temperature parameters continue to decrease, it combines the probability jump characteristics to randomly find the global optimal solution of the objective function in the solution space, that is, the local optimal solution can probabilistically jump out of the union. Eventually it tends to the global optimum. The simulated annealing algorithm is an optimization algorithm that gives the search process a time-varying probability jump that eventually approaches zero, thereby effectively avoiding falling into a local minimum and eventually approaching the global optimal serial structure.

2. Core idea

The simulated annealing algorithm starts from a certain higher initial temperature, and as the temperature parameters continue to decrease, combined with certain probability jump characteristics, it randomly searches for the global optimal solution of the objective function in the solution space, that is, the local optimal solution can be probabilistically Jump out and eventually tend to the global optimum.

The calculation of "certain probability" here refers to the annealing process of metal smelting, which is also the origin of the name of the simulated annealing algorithm. The temperature T is regarded as the control parameter, the objective function value f is regarded as the internal energy E, and a state of the solid at a certain temperature T corresponds to a solution xi x_ixi, and then the algorithm attempts to gradually reduce the objective function f (internal energy E) as the control parameter T decreases, until it approaches the global minimum (the lowest energy state at low temperatures during annealing), just like the metal annealing process.

There is an interesting metaphor about the hill climbing algorithm and simulated annealing:

  • Hill Climbing Algorithm: The rabbit jumps to a higher place than it is now. It found the tallest mountain not far away. But the mountain doesn’t have to be Everest. This is the hill climbing algorithm, which cannot guarantee that the local optimal value is the global optimal value.

  • Simulated annealing: The rabbit is drunk. It jumped randomly for a long time. During this period, it may move to higher ground or to level ground. However, it gradually woke up and jumped in the highest direction. This is simulated annealing.

3. Mathematical principles

From the above we know that the global optimal solution of the objective function will be randomly found in the solution space based on the probability jump characteristic. So what is the specific mechanism for updating the solution? If the new solution is better than the current solution, accept the new solution, otherwise Metropolisjudge whether to accept the new solution based on the criterion. The acceptance probability is:

Assume that the starting state is at A, and as the number of iterations is updated to the local optimal solution of B, it is found that when it is updated to B, the energy is lower than A, which means it is close to the optimal solution, so it is 100% transferred. After the state reaches B , it is found that the energy has increased in the next step. If it is gradient descent, it is not allowed to continue forward, and here will jump out of this pit with a certain probability. This probability is related to the current state, energy, etc., if B finally jumps out Once it reaches C, it will continue to jump out with a certain probability until it reaches D, where it will stabilize.

4. Simulated annealing process

(1) Initialization: initial temperature T (large enough), initial solution state S (which is the starting point of algorithm iteration), number of iterations for each T value L

(2) Do steps (3) to (6) for k=1, …, L:

(3) Generate a new solution S′

(4) Calculate the increment ΔT = C(S′)-C(S), where C(S) is the objective function and C(S) is equivalent to energy

(5) If ΔT<0, accept S′ as the new current solution, otherwise accept S′ as the new current solution with probability exp(-ΔT/T).

(6) If the termination condition is met, the current solution is output as the optimal solution and the program ends.

(7) T gradually decreases, and T->0, then go to step 2.

There are several points to note:

  • The selection of the initial point has a certain impact on the algorithm results. It is best to run it multiple times to make a comprehensive judgment on the results.
  • In the early stages of algorithm operation, the temperature drops quickly to avoid accepting too many bad results. As run time increases, the temperature drop slows down, allowing for faster stabilization of results.
  • When the number of iterations increases to a certain number, the results may have reached stability, but there is still some time before the end of the algorithm. Appropriate output conditions should be added when designing the program. The program can be ended when the output conditions are met.

It can be roughly divided into these four steps:

  1. The first step is to use a generation function to generate a new solution located in the solution space from the current solution; in order to facilitate subsequent calculation and acceptance and reduce the time consumption of the algorithm, a method that can generate a new solution from the current new solution through simple transformation is usually chosen. , such as replacing or exchanging all or part of the elements that constitute the new solution. Note that the transformation method that generates the new solution determines the neighborhood structure of the current new solution, and thus has a certain impact on the selection of the cooling schedule.
  2. The second step is to calculate the difference of the objective function corresponding to the new solution. Because the objective function difference is generated only by the transformation part, the objective function difference is best calculated incrementally. It turns out that for most applications this is the fastest way to calculate the difference in the objective function.
  3. The third step is to judge whether the new solution is accepted. The basis for judgment is an acceptance criterion. The most commonly used acceptance criterion is the Metropolis criterion: if ΔT < 0, accept S′ as the new current solution S, otherwise accept S′ with probability P. as the new current solution S.
  4. The fourth step is to replace the current solution with the new solution when the new solution is determined to be accepted. This only requires realizing the transformation part of the current solution corresponding to when the new solution is generated, and at the same time revising the value of the objective function. At this point, the current solution implements one iteration. The next round of testing can be started on this basis. When the new solution is judged to be discarded, the next round of trials will continue based on the original current solution.

2. Case analysis

1. Initialization parameters

# -*- coding: utf-8 -*-
"""
Created on Mon Apr  3 19:17:28 2023

@author: steve
"""
from random import random
import math
import matplotlib.pyplot as plt


max_iter = 100  # 每一次温度降低的迭代次数
alpha = 0.99  # 降温系数
T_f = 0.01  # 温度的终值
T_n = 100  # 当前的温度,也是初始温度
x, y = [random() * 10 - 5 for i in range(max_iter)], [random() * 10 - 5 for i in range(max_iter)] # 进行数据的初始化
f = lambda x, y : (4 * x ** 2 - 2.1 * x ** 4 + x ** 6 / 3 + x * y - 4 * y ** 2 + 4 * y ** 4)  # 我们需要求的函数
result = {
    
    
    "f": [], 
    "t": []
    }  # 用来存放每一次下降的最优解

2. Metrospolis Principles

def metrospolis(T_n, old, new):
    """
    进行 Metrospolis 准则的判断

    Parameters
    ----------
    T_n : int
        当前的温度.  
    old : double
        函数扰动之前的值.
    new : double
        函数扰动之后的值.

    Returns
    -------
    int
        是否需要重新寻找值.
    """
    if old >= new:
        return 1
    else:
        p = math.exp((old - new) / T_n)
        if random() < p:
            return 1
        else:
            return 0

3. Generate new values

def generate_new(T_n, x, y):
    """
    其为扰动的过程

    Parameters
    ----------
    T_n : int
        当前的温度.
    x : double
        DESCRIPTION.
    y : double
        DESCRIPTION.

    Returns
    -------
    list
        返回生成的新值.
    """
    while True:
        x_new = x + T_n * (random() - random())
        y_new = y + T_n * (random() - random())
        if (-5 <= x_new <= 5) & (-5 <= y_new <= 5):  
            break                                  #重复得到新解,直到产生的新解满足约束条件
    return x_new, y_new 

4. Obtain the optimal value

def best(max_iter, f, x, y):
    """
    计算这个温度下的最优值

    Parameters
    ----------
    max_iter : int
        最大的迭代次数.
    f : function
        我们需要求的函数.
    x : double
        DESCRIPTION.
    y : double
        DESCRIPTION.

    Returns
    -------
    list
        返回最优值,以及它的索引.

    """
    min_val, min_inx = f(x[0], y[0]), 0
    for i in range(max_iter):
        val = f(x[i], y[i])
        if min_val > val:
            min_val, min_inx = val, i
            
    return [min_val, min_inx]

5. Main program

def plot(result):
    plt.plot(result['t'], result['f'])
    plt.title('SA')
    plt.xlabel('t')
    plt.ylabel('f')
    plt.gca().invert_xaxis()
    plt.show()


def main(max_iter, alpha, T_f, T_n, x, y, f, result):
    count = 0  # 统计迭代了多少次
    while T_n > T_f:  # 外层循环,当前温度小于最低温度时,终止循环
        for i in range(max_iter):  # 内层循环
            x_new, y_new = generate_new(T_n, x[i], y[i])  # 产生新值
            if metrospolis(T_n, f(x[i], y[i]), f(x_new, y_new)):  # 将原值与新产生的值进行比较
                x[i] = x_new  # 如果接收新值,则存入数组中
                y[i] = y_new
        # 迭代 max_iter 后,记录该温度下的最优解
        [ft, _] = best(max_iter, f, x, y)
        result["f"].append(ft)
        result["t"].append(T_n)
        T_n = T_n * alpha  # 进行降温操作
        count += 1
        
    # 得到最优解
    [f_best, inx] = best(max_iter, f, x, y)
    print(f"F={
      
      f_best}, x_1={
      
      x[inx]}, x_2={
      
      y[inx]}")
    # 进行图像表示
    plot(result)

6. Total code

# -*- coding: utf-8 -*-
"""
Created on Mon Apr  3 19:17:28 2023

@author: steve
"""
from random import random
import math
import matplotlib.pyplot as plt


def metrospolis(T_n, old, new):
    """
    进行 Metrospolis 准则的判断

    Parameters
    ----------
    T_n : int
        当前的温度.  
    old : double
        函数扰动之前的值.
    new : double
        函数扰动之后的值.

    Returns
    -------
    int
        是否需要重新寻找值.
    """
    if old >= new:
        return 1
    else:
        p = math.exp((old - new) / T_n)
        if random() < p:
            return 1
        else:
            return 0
        
        
def generate_new(T_n, x, y):
    """
    其为扰动的过程

    Parameters
    ----------
    T_n : int
        当前的温度.
    x : double
        DESCRIPTION.
    y : double
        DESCRIPTION.

    Returns
    -------
    list
        返回生成的新值.
    """
    while True:
        x_new = x + T_n * (random() - random())
        y_new = y + T_n * (random() - random())
        if (-5 <= x_new <= 5) & (-5 <= y_new <= 5):  
            break                                  #重复得到新解,直到产生的新解满足约束条件
    return x_new, y_new 
    
def best(max_iter, f, x, y):
    """
    计算这个温度下的最优值

    Parameters
    ----------
    max_iter : int
        最大的迭代次数.
    f : function
        我们需要求的函数.
    x : double
        DESCRIPTION.
    y : double
        DESCRIPTION.

    Returns
    -------
    list
        返回最优值,以及它的索引.

    """
    min_val, min_inx = f(x[0], y[0]), 0
    for i in range(max_iter):
        val = f(x[i], y[i])
        if min_val > val:
            min_val, min_inx = val, i
            
    return [min_val, min_inx]


def plot(result):
    plt.plot(result['t'], result['f'])
    plt.title('SA')
    plt.xlabel('t')
    plt.ylabel('f')
    plt.gca().invert_xaxis()
    plt.show()



def main(max_iter, alpha, T_f, T_n, x, y, f, result):
    count = 0  # 统计迭代了多少次
    while T_n > T_f:  # 外层循环,当前温度小于最低温度时,终止循环
        for i in range(max_iter):  # 内层循环
            x_new, y_new = generate_new(T_n, x[i], y[i])  # 产生新值
            if metrospolis(T_n, f(x[i], y[i]), f(x_new, y_new)):  # 将原值与新产生的值进行比较
                x[i] = x_new  # 如果接收新值,则存入数组中
                y[i] = y_new
        # 迭代 max_iter 后,记录该温度下的最优解
        [ft, _] = best(max_iter, f, x, y)
        result["f"].append(ft)
        result["t"].append(T_n)
        T_n = T_n * alpha  # 进行降温操作
        count += 1
        
    # 得到最优解
    [f_best, inx] = best(max_iter, f, x, y)
    print(f"F={
      
      f_best}, x_1={
      
      x[inx]}, x_2={
      
      y[inx]}")
    # 进行图像表示
    plot(result)
    


max_iter = 100  # 每一次温度降低的迭代次数
alpha = 0.99  # 降温系数
T_f = 0.01  # 温度的终值
T_n = 100  # 当前的温度,也是初始温度
x, y = [random() * 10 - 5 for i in range(max_iter)], [random() * 10 - 5 for i in range(max_iter)] # 进行数据的初始化
f = lambda x, y : (4 * x ** 2 - 2.1 * x ** 4 + x ** 6 / 3 + x * y - 4 * y ** 2 + 4 * y ** 4)  # 我们需要求的函数
result = {
    
    
    "f": [], 
    "t": []
    }  # 用来存放每一次下降的最优解

main(max_iter, alpha, T_f, T_n, x, y, f, result)

The final running result is:

Guess you like

Origin blog.csdn.net/qq_62789540/article/details/129950196