14

宿題として、ラグランジュ補間多項式を使用して多項式の係数を計算する必要があるため、Javascript でこれを行うことにしました。

ここにラグランジュ多項式(L(x))の定義があります

ここに画像の説明を入力

ラグランジュ基底多項式は次のように定義されます。

ここに画像の説明を入力

特定の X (W(x) 関数) の y 値を計算するのは簡単ですが、多項式 ([a0、a1、...、an] の配列) の係数を計算する必要があります。これを n<=10 にする必要がありますが、任意の n があると便利な場合は、その関数をホーナー関数に入れて多項式を描くことができます。

ここに画像の説明を入力

最初の式で分母を計算する関数があります

function denominator(i, points) {
   var result = 1;
   var x_i = points[i].x;
   for (var j=points.length; j--;) {
      if (i != j) {
        result *= x_i - points[j].x;
      }
   }
   return result;
}

と horner メソッドを使用して y を返す関数 (canvas を使用した描画関数もあります)

function horner(array, x_scale, y_scale) {
   function recur(x, i, array) {
      if (i == 0) {
         return x*array[0];
      } else {
         return array[i] + x*recur(x, --i, array);
      }
   }
   return function(x) {
      return recur(x*x_scale, array.length-1, array)*y_scale;
   };
}

誰もがこれを行うアルゴリズムを知っているか、それらの係数を計算する方法を考えています

4

3 に答える 3

10

まあ、あなたはそれを素朴な方法で行うことができます。多項式をその係数の配列、配列で表す

[a_0,a_1,...,a_n]

に対応しa_0 + a_1*X + ... + a_n*X^nます。私はJavaScriptが苦手なので、擬似コードは次のことを行う必要があります。

interpolation_polynomial(i,points)
    coefficients = [1/denominator(i,points)]
    for k = 0 to points.length-1
        if k == i
            next k
        new_coefficients = [0,0,...,0] // length k+2 if k < i, k+1 if k > i
        if k < i
            m = k
        else
            m = k-1
        for j = m downto 0
            new_coefficients[j+1] += coefficients[j]
            new_coefficients[j] -= points[k]*coefficients[j]
        coefficients = new_coefficients
    return coefficients

定数多項式から始めて、すべてに対して1/((x_1-x_0)* ... *(x_i-x_{i-1})*(x_i-x_{i+1})*...*(x_i-x_n))乗算します。これでLiの係数が得られます。次に、それらにy iを掛けてy値をパラメーターとして渡す場合に初期化することでこれを行うことができます)、最後にすべての係数を加算します。X - x_kk != icoefficientsy_i/denominator(i,points)

polynomial = [0,0,...,0] // points.length entries
for i = 0 to points.length-1
    coefficients = interpolation_polynomial(i,points)
    for k = 0 to points.length-1
        polynomial[k] += y[i]*coefficients[k]

各Liの計算はO( )であるため、合計の計算はO(n³)になります。

更新: jsFiddleで、私が作成した開始インデックスの(現在修正されている)間違いに加えて、多項式の乗算ループでエラーが発生しました。

for (var j= (k < i) ? (k+1) : k; j--;) {
     new_coefficients[j+1] += coefficients[j];
     new_coefficients[j] -= points[k].x*coefficients[j];
}

テスト時にデクリメントするのでj、1つ上から開始する必要があります。

それはまだ正しい補間を生成しませんが、少なくとも以前よりも賢明です。

また、あなたのhorner関数では、

function horner(array, x_scale, y_scale) {
   function recur(x, i, array) {
      if (i == 0) {
         return x*array[0];
      } else {
         return array[i] + x*recur(x, --i, array);
      }
   }
   return function(x) {
      return recur(x*x_scale, array.length-1, array)*y_scale;
   };
}

最高の係数にを2回掛けるとx、次のようになります。

if (i == 0) {
    return array[0];
}

代わりは。しかし、それでも良い結果はありません。

Update2:最終的なタイプミスの修正、次の作業:

function horner(array, x_scale, y_scale) {
   function recur(x, i, array) {
      if (i == 0) {
         return array[0];
      } else {
         return array[i] + x*recur(x, --i, array);
      }
   }
   return function(x) {
      return recur(x*x_scale, array.length-1, array)*y_scale;
   };
}

// initialize array
function zeros(n) {
   var array = new Array(n);
   for (var i=n; i--;) {
     array[i] = 0;
   }
   return array;
}

function denominator(i, points) {
   var result = 1;
   var x_i = points[i].x;
   for (var j=points.length; j--;) {
      if (i != j) {
        result *= x_i - points[j].x;
      }
   }
    console.log(result);
   return result;
}

// calculate coefficients for Li polynomial
function interpolation_polynomial(i, points) {
   var coefficients = zeros(points.length);
    // alert("Denominator " + i + ": " + denominator(i,points));
   coefficients[0] = 1/denominator(i,points);
    console.log(coefficients[0]);
    //new Array(points.length);
   /*for (var s=points.length; s--;) {
      coefficients[s] = 1/denominator(i,points);
   }*/
   var new_coefficients;

   for (var k = 0; k<points.length; k++) {
      if (k == i) {
        continue;
      }
      new_coefficients = zeros(points.length);
       for (var j= (k < i) ? k+1 : k; j--;) {
         new_coefficients[j+1] += coefficients[j];
         new_coefficients[j] -= points[k].x*coefficients[j];
      }   
      coefficients = new_coefficients;
   }
   console.log(coefficients);
   return coefficients;
}

// calculate coefficients of polynomial
function Lagrange(points) {
   var polynomial = zeros(points.length);
   var coefficients;
   for (var i=0; i<points.length; ++i) {
     coefficients = interpolation_polynomial(i, points);
     //console.log(coefficients);
     for (var k=0; k<points.length; ++k) {
       // console.log(points[k].y*coefficients[k]);
        polynomial[k] += points[i].y*coefficients[k];
     }
   }
   return polynomial;
}
于 2012-03-25T15:55:26.537 に答える