import numpy as np
import plotly.graph_objects as go
try:
import executable_engineering as exe
except ImportError:
%pip install -q executable_engineering
import executable_engineering as exeLeft and Right Riemann Integrals¶
Riemann’'s integral is the simplest of the Newton-Cotes formulae with a polynomial of degree 0, i.e. a constant over each subdivision. Variants exist depending on which point in the subdomain is chosen to evaluate the constant.
If we take the function value at the left of the subdomain , we obtain the left Riemann integral:
Conversely, if we take the function value at the right limit, we obtain the right Riemann integral:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16def left_riemann(f, a, b, n): h = (b - a) / n x_left = np.linspace(a, b - h, n) y_left = f(x_left) integral_approx = np.sum(y_left * h) return { "x_left": x_left, "y_left": y_left, "n": n, "integral_approx": integral_approx, "a": a, "b": b, "h": h, }
exe.display_source(exe.left_riemann)
def f(x):
return x**2
result = exe.left_riemann(f, a=0, b=1, n=8)
fig = exe.visualize_left_riemann(f, result)
fig.show()1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17def right_riemann(f, a, b, n): h = (b - a) / n x_right = np.linspace(a + h, b, n) y_right = f(x_right) integral_approx = np.sum(y_right * h) return { "x_right": x_right, "y_right": y_right, "n": n, "integral_approx": integral_approx, "a": a, "b": b, "h": h, }
exe.display_source(exe.right_riemann)
def f(x):
return x**2
result = exe.right_riemann(f, a=0, b=1, n=8)
fig = exe.visualize_right_riemann(f, result)
fig.show()Error Analysis of One-Sided Riemann Sums¶
To analyze the error, consider integrating the Taylor expansion of the left integral (the right being trivially similar):
The truncation error per element is . Since there are elements, the global composite error scales as:
making left and right Riemann sums first-order accurate.
The Midpoint Riemann Integral¶
Rather than favor the left or right subdomain limit, let’'s take the midpoint . The Midpoint Rule states:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17def midpoint_riemann(f, a, b, n): h = (b - a) / n x_mid = np.linspace(a + h / 2, b - h / 2, n) y_mid = f(x_mid) integral_approx = np.sum(y_mid * h) return { "x_mid": x_mid, "y_mid": y_mid, "n": n, "integral_approx": integral_approx, "a": a, "b": b, "h": h, }
exe.display_source(exe.midpoint_riemann)
def f(x):
return x**2
result = exe.midpoint_riemann(f, a=0, b=1, n=8)
fig = exe.visualize_midpoint_riemann(f, result)
fig.show()Example: Midpoint Approximation of ¶
Approximate using the Midpoint rule across 8 subdivisions:
result = exe.midpoint_riemann(np.sin, a=0, b=np.pi, n=8)
fig = exe.visualize_midpoint_riemann(np.sin, result)
fig.show()Error Analysis: Second-Order Midpoint Accuracy¶
The error can be deduced considering the Taylor series of around the midpoint :
Because the integration limits are symmetric around , the odd term vanishes: .
Integrating the quadratic term yields:
Summing across all subdivisions gives a composite error of , a full order of accuracy higher than one-sided Riemann sums!
Note: If you only have discrete data measured at points , you cannot evaluate without interpolating between samples.