4

私はそこに提案されたアルゴリズムの 1 つを使用していましたが、結果は非常に悪いです。

ウィキアルゴリズムを実装しました

Javaで(以下のコード)。x(0)points.get(0)y(0)values[points.get(0)]αalfaおよびμmi。あとはwikiの疑似コードと同じです。

    public void createSpline(double[] values, ArrayList<Integer> points){
    a = new double[points.size()+1];

    for (int i=0; i <points.size();i++)
    {
        a[i] = values[points.get(i)];

    }

    b = new double[points.size()];
    d = new double[points.size()];
    h = new double[points.size()];

    for (int i=0; i<points.size()-1; i++){
        h[i] = points.get(i+1) - points.get(i);
    }

    alfa = new double[points.size()];

    for (int i=1; i <points.size()-1; i++){
        alfa[i] = (double)3 / h[i] * (a[i+1] - a[i]) - (double)3 / h[i-1] *(a[i+1] - a[i]);
    }

    c = new double[points.size()+1];
    l = new double[points.size()+1];
    mi = new double[points.size()+1];
    z = new double[points.size()+1];

    l[0] = 1; mi[0] = z[0] = 0;

    for (int i =1; i<points.size()-1;i++){
        l[i] = 2 * (points.get(i+1) - points.get(i-1)) - h[i-1]*mi[i-1];
        mi[i] = h[i]/l[i];
        z[i] = (alfa[i] - h[i-1]*z[i-1])/l[i];
    }

    l[points.size()] = 1;
    z[points.size()] = c[points.size()] = 0;

    for (int j=points.size()-1; j >0; j--)
    {
        c[j] = z[j] - mi[j]*c[j-1];
        b[j] = (a[j+1]-a[j]) - (h[j] * (c[j+1] + 2*c[j])/(double)3) ;
        d[j] = (c[j+1]-c[j])/((double)3*h[j]);
    }


    for (int i=0; i<points.size()-1;i++){
        for (int j = points.get(i); j<points.get(i+1);j++){
            //                fk[j] = values[points.get(i)];
            functionResult[j] = a[i] + b[i] * (j - points.get(i)) 
                                + c[i] * Math.pow((j - points.get(i)),2)
                                + d[i] * Math.pow((j - points.get(i)),3);
        }
    }

}

私が得る結果は次のとおりです。

ここに画像の説明を入力

しかし、これは次のようになります。

ここに画像の説明を入力


また、http: //www.geos.ed.ac.uk/~yliu23/docs/lect_spline.pdfに従って、別の方法でアルゴリズムを実装しようとしています。

最初に、線形スプラインを行う方法を示しますが、それは非常に簡単です。AおよびB係数を計算する関数を作成します。次に、二次導関数を追加して線形スプラインを拡張します。係数も簡単に計算できますCD

しかし、二次導関数を計算しようとすると問題が発生します。彼らがそれらをどのように計算するかわかりません。

そこで、線形補間のみを実装しました。結果は次のとおりです。

ここに画像の説明を入力

最初のアルゴリズムを修正する方法を知っている人や、2 番目のアルゴリズムで 2 次導関数を計算する方法を説明してくれる人はいますか?

4

4 に答える 4

1

スプライン補間を参照してください。ただし、使用可能な 3x3 の例しか示していません。より多くのサンプル ポイントについては、次のシステムを未知のものとして解決する必要があるx[0..N]値で列挙された N+1とします。y[0..N]k[0..N]

              2*    c[0]    * k[0] + c[0] * k[1] == 3*   d[0];
c[0] * k[0] + 2*(c[0]+c[1]) * k[1] + c[1] * k[2] == 3*(d[0]+d[1]);
c[1] * k[1] + 2*(c[1]+c[2]) * k[2] + c[2] * k[3] == 3*(d[1]+d[2]);
c[2] * k[2] + 2*(c[2]+c[3]) * k[3] + c[3] * k[4] == 3*(d[2]+d[3]);
...
c[N-2]*k[N-2]+2*(c[N-2]+c[N-1])*k[N-1]+c[N-1]*k[N] == 3*(d[N-2]+d[N-1]);
c[N-2]*k[N-1] + 2*c[N-1]        *  k[N]          == 3*   d[N-1];

どこ

c[k]=1/(x[k+1]-x[k]); d[k]=(y[k+1]-y[k])*c[k]*c[k];

これは、Gauß-Seidel 反復法 (これはまさにこのシステムのために考案されたものではありませんか?) またはお気に入りの Krylov 空間ソルバーを使用して解決できます。

于 2013-12-18T08:54:06.137 に答える