예제 #1
0
        private static DataTable ToDataTable(ACQ.Math.Linalg.Matrix matrix)
        {
            DataTable table = new DataTable(matrix.GetType().ToString());

            DataColumn column;
            DataRow    row;

            string[] cnames = new string[matrix.Columns];
            // Create new DataColumn, set DataType,
            // ColumnName and add to DataTable.
            for (int i = 0; i < matrix.Columns; i++)
            {
                cnames[i]         = i.ToString();
                column            = new DataColumn();
                column.DataType   = System.Type.GetType("System.Double");
                column.ColumnName = cnames[i];
                column.ReadOnly   = true;
                table.Columns.Add(column);
            }

            // Create three new DataRow objects and add
            // them to the DataTable
            for (int i = 0; i < matrix.Rows; i++)
            {
                row = table.NewRow();
                for (int j = 0; j < matrix.Columns; j++)
                {
                    row[cnames[j]] = matrix[i, j];
                }
                table.Rows.Add(row);
            }
            return(table);
        }
예제 #2
0
        public RbfInterpolation1D(double[] x, double[] y, enRadialBasisFunction basisFunction, double scale, double smooth)
            : base(x, y, true)
        {
            m_basisFunction = RadialBasisFunction.CreateRadialBasisFunction(basisFunction);
            m_scale         = scale;

            int n = x.Length;

            if (n > m_sizeLimit)
            {
                throw new ArgumentOutOfRangeException(String.Format("RbfInterpolation1D does not support more than {0} nodes", m_sizeLimit));
            }

            ACQ.Math.Linalg.Matrix A   = new ACQ.Math.Linalg.Matrix(n + 2, n + 2);
            ACQ.Math.Linalg.Matrix rhs = new ACQ.Math.Linalg.Matrix(n + 2, 1);

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    double r    = System.Math.Abs((x[i] - x[j]) / m_scale);
                    double func = m_basisFunction[r];
                    A[i, j] = func;
                    A[j, i] = func;
                }
                A[i, i]   = A[i, i] - smooth;
                rhs[i, 0] = y[i];
            }

            //Linear Polynomial part
            for (int i = 0; i < n; i++)
            {
                A[i, n]     = 1;
                A[i, n + 1] = x[i] / m_scale;

                A[n, i]     = 1;
                A[n + 1, i] = x[i] / m_scale;
            }

            ACQ.Math.Linalg.Matrix res = A.Solve(rhs);

            m_a = new double[n + 2];

            for (int i = 0; i < res.Rows; i++)
            {
                m_a[i] = res[i, 0];
            }
        }
예제 #3
0
        public static void TestLinearAlgebra()
        {
            double eps = ACQ.Math.Const.epsilon;

            //test magic matrices
            for (int n = 3; n <= 32; n++)
            {
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateMagic(n);

                double trace = M.Trace(); // trace   = diagonal sum, should be the magic sum, (n^3 + n)/2.

                ACQ.Math.Linalg.EigenvalueDecomposition E = new ACQ.Math.Linalg.EigenvalueDecomposition(0.5 * (M + (M.Transpose())));
                double[] d = E.GetRealEigenvalues();    //maximum eigenvalue of (A + A')/2, should equal trace

                //int r = M.rank();   //should equal n if n is odd, be less than n if n is even
                //double c = M.cond();

                ACQ.Math.Linalg.LuDecomposition LU = new ACQ.Math.Linalg.LuDecomposition(M);
                ACQ.Math.Linalg.Matrix          L  = LU.GetL();
                ACQ.Math.Linalg.Matrix          U  = LU.GetU();
                int[] p = LU.GetPivotIndex();
                ACQ.Math.Linalg.Matrix R = L * U - M.Submatrix(p, 0, n - 1);
                double lu_res            = R.Norm1();

                ACQ.Math.Linalg.QrDecomposition QR = new ACQ.Math.Linalg.QrDecomposition(M);
                ACQ.Math.Linalg.Matrix          Q  = QR.GetQ();
                R = QR.GetR();
                R = Q * R - M;
                double qr_res = R.Norm1();

                ACQ.Math.Linalg.SvDecomposition SV = new ACQ.Math.Linalg.SvDecomposition(M);
                U = SV.GetU();
                ACQ.Math.Linalg.Matrix S = SV.GetS();
                ACQ.Math.Linalg.Matrix V = SV.GetV();
                R = U * S * V.Transpose() - M;
                double sv_res = R.Norm1();
                double rank   = SV.Rank();
                double cond   = SV.Cond();

                Console.WriteLine("n:{0,3} trace:{1:E4} ev:{2:E4} lu:{3:E4} qr:{4:E4} sv:{5:E4}", n, trace, d[d.Length - 1], lu_res, qr_res, sv_res);
            }

            //test random matrices
            ACQ.Math.Random.IRandomGenerator rng = new ACQ.Math.Random.MersenneTwister();

            for (int n = 1; n <= 8; n++)
            {
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(n, n, rng);

                ACQ.Math.Linalg.SvDecomposition SV   = new ACQ.Math.Linalg.SvDecomposition(M);
                ACQ.Math.Linalg.Matrix          U    = SV.GetU();
                ACQ.Math.Linalg.Matrix          S    = SV.GetS();
                ACQ.Math.Linalg.Matrix          V    = SV.GetV();
                ACQ.Math.Linalg.Matrix          R    = U * S * V.Transpose() - M;
                ACQ.Math.Linalg.Matrix          pinv = SV.PseudoInverse();
                double pinv_res1 = (M * pinv * M - M).Norm1();
                double pinv_res2 = (pinv * M * pinv - pinv).Norm1();
                double sv_res    = R.Norm1();
                double rank      = SV.Rank();
                double cond      = SV.Cond();

                Console.WriteLine("n:{0,3} rank:{1:E4} cond:{2:E4} sv:{3:E4} pinv:{4:E4} {5:E4}", n, rank, cond, sv_res, pinv_res1, pinv_res2);
            }

            //non square matrixes, m > n
            for (int n = 1; n <= 32; n++)
            {
                for (int m = n; m <= 32; m++)
                {
                    ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(m, n, rng);

                    double err_scale = 1.0 / (System.Math.Max(m, n) * eps);
                    ACQ.Math.Linalg.SvDecomposition SV   = new ACQ.Math.Linalg.SvDecomposition(M);
                    ACQ.Math.Linalg.Matrix          U    = SV.GetU();
                    ACQ.Math.Linalg.Matrix          S    = SV.GetS();
                    ACQ.Math.Linalg.Matrix          V    = SV.GetV();
                    ACQ.Math.Linalg.Matrix          R    = U * S * V.Transpose() - M;
                    ACQ.Math.Linalg.Matrix          pinv = SV.PseudoInverse();
                    double pinv_res1 = (M * pinv * M - M).Norm1() * err_scale;
                    double pinv_res2 = (pinv * M * pinv - pinv).Norm1() * err_scale;
                    double sv_res    = R.Norm1() * err_scale;
                    double rank      = SV.Rank();
                    double cond      = SV.Cond();

                    Console.WriteLine("{0} x {1}, rank:{2:F4}, cond:{3:F4}, sv:{4:F4}, pinv:{5:F4}, {6:F4}", m, n, rank, cond, sv_res, pinv_res1, pinv_res2);
                }
            }

            //linear systems: square with full rank
            for (int n = 1; n <= 32; n++)
            {
                int m = 10;
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(n, n, rng);
                ACQ.Math.Linalg.Matrix B = new Math.Linalg.Matrix(n, m);

                for (int i = 0; i < M.Rows; i++)
                {
                    double sum = 0;
                    for (int j = 0; j < M.Columns; j++)
                    {
                        sum += M[i, j];
                    }

                    for (int k = 0; k < B.Columns; k++)
                    {
                        B[i, k] = sum * (k + 1);
                    }
                }

                double err_scale = 1.0 / (n * eps);

                ACQ.Math.Linalg.SvDecomposition SV = new ACQ.Math.Linalg.SvDecomposition(M);
                ACQ.Math.Linalg.Matrix          X1 = SV.Solve(B);
                ACQ.Math.Linalg.Matrix          X2 = SV.PseudoInverse() * B;
                double sv_res1 = (M * X1 - B).Norm1() * err_scale;
                double sv_res2 = (M * X2 - B).Norm1() * err_scale;

                ACQ.Math.Linalg.LuDecomposition LU = new ACQ.Math.Linalg.LuDecomposition(M);
                X1 = LU.Solve(B);
                double lu_res1 = (M * X1 - B).Norm1() * err_scale;

                ACQ.Math.Linalg.QrDecomposition QR = new ACQ.Math.Linalg.QrDecomposition(M);
                X1 = QR.Solve(B);
                double qr_res1 = (M * X1 - B).Norm1() * err_scale;

                Console.WriteLine("{0}, svd:{1:F4}, sv:{2:F4} lu:{3:F4} qr:{4:F4}", n, sv_res1, sv_res2, lu_res1, qr_res1);
            }

            //linear systems: symmetric with full rank
            for (int n = 1; n <= 32; n++)
            {
                int m = 10;
                ACQ.Math.Linalg.Matrix A = ACQ.Math.Linalg.Matrix.CreateRandom(n, n, rng);
                ACQ.Math.Linalg.Matrix M = A * A.Transpose();
                ACQ.Math.Linalg.Matrix B = new Math.Linalg.Matrix(n, m);

                for (int i = 0; i < M.Rows; i++)
                {
                    double sum = 0;
                    for (int j = 0; j < M.Columns; j++)
                    {
                        sum += M[i, j];
                    }

                    for (int k = 0; k < B.Columns; k++)
                    {
                        B[i, k] = sum * (k + 1);
                    }
                }

                ACQ.Math.Linalg.SvDecomposition SV = new ACQ.Math.Linalg.SvDecomposition(M);
                ACQ.Math.Linalg.Matrix          X1 = SV.Solve(B);
                ACQ.Math.Linalg.Matrix          X2 = SV.PseudoInverse() * B;
                double sv_res1 = (M * X1 - B).Norm1();
                double sv_res2 = (M * X2 - B).Norm1();

                ACQ.Math.Linalg.LuDecomposition LU = new ACQ.Math.Linalg.LuDecomposition(M);
                X1 = LU.Solve(B);
                double lu_res1 = (M * X1 - B).Norm1();

                ACQ.Math.Linalg.QrDecomposition QR = new ACQ.Math.Linalg.QrDecomposition(M);
                X1 = QR.Solve(B);
                double qr_res1 = (M * X1 - B).Norm1();

                ACQ.Math.Linalg.CholeskyDecomposition CD = new ACQ.Math.Linalg.CholeskyDecomposition(M);
                X1 = CD.Solve(B);
                double cd_res1 = (M * X1 - B).Norm1();

                Console.WriteLine("{0,3}, sv:{1:E4} pinv:{2:E4} lu:{3:E4} qr:{4:E4}, cd:{5:E4}", n, sv_res1, sv_res2, lu_res1, qr_res1, cd_res1);
            }

            ACQ.Math.Random.IRandomGenerator rnorm = new ACQ.Math.Random.BoxMuller(rng);

            //linear systems: overdetermined, full rank (least squares solution)
            for (int n = 1; n <= 32; n++)
            {
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(2 * n, n, rnorm);
                ACQ.Math.Linalg.Matrix B = ACQ.Math.Linalg.Matrix.CreateRandom(2 * n, 1, rnorm);

                for (int i = 0; i < M.Rows; i++)
                {
                    double sum = 0;
                    for (int k = 0; k < M.Columns; k++)
                    {
                        sum += M[i, k];
                    }
                    B[i, 0] = sum + 0.1 * B[i, 0];
                }

                ACQ.Math.Linalg.SvDecomposition SV  = new ACQ.Math.Linalg.SvDecomposition(M);
                ACQ.Math.Linalg.Matrix          Xsv = SV.Solve(B);
                double sv_res1 = (M * Xsv - B).Norm1();

                ACQ.Math.Linalg.QrDecomposition QR  = new ACQ.Math.Linalg.QrDecomposition(M);
                ACQ.Math.Linalg.Matrix          Xqr = QR.Solve(B);
                double qr_res1 = (M * Xqr - B).Norm1();

                double res = (Xsv - Xqr).Norm1();

                Console.WriteLine("{0,3}, sv:{1:E4} qr:{2:E4} res:{3:E4}", n, sv_res1, qr_res1, res);
            }

            //linear systems: overdetermined but not full rank (least squares solution),
            //QR does not work in this case,
            for (int n = 1; n <= 32; n++)
            {
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(2 * n, n + 1, rnorm);
                ACQ.Math.Linalg.Matrix B = ACQ.Math.Linalg.Matrix.CreateRandom(2 * n, 1, rnorm);

                for (int i = 0; i < M.Rows; i++)
                {
                    M[i, n] = M[i, n - 1];//dublicate column
                    double sum = 0;
                    for (int k = 0; k < M.Columns; k++)
                    {
                        sum += M[i, k];
                    }
                    B[i, 0] = sum + 0.1 * B[i, 0];
                }

                //solution shold be approximatly all ones, last two values should be the same
                //condition number is large (infinite actually, sometimes finite because of truncation errors)
                //rank = M.Columns - 1 (i.e. rank = n)
                ACQ.Math.Linalg.SvDecomposition SV  = new ACQ.Math.Linalg.SvDecomposition(M);
                ACQ.Math.Linalg.Matrix          Xsv = SV.Solve(B);
                double sv_res1 = (M * Xsv - B).Norm1();

                ACQ.Math.Linalg.QrDecomposition QR = new ACQ.Math.Linalg.QrDecomposition(M);
                double qr_res1 = Double.NaN;
                double res     = Double.NaN;
                if (QR.IsFullRank)
                {
                    //occasionally QR thinks that matrix is full rank,
                    //but it is poorly conditioned so solution is wrong
                    ACQ.Math.Linalg.Matrix Xqr = QR.Solve(B);
                    qr_res1 = (M * Xqr - B).Norm1();
                    res     = (Xsv - Xqr).Norm1();
                }

                Console.WriteLine("{0,3}, sv:{1:E4} qr:{2:E4} res:{3:E4}", n, sv_res1, qr_res1, res);
            }

            //linear systems: underdetermined (least norm solution)
            for (int n = 1; n <= 32; n++)
            {
                ACQ.Math.Linalg.Matrix M = ACQ.Math.Linalg.Matrix.CreateRandom(n, 2 * n + 1, rnorm);
                ACQ.Math.Linalg.Matrix B = ACQ.Math.Linalg.Matrix.CreateRandom(n, 1, rnorm);

                for (int i = 0; i < M.Rows; i++)
                {
                    M[i, 2 * n] = M[i, 2 * n - 1];//dublicate column
                }

                ACQ.Math.Linalg.SvDecomposition SV  = new ACQ.Math.Linalg.SvDecomposition(M.Transpose());
                ACQ.Math.Linalg.Matrix          Xsv = SV.Solve(B, true); //last two values should be the same
                double sv_res1 = (M * Xsv - B).Norm1();                  //this should be zero
                double x_norm  = Xsv.Norm1();

                Console.WriteLine("{0,3}, sv:{1:E4} xnorm:{2:E4}", n, sv_res1, x_norm);
            }
        }
예제 #4
0
        public RbfInterpolation(double[,] x, double[] y, enRadialBasisFunction basisFunction, double[] scale, double smooth)
            : base(x, y, true)
        {
            int n   = x.GetLength(0);
            int dim = x.GetLength(1);

            if (n > m_sizeLimit)
            {
                throw new ArgumentOutOfRangeException(String.Format("RbfInterpolation does not support more than {0} nodes", m_sizeLimit));
            }

            m_basisFunction = RadialBasisFunction.CreateRadialBasisFunction(basisFunction);

            m_invscale = new double[dim];

            //scale is optional argument, use scale of one if missing
            if (scale == null)
            {
                for (int i = 0; i < m_invscale.Length; i++)
                {
                    m_invscale[i] = 1.0;
                }
            }
            else
            {
                for (int i = 0; i < m_invscale.Length; i++)
                {
                    if (i < scale.Length)
                    {
                        m_invscale[i] = 1.0 / scale[i];
                    }
                    else
                    {
                        m_invscale[i] = 1.0;
                    }
                }
            }


            ACQ.Math.Linalg.Matrix A   = new ACQ.Math.Linalg.Matrix(n + dim + 1, n + dim + 1);
            ACQ.Math.Linalg.Matrix rhs = new ACQ.Math.Linalg.Matrix(n + dim + 1, 1);

            double[] dx = new double[dim];

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    for (int k = 0; k < dim; k++)
                    {
                        dx[k] = (x[i, k] - x[j, k]) * m_invscale[k];
                    }
                    double r    = norm2(dx);
                    double func = m_basisFunction[r];
                    A[i, j] = func;
                    A[j, i] = func;
                }
                A[i, i]   = A[i, i] - smooth;
                rhs[i, 0] = y[i];
            }

            //Linear Polynomial part
            for (int i = 0; i < n; i++)
            {
                A[i, n] = 1;
                A[n, i] = 1;

                for (int j = 0; j < dim; j++)
                {
                    A[i, n + 1 + j] = x[i, j] * m_invscale[j];
                    A[n + 1 + j, i] = x[i, j] * m_invscale[j];
                }
            }

            ACQ.Math.Linalg.Matrix res = A.Solve(rhs);

            m_a = new double[n + dim + 1];

            for (int i = 0; i < res.Rows; i++)
            {
                m_a[i] = res[i, 0];
            }
        }