Macaulay2 Engine
Loading...
Searching...
No Matches
NCReduction.cpp
Go to the documentation of this file.
2
3#include "NCAlgebras/FreeAlgebra.hpp" // for FreeAlgebra
4#include "NCAlgebras/FreeMonoid.hpp" // for MonomEq, FreeMonoid
5#include "MemoryBlock.hpp" // for MemoryBlock
6#include "NCAlgebras/NCGroebner.hpp" // for tryOutMathicCode
7#include "NCAlgebras/Word.hpp" // for Word
8#include "myalloc.hpp" // for StatsAllocator
9#include "ring.hpp" // for Ring
10#include "style.hpp" // for EQ, LT, GT
11
12#include <cassert> // for assert
13#include <mathic/Geobucket.h> // for Geobucket, GeoStoreSameSizeBuffer
14#include <mathic/Heap.h> // for Heap
15#include <mathic/TourTree.h> // for TourTree
16#include <algorithm> // for copy
17#include <iostream> // for string, operator<<, endl, basi...
18#include <map> // for map, __map_iterator, operator!=
19#include <memory> // for unique_ptr
20#include <queue> // for priority_queue
21#include <type_traits> // for swap
22#include <vector> // for vector
23
24#if 0
25Reasoning about using these structures in noncomm reduction.
26Possible ways:
271. Entry = [ringelem, monomial]
28 Questions: how is the monomial represented?
29 where is the allocated space for it?
30 are they uniquely represented i.e. are we using deduplicate, hashtable, etc?
31
32 Monomial Pool
33 Entry = pointer to [ringelem, monomial pointer]
34 deduplicate: write this.
35 cmpLessThan: monomial comparison call.
36
37 Monomial Pool
38 Hash Table of monomials. Monomial pointers are unique.
39 Pointer value could contain space for the ringelem.
40 Entry = pointer to [ringelem, monomial pointer]
41
422. Entry = PolyWithPosition
43 QueueConfiguration could own these polynomials (i.e. the Queue itself could).
44 we might need to write the 'value' function: keep popping off lead term, append to a poly.
45
46 monomial pool: use memtailor to generate this space.
47 make a new monomial in the pool.
48 PolynomialWithPosition pool. [leadmonomial, coeff, lmon, rmon, index into the poly we are using, which poly]
49 F - aGb - cGd - ...
50#endif
51
64{
65public:
66 using Entry = int; // think of each Entry as a monomial.
67 enum class CompareResult {LT, EQ, GT};
68 CompareResult compare(const Entry& a, const Entry& b) const
69 {
70 if (a < b) return CompareResult::LT;
71 if (a > b) return CompareResult::GT;
72 return CompareResult::EQ;
73 }
74 bool cmpLessThan(CompareResult a) const { return a == CompareResult::LT; }
75
76 // Specific for Geobucket
77 const size_t minBucketSize = 2;
78 const size_t geoBase = 4;
79 static const size_t insertFactor = 4;
80
81 static const bool supportDeduplication = false;
82 bool cmpEqual(CompareResult a) const; // no implementation needed
83 Entry deduplicate(Entry a, Entry b) const; // no implementation needed
84
85 static const bool minBucketBinarySearch = false;
86 static const bool trackFront = true;
87 static const bool premerge = false;
88 static const bool collectMax = true;
89
90 static const mathic::GeobucketBucketStorage bucketStorage = mathic::GeoStoreSameSizeBuffer;
91};
92
105{
106public:
107 using Entry = int; // think of each Entry as a monomial.
108 enum class CompareResult {LT, EQ, GT};
109 CompareResult compare(const Entry& a, const Entry& b) const
110 {
111 if (a < b) return CompareResult::LT;
112 if (a > b) return CompareResult::GT;
113 return CompareResult::EQ;
114 }
115 bool cmpLessThan(CompareResult a) const { return a == CompareResult::LT; }
116
117 // Specific for Geobucket
118 const size_t minBucketSize = 2;
119 const size_t geoBase = 4;
120 static const size_t insertFactor = 4;
121
122 static const bool supportDeduplication = true;
123
124 bool cmpEqual(CompareResult a) const { return a == CompareResult::EQ; }
125
126 Entry deduplicate(Entry a, Entry b) const { return a + b + 1000; }
127
128 static const bool minBucketBinarySearch = false;
129 static const bool trackFront = true;
130 static const bool premerge = false;
131 static const bool collectMax = true;
132
133 static const mathic::GeobucketBucketStorage bucketStorage = mathic::GeoStoreSameSizeBuffer;
134};
135
136std::unique_ptr<mathic::Geobucket<OurQueueConfiguration>> makeQueue()
137{
139
140 return std::make_unique<mathic::Geobucket<OurQueueConfiguration>>(C);
141}
142
143std::unique_ptr<mathic::Geobucket<OurQueueConfiguration1>> makeQueue1()
144{
146
147 return std::make_unique<mathic::Geobucket<OurQueueConfiguration1>>(C);
148}
149
163{
164public:
166 : mRing(F),
167 mValue{},
168 mIter(mValue.cbegin())
169 {
170 }
171
173
174 void clear() override { mRing.setZero(mValue); mIter = mValue.cbegin(); }
175
176 // prevent copy and assignment constructors
177 // allow move constructors, I guess?
180
181 PolynomialHeap& addPolynomial(const Poly& poly) override
182 {
183 Poly g;
184 mRing.add(g, mIter, mValue.cend(), poly.cbegin(), poly.cend());
186 mIter = mValue.cbegin();
187 return *this;
188 }
189
191 Word left,
192 Word right,
193 const Poly& poly) override
194 {
195 mRing.setZero(f);
196 mRing.setZero(g);
197 // Create f = coeff * left * poly * right;
198 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
199 mRing.add(g, mIter, mValue.cend(), f.cbegin(), f.cend());
201 mIter = mValue.cbegin();
202 return *this;
203 }
204
205 bool isZero() override
206 {
207 return mIter == mValue.cend();
208 }
209
210 std::pair<Monom, ring_elem> viewLeadTerm() override
211 {
212 return std::make_pair(mIter.monom(), mIter.coeff());
213 }
214
215 void removeLeadTerm() override
216 {
217 assert(mIter != mValue.cend());
218 ++mIter;
219 }
220
221 Poly* value() override
222 {
223 auto result = new Poly;
224 mRing.copy(*result, mIter, mValue.cend());
225 return result;
226 }
227
228 size_t getMemoryUsedInBytes() override
229 {
230 return mValue.numTerms();
231 }
232
233 std::string getName() const override { return std::string("Trivial Heap"); }
234
235private:
238 Poly::const_iterator mIter;
239 Poly f; // tmp values. Remember to zero them out before use.
241};
242
244// NaivePolynomialHeap /////////////
246
259{
260public:
262
263 using Entry = std::pair<Monom, ring_elem>;
264
265 enum class CompareResult {LT, EQ, GT, Error};
266 CompareResult compare(const Entry& a, const Entry& b) const
267 {
268 int cmp = mRing.monoid().compare(a.first, b.first);
269 if (cmp == LT) return CompareResult::LT;
270 if (cmp == GT) return CompareResult::GT;
271 if (cmp == EQ) return CompareResult::EQ;
272
273 std::cout << "Unexpected monomial comparison error in heap." << std::endl << std::flush;
275 }
276
277 bool cmpLessThan(CompareResult a) const { return a == CompareResult::LT; }
278
279 // Specific for Geobucket
280 const size_t minBucketSize = 2;
281 const size_t geoBase = 4;
282 static const size_t insertFactor = 4;
283
284 // specific for Heap
285 static const bool fastIndex = false;
286 // if set to true, a faster way of calculating indices is used
287 // but for this to work, sizeof(Entry) must be a power of two (which it
288 // should already be, since both Monom and ring_elem are really pointers?
289
290 static const bool supportDeduplication = false;
291 bool cmpEqual(CompareResult a) const; // no implementation needed
292 Entry deduplicate(Entry a, Entry b) const; // no implementation needed
293
294 static const bool minBucketBinarySearch = true;
295 static const bool trackFront = true;
296 static const bool premerge = false;
297 static const bool collectMax = true;
298
299 static const mathic::GeobucketBucketStorage bucketStorage = mathic::GeoStoreSameSizeBuffer;
300private:
302};
303
315{
316public:
318
319 using Entry = std::pair<Monom, ring_elem>;
320
321 enum class CompareResult {LT, EQ, GT, Error};
322 CompareResult compare(const Entry& a, const Entry& b) const
323 {
324 int cmp = mRing.monoid().compare(a.first, b.first);
325 if (cmp == LT) return CompareResult::LT;
326 if (cmp == GT) return CompareResult::GT;
327 if (cmp == EQ) return CompareResult::EQ;
328
329 std::cout << "Unexpected monomial comparison error in heap." << std::endl << std::flush;
331 }
332 bool cmpLessThan(CompareResult a) const { return a == CompareResult::LT; }
333
334 // Specific for Geobucket
335 const size_t minBucketSize = 2;
336 const size_t geoBase = 4;
337 static const size_t insertFactor = 4;
338
339 // specific for Heap
340 static const bool fastIndex = false;
341 // if set to true, a faster way of calculating indices is used
342 // but for this to work, sizeof(Entry) must be a power of two (which it
343 // should already be, since both Monom and ring_elem are really pointers?
344
345 static const bool supportDeduplication = true;
346 bool cmpEqual(CompareResult a) const { return a == CompareResult::EQ; }
348 {
349 ring_elem c = mRing.coefficientRing()->add(a.second, b.second);
350 return Entry(a.first, c);
351 }
352
353 static const bool minBucketBinarySearch = true;
354 static const bool trackFront = true;
355 static const bool premerge = false;
356 static const bool collectMax = true;
357
358 static const mathic::GeobucketBucketStorage bucketStorage = mathic::GeoStoreSameSizeBuffer;
359private:
361};
362
363template<template<typename> class Queue>
365{
366public:
368
370 : mRing(F),
372 mLeadTermSet(false),
373 mLeadTerm(Monom(), F.coefficientRing()->zero())
374 {
375 }
376
378
379 void clear() override {
380 // clear the heap. The free algebra is kept the same
381 // but all other aspects are reset. The MonomialSpace
382 // has all its data freed to the arena, but is available for
383 // use without any new allocations for the next computation.
384 mLeadTermSet = false;
385 mQueue.clear();
386 mMonomialSpace.deallocateAll();
387 }
388
389 // prevent copy and assignment constructors
390 // allow move constructors, I guess?
393
395 {
396 if (mLeadTermSet)
397 {
398 mQueue.push(mLeadTerm);
399 mLeadTermSet = false;
400 }
401 for (auto i = poly.cbegin(); i != poly.cend(); ++i)
402 {
403 auto rg = mMonomialSpace.allocateArray<int>(i.monom().size());
404 std::copy(i.monom().begin(), i.monom().end(), rg.first);
405 mQueue.push(Entry(Monom(rg.first), i.coeff()));
406 }
407 return *this;
408 }
409
411 Word left,
412 Word right,
413 const Poly& poly) override
414 {
415 Poly f;
416 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
417 addPolynomial(f);
418 return *this;
419 }
420
421 bool isZero() override
422 {
423 if (mLeadTermSet) return false;
424 if (mQueue.empty()) return true;
425 Entry lt = mQueue.pop();
426 while (not mQueue.empty())
427 {
428 Entry e = mQueue.top();
429 // this is bad - compare should not be used to check equality
430 if (mRing.monoid().compare(e.first, lt.first) == EQ)
431 {
432 lt.second = mRing.coefficientRing()->add(lt.second, e.second);
433 mQueue.pop();
434 }
435 else
436 {
437 if (not mRing.coefficientRing()->is_zero(lt.second))
438 {
439 mLeadTermSet = true;
440 mLeadTerm = lt;
441 return false;
442 }
443 else
444 lt = mQueue.pop();
445 }
446 }
447 if (not mRing.coefficientRing()->is_zero(lt.second))
448 {
449 mLeadTermSet = true;
450 mLeadTerm = lt;
451 return false;
452 }
453 return true;
454 }
455
456 std::pair<Monom, ring_elem> viewLeadTerm() override
457 {
458 if (isZero())
459 {
460 std::cout << "viewLeadTerm called without checking if polynomial is zero" << std::endl;
461 assert(false);
462 }
463 assert(mLeadTermSet);
464 return mLeadTerm;
465 }
466
467 void removeLeadTerm() override
468 {
469 if (isZero()) return;
470 assert(mLeadTermSet); // should only be called if mLeadTermSet is true.
471 if (mLeadTermSet)
472 mLeadTermSet = false;
473 }
474
475 Poly* value() override
476 {
477 Poly* f = new Poly;
478 if (mLeadTermSet)
479 mQueue.push(mLeadTerm);
480 mLeadTermSet = false;
481 while (not isZero())
482 {
483 auto tm = viewLeadTerm();
484 mRing.add_to_end(*f, tm.second, tm.first);
486 }
487 addPolynomial(*f);
488 return f;
489 }
490
491 size_t getMemoryUsedInBytes() override
492 {
493 return mQueue.getMemoryUse() + mMonomialSpace.getMemoryUsedInBytes();
494 }
495
496 std::string getName() const override { return mQueue.getName(); }
497
498private:
500 Queue<NaiveQueueConfiguration> mQueue;
502 bool mLeadTermSet; // true means mLeadTerm is set, to a non-zero value.
503 std::pair<Monom, ring_elem> mLeadTerm;
504};
505
506
507template<template<typename> class Queue>
509{
510public:
512
518
520
521 void clear() override {
522 // clear the heap. The free algebra is kept the same
523 // but all other aspects are reset. The MonomialSpace
524 // has all its data freed to the arena, but is available for
525 // use without any new allocations for the next computation.
526 mQueue.clear();
527 mMonomialSpace.deallocateAll();
528 }
529
530 // prevent copy and assignment constructors
531 // allow move constructors, I guess?
534
536 {
537 for (auto i = poly.cbegin(); i != poly.cend(); ++i)
538 {
539 auto rg = mMonomialSpace.allocateArray<int>(i.monom().size());
540 std::copy(i.monom().begin(), i.monom().end(), rg.first);
541 mQueue.push(Entry(Monom(rg.first), i.coeff()));
542 }
543 return *this;
544 }
545
547 Word left,
548 Word right,
549 const Poly& poly) override
550 {
551 Poly f;
552 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
553 addPolynomial(f);
554 return *this;
555 }
556
557 bool isZero() override
558 {
559 // idempotent function.
560 while (not mQueue.empty())
561 {
562 Entry e = mQueue.top();
563 if (mRing.coefficientRing()->is_zero(e.second))
564 mQueue.pop();
565 else
566 return false;
567 }
568 return true;
569 }
570
571 std::pair<Monom, ring_elem> viewLeadTerm() override
572 {
573 return mQueue.top();
574 }
575
576 void removeLeadTerm() override
577 {
578 mQueue.pop();
579 }
580
581 Poly* value() override
582 {
583 Poly* f = new Poly;
584 while (not isZero())
585 {
586 auto tm = viewLeadTerm();
587 mRing.add_to_end(*f, tm.second, tm.first);
589 }
590 addPolynomial(*f);
591 return f;
592 }
593
594 size_t getMemoryUsedInBytes() override
595 {
596 return mQueue.getMemoryUse() + mMonomialSpace.getMemoryUsedInBytes();
597 }
598
599 std::string getName() const override { return mQueue.getName(); }
600
601private:
603 Queue<NaiveDedupQueueConfiguration> mQueue;
605};
606
607
621{
622public:
623 using Entry = std::pair<Monom, ring_elem>;
624 using ConstEntry = std::pair<const Monom, ring_elem>;
625
627 : mRing(F),
628 mMonomEq(F.monoid()),
630 {
631 }
632
634
635 void clear() override {
636 // clear the heap. The free algebra is kept the same
637 // but all other aspects are reset. The MonomialSpace
638 // has all its data freed to the arena, but is available for
639 // use without any new allocations for the next computation.
640 mMap.clear();
641 mMonomialSpace.deallocateAll();
642 }
643
644 // prevent copy and assignment constructors
645 // allow move constructors, I guess?
648
649 void addTerm(Entry tm)
650 {
651 auto result = mMap.find(tm.first);
652 bool found = (result != mMap.end());
653 if (found)
654 {
655 result->second = mRing.coefficientRing()->add(tm.second, result->second);
656 }
657 else
658 {
659 // need to allocate new term, and insert into hash table and the queue.
660 auto rg = mMonomialSpace.allocateArray<int>(tm.first.size());
661 std::copy(tm.first.begin(), tm.first.end(), rg.first);
662 mMap.insert({Monom(rg.first), tm.second});
663 }
664 }
665
666 MapPolynomialHeap& addPolynomial(const Poly& poly) override
667 {
668 for (auto i = poly.cbegin(); i != poly.cend(); ++i)
669 {
670 addTerm(Entry(i.monom(), i.coeff()));
671 }
672 return *this;
673 }
674
676 Word left,
677 Word right,
678 const Poly& poly) override
679 {
680 Poly f;
681 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
682 addPolynomial(f);
683 return *this;
684 }
685
686 bool isZero() override
687 {
688 // idempotent function.
689 while (not mMap.empty())
690 {
691 const Entry& e = *(mMap.begin());
692 if (mRing.coefficientRing()->is_zero(e.second))
693 mMap.erase(mMap.begin());
694 else
695 return false;
696 }
697 return true;
698 }
699
701 {
702 return * (mMap.begin());
703 }
704
705 void removeLeadTerm() override
706 {
707 mMap.erase(mMap.begin());
708 }
709
710 Poly* value() override
711 {
712 Poly* f = new Poly;
713 while (not isZero())
714 {
715 auto tm = viewLeadTerm();
716 mRing.add_to_end(*f, tm.second, tm.first);
718 }
719 addPolynomial(*f);
720 return f;
721 }
722
723 size_t getMemoryUsedInBytes() override
724 {
725 return 0;
726 }
727
728 std::string getName() const override { return "map heap"; }
729
730private:
733 //std::map<Monom, ring_elem, MonomEq, StatsAllocator<ConstEntry>> mMap;
734 std::map<Monom, ring_elem, MonomEq, gc_allocator<ConstEntry>> mMap;
736};
737
738#if 0
739class HashedConfiguration
740{
741public:
742 HashedConfiguration(const FreeAlgebra& F) : mRing(F) {}
743
744 using Entry = Monom;
745 using Term = Entry *;
746
747 // Members needed for Geobucket, TourTree and Heap data structures.
748 enum class CompareResult {LT, EQ, GT, Error};
749 CompareResult compare(const Entry& a, const Entry& b) const
750 {
751 int cmp = mRing.monoid().compare(a->second, b->second);
752 if (cmp == LT) return CompareResult::LT;
753 if (cmp == GT) return CompareResult::GT;
754 if (cmp == EQ) return CompareResult::EQ;
755
756 std::cout << "Unexpected monomial comparison error in heap." << std::endl << std::flush;
757 return CompareResult::Error;
758 }
759
760 bool cmpLessThan(CompareResult a) const { return a == CompareResult::LT; }
761
762 // Specific for Geobucket
763 const size_t minBucketSize = 2;
764 const size_t geoBase = 4;
765 static const size_t insertFactor = 4;
766
767 // specific for Heap
768 static const bool fastIndex = false;
769 // if set to true, a faster way of calculating indices is used
770 // but for this to work, sizeof(Entry) must be a power of two (which it
771 // should already be, since both Monom and ring_elem are really pointers?
772
773 static const bool supportDeduplication = false;
774 bool cmpEqual(CompareResult a) const; // no implementation needed
775 Entry deduplicate(Entry a, Entry b) const; // no implementation needed
776
777 static const bool minBucketBinarySearch = true;
778 static const bool trackFront = true;
779 static const bool premerge = false;
780 static const bool collectMax = true;
781
782 static const mathic::GeobucketBucketStorage bucketStorage = mathic::GeoStoreSameSizeBuffer;
783
784 // Members needed for unordered_set
785 size_t operator()(const Term& term) const // hash value
786 {
787 return 0;
788 }
789 bool operator()(Term& term1, Term& term2) const // check for equality
790 {
791 return compare(&term1, &term2) == CompareResult::EQ;
792 }
793private:
794 const FreeAlgebra& mRing;
795};
796
797template<template<typename> class Queue>
798class HashedPolynomialHeap : public PolynomialHeap
799{
800public:
801 using Term = HashedConfiguration::Term;
802 using Entry = HashedConfiguration::Entry;
803
804 HashedPolynomialHeap(const FreeAlgebra& F)
805 : mRing(F),
806 mConfig(HashedConfiguration(F)),
807 mQueue(mConfig),
808 mHash(1024, mConfig, mConfig)
809 {
810 }
811
812 virtual ~HashedPolynomialHeap() {}
813
814 // prevent copy and assignment constructors
815 // allow move constructors, I guess?
816 HashedPolynomialHeap operator=(const HashedPolynomialHeap&) = delete;
817 HashedPolynomialHeap(const HashedPolynomialHeap&) = delete;
818
819 HashedPolynomialHeap& addTerm(Term tm)
820 {
821 auto result = mHash.find(tm);
822 bool found = (result != mHash.end());
823 if (found)
824 {
825 const_cast<ring_elem&>(result->first) = mRing.coefficientRing()->add(tm.first, result->first);
826 }
827 else
828 {
829 // need to allocate new term, and insert into hash table and the queue.
830 auto rg = mMonomialSpace.allocateArray<int>(tm.second.size());
831 std::copy(tm.second.begin(), tm.second.end(), rg.first);
832 mQueue.push(&*(inserted.first));
833 auto inserted = mHash.insert(Term(tm.first, rg.first)); // TODO: add in assert check that this insert succeeds
834 }
835 return *this;
836 }
837
838 HashedPolynomialHeap& addPolynomial(const Poly& poly) override
839 {
840 for (auto i = poly.cbegin(); i != poly.cend(); ++i)
841 addTerm(Term(i.coeff(), i.monom()));
842 return *this;
843 }
844
845 HashedPolynomialHeap& addPolynomial(ring_elem coeff,
846 Word left,
847 Word right,
848 const Poly& poly) override
849 {
850 Poly f;
851 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
852 addPolynomial(f);
853 return *this;
854 }
855
856 bool isZero() override
857 {
858 // idempotent function.
859 while (not mQueue.empty())
860 {
861 Entry e = mQueue.top();
862 if (mRing.coefficientRing()->is_zero(e->first))
863 mQueue.pop();
864 else
865 return false;
866 }
867 return true;
868 }
869
870 std::pair<ring_elem, Monom> viewLeadTerm() override
871 {
872 return * mQueue.top();
873 // loop
874 // look at lead element in queue
875 // if coeff is 0, pop it, else continue
876 }
877
878 void removeLeadTerm() override
879 {
880 mQueue.pop();
881 }
882
883 Poly* value() override
884 {
885 Poly* f = new Poly;
886 while (not isZero())
887 {
888 auto tm = viewLeadTerm();
889 mRing.add_to_end(*f, tm.first, tm.second);
891 }
892 addPolynomial(*f);
893 return f;
894 }
895
896 size_t getMemoryUsedInBytes() override
897 {
898 return mQueue.getMemoryUse() + mMonomialSpace.getMemoryUsedInBytes();
899 }
900
901 std::string getName() const override { return mQueue.getName(); }
902
903private:
904 FreeAlgebra mRing;
905 HashedConfiguration mConfig;
906 Queue<HashedConfiguration> mQueue;
907 std::unordered_map<Monom, ring_elem, HashedConfiguration, HashedConfiguration> mHash;
908 MemoryBlock mMonomialSpace;
909};
910#endif
911
927{
928public:
929
930 using Entry = std::pair<Monom,ring_elem>;
931
933
934 size_t operator()(Monom m) const // hash function
935 {
936 (void) m;
937 return 0;
938 }
939
940 bool operator() (Entry a, Entry b) const
941 {
942 // TODO: Need to be clear which one wants!
943 //return mMonoid.compare(a.first, b.first) == GT;
944 return mMonoid.compare(a.first, b.first) == LT;
945 }
946
947private:
949};
950
967{
968public:
969 using Entry = std::pair<Monom, ring_elem>;
970 using Container = std::vector<Entry, StatsAllocator<Entry>>;
971
973 : mRing(F),
974 mEntryConfig(F.monoid()),
976 mLeadTermSet(false),
977 mLeadTerm(Monom(), F.coefficientRing()->zero())
978 {
979 }
980
982
983 void clear() override {
984 // clear the heap. The free algebra is kept the same
985 // but all other aspects are reset. The MonomialSpace
986 // has all its data freed to the arena, but is available for
987 // use without any new allocations for the next computation.
988 mLeadTermSet = false;
989 while (!mQueue.empty())
990 mQueue.pop();
991 mMonomialSpace.deallocateAll();
992 }
993
994 // prevent copy and assignment constructors
995 // allow move constructors, I guess?
998
1000 {
1001 auto rg = mMonomialSpace.allocateArray<int>(entry.first.size());
1002 std::copy(entry.first.begin(), entry.first.end(), rg.first);
1003 mQueue.push(Entry(Monom(rg.first), entry.second));
1004 return *this;
1005 }
1006
1008 {
1009 if (mLeadTermSet)
1010 {
1011 mQueue.push(mLeadTerm);
1012 mLeadTermSet = false;
1013 }
1014 for (auto i = poly.cbegin(); i != poly.cend(); ++i)
1015 addEntry(Entry(i.monom(),i.coeff()));
1016 return *this;
1017 }
1018
1020 Word left,
1021 Word right,
1022 const Poly& poly) override
1023 {
1024
1025 Poly f;
1026 mRing.mult_by_term_left_and_right(f, poly, coeff, left, right);
1027 addPolynomial(f);
1028 return *this;
1029 }
1030
1031 bool isZero() override
1032 {
1033 if (mLeadTermSet) return false;
1034 if (mQueue.empty()) return true;
1035 Entry lt = mQueue.top();
1036 mQueue.pop();
1037 while (not mQueue.empty())
1038 {
1039 Entry e = mQueue.top();
1040 if (mRing.monoid().compare(e.first, lt.first) == EQ)
1041 {
1042 lt.second = mRing.coefficientRing()->add(lt.second, e.second);
1043 mQueue.pop();
1044 }
1045 else
1046 {
1047 if (not mRing.coefficientRing()->is_zero(lt.second))
1048 {
1049 mLeadTermSet = true;
1050 mLeadTerm = lt;
1051 return false;
1052 }
1053 else
1054 {
1055 lt = mQueue.top();
1056 mQueue.pop();
1057 }
1058 }
1059 }
1060 if (not mRing.coefficientRing()->is_zero(lt.second))
1061 {
1062 mLeadTermSet = true;
1063 mLeadTerm = lt;
1064 return false;
1065 }
1066 return true;
1067 }
1068
1069 std::pair<Monom, ring_elem> viewLeadTerm() override
1070 {
1071 if (isZero())
1072 {
1073 std::cout << "viewLeadTerm called without checking if polynomial is zero" << std::endl;
1074 assert(false);
1075 }
1076 assert(mLeadTermSet);
1077 return mLeadTerm;
1078 }
1079
1080 void removeLeadTerm() override
1081 {
1082 if (isZero()) return;
1083 assert(mLeadTermSet); // should only be called if mLeadTermSet is true.
1084 if (mLeadTermSet)
1085 mLeadTermSet = false;
1086 }
1087
1088 Poly* value() override
1089 {
1090 Poly* f = new Poly;
1091 if (mLeadTermSet)
1092 mQueue.push(mLeadTerm);
1093 mLeadTermSet = false;
1094 while (not isZero())
1095 {
1096 auto tm = viewLeadTerm();
1097 mRing.add_to_end(*f, tm.second, tm.first);
1099 }
1100 addPolynomial(*f);
1101 return f;
1102 }
1103
1104 size_t getMemoryUsedInBytes() override
1105 {
1106 return (mQueue.size()*sizeof(Entry)) + mMonomialSpace.getMemoryUsedInBytes();
1107 }
1108
1109 std::string getName() const override { return "Priority queue heap."; }
1110
1111private:
1114 std::priority_queue<Entry,Container,EntryConfig> mQueue;
1116 bool mLeadTermSet; // true means mLeadTerm is set, to a non-zero value.
1118};
1119
1120
1121
1122
1124{
1125 // The first 3 bits of strategy encode which heap type to use.
1126 switch (strategy & 7) {
1127 case 0: return HeapType::Map; // good one
1128 case 1: return HeapType::PriorityQueue; // good one
1129 case 2: return HeapType::Trivial;
1130 case 3: return HeapType::NaiveDedupGeobucket;
1131 case 4: return HeapType::NaiveGeobucket;
1132 case 5: return HeapType::NaiveTourTree;
1133 case 6: return HeapType::NaiveHeap;
1134 default: return HeapType::Map;
1135 }
1136}
1137
1138std::string getHeapName(HeapType type)
1139{
1140 switch (type) {
1141 case HeapType::Map:
1142 return "Map";
1144 return "PriorityQueue";
1145 case HeapType::Trivial:
1146 return "Trivial";
1148 return "NaiveDedupGeobucket";
1150 return "NaiveGeobucket";
1152 return "NaiveTourTree";
1154 return "NaiveHeap";
1155 default: return "Map"; // see above.
1156 // case HeapType::HashedGeobucket:
1157 // return "HashedGeobucket";
1158 };
1159}
1160
1161std::unique_ptr<PolynomialHeap>
1163{
1164 switch (type) {
1165 // case HeapType::HashedGeobucket:
1166 // return std::make_unique<HashedPolynomialHeap<mathic::Geobucket>>(F);
1167 case HeapType::Map:
1168 return std::make_unique<MapPolynomialHeap>(F);
1170 return std::make_unique<PriorityQueuePolynomialHeap>(F);
1171 case HeapType::Trivial:
1172 return std::make_unique<TrivialPolynomialHeap>(F);
1174 return std::make_unique<NaiveDedupPolynomialHeap<mathic::Geobucket>>(F);
1176 return std::make_unique<NaivePolynomialHeap<mathic::Geobucket>>(F);
1178 return std::make_unique<NaivePolynomialHeap<mathic::TourTree>>(F);
1180 return std::make_unique<NaivePolynomialHeap<mathic::Heap>>(F);
1181 };
1182 return nullptr;
1183}
1184
1186{
1187 std::cout << "trying out mathic code!" << std::endl;
1188
1189 auto Q = makeQueue();
1190 Q->push(3);
1191 Q->push(7);
1192 Q->push(2);
1193 Q->push(42);
1194 Q->push(7);
1195 while (not Q->empty())
1196 {
1197 int a = Q->pop();
1198 std::cout << "popped: " << a << std::endl;
1199 }
1200
1201
1202 std::cout << "trying out mathic code, part 2!" << std::endl;
1203
1204 auto Q1 = makeQueue1();
1205 Q1->push(3);
1206 Q1->push(7);
1207 Q1->push(2);
1208 Q1->push(42);
1209 Q1->push(7);
1210 while (not Q1->empty())
1211 {
1212 int a = Q1->pop();
1213 std::cout << "popped: " << a << std::endl;
1214 }
1215}
1216
1217// Local Variables:
1218// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1219// indent-tabs-mode: nil
1220// End:
Free associative algebra k<x_1,...,x_n> over an arbitrary coefficient ring.
FreeMonoid — monoid of length-prefixed non-commutative words with weight-vector prefix.
Bump-pointer arena allocator for transient inner-loop allocations.
NCGroebner — Buchberger-style two-sided Gröbner basis driver over a FreeAlgebra.
std::unique_ptr< PolynomialHeap > makePolynomialHeap(HeapType type, const FreeAlgebra &F)
std::string getHeapName(HeapType type)
std::unique_ptr< mathic::Geobucket< OurQueueConfiguration > > makeQueue()
void tryOutMathicCode()
HeapType getHeapType(int strategy)
std::unique_ptr< mathic::Geobucket< OurQueueConfiguration1 > > makeQueue1()
HeapType
@ NaiveDedupGeobucket
PolynomialHeap abstract interface — batched-subtraction heap for non-commutative reduction.
Polynomial< CoefficientRingType > Poly
Word and WordWithData — non-owning views over the flat-int encoding of a non-commutative word.
const FreeMonoid & mMonoid
size_t operator()(Monom m) const
std::pair< Monom, ring_elem > Entry
EntryConfig(const FreeMonoid &M)
Comparator (and trivial hash) functor wired into the std::priority_queue inside PriorityQueuePolynomi...
Free associative algebra over a coefficient ring: the non-commutative analogue of PolynomialRing.
The free non-commutative monoid on a set of named variables, with monomial ordering and degree / weig...
MemoryBlock mMonomialSpace
MapPolynomialHeap operator=(const MapPolynomialHeap &)=delete
std::pair< Monom, ring_elem > Entry
Poly * value() override
void addTerm(Entry tm)
std::string getName() const override
bool isZero() override
std::map< Monom, ring_elem, MonomEq, gc_allocator< ConstEntry > > mMap
virtual ~MapPolynomialHeap()
void clear() override
MapPolynomialHeap & addPolynomial(ring_elem coeff, Word left, Word right, const Poly &poly) override
void removeLeadTerm() override
size_t getMemoryUsedInBytes() override
Entry viewLeadTerm() override
MapPolynomialHeap & addPolynomial(const Poly &poly) override
std::pair< const Monom, ring_elem > ConstEntry
MapPolynomialHeap(const MapPolynomialHeap &)=delete
MapPolynomialHeap(const FreeAlgebra &F)
Thin RAII wrapper around memtailor::Arena providing bump-pointer array allocation with optional mutex...
Strict comparator on Monoms under a FreeMonoid order: returns true exactly when the first monomial is...
size_t getMemoryUsedInBytes() override
Queue< NaiveDedupQueueConfiguration > mQueue
void removeLeadTerm() override
NaiveDedupPolynomialHeap operator=(const NaiveDedupPolynomialHeap &)=delete
NaiveDedupPolynomialHeap(const FreeAlgebra &F)
std::string getName() const override
NaiveDedupPolynomialHeap & addPolynomial(const Poly &poly) override
NaiveDedupPolynomialHeap & addPolynomial(ring_elem coeff, Word left, Word right, const Poly &poly) override
Poly * value() override
NaiveDedupQueueConfiguration::Entry Entry
NaiveDedupPolynomialHeap(const NaiveDedupPolynomialHeap &)=delete
std::pair< Monom, ring_elem > viewLeadTerm() override
static const mathic::GeobucketBucketStorage bucketStorage
CompareResult compare(const Entry &a, const Entry &b) const
bool cmpEqual(CompareResult a) const
static const bool minBucketBinarySearch
NaiveDedupQueueConfiguration(const FreeAlgebra &F)
bool cmpLessThan(CompareResult a) const
std::pair< Monom, ring_elem > Entry
const FreeAlgebra & mRing
Entry deduplicate(Entry a, Entry b) const
static const size_t insertFactor
static const bool supportDeduplication
Variant of NaiveQueueConfiguration with deduplication enabled: deduplicate(a, b) sums the coefficient...
NaivePolynomialHeap & addPolynomial(ring_elem coeff, Word left, Word right, const Poly &poly) override
bool isZero() override
NaiveQueueConfiguration::Entry Entry
virtual ~NaivePolynomialHeap()
Queue< NaiveQueueConfiguration > mQueue
void clear() override
std::pair< Monom, ring_elem > mLeadTerm
NaivePolynomialHeap & addPolynomial(const Poly &poly) override
MemoryBlock mMonomialSpace
NaivePolynomialHeap(const NaivePolynomialHeap &)=delete
Poly * value() override
size_t getMemoryUsedInBytes() override
std::pair< Monom, ring_elem > viewLeadTerm() override
void removeLeadTerm() override
std::string getName() const override
NaivePolynomialHeap(const FreeAlgebra &F)
NaivePolynomialHeap operator=(const NaivePolynomialHeap &)=delete
bool cmpEqual(CompareResult a) const
static const mathic::GeobucketBucketStorage bucketStorage
CompareResult compare(const Entry &a, const Entry &b) const
static const bool supportDeduplication
static const bool premerge
static const bool minBucketBinarySearch
Entry deduplicate(Entry a, Entry b) const
static const size_t insertFactor
const FreeAlgebra & mRing
static const bool trackFront
static const bool fastIndex
bool cmpLessThan(CompareResult a) const
static const bool collectMax
NaiveQueueConfiguration(const FreeAlgebra &F)
std::pair< Monom, ring_elem > Entry
mathic::Geobucket configuration whose Entry is a (Monom, ring_elem) pair compared by the FreeMonoid o...
CompareResult compare(const Entry &a, const Entry &b) const
bool cmpEqual(CompareResult a) const
static const bool trackFront
static const bool collectMax
static const bool minBucketBinarySearch
Entry deduplicate(Entry a, Entry b) const
bool cmpLessThan(CompareResult a) const
static const bool supportDeduplication
static const mathic::GeobucketBucketStorage bucketStorage
static const bool premerge
static const size_t insertFactor
Variant of OurQueueConfiguration with deduplication enabled, used by makeQueue1().
bool cmpLessThan(CompareResult a) const
static const bool premerge
const size_t minBucketSize
Entry deduplicate(Entry a, Entry b) const
static const size_t insertFactor
bool cmpEqual(CompareResult a) const
static const bool collectMax
static const bool supportDeduplication
static const mathic::GeobucketBucketStorage bucketStorage
CompareResult compare(const Entry &a, const Entry &b) const
static const bool minBucketBinarySearch
static const bool trackFront
Experimental mathic::Geobucket configuration whose Entry is an int — a placeholder used by makeQueue(...
virtual void removeLeadTerm()=0
virtual bool isZero()=0
virtual std::pair< Monom, ring_elem > viewLeadTerm()=0
virtual Poly * value()=0
virtual size_t getMemoryUsedInBytes()=0
virtual std::string getName() const =0
virtual PolynomialHeap & addPolynomial(const Poly &poly)=0
Abstract interface for accumulating a polynomial as a sum of (coeff, left * poly * right) contributio...
PriorityQueuePolynomialHeap & addPolynomial(ring_elem coeff, Word left, Word right, const Poly &poly) override
PriorityQueuePolynomialHeap & addPolynomial(const Poly &poly) override
std::pair< Monom, ring_elem > viewLeadTerm() override
std::priority_queue< Entry, Container, EntryConfig > mQueue
PriorityQueuePolynomialHeap operator=(const PriorityQueuePolynomialHeap &)=delete
size_t getMemoryUsedInBytes() override
PriorityQueuePolynomialHeap(const PriorityQueuePolynomialHeap &)=delete
PriorityQueuePolynomialHeap & addEntry(const Entry &entry)
std::string getName() const override
std::pair< Monom, ring_elem > Entry
std::vector< Entry, StatsAllocator< Entry > > Container
PriorityQueuePolynomialHeap(const FreeAlgebra &F)
Poly * value() override
Poly::const_iterator mIter
TrivialPolynomialHeap(const FreeAlgebra &F)
std::string getName() const override
TrivialPolynomialHeap operator=(const TrivialPolynomialHeap &)=delete
TrivialPolynomialHeap & addPolynomial(ring_elem coeff, Word left, Word right, const Poly &poly) override
TrivialPolynomialHeap(const TrivialPolynomialHeap &)=delete
void clear() override
void removeLeadTerm() override
size_t getMemoryUsedInBytes() override
virtual ~TrivialPolynomialHeap()
std::pair< Monom, ring_elem > viewLeadTerm() override
bool isZero() override
PolynomialHeap & addPolynomial(const Poly &poly) override
Non-owning view of a non-commutative word: [begin, end) of int variable indices.
Definition Word.hpp:56
std::list< brMonomial > monomials
#define monomial
Definition gb-toric.cpp:11
static int compare(const vecterm *t, const vecterm *s)
Definition geovec.hpp:112
int zero
void * pointers[10]
Definition m2-mem.cpp:39
VALGRIND_MAKE_MEM_DEFINED & result(result)
AllocLogger / StatsAllocator — single-threaded debug/benchmark instrumentation.
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition mpreal.h:3244
Ring — the legacy abstract base class for every coefficient and polynomial ring.
Non-owning view onto a [length, degree, v1, v2, ..., vn] packed monomial in some externally managed b...
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.