jeudi 16 juin 2016

SymPy cannot lambdify Product

I'm using SymPy 1.0 and Python 2.7. I want to compute the sum of first 100 integer numbers:

This code runs succesfully

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))

And gives 5050 as expected. But when I try to do the same with a Product instead of a 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))

I got a NameError: global name 'Product' is not defined What am I doing wrong? Is there a workaround to get what I want?

Edit 1: And what if I don't know in advance the limit of the Product. Let's say something like

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)

Edit 2: I'm trying to find a workaround. NameError: global name 'Product' is not defined error is given because of this:

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

That gives:

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

While for the Sum we got a working lambda function:

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

At this point the problem revolves around the definition of the Product function. According to the manual I can inject via a dict my definition of a function

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)

Problem is, list indices must be integers, not Symbol error is raised when I try to use the lambdified function f. I guess this is due to i that is a symbol while it is supposed to be an integer. I can't understand why it's not passed the actual integer before trying to call my_prod as it is for the Sum case.

Aucun commentaire:

Enregistrer un commentaire