http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/Centroid.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/Centroid.java b/math/src/main/java/org/apache/mahout/math/Centroid.java deleted file mode 100644 index dceffe1..0000000 --- a/math/src/main/java/org/apache/mahout/math/Centroid.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.function.Functions; - -/** - * A centroid is a weighted vector. We have it delegate to the vector itself for lots of operations - * to make it easy to use vector search classes and such. - */ -public class Centroid extends WeightedVector { - public Centroid(WeightedVector original) { - super(original.getVector().like().assign(original), original.getWeight(), original.getIndex()); - } - - public Centroid(int key, Vector initialValue) { - super(initialValue, 1, key); - } - - public Centroid(int key, Vector initialValue, double weight) { - super(initialValue, weight, key); - } - - public static Centroid create(int key, Vector initialValue) { - if (initialValue instanceof WeightedVector) { - return new Centroid(key, new DenseVector(initialValue), ((WeightedVector) initialValue).getWeight()); - } else { - return new Centroid(key, new DenseVector(initialValue), 1); - } - } - - public void update(Vector v) { - if (v instanceof Centroid) { - Centroid c = (Centroid) v; - update(c.delegate, c.getWeight()); - } else { - update(v, 1); - } - } - - public void update(Vector other, final double wy) { - final double wx = getWeight(); - delegate.assign(other, Functions.reweigh(wx, wy)); - setWeight(wx + wy); - } - - @Override - public Centroid like() { - return new Centroid(getIndex(), getVector().like(), getWeight()); - } - - /** - * Gets the index of this centroid. Use getIndex instead to maintain standard names. - */ - @Deprecated - public int getKey() { - return getIndex(); - } - - public void addWeight(double newWeight) { - setWeight(getWeight() + newWeight); - } - - @Override - public String toString() { - return String.format("key = %d, weight = %.2f, vector = %s", getIndex(), getWeight(), delegate); - } - - @SuppressWarnings("CloneDoesntCallSuperClone") - @Override - public Centroid clone() { - return new Centroid(this); - } -}
http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/CholeskyDecomposition.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/CholeskyDecomposition.java b/math/src/main/java/org/apache/mahout/math/CholeskyDecomposition.java deleted file mode 100644 index 5cea8e5..0000000 --- a/math/src/main/java/org/apache/mahout/math/CholeskyDecomposition.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import com.google.common.base.Preconditions; -import org.apache.mahout.math.function.Functions; - -/** - * Cholesky decomposition shamelessly ported from JAMA. - * <p> - * A Cholesky decomposition of a semi-positive definite matrix A is a lower triangular matrix L such - * that L L^* = A. If A is full rank, L is unique. If A is real, then it must be symmetric and R - * will also be real. - */ -public class CholeskyDecomposition { - private final PivotedMatrix L; - private boolean isPositiveDefinite = true; - - public CholeskyDecomposition(Matrix a) { - this(a, true); - } - - public CholeskyDecomposition(Matrix a, boolean pivot) { - int rows = a.rowSize(); - L = new PivotedMatrix(new DenseMatrix(rows, rows)); - - // must be square - Preconditions.checkArgument(rows == a.columnSize(), "Must be a Square Matrix"); - - if (pivot) { - decomposeWithPivoting(a); - } else { - decompose(a); - } - } - - private void decomposeWithPivoting(Matrix a) { - int n = a.rowSize(); - L.assign(a); - - // pivoted column-wise submatrix cholesky with simple pivoting - double uberMax = L.viewDiagonal().aggregate(Functions.MAX, Functions.ABS); - for (int k = 0; k < n; k++) { - double max = 0; - int pivot = k; - for (int j = k; j < n; j++) { - if (L.get(j, j) > max) { - max = L.get(j, j); - pivot = j; - if (uberMax < Math.abs(max)) { - uberMax = Math.abs(max); - } - } - } - L.swap(k, pivot); - - double akk = L.get(k, k); - double epsilon = 1.0e-10 * Math.max(uberMax, L.viewColumn(k).aggregate(Functions.MAX, Functions.ABS)); - - if (akk < -epsilon) { - // can't have decidedly negative element on diagonal - throw new IllegalArgumentException("Matrix is not positive semi-definite"); - } else if (akk <= epsilon) { - // degenerate column case. Set all to zero - L.viewColumn(k).assign(0); - isPositiveDefinite = false; - - // no need to subtract from remaining sub-matrix - } else { - // normalize column by diagonal element - akk = Math.sqrt(Math.max(0, akk)); - L.viewColumn(k).viewPart(k, n - k).assign(Functions.div(akk)); - L.viewColumn(k).viewPart(0, k).assign(0); - - // subtract off scaled version of this column to the right - for (int j = k + 1; j < n; j++) { - Vector columnJ = L.viewColumn(j).viewPart(k, n - k); - Vector columnK = L.viewColumn(k).viewPart(k, n - k); - columnJ.assign(columnK, Functions.minusMult(columnK.get(j - k))); - } - - } - } - } - - private void decompose(Matrix a) { - int n = a.rowSize(); - L.assign(a); - - // column-wise submatrix cholesky with simple pivoting - for (int k = 0; k < n; k++) { - - double akk = L.get(k, k); - - // set upper part of column to 0. - L.viewColumn(k).viewPart(0, k).assign(0); - - double epsilon = 1.0e-10 * L.viewColumn(k).aggregate(Functions.MAX, Functions.ABS); - if (akk <= epsilon) { - // degenerate column case. Set diagonal to 1, all others to zero - L.viewColumn(k).viewPart(k, n - k).assign(0); - - isPositiveDefinite = false; - - // no need to subtract from remaining sub-matrix - } else { - // normalize column by diagonal element - akk = Math.sqrt(Math.max(0, akk)); - L.set(k, k, akk); - L.viewColumn(k).viewPart(k + 1, n - k - 1).assign(Functions.div(akk)); - - // now subtract scaled version of column - for (int j = k + 1; j < n; j++) { - Vector columnJ = L.viewColumn(j).viewPart(j, n - j); - Vector columnK = L.viewColumn(k).viewPart(j, n - j); - columnJ.assign(columnK, Functions.minusMult(L.get(j, k))); - } - } - } - } - - public boolean isPositiveDefinite() { - return isPositiveDefinite; - } - - public Matrix getL() { - return L.getBase(); - } - - public PivotedMatrix getPermutedL() { - return L; - } - - /** - * @return Returns the permutation of rows and columns that was applied to L - */ - public int[] getPivot() { - return L.getRowPivot(); - } - - public int[] getInversePivot() { - return L.getInverseRowPivot(); - } - - /** - * Compute inv(L) * z efficiently. - * - * @param z - */ - public Matrix solveLeft(Matrix z) { - int n = L.columnSize(); - int nx = z.columnSize(); - - Matrix X = new DenseMatrix(n, z.columnSize()); - X.assign(z); - - // Solve L*Y = Z using back-substitution - // note that k and i have to go in a funny order because L is pivoted - for (int internalK = 0; internalK < n; internalK++) { - int k = L.rowUnpivot(internalK); - for (int j = 0; j < nx; j++) { - for (int internalI = 0; internalI < internalK; internalI++) { - int i = L.rowUnpivot(internalI); - X.set(k, j, X.get(k, j) - X.get(i, j) * L.get(k, i)); - } - if (L.get(k, k) != 0) { - X.set(k, j, X.get(k, j) / L.get(k, k)); - } else { - X.set(k, j, 0); - } - } - } - return X; - } - - /** - * Compute z * inv(L') efficiently - */ - public Matrix solveRight(Matrix z) { - int n = z.columnSize(); - int nx = z.rowSize(); - - Matrix x = new DenseMatrix(z.rowSize(), z.columnSize()); - x.assign(z); - - // Solve Y*L' = Z using back-substitution - for (int internalK = 0; internalK < n; internalK++) { - int k = L.rowUnpivot(internalK); - for (int j = 0; j < nx; j++) { - for (int internalI = 0; internalI < k; internalI++) { - int i = L.rowUnpivot(internalI); - x.set(j, k, x.get(j, k) - x.get(j, i) * L.get(k, i)); - if (Double.isInfinite(x.get(j, k)) || Double.isNaN(x.get(j, k))) { - throw new IllegalStateException( - String.format("Invalid value found at %d,%d (should not be possible)", j, k)); - } - } - if (L.get(k, k) != 0) { - x.set(j, k, x.get(j, k) / L.get(k, k)); - } else { - x.set(j, k, 0); - } - if (Double.isInfinite(x.get(j, k)) || Double.isNaN(x.get(j, k))) { - throw new IllegalStateException(String.format("Invalid value found at %d,%d (should not be possible)", j, k)); - } - } - } - return x; - } - -} - http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/ConstantVector.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/ConstantVector.java b/math/src/main/java/org/apache/mahout/math/ConstantVector.java deleted file mode 100644 index f10f631..0000000 --- a/math/src/main/java/org/apache/mahout/math/ConstantVector.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import java.util.Iterator; - -import com.google.common.collect.AbstractIterator; - -/** - * Implements a vector with all the same values. - */ -public class ConstantVector extends AbstractVector { - private final double value; - - public ConstantVector(double value, int size) { - super(size); - this.value = value; - } - - /** - * Subclasses must override to return an appropriately sparse or dense result - * - * @param rows the row cardinality - * @param columns the column cardinality - * @return a Matrix - */ - @Override - protected Matrix matrixLike(int rows, int columns) { - return new DenseMatrix(rows, columns); - } - - /** - * Used internally by assign() to update multiple indices and values at once. - * Only really useful for sparse vectors (especially SequentialAccessSparseVector). - * <p> - * If someone ever adds a new type of sparse vectors, this method must merge (index, value) pairs into the vector. - * - * @param updates a mapping of indices to values to merge in the vector. - */ - @Override - public void mergeUpdates(OrderedIntDoubleMapping updates) { - throw new UnsupportedOperationException("Cannot mutate a ConstantVector"); - } - - /** - * @return true iff this implementation should be considered dense -- that it explicitly represents - * every value - */ - @Override - public boolean isDense() { - return true; - } - - /** - * @return true iff this implementation should be considered to be iterable in index order in an - * efficient way. In particular this implies that {@link #iterator()} and {@link - * #iterateNonZero()} return elements in ascending order by index. - */ - @Override - public boolean isSequentialAccess() { - return true; - } - - /** - * Iterates over all elements <p> - * NOTE: Implementations may choose to reuse the Element returned - * for performance reasons, so if you need a copy of it, you should call {@link #getElement(int)} - * for the given index - * - * @return An {@link java.util.Iterator} over all elements - */ - @Override - public Iterator<Element> iterator() { - return new AbstractIterator<Element>() { - private int i = 0; - private final int n = size(); - @Override - protected Element computeNext() { - if (i < n) { - return new LocalElement(i++); - } else { - return endOfData(); - } - } - }; - } - - /** - * Iterates over all non-zero elements.<p> - * NOTE: Implementations may choose to reuse the Element - * returned for performance reasons, so if you need a copy of it, you should call {@link - * #getElement(int)} for the given index - * - * @return An {@link java.util.Iterator} over all non-zero elements - */ - @Override - public Iterator<Element> iterateNonZero() { - return iterator(); - } - - /** - * Return the value at the given index, without checking bounds - * - * @param index an int index - * @return the double at the index - */ - @Override - public double getQuick(int index) { - return value; - } - - /** - * Return an empty vector of the same underlying class as the receiver - * - * @return a Vector - */ - @Override - public Vector like() { - return new DenseVector(size()); - } - - @Override - public Vector like(int cardinality) { - return new DenseVector(cardinality); - } - - /** - * Set the value at the given index, without checking bounds - * - * @param index an int index into the receiver - * @param value a double value to set - */ - @Override - public void setQuick(int index, double value) { - throw new UnsupportedOperationException("Can't set a value in a constant matrix"); - } - - /** - * Return the number of values in the recipient - * - * @return an int - */ - @Override - public int getNumNondefaultElements() { - return size(); - } - - @Override - public double getLookupCost() { - return 1; - } - - @Override - public double getIteratorAdvanceCost() { - return 1; - } - - @Override - public boolean isAddConstantTime() { - throw new UnsupportedOperationException("Cannot mutate a ConstantVector"); - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/DelegatingVector.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/DelegatingVector.java b/math/src/main/java/org/apache/mahout/math/DelegatingVector.java deleted file mode 100644 index 0b2e36b..0000000 --- a/math/src/main/java/org/apache/mahout/math/DelegatingVector.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.function.DoubleDoubleFunction; -import org.apache.mahout.math.function.DoubleFunction; - -/** - * A delegating vector provides an easy way to decorate vectors with weights or id's and such while - * keeping all of the Vector functionality. - * - * This vector implements LengthCachingVector because almost all delegates cache the length and - * the cost of false positives is very low. - */ -public class DelegatingVector implements Vector, LengthCachingVector { - protected Vector delegate; - - public DelegatingVector(Vector v) { - delegate = v; - } - - protected DelegatingVector() { - } - - public Vector getVector() { - return delegate; - } - - @Override - public double aggregate(DoubleDoubleFunction aggregator, DoubleFunction map) { - return delegate.aggregate(aggregator, map); - } - - @Override - public double aggregate(Vector other, DoubleDoubleFunction aggregator, DoubleDoubleFunction combiner) { - return delegate.aggregate(other, aggregator, combiner); - } - - @Override - public Vector viewPart(int offset, int length) { - return delegate.viewPart(offset, length); - } - - @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException") - @Override - public Vector clone() { - DelegatingVector r; - try { - r = (DelegatingVector) super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("Clone not supported for DelegatingVector, shouldn't be possible"); - } - // delegate points to original without this - r.delegate = delegate.clone(); - return r; - } - - @Override - public Iterable<Element> all() { - return delegate.all(); - } - - @Override - public Iterable<Element> nonZeroes() { - return delegate.nonZeroes(); - } - - @Override - public Vector divide(double x) { - return delegate.divide(x); - } - - @Override - public double dot(Vector x) { - return delegate.dot(x); - } - - @Override - public double get(int index) { - return delegate.get(index); - } - - @Override - public Element getElement(int index) { - return delegate.getElement(index); - } - - /** - * Merge a set of (index, value) pairs into the vector. - * - * @param updates an ordered mapping of indices to values to be merged in. - */ - @Override - public void mergeUpdates(OrderedIntDoubleMapping updates) { - delegate.mergeUpdates(updates); - } - - @Override - public Vector minus(Vector that) { - return delegate.minus(that); - } - - @Override - public Vector normalize() { - return delegate.normalize(); - } - - @Override - public Vector normalize(double power) { - return delegate.normalize(power); - } - - @Override - public Vector logNormalize() { - return delegate.logNormalize(); - } - - @Override - public Vector logNormalize(double power) { - return delegate.logNormalize(power); - } - - @Override - public double norm(double power) { - return delegate.norm(power); - } - - @Override - public double getLengthSquared() { - return delegate.getLengthSquared(); - } - - @Override - public void invalidateCachedLength() { - if (delegate instanceof LengthCachingVector) { - ((LengthCachingVector) delegate).invalidateCachedLength(); - } - } - - @Override - public double getDistanceSquared(Vector v) { - return delegate.getDistanceSquared(v); - } - - @Override - public double getLookupCost() { - return delegate.getLookupCost(); - } - - @Override - public double getIteratorAdvanceCost() { - return delegate.getIteratorAdvanceCost(); - } - - @Override - public boolean isAddConstantTime() { - return delegate.isAddConstantTime(); - } - - @Override - public double maxValue() { - return delegate.maxValue(); - } - - @Override - public int maxValueIndex() { - return delegate.maxValueIndex(); - } - - @Override - public double minValue() { - return delegate.minValue(); - } - - @Override - public int minValueIndex() { - return delegate.minValueIndex(); - } - - @Override - public Vector plus(double x) { - return delegate.plus(x); - } - - @Override - public Vector plus(Vector x) { - return delegate.plus(x); - } - - @Override - public void set(int index, double value) { - delegate.set(index, value); - } - - @Override - public Vector times(double x) { - return delegate.times(x); - } - - @Override - public Vector times(Vector x) { - return delegate.times(x); - } - - @Override - public double zSum() { - return delegate.zSum(); - } - - @Override - public Vector assign(double value) { - delegate.assign(value); - return this; - } - - @Override - public Vector assign(double[] values) { - delegate.assign(values); - return this; - } - - @Override - public Vector assign(Vector other) { - delegate.assign(other); - return this; - } - - @Override - public Vector assign(DoubleDoubleFunction f, double y) { - delegate.assign(f, y); - return this; - } - - @Override - public Vector assign(DoubleFunction function) { - delegate.assign(function); - return this; - } - - @Override - public Vector assign(Vector other, DoubleDoubleFunction function) { - delegate.assign(other, function); - return this; - } - - @Override - public Matrix cross(Vector other) { - return delegate.cross(other); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public String asFormatString() { - return delegate.asFormatString(); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object o) { - return delegate.equals(o); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public boolean isDense() { - return delegate.isDense(); - } - - @Override - public boolean isSequentialAccess() { - return delegate.isSequentialAccess(); - } - - @Override - public double getQuick(int index) { - return delegate.getQuick(index); - } - - @Override - public Vector like() { - return new DelegatingVector(delegate.like()); - } - - @Override - public Vector like(int cardinality) { - return new DelegatingVector(delegate.like(cardinality)); - } - - @Override - public void setQuick(int index, double value) { - delegate.setQuick(index, value); - } - - @Override - public void incrementQuick(int index, double increment) { - delegate.incrementQuick(index, increment); - } - - @Override - public int getNumNondefaultElements() { - return delegate.getNumNondefaultElements(); - } - - @Override - public int getNumNonZeroElements() { - return delegate.getNumNonZeroElements(); - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/DenseMatrix.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/DenseMatrix.java b/math/src/main/java/org/apache/mahout/math/DenseMatrix.java deleted file mode 100644 index eac449a..0000000 --- a/math/src/main/java/org/apache/mahout/math/DenseMatrix.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.flavor.MatrixFlavor; - -import java.util.Arrays; - -/** Matrix of doubles implemented using a 2-d array */ -public class DenseMatrix extends AbstractMatrix { - - private double[][] values; - - /** - * Construct a matrix from the given values - * - * @param values - * a double[][] - */ - public DenseMatrix(double[][] values) { - this(values, false); - } - - /** - * Construct a matrix from the given values - * - * @param values - * a double[][] - * @param shallowCopy directly use the supplied array? - */ - public DenseMatrix(double[][] values, boolean shallowCopy) { - super(values.length, values[0].length); - if (shallowCopy) { - this.values = values; - } else { - this.values = new double[values.length][]; - for (int i = 0; i < values.length; i++) { - this.values[i] = values[i].clone(); - } - } - } - - /** - * Constructs an empty matrix of the given size. - * @param rows The number of rows in the result. - * @param columns The number of columns in the result. - */ - public DenseMatrix(int rows, int columns) { - super(rows, columns); - this.values = new double[rows][columns]; - } - - /** - * Returns the backing array - * @return double[][] - */ - public double[][] getBackingStructure() { - return this.values; - } - - @Override - public Matrix clone() { - DenseMatrix clone = (DenseMatrix) super.clone(); - clone.values = new double[values.length][]; - for (int i = 0; i < values.length; i++) { - clone.values[i] = values[i].clone(); - } - return clone; - } - - @Override - public double getQuick(int row, int column) { - return values[row][column]; - } - - @Override - public Matrix like() { - return like(rowSize(), columnSize()); - } - - @Override - public Matrix like(int rows, int columns) { - return new DenseMatrix(rows, columns); - } - - @Override - public void setQuick(int row, int column, double value) { - values[row][column] = value; - } - - @Override - public Matrix viewPart(int[] offset, int[] size) { - int rowOffset = offset[ROW]; - int rowsRequested = size[ROW]; - int columnOffset = offset[COL]; - int columnsRequested = size[COL]; - - return viewPart(rowOffset, rowsRequested, columnOffset, columnsRequested); - } - - @Override - public Matrix viewPart(int rowOffset, int rowsRequested, int columnOffset, int columnsRequested) { - if (rowOffset < 0) { - throw new IndexException(rowOffset, rowSize()); - } - if (rowOffset + rowsRequested > rowSize()) { - throw new IndexException(rowOffset + rowsRequested, rowSize()); - } - if (columnOffset < 0) { - throw new IndexException(columnOffset, columnSize()); - } - if (columnOffset + columnsRequested > columnSize()) { - throw new IndexException(columnOffset + columnsRequested, columnSize()); - } - return new MatrixView(this, new int[]{rowOffset, columnOffset}, new int[]{rowsRequested, columnsRequested}); - } - - @Override - public Matrix assign(double value) { - for (int row = 0; row < rowSize(); row++) { - Arrays.fill(values[row], value); - } - return this; - } - - public Matrix assign(DenseMatrix matrix) { - // make sure the data field has the correct length - if (matrix.values[0].length != this.values[0].length || matrix.values.length != this.values.length) { - this.values = new double[matrix.values.length][matrix.values[0].length]; - } - // now copy the values - for (int i = 0; i < this.values.length; i++) { - System.arraycopy(matrix.values[i], 0, this.values[i], 0, this.values[0].length); - } - return this; - } - - @Override - public Matrix assignColumn(int column, Vector other) { - if (rowSize() != other.size()) { - throw new CardinalityException(rowSize(), other.size()); - } - if (column < 0 || column >= columnSize()) { - throw new IndexException(column, columnSize()); - } - for (int row = 0; row < rowSize(); row++) { - values[row][column] = other.getQuick(row); - } - return this; - } - - @Override - public Matrix assignRow(int row, Vector other) { - if (columnSize() != other.size()) { - throw new CardinalityException(columnSize(), other.size()); - } - if (row < 0 || row >= rowSize()) { - throw new IndexException(row, rowSize()); - } - for (int col = 0; col < columnSize(); col++) { - values[row][col] = other.getQuick(col); - } - return this; - } - - @Override - public Vector viewRow(int row) { - if (row < 0 || row >= rowSize()) { - throw new IndexException(row, rowSize()); - } - return new DenseVector(values[row], true); - } - - @Override - public MatrixFlavor getFlavor() { - return MatrixFlavor.DENSELIKE; - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/DenseSymmetricMatrix.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/DenseSymmetricMatrix.java b/math/src/main/java/org/apache/mahout/math/DenseSymmetricMatrix.java deleted file mode 100644 index 7252b9b..0000000 --- a/math/src/main/java/org/apache/mahout/math/DenseSymmetricMatrix.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.flavor.TraversingStructureEnum; - -/** - * Economy packaging for a dense symmetric in-core matrix. - */ -public class DenseSymmetricMatrix extends UpperTriangular { - public DenseSymmetricMatrix(int n) { - super(n); - } - - public DenseSymmetricMatrix(double[] data, boolean shallow) { - super(data, shallow); - } - - public DenseSymmetricMatrix(Vector data) { - super(data); - } - - public DenseSymmetricMatrix(UpperTriangular mx) { - super(mx); - } - - @Override - public double getQuick(int row, int column) { - if (column < row) { - int swap = row; - row = column; - column = swap; - } - return super.getQuick(row, column); - } - - @Override - public void setQuick(int row, int column, double value) { - if (column < row) { - int swap = row; - row = column; - column = swap; - } - super.setQuick(row, column, value); - } - -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/DenseVector.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/DenseVector.java b/math/src/main/java/org/apache/mahout/math/DenseVector.java deleted file mode 100644 index 3961966..0000000 --- a/math/src/main/java/org/apache/mahout/math/DenseVector.java +++ /dev/null @@ -1,442 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import com.google.common.base.Preconditions; - -/** Implements vector as an array of doubles */ -public class DenseVector extends AbstractVector { - - private double[] values; - - /** For serialization purposes only */ - public DenseVector() { - super(0); - } - - /** Construct a new instance using provided values - * @param values - array of values - */ - public DenseVector(double[] values) { - this(values, false); - } - - public DenseVector(double[] values, boolean shallowCopy) { - super(values.length); - this.values = shallowCopy ? values : values.clone(); - } - - public DenseVector(DenseVector values, boolean shallowCopy) { - this(values.values, shallowCopy); - } - - /** Construct a new instance of the given cardinality - * @param cardinality - number of values in the vector - */ - public DenseVector(int cardinality) { - super(cardinality); - this.values = new double[cardinality]; - } - - /** - * Copy-constructor (for use in turning a sparse vector into a dense one, for example) - * @param vector The vector to copy - */ - public DenseVector(Vector vector) { - super(vector.size()); - values = new double[vector.size()]; - for (Element e : vector.nonZeroes()) { - values[e.index()] = e.get(); - } - } - - @Override - public double dot(Vector x) { - if (!x.isDense()) { - return super.dot(x); - } else { - - int size = x.size(); - if (values.length != size) { - throw new CardinalityException(values.length, size); - } - - double sum = 0; - for (int n = 0; n < size; n++) { - sum += values[n] * x.getQuick(n); - } - return sum; - } - } - - @Override - protected Matrix matrixLike(int rows, int columns) { - return new DenseMatrix(rows, columns); - } - - @SuppressWarnings("CloneDoesntCallSuperClone") - @Override - public DenseVector clone() { - return new DenseVector(values.clone()); - } - - /** - * @return true - */ - @Override - public boolean isDense() { - return true; - } - - /** - * @return true - */ - @Override - public boolean isSequentialAccess() { - return true; - } - - @Override - protected double dotSelf() { - double result = 0.0; - int max = size(); - for (int i = 0; i < max; i++) { - result += values[i] * values[i]; - } - return result; - } - - @Override - public double getQuick(int index) { - return values[index]; - } - - @Override - public DenseVector like() { - return new DenseVector(size()); - } - - @Override - public Vector like(int cardinality) { - return new DenseVector(cardinality); - } - - @Override - public void setQuick(int index, double value) { - invalidateCachedLength(); - values[index] = value; - } - - @Override - public void incrementQuick(int index, double increment) { - invalidateCachedLength(); - values[index] += increment; - } - - @Override - public Vector assign(double value) { - invalidateCachedLength(); - Arrays.fill(values, value); - return this; - } - - @Override - public int getNumNondefaultElements() { - return values.length; - } - - @Override - public int getNumNonZeroElements() { - int numNonZeros = 0; - for (int index = 0; index < values.length; index++) { - if (values[index] != 0) { - numNonZeros++; - } - } - return numNonZeros; - } - - public Vector assign(DenseVector vector) { - // make sure the data field has the correct length - if (vector.values.length != this.values.length) { - this.values = new double[vector.values.length]; - } - // now copy the values - System.arraycopy(vector.values, 0, this.values, 0, this.values.length); - return this; - } - - @Override - public void mergeUpdates(OrderedIntDoubleMapping updates) { - int numUpdates = updates.getNumMappings(); - int[] indices = updates.getIndices(); - double[] values = updates.getValues(); - for (int i = 0; i < numUpdates; ++i) { - this.values[indices[i]] = values[i]; - } - } - - @Override - public Vector viewPart(int offset, int length) { - if (offset < 0) { - throw new IndexException(offset, size()); - } - if (offset + length > size()) { - throw new IndexException(offset + length, size()); - } - return new DenseVectorView(this, offset, length); - } - - @Override - public double getLookupCost() { - return 1; - } - - @Override - public double getIteratorAdvanceCost() { - return 1; - } - - @Override - public boolean isAddConstantTime() { - return true; - } - - /** - * Returns an iterator that traverses this Vector from 0 to cardinality-1, in that order. - */ - @Override - public Iterator<Element> iterateNonZero() { - return new NonDefaultIterator(); - } - - @Override - public Iterator<Element> iterator() { - return new AllIterator(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof DenseVector) { - // Speedup for DenseVectors - return Arrays.equals(values, ((DenseVector) o).values); - } - return super.equals(o); - } - - public void addAll(Vector v) { - if (size() != v.size()) { - throw new CardinalityException(size(), v.size()); - } - - for (Element element : v.nonZeroes()) { - values[element.index()] += element.get(); - } - } - - private final class NonDefaultIterator implements Iterator<Element> { - private final DenseElement element = new DenseElement(); - private int index = -1; - private int lookAheadIndex = -1; - - @Override - public boolean hasNext() { - if (lookAheadIndex == index) { // User calls hasNext() after a next() - lookAhead(); - } // else user called hasNext() repeatedly. - return lookAheadIndex < size(); - } - - private void lookAhead() { - lookAheadIndex++; - while (lookAheadIndex < size() && values[lookAheadIndex] == 0.0) { - lookAheadIndex++; - } - } - - @Override - public Element next() { - if (lookAheadIndex == index) { // If user called next() without checking hasNext(). - lookAhead(); - } - - Preconditions.checkState(lookAheadIndex > index); - index = lookAheadIndex; - - if (index >= size()) { // If the end is reached. - throw new NoSuchElementException(); - } - - element.index = index; - return element; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - private final class AllIterator implements Iterator<Element> { - private final DenseElement element = new DenseElement(); - - private AllIterator() { - element.index = -1; - } - - @Override - public boolean hasNext() { - return element.index + 1 < size(); - } - - @Override - public Element next() { - if (element.index + 1 >= size()) { // If the end is reached. - throw new NoSuchElementException(); - } - element.index++; - return element; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - private final class DenseElement implements Element { - int index; - - @Override - public double get() { - return values[index]; - } - - @Override - public int index() { - return index; - } - - @Override - public void set(double value) { - invalidateCachedLength(); - values[index] = value; - } - } - - private final class DenseVectorView extends VectorView { - - public DenseVectorView(Vector vector, int offset, int cardinality) { - super(vector, offset, cardinality); - } - - @Override - public double dot(Vector x) { - - // Apply custom dot kernels for pairs of dense vectors or their views to reduce - // view indirection. - if (x instanceof DenseVectorView) { - - if (size() != x.size()) - throw new IllegalArgumentException("Cardinality mismatch during dot(x,y)."); - - DenseVectorView xv = (DenseVectorView) x; - double[] thisValues = ((DenseVector) vector).values; - double[] thatValues = ((DenseVector) xv.vector).values; - int untilOffset = offset + size(); - - int i, j; - double sum = 0.0; - - // Provoking SSE - int until4 = offset + (size() & ~3); - for ( - i = offset, j = xv.offset; - i < until4; - i += 4, j += 4 - ) { - sum += thisValues[i] * thatValues[j] + - thisValues[i + 1] * thatValues[j + 1] + - thisValues[i + 2] * thatValues[j + 2] + - thisValues[i + 3] * thatValues[j + 3]; - } - - // Picking up the slack - for ( - i = offset, j = xv.offset; - i < untilOffset; - ) { - sum += thisValues[i++] * thatValues[j++]; - } - return sum; - - } else if (x instanceof DenseVector ) { - - if (size() != x.size()) - throw new IllegalArgumentException("Cardinality mismatch during dot(x,y)."); - - DenseVector xv = (DenseVector) x; - double[] thisValues = ((DenseVector) vector).values; - double[] thatValues = xv.values; - int untilOffset = offset + size(); - - int i, j; - double sum = 0.0; - - // Provoking SSE - int until4 = offset + (size() & ~3); - for ( - i = offset, j = 0; - i < until4; - i += 4, j += 4 - ) { - sum += thisValues[i] * thatValues[j] + - thisValues[i + 1] * thatValues[j + 1] + - thisValues[i + 2] * thatValues[j + 2] + - thisValues[i + 3] * thatValues[j + 3]; - } - - // Picking up slack - for ( ; - i < untilOffset; - ) { - sum += thisValues[i++] * thatValues[j++]; - } - return sum; - - } else { - return super.dot(x); - } - } - - @Override - public Vector viewPart(int offset, int length) { - if (offset < 0) { - throw new IndexException(offset, size()); - } - if (offset + length > size()) { - throw new IndexException(offset + length, size()); - } - return new DenseVectorView(vector, offset + this.offset, length); - } - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/DiagonalMatrix.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/DiagonalMatrix.java b/math/src/main/java/org/apache/mahout/math/DiagonalMatrix.java deleted file mode 100644 index 070fad2..0000000 --- a/math/src/main/java/org/apache/mahout/math/DiagonalMatrix.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.flavor.MatrixFlavor; -import org.apache.mahout.math.flavor.TraversingStructureEnum; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public class DiagonalMatrix extends AbstractMatrix implements MatrixTimesOps { - private final Vector diagonal; - - public DiagonalMatrix(Vector values) { - super(values.size(), values.size()); - this.diagonal = values; - } - - public DiagonalMatrix(Matrix values) { - this(values.viewDiagonal()); - } - - public DiagonalMatrix(double value, int size) { - this(new ConstantVector(value, size)); - } - - public DiagonalMatrix(double[] values) { - super(values.length, values.length); - this.diagonal = new DenseVector(values); - } - - public static DiagonalMatrix identity(int size) { - return new DiagonalMatrix(1, size); - } - - @Override - public Matrix assignColumn(int column, Vector other) { - throw new UnsupportedOperationException("Can't assign a column to a diagonal matrix"); - } - - /** - * Assign the other vector values to the row of the receiver - * - * @param row the int row to assign - * @param other a Vector - * @return the modified receiver - * @throws CardinalityException if the cardinalities differ - */ - @Override - public Matrix assignRow(int row, Vector other) { - throw new UnsupportedOperationException("Can't assign a row to a diagonal matrix"); - } - - @Override - public Vector viewRow(int row) { - return new SingleElementVector(row); - } - - @Override - public Vector viewColumn(int row) { - return new SingleElementVector(row); - } - - /** - * Special class to implement views of rows and columns of a diagonal matrix. - */ - public class SingleElementVector extends AbstractVector { - private int index; - - public SingleElementVector(int index) { - super(diagonal.size()); - this.index = index; - } - - @Override - public double getQuick(int index) { - if (index == this.index) { - return diagonal.get(index); - } else { - return 0; - } - } - - @Override - public void set(int index, double value) { - if (index == this.index) { - diagonal.set(index, value); - } else { - throw new IllegalArgumentException("Can't set off-diagonal element of diagonal matrix"); - } - } - - @Override - protected Iterator<Element> iterateNonZero() { - return new Iterator<Element>() { - boolean more = true; - - @Override - public boolean hasNext() { - return more; - } - - @Override - public Element next() { - if (more) { - more = false; - return new Element() { - @Override - public double get() { - return diagonal.get(index); - } - - @Override - public int index() { - return index; - } - - @Override - public void set(double value) { - diagonal.set(index, value); - } - }; - } else { - throw new NoSuchElementException("Only one non-zero element in a row or column of a diagonal matrix"); - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Can't remove from vector view"); - } - }; - } - - @Override - protected Iterator<Element> iterator() { - return new Iterator<Element>() { - int i = 0; - - Element r = new Element() { - @Override - public double get() { - if (i == index) { - return diagonal.get(index); - } else { - return 0; - } - } - - @Override - public int index() { - return i; - } - - @Override - public void set(double value) { - if (i == index) { - diagonal.set(index, value); - } else { - throw new IllegalArgumentException("Can't set any element but diagonal"); - } - } - }; - - @Override - public boolean hasNext() { - return i < diagonal.size() - 1; - } - - @Override - public Element next() { - if (i < SingleElementVector.this.size() - 1) { - i++; - return r; - } else { - throw new NoSuchElementException("Attempted to access passed last element of vector"); - } - } - - - @Override - public void remove() { - throw new UnsupportedOperationException("Default operation"); - } - }; - } - - @Override - protected Matrix matrixLike(int rows, int columns) { - return new DiagonalMatrix(rows, columns); - } - - @Override - public boolean isDense() { - return false; - } - - @Override - public boolean isSequentialAccess() { - return true; - } - - @Override - public void mergeUpdates(OrderedIntDoubleMapping updates) { - throw new UnsupportedOperationException("Default operation"); - } - - @Override - public Vector like() { - return new DenseVector(size()); - } - - @Override - public Vector like(int cardinality) { - return new DenseVector(cardinality); - } - - @Override - public void setQuick(int index, double value) { - if (index == this.index) { - diagonal.set(this.index, value); - } else { - throw new IllegalArgumentException("Can't set off-diagonal element of DiagonalMatrix"); - } - } - - @Override - public int getNumNondefaultElements() { - return 1; - } - - @Override - public double getLookupCost() { - return 0; - } - - @Override - public double getIteratorAdvanceCost() { - return 1; - } - - @Override - public boolean isAddConstantTime() { - return false; - } - } - - /** - * Provides a view of the diagonal of a matrix. - */ - @Override - public Vector viewDiagonal() { - return this.diagonal; - } - - /** - * Return the value at the given location, without checking bounds - * - * @param row an int row index - * @param column an int column index - * @return the double at the index - */ - @Override - public double getQuick(int row, int column) { - if (row == column) { - return diagonal.get(row); - } else { - return 0; - } - } - - /** - * Return an empty matrix of the same underlying class as the receiver - * - * @return a Matrix - */ - @Override - public Matrix like() { - return new SparseRowMatrix(rowSize(), columnSize()); - } - - /** - * Returns an empty matrix of the same underlying class as the receiver and of the specified - * size. - * - * @param rows the int number of rows - * @param columns the int number of columns - */ - @Override - public Matrix like(int rows, int columns) { - return new SparseRowMatrix(rows, columns); - } - - @Override - public void setQuick(int row, int column, double value) { - if (row == column) { - diagonal.set(row, value); - } else { - throw new UnsupportedOperationException("Can't set off-diagonal element"); - } - } - - /** - * Return the number of values in the recipient - * - * @return an int[2] containing [row, column] count - */ - @Override - public int[] getNumNondefaultElements() { - throw new UnsupportedOperationException("Don't understand how to implement this"); - } - - /** - * Return a new matrix containing the subset of the recipient - * - * @param offset an int[2] offset into the receiver - * @param size the int[2] size of the desired result - * @return a new Matrix that is a view of the original - * @throws CardinalityException if the length is greater than the cardinality of the receiver - * @throws IndexException if the offset is negative or the offset+length is outside of the - * receiver - */ - @Override - public Matrix viewPart(int[] offset, int[] size) { - return new MatrixView(this, offset, size); - } - - @Override - public Matrix times(Matrix other) { - return timesRight(other); - } - - @Override - public Matrix timesRight(Matrix that) { - if (that.numRows() != diagonal.size()) { - throw new IllegalArgumentException("Incompatible number of rows in the right operand of matrix multiplication."); - } - Matrix m = that.like(); - for (int row = 0; row < diagonal.size(); row++) { - m.assignRow(row, that.viewRow(row).times(diagonal.getQuick(row))); - } - return m; - } - - @Override - public Matrix timesLeft(Matrix that) { - if (that.numCols() != diagonal.size()) { - throw new IllegalArgumentException( - "Incompatible number of rows in the left operand of matrix-matrix multiplication."); - } - Matrix m = that.like(); - for (int col = 0; col < diagonal.size(); col++) { - m.assignColumn(col, that.viewColumn(col).times(diagonal.getQuick(col))); - } - return m; - } - - @Override - public MatrixFlavor getFlavor() { - return MatrixFlavor.DIAGONALLIKE; - } - -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/FileBasedMatrix.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/FileBasedMatrix.java b/math/src/main/java/org/apache/mahout/math/FileBasedMatrix.java deleted file mode 100644 index 3a19318..0000000 --- a/math/src/main/java/org/apache/mahout/math/FileBasedMatrix.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.DoubleBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.util.List; - -/** - * Provides a way to get data from a file and treat it as if it were a matrix, but avoids putting all that - * data onto the Java heap. Instead, the file is mapped into non-heap memory as a DoubleBuffer and we access - * that instead. - */ -public final class FileBasedMatrix extends AbstractMatrix { - private final int rowsPerBlock; - private final List<DoubleBuffer> content = Lists.newArrayList(); - - /** - * Constructs an empty matrix of the given size. - * - * @param rows The number of rows in the result. - * @param columns The number of columns in the result. - */ - public FileBasedMatrix(int rows, int columns) { - super(rows, columns); - long maxRows = ((1L << 31) - 1) / (columns * 8); - if (rows > maxRows) { - rowsPerBlock = (int) maxRows; - } else { - rowsPerBlock = rows; - } - } - - private void addData(DoubleBuffer content) { - this.content.add(content); - } - - public void setData(File f, boolean loadNow) throws IOException { - Preconditions.checkArgument(f.length() == rows * columns * 8L, "File " + f + " is wrong length"); - - for (int i = 0; i < (rows + rowsPerBlock - 1) / rowsPerBlock; i++) { - long start = i * rowsPerBlock * columns * 8L; - long size = rowsPerBlock * columns * 8L; - MappedByteBuffer buf = new FileInputStream(f).getChannel().map(FileChannel.MapMode.READ_ONLY, start, - Math.min(f.length() - start, size)); - if (loadNow) { - buf.load(); - } - addData(buf.asDoubleBuffer()); - } - } - - public static void writeMatrix(File f, Matrix m) throws IOException { - Preconditions.checkArgument(f.canWrite(), "Can't write to output file"); - FileOutputStream fos = new FileOutputStream(f); - try { - ByteBuffer buf = ByteBuffer.allocate(m.columnSize() * 8); - for (MatrixSlice row : m) { - buf.clear(); - for (Vector.Element element : row.vector().all()) { - buf.putDouble(element.get()); - } - buf.flip(); - fos.write(buf.array()); - } - } finally { - fos.close(); - } - } - - /** - * Assign the other vector values to the column of the receiver - * - * @param column the int row to assign - * @param other a Vector - * @return the modified receiver - * @throws org.apache.mahout.math.CardinalityException - * if the cardinalities differ - */ - @Override - public Matrix assignColumn(int column, Vector other) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Assign the other vector values to the row of the receiver - * - * @param row the int row to assign - * @param other a Vector - * @return the modified receiver - * @throws org.apache.mahout.math.CardinalityException - * if the cardinalities differ - */ - @Override - public Matrix assignRow(int row, Vector other) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Return the value at the given indexes, without checking bounds - * - * @param row an int row index - * @param column an int column index - * @return the double at the index - */ - @Override - public double getQuick(int row, int column) { - int block = row / rowsPerBlock; - return content.get(block).get((row % rowsPerBlock) * columns + column); - } - - /** - * Return an empty matrix of the same underlying class as the receiver - * - * @return a Matrix - */ - @Override - public Matrix like() { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Returns an empty matrix of the same underlying class as the receiver and of the specified size. - * - * @param rows the int number of rows - * @param columns the int number of columns - */ - @Override - public Matrix like(int rows, int columns) { - return new DenseMatrix(rows, columns); - } - - /** - * Set the value at the given index, without checking bounds - * - * @param row an int row index into the receiver - * @param column an int column index into the receiver - * @param value a double value to set - */ - @Override - public void setQuick(int row, int column, double value) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Return a view into part of a matrix. Changes to the view will change the - * original matrix. - * - * @param offset an int[2] offset into the receiver - * @param size the int[2] size of the desired result - * @return a matrix that shares storage with part of the original matrix. - * @throws org.apache.mahout.math.CardinalityException - * if the length is greater than the cardinality of the receiver - * @throws org.apache.mahout.math.IndexException - * if the offset is negative or the offset+length is outside of the receiver - */ - @Override - public Matrix viewPart(int[] offset, int[] size) { - throw new UnsupportedOperationException("Default operation"); - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/FileBasedSparseBinaryMatrix.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/FileBasedSparseBinaryMatrix.java b/math/src/main/java/org/apache/mahout/math/FileBasedSparseBinaryMatrix.java deleted file mode 100644 index 0b0c25e..0000000 --- a/math/src/main/java/org/apache/mahout/math/FileBasedSparseBinaryMatrix.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.nio.channels.FileChannel; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.common.collect.AbstractIterator; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -/** - * Provides a way to get data from a file and treat it as if it were a matrix, but avoids putting - * all that data onto the Java heap. Instead, the file is mapped into non-heap memory as a - * DoubleBuffer and we access that instead. The interesting aspect of this is that the values in - * the matrix are binary and sparse so we don't need to store the actual data, just the location of - * non-zero values. - * <p> - * Currently file data is formatted as follows: - * <p> - * <ul> <li>A magic number to indicate the file format.</li> <li>The size of the matrix (max rows - * and columns possible)</li> <li>Number of non-zeros in each row.</li> <li>A list of non-zero - * columns for each row. The list starts with a count and then has column numbers</li> </ul> - * <p> - * It would be preferable to use something like protobufs to define the format so that we can use - * different row formats for different kinds of data. For instance, Golay coding of column numbers - * or compressed bit vectors might be good representations for some purposes. - */ -public final class FileBasedSparseBinaryMatrix extends AbstractMatrix { - private static final int MAGIC_NUMBER_V0 = 0x12d7067d; - - private final List<IntBuffer> data = Lists.newArrayList(); - private int[] bufferIndex; - private int[] rowOffset; - private int[] rowSize; - - /** - * Constructs an empty matrix of the given size. - * - * @param rows The number of rows in the result. - * @param columns The number of columns in the result. - */ - public FileBasedSparseBinaryMatrix(int rows, int columns) { - super(rows, columns); - } - - public void setData(File f) throws IOException { - List<ByteBuffer> buffers = Lists.newArrayList(); - FileChannel input = new FileInputStream(f).getChannel(); - - buffers.add(input.map(FileChannel.MapMode.READ_ONLY, 0, Math.min(Integer.MAX_VALUE, f.length()))); - data.add(buffers.get(0).asIntBuffer()); - Preconditions.checkArgument(buffers.get(0).getInt() == MAGIC_NUMBER_V0, "Wrong type of file"); - - int rows = buffers.get(0).getInt(); - int cols = buffers.get(0).getInt(); - Preconditions.checkArgument(rows == rowSize()); - Preconditions.checkArgument(cols == columnSize()); - - rowOffset = new int[rows]; - rowSize = new int[rows]; - bufferIndex = new int[rows]; - - int offset = 12 + 4 * rows; - for (int i = 0; i < rows; i++) { - int size = buffers.get(0).getInt(); - int buffer = 0; - while (buffer < buffers.size()) { - if (offset + size * 4 <= buffers.get(buffer).limit()) { - break; - } else { - offset -= buffers.get(buffer).capacity(); - } - } - if (buffer == buffers.size()) { - buffers.add(input.map(FileChannel.MapMode.READ_ONLY, 0, Math.min(Integer.MAX_VALUE, f.length() - offset))); - data.add(buffers.get(buffer).asIntBuffer()); - } - rowOffset[i] = offset / 4; - rowSize[i] = size; - bufferIndex[i] = buffer; - -// final SparseBinaryVector v = new SparseBinaryVector(buffers.get(buffer), columns, offset, size); -// this.rows.add(v); - offset += size * 4; - } - } - - public static void writeMatrix(File f, Matrix m) throws IOException { - Preconditions.checkArgument(f.canWrite(), "Can't write to output file"); - FileOutputStream fos = new FileOutputStream(f); - - // write header - DataOutputStream out = new DataOutputStream(fos); - out.writeInt(MAGIC_NUMBER_V0); - out.writeInt(m.rowSize()); - out.writeInt(m.columnSize()); - - // compute offsets and write row headers - for (MatrixSlice row : m) { - int nondefaultElements = row.vector().getNumNondefaultElements(); - out.writeInt(nondefaultElements); - } - - // write rows - for (MatrixSlice row : m) { - List<Integer> columns = Lists.newArrayList(Iterables.transform(row.vector().nonZeroes(), - new Function<Vector.Element, Integer>() { - @Override - public Integer apply(Vector.Element element) { - return element.index(); - } - })); - Collections.sort(columns); - - for (Integer column : columns) { - out.writeInt(column); - } - } - - out.close(); - fos.close(); - } - - /** - * Assign the other vector values to the column of the receiver - * - * @param column the int row to assign - * @param other a Vector - * @return the modified receiver - * @throws org.apache.mahout.math.CardinalityException - * if the cardinalities differ - */ - @Override - public Matrix assignColumn(int column, Vector other) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Assign the other vector values to the row of the receiver - * - * @param row the int row to assign - * @param other a Vector - * @return the modified receiver - * @throws org.apache.mahout.math.CardinalityException - * if the cardinalities differ - */ - @Override - public Matrix assignRow(int row, Vector other) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Return the value at the given indexes, without checking bounds - * - * @param rowIndex an int row index - * @param columnIndex an int column index - * @return the double at the index - */ - @Override - public double getQuick(int rowIndex, int columnIndex) { - IntBuffer tmp = data.get(bufferIndex[rowIndex]).asReadOnlyBuffer(); - tmp.position(rowOffset[rowIndex]); - tmp.limit(rowSize[rowIndex]); - tmp = tmp.slice(); - return searchForIndex(tmp, columnIndex); - } - - private static double searchForIndex(IntBuffer row, int columnIndex) { - int high = row.limit(); - if (high == 0) { - return 0; - } - int low = 0; - while (high > low) { - int mid = (low + high) / 2; - if (row.get(mid) < columnIndex) { - low = mid + 1; - } else { - high = mid; - } - } - if (low >= row.limit()) { - return 0; - } else if (high == low && row.get(low) == columnIndex) { - return 1; - } else { - return 0; - } - } - - /** - * Return an empty matrix of the same underlying class as the receiver - * - * @return a Matrix - */ - @Override - public Matrix like() { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Returns an empty matrix of the same underlying class as the receiver and of the specified - * size. - * - * @param rows the int number of rows - * @param columns the int number of columns - */ - @Override - public Matrix like(int rows, int columns) { - return new DenseMatrix(rows, columns); - } - - /** - * Set the value at the given index, without checking bounds - * - * @param row an int row index into the receiver - * @param column an int column index into the receiver - * @param value a double value to set - */ - @Override - public void setQuick(int row, int column, double value) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Return a view into part of a matrix. Changes to the view will change the original matrix. - * - * @param offset an int[2] offset into the receiver - * @param size the int[2] size of the desired result - * @return a matrix that shares storage with part of the original matrix. - * @throws org.apache.mahout.math.CardinalityException - * if the length is greater than the cardinality of the receiver - * @throws org.apache.mahout.math.IndexException - * if the offset is negative or the offset+length is outside of the receiver - */ - @Override - public Matrix viewPart(int[] offset, int[] size) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Returns a view of a row. Changes to the view will affect the original. - * - * @param rowIndex Which row to return. - * @return A vector that references the desired row. - */ - @Override - public Vector viewRow(int rowIndex) { - IntBuffer tmp = data.get(bufferIndex[rowIndex]).asReadOnlyBuffer(); - tmp.position(rowOffset[rowIndex]); - tmp.limit(rowOffset[rowIndex] + rowSize[rowIndex]); - tmp = tmp.slice(); - return new SparseBinaryVector(tmp, columnSize()); - } - - private static class SparseBinaryVector extends AbstractVector { - private final IntBuffer buffer; - private final int maxIndex; - - private SparseBinaryVector(IntBuffer buffer, int maxIndex) { - super(maxIndex); - this.buffer = buffer; - this.maxIndex = maxIndex; - } - - SparseBinaryVector(ByteBuffer row, int maxIndex, int offset, int size) { - super(maxIndex); - row = row.asReadOnlyBuffer(); - row.position(offset); - row.limit(offset + size * 4); - row = row.slice(); - this.buffer = row.slice().asIntBuffer(); - this.maxIndex = maxIndex; - } - - /** - * Subclasses must override to return an appropriately sparse or dense result - * - * @param rows the row cardinality - * @param columns the column cardinality - * @return a Matrix - */ - @Override - protected Matrix matrixLike(int rows, int columns) { - throw new UnsupportedOperationException("Default operation"); - } - - /** - * Used internally by assign() to update multiple indices and values at once. - * Only really useful for sparse vectors (especially SequentialAccessSparseVector). - * <p/> - * If someone ever adds a new type of sparse vectors, this method must merge (index, value) pairs into the vector. - * - * @param updates a mapping of indices to values to merge in the vector. - */ - @Override - public void mergeUpdates(OrderedIntDoubleMapping updates) { - throw new UnsupportedOperationException("Cannot mutate SparseBinaryVector"); - } - - /** - * @return true iff this implementation should be considered dense -- that it explicitly represents - * every value - */ - @Override - public boolean isDense() { - return false; - } - - /** - * @return true iff this implementation should be considered to be iterable in index order in an - * efficient way. In particular this implies that {@link #iterator()} and {@link - * #iterateNonZero()} return elements in ascending order by index. - */ - @Override - public boolean isSequentialAccess() { - return true; - } - - /** - * Iterates over all elements - * - * NOTE: Implementations may choose to reuse the Element returned - * for performance reasons, so if you need a copy of it, you should call {@link #getElement(int)} - * for the given index - * - * @return An {@link java.util.Iterator} over all elements - */ - @Override - public Iterator<Element> iterator() { - return new AbstractIterator<Element>() { - int i = 0; - - @Override - protected Element computeNext() { - if (i < maxIndex) { - return new Element() { - int index = i++; - /** - * @return the value of this vector element. - */ - @Override - public double get() { - return getQuick(index); - } - - /** - * @return the index of this vector element. - */ - @Override - public int index() { - return index; - } - - /** - * @param value Set the current element to value. - */ - @Override - public void set(double value) { - throw new UnsupportedOperationException("Default operation"); - } - }; - } else { - return endOfData(); - } - } - }; - } - - /** - * Iterates over all non-zero elements. <p/> NOTE: Implementations may choose to reuse the Element - * returned for performance reasons, so if you need a copy of it, you should call {@link - * #getElement(int)} for the given index - * - * @return An {@link java.util.Iterator} over all non-zero elements - */ - @Override - public Iterator<Element> iterateNonZero() { - return new AbstractIterator<Element>() { - int i = 0; - @Override - protected Element computeNext() { - if (i < buffer.limit()) { - return new BinaryReadOnlyElement(buffer.get(i++)); - } else { - return endOfData(); - } - } - }; - } - - /** - * Return the value at the given index, without checking bounds - * - * @param index an int index - * @return the double at the index - */ - @Override - public double getQuick(int index) { - return searchForIndex(buffer, index); - } - - /** - * Return an empty vector of the same underlying class as the receiver - * - * @return a Vector - */ - @Override - public Vector like() { - return new RandomAccessSparseVector(size()); - } - - @Override - public Vector like(int cardinality) { - return new RandomAccessSparseVector(cardinality); - } - - /** - * Copy the vector for fast operations. - * - * @return a Vector - */ - @Override - protected Vector createOptimizedCopy() { - return new RandomAccessSparseVector(size()).assign(this); - } - - /** - * Set the value at the given index, without checking bounds - * - * @param index an int index into the receiver - * @param value a double value to set - */ - @Override - public void setQuick(int index, double value) { - throw new UnsupportedOperationException("Read-only view"); - } - - /** - * Set the value at the given index, without checking bounds - * - * @param index an int index into the receiver - * @param increment a double value to set - */ - @Override - public void incrementQuick(int index, double increment) { - throw new UnsupportedOperationException("Read-only view"); - } - - /** - * Return the number of values in the recipient which are not the default value. For instance, for - * a sparse vector, this would be the number of non-zero values. - * - * @return an int - */ - @Override - public int getNumNondefaultElements() { - return buffer.limit(); - } - - @Override - public double getLookupCost() { - return 1; - } - - @Override - public double getIteratorAdvanceCost() { - return 1; - } - - @Override - public boolean isAddConstantTime() { - throw new UnsupportedOperationException("Can't add binary value"); - } - } - - public static class BinaryReadOnlyElement implements Vector.Element { - private final int index; - - public BinaryReadOnlyElement(int index) { - this.index = index; - } - - /** - * @return the value of this vector element. - */ - @Override - public double get() { - return 1; - } - - /** - * @return the index of this vector element. - */ - @Override - public int index() { - return index; - } - - /** - * @param value Set the current element to value. - */ - @Override - public void set(double value) { - throw new UnsupportedOperationException("Can't set binary value"); - } - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/FunctionalMatrixView.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/FunctionalMatrixView.java b/math/src/main/java/org/apache/mahout/math/FunctionalMatrixView.java deleted file mode 100644 index 9028e23..0000000 --- a/math/src/main/java/org/apache/mahout/math/FunctionalMatrixView.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -import org.apache.mahout.math.flavor.BackEnum; -import org.apache.mahout.math.flavor.MatrixFlavor; -import org.apache.mahout.math.flavor.TraversingStructureEnum; -import org.apache.mahout.math.function.IntIntFunction; - -/** - * Matrix View backed by an {@link IntIntFunction} - */ -class FunctionalMatrixView extends AbstractMatrix { - - /** - * view generator function - */ - private IntIntFunction gf; - private boolean denseLike; - private MatrixFlavor flavor; - - public FunctionalMatrixView(int rows, int columns, IntIntFunction gf) { - this(rows, columns, gf, false); - } - - /** - * @param gf generator function - * @param denseLike whether like() should create Dense or Sparse matrix. - */ - public FunctionalMatrixView(int rows, int columns, IntIntFunction gf, boolean denseLike) { - super(rows, columns); - this.gf = gf; - this.denseLike = denseLike; - flavor = new MatrixFlavor.FlavorImpl(BackEnum.JVMMEM, TraversingStructureEnum.BLOCKIFIED, denseLike); - } - - @Override - public Matrix assignColumn(int column, Vector other) { - throw new UnsupportedOperationException("Assignment to a matrix not supported"); - } - - @Override - public Matrix assignRow(int row, Vector other) { - throw new UnsupportedOperationException("Assignment to a matrix view not supported"); - } - - @Override - public double getQuick(int row, int column) { - return gf.apply(row, column); - } - - @Override - public Matrix like() { - return like(rows, columns); - } - - @Override - public Matrix like(int rows, int columns) { - if (denseLike) - return new DenseMatrix(rows, columns); - else - return new SparseMatrix(rows, columns); - } - - @Override - public void setQuick(int row, int column, double value) { - throw new UnsupportedOperationException("Assignment to a matrix view not supported"); - } - - @Override - public Vector viewRow(int row) { - return new MatrixVectorView(this, row, 0, 0, 1, denseLike); - } - - @Override - public Vector viewColumn(int column) { - return new MatrixVectorView(this, 0, column, 1, 0, denseLike); - } - - @Override - public MatrixFlavor getFlavor() { - return flavor; - } -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/IndexException.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/IndexException.java b/math/src/main/java/org/apache/mahout/math/IndexException.java deleted file mode 100644 index 489d536..0000000 --- a/math/src/main/java/org/apache/mahout/math/IndexException.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -/** - * Exception thrown when a matrix or vector is accessed at an index, or dimension, - * which does not logically exist in the entity. - */ -public class IndexException extends IllegalArgumentException { - - public IndexException(int index, int cardinality) { - super("Index " + index + " is outside allowable range of [0," + cardinality + ')'); - } - -} http://git-wip-us.apache.org/repos/asf/mahout/blob/e0573de3/math/src/main/java/org/apache/mahout/math/LengthCachingVector.java ---------------------------------------------------------------------- diff --git a/math/src/main/java/org/apache/mahout/math/LengthCachingVector.java b/math/src/main/java/org/apache/mahout/math/LengthCachingVector.java deleted file mode 100644 index 770ccc4..0000000 --- a/math/src/main/java/org/apache/mahout/math/LengthCachingVector.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.mahout.math; - -/** - * Marker interface for vectors that may cache their squared length. - */ -interface LengthCachingVector { - /** - * Gets the currently cached squared length or if there is none, recalculates - * the value and returns that. - * @return The sum of the squares of all elements in the vector. - */ - double getLengthSquared(); - - /** - * Invalidates the length cache. This should be called by all mutators of the vector. - */ - void invalidateCachedLength(); -}
