shh.csparse
Class CSparse

Object
  extended byMatrix
      extended byCSparse
All Implemented Interfaces:
Cloneable

public class CSparse
extends Matrix
implements Cloneable

Large sparse matrices over an integral domain, with linear algebra tools that aim to preserve sparsity by avoiding both fill-in and explosion of the individual matrix entries.

The matrix is stored as an array of columns, where each column is a sparse vector (see SparseV). The matrix entries, which are instances of SparseElt, can in principle be over any integral domain. There's currently the most support for the rings Z (see SparseEltZ) and Fp (see the implementations of SparseEltField).

Most operations on a CSparse are destructive. In order to save space, they overwrite the matrix entries.

This class contains the low-level algorithms like elementary row/column operations, copying, and creating matrices. The key linear algebra routines are in other classes. The main reduction algorithms over Z, which are based on Smith Normal Form (SNF), are in MPDQ. The LLL algorithm for dense matrices over Z is at DenseMatrixZ.doLLL(); use moveToDenseZ and moveFromDenseZ to go back and forth between sparse and dense versions of a matrix. Hermite Normal Form over Euclidean domains, which includes Gaussian elimination mod p, is at HNF() below.

Author:
Mark McConnell

Field Summary
protected  SparseV[] cols
          cols[j] is the j-th column of this sparse matrix.
protected  int numRows
          In an m × n matrix, this is m.
 
Constructor Summary
CSparse(int m, int n)
          Constructs a zero matrix with m rows and n columns.
CSparse(int m, SparseV[] colArray)
          Constructs a matrix with m rows and the specified columns.
 
Method Summary
 Matrix add(Matrix b0)
          Adds this and another CSparse, returning a CSparse.
 void alterCol(int j1, SparseElt factor, int j2)
          Alter column j1 by adding to it the value in factor times column j2.
 void alterRow(int i1, SparseElt factor, int i2)
          Alter row i1 by adding to it the value in factor times row i2.
 Object clone()
           
static CSparse concatLeftRight(CSparse A, CSparse B)
          Concatenates A, B into (A | B).
 CSparse copyMod(int p)
          If this CSparse has entries over Z, returns a new CSparse whose entries are their reductions mod p.
 CSparse copyWithoutZeroCols()
          Returns a new CSparse whose columns are copies of the columns of this, except that null or zero columns are omitted.
 boolean equalsCSparse(CSparse b)
          Returns true if and only if this and b have the same size and the entries are equal term by term.
 SparseElt get(int i, int j)
          Gets the i,j entry.
 SparseV getCol(int j)
          Returns the jth column, or possibly null if the column is all zero.
 int getNumCols()
          Returns the number n of columns.
 int getNumRows()
          Returns the number m of rows.
 float getSparsity()
          Returns the ratio (number of non-zero entries)/(total number of entries), as a number between 0 and 1.
 float getSparsity(int corner, boolean isNortheast0)
          Returns the ratio (number of non-zero entries)/(total number of entries) in the southeast region [corner, m) × [corner, n), as a number between 0 and 1.
 float[] getSparsityZ(int corner)
          In slot 0 of the result, returns the same as getSparsity(int, boolean) with arguments (corner, true).
 SortedSet HNF()
          Does column operations, destructively, to replace this with its upper-triangular Hermite Normal Form (HNF).
protected  Integer HNF(int j0)
          One step of HNF().
 Matrix inverse()
          Unsupported.
 boolean isIdentity()
          Whether this is an n × n identity matrix.
 boolean isProductZero(Matrix b0)
          Tests whether this * b0 is zero, without storing the product.
 boolean isZero()
          Whether every entry in this matrix is zero.
static CSparse makeZeroAndId(int m, int n, int i0, int j0, int s)
          Returns an m × n CSparse that is zero except that, in the square block starting at i0,j0 and of side s, it is the identity.
 void moveFromDenseZ(DenseMatrixZ M, int i0, int i1, int j0, int j1)
          Destructively replaces a rectangular block of this matrix with the contents of M.
 void moveFromDenseZ(DenseMatrixZ M, int i0, int i1, int j0, int j1, int j2, int j3)
          Destructively replaces two rectangular blocks of this matrix with the contents of M.
 DenseMatrixZ moveToDenseZ(int i0, int i1, int j0, int j1)
          Destructively removes a rectangular block from this matrix, putting the block into a dense matrix and returning the latter.
 DenseMatrixZ moveToDenseZ(int i0, int i1, int j0, int j1, int j2, int j3)
          Destructively removes two rectangular blocks from this matrix, putting the blocks side by side into a dense matrix and returning the latter.
 Matrix mult(Matrix b)
          Returns this * b.
 void negateCol(int j)
          Multiply through column j by -1.
 void negateRow(int i)
          Multiply through row i by -1.
 Enumeration rowEnum()
          Returns the rows of this as SparseVs.
 void set(SparseElt rowIndexAndVal, int colIndex)
          Sets a matrix entry.
 void swapCols(int j1, int j2)
          Interchange two columns.
 void swapRows(int i1, int i2)
          Interchange two rows.
 DenseMatrixZ toDenseZ()
          Returns a DenseMatrixZ with the same size and entries as this.
 Matrix transpose()
          Non-destructive.
 void updateNormSq(int j0)
          Calls SparseV.updateNormSq() on all columns j ≥ j0.
 void userInputMatrix(List ravelList)
          Fills this CSparse from the entries in ravelList, in row-major order.
 
