public void CheckHessianDeterminantsTests()
        {
            var func  = new FunctionDefinition("f(x1,x2) = x1^2 +x2^2");
            var point = new Point(5, 4);

            var StatCondition = Hessian.ChceckHessianDeterminants(func, point);

            Assert.AreEqual(Hessian.StationaryConditions.Minimum, StatCondition);
        }
        public virtual IObjectiveFunction Fork()
        {
            // we need to deep-clone values since they may be updated inplace on evaluation
            ObjectiveFunctionBase objective = (ObjectiveFunctionBase)CreateNew();

            objective.Point    = Point == null ? null : Point.Clone();
            objective.Value    = Value;
            objective.Gradient = Gradient == null ? null : Gradient.Clone();
            objective.Hessian  = Hessian == null ? null : Hessian.Clone();
            return(objective);
        }
        public void CalculateHessianTests(double p1, double p2, double p3, double result)
        {
            var func = new FunctionDefinition("f(x1, x2, x3) = x1^3 + 2 * x2 * x3^2 + x3 * x2 + x3^3");

            var point = new Point(p1, p2, p3);

            var der = Hessian.CalculateHessian(func, point);

            if (Math.Abs(der[0, 0] - result) < 0.0001 && Math.Abs(der[1, 2] - 5) < 0.0001)
            {
                Assert.Pass();
            }
            else
            {
                Assert.AreEqual(result, der);
            }
        }
Пример #4
0
        private void CalculateMinimum()
        {
            try
            {
                StartCalculating();

                var value = Variables.Select(v => v.Value).ToArray();
                var x0    = new Point(value);
                var NS    = new FastestFallAlgorithm(_functionDefinition, x0, InputParameters.Beta, InputParameters.Tau, InputParameters.LIteration, InputParameters.Epsilon1, InputParameters.Epsilon2, InputParameters.Epsilon3);

                calcucatedPoints = NS.Run();
                var result = calcucatedPoints.Last();

                var hessianResult = Hessian.ChceckHessianDeterminants(_functionDefinition, result, InputParameters.Epsilon1);

                UpdateDataTable(calcucatedPoints);

                if (hessianResult == Hessian.StationaryConditions.Minimum)
                {
                    _messageDialogService.ShowInfoDialog($"Znaleziono minimum lokalne w punkcie : {result} \nWartość : { _functionDefinition.GetValue(result)}");
                }
                if (hessianResult != Hessian.StationaryConditions.Minimum)
                {
                    _messageDialogService.ShowInfoDialog($"Obliczono resultat, który nie jest minimum lokalnym w punkcie : {result} \nWartość : { _functionDefinition.GetValue(result)}");
                }
            }
            catch (InvalidTauException)
            {
                _messageDialogService.ShowInfoDialog("Nie można obliczyć minimum dla podaego tau. Podaj inny parametr");
            }
            catch (UnfortunateFunctionCaseException fex)
            {
                calcucatedPoints = fex.Points;
                UpdateDataTable(fex.Points);
                var lastPoint = fex.Points.Last();
                _messageDialogService.ShowInfoDialog($"Algorytm zakończył działanie z powodu zbyt dużej ilości obliczeń. \nOstatni obliczony punkt wynosi : {lastPoint} \nWartość : { _functionDefinition.GetValue(lastPoint)}");
            }
            catch (Exception ex)
            {
                _messageDialogService.ShowInfoDialog(ex.ToString());
            }
        }
