Macaulay2 Engine
Loading...
Searching...
No Matches
f4-spairs.cpp
Go to the documentation of this file.
1// Copyright 2005-2021 Michael E. Stillman
2
3#include "f4/f4-spairs.hpp"
4
5#include "mem.hpp" // for stash
6#include "style.hpp" // for INTSIZE
7
8#include <gc/gc_allocator.h> // for gc_allocator
9#include <stdint.h> // for int32_t
10#include <stdio.h> // for fprintf, stderr, size_t
11#include <algorithm> // for stable_sort
12#include <vector> // for vector, vector<>::iterator
13
14#if defined(WITH_TBB)
15F4SPairSet::F4SPairSet(const MonomialInfo *M0, const gb_array &gb0, mtbb::task_arena& scheduler)
16#else
18#endif
19 : M(M0),
20 gb(gb0),
25#if defined(WITH_TBB)
26 , mScheduler(scheduler)
27#endif
28{
29 max_varpower_size = 2 * M->n_vars() + 1;
30
31 //spair *used_to_determine_size = nullptr;
32 //mSPairSizeInBytes = sizeofspair(used_to_determine_size, M->max_monomial_size());
33}
34
36{
37 // Deleting the stash deletes all memory used here
38 // PS, VP are deleted automatically.
39 M = nullptr;
40}
41
43{
44 int j = p->j;
45 int deg = p->deg1 + gb[me]->deg;
46 // int me_component = M->get_component(gb[me]->f.monoms);
47
48 spair result {SPairType::SPair, deg, me, j, nullptr};
49
50 auto allocRange = mSPairLCMs.allocateArray<monomial_word>(M->max_monomial_size());
51 result.lcm = allocRange.first;
52
53 M->from_varpower_monomial(p->quot, 0, result.lcm);
54 M->unchecked_mult(result.lcm, gb[me]->f.monoms, result.lcm);
55
56 mSPairLCMs.shrinkLastAllocate(allocRange.first,
57 allocRange.second,
58 allocRange.first + M->monomial_size(result.lcm));
59
60 auto sPairIndex = mSPairs.size();
61 mSPairs.push_back(result);
62 mSPairQueue.push(sPairIndex);
63
64}
65
68{
69 spair result {SPairType::Generator,deg,col,-1,nullptr};
70
71 auto allocRange = mSPairLCMs.allocateArray<monomial_word>(M->monomial_size(lcm));
72 result.lcm = allocRange.first;
73
74 M->copy(lcm, result.lcm);
75
76 auto sPairIndex = mSPairs.size();
77 mSPairs.push_back(result);
78 mSPairQueue.push(sPairIndex);
79}
80
82{
83 // if (p->type != SPairType::SPair && p->type != SPairType::Ring) return false;
84 if (p->type != SPairType::SPair) return false;
85 if (M->get_component(p->lcm) != M->get_component(m->f.monoms)) return false;
86 return M->unnecessary(
87 m->f.monoms, gb[p->i]->f.monoms, gb[p->j]->f.monoms, p->lcm);
88}
89
91{
92 // Loop through every spair, determine if it can be jettisoned
93 // and do so. Return the number removed.
94
95 // MES: Check the ones in this_set? Probably not needed...
96
97 if (gb.size() == 0) return 0;
98
99 gbelem *m = gb[gb.size() - 1];
100 //long nremoved = 0;
101
102#if defined(WITH_TBB)
103 mScheduler.execute([&] {
104 mtbb::parallel_for(mtbb::blocked_range<int>{0, INTSIZE(mSPairs)},
105 [&](const mtbb::blocked_range<int>& r)
106 {
107 for (auto i = r.begin(); i != r.end(); ++i)
108 {
109 if (pair_not_needed(&mSPairs[i],m))
110 {
111 mSPairs[i].type = SPairType::Retired;
112 }
113 }
114 });
115 });
116#else
117 for (auto& p : mSPairs)
118 {
119 if (pair_not_needed(&p,m))
120 {
121 p.type = SPairType::Retired;
122 //++nremoved;
123 }
124 }
125#endif
126 return 0;
127 //return nremoved;
128
129}
130
131std::pair<bool,int> F4SPairSet::setThisDegree()
132{
133 if (mSPairQueue.empty()) return {false, 0};
134
135 auto queueTop = mSPairQueue.top();
136 while (mSPairs[queueTop].type == SPairType::Retired)
137 {
138 mSPairQueue.pop();
139 if (mSPairQueue.empty()) return {false, 0};
140 queueTop = mSPairQueue.top();
141 }
142
143 mThisDegree = mSPairs[queueTop].deg;
144 return {true,mThisDegree};
145
146}
147
148//spair *F4SPairSet::get_next_pair()
149std::pair<bool,spair> F4SPairSet::get_next_pair()
150// get the next pair in this degree (the one 'prepare_next_degree' set up')
151{
152 if (mSPairQueue.empty()) return {false, {}};
153 auto result = mSPairQueue.top();
154 if (mSPairs[result].deg != mThisDegree) return {false, {} };
155 mSPairQueue.pop();
156 return {true,mSPairs[result]};
157}
158
160{
161 while (not mSPairQueue.empty())
162 {
163 auto result = mSPairQueue.top();
164 if (mSPairs[result].deg != mThisDegree) return;
166 mSPairQueue.pop();
167 }
168}
169
170int F4SPairSet::find_new_pairs(bool remove_disjoints)
171// returns the number of new pairs found
172{
173 // this is used for "late" removal of spairs -- will need to be reworked
174 // in the new priority_queue approach
176 int len = construct_pairs(remove_disjoints);
177 return len;
178}
179
181// A debugging routine which displays an spair
182{
183 if (p->type == SPairType::SPair)
184 {
185 fprintf(stderr, "[%d %d deg %d lcm ", p->i, p->j, p->deg);
186 M->show(p->lcm);
187 fprintf(stderr, "\n");
188 }
189 else
190 {
191 fprintf(stderr, "unknown type\n");
192 }
193}
194
196// A debugging routine which displays the spairs in the set
197{
198 /*
199 fprintf(stderr, "spair set\n");
200 for (spair *p = heap; p != nullptr; p = p->next)
201 {
202 fprintf(stderr, " ");
203 display_spair(p);
204 }
205 fprintf(stderr, "current set\n");
206 for (spair *p = this_set; p != nullptr; p = p->next)
207 {
208 fprintf(stderr, " ");
209 display_spair(p);
210 }
211 */
212}
213
215// Construction of new spairs //
217
219{
220 // Steps:
221 // a. allocate the space for the pre_spair and the varpower monomial
222 // b. compute the quotient and the degree
223 pre_spair *result = PS.allocate();
224 result->quot = VP.reserve(max_varpower_size);
225 result->j = j;
226 result->type = SPairType::SPair;;
227 M->quotient_as_vp(gb[j]->f.monoms,
228 gb[gb.size() - 1]->f.monoms,
229 result->quot,
230 result->deg1,
231 result->are_disjoint);
232 int len = static_cast<int>(varpower_monomials::length(result->quot));
233 VP.intern(len);
234 return result;
235}
236
237void insert_pre_spair(std::vector<std::vector<pre_spair *>> & bins, pre_spair *p)
238{
239 int d = p->deg1;
240 if (d >= bins.size()) bins.resize(d + 1);
241 bins[d].push_back(p);
242}
243
244long PreSPairSorter::ncmps = 0;
245
246int F4SPairSet::construct_pairs(bool remove_disjoints)
247{
248 if (gb.size() == 0) return 0;
249
250 VP.reset();
251 PS.reset();
252 gbelem *me = gb[gb.size() - 1];
253 int me_component = static_cast<int>(M->get_component(me->f.monoms));
254
255 std::vector<std::vector<pre_spair *>> bins;
256
257 mtbb::tick_count t0 {mtbb::tick_count::now()};
258
259 // Loop through each element of gb, and create the pre_spair
260 for (int i = 0; i < gb.size() - 1; i++)
261 {
262 if (gb[i]->minlevel == ELEM_NON_MIN_GB) continue;
263 if (me_component != M->get_component(gb[i]->f.monoms)) continue;
265 insert_pre_spair(bins, p);
266 }
267
268 mtbb::tick_count t1 {mtbb::tick_count::now()};
269 mPrePairsSeconds += (t1-t0).seconds();
270
272 // Now minimalize the set //
274 MonomialLookupTable *montab = new MonomialLookupTable(M->n_vars());
275
277 int n_new_pairs = 0;
278 for (int i = 0; i < bins.size(); i++)
279 {
280 if (bins[i].size() == 0) continue;
281 // First sort the monomials of this degree
282
283 std::stable_sort(bins[i].begin(), bins[i].end(), C);
284
285 // Loop through each degree and potentially insert...
286 auto first = bins[i].begin();
287 auto next = first;
288 auto end = bins[i].end();
289 for (; first != end; first = next)
290 {
291 next = first + 1;
292 pre_spair *chosen = *first;
293 while (next != end)
294 {
295 pre_spair *p = *next;
296 if (!varpower_monomials::is_equal(chosen->quot, p->quot)) break;
297 next++;
298 }
299 /* At this point: [first,next) is the range of equal monomials */
300
301 int32_t junk;
302 bool inideal = montab->find_one_divisor_vp(0, chosen->quot, junk);
303 if (!inideal)
304 {
305 // MES: Maybe choose another of the equal monomials...
306 montab->insert_minimal_vp(0, chosen->quot, 0);
307 // The following condition is that gcd is not one
308 if (!remove_disjoints || !chosen->are_disjoint)
309 {
310 insert_spair(chosen, INTSIZE(gb) - 1);
311 n_new_pairs++;
312 }
313 }
314 }
315 }
316 delete montab;
317 mtbb::tick_count t2 {mtbb::tick_count::now()};
318 mMinimizePairsSeconds += (t2-t1).seconds();
319
320 return n_new_pairs;
321}
322
323#if 0
324// testing mathic and mathicgb routines...
325class TestPairQueueConfiguration
326{
327private:
328 // What should be here?
329
330public:
331 TestPairQueueConfiguration(const gb_array& gb,
332 XXX
333 );
334 using PairData = MonomialInfo::OrderedMonomial;
335 void computePairData(
336 size_t col,
337 size_t row,
338 PairData & m, // allocated space?
339 ) const;
340
341 using CompareResult = bool;
342 bool compare(
343 size_t colA,
344 size_t rowA,
345 MonomialInfo::ConstOrderedMonomial a,
346 size_t colB,
347 size_t rowB,
348 MonomialInfo::ConstOrderedMonomial b) const
349 {
350 // What to change this test code to?
351 const auto cmp = orderMonoid().compare(*a, *b);
352 if (cmp == GT)
353 return true;
354 if (cmp == LT)
355 return false;
356
357 const bool aRetired = mBasis.retired(rowA) || mBasis.retired(colA);
358 const bool bRetired = mBasis.retired(rowB) || mBasis.retired(colB);
359 if (aRetired || bRetired)
360 return !bRetired;
361
362 if (mPreferSparseSPairs) {
363 const auto termCountA =
364 mBasis.basisElement(colA).termCount() +
365 mBasis.basisElement(rowA).termCount();
366 const auto termCountB =
367 mBasis.basisElement(colB).termCount() +
368 mBasis.basisElement(rowB).termCount();
369 if (termCountA > termCountB)
370 return true;
371 if (termCountA < termCountB)
372 return false;
373 }
374 return colA + rowA > colB + rowB;
375 }
376
377 bool cmpLessThan(bool v) const {return v;}
378};
379
380class TestSPairs
381{
382private:
383 mathic::PairQueue<TestPairQueueConfiguration> mPairQueue;
384
385public:
386 TestSPairs(gb_poly& currentGroebnerBasis);
387
388 ~TestSPairs() {} // anything here?
389
390};
391#endif
392
393// Local Variables:
394// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
395// indent-tabs-mode: nil
396// End:
static const Exponent length(ConstExponents m)
static bool is_equal(ConstExponents a, ConstExponents b)
void insert_minimal_vp(long comp, const_varpower_monomial m, Key k)
bool find_one_divisor_vp(long comp, const_varpower_monomial m, Key &result_k) const
int construct_pairs(bool remove_disjoints)
MemoryBlock mSPairLCMs
long mThisDegree
std::pair< bool, spair > get_next_pair()
std::pair< bool, int > setThisDegree()
int remove_unneeded_pairs()
Definition f4-spairs.cpp:90
void delete_spair(spair *p)
Definition f4-spairs.cpp:66
void insert_generator(int deg, packed_monomial lcm, int column)
Definition f4-spairs.cpp:67
std::vector< spair > mSPairs
int max_varpower_size
void display()
long nsaved_unneeded
void discardSPairsInCurrentDegree()
SPairCompare mSPairCompare
const gb_array & gb
double mPrePairsSeconds
void display_spair(spair *p)
void insert_spair(pre_spair *p, int me)
Definition f4-spairs.cpp:42
const MonomialInfo * M
F4SPairSet(const MonomialInfo *MI0, const gb_array &gb0)
Definition f4-spairs.cpp:17
F4MemoryBlock< varpower_word > VP
bool pair_not_needed(spair *p, gbelem *m)
Definition f4-spairs.cpp:81
double mMinimizePairsSeconds
F4MemoryBlock< pre_spair > PS
std::priority_queue< size_t, std::vector< size_t >, SPairCompare > mSPairQueue
int find_new_pairs(bool remove_disjoints)
pre_spair * create_pre_spair(int i)
Per-ring monomial layout / encoding helper used by F4GB.
Definition moninfo.hpp:108
static long ncmps
Definition f4-types.hpp:305
Comparator that orders pre_spair* pointers by the quot varpower monomial of each pre-S-pair.
Definition f4-types.hpp:300
void insert_pre_spair(std::vector< std::vector< pre_spair * > > &bins, pre_spair *p)
F4SPairSet — priority-queue + pruning logic for F4 S-pairs.
F4MonomialLookupTableT< int32_t > MonomialLookupTable
Definition f4-types.hpp:357
std::vector< gbelem * > gb_array
Definition f4-types.hpp:145
@ ELEM_NON_MIN_GB
Definition f4-types.hpp:77
void gb(IntermediateBasis &F, int n)
static unsigned long nsaved_unneeded
static int compare(const vecterm *t, const vecterm *s)
Definition geovec.hpp:112
int p
VALGRIND_MAKE_MEM_DEFINED & result(result)
stash and doubling_stash — legacy size-class allocator interfaces, now stubbed to plain GC allocation...
monomial_word * packed_monomial
Definition moninfo.hpp:78
long monomial_word
Definition moninfo.hpp:77
TermIterator< Nterm > begin(Nterm *ptr)
Definition ringelem.cpp:4
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
monomial_word * monoms
Definition f4-types.hpp:110
GBF4Polynomial f
Definition f4-types.hpp:139
bool are_disjoint
Definition f4-types.hpp:120
varpower_monomial quot
Definition f4-types.hpp:118
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39
#define INTSIZE(a)
Definition style.hpp:37
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
double seconds(DurationType time_diff)
Definition timing.hpp:59