public void QrDecompositionConstructorTest()
        {
            double[,] value =
            {
                {  2, -1,  0 },
                { -1,  2, -1 },
                {  0, -1,  2 }
            };


            var target = new QrDecomposition(value);

            // Decomposition Identity
            var Q   = target.OrthogonalFactor;
            var QQt = Q.DotWithTransposed(Q);

            Assert.IsTrue(Matrix.IsEqual(QQt, Matrix.Identity(3), 1e-6));
            Assert.IsTrue(Matrix.IsEqual(value, target.Reverse(), 1e-6));


            // Linear system solving
            double[,] B        = Matrix.ColumnVector(new double[] { 1, 2, 3 });
            double[,] expected = Matrix.ColumnVector(new double[] { 2.5, 4.0, 3.5 });
            double[,] actual   = target.Solve(B);

            Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001));
        }
        public void SolveTest2()
        {
            // Example from Lecture notes for MATHS 370: Advanced Numerical Methods
            // http://www.math.auckland.ac.nz/~sharp/370/qr-solving.pdf

            double[,] value =
            {
                { 1,  0,    0 },
                { 1,  7,   49 },
                { 1, 14,  196 },
                { 1, 21,  441 },
                { 1, 28,  784 },
                { 1, 35, 1225 },
            };

            // Matrices
            {
                double[,] b =
                {
                    { 4 },
                    { 1 },
                    { 0 },
                    { 0 },
                    { 2 },
                    { 5 },
                };

                double[,] expected =
                {
                    {  3.9286 },
                    { -0.5031 },
                    {  0.0153 },
                };

                var target = new QrDecomposition(value);
                double[,] actual = target.Solve(b);

                Assert.IsTrue(Matrix.IsEqual(expected, actual, atol: 1e-4));
                Assert.IsTrue(Matrix.IsEqual(value, target.Reverse(), 1e-6));


                var        target2 = new JaggedQrDecomposition(value.ToJagged());
                double[][] actual2 = target2.Solve(b.ToJagged());

                Assert.IsTrue(Matrix.IsEqual(expected, actual2, atol: 1e-4));
                Assert.IsTrue(Matrix.IsEqual(value, target2.Reverse(), 1e-6));
            }

            // Vectors
            {
                double[] b        = { 4, 1, 0, 0, 2, 5 };
                double[] expected = { 3.9286, -0.5031, 0.0153 };

                var      target = new QrDecomposition(value);
                double[] actual = target.Solve(b);

                Assert.IsTrue(Matrix.IsEqual(expected, actual, atol: 1e-4));
            }
        }
        public void SolveTest()
        {
            double[,] value =
            {
                {  2, -1,  0 },
                { -1,  2, -1 },
                {  0, -1,  2 }
            };

            double[] b = { 1, 2, 3 };

            double[] expected = { 2.5000, 4.0000, 3.5000 };

            QrDecomposition target = new QrDecomposition(value);

            double[] actual = target.Solve(b);

            Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001));
        }
        private double[,] SolveMatrix(Dictionary <Joint, Joint> matching)
        {
            double[,] matrix = new double[3 * matching.Count, 12];
            double[] rightSide = new double[3 * matching.Count];

            int i = 0;

            foreach (Joint key in matching.Keys)
            {
                for (int k = 0; k < 3; k++)
                {
                    matrix[3 * i + k, 4 * k]     = key.Position.X;
                    matrix[3 * i + k, 4 * k + 1] = key.Position.Y;
                    matrix[3 * i + k, 4 * k + 2] = key.Position.Z;
                    matrix[3 * i + k, 4 * k + 3] = 1;
                }
                rightSide[3 * i]     = matching[key].Position.X;
                rightSide[3 * i + 1] = matching[key].Position.Y;
                rightSide[3 * i + 2] = matching[key].Position.Z;
                i++;
            }

            QrDecomposition decomposition = new QrDecomposition(matrix);

            double[] coefficientsVector = decomposition.Solve(rightSide);

            double[,] coefficients = new double[4, 4];
            for (int j = 0; j < coefficients.GetLength(0) - 1; j++)
            {
                for (int k = 0; k < coefficients.GetLength(1); k++)
                {
                    coefficients[j, k] = coefficientsVector[j * coefficients.GetLength(1) + k];
                }
            }
            for (int k = 0; k < coefficients.GetLength(1); k++)
            {
                coefficients[3, k] = (k == 3) ? 1 : 0;
            }

            return(coefficients);
        }
        public void InverseTestNaN()
        {
            int n = 5;

            var I = Matrix.Identity(n);

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    double[,] value = Matrix.Magic(n);

                    value[i, j] = double.NaN;

                    var target   = new QrDecomposition(value);
                    var solution = target.Solve(I);
                    var inverse  = target.Inverse();

                    Assert.IsTrue(Matrix.IsEqual(solution, inverse));
                }
            }
        }
