SymPy doit returns NaN instead of zero

Viewed 59

I'm trying to evaluate a long expression with lots of summations and n choose k's. For some reason, the following expression (which is a part of the long expression) returns NaN.

from sympy import *
w_1_2_3 = symbols('w_1_2_3')
w_1_3 = symbols('w_1_3')
w_2_3 = symbols('w_2_3')
w_1_2 = symbols('w_1_2')
exprr = 7*Sum(binomial(5, w_1_2_3)*Sum(binomial(0, -w_1_2_3 + w_1_3)*binomial(2, w_1_2_3 - w_1_3 - 2)*binomial(13, 11 - w_1_2_3), (w_1_3, w_1_2_3, 5)), (w_1_2_3, 0, 5))/868017280
exprr.doit()
-> NaN

However, if I evaluate each of the terms in the first sum separately, I get 0 for each of them (as should be):

exprr2 = binomial(5, w_1_2_3)*Sum(binomial(0, -w_1_2_3 + w_1_3)*binomial(2, w_1_2_3 - w_1_3 - 2)*binomial(13, 11 - w_1_2_3), (w_1_3, w_1_2_3, 5))

for t in range(0, 6):
    res = exprr2.subs(w_1_2_3, t).doit()
    print(t, res)
-> 0 0
   1 0
   2 0
   3 0
   4 0
   5 0

What is going on here? Why do I get NaN for the overall term?

1 Answers

I rewrote your example a little to wrap my head around it:

from sympy import *

a = symbols("a", integer=True)
b = symbols("b", integer=True)
summand = binomial(5, a) * Sum(
    binomial(0, -a + b)
    * binomial(2, a - b - 2)
    * binomial(13, 11 - a),
    (b, a, 5),
)
inner_sum = summand.doit()#.simplify()   # <--- the important part
summation = (
    7
    * Sum(
        inner_sum,
        (a, 0, 5),
    )
    / 868017280
)
print(summation.doit())


for t in range(0, 6):
    res = summand.subs(a, t).doit()
    print(t, res)

Note how I told sympy to do the inner sum explicitly via .doit(). Let's take a look at that:

>>> pprint(inner_sum)
        ⎛   4        3        2               ⎞ ⎛  0  ⎞ ⎛  2  ⎞ ⎛5⎞ ⎛  13  ⎞
(a - 5)⋅⎝6⋅a  - 102⋅a  + 607⋅a  - 1407⋅a + 756⎠⋅⎜     ⎟⋅⎜     ⎟⋅⎜ ⎟⋅⎜      ⎟
                                                ⎝5 - a⎠ ⎝a - 7⎠ ⎝a⎠ ⎝11 - a⎠
────────────────────────────────────────────────────────────────────────────
                     a⋅(a - 6)⋅(a - 3)⋅(a - 2)⋅(a - 1)

Note how the denominator is chock-full of zeros just at the numbers you're summing this whole thing over! This is in fact what's causing the nans to appear when you sum them.

If, instead, we massage this thing a little, your binomials disappear and merge with the zeros from the denominator, becoming factorials in the denominator, which are safe to work with:

>>> pprint(inner_sum.simplify().factor())
               ⎛   4        3        2               ⎞
-1494484992000⋅⎝6⋅a  - 102⋅a  + 607⋅a  - 1407⋅a + 756⎠
───────────────────────────────────────────────────────
        2
(-a)!⋅a! ⋅(3 - a)!⋅(9 - a)!⋅(11 - a)!⋅(a - 1)!⋅(a + 2)!

And this expression sums properly over the [0, 6] range, as you can verify.

Related