Adriaan
Adriaan

Reputation: 715

Integrate a lambda list function in Python

In Python I'm trying

from scipy.integrate import quad
time_start = 0
fun = lambda time: [cos(time), sin(time)]
integral = lambda time: quad(fun, time_start, time)

and would like the program to return integral as a list of which the elements are the element wise integration of fun, so [quad(cos, time_start, time), quad(sin, time_start, time)].

I, however, get TypeError: must be real number, not list.

How do I solve this?

Upvotes: 0

Views: 1258

Answers (1)

Rory Daulton
Rory Daulton

Reputation: 22544

Don't use quad on a function that returns a list of two functions--instead, use it twice on two functions then compose the results into a list. The documentation for scipy.integrate.quad gives the possible signatures for the function to be integrated, and each signature shows that the function must return a double value (called float in Python), not a list.

If you cannot change the definitions of time_start or fun or the parameters or return value of integral, you could use this code.

from math import cos, sin
from scipy.integrate import quad

# Global variables and constants used in function `integral`
time_start = 0
fun = lambda time: [cos(time), sin(time)]

# The desired function
def integral(time):
    """Return a list of two items containing the integrals of the two
    components of the `fun` function from `start_time` to `time`.
    """
    def fun0(time):
        return fun(time)[0]
    def fun1(time):
        return fun(time)[1]

    integral0 = quad(fun0, time_start, time)[0]
    integral1 = quad(fun1, time_start, time)[0]
    return [integral0, integral1]

Then the result of the statement

print(integral(0), integral(pi/2), integral(pi))

is

[0.0, 0.0] [0.9999999999999999, 0.9999999999999999] [3.6775933888827275e-17, 2.0]

which is what you want, within precision error.


By the way, using a lambda expression to create a function then assigning it to a name is considered to be poor programming practice in Python. See here, the fifth bullet point. Use a regular def block instead:

def fun(time):
    return [cos(time), sin(time)]

def integral(time):
    # as shown above

Of course, the use of time_start and fun as global variables, rather than as parameters of integral, is also bad practice, but I kept to the way you used them.

Upvotes: 1

Related Questions