Пример #5
0
        public void Hessian___Gradient___Calculation___Test()
        {
            int accuracy = 15;

            /*
             * function obliczanie_hesjan_gradient()
             * clear();
             * inp = [-1 -1;-1 1; 1 -1];
             * dout = [1;0;0];
             * topo = [3 1 2 4 1 2 3];
             * ww = [1 1 1 1 1 1 1];
             * act = [2 0];
             * gain = [1 1];
             * param = [3 2 1 7 2];
             * iw = [1 4 8];
             * format long;
             *
             * [gradient,hessian] = Hessian(inp,dout,topo,ww,act,gain,param,iw);
             * fprintf('Otrzymany gradient:\n');
             * disp(gradient);
             * fprintf('\nOtrzymany hesjan:\n');
             * disp(hessian);
             *
             * % To jest otrzymywane
             * % Otrzymany gradient:
             * %   -0.839948683228052
             * %    2.319597374905329
             * %    2.319597374905329
             * %   -2.000000000000000
             * %    5.523188311911530
             * %    5.523188311911531
             * %    6.889667569278484
             * %
             * %
             * % Otrzymany hesjan:
             * %   Columns 1 through 6
             * %
             * %    1.058270685684809  -0.705513790456539  -0.705513790456539   2.519846049684157  -1.679897366456105  -1.679897366456105
             * %   -0.705513790456539   1.058270685684809   0.352756895228269  -1.679897366456105   2.519846049684157   0.839948683228052
             * %   -0.705513790456539   0.352756895228269   1.058270685684809  -1.679897366456105   0.839948683228052   2.519846049684157
             * %    2.519846049684157  -1.679897366456105  -1.679897366456105   6.000000000000000  -4.000000000000000  -4.000000000000000
             * %   -1.679897366456105   2.519846049684157   0.839948683228052  -4.000000000000000   6.000000000000000   2.000000000000000
             * %   -1.679897366456105   0.839948683228052   2.519846049684157  -4.000000000000000   2.000000000000000   6.000000000000000
             * %   -0.639700008449225   1.279400016898449   1.279400016898449  -1.523188311911530   3.046376623823059   3.046376623823059
             * %
             * %   Column 7
             * %
             * %   -0.639700008449225
             * %    1.279400016898449
             * %    1.279400016898449
             * %   -1.523188311911530
             * %    3.046376623823059
             * %    3.046376623823059
             * %    3.480153950315843
             * end
             */
            Input input = new Input(3, 2);//inp = [-1 -1;-1 1; 1 -1];

            input[0, 0] = -1;
            input[0, 1] = -1;
            input[1, 0] = -1;
            input[1, 1] = 1;
            input[2, 0] = 1;
            input[2, 1] = -1;

            Output output = new Output(3, 1);//dout = [1;0;0];

            output[0, 0] = 1;
            output[1, 0] = 0;
            output[2, 0] = 0;

            NetworkInfo info = new NetworkInfo();//param = [3 2 1 7 2];

            info.ni = 2;
            info.nn = 2;
            info.no = 1;
            info.np = 3;
            info.nw = 7;

            VectorHorizontal vh = new VectorHorizontal(3);

            vh[0, 0] = 2;
            vh[0, 1] = 1;
            vh[0, 2] = 1;

            Topography topo = Topography.Generate(TopographyType.BMLP, vh);//topo = [3 1 2 4 1 2 3];

            //w C# indeksy są od zera a nie od 1 więc wszystko o 1 w dół przestawione jest
            Assert.AreEqual(2, topo[0]);
            Assert.AreEqual(0, topo[1]);
            Assert.AreEqual(1, topo[2]);
            Assert.AreEqual(3, topo[3]);
            Assert.AreEqual(0, topo[4]);
            Assert.AreEqual(1, topo[5]);
            Assert.AreEqual(2, topo[6]);

            Weights weights = new Weights(info.nw); //w = [1 1 1 1 1 1 1];

            weights.FillWithNumber(1);              //załatwione

            Activation act = new Activation(2);     //act = [2 0];

            act[0] = 2;
            act[1] = 0;

            Gain gain = new Gain(2);//gain = [1 1];

            gain[0] = 1;
            gain[1] = 1;

            Index iw = Index.Find(ref topo);//iw = [1 4 8];

            //ta sama sytuacja, indeksy od 0 startują
            Assert.AreEqual(0, iw[0]);
            Assert.AreEqual(3, iw[1]);
            Assert.AreEqual(7, iw[2]);
            Console.WriteLine("Testowanie obliczania gradientu i macierzy hesjana");
            Console.WriteLine("Użyte dane:");
            Console.WriteLine("\nDane wejściowe:");
            Console.WriteLine(input.MatrixToString());
            Console.WriteLine("\nDane wyjściowe:");
            Console.WriteLine(output.MatrixToString());
            Console.WriteLine("\nWagi;");
            Console.WriteLine(weights.MatrixToString());
            Console.WriteLine("\nTopologia:");
            Console.WriteLine(topo.MatrixToString());
            Console.WriteLine("\nIndeksy topologii:");
            Console.WriteLine(iw.MatrixToString());
            Console.WriteLine("\nFunkcje aktywacji:");
            Console.WriteLine(act.MatrixToString());
            Console.WriteLine("\nWzmocnienia (gains):");
            Console.WriteLine(gain.MatrixToString());
            Console.WriteLine("\nParametry (param):");
            Console.WriteLine(info.ToString());
            Hessian hess = new Hessian(ref info);

            hess.Compute(ref info, ref input, ref output, ref topo, weights, ref act, ref gain, ref iw);
            var g = hess.GradientMat;
            var h = hess.HessianMat;

            Console.WriteLine("\nSprawdzanie gradientu z dokładnością do 15 miejsc po przecinku");
            var matG = new double[] { -0.839948683228052, 2.319597374905329, 2.319597374905329, -2.000000000000000, 5.523188311911530, 5.523188311911531, 6.889667569278484 };

            /*
             * % Otrzymany gradient:
             * %   -0.839948683228052
             * %    2.319597374905329
             * %    2.319597374905329
             * %   -2.000000000000000
             * %    5.523188311911530
             * %    5.523188311911531
             * %    6.889667569278484
             */
            for (int i = 0; i < matG.Length; i++)
            {
                Console.WriteLine(string.Format("NBN C#: {0}\tMatLab NBN: {1}\t{2}", Math.Round(g[i, 0], accuracy), matG[i], Math.Round(g[i, 0], accuracy) == matG[i] ? "OK" : "źle"));
            }

            Assert.AreEqual(-0.839948683228052, Math.Round(g[0, 0], accuracy));
            Assert.AreEqual(2.319597374905329, Math.Round(g[1, 0], accuracy));
            Assert.AreEqual(2.319597374905329, Math.Round(g[2, 0], accuracy));
            Assert.AreEqual(-2.000000000000000, Math.Round(g[3, 0], accuracy));
            Assert.AreEqual(5.523188311911530, Math.Round(g[4, 0], accuracy));
            Assert.AreEqual(5.523188311911531, Math.Round(g[5, 0], accuracy));
            Assert.AreEqual(6.889667569278484, Math.Round(g[6, 0], accuracy));

            Console.WriteLine("\nSprawdzanie macierzy hesjana\nPorównania z dokładnością do 15 miejsc po przecinku");
            MatrixMB matH = new MatrixMB(7, 7);

            //col 1
            matH[0, 0] = 1.058270685684809;
            matH[1, 0] = -0.705513790456539;
            matH[2, 0] = -0.705513790456539;
            matH[3, 0] = 2.519846049684157;
            matH[4, 0] = -1.679897366456105;
            matH[5, 0] = -1.679897366456105;
            matH[6, 0] = -0.639700008449225;

            //col 2
            matH[0, 1] = -0.705513790456539;
            matH[1, 1] = 1.058270685684809;
            matH[2, 1] = 0.352756895228269;
            matH[3, 1] = -1.679897366456105;
            matH[4, 1] = 2.519846049684157;
            matH[5, 1] = 0.839948683228052;
            matH[6, 1] = 1.279400016898449;

            //col 3
            matH[0, 2] = -0.705513790456539;
            matH[1, 2] = 0.352756895228269;
            matH[2, 2] = 1.058270685684809;
            matH[3, 2] = -1.679897366456105;
            matH[4, 2] = 0.839948683228052;
            matH[5, 2] = 2.519846049684157;
            matH[6, 2] = 1.279400016898449;

            //col 4
            matH[0, 3] = 2.519846049684157;
            matH[1, 3] = -1.679897366456105;
            matH[2, 3] = -1.679897366456105;
            matH[3, 3] = 6.000000000000000;
            matH[4, 3] = -4.000000000000000;
            matH[5, 3] = -4.000000000000000;
            matH[6, 3] = -1.523188311911530;

            //col 5
            matH[0, 4] = -1.679897366456105;
            matH[1, 4] = 2.519846049684157;
            matH[2, 4] = 0.839948683228052;
            matH[3, 4] = -4.000000000000000;
            matH[4, 4] = 6.000000000000000;
            matH[5, 4] = 2.000000000000000;
            matH[6, 4] = 3.046376623823059;

            //col 6
            matH[0, 5] = -1.679897366456105;
            matH[1, 5] = 0.839948683228052;
            matH[2, 5] = 2.519846049684157;
            matH[3, 5] = -4.000000000000000;
            matH[4, 5] = 2.000000000000000;
            matH[5, 5] = 6.000000000000000;
            matH[6, 5] = 3.046376623823059;

            //col 7
            matH[0, 6] = -0.639700008449225;
            matH[1, 6] = 1.279400016898449;
            matH[2, 6] = 1.279400016898449;
            matH[3, 6] = -1.523188311911530;
            matH[4, 6] = 3.046376623823059;
            matH[5, 6] = 3.046376623823059;
            matH[6, 6] = 3.480153950315843;

            for (int k = 0; k < h.Cols; k++)
            {
                Console.WriteLine(string.Format("Kolumna {0}", k + 1));
                for (int w = 0; w < h.Rows; w++)
                {
                    decimal dh  = Math.Round((decimal)h[w, k], accuracy);
                    decimal dmh = Math.Round((decimal)matH[w, k], accuracy);
                    Console.WriteLine(string.Format("NBN C#: {0}\tMatLab NBN: {1}\t{2}", dh, dmh, dh == dmh ? "OK" : "źle"));
                }
                Console.WriteLine("");
            }

            for (int k = 0; k < h.Cols; k++)
            {
                for (int w = 0; w < h.Rows; w++)
                {
                    decimal dh  = Math.Round((decimal)h[w, k], accuracy);
                    decimal dmh = Math.Round((decimal)matH[w, k], accuracy);
                    Assert.AreEqual(dmh, dh);
                }
            }

            /*
             * % Otrzymany hesjan:
             * %   Columns 1 through 6
             * %
             * %    1.058270685684809  -0.705513790456539  -0.705513790456539   2.519846049684157  -1.679897366456105  -1.679897366456105
             * %   -0.705513790456539   1.058270685684809   0.352756895228269  -1.679897366456105   2.519846049684157   0.839948683228052
             * %   -0.705513790456539   0.352756895228269   1.058270685684809  -1.679897366456105   0.839948683228052   2.519846049684157
             * %    2.519846049684157  -1.679897366456105  -1.679897366456105   6.000000000000000  -4.000000000000000  -4.000000000000000
             * %   -1.679897366456105   2.519846049684157   0.839948683228052  -4.000000000000000   6.000000000000000   2.000000000000000
             * %   -1.679897366456105   0.839948683228052   2.519846049684157  -4.000000000000000   2.000000000000000   6.000000000000000
             * %   -0.639700008449225   1.279400016898449   1.279400016898449  -1.523188311911530   3.046376623823059   3.046376623823059
             * %
             * %   Column 7
             * %
             * %   -0.639700008449225
             * %    1.279400016898449
             * %    1.279400016898449
             * %   -1.523188311911530
             * %    3.046376623823059
             * %    3.046376623823059
             * %    3.480153950315843
             */
        }
 public FunctionWrapper(Function function, Gradients gradient, Hessian hessian = null)
 {
     _function = function;
     _gradient = gradient;
     _hessian  = hessian;
 }
