5 python numpy sympy python-3.x lambdify
我昨天问了一个问题关于区分python函数的问题,然后当我发现张贴的答案都不能满足我对某些变量的求值(然后绘制导数)的需要时,我便能找到自己的解决方案。
import sympy as sym
import math
def f(x,y):
return x**2 + x*y**2
x, y = sym.symbols('x y')
def fprime(x,y):
return sym.diff(f(x,y),x)
print(fprime(x,y)) #This works.
print(fprime(1,1))
Run Code Online (Sandbox Code Playgroud)
import sympy as sym
import math
def f(x,y):
return x**2 + x*y**2
x, y = sym.symbols('x y')
def fprime(x,y):
return sym.diff(f(x,y),x)
print(fprime(x,y)) #This works.
DerivativeOfF = sym.lambdify((x,y),fprime(x,y),"numpy")
print(DerivativeOfF(1,1))
Run Code Online (Sandbox Code Playgroud)
如您所见,我通过创建新函数DerivativeOfF克服了无法评估派生fprime的功能,该函数是fprime的“ lambdified”版本。从那里,我能够评估DerivativeOfF,并将其绘制在变量之一中。
我的问题是:为什么要这样做?我到底做了什么?这种方法有什么缺点?我曾尝试阅读过lambdify文档,但对我来说却非常混乱(我是Python的初学者)。我的猜测是我将Python函数fprime转换为Sympy表达式DerivativeOfF或类似的东西。任何帮助解释发生了什么事,为什么发生以及lambdify所做的事情(以外行的术语)的帮助,将不胜感激。
让我们看看我是否可以说明这个动作。我很了解 Python numpy
,但没有使用sympy
太多(但使用过其他符号代数包,例如macsyma
)。
在 ipython numpy 会话中:
In [1]: def f(x,y):
...: return x**2 + x*y**2
...:
In [2]: f(1,3)
Out[2]: 10
In [3]: f(np.arange(1,4), np.arange(10,13))
Out[3]: array([101, 246, 441])
Run Code Online (Sandbox Code Playgroud)
f
是一个Python函数;它返回的内容取决于输入如何处理*
、**
和 等操作+
。标量和数组都有效。列出句柄+
和*
(连接、复制),但不列出**
。
In [4]: import sympy as sym
In [5]: x, y = sym.symbols('x y')
In [6]: type(x)
Out[6]: sympy.core.symbol.Symbol
In [7]: x+y
Out[7]: x + y
In [8]: type(_)
Out[8]: sympy.core.add.Add
Run Code Online (Sandbox Code Playgroud)
定义symbols
创建了几个新对象。+
他们以自己的象征方式处理等。
In [9]: fsym = f(x,y)
In [10]: type(fsym)
Out[10]: sympy.core.add.Add
In [11]: print(fsym)
x**2 + x*y**2
Run Code Online (Sandbox Code Playgroud)
f
使用这 2 个符号对象进行调用会创建一个新的 sym 对象。我还可以用符号和数字甚至数组的其他组合来调用它。
In [12]: f(x,0)
Out[12]: x**2
In [13]: f(1,x)
Out[13]: x**2 + 1
In [14]: f(np.arange(3), x)
Out[14]: array([0, x**2 + 1, 2*x**2 + 4], dtype=object)
Run Code Online (Sandbox Code Playgroud)
如果我将此Add
对象传递给我,sym.diff
我会得到一个新Add
对象
In [15]: fprime = sym.diff(fsym,x)
In [16]: fprime
Out[16]: 2*x + y**2
Run Code Online (Sandbox Code Playgroud)
也不fsym
是fprime
可调用的。它们不是 Python 函数。fsym(1,2)
不起作用。
但fsym.subs
可以用来替换x
or/andy
为其他值,无论是数字还是其他符号:
In [19]: fsym.subs(x,1)
Out[19]: y**2 + 1
In [20]: fsym.subs(y,2*x)
Out[20]: 4*x**3 + x**2
In [21]: fsym.subs([(x,1),(y,2)])
Out[21]: 5
In [22]: fprime.subs([(x,1),(y,2)])
Out[22]: 6
Run Code Online (Sandbox Code Playgroud)
lambdify
是一个sympy
函数,它接受一个 sympy 对象并返回一个 Python 函数,可能是numpy
兼容的。
In [24]: fl = sym.lambdify((x,y), fsym, "numpy")
In [25]: fl
Out[25]: <function numpy.<lambda>>
In [26]: fl(1,2)
Out[26]: 5
In [27]: fl(np.arange(1,4), np.arange(10,13)) # cf with f(same) above
Out[27]: array([101, 246, 441])
Run Code Online (Sandbox Code Playgroud)
这个fl
功能和原来的类似f
。它并不相同,例如它有一个help/doc
表达式。
lambdify
应用于fprime
做同样的事情,但使用不同的符号表达式:
In [28]: fpl = sym.lambdify((x,y), fprime, "numpy")
In [29]: fpl(1,2)
Out[29]: 6
In [30]: fpl(np.arange(1,4), np.arange(10,13))
Out[30]: array([102, 125, 150])
Run Code Online (Sandbox Code Playgroud)
python/numpy 函数或表达式与 sympy 函数或表达式之间的这种透明度是有限制的。另一个(已删除)答案试图探索这些。math.sin
例如,numpy.sin
和之间存在差异sym.sin
。
在这些示例中,微分是通过sym.diff
函数象征性地完成的。
In [35]: fsym
Out[35]: x**2 + x*y**2
In [36]: fprime
Out[36]: 2*x + y**2
Run Code Online (Sandbox Code Playgroud)
sym.lambdify
只是将这些 sympy 对象转换为 Python 函数的一种方法。
在其他答案的讨论中选取示例
sym
定义使用sin/cos 版本的函数:
In [53]: def f1(x,y):
...: return sym.sin(x) + x*sym.sin(y)
...:
In [54]: f1(x,y)
Out[54]: x*sin(y) + sin(x)
In [55]: f1(1,2)
Out[55]: sin(1) + sin(2)
In [56]: f1(1, np.arange(3)
...
SympifyError: Sympify of expression 'could not parse '[0 1 2]'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)
Run Code Online (Sandbox Code Playgroud)
我认为因为sym.sin(<array>)
行不通;它必须是np.sin(...)
,但这不适用于符号。
和以前一样,我们可以采用符号导数:
In [57]: sym.diff(f1(x,y),x)
Out[57]: sin(y) + cos(x)
In [58]: sym.diff(f1(x,y),y)
Out[58]: x*cos(y)
In [59]: sym.diff(sym.diff(f1(x,y),x),y)
Out[59]: cos(y)
Run Code Online (Sandbox Code Playgroud)
同样,这些都不起作用。必须使用subs
或进行评估lambdify
。
In [60]: f2 = sym.lambdify((x,y),f1(x,y),"numpy")
In [61]: f2
Out[61]: <function numpy.<lambda>>
In [62]: f2(1, np.arange(3))
Out[62]: array([ 0.84147098, 1.68294197, 1.75076841])
Run Code Online (Sandbox Code Playgroud)
我可以f2
使用数组输入进行评估,而我无法使用f1
. 大概sympy
可以np.sin
替代sym.sin
.
事实上,当我尝试f2
用符号进行评估时,numpy
会抱怨:
In [63]: f2(1,y)
...
/usr/local/lib/python3.5/dist-packages/numpy/__init__.py in <lambda>(_Dummy_30, _Dummy_31)
AttributeError: 'Symbol' object has no attribute 'sin'
In [66]: sym.diff(f2(x,y),x)
....
AttributeError: 'Symbol' object has no attribute 'sin'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1908 次 |
最近记录: |