雑学1473612 views
高校物理160203 views
高校国語788336 views
教育149510 views
ヒストリア290598 views
世界の国564520 views
いろは3010814 views
高校倫理1440106 views
りんご209490 views
中学英語811710 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsRolling DiceCross SectionsMotion PathMechanicsWavesElectromagnetic WavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

台形則・シンプソン則による数値積分|Python

数値積分は、解析的に積分できない関数や、データ点しか与えられていない場合に積分値を近似する手法だ。台形則とシンプソン則は最も基本的なアルゴリズムであり、原理を理解しておくと SciPy などのライブラリを使う際にも役立つ。

台形則の原理

台形則は、関数のグラフを台形で近似して面積を求める。区間 等分したとき、刻み幅は となり、積分は次のように近似される。

def trapezoidal(f, a, b, n):
    """台形則による数値積分"""
    h = (b - a) / n
    result = (f(a) + f(b)) / 2
    for i in range(1, n):
        result += f(a + i * h)
    return result * h

import math

# ∫₀^π sin(x) dx = 2
f = lambda x: math.sin(x)
print(trapezoidal(f, 0, math.pi, 10))   # 1.9835235375094546
print(trapezoidal(f, 0, math.pi, 100))  # 1.9998355038874436
print(trapezoidal(f, 0, math.pi, 1000)) # 1.9999983550656624

を増やすと真の値 に近づく。台形則の誤差は で、二次精度を持つ。

シンプソン則の原理

シンプソン則は、関数を二次多項式(放物線)で近似する。台形則より高精度で、誤差は となる。 は偶数でなければならない。

def simpson(f, a, b, n):
    """シンプソン則による数値積分(n は偶数)"""
    if n % 2 != 0:
        raise ValueError("n must be even")
    h = (b - a) / n
    result = f(a) + f(b)
    for i in range(1, n):
        x = a + i * h
        if i % 2 == 0:
            result += 2 * f(x)
        else:
            result += 4 * f(x)
    return result * h / 3

import math

f = lambda x: math.sin(x)
print(simpson(f, 0, math.pi, 10))   # 2.0000067844418012
print(simpson(f, 0, math.pi, 100))  # 2.000000000067847

でも台形則の より正確だ。シンプソン則の威力がわかる。

台形則

二次精度 。実装が単純。データ点の個数に制約がない。

シンプソン則

四次精度 。同じ でより高精度。 は偶数でなければならない。

精度の比較

具体的な例で精度を比較してみよう。 を計算する。

import math

f = lambda x: math.exp(x)
true_value = math.e - 1

for n in [4, 8, 16, 32]:
    trap = trapezoidal(f, 0, 1, n)
    simp = simpson(f, 0, 1, n)
    print(f'n={n:2d}: 台形則 誤差={abs(trap - true_value):.2e}, '
          f'シンプソン則 誤差={abs(simp - true_value):.2e}')

を 2 倍にすると、台形則の誤差は約 に、シンプソン則の誤差は約 になる。

複合則と適応型積分

上で示した公式は「複合台形則」「複合シンプソン則」と呼ばれ、区間を分割して適用している。さらに高度な手法として、誤差を推定しながら分割を調整する「適応型積分」がある。SciPy の quad はこの適応型積分を使っている。

ロンバーグ積分

ロンバーグ積分は、台形則の結果を外挿して高精度化する手法だ。リチャードソン外挿を繰り返し適用する。

def romberg(f, a, b, max_iter=10, tol=1e-10):
    """ロンバーグ積分"""
    R = [[0] * (max_iter + 1) for _ in range(max_iter + 1)]
    
    # 初期値(台形則、n=1)
    h = b - a
    R[0][0] = h * (f(a) + f(b)) / 2
    
    for i in range(1, max_iter + 1):
        h /= 2
        # 台形則の細分化
        sum_mid = sum(f(a + (2*k - 1) * h) for k in range(1, 2**(i-1) + 1))
        R[i][0] = R[i-1][0] / 2 + h * sum_mid
        
        # リチャードソン外挿
        for j in range(1, i + 1):
            R[i][j] = R[i][j-1] + (R[i][j-1] - R[i-1][j-1]) / (4**j - 1)
        
        if i > 1 and abs(R[i][i] - R[i-1][i-1]) < tol:
            return R[i][i]
    
    return R[max_iter][max_iter]

import math
f = lambda x: math.sin(x)
print(romberg(f, 0, math.pi))  # 2.0000000000000004

ロンバーグ積分は少ない関数評価で高精度な結果を得られる。

ガウス求積法

ガウス求積法は、評価点と重みを最適に選ぶことで、少ない点数で高精度を達成する手法だ。 点のガウス・ルジャンドル求積法は、 次までの多項式を正確に積分できる。

# 2 点ガウス・ルジャンドル求積法(区間 [-1, 1])
def gauss_legendre_2(f):
    """2 点ガウス求積法"""
    x = [-1/math.sqrt(3), 1/math.sqrt(3)]
    w = [1, 1]
    return sum(w[i] * f(x[i]) for i in range(2))

# 区間 [a, b] への変換
def gauss_quad(f, a, b):
    """区間 [a, b] でのガウス求積法"""
    def g(t):
        x = (b - a) / 2 * t + (a + b) / 2
        return f(x) * (b - a) / 2
    return gauss_legendre_2(g)

import math
f = lambda x: x**3  # 3 次多項式は 2 点で正確に積分可能
print(gauss_quad(f, 0, 1))  # 0.25(真の値と一致)

実用上の選択

簡単な関数

シンプソン則で十分。SciPy の quad を使うのが最も簡単。

データ点のみ

台形則(numpy.trapz)や シンプソン則(scipy.integrate.simpson)を使う。

高精度が必要

ロンバーグ積分やガウス求積法。SciPy の rombergfixed_quad が利用可能。

原理を理解した上でライブラリを使うと、適切な手法を選べるようになる。