[mathicgb] 21/393: Renamed SPairHandler to SigSPairs, moved responsibility for ordering sig S-pairs into FreeModuleOrder.cpp and speed up sig S-pair ordering by using scrambled signatures.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:25 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 e0cba69a24e782abf127093ebd6550977040e197
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Wed Aug 8 19:47:38 2012 -0400

    Renamed SPairHandler to SigSPairs, moved responsibility for ordering sig S-pairs into FreeModuleOrder.cpp and speed up sig S-pair ordering by using scrambled signatures.
---
 Makefile.am                                      |   5 +-
 src/mathicgb/FreeModuleOrder.cpp                 | 316 +++++++++++++++++++----
 src/mathicgb/FreeModuleOrder.hpp                 |  17 +-
 src/mathicgb/PairTriangle.cpp                    |   2 +-
 src/mathicgb/SigSPairQueue.cpp                   |   5 +
 src/mathicgb/SigSPairQueue.hpp                   |  69 +++++
 src/mathicgb/{SPairHandler.cpp => SigSPairs.cpp} | 103 +++-----
 src/mathicgb/{SPairHandler.hpp => SigSPairs.hpp} |  34 +--
 src/mathicgb/SignatureGB.cpp                     |  93 +++----
 src/mathicgb/SignatureGB.hpp                     |  14 +-
 src/mathicgb/io-util.cpp                         |   1 -
 src/test/FreeModuleOrderTest.cpp                 |   2 +-
 src/test/gb-test.cpp                             |   1 -
 src/test/poly-test.cpp                           |   1 -
 14 files changed, 452 insertions(+), 211 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index bf63f52..f9d9882 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,10 +49,11 @@ libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp				\
   src/mathicgb/ReducerHelper.hpp src/mathicgb/ReducerNoDedup.hpp		\
   src/mathicgb/ReducerPack.hpp src/mathicgb/ReducerPackDedup.hpp		\
   src/mathicgb/SignatureGB.cpp src/mathicgb/SignatureGB.hpp				\
-  src/mathicgb/SPairHandler.cpp src/mathicgb/SPairHandler.hpp			\
+  src/mathicgb/SigSPairs.cpp src/mathicgb/SigSPairs.hpp					\
   src/mathicgb/SPairs.cpp src/mathicgb/SPairs.hpp						\
   src/mathicgb/stdinc.h src/mathicgb/TournamentReducer.cpp				\
-  src/mathicgb/TournamentReducer.hpp
+  src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp		\
+  src/mathicgb/SigSPairQueue.cpp
 
 # When making a distribution file, Automake knows to include all files
 # that are necessary to build the project. EXTRA_DIST specifies files
diff --git a/src/mathicgb/FreeModuleOrder.cpp b/src/mathicgb/FreeModuleOrder.cpp
index 4834cd8..e7297d8 100755
--- a/src/mathicgb/FreeModuleOrder.cpp
+++ b/src/mathicgb/FreeModuleOrder.cpp
@@ -1,13 +1,222 @@
 // Copyright 2011 Michael E. Stillman
 
 #include "stdinc.h"
-#include <iostream>
-#include <algorithm>
 #include "FreeModuleOrder.hpp"
+
 #include "Poly.hpp"
 #include "Ideal.hpp"
+#include "SigSPairQueue.hpp"
+#include "GroebnerBasis.hpp"
+#include "PolyRing.hpp"
 #include <mathic.h>
