[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