Ejemplo n.º 6
0
        public static void m1()
        {
            double[][] dataA = new double[][]
            {
                new double[] { 8.1, 2.3, -1.5 },
                new double[] { 0.5, -6.23, 0.87 },
                new double[] { 2.5, 1.5, 10.2 },
            };

            double[][] dataB = new double[][]
            {
                new double[] { 6.1 },
                new double[] { 2.3 },
                new double[] { 1.8 },
            };

            Matrix A = new Matrix(dataA);
            Matrix b = new Matrix(dataB);

            // 通过LU上下三角分解法 求解线性方程组 Ax = b
            QrDecomposition d = new QrDecomposition(A);
            Matrix          x = d.Solve(b);
        }
        public void SolveTest3()
        {
            double[][] value =
            {
                new double[] { 41.9, 29.1, 1 },
                new double[] { 43.4, 29.3, 1 },
                new double[] { 43.9, 29.5, 0 },
                new double[] { 44.5, 29.7, 0 },
                new double[] { 47.3, 29.9, 0 },
                new double[] { 47.5, 30.3, 0 },
                new double[] { 47.9, 30.5, 0 },
                new double[] { 50.2, 30.7, 0 },
                new double[] { 52.8, 30.8, 0 },
                new double[] { 53.2, 30.9, 0 },
                new double[] { 56.7, 31.5, 0 },
                new double[] { 57.0, 31.7, 0 },
                new double[] { 63.5, 31.9, 0 },
                new double[] { 65.3, 32.0, 0 },
                new double[] { 71.1, 32.1, 0 },
                new double[] { 77.0, 32.5, 0 },
                new double[] { 77.8, 32.9, 0 }
            };

            double[][] b =
            {
                new double[] { 251.3 },
                new double[] { 251.3 },
                new double[] { 248.3 },
                new double[] { 267.5 },
                new double[] { 273.0 },
                new double[] { 276.5 },
                new double[] { 270.3 },
                new double[] { 274.9 },
                new double[] { 285.0 },
                new double[] { 290.0 },
                new double[] { 297.0 },
                new double[] { 302.5 },
                new double[] { 304.5 },
                new double[] { 309.3 },
                new double[] { 321.7 },
                new double[] { 330.7 },
                new double[] { 349.0 }
            };

            double[][] expected =
            {
                new double[] {  1.7315235669547167 },
                new double[] {    6.25142110500275 },
                new double[] { -5.0909763966987178 },
            };

            var target = new JaggedQrDecomposition(value);

            double[][] actual = target.Solve(b);

            Assert.IsTrue(Matrix.IsEqual(expected, actual, atol: 1e-4));
            var reconstruct = value.Dot(expected);

            Assert.IsTrue(Matrix.IsEqual(reconstruct, b, rtol: 1e-1));
            double[] b2        = b.GetColumn(0);
            double[] expected2 = expected.GetColumn(0);

            var target2 = new JaggedQrDecomposition(value);

            double[] actual2 = target2.Solve(b2);
            Assert.IsTrue(Matrix.IsEqual(expected2, actual2, atol: 1e-4));

            var targetMat = new QrDecomposition(value.ToMatrix());

            double[,] actualMat = targetMat.Solve(b.ToMatrix());

            Assert.IsTrue(Matrix.IsEqual(expected, actualMat, atol: 1e-4));
            var reconstructMat = value.ToMatrix().Dot(expected);

            Assert.IsTrue(Matrix.IsEqual(reconstruct, b, rtol: 1e-1));

            var targetMat2 = new QrDecomposition(value.ToMatrix());

            Assert.IsTrue(Matrix.IsEqual(target2.Diagonal, targetMat2.Diagonal, atol: 1e-4));
            Assert.IsTrue(Matrix.IsEqual(target2.OrthogonalFactor, targetMat2.OrthogonalFactor, atol: 1e-4));
            Assert.IsTrue(Matrix.IsEqual(target2.UpperTriangularFactor, targetMat2.UpperTriangularFactor, atol: 1e-4));

            double[] actualMat2 = targetMat2.Solve(b2);
            Assert.IsTrue(Matrix.IsEqual(expected2, actualMat2, atol: 1e-4));
        }