Пример #7
0
        public void FitLM(Multiplet exp, out string MSG, out string LATEX)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            //Matrix<double> Grad;
            Matrix <double> Hessiandiag;
            Matrix <double> parameters = Matrix <double> .Build.Dense(3, 1);

            Matrix <double> newparams;// = Matrix<double>.Build.Dense(3, 1);

            //Vector<double> error;// = Vector<double>.Build.Dense(3);
            LATEX            = "";
            parameters[0, 0] = exp.o2;
            parameters[1, 0] = exp.o4;
            parameters[2, 0] = exp.o6;
            double no2, no4, no6, sumfexp, sumdfexp;
            double lambda, chi2s, chi2n;

            lambda   = 1 / 1024.0;
            sumdfexp = 0;
            sumfexp  = 0;
//            chi2s = 0;
            chi2n       = 0;
            Hessiandiag = Matrix <double> .Build.Dense(3, 3, 1);

            MSG = "Num.\tChi2\tO2\tO4\tO6\r\n";
            Console.WriteLine("Beginnig fitting procedure.");
            for (int i = 1; i < 10; i++)
            {
                chi2s = Chi2(exp);
                CalculateHessian(exp, out Matrix <double> Hessian, out Matrix <double> Grad);

                /*Console.WriteLine("gradient");
                 * Console.WriteLine(Grad.ToString());
                 * Console.WriteLine("hessian");
                 * Console.WriteLine(Hessian.ToString());
                 */
                Hessiandiag = Matrix <double> .Build.DiagonalOfDiagonalVector(Hessian.Diagonal());

                //Console.WriteLine(Hessiandiag.ToString());
                newparams = parameters - ((Hessian + lambda * Hessiandiag).Inverse() * Grad);
                //Console.WriteLine(newparams.ToString());
                no2 = (newparams[0, 0]);
                no4 = (newparams[1, 0]);
                no6 = (newparams[2, 0]);

                chi2n = Chi2new(exp, no2, no4, no6);
                Console.WriteLine(i + " " + chi2s.ToString("G6") + " " + no2.ToString("G6") + " " + no4.ToString("G6") + " " + no6.ToString("G6"));
                MSG += i.ToString() + "\t" + chi2s.ToString("G6") + "\t" + no2.ToString("G6") + "\t" + no4.ToString("G6") + "\t" + no6.ToString("G6") + "\r\n";
                if (chi2n < chi2s)
                {
                    parameters = newparams;
                    exp.o2     = no2;
                    exp.o4     = no4;
                    exp.o6     = no6;
                    lambda    *= 1.1;
                }
                else
                {
                    lambda *= 1 / 1.1;
                }
            }
            Console.WriteLine("Fitting finished");
            MSG += "Fitting finished \r\n";
            DumpFitResult(exp, ref MSG, ref LATEX, sw, Hessiandiag, ref sumfexp, ref sumdfexp, chi2n);
        }
