Beispiel #1
0
        public static void test_SparseCG_Precond()
        {
            // A test case where Jacobi preconditioner (ie M = diag(A)) provides some improvement
            // described in http://www.math.iit.edu/~fass/477577_Chapter_16.pdf

            int N = 10000;
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            double[] B = new double[N];
            for (int i = 0; i < N; ++i)
            {
                for (int j = i; j < N; ++j)
                {
                    if (i == j)
                    {
                        M.Set(i, i, 0.5 + Math.Sqrt(i));
                    }
                    else if (Math.Abs(i - j) == 1)
                    {
                        M.Set(i, j, 1);
                    }
                    else if (Math.Abs(i - j) == 100)
                    {
                        M.Set(i, j, 1);
                    }
                }
                B[i] = 1;
            }

            SparseSymmetricCG Solver = new SparseSymmetricCG()
            {
                B = B, MultiplyF = M.Multiply
            };

            Solver.Solve();
            double[] BTest = new double[N];
            M.Multiply(Solver.X, BTest);
            double diff = BufferUtil.DistanceSquared(B, BTest);

            if (diff > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: initial solve failed!");
            }

            PackedSparseMatrix PackedM = new PackedSparseMatrix(M);

            PackedM.Sort();
            SparseSymmetricCG Solver_PackedM = new SparseSymmetricCG()
            {
                B = B, MultiplyF = PackedM.Multiply
            };

            Solver_PackedM.Solve();
            PackedM.Multiply(Solver_PackedM.X, BTest);
            double diff_packed = BufferUtil.DistanceSquared(B, BTest);

            if (diff_packed > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: Packed solve failed!");
            }

#if false
            SparseCholeskyDecomposition cholDecomp = new SparseCholeskyDecomposition(PackedM);
            cholDecomp.ComputeIncomplete();

            // factorization is filled with NaNs!! doing something wrong.

            double[] TmpX = new double[N], Y = new double[N];
            cholDecomp.Solve(BTest, TmpX, Y);

            // note: can also try just lower-triangular matrix - this is (L+D), Gauss-Seidel preconditioner?
            //   see http://www.math.iit.edu/~fass/477577_Chapter_16.pdf

            Action <double[], double[]> cholPrecond = (R, Z) => {
                cholDecomp.Solve(R, Z, Y);
            };

            SymmetricSparseMatrix diagPrecond = new SymmetricSparseMatrix(N);
            for (int k = 0; k < N; ++k)
            {
                diagPrecond[k, k] = 1.0 / M[k, k];
            }

            SparseSymmetricCG Solver_Precond = new SparseSymmetricCG()
            {
                B = B, MultiplyF = PackedM.Multiply, PreconditionMultiplyF = diagPrecond.Multiply
            };
            //SparseSymmetricCG Solver_Precond = new SparseSymmetricCG() { B = B, MultiplyF = PackedM.Multiply, PreconditionMultiplyF = cholPrecond };
            Solver_Precond.SolvePreconditioned();
            PackedM.Multiply(Solver_Precond.X, BTest);
            double diff_precond = BufferUtil.DistanceSquared(B, BTest);
            if (diff_precond > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: cholesky-preconditioned solve failed!");
            }

            System.Console.WriteLine("Iterations regular {0}  precond {1}", Solver_PackedM.Iterations, Solver_Precond.Iterations);
            System.Console.WriteLine("Tol regular {0}  precond {1}", diff_packed, diff_precond);
#endif
        }
