Mauricio
Mauricio

Reputation: 454

SymPy lambdify raises OverflowError: math range error

So, I have this code

from __future__ import division, print_function
import sympy as sp
import numpy as np
from sympy.utilities.lambdify import *

u = np.random.uniform(4, 6, 500)
w, k = sp.symbols('w k')
f = sp.log((k - w) * sp.exp((k - w)**5))
l = sum(f.subs(dict(k=k)) for k in u)

And now I want to use l as a function of w. So I know of some options

z_lambdify = lambdify(w, l)
z_subs = lambda x: l.subs(w, x)

The first function gives an error

>>> z_lambdify(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
OverflowError: math range error
>>> z_lambdify(4)
40.862695278600114

While the second gives answers

>>> z_subs(1)
11469.9130597554
>>> z_subs(4)
40.8626952786003

I would just use this, but it is very slow. Any way to get around this (fixing the lamdify error or a way of using l as a function that is not so slow)?

Version: Python 2.7.6, NumPy 1.8.1, SymPy 0.7.4.1

Upvotes: 3

Views: 338

Answers (1)

Saullo G. P. Castro
Saullo G. P. Castro

Reputation: 58985

Answering your question:

The problem is that:

z_lambdify = lambdify(w, l)

tells the new function to perform the calculations using the built-in math functions, which you can check running with cProfile.run('z_lambdify(1)'); while doing z_subs(1) calls sympy functions. To get the same behavior you should tell lambdify() to use the same module:

 z_lambdify = lambdify(w, l, "sympy")

Important suggestion:

You should simplify your function already at its definition and then useNumPy to perform the calculations much more efficiently. Using some simple algebra your function can be rewritten in a "non-overflowing" format as:

f = lambda k, w: np.log(k - w) + (k - w)**5

such that your desired answer can be achieved doing:

f(k=u, w=1).sum()

when you do f(k=u, w=1) you get an array with the same shape of u, where each value represents the result of the function evaluated with each value of u. You can use this function to simultaneously evaluate f() for different values of k and w, i.e. passing w as another array with the same shape of u instead of using a constant value.

Upvotes: 1

Related Questions