旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【C#】 偏微分を計算するクラス

偏微分を計算するクラスを作成します。

public class PartialDerivative
{
    private const double _h = 1e-5;

    /// <summary>
    /// 偏導関数を計算するメソッド
    /// </summary>
    /// <param name="f">関数</param>
    /// <param name="index">偏微分を行うインデックス</param>
    /// <returns>fの偏導関数</returns>
    public static Func<double[], double> Compute(Func<double[], double> f, int index)
    {
        if (index < 0)
        {
            throw new ArgumentOutOfRangeException("index");
        }

        return x =>
        {
            if (index > x.Length - 1)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            var xCopied = new double[x.Length];
            Array.Copy(x, xCopied, x.Length);
            xCopied[index] += _h;
            double f1 = f(xCopied);
            xCopied[index] -= _h;

            xCopied[index] -= _h;
            double f2 = f(xCopied);

            return (f1 - f2)/(2.0*_h);
        };
    }

    /// <summary>
    /// 偏微分係数を計算するメソッド
    /// </summary>
    /// <param name="f">関数</param>
    /// <param name="x">偏微分係数を計算する座標値</param>
    /// <param name="index">偏微分を行うインデックス</param>
    /// <returns>偏微分係数</returns>
    public static double Compute(Func<double[], double> f, double[] x, int index)
    {
        return Compute(f, index)(x);
    }
}

作成したクラスを使って偏微分係数を計算する例です。 ここではf(x_0,x_1)=x_0^2+x_0x_1+x_1^2-2(x_0,x_1)=(1,-1)における偏微分係数を計算しています。

var xAt = new double[] { 1.0, -1.0 };
double v0 = PartialDerivative.Compute((x) => x[0]*x[0] + x[0]*x[1] + x[1]*x[1] - 2.0, xAt, 0);
double v1 = PartialDerivative.Compute((x) => x[0]*x[0] + x[0]*x[1] + x[1]*x[1] - 2.0, xAt, 1);

f(x_0,x_1)x_0偏微分すると2x_0+x_1なので、(x_0,x_1)=(1,-1)では1になると正解です。実際v0は限りなく1に近い値を出力します。 f(x_0,x_1)x_1偏微分するとx_0+2x_1なので、(x_0,x_1)=(1,-1)では-1になると正解です。実際v1は限りなく-1に近い値を出力します。

関連記事
【C#】 微分を計算するクラス - 旅行好きなソフトエンジニアの備忘録
【C#】 勾配ベクトルを計算するクラス - 旅行好きなソフトエンジニアの備忘録