gpt4 book ai didi

python - SymPy 不能 lambdify Product

转载 作者:太空狗 更新时间:2023-10-30 02:57:13 25 4
gpt4 key购买 nike

我正在使用 SymPy 1.0 和 Python 2.7。我想计算前 100 个整数的总和:

这段代码运行成功

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
s = sy.Sum(x[i], (i, 0, 100))
s_lambda = sy.lambdify(sy.DeferredVector('x'), s, 'numpy')
s_lambda(np.arange(101))

并按预期给出 5050。但是,当我尝试对 Product 而不是 Sum 执行相同操作时:

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
s = sy.Product(x[i], (i, 0, 100))
s_lambda = sy.lambdify(sy.DeferredVector('x'), s, 'numpy')
s_lambda(np.arange(101))

我收到一个NameError: global name 'Product' is not defined我究竟做错了什么?是否有解决方法来获得我想要的东西?

编辑 1:如果我事先不知道 Product 的限制怎么办。比如说

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
n = sy.symbols('n', integer=True, positive=True)
s = sy.Product(x[i], (i, 0, n))
s_lambda = sy.lambdify((sy.DeferredVector('x'), n) s.doit(), 'numpy')
s_lambda(np.arange(101), 5)

编辑 2:我正在尝试找到解决方法。 NameError: global name 'Product' is not defined 错误是因为这个:

lambdastr((sy.DeferredVector('x'), n), p)

这给出了:

lambda x,n: (Product(x[i], (i, 0, n)))

虽然对于 Sum,我们得到了一个有效的 lambda 函数:

lambda x,n: ((builtins.sum(x[i] for i in range(0, n+1))))

此时问题围绕着 Product 函数的定义展开。根据手册,我可以通过 dict 注入(inject)我对函数的定义

def my_prod(a, b):
# my implementation
pass

my_fun = {"Product" : my_prod}
f = sy.lambdify((sy.DeferredVector('x'), n), p, modules=['numpy', my_fun])
f([1,2,3,4,5], 2)

问题是,当我尝试使用 lambdified 函数 f 时,list indices must be integers, not Symbol 出现错误。我想这是由于 i 是一个符号,而它应该是一个整数。我不明白为什么它在尝试调用 my_prod 之前没有传递实际的 integer,因为它是针对 Sum 的情况。

最佳答案

Product的限制是事先已知的

您可以通过调用 .doit()Product 展开为其组成部分来解决此问题:

In [104]: s = sy.Product(x[i], (i, 1, 10)); s
Out[104]: Product(x[i], (i, 1, 10))

In [105]: s.doit()
Out[105]: x[1]*x[2]*x[3]*x[4]*x[5]*x[6]*x[7]*x[8]*x[9]*x[10]

例如,

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
s = sy.Product(x[i], (i, 1, 10))
s_lambda = sy.lambdify(sy.DeferredVector('x'), s.doit(), 'numpy')
print(s_lambda(np.arange(11)))

打印

3628800

但是,如果您将 .doit()sy.Product(x[i], (i, 1, 100)) 一起使用,那么您将得到一个算术溢出,因为 np.arange(101) 的 dtype int32int64(取决于您的操作系统)和产品 100!

In [109]: math.factorial(100)
Out[109]: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

太大,无法存储在 int32int64 数组值中。

In [118]: np.iinfo('int64').max
Out[118]: 9223372036854775807

In [119]: np.iinfo('int64').max < math.factorial(100)
Out[119]: True

因此,

s = sy.Product(x[i], (i, 1, 100))
s_lambda = sy.lambdify(sy.DeferredVector('x'), s.doit(), 'numpy')
print(s_lambda(np.arange(101)))

提出一个

RuntimeWarning: overflow encountered in long_scalars

并错误地打印出 0


如果将输入从 dtype int64 数组更改为 Python int 列表,则产品可以正确计算:

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
s = sy.Product(x[i], (i, 1, 100))
s_lambda = sy.lambdify(sy.DeferredVector('x'), s.doit(), 'numpy')
print(s_lambda(np.arange(101).tolist()))

打印

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Product 的限制事先已知

解决方法(AFAICS)变得更加复杂。如果您使用调试器跟踪代码路径在使用 Sum 时,您会发现 LambdaPrinter._print_Sum被调用以将 Sum(x[i], (i, 0, n)) 转换为表达式 builtins.sum(x[i] for
我在范围 (0, n+1))
.

如果我们将 _print_Product 方法添加到 NumPyPrinter(LambdaPrinter 的子类),然后我们可以让 lambdify 成功地将 Product 转换为 NumPy 可以计算的表达式:

import sympy as sy
from sympy.tensor import IndexedBase, Idx
import numpy as np
import sympy.printing.lambdarepr as SPL

def _print_Product(self, expr):
loops = (
'for {i} in range({a}, {b}+1)'.format(
i=self._print(i),
a=self._print(a),
b=self._print(b))
for i, a, b in expr.limits)
return '(prod([{function} {loops}]))'.format(
function=self._print(expr.function),
loops=' '.join(loops))
SPL.NumPyPrinter._print_Product = _print_Product

x = sy.IndexedBase('x')
i = sy.symbols('i', cls=Idx)
n = sy.symbols('n', integer=True, positive=True)
s = sy.Product(x[i], (i, 1, n))
s_lambda = sy.lambdify((sy.DeferredVector('x'), n), s, 'numpy')
print(s_lambda(np.arange(101), 5))

打印

120

关于python - SymPy 不能 lambdify Product,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37846492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com