“添加”对象在数字和符号表达式中没有属性“ sinh”错误?

时间:2019-11-06 20:31:10

标签: python numpy sympy lambdify

最终,我的目标是相对于t,相对于X和相对于X,对表达式'u'(请参见代码)进行数值区分。

第一个想法是只将表达式数字记下来,为X和t提供数组(线性空间)。这导致错误“'添加'对象没有属性'cosh'”。关于此错误,我唯一了解的是它指示我应该使用sympy-functions而不是numpy-functions或其他方式。但是,使用符号表达(sympy函数)然后尝试进行lambdify会产生相同的错误,这次没有属性“ sinh”。

我不知道我要怎么做。符号表达式定义得很好,仅当我将第一个lambdify添加到代码中时,才会发生错误。

import numpy as np
import sympy as sp
c_1=1.35
c_2=0.7
X = sp.Symbol('X')
t = sp.Symbol('t')
u = sp.Function('u')(X,t)
u = 2*(c_1-c_2)*(c_1*(sp.cosh(sp.sqrt(c_2)*(X-c_2*t)/2))**2 + c_2*(sp.sinh(sp.sqrt(c_1)*(-X-c_1*t)/2))**2)/((sp.sqrt(c_1)-sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t) + sp.sqrt(c_2)*(X-c_2*t))/2)+ (sp.sqrt(c_1)+sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t)-sp.sqrt(c_2)*(X-c_2*t))/2))**2
Y= np.linspace(-20,20,100)
T = np.linspace(-35,35,300)
U = sp.lambdify(X,u,"numpy")
U2 = sp.lambdify(t,U(Y),"numpy")(T)

有人知道如何修复我的代码以防止出现此错误,还是知道另一种如上所述对u进行数值区分的方法?

2 个答案:

答案 0 :(得分:0)

usympy表达式。 python / numpy中的Usp.sinh等被翻译为np.sinh等。

U(Y)使用numpy数组对此求值,但是t仍然是一个符号。生成numpy对象dtype数组,其中包含数字和符号的某种混合。 np.sinh(x)被评估为[z.sinh() for z in x]。由于大多数对象(包括符号)都没有sinh方法,因此会引发错误。

对此我不确定,但是我怀疑您需要同时lambdifyX同时t(Y,T)一起进行评估,而不是在两步。

(稍后我可能会尝试通过isympy会话进行演示。)

答案 1 :(得分:0)

SymPy和NumPy是完全独立的库。 SymPy在符号数学领域蓬勃发展,并在数学表达式的每个部分都使用自己的符号。

SymPy和NumPy唯一接触的地方是lambdify,在那里所有内容都转换为NumPy符号,可以进行数字运算了。

函数u不需要符号:它通过基于tX的定义来获取SymPy表示形式。

差异完全发生在SymPy内部,例如diff(u, X, 3)计算u相对于X的三阶导数。 simplify有助于减小表达式的大小。但是,du_dddX的表达式似乎很长,以至于简化需要大量时间。如果您不需要数百万次调用该函数,则可以不做任何简化。

import numpy as np
import sympy as sp
c_1 = 1.35
c_2 = 0.7
X = sp.Symbol('X', real=True)
t = sp.Symbol('t', real=True)
u = 2*(c_1-c_2)*(c_1*(sp.cosh(sp.sqrt(c_2)*(X-c_2*t)/2))**2 + c_2*(sp.sinh(sp.sqrt(c_1)*(-X-c_1*t)/2))**2)/((sp.sqrt(c_1)-sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t) + sp.sqrt(c_2)*(X-c_2*t))/2)+ (sp.sqrt(c_1)+sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t)-sp.sqrt(c_2)*(X-c_2*t))/2))**2
du_dt = sp.simplify(sp.diff(u, t))
du_dX = sp.simplify(sp.diff(u, X))
du_dddX = sp.diff(u, X, 3)
#du_dddX = sp.simplify(du_dddX)

U = sp.lambdify((X,t), u, "numpy")
U1 = sp.lambdify((X,t), du_dt, "numpy")
U2 = sp.lambdify((X,t), du_dX, "numpy")
U3 = sp.lambdify((X,t), du_dddX, "numpy")

# before this line, everything happened in SymPy
# now the NumPy part starts

Y = np.linspace(-20, 20, 20)
T = np.linspace(-35, 35, 20)

print(U(Y, T))
print(U1(Y, T))
print(U2(Y, T))
print(U3(Y, T))

请注意,如果要直接在它们上调用lambdified函数,则Y和T的linspace必须具有相同的大小。您可能想使用np.meshgrid()将1D线性空间扩展到2D网格。网格在两个方向上可以具有不同数量的划分。函数示例:

import matplotlib.pyplot as plt
Y = np.linspace(-20, 20, 100)
T = np.linspace(-35, 35, 300)
YY, TT = np.meshgrid(Y, T)
z = U1(YY, TT)
h = plt.contourf(Y,T,z)
plt.show()

PS:尽管表达式很长,但要将表达式转换为LaTeX:

print(sp.latex(du_dt))
print(sp.latex(du_dX))