Beispiel #2
0
        public static void test_Matrices()
        {
            int N = 200;
            //int N = 2500;
            DenseMatrix           M1 = new DenseMatrix(N, N);
            SymmetricSparseMatrix M2 = new SymmetricSparseMatrix();

            for (int i = 0; i < N; ++i)
            {
                for (int j = i; j < N; ++j)
                {
                    if (i == j)
                    {
                        M1.Set(i, i, N);
                        M2.Set(i, i, N);
                    }
                    else if (j % 2 != 0)
                    {
                        double d = 1.0 / Math.Sqrt(i + j);
                        M1.Set(i, j, d);
                        M1.Set(j, i, d);
                        M2.Set(i, j, d);
                    }
                }
            }


            double[] X = new double[N], b1 = new double[N], b2 = new double[N];
            for (int i = 0; i < N; ++i)
            {
                X[i] = (double)i / (double)N;
            }

            M1.Multiply(X, b1);
            M2.Multiply(X, b2);

            for (int i = 0; i < N; ++i)
            {
                Debug.Assert(MathUtil.EpsilonEqual(b1[i], b2[i]));
            }

            Debug.Assert(M1.IsSymmetric());
            Debug.Assert(M1.IsPositiveDefinite());

            // test parallel cholesky decomposition

            LocalProfiler p = new LocalProfiler();

            p.Start("chol");
            CholeskyDecomposition decompM = new CholeskyDecomposition(M1);

            decompM.ComputeParallel();
            p.Stop("chol");
            //System.Console.WriteLine(p.AllTimes());

            DenseMatrix LLT_M1 = decompM.L.Multiply(decompM.L.Transpose());

            if (LLT_M1.EpsilonEquals(M1) == false)
            {
                System.Console.WriteLine("FAIL  choleskyM1 did not reproduce input");
            }

            // test cholesky-decomp backsubstitution

            Random r = new Random(31337);

            double[] RealX = TestUtil.RandomScalars(N, r, new Interval1d(-10, 10));
            double[] B     = new double[N], SolvedX = new double[N], TmpY = new double[N];
            M1.Multiply(RealX, B);
            decompM.Solve(B, SolvedX, TmpY);
            if (BufferUtil.DistanceSquared(RealX, SolvedX) > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("FAIL choleskyM1 backsubstution did not reproduce input vector");
            }


            // test case from: https://people.cs.kuleuven.be/~karl.meerbergen/didactiek/h03g1a/ilu.pdf
            //DenseMatrix tmp = new DenseMatrix(6, 6);
            //tmp.Set(new double[] {
            //    3,0,-1,-1,0,-1,
            //    0,2,0,-1,0,0,
            //    -1,0,3,0,-1,0,
            //    -1,-1,0,2,0,-1,
            //    0,0,-1,0,3,-1,
            //    -1,0,0,-1,-1,4});
            //CholeskyDecomposition decompDense = new CholeskyDecomposition(tmp);
            //decompDense.Compute();
            //PackedSparseMatrix M1_sparse = PackedSparseMatrix.FromDense(tmp, true);
            //M1_sparse.Sort();
            //SparseCholeskyDecomposition decompM1_sparse = new SparseCholeskyDecomposition(M1_sparse);
            //decompM1_sparse.ComputeIncomplete();


            // cholesky decomposition known-result test
            DenseMatrix MSym3x3 = new DenseMatrix(3, 3);

            MSym3x3.Set(new double[] { 25, 15, -5, 15, 18, 0, -5, 0, 11 });
            DenseMatrix MSym3x3_Chol = new DenseMatrix(3, 3);

            MSym3x3_Chol.Set(new double[] { 5, 0, 0, 3, 3, 0, -1, 1, 3 });
            CholeskyDecomposition decomp3x3 = new CholeskyDecomposition(MSym3x3);

            decomp3x3.Compute();
            if (decomp3x3.L.EpsilonEquals(MSym3x3_Chol) == false)
            {
                System.Console.WriteLine("FAIL  cholesky3x3 incorrect result");
            }
            if (decomp3x3.L.Multiply(decomp3x3.L.Transpose()).EpsilonEquals(MSym3x3) == false)
            {
                System.Console.WriteLine("FAIL  cholesky3x3 did not reproduce input");
            }

            // cholesky decomposition known-result test
            DenseMatrix MSym4x4 = new DenseMatrix(4, 4);

            MSym4x4.Set(new double[] {
                18, 22, 54, 42, 22, 70, 86, 62,
                54, 86, 174, 134, 42, 62, 134, 106
            });
            DenseMatrix MSym4x4_Chol = new DenseMatrix(4, 4);

            MSym4x4_Chol.Set(new double[] {
                4.24264, 0, 0, 0, 5.18545, 6.56591, 0, 0,
                12.72792, 3.04604, 1.64974, 0, 9.89949, 1.62455, 1.84971, 1.39262
            });
            CholeskyDecomposition decomp4x4 = new CholeskyDecomposition(MSym4x4);

            decomp4x4.Compute();
            if (decomp4x4.L.EpsilonEquals(MSym4x4_Chol, 0.0001) == false)
            {
                System.Console.WriteLine("FAIL  cholesky4x4 incorrect result");
            }
            if (decomp4x4.L.Multiply(decomp4x4.L.Transpose()).EpsilonEquals(MSym4x4) == false)
            {
                System.Console.WriteLine("FAIL  cholesky4x4 did not reproduce input");
            }
        }
