/// <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); }
/// <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); }