Ejemplo n.º 8
0
        public static void Run(int pllproc)
        {
            double[] @params  = new double[6];
            double   maxgrad  = 0;
            double   stpthrsh = 0;
            double   maxeigen;
            double   mineigen;
            double   wr = 0;

            double[] alpha = { 0.50, 1.00 };
            double   rfMax = 2.75;
            int      td    = 0;

            int[]  prtls   = { -1, -1, -1, -1 };
            int    iterint = 1;
            long   sn      = (long)Math.Pow(10.0, 7);
            int    prec    = (int)Math.Pow(10.0, 4);
            string type    = "";
            string alg     = "";

            const string rootdir = Config.ConfigsRootDir;

            // Read setup details from control file.
            try
            {
                var getParams = File.ReadAllText(Path.Combine(rootdir, Config.ControlFile));
                var s         = getParams.Split(new[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                @params  = s.Take(6).Select(i => double.Parse(i, CultureInfo.InvariantCulture)).ToArray();
                td       = int.Parse(s[6]);
                wr       = double.Parse(s[7]);
                stpthrsh = double.Parse(s[8]);
                alg      = s[9];
                type     = s[10];
                if (type.Equals("sim"))
                {
                    sn       = int.Parse(s[11]);
                    alpha[0] = double.Parse(s[12]);
                    alpha[1] = double.Parse(s[13]);
                }
                else if (type.Equals("dp"))
                {
                    prec  = int.Parse(s[11]);
                    rfMax = double.Parse(s[12]);
                }
            }
            catch (Exception ex)
            {
                Trace.Write("ERROR: Could not read file: ");
                Trace.WriteLine(Path.Combine(rootdir, Config.ControlFile) + $". {ex.Message}");
                Trace.WriteLine("EXITING...main()...");
                Console.Read();
                Environment.Exit(1);
            }


            // Read initial glide-path from file.
            var gp = new double[td];

            var gpPath = Path.Combine(rootdir, Config.InitGladepathFile);

            try
            {
                gp = File.ReadAllLines(gpPath).Select(double.Parse)
                     .Take(td).ToArray();
            }
            catch (Exception ex)
            {
                Trace.Write("ERROR: Could not read file: ");
                Trace.WriteLine(gpPath + ". Error: " + ex.Message);
                Trace.WriteLine("EXITING...main()...");
                Console.Read();
                Environment.Exit(1);
            }

            if (gp.Length != td)
            {
                Trace.Write("ERROR: File: ");
                Trace.Write(gpPath);
                Trace.Write(" needs ");
                Trace.Write(td);
                Trace.WriteLine(" initial asset allocations, but has fewer.");
                Trace.WriteLine("EXITING...main()...");
                Console.Read();
                Environment.Exit(1);
            }

            // Display optimization algorithm.
            Trace.Write(@"===> Optimization algorithm: ");
            if (alg == "nr")
            {
                Trace.WriteLine(@"Newton's Method");
            }
            else if (alg == "ga")
            {
                Trace.WriteLine(@"Gradient Ascent");
            }

            // Display estimation method.
            Trace.WriteLine("");
            Trace.Write(@"===> Estimation method: ");
            if (type == "sim")
            {
                Trace.WriteLine(@"Simulation");
            }
            else if (type == "dp")
            {
                Trace.WriteLine(@"Dynamic Program");
                pllproc = 4 * pllproc;
            }

            // Declare variables that depend on data read from the control file for sizing.
            double[,] hess;
            double[] ngrdnt = new double[td];
            EigenvalueDecomposition hevals;

            var grad = new double[td];

            // Take some steps (1 full iteration but no more than 50 steps) in the direction of steepest ascent. This can move us off
            // the boundary region where computations may be unstable (infinite), especially when constructing the Hessian for Newton's method.
            // Also, this initial stepping usually makes improvements very quickly before proceeding with the optimization routine.
            double probnr = GetPNR.Run(type, @params, gp, td, wr, 4 * sn, (int)(rfMax * prec), prec, prtls, pllproc);

            Trace.WriteLine("");
            Trace.WriteLine("Initial Glide-Path (w/Success Probability):");
            WrtAry.Run(probnr, gp, "GP", td);
            for (int s = 1; s <= 2; ++s)
            {
                maxgrad = BldGrad.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, probnr, 4 * sn, alpha[1], pllproc, grad);
                if (maxgrad <= stpthrsh)
                {
                    Trace.Write("The glide-path supplied satisfies the EPSILON convergence criteria: ");
                    Trace.WriteLine($"{maxgrad:F15} vs. {stpthrsh:F15}");
                    s = s + 1;
                }
                else if (s != 2)
                {
                    probnr = Climb.Run(type, @params, gp, td, wr, 2 * sn, (int)(rfMax * prec), prec, pllproc, maxgrad,
                                       probnr, 4 * sn, grad, alpha[0], 50);
                    Trace.WriteLine("");
                    Trace.WriteLine("New (Post Initial Climb) Glide-Path (w/Success Probability):");
                    WrtAry.Run(probnr, gp, "GP", td);
                }
                else if (maxgrad <= stpthrsh)
                {
                    Trace.Write("The glide-path supplied satisfies the EPSILON convergence criteria after intial climb without iterating: ");
                    Trace.WriteLine($"{maxgrad:F15} vs. {stpthrsh:F15}");
                }
            }

            // Negate the gradient if using NR method.
            if (alg == "nr")
            {
                for (int y = 0; y < td; ++y)
                {
                    ngrdnt[y] = -1.00 * grad[y];
                }
            }

            // If convergence is not achieved after initial climb then launch into full iteration mode.
            while (maxgrad > stpthrsh)
            {
                Trace.WriteLine("");
                Trace.WriteLine("=========================");
                Trace.WriteLine($"Start Iteration #{iterint}");
                Trace.WriteLine("=========================");
                if (alg == "nr")
                {
                    // Record the probability before iterating.
                    double strtpnr = probnr;

                    // Build the Hessian matrix for this glide-path and derive its eigenvalues. (Display the largest & smallest value.)
                    // This is required when method=nr. When either procedure ends with convergence we recompute the Hessian matrix to
                    // ensure we are at a local/global maximum (done below after convergence).
                    hess = DrvHess.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, pllproc, grad, probnr);
                    //hevals.compute(hess, false);
                    hevals = new EigenvalueDecomposition(hess);

                    var reals = hevals.RealEigenvalues;
                    maxeigen = reals.Max();
                    mineigen = reals.Min();

                    // Display the smallest/largest eigenvalues.
                    Trace.WriteLine("");
                    Trace.Write("Min Hessian eigenvalue for this iteration (>=0.00 --> convex region): ");
                    Trace.WriteLine(mineigen);
                    Trace.WriteLine("");
                    Trace.Write("Max Hessian eigenvalue for this iteration (<=0.00 --> concave region): ");
                    Trace.WriteLine(maxeigen);

                    // Update the glidepath and recompute the probability using the new glidepath.
                    //sol = hess.colPivHouseholderQr().solve(ngrdnt);
                    var qr  = new QrDecomposition(hess);
                    var sol = qr.Solve(ngrdnt);

                    for (int y = 0; y < td; ++y)
                    {
                        gp[y] += sol[y];
                    }
                    probnr = GetPNR.Run(type, @params, gp, td, wr, 4 * sn, (int)(rfMax * prec), prec, prtls, pllproc);

                    // If success probability has worsened alert the user.
                    if (probnr < strtpnr)
                    {
                        Trace.WriteLine("");
                        Trace.WriteLine("NOTE: The success probability has worsened during the last iteration. This could happen for different reasons:");
                        Trace.WriteLine(" 1.) The difference in probabilities is beyond the system's ability to measure accurately (i.e., beyond 15 significant digits).");
                        Trace.WriteLine(" 2.) The difference is due to estimation/approximation error.");
                        Trace.WriteLine(" 3.) You may be operating along the boundary region. In general the procedure is not well defined on the boundaries. (Try gradient ascent.)");
                    }
                }
                else if (alg == "ga")
                {
                    // Update the glide-path and recompute the probability using the new glide-path.
                    probnr = Climb.Run(type, @params, gp, td, wr, 2 * sn, (int)(rfMax * prec), prec, pllproc, maxgrad,
                                       probnr, 4 * sn, grad, alpha[0]);
                }

                // Display the new glide-path.
                Trace.WriteLine("");
                Trace.Write("New Glide-Path:");
                WrtAry.Run(probnr, gp, "GP", td);

                // Rebuild the gradient and negate it when using NR.
                maxgrad = BldGrad.Run(type, @params, gp, td, wr, 1 * sn, (int)(rfMax * prec), prec, probnr,
                                      4 * sn, alpha[1], pllproc, grad);
                if (alg == "nr")
                {
                    for (int y = 0; y < td; ++y)
                    {
                        ngrdnt[y] = -1.00 * grad[y];
                    }
                }
                // Report the convergence status.
                Trace.WriteLine("");
                Trace.WriteLine($"EPSILON Convergence Criteria: {maxgrad:F15} vs. {stpthrsh:F15}");
                if (maxgrad <= stpthrsh)
                {
                    Trace.WriteLine("");
                    Trace.WriteLine("==========> EPSILON Convergence criteria satisfied. <==========");
                }
                Trace.WriteLine("");
                Trace.WriteLine(new String('=', 25));
                Trace.Write("End Iteration #");
                Trace.WriteLine(iterint);
                Trace.WriteLine(new String('=', 25));
                iterint++;
            }

            // Build Hessian and confirm we are at a maximum, not a saddle-point or plateau for example.
            Trace.WriteLine("");
            Trace.WriteLine("Convergence Achieved: Final step is to confirm we are at a local/global maximum. Hessian is being built.");
            hess = DrvHess.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, pllproc, grad, probnr);

            hevals = new EigenvalueDecomposition(hess);
            var r = hevals.RealEigenvalues;

            maxeigen = r.Max();
            mineigen = r.Min();

            // Display the smallest/largest eigenvalues.
            Trace.WriteLine("");
            Trace.Write("Min Hessian eigenvalue at solution [>=0.00 --> convex region --> (local/global) minimum]: ");
            Trace.WriteLine(mineigen);
            Trace.WriteLine("");
            Trace.Write("Max Hessian eigenvalue at solution [<=0.00 --> concave region --> (local/global) maximum]: ");
            Trace.WriteLine(maxeigen);

            // Write final GP to the output file.
            Trace.WriteLine("");
            if (maxeigen <= 0 || mineigen >= 0)
            {
                Trace.Write("(Local/Global) Optimal ");
            }
            Trace.WriteLine("Glide-Path:");
            WrtAry.Run(probnr, gp, "GP", td, Path.Combine(rootdir, Config.Outfile));
            Trace.WriteLine("");
        }