forum.alglib.net

ALGLIB forum
It is currently Sun Dec 22, 2024 9:20 am

All times are UTC


Forum rules


1. This forum can be used for discussion of both ALGLIB-related and general numerical analysis questions
2. This forum is English-only - postings in other languages will be removed.



Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Nonlinear Fit for Gaussian Surface [SOLVED]
PostPosted: Tue Sep 18, 2018 3:12 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
I would like to use free alglib in C# to fit surfaces with various 2-D functions. I can read all of your code and definitions just fine, but it is not clear how one would define things for a multivariate multidimensional problem. (Multivariate in a single dimension is of course described in the documentation.)

The function to fit to data would be a simple Gaussian for example:

G(x,y|p) = p(0)*exp(-((x-p(1))^2 + (y - p(3))^2)/(2*p(4)^2)) + p(5)

- 'x & y' are in principle a grid and G is the surface value at the grid coordinates. 'p' are the parameters to fit. Obviously the Gaussian could be generalized to be elliptical and have independent x,y sigma's, etc. The actual data and their x,y coordinates would of course be supplied. It is no problem to supply the gradient, etc.

So, I can read c# just fine and have used it extensively, but after reading the documentation for a few days and through the forum, I do not understand how to implement things for this type of problem.

Right now I use the Matlab builder for .Net and interface my c++ .net code to the Matlab Component Runtime, and of course Matlab is great for function fitting, but it does cost a license fee even for academic aerospace work, and it takes maybe 5 seconds to initialize the Matlab MCR the first time it is called. And so using alglib in c# would be fast, and free, and awesome. I've already switched my Matlab 1-D spline calls to the alglib spline library and this works great and is much faster! If I can do surface fitting then I can remove dependence on Matlab even more.

Thanks for the help. Perhaps it would be good to add such an example problem to the documentation since this is a fairly common problem.


