[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