/** * {@inheritDoc} * * NOTE: Upon completion this is in the compressed Yale format. * @return {@inheritDoc} */ @Override public final Matrix times( final DiagonalMatrix other) { this.assertMultiplicationDimensions(other); if (!isCompressed()) { compress(); } SparseMatrix result = new SparseMatrix(getNumRows(), getNumColumns()); result.columnIndices = Arrays.copyOf(columnIndices, columnIndices.length); result.firstIndicesForRows = Arrays.copyOf(firstIndicesForRows, firstIndicesForRows.length); result.values = new double[values.length]; for (int i = 0; i < values.length; ++i) { result.values[i] = values[i] * other.get(columnIndices[i], columnIndices[i]); } return result; }
/** * {@inheritDoc} * * NOTE: Upon completion, this is in compressed Yale format. Returned sparse * matrix is in sparse vector format. * * @return {@inheritDoc} */ @Override final public Matrix transpose() { SparseMatrix result = new SparseMatrix(numCols, numRows); if (!isCompressed()) { compress(); } int rowNum = 0; for (int i = 0; i < values.length; ++i) { while (i >= firstIndicesForRows[rowNum + 1]) { ++rowNum; } result.setElement(columnIndices[i], rowNum, values[i]); } return result; }
final SparseMatrix other) this.assertSameDimensions(other); if (!isCompressed()) compress(); if (!other.isCompressed()) other.compress(); int nnzAfter = getNumNonZeroWhenCombinedWith(other.columnIndices, other.firstIndicesForRows, Combiner.OR); int[] newFirstIdxsForRows = new int[getNumRows() + 1]; plusEqualsScaled(newColIdxs, newFirstIdxsForRows, newVals, other, 1);
@Override public int getEntryCount() { if (!this.isCompressed()) { this.compress(); } return this.values.length; }
/** * Package-private helper that allows other matrices direct access to * setting the sparse vector rows of this. Be very careful when calling this * -- you have direct access to the data! * * NOTE: Upon completion, this is in the sparse vector format. * * @param i The row index * @param v The vector that to put in the new row */ final void setRowInternal( final int i, final SparseVector v) { if (isCompressed()) { decompress(); } rows[i] = v; }
/** * {@inheritDoc} * * NOTE: Upon completion this is in the compressed Yale format. */ @Override public final void plusEquals( final DiagonalMatrix other) { this.assertSameDimensions(other); if (!isCompressed()) { compress(); } // Count the number of new values to add. int nnz = getNumNonZeroWhenCombinedWith(getZeroToNMinusOneArray( other.getNumRows()), getZeroToNMinusOneArray(other.getNumRows() + 1), Combiner.OR); // Now start up the values for the sum matrix double[] newVals = new double[nnz]; int[] newFirstIdxsForRows = new int[firstIndicesForRows.length]; int[] newColIdxs = new int[nnz]; // Now do the logic for adding plusEqualsScaled(newColIdxs, newFirstIdxsForRows, newVals, other, 1); // Now store the new values in me values = newVals; columnIndices = newColIdxs; firstIndicesForRows = newFirstIdxsForRows; }
/** * {@inheritDoc} * * NOTE: Upon completion this is in the compressed Yale format. * * @return {@inheritDoc} */ @Override public final Vector preTimes( final DenseVector vector) { vector.assertDimensionalityEquals(this.getNumRows()); if (!isCompressed()) { compress(); } DenseVector result = new DenseVector(getNumColumns()); int row = 0; for (int i = 0; i < values.length; ++i) { while (i >= firstIndicesForRows[row + 1]) { ++row; } result.setElement(columnIndices[i], result.get(columnIndices[i]) + vector.get(row) * values[i]); } return result; }
final DenseMatrix other) this.assertMultiplicationDimensions(other); if (!isCompressed()) compress(); DenseMatrix result = new DenseMatrix(getNumRows(), otherNumColumns); int curRow = 0; for (int i = 0; i < values.length; ++i)
final int maxColumn) checkSubmatrixRange(minRow, maxRow, minColumn, maxColumn); if (!isCompressed()) compress(); SparseMatrix result = new SparseMatrix(maxRow - minRow + 1, maxColumn - minColumn + 1, true);
/** * Helper method converts P into a pivot matrix that can pre-multiply * L*U. * * @return an identity matrix with the appropriate row swaps to * re-generate the original matrix A when P * L * U is calculated. */ public Matrix getPivotMatrix() { SparseMatrix pivot = new SparseMatrix(L.getNumRows(), L.getNumRows()); pivot.identity(); for (int i = 0; i < P.size(); ++i) { if (P.get(i) != i) { Vector tmp = pivot.getRow(i); pivot.setRow(i, pivot.getRow(P.get(i))); pivot.setRow(P.get(i), tmp); } } return pivot; }
@Override final public Matrix getSubMatrix( final int minRow, final int maxRow, final int minColumn, final int maxColumn) { checkSubmatrixRange(minRow, maxRow, minColumn, maxColumn); SparseMatrix result = new SparseMatrix(maxRow - minRow + 1, maxColumn - minColumn + 1); // You only need worry about the diagonal, so one of the extents will do for (int i = minRow; i <= maxRow; ++i) { // Check to make sure that this element of the diagonal is also in // the other extents if (i >= minColumn && i <= maxColumn) { // If it is, add it at the right place in the output result.setElement(i - minRow, i - minColumn, get(i, i)); } } return result; }
/** * {@inheritDoc} * * NOTE: Upon completion this is in the compressed Yale format. */ @Override public final void dotTimesEquals( final DenseMatrix other) { this.assertSameDimensions(other); if (!isCompressed()) { compress(); } // The shortcut I'll take here is that few of the dense matrix's values // are zero where I'm not int rownum = 0; for (int i = 0; i < values.length; ++i) { while (i >= firstIndicesForRows[rownum + 1]) { ++rownum; } values[i] *= other.get(rownum, columnIndices[i]); } }
@Override public final Matrix outerProduct( final SparseVector other) { compress(); other.compress(); int numRows = getDimensionality(); int numCols = other.getDimensionality(); SparseMatrix result = new SparseMatrix(numRows, numCols, true); int idx = 0; for (int i = 0; i < numRows; ++i) { SparseVector row = new SparseVector(numCols); if ((idx < indices.length) && (indices[idx] == i)) { for (int j = 0; j < other.indices.length; ++j) { row.elements.put(other.indices[j], new MutableDouble(values[idx] * other.values[j])); } ++idx; } result.setRowInternal(i, row); } return result; }
final SparseMatrix m) this.numCols = m.getNumColumns(); this.numRows = m.getNumRows(); rows = new SparseVector[m.rows.length]; if (m.isCompressed())
/** * NEVER call this from real code. Java's serialization code will need to * call this, but if all of the values aren't immediately filled with useful * values through introspection, the instance created with this method won't * provide useful values. */ protected MultipartiteValenceMatrix() { // NOTE: I have to pass something, but it's going to be overwritten immediately super(new SparseMatrix(1, 1)); }
/** * This method is provided so that the calling programmer can explicitly * declare when a matrix should be decompressed from the compressed Yale * format. Note that the method will be automatically compressed and * decompressed when various methods are called (e.g., decompressed for set* * methods, compressed for times, dotTimes, etc.). */ final public void decompress() { if (!isCompressed()) { return; } for (int i = 0; i < getNumRows(); ++i) { rows[i].clear(); for (int j = firstIndicesForRows[i]; j < firstIndicesForRows[i + 1]; ++j) { rows[i].setElement(columnIndices[j], values[j]); } } values = null; firstIndicesForRows = columnIndices = null; }
/** * {@inheritDoc} * * NOTE: Returned matrix is Yale format if m is Diagonal, Dense, or Sparse * in Yale format. Is sparse row if m is Sparse and in sparse row format. * * @return {@inheritDoc} */ @Override final public SparseMatrix copyMatrix( final Matrix m) { if (m instanceof SparseMatrix) { return new SparseMatrix((SparseMatrix) m); } else if (m instanceof DenseMatrix) { return new SparseMatrix((DenseMatrix) m); } else if (m instanceof DiagonalMatrix) { return new SparseMatrix((DiagonalMatrix) m); } // I have to handle other matrix types SparseMatrix result = new SparseMatrix(m.getNumRows(), m.getNumColumns()); result.convertFromVector(m.convertToVector()); return result; }
@Override public final Matrix times( final SparseMatrix other) { this.assertMultiplicationDimensions(other); if (!other.isCompressed()) { other.compress(); } final int numRows = this.getNumRows(); final DenseVector[] resultRows = new DenseVector[numRows]; for (int i = 0; i < numRows; ++i) { resultRows[i] = (DenseVector) other.preTimes(this.rows[i]); } return new DenseMatrix(resultRows); }
/** * {@inheritDoc} * * NOTE: Upon completion this is in the compressed Yale format. * * @param rowIndex {@inheritDoc} * @param columnIndex {@inheritDoc} * @param value {@inheritDoc} * @throws ArrayIndexOutOfBoundsException if the indices are out of bounds */ @Override public void set( final int rowIndex, final int columnIndex, final double value) { setElement(rowIndex, columnIndex, value); }
/** * Initializes a new iterator starting at the first value in the first * row of the matrix * * @param startRow The row to start on * @throws IllegalArgumentException if startRow is outside of [0 .. * numRows] */ public NonZeroEntryIterator( final int startRow) { if (startRow >= getNumRows() || startRow < 0) { throw new IllegalArgumentException("Input row index (" + startRow + ") greater than number of rows: " + getNumRows()); } rowIdx = startRow; columnValueIndex = firstIndicesForRows[rowIdx]; // If there are no-entry rows, we need to skip past them while (columnValueIndex >= firstIndicesForRows[rowIdx + 1]) { ++rowIdx; if (rowIdx >= numRows) { break; } } }