예제 #1
0
        /// <summary>
        /// Copies the matrix.
        /// </summary>
        /// <returns>An independent copy of the matrix.</returns>
        public SparseSquareMatrix Copy()
        {
            // a simple, slow solution is to create an empty sparse matrix with the same dimension and call
            // set element for each entry; but this moves along each linked list many times

            // we would like to just move along, say, each row, just once, copying the elements we find
            // but that isn't simple, because we need to store pointers to the next in row and next in column,
            // which we don't have on hand as we create the element

            // dealing with the next in row is easy: just keep a reference to the last one we do and
            // set its pointer to the next in row when we create the next element in the row

            // dealing with the next in column is harder; we need to know what is above it in the column,
            // but that was created a long time ago when we were dealing with a previous row.
            // to solve this problem, we use auxiluary storage: a N-element array that stores that last
            // element created in each column. when we create a new element, we hook it up to the previous
            // element stored in that array, then put the new element in the array


            SparseMatrixElement[] copyRows     = new SparseMatrixElement[dimension];
            SparseMatrixElement[] copyColumns  = new SparseMatrixElement[dimension];
            SparseMatrixElement[] lastInColumn = new SparseMatrixElement[dimension];

            for (int r = 0; r < dimension; r++)
            {
                SparseMatrixElement element   = rows[r];
                SparseMatrixElement lastInRow = null;
                while (element != null)
                {
                    // create a copy of the element
                    SparseMatrixElement copyElement = new SparseMatrixElement(element.Row, element.Column, element.Value);
                    // hook it up to the previous one in the row (and store it for the next one)
                    if (lastInRow != null)
                    {
                        lastInRow.NextInRow = copyElement;
                    }
                    else
                    {
                        copyRows[r] = copyElement;
                    }
                    lastInRow = copyElement;
                    // hook it up to the previous one in the column (and store it for the next one)
                    if (lastInColumn[element.Column] != null)
                    {
                        lastInColumn[element.Column].NextInColumn = copyElement;
                    }
                    else
                    {
                        copyColumns[element.Column] = copyElement;
                    }
                    lastInColumn[element.Column] = copyElement;
                    // move to the next element in the row
                    element = element.NextInRow;
                }
            }

            SparseSquareMatrix copy = new SparseSquareMatrix(dimension, copyRows, copyColumns, fill);

            return(copy);
        }
        public void SparseSquareMatrixCopy()
        {
            SparseSquareMatrix A = new SparseSquareMatrix(5);
            A[1, 1] = 1.0;
            A[3, 1] = 2.0;
            A[1, 3] = 3.0;
            A[3, 3] = 4.0;
            A[2, 4] = 5.0;

            // make a copy
            SparseSquareMatrix AC = A.Copy();

            // test that the copy agrees

            Assert.IsTrue(AC.Dimension == A.Dimension);
            Assert.IsTrue(AC.FillCount == A.FillCount);

            Assert.IsTrue(AC[2, 2] == A[2, 2]);
            Assert.IsTrue(AC[3, 3] == A[3, 3]);

            // test the copy's independence

            A[3, 3] += 1.0;
            Assert.IsTrue(AC[3,3] != A[3,3]);

            A[1, 3] = 0.0;
            Assert.IsTrue(AC[1, 3] != A[1, 3]);
            Assert.IsTrue(AC.FillCount != A.FillCount);
        }
        public void SparseSquareMatrixAgreement()
        {
            int d = 6;
            SparseSquareMatrix A = new SparseSquareMatrix(d);
            SquareMatrix B = new SquareMatrix(d);

            Random rng = new Random(1);
            for (int i = 0; i < 2 * d; i++) {
                int r = (int) Math.Floor(rng.NextDouble() * d);
                int c = (int) Math.Floor(rng.NextDouble() * d);
                A[r, c] = 2.0 * rng.NextDouble() - 1.0;
                B[r, c] = A[r, c];
            }

            RowVector u = new RowVector(d);
            ColumnVector v = new ColumnVector(d);
            for (int i = 0; i < d; i++) {
                u[i] = 2.0 * rng.NextDouble() - 1.0;
                v[i] = 2.0 * rng.NextDouble() - 1.0;
            }

            RowVector uA = u * A;
            RowVector uB = u * B;
            Assert.IsTrue(TestUtilities.IsNearlyEqual(uA, uB));

            ColumnVector Av = A * v;
            ColumnVector Bv = B * v;
            Assert.IsTrue(TestUtilities.IsNearlyEqual(Av, Bv));
        }
        public SparseSquareMatrix CreateRandomSparseSquareMatrix(int dim, int fill, Random rng)
        {
            SparseSquareMatrix S = new SparseSquareMatrix(dim);

            for (int i = 0; i < fill; i++) {
                int r = (int)Math.Floor(rng.NextDouble() * dim);
                int c = (int)Math.Floor(rng.NextDouble() * dim);
                S[r, c] = 2.0 * rng.NextDouble() - 1.0;
            }

            return (S);
        }
