補間 本文へジャンプ

ラグランジュ補間
与えられたN個の点
 (SampleX[I],SampleY[I]),I=1,2,・・・,N
を通るN-1次の多項式をラグランジュ補間(Lagrange interpolation)という。
あらかじめ大域変数として SampleX[1..N],SampleY[1..N]を与えておくと,関数Interpolation(X)は,Xにおけるラグランジュ補間の値を求める。
いろいろなXの値について点(X,Interpolation(X))をプロットすれば,最初に与えたN個の点を通る滑らかな曲線ができる。
 場合によっては,ラグランジュ補間は奇妙に振動することがあるので,心配な場合はスプライン補間を使用する。
ラグランジュ補間
const N=5 (* 例えば *)         (* 標本点の数 *)
var SampleX,,SampleY : array [1..N] of real;   (* 標本点の座標 *)

function Interpolation(X : real) : real;
  var I, J: integer;
     T, Y: real;
begin
  Y := 0;
  for I := 1 to N do begin
   T = SampleY[I];
     for J <> 1 to N do
       if J<>I then T := T * ( X - SampleX[J]) / (SampleX[I] -SampleX[J;
     Y := Y+T
   end:
   Interolation := Y
end]

スプライン補間
3次スプライン補間(非周期関数)
N個の点
  (SampleX[i],SampleY[i]), i = 1,2,・・・,N
が与えられているとする。 但し,SampleX[1]<SampleX[2]<・・・<SampleX[N]
とする。
これらのN点を通り、区分的にXの3次式で表され,N-2個のつなぎ目で2次導関数まで連続であり,両端点I=1,Nで2次導関数が0になるような曲線の方程式を求めるのが,ここでいう3次スプライン補間である。 スプライン(弾性のある薄板)を曲げたような滑らかな曲線が得られるので,こう呼ばれる。
先ず,上述のSampleX[1..N],SampleY[1..N]を与えて,手続きMakeSpline(SampleX,SampleY,Table)を呼び出す。 すると Table[1..N]に各点での2次導関数を6で割った値が求められる。 SampleX[1..N],SampleY[1..N]の値は変わらない。なお,この手続きの呼び出しは,最初に1回だけ行えば良い。
そうしてから,関数Interpolation(X,SampleX,SampleY,Table)を呼び出すと,与えられたx座標の値Xに対応する関数値(y座標の値)が得られる。 このXの値は,SmapleX[1]=<X<=SampleX[N]の範囲になくても良い。
Xの値を少しずつ変えてY-Interpolation(X,SampleX,SampleY,Table)の値を求め,(X,Y)をプロットすれば最初に与えたN個の点を通る滑らかな曲線ができる。
なお,補間によって得られる曲線が周期関数で表されることが分かっている場合には,周期関数編を使うべきである。

const N = 10;   (* 標本点の数 *)
type Vector = array [1..N] of real;

(*  補間のための表を作る *)
procedure MakeSpline( var SampleX, SampleY, Table: Vector);
  const Yxx1 = 0; YxxN = 0; (*  両端点での第2次導関数 *)
  var I: Integer;
    T,U: real;
    H,D: Vector;
begin
  for I := 1 to N - 1 do H[ I ] := SampleX[ I + 1 ] - SampleX[ I ];
  for I := 2 to N - 1 do D[ I ] := 2 * (SampleX[ I + 1 ] - SampleX[ I - 1 ]);
  U := (SampleY[ I + 1 ] - SampleY[ I ] ) / H[ I ];
  for I := 2 to N - 1 do begin
    T := (SampleY[ I + 1 ] - SampleY[ I ] ) / H[ I ] ;
    Table[ I ] := T - U; U := T
  end;
  Table[1] := Yxx1 / 6: Table[ N ] := YxxN / 6;
  Table[2] := Table[2] - H[1]*Table[1];
  Table[N - 1] := Table[N - 1] - H[N - 1] *Table[N];
  for I := 2 to N - 2 do begin
    T := H[ I ] / D[ I ];
    Table[ I + 1 ] := Table[ I + 1 ] - Table[ I ]*T;
    D[ I + 1] := D[ I +1 ] -H[ I ] * T
  end;
  for I := N - 1 downto 2 do
    Table[ I ] := (Table[ I ] - H[ I ]*Table[ I + 1 ])/D[ I ]
end;
(* 実際の補間を行う *)
function Interpolation(X: real; var SampleX, SampleY, Table:Vector) : real;
  var I,J, K:integer;
     T, H:real;
  function F(X: real): real;
  begin
   F := (sqr(X) - 1) * X
  end;

begin { Interpolation }
  I := 1; J := N;
  while I < J do begin
    K : = ( I + J ) div 2;
    if SampleX[ K ] < X then I := k + 1 else J := K
  end;
  if  I > 1 then I := I - 1;
  H := SampleX[ i + 1 ] - SampleX[ I ];
  T := (X - SampleX[ I ] ) / H;
  Interpolation := T * SampleY[ I + 1 ] + ( 1 - T) * SampleY[ I ]
     + sqr( H ) * (F( T ) * Table[ I + 1 ] + F( 1 - T) * Table[ I ])
end;

3次スプライン補間(周期関数

スプライン補間

(a)補間多項式の表現

標本点がx<x<・・・<xと番号づけられているとする。Lagrange補間やHermite補間は,ひとつの多項式を用いた区間[x,x]全域での近似であるが,ここでは,各小区間[xk-1,x]で別々の多項式を用いた近似を考える。 一般に,有限個の分点で区切られた各小区分間上でm次多項式であるような関数を区分的m次多項式,(m-1)階までの導関数が全域で連続な区分的m次多項式をm次スプラインと呼ぶ。 与えられたn個のデータ(x,y)(k=1,・・・,n)に対して,補間条件

S(xk)=yk    (k=1,・・・,n)

を満たすm次スプラインS(x)による補間をm次スプライン補間という。

スプライン補間は,1946年 I,J.Schoenbergによって提案され,1960年代以後いろいろな分野に盛んに応用されるようになった。スプラインの名は,Schoenbergの論文にも言及されているように,滑らかな曲線を引く簡単な製図具に由来する。 この製図具によって描かれる滑らかな曲線が連続な2階導関数をもつ区分的3次多項式になること(工学の分野では連続梁の理論で古くから知られている事実の一般化として,Schoenbergは上記の数学的なスプラインの概念を導入したのである。

応用上最も頻繁に使用される(m=)3次スプライン補間S(x)について述べる。 先ず,S(x)の表式を導く。 x=xkにおけるS(x)の導関数値をdkとしておくと,Hermite 補間の結果から,小区間[xk-1,xk]において

但し、h=x-xk-1である。 この作り方から,S(x)の1階導関数は連続である。 2階導関数の連続性を考える。