Last edited by fatalfitter on Tue Sep 18, 2018 8:48 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface
PostPosted: Tue Sep 18, 2018 4:41 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
Going off of this example (http://www.alglib.net/translator/man/manual.csharp.html#example_lsfit_d_nlf), and having read through the forum, it seems that the function variable x[] can be interpreted as multidimensional if x[0] = x-axis and x[1] = yaxis. Thus:

public static void function_Gauss_2_func(double[] p, double[] x, ref double func, object obj)
{
// this callback calculates a 2-d Gaussian surface G(x,y|p) = p(0)*exp(-((x-p(1))^2 + (y - p(2))^2)/(2*p(3)^2)) + p(4)
// where x[0] is a position on X-axis and x[1] is a position on Y-axis and p is adjustable parameter, and G is the value of the surface at the position.
func = p[0] * System.Math.Exp(-((x[0]-p(1))^2 + (x[1] - p(2))^2)/(2*p(3)^2)) + p[4];
}

Okay, so that would work fine for computing single scalar values. But then how would you construct things after that?
In the example below (from the above link) it is not clear why you are using a 2-d array for x when you are fitting only a 1-d array of y values. Obviously c should be a 1-d array if it has multiple parameters.
In general the 2-d Gaussian surface would have independent grid position coordinates and then a 2-d array of values at those coordinates. So how would one alglib.lsfitcreatef for such a problem?

public static int Main(string[] args)
{
double[,] x = new double[,]{{-1},{-0.8},{-0.6},{-0.4},{-0.2},{0},{0.2},{0.4},{0.6},{0.8},{1.0}};
double[] y = new double[]{0.223130,0.382893,0.582748,0.786628,0.941765,1.000000,0.941765,0.786628,0.582748,0.382893,0.223130};
double[] c = new double[]{0.3};
double epsx = 0.000001;
int maxits = 0;
int info;
alglib.lsfitstate state;
alglib.lsfitreport rep;
double diffstep = 0.0001;

alglib.lsfitcreatef(x, y, c, diffstep, out state);
alglib.lsfitsetcond(state, epsx, maxits);
alglib.lsfitfit(state, function_cx_1_func, null, null);
alglib.lsfitresults(state, out info, out c, out rep);
}


Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface
PostPosted: Tue Sep 18, 2018 5:03 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
In

public static int Main(string[] args)
{
double[,] x = new double[,]{{-1},{-0.8},{-0.6},{-0.4},{-0.2},{0},{0.2},{0.4},{0.6},{0.8},{1.0}};
double[] y = new double[]{0.223130,0.382893,0.582748,0.786628,0.941765,1.000000,0.941765,0.786628,0.582748,0.382893,0.223130};
double[] c = new double[]{0.3};
...

is the idea to make x[,] a column array/table of x,y points, and then 'y' (from above) is the corresponding value at the point? As in (using c++ .net code):
Code:
int N = Gaussian_Data->Length();//the total number of data points in the Gaussian surface data to fit
array<double,2>^ x = gcnew array<double,2>(2, N);
array<double>^ y = gcnew array<double>(N);

int i = 0;
for (int xaxis = 0; xaxis = Gaussian_Data->GetLength(0); xaxis++)
    for (int yaxis = 0; yaxis = Gaussian_Data->GetLength(1); yaxis++)
    {
        x[0, i] = (double)xaxis;
        x[1, i] = (double)yaxis;
        y[i] = Gaussian_Data[xaxis, yaxis];
        i++;
    }


So is that the idea for doing multidimensional fitting?

I guess I can just try coding it this way and see what happens.


Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface
PostPosted: Tue Sep 18, 2018 5:55 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
So, this:

Code:
static void function_Gauss_2d(array<double>^ p, array<double>^ x, double &val)
   {
      // this callback calculates a 2-d Gaussian surface G(x,y|p) = p(0)*exp(-((x-p(1))^2 + (y - p(2))^2)/(2*p(3)^2)) + p(4)
      // where x[0] is a position on X-axis and x[1] is a position on Y-axis, p is adjustable parameters, val is the value of the surface at the position.
      val = p[0] * Math::Exp(-((x[0] - p[1])*(x[0] - p[1]) + (x[1] - p[2])*(x[1] - p[2])) / (2 * p[3] * p[3])) + p[4];
   }


Code:
array<double>^ Fit_Gaussian(array<double, 2>^ xdata, array<double, 2>^ ydata, array<double, 2>^ G_xy, array<double>^ p0)
{
   int N = G_xy->Length;
   array<double, 2>^ x = gcnew array<double, 2>(2, N);
   array<double>^ y = gcnew array<double>(N);

   int i = 0;
   for (int xaxis = 0; xaxis = G_xy->GetLength(0); xaxis++)
      for (int yaxis = 0; yaxis = G_xy->GetLength(1); yaxis++)
      {
         x[0, i] = xdata[xaxis, yaxis];
         x[1, i] = ydata[xaxis, yaxis];
         y[i] = G_xy[xaxis, yaxis];
         i++;
      }

   alglib::lsfitstate^ state;
   alglib::lsfitreport^ rep;
   double diffstep = 0.0001;
   double epsx = 0.000001;
   int maxits = 0;
   int info;

   alglib::lsfitcreatef(x, y, p0, diffstep, state);
   alglib::lsfitsetcond(state, epsx, maxits);
   alglib::lsfitfit(state, function_Gauss_2d, nullptr, nullptr);
   alglib::lsfitresults(state, info, p0, rep);
   return p0;
}


However this gives a compile error:

error C3374: can't take address of 'function_Gauss_2d' unless creating delegate instance

All of this code exists inside a ref class.

Some input would be appreciated.


Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface
PostPosted: Tue Sep 18, 2018 6:41 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
This code compiles, but I am not sure if it actually does what it is supposed to yet:

Code:
public ref class JPMath
{
array<double>^ Fit_Gaussian(array<double, 2>^ xdata, array<double, 2>^ ydata, array<double, 2>^ G_xy, array<double>^ p0)
{
   int N = G_xy->Length;
   array<double, 2>^ x = gcnew array<double, 2>(2, N);
   array<double>^ y = gcnew array<double>(N);

   int i = 0;
   for (int xaxis = 0; xaxis = G_xy->GetLength(0); xaxis++)
      for (int yaxis = 0; yaxis = G_xy->GetLength(1); yaxis++)
      {
         x[0, i] = xdata[xaxis, yaxis];
         x[1, i] = ydata[xaxis, yaxis];
         y[i] = G_xy[xaxis, yaxis];
         i++;
      }

   function_Gauss_2d_delegate^ del = gcnew function_Gauss_2d_delegate(function_Gauss_2d);
   alglib::ndimensional_rep^ rep;
   Object^ obj;
   alglib::lsfitstate^ state;
   alglib::lsfitreport^ report;
   double diffstep = 0.0001;
   double epsx = 0.000001;
   int maxits = 0;
   int info;

   alglib::lsfitcreatef(x, y, p0, diffstep, state);
   alglib::lsfitsetcond(state, epsx, maxits);
   alglib::lsfitfit(state, (alglib::ndimensional_pfunc^)del, rep, obj);
   alglib::lsfitresults(state, info, p0, report);
   return p0;
}
static void function_Gauss_2d(array<double>^ p, array<double>^ x, double &val)
{
   // this callback calculates a 2-d Gaussian surface G(x,y|p) = p(0)*exp(-((x-p(1))^2 + (y - p(2))^2)/(2*p(3)^2)) + p(4)
   // where x[0] is a position on X-axis and x[1] is a position on Y-axis, p is adjustable parameters, val is the value of the surface at the position.
   val = p[0] * Math::Exp(-((x[0] - p[1])*(x[0] - p[1]) + (x[1] - p[2])*(x[1] - p[2])) / (2 * p[3] * p[3])) + p[4];
}
delegate void function_Gauss_2d_delegate(array<double>^ p, array<double>^ x, double &val);
};


Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface [SOLVED]
PostPosted: Tue Sep 18, 2018 8:52 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
Here is the solution (note that I am using c++ .net):

Code:
public ref class JPMath
{
   static void function_Gauss_2d(array<double>^ p, array<double>^ x, double %val, Object^ obj)
   {
      val = p[0] * Math::Exp(-((x[0] - p[1])*(x[0] - p[1]) + (x[1] - p[2])*(x[1] - p[2])) / (2 * p[3] * p[3])) + p[4];
   }
   delegate void function_Gauss_2d_delegate(array<double>^ p, array<double>^ x, double %val, Object^ obj);

array<double>^ Fit_Gaussian(array<double, 2>^ xdata, array<double, 2>^ ydata, array<double, 2>^ G_xy, array<double>^ p)
{
   int N = G_xy->Length;
   array<double, 2>^ x = gcnew array<double, 2>(N, 2);
   array<double>^ y = gcnew array<double>(N);

   int i = 0;
   for (int xaxis = 0; xaxis < G_xy->GetLength(0); xaxis++)
      for (int yaxis = 0; yaxis < G_xy->GetLength(1); yaxis++)
      {
         x[i, 0] = xdata[xaxis, yaxis];
         x[i, 1] = ydata[xaxis, yaxis];
         y[i] = G_xy[xaxis, yaxis];
         i++;
      }

   alglib::ndimensional_pfunc^ pf = gcnew alglib::ndimensional_pfunc(function_Gauss_2d);
   alglib::ndimensional_rep^ rep;
   Object^ obj;
   alglib::lsfitstate^ state;
   alglib::lsfitreport^ report;
   double diffstep = 0.0001;
   double epsx = 0.000001;
   int maxits = 0;
   int info;

   alglib::lsfitcreatef(x, y, p, diffstep, state);
   alglib::lsfitsetcond(state, epsx, maxits);
   alglib::lsfitfit(state, pf, rep, obj);
   alglib::lsfitresults(state, info, p, report);
   return p;
}

};


Top
 Profile  
 
 Post subject: Re: Nonlinear Fit for Gaussian Surface [SOLVED]
PostPosted: Tue Sep 18, 2018 8:53 pm 
Offline

Joined: Tue Sep 18, 2018 2:51 pm
Posts: 7
Thanks for the help everybody!

In Mother Russia, the internet helps you! :-)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 40 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group