Search code examples
pythonnumpysympyconverters

How can I convert a SymPy expression to NumPy?


How can I convert a sympy expression to numpy code? For example, say I this was the code for the expression:

expression = 2 * x/y + 10 * sympy.exp(x) # Assuming that x and y are predefined from sympy.symbols

I would want to go from expression to this:

np_expression = "np.dot(2, np.dot(x, np.linalg.pinv(y))) + np.dot(10, np.exp(x))"

Note that x and y are matrices, but we can assume the shapes will match

An example with real numbers would go like this:

a = np.array([1,2],[3,4])
b = np.array([5,6],[7,8])

expression = 2 * a/b + 10 # These would be sympy symbols rather than numbers

and the result would be this:

np_expression = "np.dot(2, np.dot(5, np.linalg.pinv(9))) + 10"

Solution

  • In [1]: expr = 2 *x/y + 10 * exp(x)
    In [3]: f = lambdify((x,y), expr)
    In [4]: help(f)
    _lambdifygenerated(x, y)
        Created with lambdify. Signature:
        
        func(x, y)
        
        Expression:
        
        2*x/y + 10*exp(x)
        
        Source code:
        
        def _lambdifygenerated(x, y):
            return 2*x/y + 10*exp(x)
    

    Which for specific inputs, array or otherwise:

    In [5]: f(np.arange(1,5)[:,None], np.arange(1,4))
    Out[5]: 
    array([[ 29.18281828,  28.18281828,  27.84948495],
           [ 77.89056099,  75.89056099,  75.22389432],
           [206.85536923, 203.85536923, 202.85536923],
           [553.98150033, 549.98150033, 548.648167  ]])
    In [6]: f(1,1)
    Out[6]: 29.18281828459045
    In [7]: f(2,3)
    Out[7]: 75.22389432263984
    In [8]: f(np.arange(1,4),np.arange(1,4))
    Out[8]: array([ 29.18281828,  75.89056099, 202.85536923])
    

    Normal array broadcasting rules apply. Note that x/y is element-wise. I'm not sure what lambdify will translate into dot and inv code.

    trying your numpy code:

    In [9]: np.dot(2, np.dot(2,np.linalg.pinv(3)))+10*np.exp(2)
    ---------------------------------------------------------------------------
    LinAlgError                               Traceback (most recent call last)
    <ipython-input-9-6cae91f0e0f8> in <module>
    ----> 1 np.dot(2, np.dot(2,np.linalg.pinv(3)))+10*np.exp(2)
     ....
    
    LinAlgError: 0-dimensional array given. Array must be at least two-dimensional
    

    We have to change the y into a 2d array, e.g. [[3]]:

    In [10]: np.dot(2, np.dot(2,np.linalg.pinv([[3]])))+10*np.exp(2)
    Out[10]: array([[75.22389432]])