Search code examples
c#alglibfunction-fitting

Using nonlinear square fit in C#


I'm trying to find a fit function that has the form:

f(x) = P / (1 + e^((x + m) / s)

Where P is a known constant. I'm fitting this function to a list of measured doubles (between 20-100 elements) and all these values has a corresponding x-value. I'm relatively new to C# and not very in to the maths either so I find it kind of hard to read the documentation available.

I have tried using AlgLib, but don't know where to start or what function to use.

Edit: So to precise what I#m looking for: I'd like to find a C# method where i can pass the functions form, aswell as some coordinates (x- and y-values) and have the method returning the two unknown variables (s and m above).


Solution

  • I use AlgLib daily for exactly this purpose. If you go to the link http://www.alglib.net/docs.php and scroll all the way down, you'll find the documentation with code examples in a number of languages (including C#) that I think will help you immensely: http://www.alglib.net/translator/man/manual.csharp.html

    For your problem, you should consider all the constraints you need, but a simple example of obtaining a nonlinear least-squares fit given your input function and data would look something like this:

    public SomeReturnObject Optimize(SortedDictionary<double, double> dataToFitTo, double p, double initialGuessM, double initialGuessS)
    {
       var x = new double[dataToFitTo.Count,1];
    
       for(int i=0; i < dataToFitTo.Count; i++)
       {
           x[i, 0] = dataToFitTo.Keys.ElementAt(i);
       }
    
       var y = dataToFitTo.Values.ToArray();
       var c = new[] {initialGuessM, initialGuessS};
    
       int info;
       alglib.lsfitstate state;
       alglib.lsfitreport rep;
    
       alglib.lsfitcreatef(x, y, c, 0.0001, out state);
       alglib.lsfitsetcond(state, epsf, 0, 0);
       alglib.lsfitfit(state, MyFunc, null, p);
       alglib.lsfitresults(state, out info, out c, out rep);
    
       /*  When you get here, the c[] array should have the optimized values 
           for m and s, so you'll want to handle accordingly depending on your
           needs.  I'm not sure if you want out parameters for m and s or an 
           object that has m and s as properties. */
    
    }
    
    private void MyFunc(double[] c, double[] x, ref double func, object obj)
    {
        var xPt = x[0];
        var m = c[0];
        var s = c[1];
        var P = (double)obj;
        func = P / (1 + Math.Exp((xPt + m) / s));
    }
    

    Mind you, this is just a quick and dirty example. There is a lot of built-in functionality in Alglib so you'll need to adjust the problem code here to suit your needs with boundary constraints, weighting, step size, variable scaling....etc. It should be clear how to do all that from the examples and documentation in the second link.

    Also note that Alglib is very particular about the method signature of MyFunc, so I would avoid moving around those inputs or adding any more.

    Alternatively, you can write your own Levenberg-Marquardt algorithm if Alglib doesn't satisfy all your needs.