-#include "PairTriangle.hpp"
+#include <iostream>
+#include <algorithm>
+#include <limits>
+#include <stdexcept>
+
+// In this file we define various term orders. Some classes need to be
+// specialized to each term order which we do using templates. Those
+// classes are defined here since they should not be used from
+// anywhere else - instead they should be accessed through their
+// virtual interface.
+
+// *******************************************************
+// ** Utility objects
+
+namespace {
+  // Comparer for scrambled signatures
+  template<class Cmp>
+  class ScrambledComparer {
+  public:
+    ScrambledComparer(const Cmp& cmp): mCmp(cmp), mComparisons(0) {}
+    bool operator()(const PreSPair& a, const PreSPair& b) const {
+      ++mComparisons;
+      return mCmp.scrambledLessThan(a.signature, b.signature);
+    }
+    size_t comparisons() const {return mComparisons;}
+  private:
+    const Cmp& mCmp;
+    mutable size_t mComparisons;
+  };
+
+  // Iterator that accesses the field i based on a passed-in iterator.
+  template<class PairIterator>
+  class IndexIterator {
+  public:
+	typedef typename PairIterator::iterator_category iterator_category;
+	typedef typename PairIterator::value_type value_type;
+	typedef typename PairIterator::difference_type difference_type;
+	typedef typename PairIterator::pointer pointer;
+	typedef typename PairIterator::reference reference;
+
+	IndexIterator(PairIterator pairIterator): mIterator(pairIterator) {}
+	IndexIterator& operator++() {++mIterator; return *this;}
+	size_t operator*() const {return mIterator->i;}
+	difference_type operator-(const IndexIterator<PairIterator>& it) const {
+	  return mIterator - it.mIterator;
+	}
+	bool operator==(const IndexIterator<PairIterator>& it) const {
+	  return mIterator == it.mIterator;
+	}
+	bool operator!=(const IndexIterator<PairIterator>& it) const {
+	  return mIterator != it.mIterator;
+	}
+
+  private:
+	PairIterator mIterator;
+  };
+}
+
+// *******************************************************
+// ** SigSPairQueue
+namespace {
+  // Configuration of mathic::PairTriangle for use with signature queues.
+  template<class Cmp>
+  class SigPTConfiguration {
+  public:
+	SigPTConfiguration
+    (GroebnerBasis const& basis, Cmp const& cmp): mBasis(basis), mCmp(cmp) {}
+
+	typedef monomial PairData;
+	void computePairData(size_t col, size_t row, monomial sig) {
+      ASSERT(mBasis.ratioCompare(col, row) != EQ);
+      // ensure that ratio(col) > ratio(row)
+      if (mBasis.ratioCompare(col, row) == LT)
+        std::swap(col, row);
+      mBasis.ring().monomialFindSignature
+        (mBasis.getLeadMonomial(col),
+         mBasis.getLeadMonomial(row),
+         mBasis.getSignature(col), sig);
+      mCmp.scrambleSignatureForFastComparison(sig);
+    }
+
+	typedef bool CompareResult;
+	bool compare(int colA, int rowA, const_monomial a,
+				 int colB, int rowB, const_monomial b) const {
+      return mCmp.scrambledLessThan(b, a);
+	}
+	bool cmpLessThan(bool v) const {return v;}
+
+    GroebnerBasis const& basis() const {return mBasis;}
+    Cmp const& comparer() const {return mCmp;}
+
+  private:
+    GroebnerBasis const& mBasis;
+    Cmp const& mCmp;
+  };
+
+  // Object that stores S-pairs and orders them according to a monomial
+  // or signature.
+  template<class Cmp>
+  class ConcreteSigSPairQueue : public SigSPairQueue {
+  public:
+    ConcreteSigSPairQueue(GroebnerBasis const& basis, Cmp const& cmp):
+      mPairQueue(PC(basis, cmp)) {}
+
+    virtual monomial popSignature(Pairs& pairs) {
+      pairs.clear();
+      if (mPairQueue.empty())
+        return 0;
+      monomial sig = ring().allocMonomial();
+      ring().monomialCopy(mPairQueue.topPairData(), sig);
+      do {
+        pairs.push_back(mPairQueue.topPair());
+        mPairQueue.pop();
+      } while
+          (!mPairQueue.empty() && ring().monomialEQ(mPairQueue.topPairData(), sig));
+      comparer().unscrambleSignature(sig);
+      return sig;
+    }
+
+    virtual void pushPairs(size_t pairWith, IndexSigs& pairs) {
+#ifdef DEBUG
+      monomial tmp = ring().allocMonomial();
+      for (size_t i = 0; i < pairs.size(); ++i) {
+        ASSERT(pairs[i].i < columnCount());
+        mPairQueue.configuration().computePairData
+          (columnCount(), pairs[i].i, tmp);
+        comparer().unscrambleSignature(tmp);
+        ASSERT(ring().monomialEQ(tmp, pairs[i].signature));
+      }
+      ring().freeMonomial(tmp);
+#endif
+
+      if (columnCount() >= std::numeric_limits<BigIndex>::max())
+        throw std::overflow_error
+          ("Too large basis element index in constructing S-pairs.");
+    
+      // sort and insert new column
+      ScrambledComparer<Cmp> cmp(comparer());
+      comparer().scrambleSignaturesForFastComparison(pairs);
+      std::sort(pairs.begin(), pairs.end(), cmp);
+      //mPreComparisons += cmp.comparisons();
+      //order().destructiveSort(pairs);
+      typedef IndexIterator<std::vector<PreSPair>::const_iterator> Iter;
+      mPairQueue.addColumnDescending(Iter(pairs.begin()), Iter(pairs.end()));
+    
+      // free signatures
+      std::vector<PreSPair>::iterator end = pairs.end();
+      for (std::vector<PreSPair>::iterator it = pairs.begin(); it != end; ++it)
+        ring().freeMonomial(it->signature);
+      pairs.clear();
+    }
+  
+    virtual std::string name() const {return "todo";}
+
+    virtual size_t memoryUse() const {return mPairQueue.getMemoryUse();}
+
+    virtual size_t pairCount() const {return mPairQueue.pairCount();}
+
+    virtual size_t columnCount() const {return mPairQueue.columnCount();}
+
+  private:
+    ConcreteSigSPairQueue(const ConcreteSigSPairQueue<Cmp>&); // not available
+    void operator=(const ConcreteSigSPairQueue<Cmp>&); // not available
+
+    // the compiler should be able to resolve these accessors into a direct
+    // offset as though these were member variables.
+    const GroebnerBasis& basis() const {
+      return mPairQueue.configuration().basis();
+    }
+    const Cmp& comparer() const {return mPairQueue.configuration().comparer();}
+    PolyRing const& ring() const {return basis().ring();}
+    FreeModuleOrder const& order() const {return basis().order();}
+
+    typedef SigPTConfiguration<Cmp> PC;
+    mathic::PairQueue<PC> mPairQueue;
+    friend class mathic::PairQueueNamespace::ConstructPairDataFunction<PC>;
+    friend class mathic::PairQueueNamespace::DestructPairDataFunction<PC>;
+  };
+}
+
+namespace mathic {
+  namespace PairQueueNamespace {
+	template<class Cmp>
+    struct ConstructPairDataFunction<SigPTConfiguration<Cmp> > {
+      inline static void function
+      (void* memory, Index col, Index row, SigPTConfiguration<Cmp>& conf) {
+        MATHICGB_ASSERT(memory != 0);
+        MATHICGB_ASSERT(col > row);
+        monomial* pd = new (memory) monomial
+          (conf.basis().ring().allocMonomial());
+        conf.computePairData(col, row, *pd);
+      }
+	};
+
+	template<class Cmp>
+    struct DestructPairDataFunction<SigPTConfiguration<Cmp> > {
+      inline static void function
+      (monomial* pd, Index col, Index row, SigPTConfiguration<Cmp>& conf) {
+        MATHICGB_ASSERT(pd != 0);
+        MATHICGB_ASSERT(col > row);
+        conf.basis().ring().freeMonomial(*pd);
+      }
+    };
+  }
+}
+
+// *******************************************************
+// ** Term orders
 
 template<class Cmp>
 class ConcreteOrder : public FreeModuleOrder {
@@ -29,9 +238,9 @@ public:
     return mCmp.signatureCompare(sigA, monoB, sigB);
   }
 
