Author: jmannix Date: Thu Jan 21 13:12:40 2010 New Revision: 901692 URL: http://svn.apache.org/viewvc?rev=901692&view=rev Log: Fixes MAHOUT-211, adding some consistent view semantics to matrices, and adding a shallow (view) constructor for DenseVector.
Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/AbstractMatrix.java lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseMatrix.java lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseVector.java lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseColumnMatrix.java lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseRowMatrix.java Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/AbstractMatrix.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/AbstractMatrix.java?rev=901692&r1=901691&r2=901692&view=diff ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/AbstractMatrix.java (original) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/AbstractMatrix.java Thu Jan 21 13:12:40 2010 @@ -21,11 +21,9 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; import java.lang.reflect.Type; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; /** A few universal implementations of convenience functions */ @@ -460,4 +458,128 @@ return result; } + protected class TransposeViewVector extends AbstractVector { + + protected Matrix matrix; + protected int transposeOffset; + protected int numCols; + private boolean rowToColumn; + + public TransposeViewVector(Matrix m, int offset) { + this(m, offset, true); + } + + public TransposeViewVector(Matrix m, int offset, boolean rowToColumn) { + matrix = m; + this.transposeOffset = offset; + this.rowToColumn = rowToColumn; + numCols = rowToColumn ? m.numCols() : m.numRows(); + size = rowToColumn ? m.numRows() : m.numCols(); + } + + @Override + public Vector clone() { + Vector v = new DenseVector(size); + addTo(v); + return v; + } + + @Override + protected Matrix matrixLike(int rows, int columns) { + return matrix.like(rows, columns); + } + + @Override + public Iterator<Element> iterateAll() { + return new Iterator<Element>() { + int i = 0; + @Override + public boolean hasNext() { + return i < size; + } + + @Override + public Element next() { + return getElement(i++); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Element removal not supported"); + } + }; + } + + /** + * Currently delegates to iterateAll. TODO: This could be optimized to at least skip empty rows if there are + * many of them. + * @return an iterator (currently dense). + */ + @Override + public Iterator<Element> iterateNonZero() { + return iterateAll(); + } + + @Override + public Element getElement(final int i) { + return new Element() { + @Override + public double get() { + return getQuick(i); + } + + @Override + public int index() { + return i; + } + + @Override + public void set(double value) { + setQuick(i, value); + } + }; + } + + @Override + public double getQuick(int index) { + Vector v = rowToColumn ? matrix.getRow(index) : matrix.getColumn(index); + return v == null ? 0 : v.getQuick(transposeOffset); + } + + @Override + public void setQuick(int index, double value) { + Vector v = rowToColumn ? matrix.getRow(index) : matrix.getColumn(index); + if(v == null) { + v = newVector(numCols); + matrix.assignRow(index, v); + } + v.setQuick(transposeOffset, value); + } + + protected Vector newVector(int cardinality) + { + return new DenseVector(cardinality); + } + + @Override + public Vector like() { + return new DenseVector(size); + } + + @Override + public Vector like(int cardinality) { + return new DenseVector(cardinality); + } + + /** + * TODO: currently I don't know of an efficient way to get this value correctly. + * + * @return the number of nonzero entries + */ + @Override + public int getNumNondefaultElements() { + return size; + } + } + } Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseMatrix.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseMatrix.java?rev=901692&r1=901691&r2=901692&view=diff ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseMatrix.java (original) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseMatrix.java Thu Jan 21 13:12:40 2010 @@ -136,11 +136,7 @@ if (column < 0 || column >= columnSize()) { throw new IndexException(); } - double[] col = new double[rowSize()]; - for (int row = 0; row < rowSize(); row++) { - col[row] = values[row][column]; - } - return new DenseVector(col); + return new TransposeViewVector(this, column); } @Override @@ -148,7 +144,7 @@ if (row < 0 || row >= rowSize()) { throw new IndexException(); } - return new DenseVector(values[row]); + return new DenseVector(values[row], true); } } Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseVector.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseVector.java?rev=901692&r1=901691&r2=901692&view=diff ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseVector.java (original) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/DenseVector.java Thu Jan 21 13:12:40 2010 @@ -37,7 +37,11 @@ /** Construct a new instance using provided values */ public DenseVector(double[] values) { - this.values = values.clone(); + this(values, false); + } + + public DenseVector(double[] values, boolean shallowCopy) { + this.values = shallowCopy ? values : values.clone(); } public DenseVector(String name, double[] values) { Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseColumnMatrix.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseColumnMatrix.java?rev=901692&r1=901691&r2=901692&view=diff ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseColumnMatrix.java (original) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseColumnMatrix.java Thu Jan 21 13:12:40 2010 @@ -160,11 +160,7 @@ if (row < 0 || row >= cardinality[ROW]) { throw new IndexException(); } - double[] d = new double[cardinality[COL]]; - for (int col = 0; col < cardinality[COL]; col++) { - d[col] = getQuick(row, col); - } - return new DenseVector(d); + return new TransposeViewVector(this, row, false); } } Modified: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseRowMatrix.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseRowMatrix.java?rev=901692&r1=901691&r2=901692&view=diff ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseRowMatrix.java (original) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/SparseRowMatrix.java Thu Jan 21 13:12:40 2010 @@ -143,18 +143,29 @@ return this; } + /** + * + * @param column an int column index + * @return a shallow view of the column of this row matrix. + */ @Override public Vector getColumn(int column) { if (column < 0 || column >= cardinality[COL]) { throw new IndexException(); } - double[] d = new double[cardinality[ROW]]; - for (int row = 0; row < cardinality[ROW]; row++) { - d[row] = getQuick(row, column); - } - return new DenseVector(d); + return new TransposeViewVector(this, column) { + @Override + protected Vector newVector(int cardinality) { + return new RandomAccessSparseVector(cardinality, 10); + } + }; } + /** + * + * @param row an int row index + * @return a deep view of the Vector at specified row (ie you may mutate the original matrix using this row) + */ @Override public Vector getRow(int row) { if (row < 0 || row >= cardinality[ROW]) {