本ポストではこちらの続きです。

ガウス求積とは
ある関数 \(f(\xi)\) を、区間 \([-1,1]\) で積分したいとします。
\[\int_{-1}^{1} f(\xi)\,d\xi\]
これを、いくつかの決まった点 \(\xi_1,\xi_2,\dots,\xi_n\) での関数の値に、対応する重み \(w_1,w_2,\dots,w_n\) を掛けて足し合わせることで近似する方法が ガウス求積 です。
\[\int_{-1}^{1} f(\xi)\,d\xi \approx \sum_{i=1}^{n} w_i\,f(\xi_i)\]
評価点の個数\(\,n\)、位置 \(\xi_i\) そして重み \(w_i\) につきましては、、ガウス・ルジャンドル公式による求積を参照して下さい。
5点ガウス求積の評価点は、原点を中心に左右対称に配置されます。
\[\xi = 0,\quad \pm\frac{1}{3}\sqrt{5-2\sqrt{\tfrac{10}{7}}},\quad \pm\frac{1}{3}\sqrt{5+2\sqrt{\tfrac{10}{7}}}\]
これらの値は、次数5のルジャンドル多項式 \(P_5(\xi)\) の根(=\(P_5(\xi)=0\) となる \(\xi\))として導かれます。
対応する重みは、
\[w = \frac{128}{225},\quad \frac{322\pm13\sqrt{70}}{900}\ (\text{各2個})\]
です。
Rコード
解析的な積分結果が分かっている\(f(\xi)\)のガウス求積を求め、その解析解とガウス求積の結果を比較します。
\(f(\xi)\)は以下の多項式とします。
\[f(\xi) = 5 - 2\xi + 6\xi^2 - \xi^3 + 7\xi^4 - 4\xi^5 + 2\xi^6 - 5\xi^7 + 0\cdot\xi^8 + 3\xi^9\]
# ============================================================
# 5点ガウス求積の検証:解析的な積分結果との比較
# ============================================================
#
# 5点ガウス求積は、2n-1=9次以下の多項式であれば厳密に(誤差なく)積分できる
# という性質がある。これを、実際に解析的な積分結果と比較して確認する。
#
# 検証に使う関数f(ξ)として、単純すぎないよう、0次から9次までの項を
# すべて含む9次多項式を用意する。多項式ですので、各項ξ^kの積分は
# 手計算でも簡単に求まる(kが奇数なら0、偶数なら2/(k+1))ため、
# 解析解を数値的に正確に計算できる。
# ------------------------------------------------------------
# 1. 検証用の9次多項式 f(ξ) の係数を定義する
# ------------------------------------------------------------
# f(ξ) = 5 - 2ξ + 6ξ^2 - ξ^3 + 7ξ^4 - 4ξ^5 + 2ξ^6 - 5ξ^7 + 0ξ^8 + 3ξ^9
coeffs <- c(5, -2, 6, -1, 7, -4, 2, -5, 0, 3) # 0次からの係数(coeffs[k+1]がξ^kの係数)
f <- function(xi) {
total <- 0
for (k in 0:9) {
total <- total + coeffs[k + 1] * xi^k
}
total
}
# ------------------------------------------------------------
# 2. 解析的な積分値を求める
# ------------------------------------------------------------
# ∫[-1,1] ξ^k dξ は、kが奇数なら0、偶数なら 2/(k+1) になる。
# これを各項について計算し、係数を掛けて足し合わせる。
analytic_integral <- 0
for (k in 0:9) {
if (k %% 2 == 0) { # kが偶数の項だけが寄与する
analytic_integral <- analytic_integral + coeffs[k + 1] * (2 / (k + 1))
}
}
cat("解析的な積分値:", analytic_integral, "\n")
# ------------------------------------------------------------
# 3. 5点ガウス求積による近似値を求める
# ------------------------------------------------------------
gauss_pts <- c(
0,
-1 / 3 * sqrt(5 - 2 * sqrt(10 / 7)),
1 / 3 * sqrt(5 - 2 * sqrt(10 / 7)),
-1 / 3 * sqrt(5 + 2 * sqrt(10 / 7)),
1 / 3 * sqrt(5 + 2 * sqrt(10 / 7))
)
gauss_wts <- c(
128 / 225,
(322 + 13 * sqrt(70)) / 900,
(322 + 13 * sqrt(70)) / 900,
(322 - 13 * sqrt(70)) / 900,
(322 - 13 * sqrt(70)) / 900
)
gauss_integral <- sum(gauss_wts * f(gauss_pts)) # 評価点での関数値×重み、を全点分足し合わせる
cat("5点ガウス求積の近似値:", gauss_integral, "\n")
# ------------------------------------------------------------
# 4. 両者の差を確認する
# ------------------------------------------------------------
cat("差:", gauss_integral - analytic_integral, "\n")解析的な積分値: 17.37143
5点ガウス求積の近似値: 17.37143
差: -3.552714e-15 両者の差は浮動小数点の丸め誤差レベル(\(10^{-15}\sim10^{-16}\))に収まっています。
# ------------------------------------------------------------
# 5. 10次の項を加えると、理論通り誤差が生じることを確認する
# ------------------------------------------------------------
# 5点ガウス求積は「9次まで厳密」ですので、10次の項(偶数次)を加えると
# 理論上、有限の誤差が生じるはずである(奇数次の項は対称性により
# 常にゼロに積分されるため、ここでは偶数次である10次の項を追加する)。
coeffs10 <- c(coeffs, 6) # 10次の項(係数6)を追加した、10次多項式の係数
f10 <- function(xi) {
total <- 0
for (k in 0:10) {
total <- total + coeffs10[k + 1] * xi^k
}
total
}
analytic_integral10 <- 0
for (k in 0:10) {
if (k %% 2 == 0) {
analytic_integral10 <- analytic_integral10 + coeffs10[k + 1] * (2 / (k + 1))
}
}
gauss_integral10 <- sum(gauss_wts * f10(gauss_pts))
cat("--- 10次多項式(5点ガウス求積の適用範囲を超える場合) ---\n")
cat("解析的な積分値:", analytic_integral10, "\n")
cat("5点ガウス求積の近似値:", gauss_integral10, "\n")
cat("差:", gauss_integral10 - analytic_integral10, "\n")--- 10次多項式(5点ガウス求積の適用範囲を超える場合) ---
解析的な積分値: 18.46234
5点ガウス求積の近似値: 18.44475
差: -0.01759087 10次の項(偶数次)を追加したことで、5点ガウス求積が厳密に積分できる上限の次数(9次)を超えてしまっているため、誤差が \(10^{-15}\) 台ではなく、\(10^{-2}\) 台というはっきりした大きさになっています。
以上です。