Пример #8
0
        /// <summary>
        /// Non-linear least square fitting by the Levenberg-Marduardt algorithm.
        /// </summary>
        /// <param name="objective">The objective function, including model, observations, and parameter bounds.</param>
        /// <param name="initialGuess">The initial guess values.</param>
        /// <param name="initialMu">The initial damping parameter of mu.</param>
        /// <param name="gradientTolerance">The stopping threshold for infinity norm of the gradient vector.</param>
        /// <param name="stepTolerance">The stopping threshold for L2 norm of the change of parameters.</param>
        /// <param name="functionTolerance">The stopping threshold for L2 norm of the residuals.</param>
        /// <param name="maximumIterations">The max iterations.</param>
        /// <returns>The result of the Levenberg-Marquardt minimization</returns>
        public NonlinearMinimizationResult Minimum(IObjectiveModel objective, Vector <double> initialGuess,
                                                   Vector <double> lowerBound = null, Vector <double> upperBound = null, Vector <double> scales = null, List <bool> isFixed      = null,
                                                   double initialMu           = 1E-3, double gradientTolerance   = 1E-15, double stepTolerance = 1E-15, double functionTolerance = 1E-15, int maximumIterations = -1)
        {
            // Non-linear least square fitting by the Levenberg-Marduardt algorithm.
            //
            // Levenberg-Marquardt is finding the minimum of a function F(p) that is a sum of squares of nonlinear functions.
            //
            // For given datum pair (x, y), uncertainties σ (or weighting W  =  1 / σ^2) and model function f = f(x; p),
            // let's find the parameters of the model so that the sum of the quares of the deviations is minimized.
            //
            //    F(p) = 1/2 * ∑{ Wi * (yi - f(xi; p))^2 }
            //    pbest = argmin F(p)
            //
            // We will use the following terms:
            //    Weighting W is the diagonal matrix and can be decomposed as LL', so L = 1/σ
            //    Residuals, R = L(y - f(x; p))
            //    Residual sum of squares, RSS = ||R||^2 = R.DotProduct(R)
            //    Jacobian J = df(x; p)/dp
            //    Gradient g = -J'W(y − f(x; p)) = -J'LR
            //    Approximated Hessian H = J'WJ
            //
            // The Levenberg-Marquardt algorithm is summarized as follows:
            //    initially let μ = τ * max(diag(H)).
            //    repeat
            //       solve linear equations: (H + μI)ΔP = -g
            //       let ρ = (||R||^2 - ||Rnew||^2) / (Δp'(μΔp - g)).
            //       if ρ > ε, P = P + ΔP; μ = μ * max(1/3, 1 - (2ρ - 1)^3); ν = 2;
            //       otherwise μ = μ*ν; ν = 2*ν;
            //
            // References:
            // [1]. Madsen, K., H. B. Nielsen, and O. Tingleff.
            //    "Methods for Non-Linear Least Squares Problems. Technical University of Denmark, 2004. Lecture notes." (2004).
            //    Available Online from: http://orbit.dtu.dk/files/2721358/imm3215.pdf
            // [2]. Gavin, Henri.
            //    "The Levenberg-Marquardt method for nonlinear least squares curve-fitting problems."
            //    Department of Civil and Environmental Engineering, Duke University (2017): 1-19.
            //    Availble Online from: http://people.duke.edu/~hpgavin/ce281/lm.pdf

            if (objective == null)
            {
                throw new ArgumentNullException(nameof(objective));
            }

            ValidateBounds(initialGuess, lowerBound, upperBound, scales);

            objective.SetParameters(initialGuess, isFixed);

            ExitCondition exitCondition = ExitCondition.None;

            // First, calculate function values and setup variables
            var             P = ProjectToInternalParameters(initialGuess); // current internal parameters
            Vector <double> Pstep;                                         // the change of parameters
            var             RSS = EvaluateFunction(objective, P);          // Residual Sum of Squares = R'R

            if (maximumIterations < 0)
            {
                maximumIterations = 200 * (initialGuess.Count + 1);
            }

            // if RSS == NaN, stop
            if (double.IsNaN(RSS))
            {
                exitCondition = ExitCondition.InvalidValues;
                return(new NonlinearMinimizationResult(objective, -1, exitCondition));
            }

            // When only function evaluation is needed, set maximumIterations to zero,
            if (maximumIterations == 0)
            {
                exitCondition = ExitCondition.ManuallyStopped;
            }

            // if RSS <= fTol, stop
            if (RSS <= functionTolerance)
            {
                exitCondition = ExitCondition.Converged; // SmallRSS
            }

            // Evaluate gradient and Hessian
            var(Gradient, Hessian) = EvaluateJacobian(objective, P);
            var diagonalOfHessian = Hessian.Diagonal(); // diag(H)

            // if ||g||oo <= gtol, found and stop
            if (Gradient.InfinityNorm() <= gradientTolerance)
            {
                exitCondition = ExitCondition.RelativeGradient;
            }

            if (exitCondition != ExitCondition.None)
            {
                return(new NonlinearMinimizationResult(objective, -1, exitCondition));
            }

            double mu         = initialMu * diagonalOfHessian.Max(); // μ
            double nu         = 2;                                   //  ν
            int    iterations = 0;

            while (iterations < maximumIterations && exitCondition == ExitCondition.None)
            {
                iterations++;

                while (true)
                {
                    Hessian.SetDiagonal(Hessian.Diagonal() + mu); // hessian[i, i] = hessian[i, i] + mu;

                    // solve normal equations
                    Pstep = Hessian.Solve(-Gradient);

                    // if ||ΔP|| <= xTol * (||P|| + xTol), found and stop
                    if (Pstep.L2Norm() <= stepTolerance * (stepTolerance + P.DotProduct(P)))
                    {
                        exitCondition = ExitCondition.RelativePoints;
                        break;
                    }

                    var Pnew = P + Pstep; // new parameters to test
                    // evaluate function at Pnew
                    var RSSnew = EvaluateFunction(objective, Pnew);

                    if (double.IsNaN(RSSnew))
                    {
                        exitCondition = ExitCondition.InvalidValues;
                        break;
                    }

                    // calculate the ratio of the actual to the predicted reduction.
                    // ρ = (RSS - RSSnew) / (Δp'(μΔp - g))
                    var predictedReduction = Pstep.DotProduct(mu * Pstep - Gradient);
                    var rho = (predictedReduction != 0)
                            ? (RSS - RSSnew) / predictedReduction
                            : 0;

                    if (rho > 0.0)
                    {
                        // accepted
                        Pnew.CopyTo(P);
                        RSS = RSSnew;

                        // update gradient and Hessian
                        (Gradient, Hessian) = EvaluateJacobian(objective, P);
                        diagonalOfHessian   = Hessian.Diagonal();

                        // if ||g||_oo <= gtol, found and stop
                        if (Gradient.InfinityNorm() <= gradientTolerance)
                        {
                            exitCondition = ExitCondition.RelativeGradient;
                        }

                        // if ||R||^2 < fTol, found and stop
                        if (RSS <= functionTolerance)
                        {
                            exitCondition = ExitCondition.Converged; // SmallRSS
                        }

                        mu = mu * Math.Max(1.0 / 3.0, 1.0 - Math.Pow(2.0 * rho - 1.0, 3));
                        nu = 2;

                        break;
                    }
                    else
                    {
                        // rejected, increased μ
                        mu = mu * nu;
                        nu = 2 * nu;

                        Hessian.SetDiagonal(diagonalOfHessian);
                    }
                }
            }

            if (iterations >= maximumIterations)
            {
                exitCondition = ExitCondition.ExceedIterations;
            }

            return(new NonlinearMinimizationResult(objective, iterations, exitCondition));
        }
