Numpy Sympy lambdify最大可操作性

Numpy Sympy lambdify最大可操作性,numpy,sympy,Numpy,Sympy,Sympy可用于连接numpy和Sympy之间的功能。但是,我没有发现使用lambdify时存在哪些缺点。例如,我有兴趣将Max与sympy和numpy一起使用: f = lambdify([x], Max(x, 1), 'numpy') f(np.array([-1,0,1])) 抛出ValueError: ValueError: The argument '[-1, 0, 1]' is not comparable. 另一方面,采用dunder方法的原油操作效果良好: f = lamb

Sympy可用于连接numpy和Sympy之间的功能。但是,我没有发现使用lambdify时存在哪些缺点。例如,我有兴趣将Max与sympy和numpy一起使用:

f = lambdify([x], Max(x, 1), 'numpy')

f(np.array([-1,0,1]))
抛出ValueError:

ValueError: The argument '[-1, 0, 1]' is not comparable.
另一方面,采用dunder方法的原油操作效果良好:

f = lambdify([x], Add(x, 1), 'numpy')

f(np.array([-1,0,1]))
输出:

array([0, 1, 2])
最后,我希望lambdify使用包含sympy符号对象的numpy数组(或
sympy.tensor.array.array
):

抛出类型错误:

TypeError: cannot determine truth value of Relational
我的预期产出是:

array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)
当然,我可以使用列表理解来实现这一点。

帮助(f)
显示:

Help on function _lambdifygenerated:

_lambdifygenerated(x)
    Created with lambdify. Signature:
    
    func(x)
    
    Expression:
    
    Max(1, x)
    
    Source code:
    
    def _lambdifygenerated(x):
        return (amax((1,x), axis=0))
尝试将此应用于1d阵列有两个问题

In [62]: a
Out[62]: array([-1,  0,  1])
首先,它尝试从
(1,x)
生成一个数组,从而产生“不规则数组”警告

In [63]: f(a)
/usr/local/lib/python3.8/dist-packages/numpy/core/fromnumeric.py:87: 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 ufunc.reduce(obj, axis, dtype, out, **passkwargs)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-63-730f2a0fa0b7> in <module>
----> 1 f(a)

<lambdifygenerated-4> in _lambdifygenerated(x)
      1 def _lambdifygenerated(x):
----> 2     return (amax((1,x), axis=0))

<__array_function__ internals> in amax(*args, **kwargs)
....
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
这是一个有效的
numpy
表达式

您的
symarray
案例:

In [72]: a = symarray('a', (3,))

In [73]: a
Out[73]: array([a_0, a_1, a_2], dtype=object)
同样,
np.array((1,a))
生成一个不规则的数组。
max.reduce
将数组与标量进行比较

Add
有效地对
a
数组的元素进行列表理解:

In [74]: g=lambdify([x], Add(x, 1), 'numpy')
In [75]: g(a)
Out[75]: array([a_0 + 1, a_1 + 1, a_2 + 1], dtype=object)
但我们不需要
lambdify
来完成这项工作:

In [83]: a+1
Out[83]: array([a_0 + 1, a_1 + 1, a_2 + 1], dtype=object)
A*A.T
计算类型:

In [89]: a*a[:,None]
Out[89]: 
array([[a_0**2, a_0*a_1, a_0*a_2],
       [a_0*a_1, a_1**2, a_1*a_2],
       [a_0*a_2, a_1*a_2, a_2**2]], dtype=object)

In [90]: _.sum(axis=1)
Out[90]: 
array([a_0**2 + a_0*a_1 + a_0*a_2, a_0*a_1 + a_1**2 + a_1*a_2,
       a_0*a_2 + a_1*a_2 + a_2**2], dtype=object)
您的
Max
可通过
frompyfunc
应用于
a

In [91]: f=np.frompyfunc(lambda x: Max(1,x),1,1)
In [93]: f(a)
Out[93]: array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)
这类似于:

In [94]: np.array([Max(1,x) for x in a])
Out[94]: array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)

速度大致相同,但在使用
广播时更灵活一些。

为什么不使用列表压缩?我认为广播/缩小某些轴时会很复杂,但也许numpy通过使用某种迭代器支持这一点?我认为einsum是最糟糕的,因为我可能需要自己解析下标字符串。我没有使用过
symarray
,但它看起来像对待任何其他对象数据类型数组一样。这意味着一些数学直接起作用,例如
a+1
——无需
lambdify
。但是将“函数”应用于
a
(例如
Max
)的每个元素需要显式迭代。请参阅我的编辑。另请参阅我所了解的
np.max
np.max.reduce
的缩写,就像
np.sum
np.add.reduce
的缩写一样。我可以按照hpaulj的建议,通过使用Pyfunc的
来以元素方式在对象数组上应用
np.max
np.add
。另一方面,我发现很难应用像
reduce
这样的广义函数。
In [91]: f=np.frompyfunc(lambda x: Max(1,x),1,1)
In [93]: f(a)
Out[93]: array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)
In [94]: np.array([Max(1,x) for x in a])
Out[94]: array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)