首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sympy lambdify最大可操作性

Sympy lambdify最大可操作性
EN

Stack Overflow用户
提问于 2021-06-11 05:39:56
回答 1查看 63关注 0票数 1

sympy lambdify可以用来桥接numpy和Sympy之间的功能。然而,我找不到使用lambdify时存在的缺点。例如,我感兴趣的是将Max与sympy和numpy一起使用:

代码语言:javascript
复制
f = lambdify([x], Max(x, 1), 'numpy')

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

抛出ValueError:

代码语言:javascript
复制
ValueError: The argument '[-1, 0, 1]' is not comparable.

另一方面,使用dunder方法的原油操作很好:

代码语言:javascript
复制
f = lambdify([x], Add(x, 1), 'numpy')

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

输出:

代码语言:javascript
复制
array([0, 1, 2])

最后,我希望lambdify能够与包含渐近符号对象(或sympy.tensor.array.Array)的numpy数组一起工作:

代码语言:javascript
复制
a = symarray('a', (3,))
f = lambdify([x], Max(x, 1), 'numpy')

f(a)

抛出TypeError:

代码语言:javascript
复制
TypeError: cannot determine truth value of Relational

我的预期输出是:

代码语言:javascript
复制
array([Max(1, a_0), Max(1, a_1), Max(1, a_2)], dtype=object)

当然,我可以使用列表理解来实现这一点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-11 10:43:15

help(f)显示:

代码语言:javascript
复制
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))

尝试将其应用于一维数组有几个问题。

代码语言:javascript
复制
In [62]: a
Out[62]: array([-1,  0,  1])

首先,它尝试从(1,x)生成一个数组,导致出现ragged警告。

代码语言:javascript
复制
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()

然后,它从尝试比较a1的错误中获得歧义,结果是一个布尔数组。

lambdify是一个从sympynumpy的相对“愚蠢”的词典翻译器,很容易失败。

Add的代码是

代码语言:javascript
复制
def _lambdifygenerated(x):
    return (x + 1)

它是一个有效的numpy表达式。

您的symarray案例:

代码语言:javascript
复制
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数组的元素进行列表理解:

代码语言:javascript
复制
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来做这件事:

代码语言:javascript
复制
In [83]: a+1
Out[83]: array([a_0 + 1, a_1 + 1, a_2 + 1], dtype=object)

A*A.T类型的计算:

代码语言:javascript
复制
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

代码语言:javascript
复制
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)

这类似于:

代码语言:javascript
复制
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)

使用相同的速度,但在使用broadcasting等时更具灵活性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67928751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档