[mathicgb] 164/393: Significant speed-up from choosing sparser and older reducers. This was already implemented, I thought, but it turns out that only applied to siggb, not gb.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:53 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 be633a03ccdc6bef691f57192991136d02e24ca6
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Mon Feb 11 22:01:33 2013 +0100
Significant speed-up from choosing sparser and older reducers. This was already implemented, I thought, but it turns out that only applied to siggb, not gb.
---
src/mathicgb/BuchbergerAlg.cpp | 39 +++++++++++++++++++++++++-
src/mathicgb/DivLookup.hpp | 58 +++++++++++++++++++++++++++++++++++----
src/mathicgb/DivisorLookup.hpp | 5 ++++
src/mathicgb/F4MatrixBuilder.cpp | 2 +-
src/mathicgb/F4MatrixBuilder2.cpp | 2 +-
src/mathicgb/PolyBasis.cpp | 10 +++++++
src/mathicgb/PolyBasis.hpp | 4 +++
src/mathicgb/QuadMatrix.cpp | 4 ---
src/mathicgb/TypicalReducer.cpp | 2 +-
9 files changed, 113 insertions(+), 13 deletions(-)
diff --git a/src/mathicgb/BuchbergerAlg.cpp b/src/mathicgb/BuchbergerAlg.cpp
index 0512f8d..2736859 100755
--- a/src/mathicgb/BuchbergerAlg.cpp
+++ b/src/mathicgb/BuchbergerAlg.cpp
@@ -266,7 +266,44 @@ void BuchbergerAlg::step() {
return; // no more s-pairs
std::vector<std::unique_ptr<Poly> > reduced;
mReducer.classicReduceSPolySet(spairGroup, mBasis, reduced);
-
+
+ // sort the elements to get deterministic behavior. The order will change
+ // arbitrarily when running multithreaded. Also, if preferring older
+ // reducers, it is of benefit to break ties by preferring the sparser
+ // reducer. Age does not have ties, since each element has a distinct
+ // index, but if they all come from the same matrix then there is
+ // really nothing to distinguish them - the relative age is arbitrarily
+ // chosen. If we order sparsest-first, we will effectively make the
+ // arbitrary choice among reducers from the same matrix in favor of sparser
+ // reducers.
+ auto& order = [&](
+ const std::unique_ptr<Poly>& a,
+ const std::unique_ptr<Poly>& b
+ ) {
+ const auto aTermCount = a->nTerms();
+ const auto bTermCount = b->nTerms();
+ if (aTermCount < bTermCount)
+ return true;
+ if (aTermCount > bTermCount)
+ return false;
+ auto bIt = b->begin();
+ const auto aEnd = a->end();
+ for (auto aIt = a->begin(); aIt != aEnd; ++aIt, ++bIt) {
+ const auto monoCmp =
+ mRing.monomialCompare(aIt.getMonomial(), bIt.getMonomial());
+ if (monoCmp == LT)
+ return true;
+ if (monoCmp == GT)
+ return false;
+ if (aIt.getCoefficient() < bIt.getCoefficient())
+ return true;
+ if (aIt.getCoefficient() > bIt.getCoefficient())
+ return false;
+ }
+ return false;
+ };
+ std::sort(reduced.begin(), reduced.end(), order);
+
insertPolys(reduced);
/*
for (auto it = reduced.begin(); it != reduced.end(); ++it) {
diff --git a/src/mathicgb/DivLookup.hpp b/src/mathicgb/DivLookup.hpp
index 94228af..2e6d619 100644
--- a/src/mathicgb/DivLookup.hpp
+++ b/src/mathicgb/DivLookup.hpp
@@ -209,7 +209,8 @@ public:
void displayStats(std::ostream &o) const;
///////////////////////////
- const GroebnerBasis* basis() const {return mSigBasis;}
+ const GroebnerBasis* sigBasis() const {return mSigBasis;}
+ const PolyBasis* basis() const {return mBasis;}
const PolyRing* getPolyRing() const {return mRing;}
unsigned long long getExpQueryCount() const {return _expQueryCount;}
int type() const {return _type;}
@@ -264,7 +265,7 @@ class DivLookup : public DivisorLookup {
size_t maxDivisors,
size_t newGenerator
) const {
- const GroebnerBasis* GB = _finder.getConfiguration().basis();
+ const GroebnerBasis* GB = _finder.getConfiguration().sigBasis();
const_monomial sigNew = GB->getSignature(newGenerator);
@@ -274,7 +275,7 @@ class DivLookup : public DivisorLookup {
}
virtual size_t highBaseDivisor(size_t newGenerator) const {
- const GroebnerBasis* basis = _finder.getConfiguration().basis();
+ const GroebnerBasis* basis = _finder.getConfiguration().sigBasis();
MATHICGB_ASSERT(newGenerator < basis->size());
HighBaseDivisor searchObject(*basis, newGenerator);
@@ -284,11 +285,18 @@ class DivLookup : public DivisorLookup {
}
virtual size_t minimalLeadInSig(const_monomial sig) const {
- MinimalLeadInSig searchObject(*_finder.getConfiguration().basis());
+ MinimalLeadInSig searchObject(*_finder.getConfiguration().sigBasis());
_finder.findAllDivisors(sig, searchObject);
return searchObject.minLeadGen();
}
+ virtual size_t classicReducer(const_monomial mon) const {
+ const auto& conf = _finder.getConfiguration();
+ ClassicReducer searchObject(*conf.basis(), conf.preferSparseReducers());
+ _finder.findAllDivisors(mon, searchObject);
+ return searchObject.reducer();
+ }
+
virtual size_t divisor(const_monomial mon) const {
const Entry* entry = _finder.findDivisor(mon);
return entry == 0 ? static_cast<size_t>(-1) : entry->index;
@@ -464,6 +472,46 @@ private:
const GroebnerBasis& mSigBasis;
size_t mMinLeadGen;
};
+
+ // Class used in ClassicReducer.
+ class ClassicReducer {
+ public:
+ ClassicReducer(const PolyBasis& basis, const bool preferSparse):
+ mBasis(basis),
+ mPreferSparse(preferSparse),
+ mReducer(static_cast<size_t>(-1)) {}
+
+ bool proceed(const Entry& entry) {
+ if (mReducer == static_cast<size_t>(-1)) {
+ mReducer = entry.index;
+ return true;
+ }
+
+ if (mPreferSparse) {
+ const auto oldTermCount = mBasis.poly(mReducer).nTerms();
+ const auto newTermCount = mBasis.poly(entry.index).nTerms();
+ if (oldTermCount > newTermCount) {
+ mReducer = entry.index; // prefer sparser
+ return true;
+ }
+ if (oldTermCount < newTermCount)
+ return true;
+ // break ties by age
+ }
+
+ if (mReducer > entry.index)
+ mReducer = entry.index; // prefer older
+ return true;
+ }
+
+ size_t reducer() const {return mReducer;}
+
+ private:
+ const PolyBasis& mBasis;
+ const bool mPreferSparse;
+ size_t mReducer;
+ };
+
/*
// Class used in findDivisor()
class DO {
@@ -587,7 +635,7 @@ public:
virtual size_t regularReducer(const_monomial sig, const_monomial mon) const
{
DOCheckAll out(
- *getConfiguration().basis(),
+ *getConfiguration().sigBasis(),
sig,
mon,
getConfiguration().preferSparseReducers()
diff --git a/src/mathicgb/DivisorLookup.hpp b/src/mathicgb/DivisorLookup.hpp
index 5ddd2fe..5988614 100644
--- a/src/mathicgb/DivisorLookup.hpp
+++ b/src/mathicgb/DivisorLookup.hpp
@@ -34,6 +34,11 @@ public:
virtual size_t regularReducer
(const_monomial sig, const_monomial mon) const = 0;
+ // Returns the index of a basis element whose lead term divides mon. The
+ // strategy used to break ties is up to the implementation of the interface,
+ // but the outcome must be deterministic.
+ virtual size_t classicReducer(const_monomial mon) const = 0;
+
virtual std::string getName() const = 0;
virtual size_t getMemoryUse() const = 0;
diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index 48261ea..4aeaa19 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -253,7 +253,7 @@ F4MatrixBuilder::createColumn(
MATHICGB_ASSERT(ring().hashValid(mTmp));
// look for a reducer of mTmp
- const size_t reducerIndex = mBasis.divisor(mTmp);
+ const size_t reducerIndex = mBasis.classicReducer(mTmp);
const bool insertLeft = (reducerIndex != static_cast<size_t>(-1));
// Create the new left or right column
diff --git a/src/mathicgb/F4MatrixBuilder2.cpp b/src/mathicgb/F4MatrixBuilder2.cpp
index 6879fc2..d1b45ab 100755
--- a/src/mathicgb/F4MatrixBuilder2.cpp
+++ b/src/mathicgb/F4MatrixBuilder2.cpp
@@ -772,7 +772,7 @@ F4MatrixBuilder2::createColumn(
MATHICGB_ASSERT(ring().hashValid(mTmp));
// look for a reducer of mTmp
- const size_t reducerIndex = mBasis.divisor(mTmp);
+ const size_t reducerIndex = mBasis.classicReducer(mTmp);
const bool insertLeft = (reducerIndex != static_cast<size_t>(-1));
// Create the new left or right column
diff --git a/src/mathicgb/PolyBasis.cpp b/src/mathicgb/PolyBasis.cpp
index 0d78a12..761cf6c 100755
--- a/src/mathicgb/PolyBasis.cpp
+++ b/src/mathicgb/PolyBasis.cpp
@@ -96,6 +96,16 @@ size_t PolyBasis::divisor(const_monomial mon) const {
return index;
}
+size_t PolyBasis::classicReducer(const_monomial mon) const {
+ return divisorLookup().classicReducer(mon);
+ size_t index = divisorLookup().classicReducer(mon);
+ MATHICGB_ASSERT((index == static_cast<size_t>(-1)) ==
+ (divisorSlow(mon) == static_cast<size_t>(-1)));
+ MATHICGB_ASSERT(index == static_cast<size_t>(-1) ||
+ ring().monomialIsDivisibleBy(mon, leadMonomial(index)));
+ return index;
+}
+
size_t PolyBasis::divisorSlow(const_monomial mon) const {
const size_t stop = size();
for (size_t i = 0; i != stop; ++i)
diff --git a/src/mathicgb/PolyBasis.hpp b/src/mathicgb/PolyBasis.hpp
index ea86b24..4b38816 100755
--- a/src/mathicgb/PolyBasis.hpp
+++ b/src/mathicgb/PolyBasis.hpp
@@ -34,6 +34,10 @@ public:
// Returns -1 if there is no such basis element.
size_t divisor(const_monomial mon) const;
+ // As divisor(mon), but if there is more than one divisor then the divisor
+ // is chosen in according to a notion of which reducer is better.
+ size_t classicReducer(const_monomial mon) const;
+
// As the non-slow version, but uses simpler and slower code.
size_t divisorSlow(const_monomial mon) const;
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index 885c057..45b9e3e 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -178,10 +178,6 @@ QuadMatrix QuadMatrix::toCanonical() const {
public:
RowComparer(const SparseMatrix& matrix): mMatrix(matrix) {}
bool operator()(SparseMatrix::RowIndex a, SparseMatrix::RowIndex b) const {
- // if you need this to work for empty rows or identical leading columns
- // then update this code.
- MATHICGB_ASSERT(!mMatrix.emptyRow(a));
- MATHICGB_ASSERT(!mMatrix.emptyRow(b));
auto itA = mMatrix.rowBegin(a);
const auto endA = mMatrix.rowEnd(a);
auto itB = mMatrix.rowBegin(b);
diff --git a/src/mathicgb/TypicalReducer.cpp b/src/mathicgb/TypicalReducer.cpp
index d8ee1bf..3c54cea 100755
--- a/src/mathicgb/TypicalReducer.cpp
+++ b/src/mathicgb/TypicalReducer.cpp
@@ -177,7 +177,7 @@ std::unique_ptr<Poly> TypicalReducer::classicReduce
std::cerr << std::endl;
}
- size_t reducer = basis.divisor(v.monom);
+ size_t reducer = basis.classicReducer(v.monom);
if (reducer == static_cast<size_t>(-1)) { // no reducer found
MATHICGB_ASSERT(result->isZero() ||
basis.order().signatureCompare(v.monom, result->backMonomial()) == LT);
--
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