-  virtual void destructiveSort(std::vector<PreSPair>& pairs) const {
-    DestructiveSortComparer cmp(mCmp);
-    mCmp.prepareDestructiveSort(pairs);
+  virtual void sortAndScrambleSignatures(std::vector<PreSPair>& pairs) const {
+    ScrambledComparer<Cmp> cmp(mCmp);
+    mCmp.scrambleSignaturesForFastComparison(pairs);
     std::sort(pairs.begin(), pairs.end(), cmp);
     mPreComparisons += cmp.comparisons();
   }
@@ -49,25 +258,20 @@ public:
     preComparisons = mPreComparisons;
   }
 
-private:
-  class DestructiveSortComparer {
-  public:
-    DestructiveSortComparer(const Cmp& cmp): mCmp(cmp), mComparisons(0) {}
-    bool operator()(const PreSPair& a, const PreSPair& b) const {
-      ++mComparisons;
-      return mCmp.lessThanForDestructiveSort(a.signature, b.signature);
-    }
-    size_t comparisons() const {return mComparisons;}
-  private:
-    const Cmp& mCmp;
-    mutable size_t mComparisons;
-  };
+  virtual std::auto_ptr<SigSPairQueue>
+  createSigSPairQueue(GroebnerBasis const& basis) const {
+    return std::auto_ptr<SigSPairQueue>
+      (new ConcreteSigSPairQueue<Cmp>(basis, mCmp));
+  }
 
+private:
   Cmp mCmp;
   mutable size_t mComparisons;
   mutable size_t mPreComparisons;
 };
 
+
+
 // ** Graded reverse lex.
 // Degrees and exponents considered from high index to low index.
 //
@@ -83,11 +287,12 @@ public:
     return mRing->monomialCompare(sigA, sigB);
   }
 
