简体   繁体   中英

Calculating a derivative with Math.NET C#

I'm looking for a simple function that will accept an array of double values and return the mathematical derivative.

Math.NET appears to have such a function, but it's asking for the following syntax:

double FirstDerivative(Func<double, double> f, double x)

I'm not sure why I would need to specify a function. I just want a preexisting function that I can pass data to.

Take your data points and create a Math.NET Numerics Cubic Spline object. Then use the .Differentiate() method to get the slope at each point you want.

Example

Try the code below:

static class Program
{
    const int column_width = 12;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        var xvec = new DenseVector(new double[] { 0.0, 1.0, 2.0, 3.0, 4.0 });
        var yvec = new DenseVector(new double[] { 3.0, 2.7, 2.3, 1.6, 0.2 });
        Debug.WriteLine("Input Data Table");
        Debug.WriteLine($"{"x",column_width} {"y",column_width}");
        for(int i = 0; i < xvec.Count; i++)
        {
            Debug.WriteLine($"{xvec[i],column_width:G5} {yvec[i],column_width:G5}");
        }
        Debug.WriteLine(" ");
        var cs = CubicSpline.InterpolateNatural(xvec, yvec);

        var x = new DenseVector(15);
        var y = new DenseVector(x.Count);
        var dydx = new DenseVector(x.Count);
        Debug.WriteLine("Interpoaltion Results Table");
        Debug.WriteLine($"{"x",column_width} {"y",column_width} {"dy/dx",column_width}");
        for(int i = 0; i < x.Count; i++)
        {
            x[i] = (4.0*i)/(x.Count-1);
            y[i] = cs.Interpolate(x[i]);
            dydx[i] = cs.Differentiate(x[i]);
            Debug.WriteLine($"{x[i],column_width:G5} {y[i],column_width:G5} {dydx[i],column_width:G5}");
        }


    }
}

And look at the debug output:

Input Data Table
           x            y
           0            3
           1          2.7
           2          2.3
           3          1.6
           4          0.2

Interpoaltion Results Table
           x            y        dy/dx
           0            3     -0.28214
     0.28571        2.919     -0.28652
     0.57143       2.8354     -0.29964
     0.85714       2.7469      -0.3215
      1.1429       2.6509     -0.35168
      1.4286       2.5454     -0.38754
      1.7143        2.429     -0.42864
           2          2.3       -0.475
      2.2857        2.154     -0.55809
      2.5714       1.9746      -0.7094
      2.8571       1.7422     -0.92894
      3.1429       1.4382      -1.1979
      3.4286       1.0646      -1.4034
      3.7143      0.64404      -1.5267
           4          0.2      -1.5679

情节1

If you aren't opposed to libraries other than Math.Net, you could try AlgLib and their spline1ddiff function

Building the spline is easy, and the Akima spline looks to be nice and smooth through the points. If you wanted a method that takes in a set of data and returns the derivatives, here's an example using the AlgLib math library:

public static void CalculateDerivatives(this Dictionary<double, double> inputPoints, out Dictionary<double, double> firstDerivatives, out Dictionary<double, double> secondDerivatives)
{
        var inputPointsXArray = inputPoints.Keys.ToArray();
        var inputPointsYArray = inputPoints.Values.ToArray();

        spline1dinterpolant akimaSplineToDifferentiate;
        alglib.spline1dbuildakima(inputPointsXArray, inputPointsYArray, out akimaSplineToDifferentiate);

        firstDerivatives = new Dictionary<double, double>();
        secondDerivatives = new Dictionary<double, double>();
        foreach (var pair in inputPoints)
        {
            var xPoint = pair.Key;
            double functionVal, firstDeriv, secondDeriv;
            alglib.spline1ddiff(akimaSplineToDifferentiate, xPoint, out functionVal, out firstDeriv, out secondDeriv);

            firstDerivatives.Add(point, firstDeriv);
            secondDerivatives.Add(point, secondDeriv);
        }
}

Be Warned: Akima Spline has unpredictable behavior outside of the range of your dataset.

Thanks for the responses.

I believe I'll need to iterate through the array, calling the Differentiate function from Math.NET, or perhaps simply write my own (rise over run) calculation.

Here you have derivative extension for function

public static Func<double[], double> Derivative(this Func<double[], double> func, int derivativeIndex)
{
    double step = 0.001;
    return income => 
    {
        double[] increasedIncome = (double[])income.Clone();
        increasedIncome[derivativeIndex] += step;

        double[] decreasedIncome = (double[])income.Clone();
        decreasedIncome[derivativeIndex] -= step;

        return (func(increasedIncome) - func(decreasedIncome)) / (2 * step);
    };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM