title: Alglib Data fitting with minlmoptimize does not minimize the results. Full c# included
body: <p>I'm having trouble implementing the lm optimizer in the alglib library.  I'm not sure why the parameters are hardly changing at all while still receiving an exit code of 4. I have been unable to determine what i am doing wrong with the documentation for alglib. Below is the full source I am running:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;
  using System.Threading.Tasks;
  
  namespace FBkineticsFitter
  {
      class Program
      {
  
          public static int Main(string[] args)
          {
              /*
               * This code finds the parameters ka, kd, and Bmax from the minimization of the residuals using "V" mode of the Levenberg-Marquardt optimizer (alglib library).
               * This optimizer is used because the equation is non-linear and this particular version of the optimizer does not require the ab inito calculation of partial
               * derivatives, a jacobian matrix, or other parameter-space definitions, so it's implementation is simple.
               * 
               * The equations being solved represent a model of a protein-protein interaction where protein in solution is interacting with immobilized protein on a sensor
               * in a 1:1 stoichiometery. Mass transport limit is not taken into account. The detials of this equation are described in:
               *      R.B.M. Schasfoort and Anna J. Tudos Handbook of Surface Plasmon Resonance, 2008, Chapter 5, ISBN: 978-0-85404-267-8
               *
               *          Y=((ka*Cpro*Bmax)/(ka*Cpro+kd))*(1-exp(-1*X*(ka*Cpro+kd)))  ; this equation describes the association phase
               *          
               *          Y=Req*exp(-1*X*kd) ; this equation describes the dissociation phase
               * 
               * The data are fit globally such that Bmax and Req parameters are linked and kd parameters are linked during simultaneous optimization for the most robust fit
               *          
               *  Y= signal
               *  X= time
               *  ka= association constant
               *  kd= dissociation constant
               *  Bmax= maximum binding capacity at equilibrium
               *  Req=(Cpro/(Cpro+kobs))*Bmax :. in this case Req=Bmax because Cpro=0 during the dissociation step
               *  Cpro= concentration of protein in solution
               *  
               *      additional calculations:
               *          kobs=ka*Cpro
               *          kD=kd/ka
              */
              GetRawDataXY(@"C:\Results.txt");
              double epsg = .0000001;
              double epsf = 0;
              double epsx = 0;
              int maxits = 0;
              alglib.minlmstate state;
              alglib.minlmreport rep;
  
              alglib.minlmcreatev(2, GlobalVariables.param, 0.0001, out state);
              alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
              alglib.minlmoptimize(state, Calc_residuals, null, null);
              alglib.minlmresults(state, out GlobalVariables.param, out rep);
  
              System.Console.WriteLine("{0}", rep.terminationtype); ////1=relative function improvement is no more than EpsF. 2=relative step is no more than EpsX. 4=gradient norm is no more than EpsG. 5=MaxIts steps was taken. 7=stopping conditions are too stringent,further improvement is impossible, we return best X found so far. 8= terminated by user
              System.Console.WriteLine("{0}", alglib.ap.format(GlobalVariables.param, 20));
              System.Console.ReadLine();
              return 0;
          }
  
          public static void Calc_residuals(double[] param, double[] fi, object obj)
          {
              /*calculate the difference of the model and the raw data at each X (I.E. residuals)
               * the sum of the square of the residuals is returned to the optimized function to be minimized*/
              fi[0] = 0;
              fi[1] = 0;
  
              for (int i = 0; i &lt; GlobalVariables.rawXYdata[0].Count();i++ )
              {
                  if (GlobalVariables.rawXYdata[1][i] &lt;= GlobalVariables.breakpoint)
                  {
                      fi[0] += System.Math.Pow((kaEQN(GlobalVariables.rawXYdata[0][i]) - GlobalVariables.rawXYdata[1][i]), 2);
                  }
                  else
                  {
                      fi[1] += System.Math.Pow((kdEQN(GlobalVariables.rawXYdata[0][i]) - GlobalVariables.rawXYdata[1][i]), 2);
                  }
              }
  
          }
  
          public static double kdEQN(double x)
          {
              /*Calculate kd Y value based on the incremented parameters*/
              return GlobalVariables.param[2] * Math.Exp(-1 * x * GlobalVariables.param[1]);
          }
  
          public static double kaEQN(double x)
          {
              /*Calculate ka Y value based on the incremented parameters*/
              return ((GlobalVariables.param[0] * GlobalVariables.Cpro * GlobalVariables.param[2]) / (GlobalVariables.param[0] * GlobalVariables.Cpro + GlobalVariables.param[1])) * (1 - Math.Exp(-1 * x * (GlobalVariables.param[0] * GlobalVariables.Cpro + GlobalVariables.param[1])));
          }
  
          public static void GetRawDataXY(string filename)
          {
              /*Read in Raw data From tab delim txt*/
              string[] elements = { "x", "y" };
              int count = 0;
              GlobalVariables.rawXYdata[0] = new double[1798];
              GlobalVariables.rawXYdata[1] = new double[1798];
  
              using (StreamReader sr = new StreamReader(filename))
              {
                  while (sr.Peek() &gt;= 0)
                  {
                      elements = sr.ReadLine().Split('\t');
                      GlobalVariables.rawXYdata[0][count] = Convert.ToDouble(elements[0]);
                      GlobalVariables.rawXYdata[1][count] = Convert.ToDouble(elements[1]);
                      count++;
                  }
              }
          }
  
          public class GlobalVariables
          {
              public static double[] param = new double[] { 1, .02, 0.13 }; ////ka,kd,Bmax  these are initial guesses for the algorithm
              public static double[][] rawXYdata = new double[2][];
              public static double Cpro = 100E-9;
              public static double kD = 0;
              public static double breakpoint = 180;
          }
      }
  }
  </code></pre>