32 inline size_t getPopVar(
const size_t* divCounts,
const size_t varCount) {
33 return max_element(divCounts, divCounts + varCount) - divCounts;
36 inline size_t getRareVar(
const size_t* divCounts,
const size_t varCount) {
37 const size_t* end = divCounts + varCount;
38 const size_t* rare = divCounts;
44 const size_t* it = rare + 1;
45 for (; it != end; ++it)
46 if (*it > 0 && *it < *rare)
49 return rare - divCounts;
52 inline void makeRareVarsMask
53 (
Word* mask,
const size_t* divCounts,
const size_t varCount) {
54 const size_t rareVar = getRareVar(divCounts, varCount);
55 ASSERT(rareVar < varCount);
56 const size_t maxCount = divCounts[rareVar];
58 for (
size_t var = 0; var < varCount; ++var)
59 if (divCounts[var] == maxCount)
63 class RawSquareFreeTerm {
65 RawSquareFreeTerm(): _term(0), _capacity(0) {}
66 ~RawSquareFreeTerm() {
delete _term;}
68 operator Word*() {
return _term;}
69 operator const Word*()
const {
return _term;}
71 void reserve(
const size_t varCount) {
72 if (varCount > _capacity) {
86 Word* termWithCapacity(
const size_t varCount) {
87 _term.reserve(varCount);
92 RawSquareFreeTerm _term;
95 class StdStrategy :
public WithPivotTerm {
98 const size_t* divCounts) = 0;
99 virtual void computationCompleted(
const PivotEulerAlg& alg) {}
100 virtual bool shouldTranspose(
const EulerState& state)
const {
105 class StdPopVar :
public StdStrategy {
112 virtual Word* getPivot(
const EulerState& state,
const size_t* divCounts) {
114 Word* pivot = termWithCapacity(varCount);
120 static const char* staticGetName() {
124 virtual void getName(ostream& out)
const {
125 out << staticGetName();
129 class StdRareVar :
public StdStrategy {
136 virtual Word* getPivot(
const EulerState& state,
const size_t* divCounts) {
138 Word* pivot = termWithCapacity(varCount);
144 static const char* staticGetName() {
148 virtual void getName(ostream& out)
const {
149 out << staticGetName();
153 class StdPopGcd :
public StdStrategy {
159 virtual Word* getPivot(
const EulerState& state,
const size_t* divCounts) {
161 const size_t popVar = getPopVar(divCounts, varCount);
162 Word* pivot = termWithCapacity(varCount);
164 if (divCounts[popVar] == 1) {
173 for (; it != end; ++it) {
188 static const char* staticGetName() {
192 virtual void getName(ostream& out)
const {
193 out << staticGetName();
197 class StdRandom :
public StdStrategy {
200 const size_t random = getRandomNotEliminatedVar(state);
204 virtual Word* getPivot(
const EulerState& state,
const size_t* divCounts) {
206 const size_t random = getRandomNotEliminatedVar(state);
207 Word* pivot = termWithCapacity(varCount);
213 static const char* staticGetName() {
217 virtual void getName(ostream& out)
const {
218 out << staticGetName();
222 size_t getRandomNotEliminatedVar(
const EulerState& state) {
231 class StdAny :
public StdStrategy {
234 const size_t any = getAnyNotEliminatedVar(state);
238 virtual Word* getPivot(
const EulerState& state,
const size_t* divCounts) {
240 const size_t any = getAnyNotEliminatedVar(state);
241 Word* pivot = termWithCapacity(varCount);
247 static const char* staticGetName() {
251 virtual void getName(ostream& out)
const {
252 out << staticGetName();
256 size_t getAnyNotEliminatedVar(
const EulerState& state) {
257 for (
size_t var = 0; ; ++var) {
265 class StdWiden :
public WithPivotTerm {
267 StdWiden(auto_ptr<StdStrategy> strat):
269 ASSERT(_strat.get() != 0);
274 Word* narrow = _strat->getPivot(state, divCounts);
275 Word* wide = termWithCapacity(varCount);
280 virtual void getName(ostream& out)
const {
282 _strat->getName(out);
285 virtual void computationCompleted(
const PivotEulerAlg& alg) {
286 _strat->computationCompleted(alg);
289 virtual bool shouldTranspose(
const EulerState& state)
const {
290 return _strat->shouldTranspose(state);
294 auto_ptr<StdStrategy> _strat;
297 class GenStrategy :
public WithPivotTerm {
301 virtual iterator filter(iterator begin, iterator end,
302 const size_t* divCounts,
303 const size_t varCount) = 0;
304 virtual void computationCompleted(
const PivotEulerAlg& alg) {}
305 virtual bool shouldTranspose(
const EulerState& state)
const {
310 class GenPopVar :
public GenStrategy {
319 virtual iterator filter(iterator begin, iterator end,
320 const size_t* divCounts,
321 const size_t varCount) {
322 size_t popVar = getPopVar(divCounts, varCount);
323 Word* term = termWithCapacity(varCount);
325 for (
size_t var = 0; var < varCount; ++var)
326 if (divCounts[var] == divCounts[popVar])
329 iterator newEnd = begin;
330 for (iterator it = begin; it != end; ++it) {
339 static const char* staticGetName() {
343 virtual void getName(ostream& out)
const {
344 out << staticGetName();
348 class GenRareMax :
public GenStrategy {
354 const size_t rareVar = getRareVar(divCounts, varCount);
356 const const_iterator end = ideal.
end();
357 size_t bestSupport = 0;
358 const_iterator best = end;
359 for (const_iterator it = ideal.
begin(); it != end; ++it) {
363 if (bestSupport < support) {
364 bestSupport = support;
372 virtual iterator filter(iterator begin, iterator end,
373 const size_t* divCounts,
374 const size_t varCount) {
375 const size_t rareVar = getRareVar(divCounts, varCount);
377 size_t bestSupport = 0;
378 iterator newEnd = begin;
379 for (iterator it = begin; it != end; ++it) {
383 if (bestSupport > support)
385 if (bestSupport < support) {
387 bestSupport = support;
395 static const char* staticGetName() {
399 virtual void getName(ostream& out)
const {
400 out << staticGetName();
404 class GenRareVar :
public GenStrategy {
413 virtual iterator filter(iterator begin, iterator end,
414 const size_t* divCounts,
415 const size_t varCount) {
416 size_t rareVar = getRareVar(divCounts, varCount);
418 iterator newEnd = begin;
419 for (iterator it = begin; it != end; ++it) {
428 static const char* staticGetName() {
432 virtual void getName(ostream& out)
const {
433 out << staticGetName();
441 _filtersDeleter(_filters) {
446 void addStrategy(auto_ptr<GenStrategy> strat) {
456 for (
size_t i = 0; i < _filters.size(); ++i)
457 end = _filters[i]->filter(begin, end, divCounts, varCount);
463 virtual void getName(ostream& out)
const {
464 for (
size_t i = 0; i < _filters.size(); ++i) {
467 _filters[i]->getName(out);
471 virtual void computationCompleted(
const PivotEulerAlg& alg) {
472 for (
size_t i = 0; i < _filters.size(); ++i)
473 _filters[i]->computationCompleted(alg);
476 virtual bool shouldTranspose(
const EulerState& state)
const {
477 return _filters.front()->shouldTranspose(state);
481 vector<GenStrategy*> _filters;
485 class GenRarestVars :
public GenStrategy {
490 divCounts, varCount);
494 virtual iterator filter(iterator begin, iterator end,
495 const size_t* divCounts,
496 const size_t varCount) {
497 size_t lastDivCount = 0;
498 while (end - begin > 1) {
499 size_t minDivCount = numeric_limits<size_t>::max();
500 for (
size_t var = 0; var < varCount; ++var)
501 if (divCounts[var] > lastDivCount && minDivCount > divCounts[var])
502 minDivCount = divCounts[var];
503 if (minDivCount == numeric_limits<size_t>::max())
506 end = filter(begin, end, divCounts, varCount, minDivCount);
507 lastDivCount = minDivCount;
512 static const char* staticGetName() {
516 virtual void getName(ostream& out)
const {
517 out << staticGetName();
521 iterator filter(iterator begin, iterator end,
522 const size_t* divCounts,
523 const size_t varCount,
526 Word* term = termWithCapacity(varCount);
528 for (
size_t var = 0; var < varCount; ++var)
529 if (divCounts[var] == divCount)
534 iterator newEnd = begin;
535 size_t maxRareCount = 0;
536 _tmp.reserve(varCount);
538 for (iterator it = begin; it != end; ++it) {
545 if (maxRareCount > rareCount)
547 if (maxRareCount < rareCount) {
548 maxRareCount = rareCount;
566 for (; it != stop; ++it)
567 if (rarer(*it, *rarest, divCounts, varCount))
569 return rarest - ideal.
begin();
575 pair<size_t, size_t> getRarity(
const Word*
const term,
576 const size_t* divCounts,
577 const size_t varCount,
579 size_t rarity = varCount;
580 size_t multiplicity = 0;
581 for (
size_t var = 0; var < varCount; ++var) {
582 const size_t co = divCounts[var];
584 ASSERT(divCounts[var] != 0);
588 rarity = divCounts[var];
593 return make_pair(rarity, multiplicity);
596 bool rarer(
const Word*
const a,
const Word*
const b,
597 const size_t* divCounts,
598 const size_t varCount) {
599 size_t lookAbove = 0;
601 pair<size_t, size_t> rarityA =
602 getRarity(a, divCounts, varCount, lookAbove);
603 pair<size_t, size_t> rarityB =
604 getRarity(b, divCounts, varCount, lookAbove);
606 if (rarityA.first < rarityB.first)
608 if (rarityA.first > rarityB.first)
611 if (rarityA.second > rarityB.second)
613 if (rarityA.second < rarityB.second)
616 if (rarityA.second == 0)
619 lookAbove = rarityA.first;
623 RawSquareFreeTerm _tmp;
626 class GenMaxSupport :
public GenStrategy {
632 virtual iterator filter(iterator begin, iterator end,
633 const size_t* divCounts,
634 const size_t varCount) {
636 iterator newEnd = begin;
637 for (iterator it = begin; it != end; ++it) {
641 if (maxSupp < supp) {
651 static const char* staticGetName() {
655 virtual void getName(ostream& out)
const {
656 out << staticGetName();
660 class GenMinSupport :
public GenStrategy {
666 virtual iterator filter(iterator begin, iterator end,
667 const size_t* divCounts,
668 const size_t varCount) {
669 size_t minSupp = varCount;
670 iterator newEnd = begin;
671 for (iterator it = begin; it != end; ++it) {
675 if (minSupp > supp) {
685 static const char* staticGetName() {
689 virtual void getName(ostream& out)
const {
690 out << staticGetName();
694 class GenAny :
public GenStrategy {
700 virtual iterator filter(iterator begin, iterator end,
701 const size_t* divCounts,
702 const size_t varCount) {
706 static const char* staticGetName() {
710 virtual void getName(ostream& out)
const {
711 out << staticGetName();
715 class GenRandom :
public GenStrategy {
722 virtual iterator filter(iterator begin, iterator end,
723 const size_t* divCounts,
724 const size_t varCount) {
725 const size_t genCount = end - begin;
726 const size_t choice = rand() % genCount;
727 Ops::swap(*begin, *(begin + choice), varCount);
731 static const char* staticGetName() {
735 virtual void getName(ostream& out)
const {
736 out << staticGetName();
742 HybridPivotStrategy(auto_ptr<PivotStrategy> stdStrat,
743 auto_ptr<PivotStrategy> genStrat):
744 _stdStrat(stdStrat), _genStrat(genStrat) {}
749 return _stdStrat->doPivot(state, divCounts);
751 return _genStrat->doPivot(state, divCounts);
754 virtual void getName(ostream& out)
const {
756 _stdStrat->getName(out);
758 _genStrat->getName(out);
762 virtual void computationCompleted(
const PivotEulerAlg& alg) {
763 _stdStrat->computationCompleted(alg);
764 _genStrat->computationCompleted(alg);
767 virtual bool shouldTranspose(
const EulerState& state)
const {
772 auto_ptr<PivotStrategy> _stdStrat;
773 auto_ptr<PivotStrategy> _genStrat;
778 DebugStrategy(auto_ptr<PivotStrategy> strat, FILE* out):
779 _strat(strat), _out(out) {}
782 const size_t* divCounts) {
783 const char* str1 =
"\n\n\n"
784 "********************************(debug output)********************************\n"
785 "********** Processing this simplified state that is not a base case **********\n";
789 EulerState* subState = _strat->doPivot(state, divCounts);
793 "<<<<<<<<<<<<<<<<<<<<<<<<<<<< Substate 1 of 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
798 "<<<<<<<<<<<<<<<<<<<<<<<<<<<< Substate 2 of 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
800 subState->
print(_out);
805 virtual void getName(ostream& out)
const {
806 _strat->getName(out);
809 virtual void computationCompleted(
const PivotEulerAlg& alg) {
810 _strat->computationCompleted(alg);
811 fputs(
"Debug: Euler characteristic computation completed.\n", _out);
812 gmp_fprintf(_out,
"Debug: Computed Euler characteristics was %Zd.\n",
816 virtual bool shouldTranspose(
const EulerState& state)
const {
817 return _strat->shouldTranspose(state);
821 auto_ptr<PivotStrategy> _strat;
828 _strat(strat), _out(out), _statesSplit(0), _transposes(0) {}
832 return _strat->doPivot(state, divCounts);
835 virtual void getName(ostream& out)
const {
836 _strat->getName(out);
839 virtual void computationCompleted(
const PivotEulerAlg& alg) {
840 _strat->computationCompleted(alg);
841 fputs(
"******** Statistics for Euler characteristic computation *****\n", _out);
842 fprintf(_out,
"* Using unique div simplify: %s\n",
844 fprintf(_out,
"* Using many div simplify: %s\n",
846 fprintf(_out,
"* Using implied div simplify: %s\n",
848 fprintf(_out,
"* Do initial autotranspose: %s\n",
850 fprintf(_out,
"* Do autotranspose at each step: %s\n",
852 ostringstream strategyName;
853 getName(strategyName);
854 fprintf(_out,
"* Pivot strategy: %s\n", strategyName.str().c_str());
859 unsigned long totalStates = 2 * _statesSplit + 1;
860 fprintf(_out,
"* States processed: %lu\n", (
unsigned long)totalStates);
861 fprintf(_out,
"* Transposes taken: %lu\n", (
unsigned long)_transposes);
862 fputs(
"********\n", _out);
865 virtual bool shouldTranspose(
const EulerState& state)
const {
866 const bool should = _strat->shouldTranspose(state);
873 auto_ptr<PivotStrategy> _strat;
875 unsigned long _statesSplit;
876 mutable unsigned long _transposes;
880 StdFactory getStdStratFactory() {
881 StdFactory factory(
"standard pivot strategy");
882 nameFactoryRegister<StdRandom>(factory);
883 nameFactoryRegister<StdAny>(factory);
884 nameFactoryRegister<StdPopVar>(factory);
885 nameFactoryRegister<StdPopGcd>(factory);
886 nameFactoryRegister<StdRareVar>(factory);
891 GenFactory getGenStratFactory() {
892 GenFactory factory(
"generator pivot strategy");
893 nameFactoryRegister<GenRareMax>(factory);
894 nameFactoryRegister<GenRareVar>(factory);
895 nameFactoryRegister<GenRarestVars>(factory);
896 nameFactoryRegister<GenPopVar>(factory);
897 nameFactoryRegister<GenMaxSupport>(factory);
898 nameFactoryRegister<GenMinSupport>(factory);
899 nameFactoryRegister<GenAny>(factory);
900 nameFactoryRegister<GenRandom>(factory);
906 if (name.compare(0, 6,
"widen_") != 0) {
907 auto_ptr<StdStrategy> strat = getStdStratFactory().create(name);
908 return auto_ptr<PivotStrategy>(strat.release());
911 auto_ptr<StdStrategy> subStrat =
912 getStdStratFactory().create(name.substr(6, name.size() - 6));
913 return auto_ptr<PivotStrategy>(
new StdWiden(subStrat));
917 GenFactory factory = getGenStratFactory();
918 if (name.find(
'_') == string::npos) {
919 auto_ptr<GenStrategy> strat = factory.create(name);
920 return auto_ptr<PivotStrategy>(strat.release());
923 auto_ptr<GenComposite> composite(
new GenComposite());
928 size_t nextPos = name.find(
'_', pos);
929 if (nextPos == string::npos) {
930 part = name.substr(pos, string::npos);
933 part = name.substr(pos, nextPos - pos);
937 auto_ptr<GenStrategy> strat = factory.create(part);
938 composite->addStrategy(strat);
939 }
while (pos != string::npos);
940 return auto_ptr<PivotStrategy>(composite.release());
944 (auto_ptr<PivotStrategy> stdStrat, auto_ptr<PivotStrategy> genStrat) {
945 PivotStrategy* strat =
new HybridPivotStrategy(stdStrat, genStrat);
946 return auto_ptr<PivotStrategy>(strat);
951 return auto_ptr<PivotStrategy>(
new DebugStrategy(strat, out));
955 (auto_ptr<PivotStrategy> strat, FILE* out) {
void exceptionSafePushBack(Container &container, auto_ptr< Element > pointer)
auto_ptr< PivotStrategy > newStdPivotStrategy(const string &name)
auto_ptr< PivotStrategy > newGenPivotStrategy(const string &name)
auto_ptr< PivotStrategy > newStatisticsPivotStrategy(auto_ptr< PivotStrategy > strat, FILE *out)
auto_ptr< PivotStrategy > newDefaultPivotStrategy()
auto_ptr< PivotStrategy > newDebugPivotStrategy(auto_ptr< PivotStrategy > strat, FILE *out)
auto_ptr< PivotStrategy > newHybridPivotStrategy(auto_ptr< PivotStrategy > stdStrat, auto_ptr< PivotStrategy > genStrat)
DebugStrategy(SliceStrategy *strategy, FILE *out)
Debug information is written to out, and every call is delegated to strategy.
EulerState * inPlaceGenSplit(size_t pivotIndex)
const Word * getEliminatedVars() const
size_t getVarCount() const
RawSquareFreeIdeal & getIdeal()
EulerState * inPlaceStdSplit(size_t pivotVar)
size_t getNonEliminatedVarCount() const
A NameFactory takes a name and then creates an instance of a class that has been previously registere...
bool getInitialAutoTranspose() const
bool getUseUniqueDivSimplify() const
bool getUseAllPairsSimplify() const
const mpz_class & getComputedEulerCharacteristic() const
bool getUseManyDivSimplify() const
bool getAutoTranspose() const
A pivot selection strategy for the Euler algorithm.
const_iterator doesn't have all it needs to be a proper STL iterator.
iterator doesn't have all it needs to be a proper STL iterator.
A bit packed square free ideal placed in a pre-allocated buffer.
void getGcdOfMultiples(Word *gcd, size_t var) const
Sets gcd to be the greatest common denominator of those generators that are divisible by var.
size_t getMinSupportGen() const
Returns the index of a generator with minimum support.
size_t getMaxSupportGen() const
Returns the index of a generator with maximum support.
size_t getVarCount() const
size_t getMultiple(size_t var) const
Returns the index of the first generator that var divides or getGeneratorCount() if no such generator...
size_t getGeneratorCount() const
A wrapper for a SliceStrategy that collects statistics on what is going on, while delegating everythi...
void setExponent(Word *a, size_t var, bool value)
Word * newTerm(size_t varCount)
Returns identity term of varCount variables.
size_t getSizeOfSupport(const Word *a, size_t varCount)
bool getExponent(const Word *a, size_t var)
returns true if var divides a and false otherwise.
void deleteTerm(Word *term)
Deletes term previously returned by newTerm().
void gcdInPlace(Word *res, const Word *resEnd, const Word *a)
void assign(Word *a, const Word *b, size_t varCount)
bool isRelativelyPrime(const Word *a, const Word *b, size_t varCount)
void gcd(Word *res, const Word *resEnd, const Word *a, const Word *b)
void setToIdentity(Word *res, const Word *resEnd)
void swap(hashtable< _Val, _Key, _HF, _Extract, _EqKey, _All > &__ht1, hashtable< _Val, _Key, _HF, _Extract, _EqKey, _All > &__ht2)
unsigned long Word
The native unsigned type for the CPU.