-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lambdify function overflows when evaluating functions, generating NaN and inf. #448
Comments
Can you give an example? |
For example, in this case, Lambdify returns inf, while using the .subs() operator gives the correct value. Note that the function is just an example but approximates the type of calculations I'm implementing. In this regard, could you recommend a possible strategy? I've visualized the internal calculations of my functions, and it seems that there is a point where the precision of Lambdify is insufficient to perform them. It appears that Lambdify works with single precision. import symengine as syme
import numpy as np
def abs0(f_x):
f=syme.sympify(f_x)
alpha1=3*(10**6)
a1_aux=(1.0/alpha1)
a2_aux=syme.log(1.0+syme.exp(alpha1*(-f)))
a3_aux=syme.log(1.0+syme.exp(alpha1*(f)))
abs1_val=a1_aux*(a2_aux+a3_aux)
return abs1_val
eq1="2*x+y-5"
sym_eq1=syme.sympify(eq1)
func=abs0(sym_eq1)+sym_eq1
vars=["x","y"]
vals=[1.0,50.02]
sym_vars=syme.symbols(vars)
eval_func=syme.Lambdify(sym_vars, func) ###Lambdify evaluation
result=eval_func(vals)
print("Lambdify result", result)
vals_aux=vals
vals=[]
precision=100
for j_val in range(len(vals_aux)):
vals.append(syme.RealMPFR(vals_aux[j_val], precision))
vars_vals =zip(vars, vals)
val_num = dict(vars_vals)
f_num= float(func.subs(val_num)) ###numeric evaluation
print("subs result", f_num) |
Ah, you are using RealMPFR instead of RealDouble. Then there's bound to be differences. The issue is not the precision, but the number of bits supported in the mantissa. In [46]: syme.exp(3000000*(-5 + 2*x + y))
Out[46]: 4.14259715718165e61261579 which is not representable in single, double nor quad precision. Using RealMPFR will be very slow. I suggest using something like def log1pexp(x):
"""returns log(1 + exp(x)). When x is greater than 32, the value
of `log(1 + exp(x))` is indistinguishable from `x` in double precision.
Therefore, `x` is returned in that case after checking the condition.
This avoids overflow in exp.
"""
return syme.Piecewise((syme.log(1.0 + syme.exp(x)), x<32.0), (x, True))
def abs0(f_x):
f=syme.sympify(f_x)
alpha1=3*(10**6)
a1_aux=(1.0/alpha1)
a2_aux=log1pexp(alpha1*(-f))
a3_aux=log1pexp(alpha1*(f))
abs1_val=a1_aux*(a2_aux+a3_aux)
return abs1_val |
Thank you for your help. Could you tell me if there is a way to limit the number of digits in calculations, regardless of losing precision? Or if there is a way to work efficiently with very large numbers? I am currently developing an application that uses functions with tens of thousands of terms, involving transcendental and exponential functions. During the solving process, I need to evaluate them numerically, which leads to overflow. I appreciate your assistance in advance. |
I'm not sure I understand the question. Could you explain more? Is |
Thank you for your prompt response. I am implementing a solver for nonlinear systems where the solution process involves a large number of numerical evaluations of complex nonlinear functions. The example I started the issue with was just one of the many functions that have caused problems during evaluation. However, the functions I need to evaluate are similar to the one I will provide below:
|
What are the typical values for |
The initial values a1, a2, ... are commonly found between -1.0 and 1.0. However, during the solution search process (Newton-Raphson), the values can vary between -inf and inf. Now, that's just one equation, but the system consists of n-equations and n-variables. |
I'm trying to implement routines to solve systems of nonlinear equations. However, when I numerically evaluate objects created with the Lambdify function, the evaluation returns NaN or inf, depending on the case. However, when I evaluate the function using myfunction.subs(), it evaluates correctly. It is worth noting that in my implementation, Lambdify is essential since I evaluate the same function thousands of times in the process, and using .subs() is extremely slow.
It possible to use a backend that improves numerical precision? Is there any configuration that can force Lambdify to operate with higher precision numbers in its internal calculations?
The text was updated successfully, but these errors were encountered: