简体   繁体   中英

Integrating in Python

I've been meaning to integrate in python, but I don't use Scipy, Numpy, or none of any other programs which go can be integrated into python. I'm pretty much a novice when it comes to coding, but I need help integrating. I've copied a small code but I still need to improve it.

def LeftEndSum(startingx, endingx, numberofRectangles) :

    width = (float(endingx) - float(startingx)) / numberofRectangles

    runningSum = 0

    for i in range(numberofRectangles) :
        height = f(startingx + i*width)
        area = height * width
        runningSum += area
    return runningSum

I'm trying to integrate, but i want to get a list of data points that I can then graph into a plot at the end of the integration

I had an idea of defining an interval [a,b] and a delta n=(a change in # boxes between points), where I can do a convergence test in order to stop the loop to get the points. the convergence test would go

if I (n(old value)+delta(n))-I (n(old value))/I (n(old)) < epsilon where epsilon=1x10^-6

in which if the integrated values the code breaks

Let's say you want to integrate y = x*x from 0.0 to 10.0, we know the answer is 333.33333. Here's some code to do that:

def y_equals_x_squared(x):
    y = x*x
    return y

def LeftEndSum(startingx, endingx, numberofRectangles) :
    width = (float(endingx) - float(startingx)) / numberofRectangles
    #print "width = " + str(width)
    runningSum = 0
    i = 1
    while i <= numberofRectangles:
        x = (endingx - startingx)/(numberofRectangles) * (i - 1) + startingx
        height = y_equals_x_squared(x)
        area = height * width
        #print "i, x , height, area = " + str(i) + ", " + str(x) + ", " + str(height) + ", " + str(area)
        runningSum += area
        i += 1
    return runningSum
#-----------------------------------------------------------------------------
startingx = 0.0 
endingx = 10.0 
#
numberofRectangles = 3
old_answer = LeftEndSum(startingx, endingx, numberofRectangles)
#
numberofRectangles = 4
new_answer = LeftEndSum(startingx, endingx, numberofRectangles)
#
delta_answer = abs(new_answer - old_answer)
#
tolerance = 0.0001
max_iterations = 500
iteration_count = 0
iterations = []
answers = []
while delta_answer > tolerance:
    numberofRectangles += 100
    new_answer = LeftEndSum(startingx, endingx, numberofRectangles)
    delta_answer = abs(new_answer - old_answer)
    old_answer = new_answer
    iteration_count += 1
    iterations.append(iteration_count)
    answers.append(new_answer)
    print "iteration_count, new_answer = " + str(iteration_count) + ", " + str(new_answer)
    if(iteration_count > max_iterations):
        print "reached max_iterations, breaking"
        break
#
OutputFile = "Integration_Results.txt"
with open(OutputFile, 'a') as the_file:
    for index in range(len(answers)):
        the_file.write(str(index) + " " + str(answers[index]) + "\n")
#
import matplotlib.pyplot as plt
#
fig, ax = plt.subplots()
ax.plot(iterations, answers, 'r-', label = "Increasing # Rectangles")
title_temp = "Simple Integration"
plt.title(title_temp, fontsize=12, fontweight='bold', color='green')
ax.legend(loc='best', ncol=1, fancybox=True, shadow=True)
plt.xlabel('Number of Iterations')
plt.ylabel('Answer') 
ax.grid(True)
plt.show(block=True)

Notice we plot the answer versus number of iterations at the end and it approaches the real answer very slowly as the number of iterations increase. There are other integration methods that will do better than simple rectangles such as the trapezoidal rule. When you put in a while loop and check for a tolerance always put in a max_iterations check so you don't get stuck in an infinite loop.

You can check your answer here: http://www.integral-calculator.com/ That's how we know the answer is 333.3333

It makes more sense to include f as a parameter in the function. Why hardwire in a fixed formula? Furthermore, the code can be drastically simplified by using the built-in function sum applied to a generator:

def riemannSum(f,a,b,n,sample = 'L'):
    """computes Riemann sum of f over [a,b] using n rectangles and left ('L'), right ('R') or midpoints ('M')"""
    h = (b-a)/float(n)
    if sample.upper() == 'L':
        s = a #s = first sample point
    elif sample.upper() == 'R':
        s = a + h
    else:
        s = a + h/2.0
    return h*sum(f(s+i*h) for i in range(n))

You can define functions explicitly and then integrate them:

>>> def reciprocal(x): return 1/x

>>> riemannSum(reciprocal,1,2,100)
0.6956534304818242

(the exact value is the natural log of 2, which is approximately 0.693147)

Or, you can use anonymous functions (lambda expressions):

>>> riemannSum(lambda x: x**2,0,1,100,'m')
0.333325

Or, you can use functions already in the math module:

>>> riemannSum(math.sin,0,math.pi,10)
1.9835235375094546

None of these methods are very accurate. A more accurate on is Simpson's Rule which is also pretty easy to do in Python:

def simpsonsRule(f,a,b,n):
    if n%2 == 1:
        return "Not applicable"
    else:
        h = (b-a)/float(n)
        s = f(a) + sum((4 if i%2 == 1 else 2)*f(a+i*h) for i in range(1,n)) + f(b)
        return s*h/3.0

For example:

>>> simpsonsRule(math.sin,0,math.pi,10)
2.0001095173150043

This is much more accurate than the Riemann sum with 10 rectangles (the true value is 2).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM