Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excel Solver : Non linear least squares equivalent in C#

Tags:

c#

math

excel

I am working on a forms application that reports based on observed data. Prior to development of the application, Excel spreadsheets were used along side excel solver to do non-linear least squares regression. Ive been out of University for a while, and it is possible for me to write one eventually, I doubt the client wants to wait for several months while I come up with a suitable replacement for excel's sovler.

So my question is this; Is there a C# equivalent of the Excel solver's non-linear least squares regression function? I have observed data and some initial guesses based on the observed data, so input isnt an issue. Hell, even the name of the equation used would be a good starting point.

Ive taken a look at alglib but im not sure which one would be appropriate.

Thanks in advance.

like image 251
John S Avatar asked Feb 23 '23 01:02

John S


1 Answers

You can do this using the MathDotNet Iridium library.

Here is a c# class example:

using MathNet.Numerics.LinearAlgebra;

namespace StackOverflow.Examples
{
public class PolynomialRegression
{
    readonly Vector _xData;
    readonly Vector _yData;
    readonly Vector _coef;
    readonly int _order;

    public PolynomialRegression(Vector xData, Vector yData, int order)
    {
        if (xData.Length != yData.Length)
        {
            throw new IndexOutOfRangeException();
        }
        _xData = xData;
        _yData = yData;
        _order = order;
        var n = xData.Length;
        var a = new Matrix(n, order + 1);
        for (var i = 0; i < n; i++)
            a.SetRowVector(VandermondeRow(xData[i]), i);

        // Least Squares |y=A(x)*c| ...  tr(A)*y = tr(A)*A*c  ...  inv(tr(A)*A)*tr(A)*y = c
        // http://en.wikipedia.org/wiki/Total_least_squares
        var at = Matrix.Transpose(a);
        var y2 = new Matrix(yData, n);
        _coef = (at * a).Solve(at * y2).GetColumnVector(0);
    }

    Vector VandermondeRow(double x)
    {
        var row = new double[_order + 1];
        for (var i = 0; i <= _order; i++)
            row[i] = Math.Pow(x, i);
        return new Vector(row);
    }

    public double Fit(double x)
    {
        return Vector.ScalarProduct(VandermondeRow(x), _coef);
    }

    public int Order { get { return _order; } }
    public Vector Coefficients { get { return _coef; } }
    public Vector XData { get { return _xData; } }
    public Vector YData { get { return _yData; } }
}
}

And here is an example usage:

 var xVector = new Vector(new double[] { 1, 2, 3, 4, 5 });
 var yVector = new Vector(new double[] { 10, 20, 30, 40, 50 });
 var order = 2;
 _poly = new PolynomialRegression(xVector, yVector, order);
like image 125
Michael Minton Avatar answered Mar 03 '23 04:03

Michael Minton