using System;
namespace Zhou.CSharp.Algorithm
{
public delegate double delFunction_x(double x);
public delegate double delFunction_xa(double[] x);
public delegate double delFunction_x_y(double x, double y);
public delegate double delFunction_x_ya(double x, double[] y);
public delegate double delFunction_xa_ya(double[] x, double[] y);
/// <summary>
/// Class NLEquations for solving nonlinear equations
/// Zhou Changfa
/// Adapted to deep confusion
/// </summary>
public static partial class NLEquations
{
/// <summary>
/// Find the generalized inverse method of the least squares solution of the nonlinear equation system
/// 1. Calculate the value of the function f(x) at the left end of the equation and its partial derivative value
/// double Func(double[] x, double[] y)
/// 2. Calculate the Jacobian matrix function
/// double FuncMJ(double[] x, double[] y)
/// </summary>
/// <param name="Func" >Calculate the left end function of the equation</param>
/// <param name="FuncMJ">Calculate the Jacobian matrix function</param>
/// <param name="m">Number of equations</param>
// / <param name="n">Number of unknowns</param>
/// <param name="x">One-dimensional array with a length of n, storing a set of initial values x0, x1, …,xn-1, not all 0 is required, the least square solution of the equation system is stored when returning, when m=n, it is the solution of the nonlinear equation system</param>
/// <param name="eps1">least square The precision of the multiplication solution controls the precision</param>
/// <param name="eps2">The precision of the singular value decomposition controls the precision</param>
/// <return>bool type, whether the solution is successful</return>
public static bool GetRootsetGinv(delFunction_xa_ya Func, delFunction_xa_ya FuncMJ, int m, int n, double[] x, double eps1, double eps2) { int i,
j , k, r, kk, jt; double alpha, z = 0, h2, y1, y2, y3, y0, h1; double[] p, d, dx;
double[] y = new double[10];
double[] b = new double[10];
// Control parameters
int ka = Math.Max(m, n) + 1;
double[] w = new double[ka];
// Set the number of iterations to 60, iterative solution
r = 60;
alpha = 1.0;
while (r > 0)
{ Matrix mtxP = new Matrix(m, n); Matrix mtxD = new Matrix(m, 1); p = mtxP.GetData(); d = mtxD.GetData();
Func(x, d);
FuncMJ(x, p);
//Construct a system of linear equations
//LEquations leqs = new LEquations(mtxP, mtxD);
//temporary matrix
Matrix mtxAP = new Matrix();
Matrix mtxU = new Matrix();
Matrix mtxV = new Matrix();
//solution Matrix
Matrix mtxDX = new Matrix();
// least squares solution based on generalized inverse
if (!LEquations.GetRootsetGinv(mtxP, mtxD, mtxDX, mtxAP, mtxU, mtxV, eps2))
{ return false; }
dx = mtxDX.GetData();
j = 0;
jt = 1;
h2 = 0.0;
while (jt == 1)
{
jt = 0;
if (j <= 2)
{
z = alpha + 0.01 * j;
}
else
{
z = h2;
}
for (i = 0; i <= n - 1; i++)
{
w[i] = x[i] - z * dx[i];
}
Func(w, d);
y1 = 0.0;
for (i = 0; i <= m - 1; i++)
{
y1 = y1 + d[i] * d[i];
}
for (i = 0; i <= n - 1; i++)
{
w[i] = x[i] - (z + 0.00001) * dx[i];
}
Func(w, d);
y2 = 0.0;
for (i = 0; i <= m - 1; i++)
{
y2 = y2 + d[i] * d[i];
}
y0 = (y2 - y1) / 0.00001;
if (Math.Abs(y0) > 1.0e-10)
{
h1 = y0; h2 = z;
if (j == 0)
{
y[0] = h1;
b[0] = h2;
}
else
{
y[j] = h1;
kk = 0;
k = 0;
while ((kk == 0) && (k <= j - 1))
{
y3 = h2 - b[k];
if (Math.Abs(y3) + 1.0 == 1.0)
{
kk = 1;
}
else
{
h2 = (h1 - y[k]) / y3;
}
k = k + 1;
}
b[j] = h2;
if (kk != 0)
{
b[j] = 1.0e+35;
}
h2 = 0.0;
for (k = j - 1; k >= 0; k--)
{
h2 = -y[k] / (b[k + 1] + h2);
}
h2 = h2 + b[0];
}
j = j + 1;
if (j <= 7)
{
jt = 1;
}
else
{
z = h2;
}
}
}
alpha = z;
y1 = 0.0;
y2 = 0.0;
for (i = 0; i <= n - 1; i++)
{
dx[i] = -alpha * dx[i];
x[i] = x[i] + dx[i];
y1 = y1 + Math.Abs(dx[i]);
y2 = y2 + Math.Abs(x[i]);
}
// Solve successfully
if (y1 < eps1 * y2)
{ return true; }
r = r - 1;
}
// Solution failed
return false;
}
}
}