python嵌套结构力学公式_【数学建模】用python numpy实现模拟退火算法

本文介绍【数学建模】用pythonnumpy实现模拟退火算法,举例源码综合分析了这个知识,无论是学习还是工作都有很大的帮助,喜欢的请深究。

前言

模拟退火算法是现代优化算法的一种,是一种启发式算法。即上一次的计算结果会对下一次结果造成影响。模拟退火算法得益于材料的统计力学结果。结构力学表明材料中离子的不同结构对应于粒子的不同能量水平。在高温条件下,粒子的能量较高,可以自由运动和重新排列;而在低温条件下,粒子的能量较低。若从高温开始,非常缓慢地降温(即退火),粒子就可以在某个温度下达到热平衡,当系统完全冷却时,形成能量最低形态的晶体。

模型过程

采用Metropolis算法可以用一个很简单的数学模型描述退火过程。

假设材料在状态iii之下的能量为E(i)E(i)E(i),那么材料在温度TTT时从状态iii进入状态jjj就会遵循以下规律:

(1)若E(j)≤E(i)E(j) \leq E(i)E(j)≤E(i),接受该状态被转换;

(2)若E(j)>E(i)E(j)>E(i)E(j)>E(i),以一定的概率ppp接受状态变换。

其中,p=eE(i)−E(j)KTp=e^{\frac{E(i)-E(j)}{K T}}p=eKTE(i)−E(j)​。

因此在求解优化问题时,即可通过该思想来对模型进行求解。

若一个组合优化问题:优化函数为:f:x→Rf: x \rightarrow R^{ }f:x→R,其中 x∈Sx\in Sx∈S为优化问题的一个可行解,R={y∣y∈R,y>0}R^{ }=\{y \mid y \in R, y>0\}R={y∣y∈R,y>0},且SSS表示函数定义域。

在进行求解时,首先给定一个初始温度T0T_0T0​和一个初始解x(0)x(0)x(0),并由该初始解形成一个在其邻域内的新解x′x'x′,是否接受该新截遵循以下公式:

P(x(0)→x′)={1若f(x′)

而对于其他任一温度TiT_iTi​时,接受新解的概率为:

P(x(k)→x′)={1若f(x′)

实例

现利用模拟退火算法解决一个简单的二次函数极值问题。

代码如下:

#模拟退火算法求函数极值

import numpy as np

def func(x):

return 21.5x[:,0]*np.sin(20*np.pi*x[:,0]) x[:,1]*np.sin(20*np.pi*x[:,1])

#定义变量

var = 2 #变量个数

T0 = 1000 #初始温度

Tt = T0 #t时刻温度

maxi = 1000 #迭代次数

times = 200 #每个温度下的迭代次数

alfa = 0.95 #衰减系数

xlow = np.array([[-3,4.1]]) #下界

xhigh = np.array([[12.1,5.8]]) #上界

#生成初始解

x0 = np.zeros((1,var))

for i in range(var):

x0[:,i] = xlow[:,i] (xhigh[:,i]-xlow[:,i])*np.random.rand()

it_x,it_y = [x0],[func(x0)]

#模拟退火过程

for i in range(maxi):

for j in range(times):

y0 = func(x0)

y = np.random.randn(1,var)

z = y / np.sqrt(np.sum(y*y))

xnew = x0 z*Tt

for k in range(var):

if xnew[:,k] < xlow[:,k]:

r = np.random.rand()

xnew[:,k] = r*xhigh[:,k] (1-r)*x0[:,k]

elif xnew[:,k] > xhigh[:,k]:

r = np.random.rand()

xnew[:,k] = r*xlow[:,k] (1-r)*x0[:,k]

x1 = xnew

y1 = func(x1)

if y1 > y0:

print('接受新解:{}'.format(x1))

x0 = x1

it_x.append(x1)

it_y.append(y1)

else:

p = np.exp(-(y0-y1)/Tt)

if np.random.rand() > p:

print('新解较小,但仍接受新解:{}'.format(x1))

else:

print('保留旧解')

x0 = x1

Tt = alfa*Tt

print(max(it_y))

最终求解结果为极值:39.15003305。

下面是相同的问题的另一种代码,思想一样,但是编写方式稍微有些不同:

import random

import numpy as np

def ob(x):

return 21.5 x[:,0]*np.sin(20*np.pi*x[:,0]) x[:,1]*np.sin(20*np.pi*x[:,1])

def main(T, x0, J):

global fB

n = 1

xl = np.array([[-3,4.1]])

xu = np.array([[12.1,5.8]])

while n <= 501:

fA = ob(x0)

print("旧解{}".format(fA))

a = np.random.randn(1,2)

zi = a / (sum(a ** 2) ** 0.5)

xn = x0 T*zi

for k in range(2):

if xn[:,k] < xl[:,k]:

r = np.random.rand()

xn[:,k] = r*xu[:,k] (1-r)*x0[:,k]

elif xn[:,k] > xu[:,k]:

r = np.random.rand()

xn[:,k] = r*xl[:,k] (1-r)*x0[:,k]

x1 = xn

fB = ob(x1)

if fB >= fA:

print("第{}次操作,接受新解{}".format((i-1) * 500 n, fB))

fA, x0 = fB, x1

elif fB < fA:

P = np.exp(-(abs(fB - fA) / T))

r = random.uniform(0, 1)

if P >= r:

print("第{}次操作,虽然比较小,但我们接受新解{}".format(i * n, fB))

fA, x0 = fB, xn

else:

print("第{}次操作,仍使用旧解{}".format((i-1) * 500 n, fA))

J.append(fB)

n = 1

return xn

T0 = 100

x0 = np.zeros((1,2))

J = []

for i in range(1,201):

T = 0.95**i*T0

main(T, x0, J)

xn = main(T,x0,J)

print("{:*^25}".format("分割线"))

print("最优解是{}".format(max(J)))

第一种方式是我自己写的,第二种是我老婆写的。最后的结果比较相近,求解得极值为:39.10768688。

参考来源

https://www.bilibili.com/video/BV1hK41157JL

关键词:python,算法,数学,数学建模,建模,实现,模拟,模拟退火,模拟退火算法,退火

你可能感兴趣的:(python嵌套结构力学公式)