예제 #5
0
        /// <summary>
        /// Multiplies a sparse matrix by a real scalar.
        /// </summary>
        /// <param name="alpha">The scalar value.</param>
        /// <param name="A">The sparse matrix.</param>
        /// <returns>The product sparse matrix.</returns>
        public static SparseSquareMatrix operator *(double alpha, SparseSquareMatrix A)
        {
            if (A == null)
            {
                throw new ArgumentNullException("A");
            }
            SparseSquareMatrix aA = A.Copy();

            if (alpha == 0.0)
            {
                return(aA);
            }
            for (int r = 0; r < aA.dimension; r++)
            {
                SparseMatrixElement element = aA.rows[r];
                while (element != null)
                {
                    element.Value = alpha * element.Value;
                    // handle the case where alpha != 0, but alpha * element.Value underflows to zero
                    element = element.NextInRow;
                }
            }
            return(aA);
        }
        public void SparseSquareMatrixManipulation()
        {
            // 0 0 0 0 0 0
            // 0 1 0 0 4 0
            // 0 5 0 0 0 0
            // 0 0 0 0 0 0
            // 3 2 0 0 6 0
            // 0 0 0 0 0 0

            SparseSquareMatrix S = new SparseSquareMatrix(6);
            Assert.IsTrue(S.Dimension == 6);
            Assert.IsTrue(S.FillCount == 0);
            Assert.IsTrue(S.FillFraction == 0.0);

            // assign values
            S[1, 1] = 1.0;
            S[4, 1] = 2.0;
            S[4, 0] = 3.0;
            S[1, 4] = 4.0;
            S[2, 1] = 5.0;
            S[4, 4] = 6.0;

            Assert.IsTrue(S[1, 1] == 1.0);
            Assert.IsTrue(S[4, 1] == 2.0);
            Assert.IsTrue(S.FillCount == 6);
            Assert.IsTrue(TestUtilities.IsNearlyEqual(S.FillFraction, 6.0 / 36.0));

            // change a value
            S[4, 4] = 7.0;
            Assert.IsTrue(S[4, 4] == 7.0);
            Assert.IsTrue(S.FillCount == 6);

            // remove a value
            S[4, 1] = 0.0;
            Assert.IsTrue(S[4, 1] == 0.0);
            Assert.IsTrue(S.FillCount == 5);
        }
        public void SparseSquareMatrixSolutionAgreement()
        {
            Random rng = new Random(2);

            int n = 16;
            //for (int n = 8; n < 100; n+= 11) {

                // create dense and sparse matrices with the same entries
                SquareMatrix M = new SquareMatrix(n);
                SparseSquareMatrix S = new SparseSquareMatrix(n);
                for (int r = 0; r < n; r++) {
                    for (int c = 0; c < n; c++) {
                        if (rng.NextDouble() < 0.5) {
                            M[r, c] = rng.NextDouble();
                            S[r, c] = M[r, c];
                        }
                    }
                }

                // pick a RHS
                ColumnVector b = new ColumnVector(n);
                for (int i = 0; i < n; i++) b[i] = rng.NextDouble();

                // solve each
                ColumnVector Mx = M.LUDecomposition().Solve(b);
                ColumnVector Sx = S.Solve(b);

                // the solutions should be the same
                Assert.IsTrue(TestUtilities.IsNearlyEqual(Mx, Sx, TestUtilities.TargetPrecision * 100.0));

            //}
        }
        public void SparseSquareMatrixPotential()
        {
            // An 2D electrostatic boundary value problem in cartesian coordinates
            // A square of length n, with specified constant potentials on each wall
            // Discritized Laplace equation is
            //  u_{x,y-1} + u_{x+1,y} + u_{x,y+1} + u_{x-1,y} - 4 u_{x,y} = 0
            // Number interior points sequentially row-wise i.e. i = x + n * y
            // Points nearest the walls will pick up a boundary value, which because it is not a variable we move to the RHS
            // Points closer to the interior pick up no boundary value, so their RHS is zero

            int n = 100;

            double pn = 0.0; double pe = 1.0; double ps = 0.0; double pw = 1.0;

            SparseSquareMatrix A = new SparseSquareMatrix(n * n);
            ColumnVector b = new ColumnVector(n * n);

            // set up A and b
            for (int y = 0; y < n; y++) {
                for (int x = 0; x < n; x++) {
                    int i = x + n * y;
                    // center value
                    A[i, i] = 4.0;
                    // north
                    if (y == 0) {
                        b[i] += pn;
                    } else {
                        int j = x + n * (y - 1);
                        A[i, j] = -1.0;
                    }
                    // east
                    if (x == (n-1)) {
                        b[i] += pe;
                    } else {
                        int j = (x + 1) + n * y;
                        A[i, j] = -1.0;
                    }
                    // south
                    if (y == (n-1)) {
                        b[i] += ps;
                    } else {
                        int j = x + n * (y + 1);
                        A[i, j] = -1.0;
                    }
                    // west
                    if (x == 0) {
                        b[i] += pw;
                    } else {
                        int j = (x - 1) + n * y;
                        A[i, j] = -1.0;
                    }
                }
            }

            ColumnVector u = A.Solve(b);

            for (int y = 0; y < 10; y++) {
                for (int x = 0; x < 10; x++) {
                    int i = x + n * y;
                    Console.Write("{0} ", u[i]);
                }
                Console.WriteLine();
            }

            Console.WriteLine(PotentialSolution(1, 2, n));
        }
        /// <summary>
        /// Copies the matrix.
        /// </summary>
        /// <returns>An independent copy of the matrix.</returns>
        public SparseSquareMatrix Copy()
        {
            // a simple, slow solution is to create an empty sparse matrix with the same dimension and call
            // set element for each entry; but this moves along each linked list many times

            // we would like to just move along, say, each row, just once, copying the elements we find
            // but that isn't simple, because we need to store pointers to the next in row and next in column,
            // which we don't have on hand as we create the element

            // dealing with the next in row is easy: just keep a reference to the last one we do and
            // set its pointer to the next in row when we create the next element in the row

            // dealing with the next in column is harder; we need to know what is above it in the column,
            // but that was created a long time ago when we were dealing with a previous row.
            // to solve this problem, we use auxiluary storage: a N-element array that stores that last
            // element created in each column. when we create a new element, we hook it up to the previous
            // element stored in that array, then put the new element in the array

            SparseMatrixElement[] copyRows = new SparseMatrixElement[dimension];
            SparseMatrixElement[] copyColumns = new SparseMatrixElement[dimension];
            SparseMatrixElement[] lastInColumn = new SparseMatrixElement[dimension];

            for (int r = 0; r < dimension; r++) {
                SparseMatrixElement element = rows[r];
                SparseMatrixElement lastInRow = null;
                while (element != null) {
                    // create a copy of the element
                    SparseMatrixElement copyElement = new SparseMatrixElement(element.Row, element.Column, element.Value);
                    // hook it up to the previous one in the row (and store it for the next one)
                    if (lastInRow != null) {
                        lastInRow.NextInRow = copyElement;
                    } else {
                        copyRows[r] = copyElement;
                    }
                    lastInRow = copyElement;
                    // hook it up to the previous one in the column (and store it for the next one)
                    if (lastInColumn[element.Column] != null) {
                        lastInColumn[element.Column].NextInColumn = copyElement;
                    } else {
                        copyColumns[element.Column] = copyElement;
                    }
                    lastInColumn[element.Column] = copyElement;
                    // move to the next element in the row
                    element = element.NextInRow;
                }
            }

            SparseSquareMatrix copy = new SparseSquareMatrix(dimension, copyRows, copyColumns, fill);
            return (copy);
        }