I've found something, that I consider to be a root of the problem.
I tried to calculate f for the approximate x (given in the message above) and have got an interesting result:
f(x) == 42.52 ; 0.038 ; almost 0 ; almost 0;
hey! f(x)[0] is not 0! but the solution is almost exact! it's not surprising that minlm* jumps over the correct solution and looks for it in wrong direction.
That led me to the idea of scaling f(x) too. The problem is (the new one), I don't know how to do it.
First of all I tried to divide f[i] by left part of corresponding equation, but it didn't help.
The source code now looks like
Code:
using System;
using System.Text;
namespace Project1
{
class Program
{
//init
static double d = 3;
static double a = 1000;
static double F_0 = 0.035;
static double F_H = 549;
static double F_d = 9;
static double c_yd = 1.3;
static double c_xd = 0.5;
static double F_sh = 5;
static double c_ysh = 0.6;
static double c_xsh = 0.9;
static double M_g = 1500;
static double M_z = 400;
static double hamma_M = 74000;
static double V = 2.2;
//
static double ro = 1030;
static double v = 1.3e-6;
static double g = 9.80665;
static double d_a = d / a;
static double F_f = F_H * a / d;
static double G_g = M_g * g * (hamma_M - ro * g) / hamma_M;
static double G_z = M_z * g * (hamma_M - ro * g) / hamma_M;
static double R_yd = c_yd * ro * V * V * F_d / 2;
static double R_xd = c_xd * ro * V * V * F_d / 2;
static double Q = c_ysh * ro * V * V * F_sh / 2;
static double R_xsh = c_xsh * ro * V * V * F_sh / 2;
//
static void f(double[] x, double[] fi, object obj)
{
double L = x[0];// *x[0];
double H = x[1];// * x[1];
double A = x[2];// * x[2];
double R_x = x[3];// * x[3];
fi[0] = (R_x - (0.04 * (A + 110.0 * Math.Exp(-6.74 * F_0) * (Math.PI * H * L / (4.0 * F_f) - 0.02)) - 0.09) * (ro * V * V * F_H / 2.0));
fi[1] = (Math.PI * H * L / (4.0 * F_f) - 1.0 + Math.Exp(0.0008 * (2.0 * R_yd + Q + 2.0 * G_g + G_z) / ((R_x + R_xsh) * F_0)));
fi[2] = A + 110.0 * Math.Exp(-6.74 * F_0) * (Math.PI * H * L / (4.0 * F_f) - 0.02) - A * (1.0 - Math.Exp(-4.5 * (2.0 * R_yd + Q + 2.0 * G_g + G_z) / (R_x + R_xsh)));
fi[3] = H / L - Math.Exp(1.0 - 2.0 * R_yd / (Q + 2.0 * G_g + G_z));
return;
//scaling
fi[0] /= R_x;
fi[1] /= H * L * Math.PI / (4 * F_f);
fi[2] /= A * (1.0 - Math.Exp(-4.5 * (2.0 * R_yd + Q + 2.0 * G_g + G_z) / (R_x + R_xsh)));
fi[3] /= H / L;
}
static double epsg = 1e-5;
static double epsf = 0;
static double epsx = 0;
static int maxits = 0;
//
static void minlm(ref double[] x)
{
alglib.minlmstate state;
alglib.minlmreport rep;
alglib.minlmcreatev(4, x, 0.0001, out state);
alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
alglib.minlmsetscale(state, new double[] { 10, 10, 10, 10000 });
alglib.minlmoptimize(state, f, null, null);
alglib.minlmresults(state, out x, out rep);
System.Console.WriteLine("{0}", rep.terminationtype); // EXPECTED: 4
}
static void Main()
{
double[] x = { 50, 50, 6, 10000 };
double[] fi = { 0, 0, 0, 0 };
minlm(ref x);
f(x, fi, null);
System.Console.WriteLine(" X : {0}, {1}, {2}, {3}", x[0], x[1], x[2], x[3]);
System.Console.WriteLine(" f(X) : {0}, {1}, {2}, {3}", fi[0], fi[1], fi[2], fi[3]);
System.Console.ReadLine();
}
}
}
I would appreciate any suggestions