Week8

Version/Date: Nov 7, 2017

Exercise

PREDICT_400-DL_SEC56 Week8 Discussion

File(s)

Fundamental Theorem of Calculus Example.ipynb

Instructions

The Fundamental Theorem of Calculus requires that the function be continuous on a closed interval before we can integrate. Find or create a function that is not continuous over some interval and explain how we might still be able to integrate the function. Using Python, incorporate a graph of your function that also indicates the area under the curve. Be sure to share your Python code and output.

Description

Fundamental Theorem of Calculus states the following is given in the cell below. In this example I will evaluate the improper integral of a function that is not continuous over the entire interval by breaking it into parts on each side of the undefined point. Evaluate each separately using the equation below and attempt to plot using python.


In [1]:
%%HTML
<a href="https://www.codecogs.com/eqnedit.php?latex=\int_{a}^{b}f(x)dx&space;=&space;F(b)&space;-&space;F(a)&space;=&space;F(x)|\binom{b}{a}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?\int_{a}^{b}f(x)dx&space;=&space;F(b)&space;-&space;F(a)&space;=&space;F(x)|\binom{b}{a}" title="\int_{a}^{b}f(x)dx = F(b) - F(a) = F(x)|\binom{b}{a}" /></a>



In [2]:
import plotly.plotly
from plotly.graph_objs import Scatter, Layout
import numpy as np
import sympy as sp
from sympy.utilities.lambdify import lambdify
x, y, z = sp.symbols('x y z')
sp.init_printing()
print('imports completed')


imports completed

In [3]:
#Note: Code in this cell is reused from my Wk 7 Example
class MyFunctions:
    
    # class init fn
    def __init__(self, low_bound, high_bound, samples):
        self.low_bound = low_bound
        self.high_bound = high_bound
        self.samples = samples
    
    def get_space(self):
        return np.linspace(self.low_bound, self.high_bound, self.samples)
    
    # functions for homework
    def h(self, x):
        expr = 2*x ** 3 + 6*x ** 2 - 12
        return expr
    
    def g(self, x):
        expr = 13*x ** 2 + 76*x
        expr_prime = sp.diff(expr)
        result = expr_prime.evalf(subs={x:100})
        return expr_prime
    
    def eval_sympy_fn(self, expr_str, x_val):
        #sympy_expr = sp.parsing.parse_expr(expr_str)
        sympy_expr = expr_str
        print(sympy_expr)
        result = sympy_expr.evalf(subs={x:x_val})
        return result

# Test MyFunctions
mf = MyFunctions(-10, 10, 20)

# build data array test function
def build_data(fn_name, space):
    tmparray = []
    fn = getattr(mf, fn_name)
    for i in space:
        tmparray.append(float(fn(i)))
    #print(tmparray)
    return np.array(tmparray)

# build sympy data array using lambda
def test_impl_fn(space):
    f2 = implemented_function(sp.Function('f2'), lambda x: 2*x ** 3 + 6*x ** 2 - 12)
    lam_f2 = lambdify(x, f2(x), 'numpy')
    #print(lam_f2(a))
    return lam_f2(space)

def lambdify_fun(fn, space):
    lam = lambdify(x, fn, 'numpy')
    return lam(space)

#new function added to give indefinite integral of original function
def lambdify_indef_integr_fun(fn, space):
    expr_int = sp.integrate(fn)
    lam_p = lambdify(x, expr_int, 'numpy')
    return lam_p(space)

#new function added to give definite integral of original function over limit range
def lambdify_def_integr_fun(fn, ran_a, ran_b, space):
    expr_int = sp.integrate(fn)
    lam_p = lambdify(x, expr_int, 'numpy')
    return lam_p(space)

In [4]:
# The expression
#expression = sp.sympify(2*x / (x-2)) - test different functions
expression = sp.sympify((2*pow(x,3) - 0.5 * x) / (x-8))
print('Original Function: ')
print(expression)


Original Function: 
(2*x**3 - 0.5*x)/(x - 8)

In [5]:
# Instantiate
mf = MyFunctions(0, 10, 100)

# Required for displaying plotly in jupyter notebook
plotly.offline.init_notebook_mode(connected=True)

# Create traces
the_space = mf.get_space()
trace1 = Scatter(x=the_space, y=lambdify_fun(expression, the_space), name='f(x)', line=dict(color='#bc42f4'), fill='tonexty')
#trace2 = Scatter(x=the_space, y=lambdify_fun(testresult, the_space), name='ex integral', line=dict(color='#52FF33'))

# plot it
plotly.offline.iplot({
    "data": [trace1],
    "layout": Layout(title="Original Function")
})



In [6]:
# Sympy has a nice a simple integrate function. However, due to the discontinuity at x = 8, we get
#complete = sp.integrate(expression, x)
complete = sp.integrate(expression, (x, 0, 10))
#print(complete)
print(sp.N(complete))


1327.64641832438 - 3204.42450666159*I

Now, instead take the area under the curve between x = 0 and 8, and then subtract it from the area from 8 to 10 using definite integrals for the same function. This shows the value is the same taken on the two separate intervals and combined. Taking values arbitrarily close to the point of discontinuity, we can estimate the value using FTC.


In [7]:
# This is an alternative way to estimate the area under the curve
soln1 = sp.integrate(expression, (x, 0, 7.9999))
#print(sp.N(soln1))
soln2 = sp.integrate(expression, (x, 8.0001, 10))
#print(sp.N(soln2))
totalsoln = soln2 - soln1
print(totalsoln)


20612.1348550407

In [8]:
# Plot separately
# Instantiate
mf1 = MyFunctions(0, 7.9999, 100)
mf2 = MyFunctions(8.0001, 10, 100)

# Create traces
space1 = mf1.get_space()
space2 = mf2.get_space()
trace1 = Scatter(x=space1, y=lambdify_fun(expression, space1), name='left side - negative', line=dict(color='#33F9FF'), fill='tozeroy')
trace2 = Scatter(x=space2, y=lambdify_fun(expression, space2), name='right side - positive', line=dict(color='#33A8FF'), fill='tozeroy')

# plot it
plotly.offline.iplot({
    "data": [trace1, trace2],
    "layout": Layout(title="Split Plot")
})



In [1]:
import sympy as sp
x, y, z = sp.symbols('x y z')
sp.init_printing()
exp = 8 / (4*x + 5)**3
ans = sp.integrate(exp, x)
print(ans)


-8/(128*x**2 + 320*x + 200)

In [ ]: