/** * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * * Created on 5 Mar 2013 * Created by Andreas Prlic * * @since 3.0.6 */ package org.biojava.nbio.structure.math; import java.io.Serializable; /** * * A sparse, square matrix, implementing using two arrays of sparse * vectors, one representation for the rows and one for the columns. * * For matrix-matrix product, we might also want to store the * column representation. * * Derived from http://introcs.cs.princeton.edu/java/44st/SparseMatrix.java.html * * For additional documentation, see <a href="http://introcs.cs.princeton.edu/44st">Section 4.4</a> of * <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne. * * **/ public class SparseSquareMatrix implements Serializable { /** * */ private static final long serialVersionUID = -5217767192992868955L; private final int N; // N-by-N matrix private SparseVector[] rows; // the rows, each row is a sparse vector /** initialize an N-by-N matrix of all 0s * * @param N - size */ public SparseSquareMatrix(int N) { this.N = N; rows = new SparseVector[N]; for (int i = 0; i < N; i++) rows[i] = new SparseVector(N); } /** set A[i][j] = value * * @param i * @param j * @param value */ public void put(int i, int j, double value) { if (i < 0 || i >= N) throw new IllegalArgumentException("Illegal index"); if (j < 0 || j >= N) throw new IllegalArgumentException("Illegal index"); rows[i].put(j, value); } /** access a value at i,j * * @param i * @param j * @return return A[i][j] */ public double get(int i, int j) { if (i < 0 || i >= N) throw new IllegalArgumentException("Illegal index " + i + " should be > 0 and < " + N); if (j < 0 || j >= N) throw new IllegalArgumentException("Illegal index " + j + " should be > 0 and < " + N); return rows[i].get(j); } /** return the number of nonzero entries (not the most efficient implementation) * * @return */ public int nnz() { int sum = 0; for (int i = 0; i < N; i++) sum += rows[i].nnz(); return sum; } /** * * @param x * @return return the matrix-vector product b = Ax */ public SparseVector times(SparseVector x) { SparseSquareMatrix A = this; if (N != x.size()) throw new IllegalArgumentException("Dimensions disagree. " + N + " != " + x.size()); SparseVector b = new SparseVector(N); for (int i = 0; i < N; i++) b.put(i, A.rows[i].dot(x)); return b; } /** return C = A + B * * @param B * @return */ public SparseSquareMatrix plus(SparseSquareMatrix B) { SparseSquareMatrix A = this; if (A.N != B.N) throw new IllegalArgumentException("Dimensions disagree. " + A.N + " != " + B.N); SparseSquareMatrix C = new SparseSquareMatrix(N); for (int i = 0; i < N; i++) C.rows[i] = A.rows[i].plus(B.rows[i]); return C; } @Override public String toString() { StringBuilder s = new StringBuilder(); s.append( "N = "); s.append( N); s.append(", nonzeros = "); s.append( nnz()); s.append( System.getProperty("line.separator")); for (int i = 0; i < N; i++) { s.append(i); s.append(": "); s.append( rows[i]); s.append( System.getProperty("line.separator")); } return s.toString(); } }