Estefy
Estefy

Reputation: 434

Integrals in Python: Add object not callable

I'm trying to solve an integral of a taylor approximation of a sin(x) function by using the trapezoid rule. The code seems fine but it keep giving me the following error: "TypeError: 'Add' object is not callable"

This is my code:

 import math
 import numpy
 import sympy as sy
 import numpy as np
 from sympy.functions import sin,cos
 import matplotlib.pyplot as plt
 x = sy.Symbol('x')
 f = sin(x)
 # Factorial function
     if n <= 0:
         return 1
     else:
         return n*factorial(n-1)

 taylor_series = sin(x).series(n=None)
 # Do a trapezoid integration
     xedge = numpy.linspace(a,b,N+1)
     integral = 0.0
     n = 0
     while n < N:
         integral += 0.5*(xedge[n+1] - xedge[n])*(f(xedge[n]) + f(xedge[n+1]))
         n += 1
     return integral

 N = 3
 a = 0.0
 b = 1.0

 z = sum([next(taylor_series) for i in range(N)])
 print("Taylor series:",z)
 # Trapezoid rule result 
 N = 2
 while (N <= 2):
     dd = trap(a,b,z,N)
     print ('Trapezoid rule result:', dd)
     N *= 2

The traceback:

Error: Traceback (most recent call last):
  File "Question1.py", line 86, in <module>
    dd = trap(a,b,z,N)
  File "Question1.py", line 67, in trap
    integral += 0.5*(xedge[n+1] - xedge[n])*(f(xedge[n]) + f(xedge[n+1]))
TypeError: 'Add' object is not callable

Upvotes: 4

Views: 17678

Answers (2)

Prune
Prune

Reputation: 77837

Your command f = sin(x) is invalid; the argument is a sympy.Symbol, not a legal argument to the sin function.

For future reference, here's how I broke down the problem to isolate the error. Replacing f with sin worked around the problem ... likely not what you need for your assignment, but useful in debugging.

import math
import numpy
import sympy as sy
import numpy as np
from sympy.functions import sin,cos
import matplotlib.pyplot as plt
x = sy.Symbol('x')
print "sy.Symbol('x') is", x, type(x)
f = sin(x)

# Factorial function that will be used in the Taylor approximation
def factorial(n):
    if n <= 0:
        return 1
    else:
        return n*factorial(n-1)

taylor_series = sin(x).series(n=None)

#def fun(x):
#   return numpy.sin(x)


# Do a trapezoid integration by breaking up the domain [a,b] into N slabs
def trap(a,b,f,N):

    xedge = numpy.linspace(a,b,N+1)

    integral = 0.0

    n = 0
    while n < N:
        x0 = xedge[n]
        x1 = xedge[n+1]
        print x0, x1
        sub1 = x1 - x0
        f0 = math.sin(x0)
        f1 = math.sin(x1)
        sub2 = f0 + f1
        integral = integral + 0.5 * sub1 * sub2
        n += 1

    return integral


N = 3
a = 0.0
b = 1.0
# takes the number of terms desired for your generator
z = sum([next(taylor_series) for i in range(N)])
print("Taylor series:",z)

# Trapezoid rule result and calculaiton of error term
N = 2

while (N <= 2):
    dd = trap(a,b,z,N)
    print ('Trapezoid rule result:', dd)
    N *= 2

Upvotes: 0

fjarri
fjarri

Reputation: 9726

In your case f is a sympy expression. You cannot just evaluate it by calling it; you have to use the evalf() method:

...
integral += 0.5*(xedge[n+1] - xedge[n])*(f.evalf(xedge[n]) + f.evalf(xedge[n+1]))
...

Produces the output:

Taylor series: x**5/120 - x**3/6 + x
Trapezoid rule result: 0.0079345703125*x**5 - 0.158203125*x**3 + 1.0*x

End

Upvotes: 4

Related Questions