简体   繁体   English

sympy lamdify 与 sympy 矩阵和 numpy 向量输入

[英]sympy lambdify with sympy matrix and numpy vector inputs

I want to compute a symbolic gradient with sympy, eg,我想用 sympy 计算一个符号梯度,例如,

import sympy as sym
x, y, z  = sym.symbols("x y z", real=True)

T = sym.cos(x**2+y**2)

gradT = sym.Matrix([sym.diff(T, x), sym.diff(T,y), sym.diff(T,z)])

Now I would like to create a lamddify function with this expression:现在我想用这个表达式创建一个 lamddify 函数:

func = lambdify((x,y,z), gradT,'numpy')

To use the function I have:要使用我有的功能:

gradT_exact = func(np.linspace(0,2,100), np.linspace(0,2,100), np.linspace(0,2,100))

and I receive the following error:我收到以下错误:

<lambdifygenerated-3>:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))

If I change T to be a function of x,y,z it gives me no problems... Why is it giving warnings when T only depends on x and y and z is set to zero.如果我将 T 更改为 x,y,z 的函数,它不会给我带来任何问题......当 T 仅取决于 x 和 y 并且 z 设置为零时,为什么它会发出警告。

Thanks in advance!提前致谢!

The gradT expression: gradT表达式:

In [84]: gradT
Out[84]: 
⎡        ⎛ 2    2⎞⎤
⎢-2⋅x⋅sin⎝x  + y ⎠⎥
⎢                 ⎥
⎢        ⎛ 2    2⎞⎥
⎢-2⋅y⋅sin⎝x  + y ⎠⎥
⎢                 ⎥
⎣        0        ⎦

and its conversion to numpy :并将其转换为numpy

In [87]: print(func.__doc__)
Created with lambdify. Signature:

func(x, y, z)

Expression:

Matrix([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]])

Source code:

def _lambdifygenerated(x, y, z):
    return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))

If x and y are arrays, then 2 terms will reflect their dimension(s), but the last is [0] .如果xy是数组,则 2 项将反映它们的维度,但最后一项是[0] That's why you get the ragged warning.这就是为什么你的ragged警告。

lambdify does a rather simple lexical translation. lambdify做了一个相当简单的词法翻译。 It does not implement any deep understanding of numpy arrays.它没有实现对numpy数组的任何深入理解。 At some level it's your responsibility to check that the numpy code looks reasonable.在某种程度上,您有责任检查 numpy 代码是否合理。

with scalar inputs:使用标量输入:

In [88]: func(1,2,3)
Out[88]: 
array([[1.91784855],
       [3.8356971 ],
       [0.        ]])

but if one input is an array:但如果一个输入是一个数组:

In [90]: func(np.array([1,2]),2,3)
<lambdifygenerated-1>:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))
Out[90]: 
array([[array([ 1.91784855, -3.95743299])],
       [array([ 3.8356971 , -3.95743299])],
       [0]], dtype=object)

The result is object dtype containing 2 arrays, plus that [0] list.结果是包含 2 个数组和[0]列表的对象 dtype。

To avoid this problem, the lambdify would have to produce a function like:为了避免这个问题, lambdify必须产生一个函数,如:

In [95]: def f(x,y,z):
    ...:     temp = 0*x*y
    ...:     return np.array([-2*x*np.sin(x**2 + y**2), -2*y*np.sin(x**2 + y**2)
    ...: , temp])

where temp is designed to give 0 value, but with a shape that reflects the broadcasted operations on x and y in the other terms.其中temp旨在给出0值,但其形状反映了其他项中xy上的广播操作。 I think that's asking too much of lambdify .我认为这对lambdify要求过高。

In [96]: 

In [96]: f(np.array([1,2]),2,3)
Out[96]: 
array([[ 1.91784855, -3.95743299],
       [ 3.8356971 , -3.95743299],
       [ 0.        ,  0.        ]])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM