<jupyter_start><jupyter_text>Define a function to integrate<jupyter_code>def func(x):
    return np.exp(-2*x)*np.cos(10*x)<jupyter_output><empty_output><jupyter_text>Define it's integral so we know the right answer<jupyter_code>def func_integral(x):
    return (-1/52)*np.exp(-2*x)*(np.cos(10*x)-5*np.sin(10*x))<jupyter_output><empty_output><jupyter_text>Define core of trapezoid method<jupyter_code>def trapezoid_core(f,x,h):
    return 0.5*h*(f(x+h)+f(x))<jupyter_output><empty_output><jupyter_text>Define the wrapper function to perform the trapezoid method<jupyter_code>def trapezoid_method(f,a,b,N):
    #f == function to integrate
    #a == lower limit of integration
    #b == upper limit of integration
    #N == number of intervals to use
    
    #define x values to perform the trapezoid rule
    x = np.linspace(a,b,N)
    h = x[1]-x[0]
    
    #define the value of the integral
    Fint = 0.0
    
    #perform the integral using the trapezoid method
    for i in range(0,len(x)-1,1):
        Fint += trapezoid_core(f,x[i],h)
        
    #return the answer
    return Fint<jupyter_output><empty_output><jupyter_text>Define the core of simpson's method<jupyter_code>def simpsons_core(f,x,h):
    return h*(f(x) + 4*f(x+h) + f(x+2*h))/3<jupyter_output><empty_output><jupyter_text>Define a wrapper for simpson's method<jupyter_code>def simpsons_method(f,a,b,N):
    #f == function to integrate
    #a == lower limit of integration
    #b == upper limit of integration
    #N == number of intervals to use
    
    
    x = np.linspace(a,b,N)
    h = x[1]-x[0]
    
    #define the value of the integral
    Fint = 0.0
    
    #perform the integral using the simpson's method
    for i in range(0,len(x)-2,2):
        Fint += simpsons_core(f,x[i],h)
        
    #apply simpson's rule over the last interval if X is even
    if((N%2)==0):
        Fint += simpsons_core(f,x[-2],0.5*h)
    
    #return the answer
    return Fint<jupyter_output><empty_output><jupyter_text>Define Romberg core<jupyter_code>def romberg_core(f,a,b,i):
    #we need the difference between a and b
    h = b-a
    
    #interval betwen function evaluations at refine level i
    dh = h/2.**(i)
    
    #we need the cofactor
    K = h/2.**(i+1)
    
    #and the function evaluations
    M = 0.0
    for j in range(2**i):
        M += f(a + 0.5*dh +j*dh)
        
    #return the answer
    return K*M<jupyter_output><empty_output><jupyter_text>Define a wrapper function<jupyter_code>def romberg_integration(f,a,b,tol):
    #define an iteration variable
    i=0
    
    #define a max number of iterations
    imax = 1000
    
    #define an error estimate
    delta = 100.0*np.fabs(tol)
    
    #set an array of integral answers
    I = np.zeros(imax,dtype=float)
    
    #fet the zeroth romberg iteration first
    I[0] = 0.5*(b-a)*(f(a) + f(b))
    
    #iterate by 1
    i += 1
    
    #iterate until we reach tolerance
    while(delta>tol):
        
        #find the romberg integration
        I[i] = 0.5*I[i-1] + romberg_core(f,a,b,i)
        
        #compute a fractional error estimate
        delta = np.fabs((I[i]-I[i-1])/I[i])
        
        print(i,":",I[i],I[i-1],delta)
        
        if(delta>tol):
            #iterate
            i += 1
            
            #if we've reached maximim iterations
            if(i>imax):
                print("Max iterations reached")
                raise StopIteration("Stopping iterations after ",i)
                
    print("number of romberg iterations used = ", i)
                
    #return the answer
    return I[i]<jupyter_output><empty_output><jupyter_text>Check the integrals<jupyter_code>print("test")


Answer = func_integral(np.pi) - func_integral(0)
print("Actual Answer: \n", Answer)



print("\nTrapezoidal method")
#print(trapezoid_method(func,0,np.pi,50))
#trap_answer = trapezoid_method(func,0,np.pi,50)

trap_interval = 5 #set the starting inverval for trapezoid method

while(abs(trapezoid_method(func,0,np.pi,trap_interval) - Answer) > 1.0e-6):
    trap_interval += 100
    
    if(abs(trapezoid_method(func,0,np.pi,trap_interval) - Answer) <= 1.0e-6):
        break
    
print("Number of intervals for trapezoid method = ", trap_interval)


print("\nSimpson's method")


#print(simpsons_method(func,0,np.pi,50))

simp_interval = 5 #set the starting interval for simpson's method

while(abs(simpsons_method(func,0,np.pi,simp_interval) - Answer) > 1.0e-6):
    simp_interval += 100
    
    if(abs(simpsons_method(func,0,np.pi,simp_interval) - Answer) <= 1.0e-6):
        break
print("Number of intervals for Simpson's method = ", simp_interval)


print("\nRomberg")
tolerance = 1.0e-6
RI = romberg_integration(func,0,np.pi,tolerance)
print("Romberg: ",RI, "\n(Difference between Romberg and answer)/answer: ",(RI-Answer)/Answer, "\nTolerance: ", tolerance)

#The intervals for trapezoid and simpson's method are set to 100 becuase it was taking a while to run and I was impatient<jupyter_output>test
Actual Answer: 
 0.019194856870544078

Trapezoidal method
Number of intervals for trapezoid method =  1305

Simpson's method
Number of intervals for Simpson's method =  205

Romberg
1 : 0.7868648494891817 1.5737296989783633 1.0
2 : 0.2974797999211515 0.7868648494891817 1.6451034648327187
3 : 0.1338682162766772 0.2974797999211515 1.222183937270994
4 : 0.07429884868669352 0.1338682162766772 0.8017535754985687
5 : 0.04631129469303243 0.07429884868669352 0.6043353825275767
6 : 0.03265075906247467 0.04631129469303243 0.41838340126854
7 : 0.02589762452336669 0.03265075906247467 0.26076270173022315
8 : 0.022539969341304138 0.02589762452336669 0.14896449641170112
9 : 0.02086584679503983 0.022539969341304138 0.08023266741622372
10 : 0.02002996035051737 0.02086584679503983 0.041731807247480004
11 : 0.01961231074592669 0.02002996035051737 0.02129527774678078
12 : 0.019403559342457077 0.01961231074592669 0.010758407763509729
13 : 0.01929920199007937 0.019403559342457077 0.005407340284398829
1[...]
{'fraction_non_alphanumeric': 0.11538461538461539, 'fraction_numerical': 0.1382943143812709, 'mean_word_length': 3.4369436201780417, 'pattern_counts': {'":': 1, '<': 38, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '598452', 'license': 'MIT', 'n_tokens_mistral': 2796, 'n_tokens_neox': 2258, 'n_words': 496, 'path': 'astr-119-hw-5/hw-5.ipynb', 'repo_name': 'QuinnPaddock/UCSC-ASTR-119', 'size': '5980'}