<jupyter_start><jupyter_text>Consider the diagram on the right, which shows an illustration of Monte Carlo integration. Given any integrable function (the line is one example) we can compute the area between f(x) and f=0 over the range x=[a,b] by filling the space with randomly drawn points over the domain x=[a,b], y=[c,d], computing the fraction of points below f(x), and then multiplying that fraction by (d-c)*(b-a).Final Project 4 Requirements1) Write a scheme to compute a Monte Carlo integral for any specified function. The integration scheme should take a defined function as a parameter, along with the domain limits x=[a,b]. The domain y=[c,d] should be determined for the function considered automatically.2) Engineer a method for specifying a tolerance for the Monte Carlo integration. Note this tolerance can refer to the absolute difference between two numerical estimates of the integral.3) Have the Monte Carlo integrator produce a plot of f(x) over the domain x=[a,b] and y=[c,d], and overplot the samples (as small colored dots, with points above and below the line f(x) as distinctive colors. Have the plot contain the answer to the integral as “F(a,b) = XXX” where XXX is the floating point answer. Make a legend for f(x), and the dots above and below f(x).4) Test your model on cos(x) over the domain x = [0,1.75]5) Extra Credit:Produce an animation of the Monte Carlo integration where each from adds more points to the panel discussed in 3). Add another panel that shows the estimated error of the integral as a function of the number of points.<jupyter_code>%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
def function(x):
    return np.cos(x)
def function2(x):
    return 2*x-4
def function3(x):
    return x**2
def function4(x):
    return np.tan(x)<jupyter_output><empty_output><jupyter_text>~Ethan: Boundary findertakes in a function and returns the minima and maxima in the y.<jupyter_code>def boundaryFinder(func):
    y=func
    ymin=y.min()
    ymax=y.max()
    for i in range(len(y)):
        if(ymin>y[i]):
            ymin=y[i]
        elif(ymax<y[i]):
            ymax=y[i]
    if(ymin==y.min() and ymax==y.max()):
        return ymin,ymax<jupyter_output><empty_output><jupyter_text>~Ethan: Generate Sampletakes in the x and y bounds and the number of samples to generate randomly sampled points.<jupyter_code>def generateSample(a,b,n,ymin,ymax):
    x=np.random.uniform(a,b,n)
    y=np.random.uniform(ymin,ymax,n)
    return x,y<jupyter_output><empty_output><jupyter_text>~Ethan: PlacePointsdetermines the position of the points on the plot in reference to the graph of the function. here the parameter func is one of the above defined functions, and that function takes the 'x' output of generateSample() as a parameter<jupyter_code>def placePoints(y,func):
    ir = np.where((y)<func)[0]
    ur = np.where((y)>func)[0]
    return ir,ur<jupyter_output><empty_output><jupyter_text>~Ethan: Compute Integralcomputes the value of the approximate integral based on the scheme provided by the assignment: compute the fraction of points below f(x), and then multiply that fraction by (d-c)*(b-a).<jupyter_code>def computeIntegral(a,b,ymin,ymax,n,ir):
    mf = (b-a)*(ymax-ymin) #mf is the factor that multiplies the
    #fraction of points under the curve.
    ans=mf*len(ir)/float(n)
    return ans<jupyter_output><empty_output><jupyter_text>~Ethan: PlotterTakes in the y boundaries as well as the x and y arrays output by generateSample() and the ir and ur arrays output by placePoints(). xf is an array generated using np.linspace(a,b,n) where is the lower bound in x, b the upper bound in x, and n is the number of samples. xf is used to set the x bounds, ymin and ymax set the y bounds<jupyter_code>def plotter(xf,x,y,ymin,ymax,func,ir,ur):
    fig = plt.figure(figsize=(7,7))
    plt.xlim(xf[0],xf[-1])
    plt.ylim([ymin,ymax])
    plt.plot(x[ir],y[ir],'.',color='blue')
    plt.plot(x[ur],y[ur],'.',color="0.75")
    yc = func
    plt.plot(xf,yc,color='green')

    plt.xlabel('x')
    plt.ylabel('y')
    plt.show()<jupyter_output><empty_output><jupyter_text>~Ethan: Monte CarloWrapper function for the defined processes<jupyter_code>def monteCarlo(a,b,n,fn):
    xf=np.linspace(a,b,n)
    if(fn==1):
        ymin,ymax=boundaryFinder(function(xf))
        x,y=generateSample(a,b,n,ymin,ymax)
        ir,ur=placePoints(y,function(x))
        plotter(xf,x,y,ymin,ymax,function(xf),ir,ur)
    elif(fn==2):
        ymin,ymax=boundaryFinder(function2(xf))
        x,y=generateSample(a,b,n,ymin,ymax)
        ir,ur=placePoints(y,function2(x))
        plotter(xf,x,y,ymin,ymax,function2(xf),ir,ur)
    elif(fn==3):
        ymin,ymax=boundaryFinder(function3(xf))
        x,y=generateSample(a,b,n,ymin,ymax)
        ir,ur=placePoints(y,function3(x))
        plotter(xf,x,y,ymin,ymax,function3(xf),ir,ur)
    elif(fn==4):
        ymin,ymax=boundaryFinder(function4(xf))
        x,y=generateSample(a,b,n,ymin,ymax)
        ir,ur=placePoints(y,function4(x))
        plotter(xf,x,y,ymin,ymax,function4(xf),ir,ur)
    return computeIntegral(a,b,ymin,ymax,n,ir)
