forum.alglib.net http://forum.alglib.net/ |
|
Nonlinear Fit for Gaussian Surface [SOLVED] http://forum.alglib.net/viewtopic.php?f=2&t=3865 |
Page 1 of 1 |
Author: | fatalfitter [ Tue Sep 18, 2018 3:12 pm ] |
Post subject: | Nonlinear Fit for Gaussian Surface [SOLVED] |
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. |
Author: | fatalfitter [ Tue Sep 18, 2018 4:41 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface |
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); } |
Author: | fatalfitter [ Tue Sep 18, 2018 5:03 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface |
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. |
Author: | fatalfitter [ Tue Sep 18, 2018 5:55 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface |
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. |
Author: | fatalfitter [ Tue Sep 18, 2018 6:41 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface |
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); }; |
Author: | fatalfitter [ Tue Sep 18, 2018 8:52 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface [SOLVED] |
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; } }; |
Author: | fatalfitter [ Tue Sep 18, 2018 8:53 pm ] |
Post subject: | Re: Nonlinear Fit for Gaussian Surface [SOLVED] |
Thanks for the help everybody! In Mother Russia, the internet helps you! :-) |
Page 1 of 1 | All times are UTC |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |