[mathicgb] 38/393: Migrated QuadMatrixBuilder to use a hash table and made F4Matrix not defer to a fallback on clasically reducing an S-pair. Fixed some bugs that was corrupting hash values.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:29 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 5edd09598ce1864169f65ee1a9cce5751e65d6fd
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Fri Sep 28 18:06:55 2012 +0200

    Migrated QuadMatrixBuilder to use a hash table and made F4Matrix not defer to a fallback on clasically reducing an S-pair. Fixed some bugs that was corrupting hash values.
---
 src/mathicgb/F4MatrixBuilder.cpp   |  4 ++++
 src/mathicgb/F4Reducer.cpp         | 19 +++++------------
 src/mathicgb/Poly.cpp              | 10 ++++++---
 src/mathicgb/PolyRing.cpp          |  9 ++++++--
 src/mathicgb/PolyRing.hpp          | 22 ++++++++++++++-----
 src/mathicgb/QuadMatrixBuilder.hpp | 43 ++++++++++++++++++++++++++++++++++++++
 src/test/F4MatrixReducer.cpp       |  1 +
 7 files changed, 84 insertions(+), 24 deletions(-)

diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index 23bc588..ad33cf8 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -32,6 +32,7 @@ void F4MatrixBuilder::addRowToMatrix
 
   task.multiple = ring().allocMonomial();
   ring().monomialCopy(multiple, task.multiple);
+  MATHICGB_ASSERT(ring().hashValid(task.multiple));
   mTodo.push_back(task);
 }
 
@@ -46,6 +47,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
   typedef std::vector<RowTask>::iterator TaskIter;
   TaskIter end = mTodo.end();
   for (TaskIter it = mTodo.begin(); it != end; ++it) {
+    MATHICGB_ASSERT(ring().hashValid(it->multiple));
     ring().monomialMult(it->multiple, it->poly->getLeadMonomial(), mono);
     LeftRightColIndex leadCol = mBuilder.findColumn(mono);
     it->useAsReducer = !leadCol.valid();
@@ -60,6 +62,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
   // we are calling here can add more items to mTodo.
   while (!mTodo.empty()) {
     RowTask task = mTodo.back();
+    MATHICGB_ASSERT(ring().hashValid(task.multiple));
     mTodo.pop_back();
     if (task.useAsReducer)
       appendRowTop(task.multiple, *task.poly);
@@ -90,6 +93,7 @@ F4MatrixBuilder::createOrFindColumnOf(const_monomial mono) {
   task.multiple = ring().allocMonomial();
   ring().monomialDivideToNegative
     (mono, task.poly->getLeadMonomial(), task.multiple);
+  MATHICGB_ASSERT(ring().hashValid(task.multiple));
   mTodo.push_back(task);
 
   return LeftRightColIndex(mBuilder.createColumnLeft(mono), true);
diff --git a/src/mathicgb/F4Reducer.cpp b/src/mathicgb/F4Reducer.cpp
index 3d79ff0..5e865db 100755
--- a/src/mathicgb/F4Reducer.cpp
+++ b/src/mathicgb/F4Reducer.cpp
@@ -28,13 +28,6 @@ std::unique_ptr<Poly> F4Reducer::classicTailReduce
 
 std::unique_ptr<Poly> F4Reducer::classicReduceSPoly
 (const Poly& a, const Poly& b, const PolyBasis& basis) {
-  std::unique_ptr<Poly> p;
-  {
-    p = mFallback->classicReduceSPoly(a, b, basis);
-    mSigStats = mFallback->sigStats();
-    mClassicStats = mFallback->classicStats();
-  }
-
   QuadMatrix qm;
   {
     F4MatrixBuilder builder(basis);
@@ -49,15 +42,13 @@ std::unique_ptr<Poly> F4Reducer::classicReduceSPoly
   {
     F4MatrixReducer red;
     red.reduce(basis.ring(), qm, reduced);
-    if (reduced.rowCount() > 0) {
-      MATHICGB_ASSERT(reduced.rowCount() == 1);
-      Poly q(&basis.ring());
-      reduced.rowToPolynomial(0, qm.rightColumnMonomials, q);
-      MATHICGB_ASSERT(q == *p);
-    } else
-      MATHICGB_ASSERT(p->isZero());
   }
 
+  auto p = make_unique<Poly>(&basis.ring());
+  if (reduced.rowCount() > 0) {
+    MATHICGB_ASSERT(reduced.rowCount() == 1);
+    reduced.rowToPolynomial(0, qm.rightColumnMonomials, *p);
+  }
   return p;
 }
 
diff --git a/src/mathicgb/Poly.cpp b/src/mathicgb/Poly.cpp
index 79e0a8f..18243e1 100755
--- a/src/mathicgb/Poly.cpp
+++ b/src/mathicgb/Poly.cpp
@@ -22,6 +22,7 @@ void Poly::copy(Poly &result) const
   std::copy(coeffs.begin(), coeffs.end(), result.coeffs.begin());
   std::copy(monoms.begin(), monoms.end(), result.monoms.begin());
 }
+
 void Poly::appendTerm(coefficient a, const_monomial m)
 {
   // the monomial will be copied on.
@@ -30,11 +31,13 @@ void Poly::appendTerm(coefficient a, const_monomial m)
   exponent const * e = m.unsafeGetRepresentation();
   monoms.insert(monoms.end(), e, e + len);
 }
+
 void Poly::append(iterator &first, iterator &last)
 {
   for ( ; first != last; ++first)
     appendTerm(first.getCoefficient(), first.getMonomial());
 }
+
 Poly *Poly::copy() const
 {
   Poly *const_this = const_cast<Poly *>(this);
@@ -228,9 +231,10 @@ void Poly::parse(std::istream &i)
           R->coefficientFromInt(b,a);
           coeffs.push_back(b);
           if (isalpha(next) || next == '<')
-            {
-              R->monomialParse(i, m);
-            }
+            R->monomialParse(i, m);
+          else
+            R->monomialSetIdentity(m); // have to do this to set hash value
+          MATHICGB_ASSERT(ring().hashValid(m));
           next = i.peek();
           if (next == '>') i.get();
         }
diff --git a/src/mathicgb/PolyRing.cpp b/src/mathicgb/PolyRing.cpp
index c6a5db2..0f29bbd 100755
--- a/src/mathicgb/PolyRing.cpp
+++ b/src/mathicgb/PolyRing.cpp
@@ -11,6 +11,10 @@
 #include <cstdlib>
 #include <limits>
 
+bool PolyRing::hashValid(const_monomial m) const {
+  return monomialHashValue(m) == computeHashValue(m);
+}
+
 PolyRing::PolyRing(long p0,
                    int nvars,
                    int nweights)
@@ -144,7 +148,7 @@ void PolyRing::monomialFindSignature(ConstMonomial v1,
       else
         weight -= t1[i] = u1[i];
     }
-#ifdef DEBUG
+#ifdef MATHICGB_DEBUG
     setWeightsOnly(t1);
     ASSERT(t1[mNumVars + 1] == weight);
 #endif
@@ -408,6 +412,7 @@ void PolyRing::monomialCopy(const_monomial a, monomial &result) const
   for (size_t i = mHashIndex; i != static_cast<size_t>(-1); --i)
     result[i] = a[i];
 }
+
 void PolyRing::monomialQuotientAndMult(const_monomial a,
                                        const_monomial b,
                                        const_monomial c,
@@ -430,7 +435,7 @@ void PolyRing::setWeightsAndHash(monomial a) const
   a++;
   for (size_t i = 0; i < mNumVars; ++i)
     hash += a[i] * mHashVals[i];
-  a[mHashIndex - 1] = hash;
+  a[mHashIndex - 1] = hash; // index-1 as we did ++a above
 }
 
 void PolyRing::monomialFindSignatures(const_monomial v1,
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index 803dbd2..c69d6e1 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -325,6 +325,8 @@ public:
 
   inline void setHashOnly(Monomial& a) const;
 
+  bool hashValid(const_monomial m) const;
+
   bool weightsCorrect(ConstMonomial a) const;
 
   int monomialCompare(ConstMonomial a, 
@@ -529,6 +531,8 @@ public:
   void resetCoefficientStats() const;
 
 private:
+  inline size_t computeHashValue(const_monomial a1) const;
+
   long mCharac; // p=mCharac: ring is ZZ/p
   size_t mNumVars;
   int mNumWeights; // stored as negative of weight vectors
@@ -593,14 +597,19 @@ inline void PolyRing::setWeightsOnly(Monomial& a1) const
     }
 }
 
-inline void PolyRing::setHashOnly(Monomial& a1) const
-{
-  exponent *a = a1.unsafeGetRepresentation();
+inline size_t PolyRing::computeHashValue(const_monomial a1) const {
+  const exponent* a = a1.unsafeGetRepresentation();
   int hash = *a;
   a++;
   for (size_t i = 0; i < mNumVars; ++i)
     hash += a[i] * mHashVals[i];
-  a[mHashIndex - 1] = hash;
+  return hash;
+}
+
+inline void PolyRing::setHashOnly(Monomial& a1) const
+{
+  exponent* a = a1.unsafeGetRepresentation();
+  a[mHashIndex] = computeHashValue(a1);
 }
 
 inline int PolyRing::monomialCompare(ConstMonomial a, ConstMonomial b) const
@@ -656,8 +665,11 @@ inline void PolyRing::monomialDivideToNegative(ConstMonomial a,
                                                ConstMonomial b, 
                                                Monomial& result) const 
 {
-  for (size_t i = 0; i <= this->mTopIndex; ++i)
+  for (size_t i = 0; i <= mHashIndex; ++i)
     result[i] = a[i] - b[i];
+  MATHICGB_ASSERT(result[mHashIndex] == a[mHashIndex] - b[mHashIndex]);
+  MATHICGB_ASSERT(!hashValid(a) || !hashValid(b) || hashValid(result));
+  MATHICGB_ASSERT(computeHashValue(result) == computeHashValue(a) - computeHashValue(b));
 }
 
 inline bool PolyRing::monomialRelativelyPrime(ConstMonomial a, 
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
index 4255b7d..48c8c69 100755
--- a/src/mathicgb/QuadMatrixBuilder.hpp
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -1,12 +1,17 @@
 #ifndef MATHICGB_QUAD_MATRIX_BUILDER_GUARD
 #define MATHICGB_QUAD_MATRIX_BUILDER_GUARD
 
+#define MATHICGB_USE_QUADMATRIX_STD_HASH
+
 #include "SparseMatrix.hpp"
 #include "PolyRing.hpp"
 #include <vector>
 #include <map>
 #include <string>
 #include <ostream>
+#ifdef MATHICGB_USE_QUADMATRIX_STD_HASH
+#include <unordered_map>
+#endif
 class FreeModuleOrder;
 class QuadMatrix;
 
@@ -21,7 +26,11 @@ class QuadMatrixBuilder {
   typedef SparseMatrix::Scalar Scalar;
 
   QuadMatrixBuilder(const PolyRing& ring):
+#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
     mMonomialToCol(ArbitraryOrdering(ring)) {}
+#else
+  mMonomialToCol(100, Hash(ring), Equal(ring)) {}
+#endif
 
   /// The index of a column that can be either on the left or the
   /// right side. The largest representable ColIndex is an invalid
@@ -198,7 +207,11 @@ class QuadMatrixBuilder {
     // The key comparer object already has a ring reference - we might
     // as well use that one instead of adding another reference to
     // this object.
+#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
     return mMonomialToCol.key_comp().ring();
+#else
+    return mMonomialToCol.key_eq().ring();
+#endif
   }
 
   ColIndex leftColCount() const {
@@ -221,6 +234,7 @@ private:
   MonomialsType mMonomialsLeft;
   MonomialsType mMonomialsRight;
 
+#ifndef MATHICGB_USE_QUADMATRIX_STD_HASH
   /// We need SOME ordering to make std::map work.
   class ArbitraryOrdering {
   public:
@@ -237,6 +251,35 @@ private:
   typedef std::map<const_monomial, LeftRightColIndex, ArbitraryOrdering>
     MonomialToColType;
   MonomialToColType mMonomialToCol;
+#else
+  struct Hash {
+  public:
+    Hash(const PolyRing& ring): mRing(ring) {}
+    size_t operator()(const_monomial m) const {
+      MATHICGB_ASSERT(mRing.hashValid(m));
+      return mRing.monomialHashValue(m);
+    }
+    const PolyRing& ring() const {return mRing;}
+
+  private:
+    const PolyRing& mRing;
+  };
+  struct Equal {
+  public:
+    Equal(const PolyRing& ring): mRing(ring) {}
+    size_t operator()(const_monomial a, const_monomial b) const {
+      return mRing.monomialEQ(a, b);
+    }
+    const PolyRing& ring() const {return mRing;}
+
+  private:
+    const PolyRing& mRing;
+  };
+
+  typedef std::unordered_map<const_monomial, LeftRightColIndex, Hash, Equal> 
+    MonomialToColType;
+  MonomialToColType mMonomialToCol;
+#endif
 
   SparseMatrix mTopLeft;
   SparseMatrix mTopRight;
diff --git a/src/test/F4MatrixReducer.cpp b/src/test/F4MatrixReducer.cpp
index 5fbf6c5..781df0a 100755
--- a/src/test/F4MatrixReducer.cpp
+++ b/src/test/F4MatrixReducer.cpp
@@ -20,6 +20,7 @@ TEST(F4MatrixReducer, Reduce) {
   size_t count = 0;
   for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
     monomial mono = it.getMonomial();
+    MATHICGB_ASSERT(ring->hashValid(mono));
     if (count < 4)
       m.leftColumnMonomials.push_back(mono);
     else

-- 
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