pythonnumerical-integrationtaylor-series

Python integral calculator doesn't print a value


I have made a calculator that approximates any given function as an input. They later I want it to calculate an integral, but after writing:

function    = str(input("The function that must be expanded and integrated: "))

It doesn't print a number but instead a value. This is my code:

from sympy.functions import sin,cos,tan
from sympy.abc import x
from sympy import *
from sympy import series
from math import *
function    = str(input("The function that must be expanded and integrated: "))
x0          = int(input("Point of development: "))
n           = int(input("Amount of expressions: "))

print(series(function, x, x0, n))

N = int(input("Amount of summs (Bigger number is more accurate but takes longer time): "))
a = int(input("Integrate from: "))
b = int(input("Integrate to: "))

# We will use the midpoint method to integrate the function

def integrate(N, a, b):
    def f(x):
        return series(function, x, x0, n)
    value=0
    value=2
    for n in range(1, N+1):
        value += f(a+((n-(1/2))*((b-a)/N)))
    value2 = ((b-a)/N)*value
    return value2

print("...................")
print("Here is your answer: ")
print(integrate(N, a, b))

I think, it's because my input is a string. However I can't choose my input to be an integer, because exp(-x**2) isn't an integer. If that's the case, how can I input any function in my calculater and still get a value?


Solution

  • There a some significant issues in your code:

    After some refactoring and using subs and removeO:

    from sympy.functions import sin,cos,tan
    from sympy.abc import x
    from sympy import series
    
    function    = str(input("The function to be expanded and integrated: "))
    x0          = int(input("Point of development: "))
    n           = 1 + int(input("Degree: "))
    # input 0 -> n=1 -> constant  (1 term, constant)
    # input 1 -> n=2 -> linear    (2 terms, constant + linear)
    # input 2 -> n=3 -> quadratic (3 terms, constant + linear + quadratic)
    # ...
    
    print(series(function, x, x0, n))
    
    N = int(input("Amount of summs (Bigger number is more accurate but takes longer time): "))
    a = int(input("Integrate from: "))
    b = int(input("Integrate to: "))
    
    # We will use the midpoint method to integrate the function
    
    def integrate(function, x0, n, N, a, b): # using the approach with all variables as parameters
        taylor = series(function, x, x0, n) # the same expression for the function, create it once
        taylor = taylor.removeO() # do not use O term (may corrups subs below)
        dx = (b-a)/N # also computed just once
        def f(v):
            return taylor.subs(x,v) # taylor is expression, return value is float evaluated with substituted x by v
        return dx * sum(f(a+(i+1/2)*dx) for i in range(N)) # simple sum function, can be rewriten using a for loop
    
    print("...................")
    print("Here is your answer: ")
    print(integrate(function, x0, n, N, a, b))
    

    Some outputs for x**2 integrated from x=0 to x=2 expanded at x=1. Analytical result is 8/3=2.6666666....

    x**2, 1, 0, 5, 0, 2 => 2.0 # constant approximation
    x**2, 1, 1, 5, 0, 2 => 2.0 # linear approximation
    x**2, 1, 2, 5, 0, 2 => 2.64 # quadratic approximation - exact function
    x**2, 1, 2, 10, 0, 2 => 2.66
    x**2, 1, 2, 100, 0, 2 => 2.6666
    x**2, 1, 2, 1000, 0, 2 => 2.666666
    

    You can use lambdify to "convert a SymPy expression into a function that allows for fast numeric evaluation". For the case of N=1000 the speedup is significant.

    from sympy.utilities.lambdify import lambdify
    def integrate(function, x0, n, N, a, b):
        taylor = series(function, x, x0, n)
        taylor = lambdify(x,taylor.removeO()) # here
        dx = (b-a)/N
        def f(v):
            return taylor(v) # here
        return dx * sum(f(a+(i+1/2)*dx) for i in range(N))