当极限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)))
prints
3628800
但是,如果您使用.doit()
with sy.Product(x[i], (i, 1, 100))
那么你会得到算术溢出np.arange(101)
有数据类型int32
or int64
(取决于您的操作系统)和产品100!
In [109]: math.factorial(100)
Out[109]: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
太大,无法存储在int32
or int64
数组值。
In [118]: np.iinfo('int64').max
Out[118]: 9223372036854775807
In [119]: np.iinfo('int64').max < math.factorial(100)
Out[119]: True
Thus,
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()))
prints
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
当极限Product
are not预先知道
解决方法
(AFAICS)变得更加复杂。如果您使用调试器来跟踪代码路径
跟随当Sum
用过你会发现LambdaPrinter._print_Sum https://github.com/sympy/sympy/blob/master/sympy/printing/lambdarepr.py#L44被调用来转换Sum(x[i], (i, 0, n))
到表达式builtins.sum(x[i] for
i in range(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))
prints
120