def monteCarloWrap(a,b,n,fn,tol,ex,imax):
    i=0
    ans=monteCarlo(a,b,n,fn)
    N=n
    while(abs(ex-ans)>tol and i<imax):
        print(ans)
        i+=1
        N*=2
        ans=monteCarlo(a,b,N,fn)
    error=abs(ex-ans)
    if(imax==i):
        print("The maximum number of iterations has been reached")
    return ans,error<jupyter_output><empty_output><jupyter_text>~Ethan: Test casesJust testing the above implemented functions to ensure they work<jupyter_code>a1=0; b1=1.75; n=10000; tol=.05; ex1=0.983986; imax=10
monteCarloWrap(a1,b1,n,1,tol,ex1,imax)
#ymin1,ymax1=boundaryFinder(function(np.linspace(a1,b1,n)))
#print(ymin1,ymax1)
#xf=np.linspace(a1,b1,n)
#x1,y1 = generateSample(a1,b1,n,ymin1,ymax1)
#ir1,ur1 = placePoints(y1,function(x1))
#plotter(xf,x1,y1,ymin1,ymax1,function(xf),ir1,ur1)
#print(computeIntegral(a1,b1,ymin1,ymax1,n,ir1))

#a2=a1; b2=5
#xf2=np.linspace(a2,b2,n)
#ymin2,ymax2=boundaryFinder(function2(xf2))
#x2,y2 = generateSample(a2,b2,n,ymin2,ymax2)
#ir2,ur2 = placePoints(y2,function2(x2))
#plotter(xf2,x2,y2,ymin2,ymax2,function2(xf2),ir2,ur2)
#print(computeIntegral(a2,b2,ymin2,ymax2,n,ir2))

#a3=-5; b3=5
#xf3=np.linspace(a3,b3,n)
#ymin3,ymax3 = boundaryFinder(function3(xf3))
#x3,y3 = generateSample(a3,b3,n,ymin3,ymax3)
#ir3,ur3 = placePoints(y3,function3(x3))
#plotter(xf3,x3,y3,ymin3,ymax3,function3(xf3),ir3,ur3)
#print(computeIntegral(a3,b3,ymin3,ymax3,n,ir3))

#a4=.5; b4=2
#xf4=np.linspace(a4,b4,n)
#ymin4,ymax4 = boundaryFinder(function4(xf4))
#x4,y4 = generateSample(a4,b4,n,ymin4,ymax4)
#ir4,ur4 = placePoints(y4,function4(x4))
#plotter(xf4,x4,y4,ymin4,ymax4,function4(xf4),ir4,ur4)
#print(computeIntegral(a4,b4,ymin4,ymax4,n,ir4))
ymin,ymax=boundaryFinder(function(np.linspace(0,1.75,10000)))
x=np.random.uniform(0,1.75,10000)
y=np.random.uniform(ymin,ymax,10000)
ir = np.where((y)<function(x))[0]
ur = np.where((y)>=function(x))[0]
fig = plt.figure(figsize=(7,7))
plt.xlim([0,1.75])
plt.ylim([ymin,ymax])
plt.plot(x[ir],y[ir],'.',color='blue')
plt.plot(x[ur],y[ur],'.',color="0.75")
theta=np.linspace(0,2*np.pi,1000)
xc = np.linspace(0,1.75,10000)
yc = np.cos(xc)
plt.plot(xc,yc,color='green')

plt.xlabel('x')
plt.ylabel('y')
plt.show()
print(np.sin(1.75))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14448979591836736, 'fraction_numerical': 0.035238095238095235, 'mean_word_length': 5.392173913043478, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, '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': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '82342', 'license': 'MIT', 'n_tokens_mistral': 2935, 'n_tokens_neox': 2871, 'n_words': 642, 'path': 'boundary_finder_and_try_random.ipynb', 'repo_name': 'bengrenier/Group_N', 'size': '7350'}