Methods inherited from class Matrix
toString
 
Methods inherited from class Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

numRows

protected final int numRows
In an m × n matrix, this is m. The value of n is cols.length.


cols

protected final SparseV[] cols
cols[j] is the j-th column of this sparse matrix.

Constructor Detail

CSparse

public CSparse(int m,
               int n)
Constructs a zero matrix with m rows and n columns.


CSparse

public CSparse(int m,
               SparseV[] colArray)
Constructs a matrix with m rows and the specified columns. colArray is used directly, not copied.

Method Detail

alterCol

public void alterCol(int j1,
                     SparseElt factor,
                     int j2)
Alter column j1 by adding to it the value in factor times column j2. The index in factor is ignored.


alterRow

public void alterRow(int i1,
                     SparseElt factor,
                     int i2)
Alter row i1 by adding to it the value in factor times row i2. The index in factor is ignored.


swapCols

public void swapCols(int j1,
                     int j2)
Interchange two columns.


swapRows

public void swapRows(int i1,
                     int i2)
Interchange two rows.


negateRow

public void negateRow(int i)
Multiply through row i by -1.


negateCol

public void negateCol(int j)
Multiply through column j by -1.


userInputMatrix

public void userInputMatrix(List ravelList)
Fills this CSparse from the entries in ravelList, in row-major order. These entries should be either Numbers or Strings. They will be converted to ints, then embedded in Z. If ravelList runs out, it starts over again from the beginning, as with APL's ravel function ρ.

For a less structured way of initializing a CSparse, use set(shh.csparse.SparseElt, int).


getCol

public SparseV getCol(int j)
Returns the jth column, or possibly null if the column is all zero.


clone

public Object clone()

equalsCSparse

public boolean equalsCSparse(CSparse b)
Returns true if and only if this and b have the same size and the entries are equal term by term.


getSparsity

public float getSparsity()
Returns the ratio (number of non-zero entries)/(total number of entries), as a number between 0 and 1. Columns that are all zero are not included. Returns 0 in undefined cases.


getSparsity

public float getSparsity(int corner,
                         boolean isNortheast0)
Returns the ratio (number of non-zero entries)/(total number of entries) in the southeast region [corner, m) × [corner, n), as a number between 0 and 1. Columns that are all zero in the region are not included. Returns 0 in undefined cases.

Parameters:
isNortheast0 - True if we know in advance that the northeast region [0, corner) × [corner, n) is always 0, as it is in MPDQ.jac().

updateNormSq

public void updateNormSq(int j0)
Calls SparseV.updateNormSq() on all columns j ≥ j0.


makeZeroAndId

public static CSparse makeZeroAndId(int m,
                                    int n,
                                    int i0,
                                    int j0,
                                    int s)
Returns an m × n CSparse that is zero except that, in the square block starting at i0,j0 and of side s, it is the identity. The entries that are 1 are in SparseEltZ.


copyWithoutZeroCols

public CSparse copyWithoutZeroCols()
Returns a new CSparse whose columns are copies of the columns of this, except that null or zero columns are omitted. The result is thus m × n0, where this is m × n and n0 ≤ n. If this had no null or zero columns to begin with, we return this, not a copy.


concatLeftRight

public static CSparse concatLeftRight(CSparse A,
                                      CSparse B)
Concatenates A, B into (A | B). The columns in the result are copies of the columns in the originals. If the m's differ, we use the bigger one.


add

public Matrix add(Matrix b0)
Adds this and another CSparse, returning a CSparse. Does not support other classes of b0. Non-destructive.

Specified by:
add in class Matrix
Throws:
IllegalArgumentException - If the dimensions don't match.

get

public SparseElt get(int i,
                     int j)
Gets the i,j entry. Does not check whether the indices are out of range. Returns null for a zero entry.

Specified by:
get in class Matrix

getNumCols

public int getNumCols()
Description copied from class: Matrix
Returns the number n of columns.

Specified by:
getNumCols in class Matrix

getNumRows

public int getNumRows()
Description copied from class: Matrix
Returns the number m of rows.

Specified by:
getNumRows in class Matrix

inverse

public Matrix inverse()
Unsupported.

Specified by:
inverse in class Matrix

isIdentity

public boolean isIdentity()
Description copied from class: Matrix
Whether this is an n × n identity matrix.

Specified by:
isIdentity in class Matrix

rowEnum

