C#, code Haishibei (55) - C# source code for "generalized inverse method" of "nonlinear equation system" and "least square solution"

 

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;
        }
 

}

}

Guess you like

Origin blog.csdn.net/beijinghorn/article/details/131316486