0

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).

Benja S
  • 59
  • 6
  • if P is a known constant, `m` and `s` are variable and you feed your list of doubles into x? – Sebastian L Jun 08 '18 at 12:34
  • have you read this http://www.alglib.net/interpolation/leastsquares.php#header2 ? – Sebastian L Jun 08 '18 at 12:42
  • @SebastianL yes I have, guess the answer is in there somewhere, but I was unable to actually write any code based on that article. – Benja S Jun 08 '18 at 12:45
  • Try the documentation for C# here that has examples for what you are trying to do: http://www.alglib.net/translator/man/manual.csharp.html – Jacob Shanley Jun 08 '18 at 15:49

1 Answers1

3

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.

Jacob Shanley
  • 893
  • 1
  • 8
  • 19
  • 1
    Thanks alot for the help! How would I set the value for P/ how can i make P a fit-parameter (c[2])? – Benja S Jun 11 '18 at 14:02
  • 1
    Np! Should be simple - Alglib will assume every element in c[] are your fit parameters, and the `object obj` item to be constants (you can pass in a list here if you need more constants). So the line with `var c = new[] {initialGuessM, initialGuessS};` would become `var c = new[] {initialGuessM, initialGuessS, initialGuessP};`, the line `alglib.lsfitfit(state, MyFunc, null, p)` would become `alglib.lsfitfit(state, MyFunc, null, null)`, and the line `var P = (double)obj;` would become `var P = c[3];`. That should do it, unless I have misunderstood what you want. – Jacob Shanley Jun 11 '18 at 16:18