Пример #1
0
        public void T01_BasicLinearEquations()
        {
            const double Accuracy = 2.2205e-15, SvdAccuracy = 4.46e-15, DeterminantAccuracy = 1.2e-13;

            // given w=-1, x=2, y=-3, and z=4...
            // w - 2x + 3y - 5z = -1 - 4 - 9 - 20 = -34
            // w + 2x + 3y + 5z = -1 + 4 - 9 + 20 = 14
            // 5w - 3x + 2y - z = -5 - 6 - 6 - 4  = -21
            // 5w + 3x + 2y + z = -5 + 6 - 6 + 4  = -1
            double[] coefficientArray = new double[16]
            {
                1, -2, 3, -5,
                1, 2, 3, 5,
                5, -3, 2, -1,
                5, 3, 2, 1,
            };
            double[] valueArray = new double[4] {
                -34, 14, -21, -1
            };

            // first solve using Gauss-Jordan elimination
            Matrix4 coefficients = new Matrix4(coefficientArray);
            Matrix  gjInverse, values = new Matrix(valueArray, 1);
            Matrix  solution = GaussJordan.Solve(coefficients.ToMatrix(), values, out gjInverse);

            CheckSolution(solution, Accuracy);
            CheckSolution(gjInverse * values, Accuracy); // make sure multiplying by the matrix inverse also gives the right answer

            // then solve using LU decomposition
            LUDecomposition lud = new LUDecomposition(coefficients.ToMatrix());

            solution = lud.Solve(values);
            CheckSolution(solution, Accuracy);
            CheckSolution(lud.GetInverse() * values, Accuracy); // check that the inverse can be multiplied to produce a good solution

            solution.Multiply(1.1);                             // mess up the solution
            lud.RefineSolution(values, solution);               // test that refinement can fix it
            CheckSolution(solution, Accuracy);

            // check that the computed determinants are what we expect
            bool negative;

            Assert.AreEqual(coefficients.GetDeterminant(), lud.GetDeterminant(), DeterminantAccuracy);
            Assert.AreEqual(Math.Log(Math.Abs(coefficients.GetDeterminant())), lud.GetLogDeterminant(out negative), Accuracy);
            Assert.AreEqual(coefficients.GetDeterminant() < 0, negative);

            // check that the inverses are about the same from both methods
            Assert.IsTrue(gjInverse.Equals(lud.GetInverse(), Accuracy));

            // then solve using QR decomposition
            QRDecomposition qrd = new QRDecomposition(coefficients.ToMatrix());

            solution = qrd.Solve(values);
            CheckSolution(solution, Accuracy);
            CheckSolution(qrd.GetInverse() * values, Accuracy); // check that the inverse can be multiplied to produce a good solution
            // TODO: test qrd.Update()

            // finally, try solving using singular value decomposition
            SVDecomposition svd = new SVDecomposition(coefficients.ToMatrix());

            solution = svd.Solve(values);
            CheckSolution(solution, SvdAccuracy);
            CheckSolution(svd.GetInverse() * values, SvdAccuracy);
            Assert.IsTrue(gjInverse.Equals(svd.GetInverse(), Accuracy));
            Assert.AreEqual(4, svd.GetRank());
            Assert.AreEqual(0, svd.GetNullity());
        }