Search code examples
pythonnumpyfactorial

Computing factorials efficiently with Python and Numpy


In python / numpy - is there a way to build an expression containing factorials - but since in my scenario, many factorials will be duplicated or reduced, wait until I instruct the run time to compute it.

Let's say F(x) := x!

And I build an expression like (F(6) + F(7)) / F(4) - I can greatly accelerate this, even do it in my head by doing

(F(6) * (1 + 7)) / F(4)
 = 5 * 6 * 8
 = 240

Basically, I'm going to generate such expressions and would like the computer to be smart, not compute all factorials by multiplying to 1, i.e using my example not actually do

(6*5*4*3*2 + 7*6*5*4*3*2) / 4*3*2

I've actually started developing a Factorial class, but I'm new to python and numpy and was wondering if this is a problem that's already solved.


Solution

  • As @Oleg has suggested, you can do this with sympy:

    import numpy as np
    import sympy as sp
    
    # preparation
    n = sp.symbols("n")
    F = sp.factorial
    
    # create the equation
    f = (F(n) + F(n + 1)) / F(n - 2)
    print(f)               # => (factorial(n) + factorial(n + 1))/factorial(n - 2)
    
    # reduce it
    f = f.simplify()
    print(f)               # => n*(n - 1)*(n + 2)
    
    # evaluate it in SymPy
    # Note: very slow!
    print(f.subs(n, 6))    # => 240
    
    # turn it into a numpy function
    # Note: much faster!
    f = sp.lambdify(n, f, "numpy")
    a = np.arange(2, 10)
    print(f(a))            # => [  8  30  72 140 240 378 560 792]