public Enumeration rowEnum()
Returns the rows of this as SparseVs. The returned rows share a single underlying SparseV instance. In particular, they're never null. Returns exactly getNumRows() items.


isProductZero

public boolean isProductZero(Matrix b0)
Tests whether this * b0 is zero, without storing the product. Only supported if b0 is a CSparse.

Specified by:
isProductZero in class Matrix
Throws:
IllegalArgumentException - if the inner dimensions don't match.

isZero

public boolean isZero()
Description copied from class: Matrix
Whether every entry in this matrix is zero.

Specified by:
isZero in class Matrix

mult

public Matrix mult(Matrix b)
Returns this * b. Non-destructive if b is a CSparse. Destructive if b is an ElemMatrix. Unsupported in other cases.

Specified by:
mult in class Matrix

set

public void set(SparseElt rowIndexAndVal,
                int colIndex)
Sets a matrix entry. Does not check whether the row or col index is out of range.

Specified by:
set in class Matrix

transpose

public Matrix transpose()
Description copied from class: Matrix
Non-destructive.

Specified by:
transpose in class Matrix

HNF

public SortedSet HNF()
Does column operations, destructively, to replace this with its upper-triangular Hermite Normal Form (HNF). For instance, a 5 × 3 matrix might become
       x x x
       0 x x
       0 x x
       0 0 x
       0 0 x
       

If the underlying integral domain is a field, the previous example will be in echelon form.

       x 0 0
       0 x x
       0 x 0
       0 0 x
       0 0 x
       

This method is designed to work simultaneously over Z, Fp, and other Euclidean domains. Over Z (and see the comments in the code about other domains), the pivots will be made positive, and the elements to the right of the pivots will be positive and as small as possible.

The algorithm is straightforward. Unlike the routines in MPDQ, it makes no special effort to handle sparsity and fill-in.

Returns:
A SortedSet of the row indices of the bottommost non-zero entries in each column, as Integers and sorted by <. In the examples above, the return value would be [0 2 4].
Throws:
ClassCastException - If some entries of the CSparse don't implement SparseEltEuc.

HNF

protected Integer HNF(int j0)
One step of HNF(). The active region is columns 0 ≤ j < j0. We do column operations on the active region until there is a unique column whose SparseV.getLastIndex() is maximal. We put that column into position j0-1 and use its last entry to clear out the right side of the corresponding row.

Returns:
That maximal LastIndex, as an Integer, or null if the active region is zero.

toDenseZ

public DenseMatrixZ toDenseZ()
Returns a DenseMatrixZ with the same size and entries as this.

Throws:
ClassCastException - If not all entires are over Z (i.e., of class SparseEltZ).

moveToDenseZ

public DenseMatrixZ moveToDenseZ(int i0,
                                 int i1,
                                 int j0,
                                 int j1)
Destructively removes a rectangular block from this matrix, putting the block into a dense matrix and returning the latter. The block is i0i < i1 × j0j < j1.

Throws:
ClassCastException - If not all entires are over Z (i.e., of class SparseEltZ).
IllegalArgumentException - If the block is out of range.

moveToDenseZ

public DenseMatrixZ moveToDenseZ(int i0,
                                 int i1,
                                 int j0,
                                 int j1,
                                 int j2,
                                 int j3)
Destructively removes two rectangular blocks from this matrix, putting the blocks side by side into a dense matrix and returning the latter. The blocks are i0i < i1 × (j0j < j1 or j2j < j3).

Throws:
ClassCastException - If not all entires are over Z (i.e., of class SparseEltZ).
IllegalArgumentException - If the block is out of range.

moveFromDenseZ

public void moveFromDenseZ(DenseMatrixZ M,
                           int i0,
                           int i1,
                           int j0,
                           int j1)
Destructively replaces a rectangular block of this matrix with the contents of M. The block is i0i < i1 × j0j < j1. The inverse of moveToDenseZ(int, int, int, int).

Throws:
IllegalArgumentException - If the block is out of range or if its size doesn't match M.

moveFromDenseZ

public void moveFromDenseZ(DenseMatrixZ M,
                           int i0,
                           int i1,
                           int j0,
                           int j1,
                           int j2,
                           int j3)
Destructively replaces two rectangular blocks of this matrix with the contents of M. The blocks are i0i < i1 × (j0j < j1 or j2j < j3).

Throws:
IllegalArgumentException - If the block is out of range or if its size doesn't match M.

getSparsityZ

public float[] getSparsityZ(int corner)
In slot 0 of the result, returns the same as getSparsity(int, boolean) with arguments (corner, true). In slot 1 of the result, returns the ratio (number of SparseEltZBig entries)/(total number of entries) in the same region.


copyMod

public CSparse copyMod(int p)
If this CSparse has entries over Z, returns a new CSparse whose entries are their reductions mod p.

Throws:
RuntimeException - If p is not a prime, or is not small enough (see SparseEltModp.checkP(int)).
ClassCastException - If not all entries are over Z (i.e., of class SparseEltZ).