## 0 대회 아이디어
(경쟁 질문이 나오는 즉시 CSDN에 공유)
https://blog.csdn.net/dc_sinor?type=blog
1 어닐링 알고리즘의 원리
1.1 물리적 배경
열역학에서 어닐링 현상이란 물체가 점차 냉각되는 물리적 현상을 말하며 온도가 낮을수록 물체의 에너지 상태가 낮아지고 충분히 낮아지면 액체가 응결되어 결정화되기 시작합니다. 상태, 시스템의 에너지 상태가 가장 낮습니다. 자연이 천천히 냉각되면(즉, 어닐링) 가장 낮은 에너지 상태인 결정화를 "찾을" 수 있습니다. 그러나 프로세스가 너무 빠르고 빠르면 급속 냉각("담금질"이라고도 함)으로 인해 에너지가 가장 낮은 상태가 아닌 비정질 상태가 됩니다.
아래 그림과 같이 먼저(왼쪽) 객체가 무정형 상태입니다. 고체를 충분히 높은 온도로 가열하고(가운데 이미지) 천천히 식히거나 어닐링합니다(오른쪽 이미지). 가열하면 온도 상승에 따라 고체 내부의 입자가 무질서해지고 내부 에너지가 증가하는 반면 천천히 냉각하면 입자가 점차 규칙적이 되어 각 온도에서 평형에 도달하고 최종적으로 실온에서 기저 상태에 도달하며, 내부 에너지가 감소합니다. 이 가장 작습니다(이 시점에서 물체는 결정 형태로 나타납니다).
1.2 수학적 모델 뒤에
어닐링의 물리적 의미에 대해 여전히 혼란스럽다면 더 간단한 방법으로 이해하는 것이 중요하지 않습니다. 이제 다음과 같은 함수가 있고 함수의 (전역) 최적 솔루션을 찾고자 한다고 상상해 보십시오. Greedy 전략이 채택되면 A 지점부터 테스트를 시작하고 함수 값이 계속 감소하면 테스트 프로세스가 계속됩니다. 그리고 우리가 B 지점에 도달하면 분명히 우리의 탐색 과정은 끝났습니다(우리가 어떤 방향으로 열심히 일하든 결과는 점점 더 커질 것이기 때문입니다). 결국 부분적인 최종 솔루션 B만 찾을 수 있습니다.
Metropolis 기준에 따르면 입자가 온도 T에서 균형을 이루려는 확률은 exp(-ΔE/(kT))입니다. 여기서 E는 온도 T에서의 내부 에너지, ΔE는 입자의 변화 수, k는 볼츠만 상수입니다. 메트로폴리스 기준은 종종 다음과 같이 표현됩니다.
Metropolis 기준은 온도가 T일 때 dE의 에너지 차이로 온도 강하 확률이 P(dE)임을 보여줍니다. P(dE) = exp(dE/(kT) )로 표현됩니다. 여기서 k는 상수이고 exp는 자연 지수를 나타내며 dE<0입니다. 따라서 P와 T는 양의 상관 관계가 있습니다. 이 공식은 온도가 높을수록 dE의 에너지 차이로 온도 강하 확률이 커지고 온도가 낮을수록 온도 강하 확률이 작아짐을 의미합니다. 그리고 dE는 항상 0보다 작기 때문에(어닐링 공정은 점차적으로 온도를 낮추는 과정이기 때문에) dE/kT < 0이므로 P(dE)의 함수값 범위는 (0,1)이 된다. 온도 T가 감소함에 따라 P(dE)는 점차 감소합니다.
우리는 열악한 솔루션으로의 이동을 온도 점프 프로세스로 간주하고 확률 P(dE)로 그러한 이동을 받아들입니다. 즉, 조합 최적화 문제를 시뮬레이션하기 위해 솔리드 어닐링을 사용할 때 내부 에너지 E는 목적 함수 값 f로 시뮬레이션하고 온도 T는 제어 매개변수 t로 진화합니다. 조합 최적화 문제는 다음과 같이 구합니다. 초기 솔루션 i와 제어 매개 변수 t의 초기 값에서 시작하여 현재 솔루션에 대해 "새 솔루션 생성 → 목적 함수의 차이 계산 → 수락 또는 폐기"를 반복합니다. 솔루션 및 t의 값을 점진적으로 감소 알고리즘이 종료될 때 현재 솔루션은 Monte Carlo 반복 솔루션 방법에 대한 휴리스틱 임의 검색 절차를 기반으로 얻은 근사 최적 솔루션입니다. 어닐링 프로세스는 냉각 일정(냉각 일정)에 의해 제어되며, 제어 매개변수의 초기 값 t 및 감쇠 계수 Δt, 반복 횟수 L 및 각 t 값에 대한 정지 조건 S가 포함됩니다.
2 어닐링 알고리즘 구현
2.1 알고리즘 프로세스
(1) 초기화: 초기 온도 T(충분히 큼), 초기 솔루션 상태 S(알고리즘 반복 시작점), 각 T 값에 대한 반복 시간 L (2) k=1, ..., L에 대해 첫 번째(3
) 6단계로 이동:
(3) 새 솔루션 S' 생성
(4) 증분 Δt'=C(S')-C(S)를 계산합니다. 여기서 C(S)는 평가 함수입니다.
(5) Δt'인 경우 <0인 경우 S'를 새로운 현재 솔루션으로 수락, 그렇지 않으면 확률 exp(-Δt'/T)로 S'를 새로운 현재 솔루션으로 수락
(6) 종료 조건이 충족되면 현재 솔루션을 최적 솔루션으로 출력 프로그램을 종료합니다.
종료 조건은 일반적으로 여러 개의 연속적인 새 솔루션이 수락되지 않을 때 알고리즘을 종료하도록 선택됩니다.
(7) T는 점차 감소하고, T->0 이후 초로 전환
2.2 알고리즘 구현
import numpy as np
import matplotlib.pyplot as plt
import random
class SA(object):
def __init__(self, interval, tab='min', T_max=10000, T_min=1, iterMax=1000, rate=0.95):
self.interval = interval # 给定状态空间 - 即待求解空间
self.T_max = T_max # 初始退火温度 - 温度上限
self.T_min = T_min # 截止退火温度 - 温度下限
self.iterMax = iterMax # 定温内部迭代次数
self.rate = rate # 退火降温速度
#############################################################
self.x_seed = random.uniform(interval[0], interval[1]) # 解空间内的种子
self.tab = tab.strip() # 求解最大值还是最小值的标签: 'min' - 最小值;'max' - 最大值
#############################################################
self.solve() # 完成主体的求解过程
self.display() # 数据可视化展示
def solve(self):
temp = 'deal_' + self.tab # 采用反射方法提取对应的函数
if hasattr(self, temp):
deal = getattr(self, temp)
else:
exit('>>>tab标签传参有误:"min"|"max"<<<')
x1 = self.x_seed
T = self.T_max
while T >= self.T_min:
for i in range(self.iterMax):
f1 = self.func(x1)
delta_x = random.random() * 2 - 1
if x1 + delta_x >= self.interval[0] and x1 + delta_x <= self.interval[1]: # 将随机解束缚在给定状态空间内
x2 = x1 + delta_x
else:
x2 = x1 - delta_x
f2 = self.func(x2)
delta_f = f2 - f1
x1 = deal(x1, x2, delta_f, T)
T *= self.rate
self.x_solu = x1 # 提取最终退火解
def func(self, x): # 状态产生函数 - 即待求解函数
value = np.sin(x**2) * (x**2 - 5*x)
return value
def p_min(self, delta, T): # 计算最小值时,容忍解的状态迁移概率
probability = np.exp(-delta/T)
return probability
def p_max(self, delta, T):
probability = np.exp(delta/T) # 计算最大值时,容忍解的状态迁移概率
return probability
def deal_min(self, x1, x2, delta, T):
if delta < 0: # 更优解
return x2
else: # 容忍解
P = self.p_min(delta, T)
if P > random.random(): return x2
else: return x1
def deal_max(self, x1, x2, delta, T):
if delta > 0: # 更优解
return x2
else: # 容忍解
P = self.p_max(delta, T)
if P > random.random(): return x2
else: return x1
def display(self):
print('seed: {}\nsolution: {}'.format(self.x_seed, self.x_solu))
plt.figure(figsize=(6, 4))
x = np.linspace(self.interval[0], self.interval[1], 300)
y = self.func(x)
plt.plot(x, y, 'g-', label='function')
plt.plot(self.x_seed, self.func(self.x_seed), 'bo', label='seed')
plt.plot(self.x_solu, self.func(self.x_solu), 'r*', label='solution')
plt.title('solution = {}'.format(self.x_solu))
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.savefig('SA.png', dpi=500)
plt.show()
plt.close()
if __name__ == '__main__':
SA([-5, 5], 'max')
결과를 달성하다