今回は,本格的な補完手法について実習を行う.
前回の課題では,2点から1次関数を決定したが,実用的には2次,3次関数など,高次の多項式による補間を行う場合も多い.
一般に,N+1個のデータからは N次式が決定でき,その際に必要な係数はN+1個となる.
独立したN+1個の座標値 (x0, y0), (x1, y1), (x2, y2), ... , (xN, yN) が与えられた場合に,これらの全ての点を通る関数を求める.
xiは,全て異なるとする.
y
= a0
+ a1 x
+ a2 x2
+ ...
+ aN xN
(1)
係数 ai をすべて求めれば関数が決まる.
関数が決まれば,既知である xi 以外の,任意の x に対する y の値が得られる.
この係数は,N+1元の連立1次方程式を解くことにより求めることができる.
3個の既知の点群 (x0, y0), (x1, y1), (x2, y2)を,式(1)に代入することにより,以下の3本の方程式が得られる.
y0
= a0
+ a1 x0
+ a2 x02
y1
= a0
+ a1 x1
+ a2 x12
y2
= a0
+ a1 x2
+ a2 x22
記号が多くあるが,xi, yi (i = 0,1,2) は既知の値なので,ここでは未知の係数a0, a1, a2 を求める問題となる.
未知数が3個で,(独立な)方程式が3個あるので,係数aが一意に決まる.
しかし,補間に用いる点の個数が増えれば増えるほど方程式の数が増えるため,これらをまともに解くのは手間がかかる.
ところが,連立方程式を解くことなく,このような点群から明示的な形で関数値を得る巧みな手法が考案されており,ラグランジュ補間はその1つである.
ラグランジュ補間法では,以下の式を用いて,N+1 個の値 (xi, yi ) を元に,任意の x に対するy = f(x) の値を計算することができる.
展開して書くと,以下の通りとなる.
上の式を見ればわかる通り,既知の値を代入して計算するだけで,任意の x にたいする関数の値が計算できる.
本来であれば,上記の式をソースコードでどのように表すことができるかは,各自で考えて欲しいが,一例として以下にソースコードの参考例を示す.
実習課題作成にあたっては,少なくともこの関数がどのような処理をしているのかを充分に理解した後に使用すること.
関連するC言語キーワード:関数,配列,繰返し,条件分岐,構造体,四則演算
double LagrangeInterp(const Point2D pnt[], const int n, const double x)
/*
* pnt : 点群を表す配列
* n : 点群の個数
* x : 求めたいxの値
* 戻り値 : xに対応する関数値 y
*/
{
int i,j;
/* 計算用変数の初期化 */
double p, s = 0.0;
for (i = 0; i < n; i++) {
p = pnt[i].y; /* 積の計算 */
for (j = 0; j < n; j++) {
if (i != j) {
p *= (x - pnt[j].x) / (pnt[i].x - pnt[j].x);
}
}
s += p;
}
return s;
}
このように,式で見ると複雑に見えるが,プログラムにすると意外とシンプルである.
先週の課題1と同じ5点の点群データを用いて,ラグランジュ補間を行ってみよう.
(n+1 点の点群から n次関数が決定できる.ここでは5点があるので,4次関数を決定する.)
上記の関数および下記を参考に,x の値を -4.0 から 3.0 まで,0.1 ずつ増加させてそれぞれ y を計算し,グラフを書け.
下記を参考に,ソースコードおよびExcelファイルを提出せよ.
struct Point2D
{
double x;
double y;
};
int main()
{
const int N = 5;
Point2D points[N] = {
{-3.5, -2.2},
{-2.2, -0.3},
{-1.0, 1.5},
{ 0.2, 1.9},
{ 2.3, 2.2}
};
/* xの値を変化させながら LagrangeInterp 関数により y の値を順次計算,出力 */
}
以下に計算結果の一例を示す.
図1.補間結果.赤点が既知の制御点,黒丸が補間により求めた点群である.
Excelの機能で,補間により求めた点を線で接続している.
参考までに,以下の手順でグラフを作成すると良い.
詳しくは各自でExcelのオンラインヘルプを参照のこと.
前章のラグランジュ補間では,データによっては意図しない形状になることがある.
(4次関数なので,関数の両端が上昇か下降かのどちらかにしかならない.)
例えば,周期関数や指数関数,正規分布など,必ずしも多項式での近似がふさわしくない場合がある.
そこで,与えられた点群すべてを使って関数を決定するのではなく,局所的な数点のみを使って局所の関数(曲線)を決定し,かつ,その曲線が全体として滑らかに接続されるような補間法が広く利用されている.
その代表例がスプライン補間である.
スプライン補間では,点群全体から単一の多項式を求めるのではなく,「各区間」を次数の比較的低い多項式で近似する.
多項式にはいろいろ考えられるが,ここでは以下の3次式を用いる「3次のスプライン補間」を行う.
(この補間に1次式を用いると,線形補間となる)
スプライン補間では,
ように,係数 pi,qi,ri,si を決める. (一般に,両端の2乗の係数 r0 = rn-1 = 0 とする).
スプライン補間の詳細なアルゴリズムは以下のソースコードおよび各種文献を参照すること.
153R000000?04?2.cpp
このソースコードを使用して,課題1と同様に5点の補間を行い,x の値を -4.0 から 3.0 まで,0.1 ずつ増加させてそれぞれ y を計算し,グラフを書け.
下記を参考に,ソースコードおよびExcelファイルを提出せよ.
また,ラグランジュ補間の結果と比較せよ.
以下に計算結果の一例を示す.
図2.補間結果,図1のラグランジ補間とスプライン補間の比較.赤点が既知の制御点である.
補間法により,通過する位置が大きく異なる区間がある.
以下は提出課題としては必須ではないが,補間法についてより深く勉強したい諸君のために,関連する課題を示しておく.