-  void prepareDestructiveSort(std::vector<PreSPair>& pairs) const {}
-
-  bool lessThanForDestructiveSort(const_monomial sigA, const_monomial sigB) const {
+  void scrambleSignatureForFastComparison(monomial sig) const {}
+  void scrambleSignaturesForFastComparison(std::vector<PreSPair>& pairs) const {}
+  bool scrambledLessThan(const_monomial sigA, const_monomial sigB) const {
     return mRing->monomialLT(sigA, sigB);
   }
+  void unscrambleSignature(monomial sig) const {}
 
   int signatureCompare(const_monomial sigA,
     const_monomial monoB, const_monomial sigB) const {
@@ -121,11 +326,12 @@ public:
       appendBasisElement(I->getPoly(i)->getLeadMonomial());
   }
 
-  void prepareDestructiveSort(std::vector<PreSPair>& pairs) const {}
-
-  bool lessThanForDestructiveSort(const_monomial a, const_monomial b) const {
+  void scrambleSignatureForFastComparison(monomial sig) const {}
+  void scrambleSignaturesForFastComparison(std::vector<PreSPair>& pairs) const {}
+  bool scrambledLessThan(const_monomial a, const_monomial b) const {
     return signatureCompare(a, b) == LT;
   }
+  void unscrambleSignature(monomial sig) const {}
 
   int signatureCompare(const_monomial sig, const_monomial sig2) const {
     int da = - sig[topindex] + deg[*sig];
@@ -192,11 +398,12 @@ public:
 
   void appendBasisElement(const_monomial m) {deg.push_back(-m[topindex]);}
 
-  void prepareDestructiveSort(std::vector<PreSPair>& pairs) const {}
-
-  bool lessThanForDestructiveSort(const_monomial a, const_monomial b) const {
+  void scrambleSignatureForFastComparison(monomial sig) const {}
+  void scrambleSignaturesForFastComparison(std::vector<PreSPair>& pairs) const {}
+  bool scrambledLessThan(const_monomial a, const_monomial b) const {
     return signatureCompare(a, b) == LT;
   }
+  void unscrambleSignature(monomial sig) const {}
 
   int signatureCompare(const_monomial sig, const_monomial sig2) const {
     int da = - sig[topindex] + deg[*sig];
@@ -282,20 +489,34 @@ public:
       return *a < *b ? GT : LT;
   }
 
-  void prepareDestructiveSort(std::vector<PreSPair>& pairs) const {
+  void scrambleSignatureForFastComparison(monomial sig) const {
+#ifdef DEBUG
+    monomial original = mRing->allocMonomial();
+    mRing->monomialCopy(sig, original);
+#endif
+    const_monomial adjust = monoms[*sig];
+    for (size_t i = topindex; i >= 1; --i) 
+      sig[i] += adjust[i];
+    if (mUp)
+      *sig = -*sig;
+#ifdef DEBUG
+    monomial unscrambled = mRing->allocMonomial();
+    mRing->monomialCopy(sig, unscrambled);
+    unscrambleSignature(unscrambled);
+    ASSERT(mRing->monomialEQ(original, unscrambled));
+    mRing->freeMonomial(original);
+    mRing->freeMonomial(unscrambled);
+#endif
+  }
+
+  void scrambleSignaturesForFastComparison(std::vector<PreSPair>& pairs) const {
     typedef std::vector<PreSPair>::iterator Iter;
     Iter end = pairs.end();
-    for (Iter it = pairs.begin(); it != end; ++it) {
-      monomial sig = it->signature;
-      const_monomial adjust = monoms[*sig];
-      for (size_t i = topindex; i >= 1; --i)
-        sig[i] += adjust[i];
-      if (mUp)
-        *sig = -*sig;
-    }
+    for (Iter it = pairs.begin(); it != end; ++it)
+      scrambleSignatureForFastComparison(it->signature);
   }
 
-  inline bool lessThanForDestructiveSort(
+  inline bool scrambledLessThan(
     const_monomial a,
     const_monomial b
   ) const {
@@ -327,6 +548,14 @@ public:
     return false; // equality
   }
 
+  void unscrambleSignature(monomial sig) const {
+    if (mUp)
+      *sig = -*sig;
+    const_monomial adjust = monoms[*sig];
+    for (size_t i = topindex; i >= 1; --i) 
+      sig[i] -= adjust[i];
+  }
+
   int signatureCompare(const_monomial a, const_monomial m2, const_monomial b) const {
     const_monomial ma = monoms[*a];
     const_monomial mb = monoms[*b];
@@ -406,15 +635,12 @@ public:
     return EQ;
   }
 
-  void prepareDestructiveSort(std::vector<PreSPair>& pairs) const {
-  }
-
-  inline bool lessThanForDestructiveSort(
-    const_monomial a,
-    const_monomial b
-  ) const {
+  void scrambleSignatureForFastComparison(monomial sig) const {}
+  void scrambleSignaturesForFastComparison(std::vector<PreSPair>& pairs) const {}
+  inline bool scrambledLessThan(const_monomial a, const_monomial b) const {
     return signatureCompare(a,b) == LT;
   }
+  void unscrambleSignature(monomial sig) const {}
 
   int signatureCompare(const_monomial a, const_monomial m2, const_monomial b) const {
     const_monomial ma = monoms[*a];
diff --git a/src/mathicgb/FreeModuleOrder.hpp b/src/mathicgb/FreeModuleOrder.hpp
index 60416f5..a59bd45 100755
--- a/src/mathicgb/FreeModuleOrder.hpp
+++ b/src/mathicgb/FreeModuleOrder.hpp
@@ -4,19 +4,14 @@
 #define _free_module_order_h_
 
 #include "PolyRing.hpp"
+#include "SigSpairQueue.hpp"
 
 class PolyRing;
 class Ideal;
+class GroebnerBasis;
+class SigSPairQueue;
 typedef int FreeModuleOrderType;
 
-typedef unsigned short SmallIndex;
-typedef unsigned int BigIndex;
-
-struct PreSPair {
-  BigIndex i;
-  monomial signature;
-};
-
 class FreeModuleOrder
 {
 public:
@@ -35,7 +30,7 @@ public:
 
   // Sorts in ascending order of signature. May alter the signatures,
   // so do not use them after calling this method other than to free them.
-  virtual void destructiveSort(std::vector<PreSPair>& pairs) const = 0;
+  virtual void sortAndScrambleSignatures(std::vector<PreSPair>& pairs) const = 0;
 
   // You must use this method to inform the order when a
   // new basis element has been added.
@@ -45,9 +40,13 @@ public:
 
   virtual std::string description() const = 0;
 
+  virtual std::auto_ptr<SigSPairQueue>
+  createSigSPairQueue(GroebnerBasis const& basis) const = 0;
+
   static FreeModuleOrder* makeOrder(FreeModuleOrderType type, const Ideal* I);
 
   static void displayOrderTypes(std::ostream &o);
+
 };
 
 #endif
diff --git a/src/mathicgb/PairTriangle.cpp b/src/mathicgb/PairTriangle.cpp
index f20c72c..eb2f17a 100755
--- a/src/mathicgb/PairTriangle.cpp
+++ b/src/mathicgb/PairTriangle.cpp
@@ -64,7 +64,7 @@ namespace {
 }
 
 void PairTriangle::endColumn() {
-  mOrder.destructiveSort(mPrePairs);
+  mOrder.sortAndScrambleSignatures(mPrePairs);
   typedef IndexIterator<std::vector<PreSPair>::const_iterator> Iter;
   mPairQueue.addColumnDescending
 	(Iter(mPrePairs.begin()), Iter(mPrePairs.end()));
diff --git a/src/mathicgb/SigSPairQueue.cpp b/src/mathicgb/SigSPairQueue.cpp
new file mode 100755
index 0000000..8def30e
--- /dev/null
+++ b/src/mathicgb/SigSPairQueue.cpp
@@ -0,0 +1,5 @@
+#include "stdinc.h"
+#include "SigSPairQueue.hpp"
+
+SigSPairQueue::~SigSPairQueue() {
+}
diff --git a/src/mathicgb/SigSPairQueue.hpp b/src/mathicgb/SigSPairQueue.hpp
new file mode 100755
index 0000000..2ec34e1
--- /dev/null
+++ b/src/mathicgb/SigSPairQueue.hpp
@@ -0,0 +1,69 @@
+#ifndef MATHICGB_SIG_S_PAIR_QUEUE_GUARD
+#define MATHICGB_SIG_S_PAIR_QUEUE_GUARD
+
+#include "PolyRing.hpp"
+#include <string>
+#include <vector>
+
+typedef unsigned short SmallIndex;
+typedef unsigned int BigIndex;
+
+struct PreSPair {
+  BigIndex i;
+  monomial signature;
+};
+
+// A priority queue on S-pairs where the priority is based on a
+// signature as in signature Grobner basis algorithms. The class is
+// not responsible for eliminating S-pairs or doing anything beyond
+// order the S-pairs.
+//
+// You create these queues from a module term order.
+class SigSPairQueue {
+public:
+  virtual ~SigSPairQueue();
+
+  typedef std::pair<size_t, size_t> Pair;
+  typedef std::vector<Pair> Pairs;
+  //typedef std::pair<size_t, monomial> IndexSig;
+  typedef PreSPair IndexSig;
+  typedef std::vector<IndexSig> IndexSigs;
+
+  // Takes the minimal signature in the queue and adds all S-pairs of
+  // that signature to pairs. Clears pairs first. Returns null and
+  // leaves pairs empty if the queue is empty.
+  //
+  // This class does not have an empty() method on purpose - you are
+  // supposed to call this method until it returns null.
+  virtual monomial popSignature(Pairs& pairs) = 0;
+
+  // If (x, sig) is an element of pairsConsumed then (pairWith, x) is
+  // added to the queue. sig must be the signature of the S-pair
+  // (pairWith, x).
+  //
+  // ATTENTION: the class to pushPairs must have pairWith in the
+  // sequence 0, 1, 2, 3 and so on. It follows from this that the
+  // queue can figure out what pairWith is without being told. Thus
+  // the purpose of pairWith is to make it possible to make an
+  // assertion saying that the caller and the queue agree on what
+  // pairWith is.
+  // 
+  // ATTENTION: pairsConsumed will be cleared and the signatures in it
+  // will be freed on the ring. This is because the queue will need to
+  // alter pairsConsumed in various ways and clearing it after that is
+  // cleaner than exposing what's being done to
+  // pairsConsumed. Especially since after you did pushPairs there
+  // would not be a reason to care about what its content was.
+  virtual void pushPairs(size_t pairWith, IndexSigs& pairsConsumed) = 0;
+
+  // Returns a string that describes the queue.
+  virtual std::string name() const = 0;
+
+  // Returns the number of pairs currently in the queue.
+  virtual size_t pairCount() const  = 0;
+
+  // Returns number of bytes of memory used.
+  virtual size_t memoryUse() const = 0;
+};
+
+#endif
diff --git a/src/mathicgb/SPairHandler.cpp b/src/mathicgb/SigSPairs.cpp
similarity index 78%
rename from src/mathicgb/SPairHandler.cpp
rename to src/mathicgb/SigSPairs.cpp
index 6df1cc3..b2d9a85 100755
--- a/src/mathicgb/SPairHandler.cpp
+++ b/src/mathicgb/SigSPairs.cpp
@@ -1,39 +1,19 @@
 // Copyright 2011 Michael E. Stillman
 
 #include "stdinc.h"
-#include <iostream>
-#include "SPairHandler.hpp"
+#include "SigSPairs.hpp"
+
 #include "GroebnerBasis.hpp"
 #include "MTArray.hpp"
 #include "FreeModuleOrder.hpp"
 #include "Reducer.hpp"
 #include <limits>
 #include <stdexcept>
+#include <iostream>
 
 extern int tracingLevel;
 
-SPairHandler::SigPairTriangle::SigPairTriangle(const GroebnerBasis& basis, size_t queueType):
-  PairTriangle(basis.order(), basis.ring(), queueType),
-  mBasis(basis) {}
-
-bool SPairHandler::SigPairTriangle::calculateOrderBy(
-  size_t a,
-  size_t b,
-  monomial orderBy
-) const {
-  ASSERT(mBasis.ratioCompare(a, b) != EQ);
-  // ensure that ratio(a) > ratio(b)
-  if (mBasis.ratioCompare(a, b) == LT)
-    std::swap(a, b);
-  mBasis.ring().monomialFindSignature(
-    mBasis.getLeadMonomial(a),
-    mBasis.getLeadMonomial(b),
-    mBasis.getSignature(a),
-    orderBy);
-  return true;
-}
-
-SPairHandler::SPairHandler(
+SigSPairs::SigSPairs(
   const PolyRing *R0,
   FreeModuleOrder *F0,
   const GroebnerBasis *GB0,
@@ -53,66 +33,46 @@ SPairHandler::SPairHandler(
   GB(GB0),
   mReducer(reducer),
   mPostponeKoszuls(postponeKoszuls),
-  mTri(*GB0, queueType) {
+  mQueue(GB->order().createSigSPairQueue(*GB)) {
 }
 
-SPairHandler::~SPairHandler()
+SigSPairs::~SigSPairs()
 {
   ASSERT(mUseBaseDivisors || mUseHighBaseDivisors || mKnownSyzygyTri.empty());
 }
 
-void SPairHandler::newSyzygy(const_monomial sig) {
+void SigSPairs::newSyzygy(const_monomial sig) {
   ASSERT(Hsyz->member(sig));
 }
 
-SPairHandler::Stats SPairHandler::getStats() const
+SigSPairs::Stats SigSPairs::getStats() const
 {
   F->getStats(mStats.comparisons, mStats.precomparisons);
   return mStats;
 }
 
-monomial SPairHandler::popSignature(PairContainer& pairs) {
-  ASSERT(!empty());
-
-  monomial sig = R->allocMonomial();
-  R->monomialCopy(mTri.topOrderBy(), sig);
-  R->setHashOnly(sig); // mTri returns monomials without the hash value set, so we set it here
-
-  pairs.clear();
-  do { // pop top as long as the top S-pair has signature sig
-    // loop invariant: topGroup is the top of the queue and has signature sig
-
-    { // push the current top S-pair onto pairs
-      std::pair<size_t, size_t> p = mTri.topPair();
-      size_t greater = p.first;
-      size_t smaller = p.second;
-      ASSERT(GB->ratioCompare(greater, smaller) != EQ);
-      if (GB->ratioCompare(greater, smaller) == LT)
-        std::swap(greater, smaller);
-      // now, greater in sense of signature in S-pair or, equivalently,
-      // in sense of sig/lead ratio.
-      ++mStats.spairsFinal;
-      pairs.push_back(std::make_pair(greater, smaller));
-    }
-    mTri.pop();
-    ++mStats.duplicateSignatures;
-  } while (!mTri.empty() && R->monomialEQ(mTri.topOrderBy(), sig));
-
-  --mStats.duplicateSignatures; // We added one too many in this loop
+monomial SigSPairs::popSignature(PairContainer& pairs) {
+  monomial sig = mQueue->popSignature(pairs);
+  if (!sig.isNull()) {
+    size_t const pairCount = pairs.size();
+    mStats.spairsFinal += pairCount;
+    mStats.duplicateSignatures += pairCount - 1;
+  }
   return sig;
 }
 
-void SPairHandler::newPairs(size_t newGen)
+void SigSPairs::newPairs(size_t newGen)
 {
-  mTri.beginColumn();
+  ASSERT(mIndexSigs.empty());
   makePreSPairs(newGen);
-  mTri.endColumn();
+  mQueue->pushPairs(newGen, mIndexSigs);
+  mIndexSigs.clear();
 
   ASSERT((!mUseBaseDivisors && !mUseHighBaseDivisors) ||
     mKnownSyzygyTri.columnCount() == newGen + 1);
 }
 
-void SPairHandler::setupBaseDivisors(
+void SigSPairs::setupBaseDivisors(
   BaseDivisor& divisor1,
   BaseDivisor& divisor2,
   size_t& highDivisorCmp,
@@ -184,8 +144,9 @@ void SPairHandler::setupBaseDivisors(
   }
 }
 
-void SPairHandler::makePreSPairs(size_t newGen)
+void SigSPairs::makePreSPairs(size_t newGen)
 {
+  ASSERT(mIndexSigs.empty());
   ASSERT(newGen < GB->size());
   mStats.spairsConstructed += newGen;
 
@@ -325,7 +286,7 @@ void SPairHandler::makePreSPairs(size_t newGen)
     result.signature = pairSig;
     pairSig = R->allocMonomial();
     result.i = static_cast<BigIndex>(oldGen);
-    mTri.addPair(result.i, result.signature);
+    mIndexSigs.push_back(result);
     ++mStats.queuedPairs;
     //pairs.push_back(result);
   }
@@ -336,14 +297,14 @@ void SPairHandler::makePreSPairs(size_t newGen)
     R->freeMonomial(hsyz);
 }
 
-void SPairHandler::setKnownSyzygies(std::vector<std::pair<size_t, size_t> >& pairs) {
+void SigSPairs::setKnownSyzygies(std::vector<std::pair<size_t, size_t> >& pairs) {
   if (!mUseBaseDivisors && !mUseHighBaseDivisors)
     return;
   for (size_t i = 0; i < pairs.size(); ++i)
     setKnownSyzygy(pairs[i].first, pairs[i].second);
 }
 
-void SPairHandler::setKnownSyzygy(size_t gen1, size_t gen2) {
+void SigSPairs::setKnownSyzygy(size_t gen1, size_t gen2) {
   ASSERT(gen1 < GB->size());
   ASSERT(gen2 < GB->size());
   ASSERT(gen1 != gen2);
@@ -351,16 +312,20 @@ void SPairHandler::setKnownSyzygy(size_t gen1, size_t gen2) {
     mKnownSyzygyTri.setBitUnordered(gen1, gen2, true);
 }
 
-std::string SPairHandler::name() {
-  return mTri.name();
+size_t SigSPairs::pairCount() const {
+  return mQueue->pairCount();
+}
+
+std::string SigSPairs::name() {
+  return mQueue->name();
 }
 
-size_t SPairHandler::getMemoryUse() const
+size_t SigSPairs::getMemoryUse() const
 {
-  return mTri.getMemoryUse() + getKnownSyzygyBitsMemoryUse();
+  return mQueue->memoryUse() + getKnownSyzygyBitsMemoryUse();
 }
 
-size_t SPairHandler::getKnownSyzygyBitsMemoryUse() const {
+size_t SigSPairs::getKnownSyzygyBitsMemoryUse() const {
   return mKnownSyzygyTri.getMemoryUse();
 }
 
diff --git a/src/mathicgb/SPairHandler.hpp b/src/mathicgb/SigSPairs.hpp
similarity index 84%
rename from src/mathicgb/SPairHandler.hpp
rename to src/mathicgb/SigSPairs.hpp
index adc699f..35c89d9 100755
--- a/src/mathicgb/SPairHandler.hpp
+++ b/src/mathicgb/SigSPairs.hpp
@@ -1,19 +1,13 @@
-// Copyright 2011 Michael E. Stillman
 
 #ifndef _spair_handler_h_
 #define _spair_handler_h_
 
-// This class is designed for the Gao GB algorithm, or other signature based methods.
-// The idea is to keep the size of the spair structures as small as possible
-
-// Externally, an spair is (signature, integer).
-
-#include "PairTriangle.hpp"
-#include <vector>
 #include "PolyRing.hpp"
 #include "KoszulQueue.hpp"
+#include "SigSPairQueue.hpp"
 #include <mathic.h>
 #include <memtailor.h>
+#include <vector>
 
 class Poly;
 class MonomialTableArray;
@@ -21,10 +15,12 @@ class GroebnerBasis;
 class FreeModuleOrder;
 class Reducer;
 
-class SPairHandler
+// Handles S-pairs in signature Grobner basis algorithms. Responsible
+// for eliminating S-pairs, storing S-pairs and ordering S-pairs.
+class SigSPairs
 {
 public:
-  SPairHandler(
+  SigSPairs(
     const PolyRing *R0,
     FreeModuleOrder *F0,
     const GroebnerBasis *GB0,
@@ -34,9 +30,8 @@ public:
     bool useBaseDivisors,
     bool useSingularCriterionEarly,
     size_t queueType);
-  ~SPairHandler();
+  ~SigSPairs();
 
-  bool empty() const {return mTri.empty();}
   typedef std::vector<std::pair<size_t, size_t> > PairContainer;
   monomial popSignature(PairContainer& pairs);
 
@@ -80,7 +75,7 @@ public:
   };
   Stats getStats() const;
 
-  size_t pairCount() const {return mTri.pairCount();}
+  size_t pairCount() const;
 
   size_t getMemoryUse() const;
   size_t getKnownSyzygyBitsMemoryUse() const;
@@ -132,15 +127,10 @@ private:
   Reducer* mReducer;
   const bool mPostponeKoszuls;
 
-  class SigPairTriangle : public PairTriangle {
-  public:
-    SigPairTriangle(const GroebnerBasis& basis, size_t queueType);
-  protected:
-    virtual bool calculateOrderBy(size_t a, size_t b, monomial orderBy) const;
-  private:
-    const GroebnerBasis& mBasis;
-  };
-  SigPairTriangle mTri;
+  typedef std::vector<PreSPair> PrePairContainer;
+
+  std::auto_ptr<SigSPairQueue> mQueue;
+  SigSPairQueue::IndexSigs mIndexSigs;
 
   mutable Stats mStats;
 };
diff --git a/src/mathicgb/SignatureGB.cpp b/src/mathicgb/SignatureGB.cpp
index f3eb8dd..288340d 100755
--- a/src/mathicgb/SignatureGB.cpp
+++ b/src/mathicgb/SignatureGB.cpp
@@ -7,7 +7,7 @@
 #include "FreeModuleOrder.hpp"
 #include "Ideal.hpp"
 #include "DivisorLookup.hpp"
-#include "SPairHandler.hpp"
+#include "SigSPairs.hpp"
 #include "PolyHeap.hpp"
 #include "MTArray.hpp"
 
@@ -22,20 +22,21 @@ void SignatureGB::computeGrobnerBasis()
   std::ostream& out = std::cout;
 
   while (true) {
-    if (SP->empty())
+    if (!step())
       break;
-    step();
 
     if (mBreakAfter > 0 && GB->size() > mBreakAfter) {
       break;
       const size_t pairs = SP->pairCount();
       size_t sigs = 0;
       size_t syzygySigs = 0;
-      while (!SP->empty()) {
-        ++sigs;
-        size_t a;
+      while (true) {
         monomial sig = SP->popSignature(mSpairTmp);
-        if (Hsyz->member(sig, a))
+        if (sig.isNull())
+          break;
+        ++sigs;
+        size_t dummy;
+        if (Hsyz->member(sig, dummy))
           ++syzygySigs;
         else
           GB->minimalLeadInSig(sig);
@@ -99,7 +100,7 @@ SignatureGB::SignatureGB(
   Hsyz = MonomialTableArray::make(R, montable_type, ideal.size(), allowRemovals);
 
   reducer = Reducer::makeReducer(reductiontyp, *R).release();
-  SP = new SPairHandler(R, F, GB, Hsyz, reducer, mPostponeKoszul, mUseBaseDivisors, useSingularCriterionEarly, queueType);
+  SP = new SigSPairs(R, F, GB, Hsyz, reducer, mPostponeKoszul, mUseBaseDivisors, useSingularCriterionEarly, queueType);
 
   // Populate GB
   for (size_t i = 0; i < ideal.size(); i++) {
@@ -135,20 +136,12 @@ SignatureGB::~SignatureGB()
 }
 
 bool SignatureGB::processSPair
-  (monomial sig, const SPairHandler::PairContainer& pairs)
+  (monomial sig, const SigSPairs::PairContainer& pairs)
 {
   ASSERT(!pairs.empty());
 
   // the module term to reduce is multiple * GB->getSignature(gen)
-  const bool constrainTermChoice = false;
-  size_t gen = mSpairTmp.back().first;
-  if (!constrainTermChoice)
-    gen = GB->minimalLeadInSig(sig);
-  else {
-    for (size_t i = 0; i < pairs.size(); ++i)
-      if (GB->ratioCompare(pairs[i].first, gen) == GT)
-        gen = pairs[i].first;
-  }
+  size_t gen = GB->minimalLeadInSig(sig);
   ASSERT(gen != static_cast<size_t>(-1));
   monomial multiple = R->allocMonomial();
   R->monomialDivide(sig, GB->getSignature(gen), multiple);
@@ -159,13 +152,6 @@ bool SignatureGB::processSPair
 
   R->freeMonomial(multiple);
 
-  if (constrainTermChoice && f != 0) {
-    if (GB->isSingularTopReducible(*f, sig)) {
-      delete f;
-      f = 0;
-    }
-  }
-
   if (f == 0) { // singular reduction
     ASSERT(f == 0);
     if (tracingLevel >= 7)
@@ -206,11 +192,11 @@ bool SignatureGB::processSPair
   return true;
 }
 
-void SignatureGB::step()
+bool SignatureGB::step()
 {
-  ASSERT(!SP->empty());
-
   monomial sig = SP->popSignature(mSpairTmp);
+  if (sig.isNull())
+    return false;
   ++stats_sPairSignaturesDone;
   stats_sPairsDone += mSpairTmp.size();
 
@@ -227,7 +213,7 @@ void SignatureGB::step()
     if (tracingLevel >= 3)
       std::cerr << "eliminated as in syzygy module" << std::endl;
     R->freeMonomial(sig);
-    return;
+    return true;
   }
 
   // Not a known syzygy
@@ -245,7 +231,7 @@ void SignatureGB::step()
       Hsyz->insert(sig, 0);
       SP->newSyzygy(sig);
       SP->setKnownSyzygies(mSpairTmp);
-      return;
+      return true;
     }
 
   typedef std::vector<std::pair<size_t, size_t> >::const_iterator iter;
@@ -263,35 +249,38 @@ void SignatureGB::step()
               Hsyz->insert(sig, not_used);
               SP->newSyzygy(sig);
               SP->setKnownSyzygies(mSpairTmp);
-              return;
+              return true;
             }
         }
     }
 #ifdef DEBUG
-  for (iter it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it)
-    {
-      const_monomial a = GB->getLeadMonomial(it->first);
-      const_monomial b = GB->getLeadMonomial(it->second);
-      ASSERT(!R->monomialRelativelyPrime(a, b));
-    }
+  for (iter it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it) {
+    const_monomial a = GB->getLeadMonomial(it->first);
+    const_monomial b = GB->getLeadMonomial(it->second);
+    ASSERT(!R->monomialRelativelyPrime(a, b));
+  }
 #endif
 
   // Reduce the pair
   ++stats_pairsReduced;
   if (!processSPair(sig, mSpairTmp) || !mPostponeKoszul)
-    return;
-  for (iter it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it)
-    {
-      const_monomial greaterSig = GB->getSignature(it->first);
-      const_monomial smallerLead = GB->getLeadMonomial(it->second);
-      monomial koszul = R->allocMonomial();
-      R->monomialMult(greaterSig, smallerLead, koszul);
-      size_t dummy;
-      if (Hsyz->member(koszul, dummy))
-        R->freeMonomial(koszul);
-      else
-        mKoszuls->push(koszul);
-    }
+    return true;
+  for (iter it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it) {
+    std::pair<size_t, size_t> p = *it;
+    if (GB->ratioCompare(p.first, p.second) == LT)
+      std::swap(p.first, p.second);
+
+    const_monomial greaterSig = GB->getSignature(p.first);
+    const_monomial smallerLead = GB->getLeadMonomial(p.second);   
+    monomial koszul = R->allocMonomial();
+    R->monomialMult(greaterSig, smallerLead, koszul);
+    size_t dummy;
+    if (Hsyz->member(koszul, dummy))
+      R->freeMonomial(koszul);
+    else
+      mKoszuls->push(koszul);
+  }
+  return true;
 }
 
 size_t SignatureGB::getMemoryUse() const {
@@ -342,7 +331,7 @@ void SignatureGB::displayStats(std::ostream &o) const
 }
 
 void SignatureGB::displayPaperStats(std::ostream& out) const {
-  SPairHandler::Stats stats = SP->getStats();
+  SigSPairs::Stats stats = SP->getStats();
   Reducer::Stats reducerStats = reducer->sigStats();
   mic::ColumnPrinter pr;
   pr.addColumn(true, " ");
@@ -546,7 +535,7 @@ void SignatureGB::displaySomeStats(std::ostream& out) const {
   extra << '\n';
 
   unsigned long long earlyNonElim;
-  SPairHandler::Stats stats = SP->getStats();
+  SigSPairs::Stats stats = SP->getStats();
   const unsigned long long lowElim = stats.lowBaseDivisorHits;
   const unsigned long long highElim = stats.highBaseDivisorHits;
   const unsigned long long syzElim = stats.syzygyModuleHits;
diff --git a/src/mathicgb/SignatureGB.hpp b/src/mathicgb/SignatureGB.hpp
index e1d0fbd..610dd8e 100755
--- a/src/mathicgb/SignatureGB.hpp
+++ b/src/mathicgb/SignatureGB.hpp
@@ -11,13 +11,13 @@
 #include "MTArray.hpp"
 #include "GroebnerBasis.hpp"
 #include "FreeModuleOrder.hpp"
-#include "SPairHandler.hpp"
+#include "SigSPairs.hpp"
 #include "Reducer.hpp"
 #include "KoszulQueue.hpp"
 #include "SPairs.hpp"
 #include <map>
 
-class SPairHandler;
+class SigSPairs;
 class DivisorLookup;
 
 class SignatureGB {
@@ -45,7 +45,7 @@ public:
 
   GroebnerBasis* getGB() { return GB; }
   MonomialTableArray* getSyzTable() { return Hsyz; }
-  SPairHandler* getSPairHandler() { return SP; }
+  SigSPairs* getSigSPairs() { return SP; }
 
   size_t getMemoryUse() const;
   void displayStats(std::ostream& out) const;
@@ -65,13 +65,13 @@ private:
   unsigned int mBreakAfter;
   unsigned int mPrintInterval;
 
-  bool processSPair(monomial sig, const SPairHandler::PairContainer& pairs);
-  void step();
+  bool processSPair(monomial sig, const SigSPairs::PairContainer& pairs);
+  bool step();
 
   const PolyRing *R;
   FreeModuleOrder *F;
 
-  SPairHandler *SP;
+  SigSPairs *SP;
   MonomialTableArray *Hsyz;
   GroebnerBasis *GB;
   KoszulQueue *mKoszuls;
@@ -83,7 +83,7 @@ private:
   // Currently we use either both criteria (high and loow) or neither.
   bool const mUseBaseDivisors;
 
-  SPairHandler::PairContainer mSpairTmp; // use only for getting S-pairs
+  SigSPairs::PairContainer mSpairTmp; // use only for getting S-pairs
 
   // stats //////////
   size_t stats_sPairSignaturesDone; // distinct S-pair signatures done
diff --git a/src/mathicgb/io-util.cpp b/src/mathicgb/io-util.cpp
old mode 100644
new mode 100755
index dd6313e..f3713cc
--- a/src/mathicgb/io-util.cpp
+++ b/src/mathicgb/io-util.cpp
@@ -12,7 +12,6 @@
 #include "PolyHeap.hpp"
 #include "PolyGeoBucket.hpp"
 #include "GroebnerBasis.hpp"
-#include "SPairHandler.hpp"
 #include "SignatureGB.hpp"
 #include "MTArray.hpp"
 
diff --git a/src/test/FreeModuleOrderTest.cpp b/src/test/FreeModuleOrderTest.cpp
index d087436..2ca434e 100755
--- a/src/test/FreeModuleOrderTest.cpp
+++ b/src/test/FreeModuleOrderTest.cpp
@@ -45,7 +45,7 @@ void runTest(
 
   std::auto_ptr<FreeModuleOrder> order
     (FreeModuleOrder::makeOrder(orderType, ideal.get()));
-  order->destructiveSort(pairs);
+  order->sortAndScrambleSignatures(pairs);
   for (size_t i = 0; i < pairs.size(); ++i) {
     ring->freeMonomial(pairs[i].signature);
     pairs[i].signature = sigs[pairs[i].i];
diff --git a/src/test/gb-test.cpp b/src/test/gb-test.cpp
index cc42525..627ec2a 100755
--- a/src/test/gb-test.cpp
+++ b/src/test/gb-test.cpp
@@ -9,7 +9,6 @@
 #include "mathicgb/io-util.hpp"
 #include "mathicgb/PolyHeap.hpp"
 #include "mathicgb/GroebnerBasis.hpp"
-#include "mathicgb/SPairHandler.hpp"
 #include "mathicgb/SignatureGB.hpp"
 #include "mathicgb/BuchbergerAlg.hpp"
 #include "test/ideals.hpp"
diff --git a/src/test/poly-test.cpp b/src/test/poly-test.cpp
index f21fb4a..7a950f3 100755
--- a/src/test/poly-test.cpp
+++ b/src/test/poly-test.cpp
@@ -19,7 +19,6 @@
 #include "mathicgb/PolyHeap.hpp"
 #include "mathicgb/PolyGeoBucket.hpp"
 #include "mathicgb/GroebnerBasis.hpp"
-#include "mathicgb/SPairHandler.hpp"
 #include "mathicgb/SignatureGB.hpp"
 
 #include <gtest/gtest.h>

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