物理学中统计力学中熵最大化的一个简单问题如下 .

目标是最大化熵函数(在stackexchange中仍然缺少LaTeX?):

H = - sum_x P_x ln P_x

受以下约束:标准化约束

1 = sum_x P_x

和平均能量的约束

U = sum_i E_x P_x

索引i在x = 1,2,...,n上运行的位置 . E_x表示系统处于微观状态x时的能量,P_x是系统处于微观状态x的概率 .

可以通过Lagrange multipliers的方法获得对这种问题的解决方案 . 在这种情况下,它的工作原理如下......

首先,拉格朗日定义为

L = H a(1 - sum_i P_x)b(U - sum_i P_x E_x)

这里,a和b是拉格朗日乘数 . 拉格朗日L是a,b的函数,x = 1,2,...,n的概率P_x . 术语a(1-sum_x P_x)对应于归一化约束,术语b(E-sum_x P_x E_x)对应于平均能量约束 .

其次,计算L相对于a,b的偏导数和不同x = 1,2,...,n的P_x . 这导致了

dL / da = 1 - sum_x P_x

dL / db = E - sum_x E_x P_x

dL / P_x = dH / P_x - a - b E_x = - ln P_x - 1 - a - b E_x

第三,我们通过将这些衍生物等同为零来找到解决方案 . 这是有道理的,因为有2 n个方程,我们有2 n个未知数:P_x,a和b . 这些方程的解决方案如下

P_x = exp( - b E_x)/ Z.

哪里

Z = sum_x exp( - b E_x)

和b由关系隐式确定

E = sum_x P_x E_x =(1 / Z)sum_x exp(-b E_x)E_x

现在定义了“数学”问题,让我们说出“计算”问题(这是我想在这里问的问题) .

计算问题如下: I would like to reproduce the previous derivation in Sympy.

我的想法是使流程自动化,最终,我可以攻击类似但更复杂的问题 .

我已经取得了一些进展 . 不过,我认为我还没有采用最好的方法 . 这是我的解决方案 .

# Lets attempt to derive these analytical result using SymPy.

import sympy as sy
import sympy.tensor as syt

# Here, n is introduced to specify an abstract range for x and y.
n = sy.symbols( 'n' , integer = True )
a , b = sy.symbols( 'a b' ) # The Lagrange-multipliers.
x = syt.Idx( 'x' , n ) # Index x for P_x
y = syt.Idx( 'y' , n ) # Index y for P_y; this is required to take derivatives according to SymPy rules.

>>> P = syt.IndexedBase( 'P' ) # The unknowns P_x.
>>> E = syt.IndexedBase( 'E' ) # The knowns E_x; each being the energy of state x.
>>> U = sy.Symbol( 'U' ) # Mean energy.
>>> 
>>> # Entropy
>>> H = sy.Sum( - P[x] * sy.log( P[x] ) , x )
>>> 
>>> # Lagrangian
>>> L = H + a * ( 1 - sy.Sum( P[x] , x ) ) + b * ( U - sy.Sum( E[x] * P[x] , x ) )

>>> # Lets compute the derivatives
>>> dLda = sy.diff( L , a )
>>> dLdb = sy.diff( L , b )
>>> dLdPy = sy.diff( L , P[y] )

>>> # These look like
>>> 
>>> print dLda
-Sum(P[x], (x, 0, n - 1)) + 1
>>> 
>>> print dLdb
U - Sum(E[x]*P[x], (x, 0, n - 1))
>>>  
>>> print dLdPy
-a*Sum(KroneckerDelta(x, y), (x, 0, n - 1)) - b*Sum(KroneckerDelta(x, y)*E[x], (x, 0, n - 1)) + Sum(-log(P[x])*KroneckerDelta(x, y) - KroneckerDelta(x, y), (x, 0, n - 1))

>>> # The following approach does not work
>>> 
>>> tmp = dLdPy.doit()
>>> print tmp
-a*Piecewise((1, 0 <= y), (0, True)) - b*Piecewise((E[y], 0 <= y), (0, True)) + Piecewise((-log(P[y]) - 1, 0 <= y), (0, True))
>>>     
>>> sy.solve( tmp , P[y] )
[]

>>> # Hence, we try an ad-hoc procedure
>>> Px = sy.Symbol( 'Px' )
>>> Ex = sy.Symbol( 'Ex' )
>>> tmp2 = dLdPy.doit().subs( P[y] , Px ).subs( E[y] , Ex ).subs( y , 0 )
>>> print tmp2
-Ex*b - a - log(Px) - 1

>>> Px = sy.solve( tmp2 , Px )
>>> print Px
[exp(-Ex*b - a - 1)]

是否有“更好”的方式继续进行?特别是,我不喜欢用Px代替P [y]和用Ex代替E [y]来解决方程 . 为什么方程不能用P [y]来求解?