1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| import os
import matplotlib
matplotlib.use('TkAgg') import numpy as np import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False
""" 目标函数:Rastrigin函数的最小值 """
def objective_function(x: list): A = 10 n = len(x) return A * n + sum([xi ** 2 - A * np.cos(2 * np.pi * xi) for xi in x])
def simulated_annealing(initial_state: list, objective_function, initial_temperature: float = 100, cool_rate: float = 0.95, num_iterations: float = 1000, perturbation_scale: float = 0.1): """ 模拟退火函数 :param initial_state:初始状态 :param objective_function:目标函数 :param initial_temperature:初始温度 :param cool_rate:冷却系数 :param num_iterations:迭代次数 :param perturbation_scale:扰动大小 :return:结果 """ current_state = initial_state.copy() best_state = initial_state.copy() current_energy = objective_function(current_state) best_energy = current_energy
energies = [current_energy] temperatures = [initial_temperature] states = [current_state.copy()] best_states = [] temperature = initial_temperature
for iteration in range(num_iterations): neighbor = current_state + np.random.normal(0, perturbation_scale, len(current_state)) neighbor_energy = objective_function(neighbor) delta_energy = neighbor_energy - current_energy if delta_energy < 0 or np.random.rand() < np.exp(-delta_energy / temperature): current_state = neighbor current_energy = neighbor_energy
if current_energy < best_energy: best_state = current_state.copy() best_energy = current_energy temperature *= cool_rate energies.append(current_energy) temperatures.append(temperature) states.append(current_state.copy())
best_states.append(best_state.copy()) if (iteration + 1) % 100 == 0: print(f"Iteration {iteration + 1}/{num_iterations}, " f"Current Energy: {current_energy:.4f}, " f"Best Energy: {best_energy:.4f}, " f"Temperature: {temperature:.4f}")
return { 'best_state': best_state, 'best_energy': best_energy, 'energies': np.array(energies), 'temperatures': np.array(temperatures), 'states': np.array(states), 'best_states_every_10': np.array(best_states) }
seed = int.from_bytes(os.urandom(4), byteorder='big', signed=False) print("种子", seed) np.random.seed(seed) initial_state = np.random.uniform(-5.12, 5.12, 2) print("initial_state", initial_state) result = simulated_annealing( initial_state, objective_function, initial_temperature=100, cool_rate=0.99, num_iterations=2000, perturbation_scale=0.5 )
best_state = result['best_state'] print("最终结果", best_state, "误差", np.sqrt(best_state[0] ** 2 + best_state[1] ** 2))
best_states = result['best_states_every_10'] x_opt = best_states[:, 0] y_opt = best_states[:, 1]
x = np.linspace(-5.12, 5.12, 200) y = np.linspace(-5.12, 5.12, 200) X, Y = np.meshgrid(x, y) Z = objective_function([X.ravel(), Y.ravel()]).reshape(X.shape)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 6))
contour = ax1.contourf(X, Y, Z, levels=20, cmap='coolwarm') fig.colorbar(contour, ax=ax1, label='目标函数值') ax1.set_title(f'Rastrigin函数等高线图,种子={seed}') ax1.set_xlabel('x1') ax1.set_ylabel('x2')
ax1.scatter(result['best_state'][0], result['best_state'][1], c='green', s=100, label='最终最优解', edgecolors='black', zorder=3) ax1.scatter(initial_state[0], initial_state[1], c='yellow', s=100, label='初始点', edgecolors='black', zorder=3) ax1.plot(x_opt, y_opt, 'r-o', linewidth=2, markersize=4, label='优化路径', zorder=2) for i, (xi, yi) in enumerate(best_states): ax1.text(xi + 0.5, yi, f'{i + 1}', color='purple', fontsize=10, ha='center', va='center', bbox=dict(facecolor='white', alpha=0.7), zorder=1)
ax1.set_aspect('equal', adjustable='box') ax1.set_xlim(-5.12, 5.12) ax1.set_ylim(-5.12, 5.12)
ax1.legend() ax1.grid(True)
ax2.plot(result['energies'], label='能量变化', color='blue', linewidth=1) ax2.set_title('能量变化') ax2.set_xlabel('迭代次数') ax2.set_ylabel('能量值') ax2.legend() ax2.grid(True)
plt.tight_layout() plt.show()
|