sympylambda-calculussymbolic-integration

Integration using Lambda function gives an error


I am trying to integrate an exponential function using a Lambda function first time. There are two versions of codes that should work the same, but the one with Lambda function is giving an error saying: enter image description here

The code giving the error is

import numpy as np
import sympy as sym

# Predetermined parameter values 
s, t, T= 0.2 ,0, 0.25
a1, a2= 1.2, 2.3
X1, X2, X3=0.5,-2.0,0.3
# Symbolic variable for integration
u = sym.symbols('u')

# Version 1 giving the above error
fx= lambda X1,X2,X3,a1,a2,T,u: (X1*sym.exp(-a1*(T-u)) + X2*sym.exp(-a2*(T-u))+X3)**2             
Fx=sym.integrate(sym.expand(fx), (u,t,s))
Fx=float(Fx)

On the other hand, I can obtain the output Fx using the following version without the Lambda function.

# Version 2 works fine
def expFun3fsq(X1,X2,X3,a1,a2,T,u):
    # Squared single line exponential function 
    # It returns a symbolic function where u is the only symbol in the function
    fx= (X1*sym.exp(-a1*(T-u))+X2*sym.exp(-a2*(T-u))+X3) **2
    return fx

Fx=sym.integrate(sym.expand(expFun3fsq(X1,X2,X3,a1,a2,T,u)), (u,t,s))
Fx=float(Fx)

What are the causes of the error and how can I fix the problem?


Solution

  • When you write f = lambda x: 1 + x you are telling python that you will provide a single argument to f (like f(1)) and that argument should be referenced as x in the formula. You only need a lambda if you want to be able to change an argument of an expression easily (in my example the f will add 1 to whatever you pass to it).

    When you write f = lambda: 1 + x this would mean that you aren't going to pass any parameters and you just want the function to use the local value of x and add 1.

    >>> f = lambda: x + 1
    >>> g = lambda x: x + 1
    >>> x = 1
    >>> f()
    2
    >>> g(1)
    2
    >>> x = 3
    >>> f()
    4
    >>> g(1)
    2    
    

    It's important to make sure you understand the above outputs. The lambda behave the same way as a defined function -- and you showed that you know how to use the defined function.

    Since you fix all but u and you want to integrate an expression that is a function of u you have to define that expression in some way: you can either pass the parameters to a function/lambda (properly) to get that expression or just write the expression. So change fx= lambda X1,X2,X3,a1,a2,T,u: to fx = and your code will work. OR, pass all the variables to the lambda just like you did in the case of using the function.

    >>> s, t, T= 0.2 ,0, 0.25
    >>> a1, a2= 1.2, 2.3
    >>> X1, X2, X3=0.5,-2.0,0.3
    >>> u = sym.symbols('u')
    

    Here, fx is the expression

    >>> fx=  (X1*sym.exp(-a1*(T-u)) + X2*sym.exp(-a2*(T-u))+X3)**2
    >>> fx.subs(u, 0)  # less convenient than using a lambda as shown last below
    0.207025570818871
    >>> Fx1=sym.integrate(sym.expand(fx), (u,t,s))
    

    Here, fx is a function to which we must pass all parameters

    >>> fx = lambda X1,X2,X3,a1,a2,T,u:(X1*sym.exp(-a1*(T-u)) + X2*sym.exp(-a2*(T-u))+X3)**2             
    >>> Fx2=sym.integrate(sym.expand(fx(X1,X2,X3,a1,a2,T,u)), (u,t,s))
    

    Here, fx is a function of u and we use the local values of the variables

    >>> fx = lambda u:(X1*sym.exp(-a1*(T-u)) + X2*sym.exp(-a2*(T-u))+X3)**2     
    >>> fx(0)
    0.207025570818871   
    >>> fx(u).n(2)
    1.3*(0.33*exp(1.2*u) - exp(2.3*u) + 0.27)**2
    >>> Fx3=sym.integrate(sym.expand(fx(u)), (u,t,s))
    

    All methods give the same answer:

    >>> Fx1,Fx2, Fx3
    (0.106060402899230, 0.106060402899230, 0.106060402899230)