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>
/// 求解非线性方程组的类 NLEquations
/// 原作 周长发
/// 改编 深度混淆
/// </summary>
public static partial class NLEquations
{
/// <summary>
/// 求非线性方程组一组实根的拟牛顿法
/// 计算方程左端函数f(x)值及其偏导数值
/// double Func(double[] x, double[] y)
/// </summary>
/// <param name="Func">计算方程左端函数</param>
/// <param name="n">方程的个数,也是未知数的个数</param>
/// <param name="x">一维数组,长度为n,存放一组初值x0, x1, …, xn-1, 返回时存放方程组的一组实根</param>
/// <param name="t">控制h大小的变量,0<t<1</param>
/// <param name="h">增量初值</param>
/// <param name="nMaxIt">迭代次数</param>
/// <param name="eps">控制精度</param>
/// <return>bool 型,求解是否成功</return>
public static bool GetRootsetNewton(delFunction_xa_ya Func, int n, double[] x, double t, double h, int nMaxIt, double eps)
{
int i, j, r;
double am, z, beta, d;
double[] y = new double[n];
// 构造矩阵
Matrix mtxCoef = new Matrix(n, n);
Matrix mtxConst = new Matrix(n, 1);
double[] a = mtxCoef.GetData();
double[] b = mtxConst.GetData();
// 迭代求解
r = nMaxIt;
am = 1.0 + eps;
while (am >= eps)
{
Func(x, b);
am = 0.0;
for (i = 0; i <= n - 1; i++)
{
z = Math.Abs(b[i]);
if (z > am)
{
am = z;
}
}
if (am >= eps)
{
r = r - 1;
if (r == 0)
{
return false;
}
for (j = 0; j <= n - 1; j++)
{
z = x[j];
x[j] = x[j] + h;
Func(x, y);
for (i = 0; i <= n - 1; i++)
{
a[i * n + j] = y[i];
}
x[j] = z;
}
// 调用全选主元高斯消元法
Matrix mtxResult = new Matrix();
if (!LEquations.GetRootsetGauss(mtxCoef, mtxConst, mtxResult))
{
return false;
}
mtxConst.SetValue(mtxResult);
b = mtxConst.GetData();
beta = 1.0;
for (i = 0; i <= n - 1; i++)
{
beta = beta - b[i];
}
if (Math.Abs(beta) < float.Epsilon)
{
return false;
}
d = h / beta;
for (i = 0; i <= n - 1; i++)
{
x[i] = x[i] - d * b[i];
}
h = t * h;
}
}
// 是否在有效迭代次数内达到精度
return (nMaxIt > r);
}
}
}