模拟退火法--数学建模(附案例代码)

1.模拟退火算法简介

模拟退火算法(Simulated Annealing,SA)是一种随机搜索算法,可以在非常复杂的问题中找到全局最优解或接近最优解的解。它的名字来源于固体物理中的模拟退火过程,退火过程是将物质加热至高温再缓慢冷却的过程,在这个过程中物质会经历多次随机的结构变化,最终达到最小自由能量状态。

模拟退火算法与传统的最优化算法不同,它不一定保证每一步都是向着更优解的方向走的,而是以一定的概率接受劣解。这个概率随着退火温度的下降而减小,最终趋近于零。这种机制使得算法能够跳出局部最优解,避免陷入局部最优解,找到全局最优解的概率更高。

模拟退火算法需要设定一些参数,包括初始温度、降温速度、停止温度等。这些参数的设置对算法的效果影响很大,需要通过实验来确定最优参数。

模拟退火算法可以用于多种类型的优化问题,例如组合优化、连续优化、整数规划等。

下面是一个简单的模拟退火算法的伪代码:

  1. 设定初始温度T和初始解x0
  2. 当T > 停止温度时,执行以下循环
    1. 随机生成一个新解x
    2. 计算解的差值delta = f(x) - f(x0)
    3. 如果delta < 0,接受新解x
    4. 如果delta >= 0,以概率exp(-delta/T)接受新解x
    5. 降低温度T
  3. 返回当前解x0

其中,f(x)表示解x的目标函数值。随着温度的降低,接受劣解的概率会逐渐降低,因此算法最终能够收敛到全局最优解。

需要注意的是,模拟退火算法通常需要多次运行,以得到最好的结果。因为算法的结果很大程度上依赖于随机数的选择,多次运行可以减少随机数的影响,提高算法的可靠性。

2.模拟退火法在数学建模中应用

模拟退火法在数学建模中有广泛的应用,包括在优化、组合优化、计算物理、统计物理等领域中的应用。

  1. 优化问题:模拟退火法可以用来解决各种优化问题,例如参数寻优、最小二乘、非线性规划等。在实际应用中,模拟退火法常常与其他优化算法结合使用,如遗传算法、蚁群算法等。

  2. 组合优化问题:模拟退火法可以应用于各种组合优化问题,如旅行商问题、图着色问题、背包问题等。

  3. 计算物理问题:模拟退火法可以应用于各种计算物理问题,如蒙特卡罗模拟、自旋玻璃等。

  4. 统计物理问题:模拟退火法可以应用于各种统计物理问题,如模拟固体结构、模拟自由能等。

总之,模拟退火法是一种通用的求解优化问题的方法,可以应用于各种不同的数学建模问题中,其适用范围非常广泛。

3.模拟退火法应用案例代码

3.1组合优化问题应用案例代码

下面是一个模拟退火法在旅行商问题中的应用例子

假设有5个城市,它们的坐标分别为(0,0)、(1,3)、(2,5)、(3,2)和(4,6)。旅行商要依次经过这5个城市,最后回到起点。求出最短的路径。

import math
import random

# 计算两个城市之间的距离
def distance(city1, city2):
    return math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2)

# 计算路径的总长度
def path_length(path, cities):
    length = 0
    for i in range(len(path) - 1):
        length += distance(cities[path[i]], cities[path[i+1]])
    length += distance(cities[path[-1]], cities[path[0]])
    return length

# 生成一个随机的路径
def generate_path(num_cities):
    path = list(range(num_cities))
    random.shuffle(path)
    return path

# 模拟退火算法
def simulated_annealing(cities, max_temperature, cooling_rate):
    # 初始温度
    temperature = max_temperature
    # 初始路径
    path = generate_path(len(cities))
    # 初始路径长度
    length = path_length(path, cities)
    while temperature > 1:
        # 生成一个随机的邻域
        new_path = path[:]
        i = random.randint(0, len(path) - 1)
        j = random.randint(0, len(path) - 1)
        new_path[i], new_path[j] = new_path[j], new_path[i]
        # 计算新路径长度
        new_length = path

3.2优化问题中应用案例代码

以下是一个简单的模拟退火算法在优化问题中的应用案例代码。该代码演示了如何使用模拟退火算法求解一个简单的函数最小值问题。

import math
import random

# 目标函数
def target_function(x, y):
    return math.sin(x) + math.cos(y)

# 初始温度
start_temperature = 1000

# 冷却率
cooling_rate = 0.99

# 迭代次数
max_iteration = 1000

# 初始状态
current_x = random.uniform(-10, 10)
current_y = random.uniform(-10, 10)

# 初始解的评价值
current_energy = target_function(current_x, current_y)

# 最优解
best_x = current_x
best_y = current_y
best_energy = current_energy

# 模拟退火算法
while start_temperature > 1e-5 and max_iteration > 0:
    # 随机生成一个新状态
    new_x = current_x + random.uniform(-0.5, 0.5)
    new_y = current_y + random.uniform(-0.5, 0.5)
    
    # 计算新解的评价值
    new_energy = target_function(new_x, new_y)
    
    # 计算能量差
    delta_energy = new_energy - current_energy
    
    # 判断是否接受新解
    if delta_energy < 0 or math.exp(-delta_energy / start_temperature) > random.uniform(0, 1):
        current_x = new_x
        current_y = new_y
        current_energy = new_energy
        
        # 更新最优解
        if current_energy < best_energy:
            best_x = current_x
            best_y = current_y
            best_energy = current_energy
    
    # 降温
    start_temperature *= cooling_rate
    max_iteration -= 1
    