Beispiel #3
0
        public static void test_SparseCG()
        {
            Random r = new Random(31337);

            int N   = 100;
            var pts = TestUtil.RandomScalars(N, r, new Interval1d(1, 10));
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            double[] B = new double[N];
            for (int i = 0; i < N; ++i)
            {
                for (int j = i; j < N; ++j)
                {
                    if (i == j)
                    {
                        M.Set(i, j, pts[i]);
                    }
                    else
                    {
                        M.Set(i, j, (double)(i + j) / 10.0);
                    }
                }
                B[i] = i + 1;
            }

            SparseSymmetricCG Solver = new SparseSymmetricCG()
            {
                B = B, MultiplyF = M.Multiply
            };

            Solver.Solve();
            double[] BTest = new double[N];
            M.Multiply(Solver.X, BTest);
            double diff = BufferUtil.DistanceSquared(B, BTest);

            if (diff > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: initial solve failed!");
            }

            PackedSparseMatrix PackedM = new PackedSparseMatrix(M);

            PackedM.Sort();
            SparseSymmetricCG Solver_PackedM = new SparseSymmetricCG()
            {
                B = B, MultiplyF = PackedM.Multiply
            };

            Solver_PackedM.Solve();
            PackedM.Multiply(Solver_PackedM.X, BTest);
            double diff_packed = BufferUtil.DistanceSquared(B, BTest);

            if (diff_packed > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: Packed solve failed!");
            }

#if false
            SparseCholeskyDecomposition decomp = new SparseCholeskyDecomposition(PackedM);
            decomp.ComputeIncomplete();
            PackedSparseMatrix choleskyPrecond = decomp.L.Square();

            SymmetricSparseMatrix diagPrecond = new SymmetricSparseMatrix(N);
            for (int k = 0; k < N; ++k)
            {
                diagPrecond[k, k] = 1.0 / M[k, k];
            }

            SparseSymmetricCG Solver_Precond = new SparseSymmetricCG()
            {
                B = B, MultiplyF = PackedM.Multiply, PreconditionMultiplyF = diagPrecond.Multiply
            };
            Solver_Precond.SolvePreconditioned();
            PackedM.Multiply(Solver_Precond.X, BTest);
            double diff_precond = BufferUtil.DistanceSquared(B, BTest);
            if (diff_precond > MathUtil.ZeroTolerance)
            {
                System.Console.WriteLine("test_SparseCG: cholesky-preconditioned solve failed!");
            }

            System.Console.WriteLine("Iterations regular {0}  precond {1}", Solver_PackedM.Iterations, Solver_Precond.Iterations);
            System.Console.WriteLine("Tol regular {0}  precond {1}", diff_packed, diff_precond);
#endif
        }