[mathicgb] 243/393: Fixed issue where memory consumption would suddenly explode due to converting a submatrix of a very sparse and large matrix into dense format. Very sparse matrices now have their own code-path that avoids this.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:11 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.
commit c35380f26106377ff17571db4de96b958faf272e
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Sat Apr 13 13:19:27 2013 -0400
Fixed issue where memory consumption would suddenly explode due to converting a submatrix of a very sparse and large matrix into dense format. Very sparse matrices now have their own code-path that avoids this.
---
src/mathicgb/F4MatrixReducer.cpp | 89 +++++++++++++++++++++++++++++++++++++++-
src/mathicgb/F4MatrixReducer.hpp | 2 +-
2 files changed, 88 insertions(+), 3 deletions(-)
diff --git a/src/mathicgb/F4MatrixReducer.cpp b/src/mathicgb/F4MatrixReducer.cpp
old mode 100644
new mode 100755
index f11a54d..c6e63d5
--- a/src/mathicgb/F4MatrixReducer.cpp
+++ b/src/mathicgb/F4MatrixReducer.cpp
@@ -306,6 +306,84 @@ namespace {
return std::move(reduced);
}
+ SparseMatrix reduceToEchelonFormSparse(
+ const SparseMatrix& toReduce,
+ const SparseMatrix::Scalar modulus
+ ) {
+ const auto colCount = toReduce.computeColCount();
+
+ const auto noRow = static_cast<SparseMatrix::RowIndex>(-1);
+
+ // pivotRowOfCol[i] is the pivot in column i or noRow
+ // if we have not identified such a pivot so far.
+ std::vector<SparseMatrix::RowIndex> pivotRowOfCol(colCount, noRow);
+
+ DenseRow rowToReduce(colCount);
+
+ // ** Reduce to row echelon form -- every row is a pivot row.
+ SparseMatrix pivots(colCount);
+ for (SparseMatrix::RowIndex row = 0; row < toReduce.rowCount(); ++row) {
+ if (toReduce.emptyRow(row))
+ continue;
+ rowToReduce.clear(colCount);
+ rowToReduce.addRow(toReduce, row);
+
+ SparseMatrix::ColIndex leadingCol = 0;
+ while (true) { // reduce row by previous pivots
+ for (; leadingCol < colCount; ++leadingCol) {
+ auto& entry = rowToReduce[leadingCol];
+ if (entry != 0) {
+ entry %= modulus;
+ if (entry != 0)
+ break;
+ }
+ }
+ if (leadingCol == colCount)
+ break; // The row has been reduced to zero.
+ const auto pivotRow = pivotRowOfCol[leadingCol];
+ if (pivotRow == noRow) { // If the row is a new pivot.
+ rowToReduce.makeUnitary(modulus, leadingCol);
+ pivotRowOfCol[leadingCol] = pivots.rowCount();
+ rowToReduce.appendTo(pivots);
+ break;
+ }
+ rowToReduce.rowReduceByUnitary(pivotRow, pivots, modulus);
+ }
+ }
+
+ // ** Reduce from row echelon form to reduced row echelon form
+
+ SparseMatrix reduced(colCount);
+ auto pivotCol = colCount;
+ // Reduce pivot rows in descending order of leading column. The reduced
+ // pivots go into reduced and we update pivotRowOfCol to refer to the
+ // row indices in reduced as we go along.
+ while (pivotCol != 0) {
+ --pivotCol;
+ const auto row = pivotRowOfCol[pivotCol];
+ if (row == noRow)
+ continue;
+ rowToReduce.clear(colCount);
+ rowToReduce.addRow(pivots, row);
+ MATHICGB_ASSERT(rowToReduce[pivotCol] == 1); // unitary
+ for (auto col = pivotCol + 1; col != colCount; ++col) {
+ auto& entry = rowToReduce[col];
+ if (entry == 0)
+ continue;
+ entry %= modulus;
+ if (entry == 0)
+ continue;
+ const auto pivotRow = pivotRowOfCol[col];
+ if (pivotRow != noRow)
+ rowToReduce.rowReduceByUnitary(pivotRow, reduced, modulus);
+ MATHICGB_ASSERT(entry < modulus);
+ }
+ pivotRowOfCol[pivotCol] = reduced.rowCount();
+ rowToReduce.appendTo(reduced);
+ }
+ return std::move(reduced);
+ }
+
SparseMatrix reduceToEchelonForm(
const SparseMatrix& toReduce,
const SparseMatrix::Scalar modulus
@@ -698,8 +776,15 @@ SparseMatrix F4MatrixReducer::reducedRowEchelonForm(
return reduceToEchelonFormShrawanDelayedModulus(matrix, mModulus);
else
return reduceToEchelonFormShrawan(matrix, mModulus);
- } else
- return reduceToEchelonForm(matrix, mModulus);
+ } else {
+ // todo: actually do some work to determine a good way to determine
+ // when to use the sparse method, or alternatively make some some
+ // sort of hybrid.
+ if ( matrix.computeDensity() < 0.02)
+ return reduceToEchelonFormSparse(matrix, mModulus);
+ else
+ return reduceToEchelonForm(matrix, mModulus);
+ }
}
SparseMatrix F4MatrixReducer::reducedRowEchelonFormBottomRight(
diff --git a/src/mathicgb/F4MatrixReducer.hpp b/src/mathicgb/F4MatrixReducer.hpp
index 4fc76a5..92b2f33 100755
--- a/src/mathicgb/F4MatrixReducer.hpp
+++ b/src/mathicgb/F4MatrixReducer.hpp
@@ -27,7 +27,7 @@ public:
/// Returns the reduced row echelon form of matrix.
SparseMatrix reducedRowEchelonForm(const SparseMatrix& matrix);
- /// Returns the lower right submatrix if the reduced row echelon
+ /// Returns the lower right submatrix of the reduced row echelon
/// form of matrix. The lower left part is not returned because it is
/// always zero after row reduction.
SparseMatrix reducedRowEchelonFormBottomRight(const QuadMatrix& matrix);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git
More information about the debian-science-commits
mailing list