Пример #9
0
        public override void GenerateJacobian()
        {
            int i = 0;

            Jacobian.Clear();
            var testEval = new Evaluator();


            foreach (var equation in Equations)
            {
                var incidenceVector = equation.Incidence(testEval);

                foreach (var variable in incidenceVector)
                {
                    if (!variable.IsConstant && variable.DefiningExpression == null)
                    {
                        int j = -1;
                        if (_variableIndex.TryGetValue(variable, out j))
                        {
                            Jacobian.Add(new JacobianElement()
                            {
                                EquationIndex = i, VariableIndex = j, Value = 1.0
                            });

                            if (UseHessian)
                            {
                                var differential = (equation.Right - equation.Left).SymbolicDiff(variable);

                                foreach (var variable2 in incidenceVector)
                                {
                                    if (!variable2.IsConstant && variable2.DefiningExpression == null)
                                    {
                                        int k = -1;
                                        if (_variableIndex.TryGetValue(variable2, out k) && k <= j)
                                        {
                                            Hessian.Add(new HessianElement()
                                            {
                                                EquationIndex = i, Variable1Index = j, Variable2Index = k, Expression = differential, Value = 1.0
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                i++;
            }



            if (UseHessian)
            {
                var incidenceVector = ObjectiveFunction.Incidence();

                foreach (var variable1 in incidenceVector)
                {
                    if (!variable1.IsConstant && variable1.DefiningExpression == null)
                    {
                        int j = -1;
                        if (_variableIndex.TryGetValue(variable1, out j))
                        {
                            var differential = ObjectiveFunction.SymbolicDiff(variable1);
                            foreach (var variable2 in incidenceVector)
                            {
                                if (!variable2.IsConstant && variable2.DefiningExpression == null)
                                {
                                    int k = -1;
                                    if (_variableIndex.TryGetValue(variable2, out k) && k <= j)
                                    {
                                        ObjectiveHessian.Add(new HessianElement()
                                        {
                                            EquationIndex = 0, Variable1Index = j, Variable2Index = k, Expression = differential, Value = 1.0
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
            }


            foreach (var equation in Constraints)
            {
                var incidenceVector = equation.Incidence(testEval);
                foreach (var variable in incidenceVector)
                {
                    if (!variable.IsConstant && variable.DefiningExpression == null)
                    {
                        int j = -1;
                        if (_variableIndex.TryGetValue(variable, out j))
                        {
                            Jacobian.Add(new JacobianElement()
                            {
                                EquationIndex = i, VariableIndex = j, Value = 1.0
                            });

                            if (UseHessian)
                            {
                                var differential = (equation.Right - equation.Left).SymbolicDiff(variable);

                                foreach (var variable2 in incidenceVector)
                                {
                                    if (!variable2.IsConstant && variable2.DefiningExpression == null)
                                    {
                                        int k = -1;
                                        if (_variableIndex.TryGetValue(variable2, out k) && k <= j)
                                        {
                                            Hessian.Add(new HessianElement()
                                            {
                                                EquationIndex = i, Variable1Index = j, Variable2Index = k, Expression = differential, Value = 1.0
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                i++;
            }

            if (UseHessian)
            {
                GenerateHessianStructureInfo();
            }
        }