print("Best solution: x = {:.4f}, y = {:.4f}, energy = {:.4f}".format(best_x, best_y, best_energy))

此代码通过模拟退火算法求解函数 $f(x, y) = \sin(x) + \cos(y)$ 的最小值。其中,初始温度为 1000,冷却率为 0.99,迭代次数为 1000。每次迭代时,随机生成一个新状态,计算新解的评价值,并计算能量差。如果能量差小于 0,直接接受新解;否则,以一定概率接受新解,其中接受概率与能量差和温度有关。随着迭代次数的增加,温度不断降低,最终收敛到最优解。

3.3计算物理问题中应用案例代码

以下是模拟退火算法在计算物理问题中的一个应用案例,即用模拟退火算法模拟氢原子在外场作用下的能级结构:

import numpy as np
import matplotlib.pyplot as plt

def V(r):  # 外场势能
    return -1 / r

def get_energy(n, l, m, r):  # 能级计算函数
    return -1 / 2 / n ** 2 + l * (l + 1) / 2 / n ** 2 - m ** 2 / 2 / n ** 2 - V(r)

def accept(delta_E, T):  # 是否接受新状态的判断函数
    if delta_E <= 0:
        return True
    elif np.random.random() < np.exp(-delta_E / T):
        return True
    else:
        return False

n_max = 4  # 最大量子数
l_max = 2  # 最大角量子数
m_max = 2  # 最大磁量子数
N = 100  # 样本数
T_init = 1  # 初始温度
T_final = 1e-3  # 最终温度
alpha = 0.99  # 降温因子

r = np.linspace(1e-6, 10, N)  # 半径
energy = np.zeros((n_max, l_max, m_max, N))  # 能量数组

for n in range(1, n_max + 1):
    for l in range(n):
        for m in range(-l, l + 1):
            E = np.zeros(N)
            E[0] = get_energy(n, l, m, r[0])
            for i in range(1, N):
                T = T_init * alpha ** i  # 温度降低
                E_new = get_energy(n, l, m, r[i])  # 新状态的能量
                delta_E = E_new - E[i - 1]  # 能量变化量
                if accept(delta_E, T):
                    E[i] = E_new
                else:
                    E[i] = E[i - 1]
            energy[n - 1, l, m + l_max, :] = E

fig, ax = plt.subplots(n_max, l_max, figsize=(12, 12))
for n in range(1, n_max + 1):
    for l in range(n):
        for m in range(-l, l + 1):
            ax[n - 1, l].plot(r, energy[n - 1, l, m + l_max, :], label='m={}'.format(m))
            ax[n - 1, l].set_title('n={}, l={}'.format(n, l))
            ax[n - 1, l].set_xlabel('r')
            ax[n - 1, l].set_ylabel('E')
            ax[n - 1, l].legend(loc='best')

plt.tight_layout()
plt.show()

该代码通过模拟退火算法模拟了氢原子在外场作用下的能级结构,具体来说,通过计算氢原子在不同半径下的能量,得到了不同的能级和能量。

3.4统计物理问题中应用案例代码

以下是模拟退火法在统计物理问题中应用的一个案例代码:

import numpy as np
import matplotlib.pyplot as plt

# 模拟系统温度
T = 1

# 模拟系统长度
N = 50

# 初始状态(随机生成)
state = np.random.randint(2, size=N)

# 计算能量
def calc_energy(state):
    return -np.sum(state[1:]*state[:-1])

# 计算概率
def calc_prob(delta_e):
    return np.exp(-delta_e / T)

# 进行模拟退火算法
def simulate_annealing(state, max_iter=10000, cooling_rate=0.01):
    energies = [calc_energy(state)]
    states = [state]
    for i in range(max_iter):
        # 随机翻转一个粒子
        j = np.random.randint(N)
        new_state = np.copy(state)
        new_state[j] = 1 - new_state[j]
        delta_e = calc_energy(new_state) - energies[-1]
        if delta_e <= 0 or np.random.rand() < calc_prob(delta_e):
            state = new_state
            energies.append(calc_energy(state))
            states.append(state)
        else:
            energies.append(energies[-1])
            states.append(states[-1])
        T *= (1 - cooling_rate)
    return states, energies

# 进行模拟退火
states, energies = simulate_annealing(state)

# 画出能量随迭代次数的变化曲线
plt.plot(np.arange(len(energies)), energies)
plt.xlabel('Iteration')
plt.ylabel('Energy')
plt.show()

# 画出最终状态
plt.imshow([states[-1]], cmap='gray')
plt.show()

这个例子是一个简单的伊辛模型,模拟了一个具有50个粒子的系统,在高温下随机初始化粒子的状态,然后使用模拟退火算法寻找系统的基态。在每个迭代步骤中,随机翻转一个粒子的状态,然后根据能量差和概率来决定是否接受这个新状态。在退火过程中,温度不断下降,直到最终冷却到0。最终状态可以用一张图片来表示,黑色代表粒子为1,白色代表粒子为0。

matlab在数学建模中应用源码+pdf分享:

链接:https://pan.baidu.com/s/1aAmX9uVv9I69zCFNJHAB8w 
提取码:7hzt

数学建模从入门到实战经验分享:

链接:https://pan.baidu.com/s/19ZqTFYQZH5zUIpZowcR5Bg 
提取码:gopt

30+种算法模型及案例代码知识分享(纯干货):

链接:https://pan.baidu.com/s/1Pg_PgPJ8-EJ0RMjZ6_dF3Q?pwd=fid3 
提取码:fid3 

猜你喜欢

转载自blog.csdn.net/qq_51533426/article/details/130431949