在 Sympy 中表示常量符号,使其不是 free_symbol

Rob*_*all 1 sympy python-3.x

应用程序 我想创建一个 python 函数(例如Laplacian(expr))。expr拉普拉斯算子被定义为取关于每个变量的二阶偏导数之和(例如, Laplacian(f(x,y,z))is diff(f,x,x) + diff(f,y,y) + diff(f,z,z)。在表达式中,可能有任意常量c,k等,就表达式而言,它们不是变量。只是由于不能求导数diff(f,126),因此对表达式求导c是没有定义的。

我需要能够从表达式中提取非常量的自由符号。

问题c = Symbol('c', constant=True, number=True)虽然我可以在 Sympy 中 构建,c.is_constant()但计算结果为False. 同样,g(c).is_constant()评估结果为 false。对于我的应用程序,该符号应该具有与和c完全相同的行为,因为它是一个数字。E.is_constant() == Trueg(E).is_constant() == True

注意事项

  1. 我无法注册c为单例,因为它仅针对此特定证明或表达式进行定义。
  2. 我无法以与构造类似值相同的方式构造它E,因为没有可以分配给它的特定数值。
  3. 我不能简单地将constants关键字添加到,因为我不知道可能出现的所有此类常量(就像添加到Laplacian没有意义一样)。constants=[1,2,3,4,...]solve()

  4. 我不能简单地variables向 中添加关键字Laplacian,因为我不知道表达式中出现的变量。

期望的用法如下:

>>> C = ... # somehow create the constant
>>> symbols_that_arent_constant_numbers(g(C))
set()
>>> symbols_that_arent_constant_numbers(g(C, x))
{x}
>>> g(C).is_constant()
True
Run Code Online (Sandbox Code Playgroud)

延伸目标:如果有一个任意常数符号能够以相同的方式吸收其他常数项,那就太棒了constantsimpc考虑在表达式中引入积分常数,然后将该表达式乘以I。就代数而言,cI=c不失任何一般性。

Rob*_*all 5

笔记

根据 Oscar Benjamin 对问题的评论,构建 sympy 风格的方法(如 )时的当前最佳实践是将or关键字Laplacian传递到方法中。应用以下解决方案时请记住这一点。此外,Sympy 中有许多应用程序,因此使用另一个已建立语义的类可能会产生意想不到的副作用。constantsvariablesfree_symbols

(如果出现更好的解决方案,我不会接受我自己的解决方案,正如本杰明先生指出的那样,存在许多未解决的相关问题。)

解决方案

Sympy 提供了一种创建此类常量的机制:sympy.physics.units.quantities.Quantity。它的行为等同于Symbol单例常量,但最值得注意的是它并不作为自由符号出现。这可以帮助防止代码将其解释为可微分的变量等。

from sympy.physics.units.quantities import Quantity
C = Quantity('C')

print("C constant?        : ", C.is_constant())
print("C free symbols     : ", C.free_symbols)
print("x constant?        : ", x.is_constant())
print("g(C) constant?     : ", g(C).is_constant())
print("g(x) constant?     : ", g(x).is_constant())
print("g(C,x) constant    : ", g(C,x).is_constant())
print("g(C) free symbols  : ", g(C).free_symbols)
print("g(C,x) free symbols: ", g(C,x).free_symbols)

assert C.is_constant()
assert C.free_symbols == set([])
assert g(C).is_constant()
assert g(C, x).is_constant() == g(x).is_constant() # consistent interface
assert g(C).free_symbols == set([])
assert g(C, x).free_symbols == set([x])
assert [5/C] == solve(C*x -5, x)
Run Code Online (Sandbox Code Playgroud)

当在 中测试时,上面的代码片段会产生以下输出sympy==1.5.1

C constant?        :  True
C free symbols     :  set()
x constant?        :  False
g(C) constant?     :  True
g(x) constant?     :  None
g(C,x) constant    :  None
g(C) free symbols  :  set()
g(C,x) free symbols:  {x}
Run Code Online (Sandbox Code Playgroud)

请注意,虽然g(C).is_constant()==True,我们看到了g(x).is_constant() == None,以及g(C,x).is_constant() == None。因此,我只断言这两个应用程序具有一致的界面。