Hello,
I am trying to fit a curve of the form: f(x)=c0+c1*tanh(c2*(x-c3)) to 300 points of 2d data e.g. "x" and "y" coordinates, in my case "x" is index and "y" is some given known numerical value. I need this to be done fast and so after solving this with lsfit I tried to implement using minlm. Since minlm minimizes a function of sum of squares form i.e., F=f1^2+f2^2+...fm^2 I defined my functions to be the errors of the data for a given guess of coefficients i.e. fi=c0+c1*tanh(c2*(i-c3))-data(i) and analytically computed the jacobian matrix (300X4). Unfortunately, minlmresults seems to do nothing and I cant figure out why. Please help me, I have nowhere else to turn. I post my code below and attach my data in a txt file. "esf" is the 300 points of data I mentions:
using System; using System.IO; using System.Text; using System.Linq;
namespace minlm_d_vj_example { class Program { public static int Main(string[] args) { string esf_string = File.ReadAllText(@"...4_1_1_esf.txt"); //Read data from file string[] esf_string_split = esf_string.Split('\n'); double[] esf = new double[esf_string_split.Length-1];
double[] ci = new double[4]; //In this block I initialize the coefficients with a clever guess ci[0] = (esf[0] + esf[^1]) / 2; ci[1] = (esf[0] - esf[^1]) / 2; int d = 0; double dThreshold = ci[0]; for (; (d < esf.Length) && (esf[d] > dThreshold); d++) ; ci[3] = d; int di = 2; double f1 = esf[d - di]; double f2 = esf[d + di]; ci[2] = -(f1 - f2) / (2 * di) / ci[1]; double[] s = new double[] { 1, 1, 1, 1}; double epsx = 0.0000000001; int maxits = 0; alglib.minlmstate state; alglib.minlmcreatevj(esf.Length, ci, out state); alglib.minlmsetcond(state, epsx, maxits); alglib.minlmsetscale(state, s); //alglib.minlmoptguardgradient(state, 0.001); alglib.minlmoptimize(state, function1_fvec, function1_jac, null, null); alglib.minlmreport rep; alglib.minlmresults(state, out ci, out rep); System.Console.WriteLine("{0}", alglib.ap.format(ci, 2)); alglib.optguardreport ogrep; alglib.minlmoptguardresults(state, out ogrep); System.Console.WriteLine("{0}", ogrep.badgradsuspected); System.Console.ReadLine(); return 0;
void function1_fvec(double[] c, double[] fi, object obj) { for (int i = 0; i < esf.Length; i++) { fi[i] = c[0] + c[1] * Math.Tanh(c[2] * (i - c[3])) - esf[i]; } } void function1_jac(double[] c, double[] fi, double[,] jac, object obj) { for (int i = 0; i < esf.Length; i++) { fi[i] = c[0] + c[1] * Math.Tanh(c[2] * (i - c[3])) - esf[i]; double k = i - c[3]; jac[i, 0] = 1; //Here I used some algebra to avoid unnecessary computations. OptGuard gives True but I can't find any problems with the jacobian. jac[i, 1] = Math.Tanh(c[2] * k); jac[i, 2] = c[1] * (1 - jac[i, 1] * jac[i, 1]) * k; jac[i, 3] = jac[i, 2] * (-c[2] / k); } } } } }
Attachments: |
File comment: This files contains the data to be fitted as a function of index.
4_1_1_esf.txt [2.64 KiB]
Downloaded 1660 times
|
|