Macaulay2 Engine
Loading...
Searching...
No Matches
res-f4.cpp
Go to the documentation of this file.
1// Copyright 2014-2016 Michael E. Stillman
2
6
7#include "ExponentVector.hpp"
8#include "monoid.hpp"
9#include "memtailor.h"
10#include "text-io.hpp"
11
12#include <iostream>
13#include <ctime>
14#include <algorithm>
15#include "timing.hpp"
16
17#if 0
18// This is test code which should be removed, or placed elsewhere!
19#include <thread>
20#include "../../system/supervisor.hpp"
21#include "../../system/supervisorinterface.h"
22static long val[2];
23static void* testFcn1(void* vint)
24{
25 long v = reinterpret_cast<long>(vint);
26 std::cout << "starting fcn1 with v = " << v << std::endl;
27 val[0] = 10;
28 return nullptr;
29}
30static void* testFcn2(void* vint)
31{
32 long v = reinterpret_cast<long>(vint);
33 std::cout << "starting fcn2 with v = " << v << std::endl;
34 val[1] = 20;
35 return nullptr;
36}
37void testTasks()
38{
39 val[0] = 666;
40 val[1] = 666;
41 ThreadTask* t1 = createThreadTask("task 1", testFcn1, reinterpret_cast<void*>(1L), 0, 0, 0);
42 ThreadTask* t2 = createThreadTask("task 1", testFcn2, reinterpret_cast<void*>(2L), 0, 0, 0);
43 pushTask(t1);
44 pushTask(t2);
45 waitOnTask(t2);
46 std::cout << val[0] << " " << val[1] << std::endl;
47}
48#endif
49
51 : mFrame(res),
52 mRing(res.ring()),
54 mHashTable(mSchreyerRes.get(), 10)
55{
56#if 0
57 std::cout << "hardware threads: " << std::thread::hardware_concurrency() << std::endl;
58 std::cout << "testing thread tasks" << std::endl;
59 testTasks();
60 std::cout << " done testing thread tasks" << std::endl;
61#endif
62}
63
65{
66 // Nothing to free here.
67}
68
69void F4Res::resetMatrix(int lev, int degree)
70{
71 mThisLevel = lev;
72 mThisDegree = degree;
74}
75
77{
78 mThisLevel = -1;
79 mThisDegree = -1;
81
82 auto timeA = timer();
83 mHashTable.reset();
84 auto timeB = timer();
85 mFrame.timeResetHashTable += seconds(timeB - timeA);
86
87 for (auto& f : mReducers)
88 {
89 mRing.vectorArithmetic().deallocateElementArray(f.mCoeffs);
90 }
91
92 for (auto& f : mSPairs)
93 {
94 mRing.vectorArithmetic().deallocateElementArray(f.mCoeffs);
95 }
96
97 mReducers.clear();
98 mSPairs.clear();
99 mSPairComponents.clear();
100 mColumns.clear();
101
102 mMonomSpace2.freeAllAllocs();
103}
104
106// m: monomial at level mThisLevel-1
107// result: monomial at level mThisLevel, IF true is returned
108// returns true if 'm' == inG(result), for some (unique) 'result'.
110{
111 // get component of m
112 // find the range of monomials to check
113 // for each of these, check divisibility in turn
114 // if one works, then return true, and set result.
115 long comp =
116 monoid().get_component(m); // component is an index into level mLevel-2
117 auto& elem = mFrame.level(mThisLevel - 2)[comp];
118 auto& lev = mFrame.level(mThisLevel - 1);
119 for (auto j = elem.mBegin; j < elem.mEnd; ++j)
120 {
121 // Check divisibility of m by this element
122 res_packed_monomial pj = lev[j].mMonom;
123 if (monoid().divide(m, pj, result)) // this sets the component to be 0
124 {
125 monoid().set_component(j, result); // this sets component correctly
126 return true;
127 }
128 }
129 return false;
130}
131
132// A monomial at level lev has the following form:
133// m[-1] index of a divisor for this monomial, -1 if no divisor exists
134// this is only used for monomials being placed into the hash table...
135// m[0] is a hash value
136// m[1] is the component, an index into the lev-1 part of the frame.
137// m[2] is the degree,
138// m[3..3+#vars-1] is the monomial.
139// Is m[-1] always present
140
141// processMonomialProduct
142// m is a monomial, component is ignored (it determined the possible n's
143// being used here)
144// n is a monomial at level 'mThisLevel-1'
145// compute their product, and return the column index of this product
146// or -1, if the monomial is not needed.
147// additionally: the product monomial is inserted into the hash table
148// and column array (if it is not already there).
149// caveats: this function is only to be used during construction
150// of the coeff matrices. It uses mThisLevel.
151//
152// If the ring has skew commuting variables, then result_sign_if_skew is set to
153// 0, 1, or -1.
156 int& result_sign_if_skew)
157{
158 result_sign_if_skew = 1;
159 auto x = monoid().get_component(n);
160 auto& p = mFrame.level(mThisLevel - 2)[x];
161 if (p.mBegin == p.mEnd) return -1;
162
163 int* thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size());
164 thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as
165 monoid().unchecked_mult(m, n, thisMonom);
166 monoid().set_component(x, thisMonom);
167
168 if (ring().isSkewCommutative())
169 {
170 result_sign_if_skew = monoid().skew_mult_sign(ring().skewInfo(), m, n);
171 if (result_sign_if_skew == 0)
172 {
173 mMonomSpace2.popLastAlloc(thisMonom-1); // we did not need this monomial!
174 return -1;
175 }
176 }
177 return processCurrentMonomial(thisMonom);
178}
179
180// new_m is a monomial that we have just created. There are several
181// things that can happen:
182// (1) new_m is already in the hash table (as is).
183// i.e. we have already processed this monomial.
184// in this case new_m[-1] is the index of the divisor for this monomial
185// (possibly -1).
186// (2) new_m is a newly seen monomial in this degree.
187// insert it into the hash table as a seen monomial
188// we set the divisor for new_m: either -1 or some index
189// If there is no divisor, return -1.
190// If there is: create a row, and push onto the mReducers list.
191// (2A)
193{
194 res_packed_monomial new_m; // a pointer to a monomial we are visiting
195 if (mHashTable.find_or_insert(thisMonom, new_m))
196 {
197 // we did not need the monomial. So pop it.
198 mMonomSpace2.popLastAlloc(thisMonom-1);
199 return static_cast<ComponentIndex>(
200 new_m[-1]); // monom exists, don't save monomial space
201 }
202
203 // At this point thisMonom has been inserted. We keep it.
204
205 thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size());
206 thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as
207
208 bool has_divisor = findDivisor(new_m, thisMonom);
209 if (!has_divisor)
210 {
211 mMonomSpace2.popLastAlloc(thisMonom-1);
212 new_m[-1] = -1; // no divisor exists
213 return -1;
214 }
215
216 ComponentIndex thiscol = static_cast<ComponentIndex>(mColumns.size());
217 new_m[-1] = thiscol; // this is a HACK: where we keep the divisor
218 mColumns.push_back(new_m);
219
220 Row row;
221 row.mLeadTerm = thisMonom;
222 mReducers.push_back(row);
223
224 return thiscol;
225}
227{
228 // std::cout << "loadRow: " << std::endl;
229
231
232 // monoid().showAlpha(r.mLeadTerm);
233 // std::cout << std::endl;
234 int skew_sign; // will be set to 1, unless ring().isSkewCommutative() is
235 // true, then it can be -1,0,1.
236 // however, if it is 0, then "val" below will also be -1.
237 long comp = monoid().get_component(r.mLeadTerm);
238 auto& thiselement = mFrame.level(mThisLevel - 1)[comp];
239 // std::cout << " comp=" << comp << " mDegree=" << thiselement.mDegree << "
240 // mThisDegree=" << mThisDegree << std::endl;
241 if (thiselement.mDegree == mThisDegree)
242 {
243 // We only need to add in the current monomial
244 // fprintf(stdout, "USING degree 0 monomial\n");
245 ComponentIndex val =
246 processMonomialProduct(r.mLeadTerm, thiselement.mMonom, skew_sign);
247 if (val < 0) fprintf(stderr, "ERROR: expected monomial to live\n");
248 r.mComponents.push_back(val);
249 if (skew_sign > 0)
250 mRing.vectorArithmetic().pushBackOne(r.mCoeffs);
251 else
252 {
253 // Only happens if we are in a skew commuting ring.
255 }
256 return;
257 }
258 auto& p = thiselement.mSyzygy;
259 auto end = ResPolynomialIterator(mRing, p, 1);
260 auto i = ResPolynomialIterator(mRing, p);
261 for (; i != end; ++i)
262 {
263 ComponentIndex val =
264 processMonomialProduct(r.mLeadTerm, i.monomial(), skew_sign);
265 // std::cout << " monom: " << val << " skewsign=" << skew_sign << "
266 // mColumns.size=" << mColumns.size() << std::endl;
267 if (val < 0) continue;
268 r.mComponents.push_back(val);
269 if (skew_sign > 0)
270 mRing.vectorArithmetic().pushBackElement(
271 r.mCoeffs, p.coeffs, i.coefficient_index());
272 else
273 {
274 // Only happens if we are in a skew commuting ring.
275 mRing.vectorArithmetic().pushBackNegatedElement(
276 r.mCoeffs, p.coeffs, i.coefficient_index());
277 }
278 }
279}
280
281static void applyPermutation(ComponentIndex* permutation,
282 std::vector<ComponentIndex>& entries)
283{
284 // TODO: permutation should be a std::vector too,
285 // and we should check the values of the permutation.
286 for (ComponentIndex i = 0; i < entries.size(); i++)
287 entries[i] = permutation[entries[i]];
288
289 // The next is just a consistency check, that maybe can be removed later.
290 for (ComponentIndex i = 1; i < entries.size(); i++)
291 {
292 if (entries[i] <= entries[i - 1])
293 {
294 fprintf(stderr, "Internal error: array out of order\n");
295 break;
296 }
297 }
298}
299
301{
302// Set up to sort the columns.
303// Result is an array 0..ncols-1, giving the new order.
304// Find the inverse of this permutation: place values into "ord" column fields.
305// Loop through every element of the matrix, changing its comp array.
306
307#if 0
308 std::cout << "-- rows --" << std::endl;
310 std::cout << "-- columns --" << std::endl;
312
313 std::cout << "reorderColumns" << std::endl;
314#endif
315 ComponentIndex ncols = static_cast<ComponentIndex>(mColumns.size());
316
317 ComponentIndex* ord = new ComponentIndex[ncols];
318
319 auto timeA = timer();
320 ResMonomialSorter sorter(ring().originalMonoid(), monoid(), frame().schreyerOrder(mThisLevel-2), mColumns);
321 auto column_order = sorter.sort();
322 auto timeB = timer();
323 double nsec_sort2 = seconds(timeB - timeA);
324 mFrame.timeSortMatrix += nsec_sort2;
325 auto ncompares = sorter.numComparisons();
326
327 if (M2_gbTrace >= 2)
328 std::cout << " #comparisons sorting " << ncols << " columns = " << ncompares << " ";
329
330 if (M2_gbTrace >= 1)
331 std::cout << " sort time: " << nsec_sort2 << std::endl;
332
333 timeA = timer();
335
336 for (ComponentIndex i = 0; i < ncols; i++)
337 {
338 ord[column_order[i]] = i;
339 }
340
341#if 0
342 std::cout << "column_order: ";
343 for (ComponentIndex i=0; i<ncols; i++) std::cout << " " << column_order[i];
344 std::cout << std::endl;
345 std::cout << "ord: ";
346 for (ComponentIndex i=0; i<ncols; i++) std::cout << " " << ord[i];
347 std::cout << std::endl;
348#endif
349 // Now move the columns into position
350 std::vector<res_packed_monomial> sortedColumnArray;
351 std::vector<Row> sortedRowArray;
352
353 sortedColumnArray.reserve(ncols);
354 sortedRowArray.reserve(ncols);
355
356 for (ComponentIndex i = 0; i < ncols; i++)
357 {
358 ComponentIndex newc = column_order[i];
359 sortedColumnArray.push_back(mColumns[newc]);
360 sortedRowArray.push_back(Row());
361 std::swap(sortedRowArray[i], mReducers[newc]);
362 }
363
364 std::swap(mColumns, sortedColumnArray);
365 std::swap(mReducers, sortedRowArray);
366
367#if 0
368 std::cout << "applying permutation to reducers" << std::endl;
369#endif
370
371 for (ComponentIndex i = 0; i < mReducers.size(); i++)
372 {
373#if 0
374 std::cout << "reducer " << i << " before:";
375 for (ComponentIndex j=0; j<mReducers[i].mComponents.size(); j++) std::cout << " " << mReducers[i].mComponents[j];
376 std::cout << std::endl;
377#endif
378 applyPermutation(ord, mReducers[i].mComponents);
379#if 0
380 std::cout << "reducer " << i << " after:";
381 for (ComponentIndex j=0; j<mReducers[i].mComponents.size(); j++) std::cout << " " << mReducers[i].mComponents[j];
382 std::cout << std::endl;
383#endif
384 }
385#if 0
386 std::cout << "applying permutation to spairs" << std::endl;
387#endif
388 for (ComponentIndex i = 0; i < mSPairs.size(); i++)
389 {
390#if 0
391 std::cout << "spair " << i << " before:";
392 for (ComponentIndex j=0; j<mSPairs[i].mComponents.size(); j++) std::cout << " " << mSPairs[i].mComponents[j];
393 std::cout << std::endl;
394#endif
395 applyPermutation(ord, mSPairs[i].mComponents);
396#if 0
397 std::cout << "spair " << i << " after:";
398 for (ComponentIndex j=0; j<mSPairs[i].mComponents.size(); j++) std::cout << " " << mSPairs[i].mComponents[j];
399 std::cout << std::endl;
400#endif
401 }
402
403 timeB = timer();
404 mFrame.timeReorderMatrix += seconds(timeB - timeA);
405 delete[] ord;
406}
407
409{
410 // std::cout << "entering makeMatrix()" << std::endl;
411 auto& myframe = mFrame.level(mThisLevel);
412 long r = 0;
413 long comp = 0;
414 for (auto it = myframe.begin(); it != myframe.end(); ++it)
415 {
416 if (it->mDegree == mThisDegree)
417 {
418 mSPairs.push_back(Row());
419 mSPairComponents.push_back(comp);
420 Row& row = mSPairs[r];
421 r++;
422 row.mLeadTerm = it->mMonom;
423 loadRow(row);
424 if (M2_gbTrace >= 4)
425 if (r % 5000 == 0)
426 std::cout << "makeMatrix sp: " << r
427 << " #rows = " << mColumns.size() << std::endl;
428 }
429 comp++;
430 }
431 // Now we process all monomials in the columns array
432 while (mNextReducerToProcess < mColumns.size())
433 {
434 // Warning: mReducers is being appended to during 'loadRow', and
435 // since we act on the Row directly, it might get moved on us!
436 // (actually, it did get moved, which prompted this fix)
437 Row thisrow;
439 loadRow(thisrow);
442 if (M2_gbTrace >= 4)
443 if (mNextReducerToProcess % 5000 == 0)
444 std::cout << "makeMatrix red: " << mNextReducerToProcess
445 << " #rows = " << mReducers.size() << std::endl;
446 }
447
449
450#if 0
453 std :: cout << "-- reducer matrix --" << std::endl;
456
457 std :: cout << "-- spair matrix --" << std::endl;
460#endif
461}
462
463//#define DEBUG_GAUSS
464
466 ElementArray& gauss_row,
467 bool onlyConstantMaps,
468 const std::vector<bool>& track)
469{
470 int i = index;
471
472#ifdef DEBUG_GAUSS
473 std::cout << "reducing row " << i << std::endl;
474#endif
475
476 // Reduce spair #i
477 // fill in dense row with this element.
478
480
481 Row& r = mSPairs[i]; // row to be reduced.
482 long comp = mSPairComponents[i];
483 result.appendMonicTerm(mFrame.level(mThisLevel)[comp].mMonom);
484
485 auto& syz = mFrame.level(mThisLevel)[comp].mSyzygy; // this is the element we will fill out
486
487 // Note: in the polynomial ring case, the row r is non-zero.
488 // BUT: for skew commuting variables, it can happen that r is zero
489 // (e.g. a.(acd<0>) = 0). In this case we have nothing to reduce.
490 if (!r.mComponents.empty())
491 {
492 ComponentIndex firstcol = r.mComponents[0];
493 ComponentIndex lastcol = static_cast<ComponentIndex>(mColumns.size() - 1); // maybe: r.mComponents[r.mComponents.size()-1];
494
495#ifdef DEBUG_GAUSS
496 std::cout << "about to fill from sparse " << i << std::endl;
497#endif
498
499 mRing.vectorArithmetic().fillDenseArray(gauss_row,
500 r.mCoeffs,
501 Range(&r.mComponents[0],
502 &r.mComponents[0] + static_cast<ComponentIndex>(r.mComponents.size())));
503
504 while (firstcol <= lastcol)
505 {
506#ifdef DEBUG_GAUSS
507 std::cout << "about to reduce with col " << firstcol << std::endl;
508 std::cout << "gauss_row: "
509 << (gauss_row.isNull() ? "null" : "not-null")
510 << std::endl;
511 std::cout << "mReducers[" << firstcol << "]: "
512 << (mReducers[firstcol].mCoeffs.isNull() ? "null"
513 : "not-null")
514 << std::endl;
515 std::cout << "result: " << (result.coefficientInserter().isNull()
516 ? "null"
517 : "not-null")
518 << std::endl;
519 std::cout << " dense: ";
520 mRing.vectorArithmetic().displayElementArray(std::cout, gauss_row)
521 << std::endl;
522 mRing.vectorArithmetic().displayElementArray(std::cout,
523 mReducers[firstcol].mCoeffs);
524 std::cout << std::endl;
525 mRing.vectorArithmetic().displayElementArray(std::cout,
526 result.coefficientInserter());
527 std::cout << std::endl;
528#endif
529
530 if (onlyConstantMaps and not track[firstcol])
531 {
532 mRing.vectorArithmetic().denseCancelFromSparse(gauss_row,
533 mReducers[firstcol].mCoeffs,
534 Range(mReducers[firstcol].mComponents.data(),
535 mReducers[firstcol].mComponents.data() +
536 mRing.vectorArithmetic().size(mReducers[firstcol].mCoeffs)));
537 }
538 else
539 {
540 mRing.vectorArithmetic().denseCancelFromSparse(gauss_row,
541 mReducers[firstcol].mCoeffs,
542 Range(mReducers[firstcol].mComponents.data(),
543 mReducers[firstcol].mComponents.data() +
544 mRing.vectorArithmetic().size(mReducers[firstcol].mCoeffs)),
545 result.coefficientInserter());
546
547#ifdef DEBUG_GAUSS
548 std::cout << " done with sparseCancel" << std::endl;
549 mRing.vectorArithmetic().displayElementArray(std::cout, gauss_row)
550 << std::endl;
551 mRing.vectorArithmetic().displayElementArray(std::cout,
552 mReducers[firstcol].mCoeffs)
553 << std::endl;
554 mRing.vectorArithmetic().displayElementArray(std::cout,
555 result.coefficientInserter())
556 << std::endl;
557 std::cout << " about to push back term" << std::endl;
558#endif
559
560 result.pushBackTerm(mReducers[firstcol].mLeadTerm);
561
562#ifdef DEBUG_GAUSS
563 std::cout << "done with col " << firstcol << std::endl;
564#endif
565 }
566 firstcol = mRing.vectorArithmetic().denseNextNonzero(gauss_row, firstcol + 1, lastcol);
567 }
568 }
569
570#ifdef DEBUG_GAUSS
571 std::cout << "about to set syz" << std::endl;
572#endif
573 result.setPoly(syz);
574#ifdef DEBUG_GAUSS
575 std::cout << "just set syz" << std::endl;
576#endif
577}
578
580{
581 bool onlyConstantMaps = false;
582 std::vector<bool> track(mReducers.size());
583
584 if (onlyConstantMaps) // and not exterior algebra?
585 {
586 for (auto i = 0; i < mReducers.size(); i++)
587 {
589 mReducers[i].mLeadTerm,
590 monoid().n_vars() - mThisLevel + 1,
591 monoid().n_vars() - 1);
592 }
593 }
594
595#if defined(WITH_TBB)
596 //std::cout << "about to do parallel gauss_reduce" << std::endl;
597 using threadLocalDense_t = mtbb::enumerable_thread_specific<ElementArray>;
598 // create a dense array for each thread
599 threadLocalDense_t threadLocalDense([&]() {
600 return mRing.vectorArithmetic().allocateElementArray(static_cast<ComponentIndex>(mColumns.size()));
601 });
602
603 // Reduce to zero every spair. Recording creates the
604 // corresponding syzygy, which is auto-reduced and correctly ordered.
605
606 // std::cout << "gauss_row: " << (gauss_row.isNull() ? "null" : "not-null")
607 // << std::endl;
608 // std::cout << "gauss_row size: " << mRing.vectorArithmetic().size(gauss_row) <<
609 // std::endl;
610
611 //size_t chunk_size = std::max(mSPairs.size() / (100*mFrame.getNumThreads()), (size_t) 1);
612 //mFrame.getScheduler().execute([this,&chunk_size,&onlyConstantMaps,&track,&threadLocalDense] {
613 mFrame.getScheduler().execute([this,&onlyConstantMaps,&track,&threadLocalDense] {
614 //mtbb::parallel_for(mtbb::blocked_range<int>{0,(int)mSPairs.size(),chunk_size},
615 mtbb::parallel_for(mtbb::blocked_range<int>{0,(int)mSPairs.size()},
616 [&](const mtbb::blocked_range<int>& r)
617 {
618 //std::cout << "gauss reduce, " << r.begin() << "..<" << r.end() << " total: " << mSPairs.size() << std::endl;
619 threadLocalDense_t::reference my_dense = threadLocalDense.local();
620 for (auto i = r.begin(); i != r.end(); ++i) {
621 gaussReduceRow(i, my_dense, onlyConstantMaps, track);
622 }
623 });
624 });
625
626 for (auto tlDense : threadLocalDense)
627 mRing.vectorArithmetic().deallocateElementArray(tlDense);
628#else
629 // allocate a dense row, of correct size
630 ElementArray gauss_row = mRing.vectorArithmetic().allocateElementArray(
631 static_cast<ComponentIndex>(mColumns.size()));
632 for (long i = 0; i < mSPairs.size(); i++)
633 {
634 gaussReduceRow(i, gauss_row, onlyConstantMaps, track);
635 }
636 mRing.vectorArithmetic().deallocateElementArray(gauss_row);
637#endif
638}
639
640void F4Res::construct(int lev, int degree)
641{
642 decltype(timer()) timeA, timeB;
643
644 resetMatrix(lev, degree);
645
646 if (M2_gbTrace >= 2)
647 std::cout << "construct (" << lev << "," << degree-lev << ")" << std::endl;
648
649 timeA = timer();
650 makeMatrix();
651 timeB = timer();
652 mFrame.timeMakeMatrix += seconds(timeB - timeA);
653
654 //if (M2_gbTrace >= 2) mHashTable.dump();
655
656 if (M2_gbTrace >= 2)
657 std::cout << " make (" << lev << "," << degree-lev << "): " << seconds(timeB - timeA) << " sec"
658 << std::endl;
659
660#if 0
661 std::cout << "-- rows --" << std::endl;
663 std::cout << "-- columns --" << std::endl;
665 std :: cout << "-- reducer matrix --" << std::endl;
666 if (true or lev <= 2)
668 else
670
671 std :: cout << "-- reducer matrix --" << std::endl;
674
675 std :: cout << "-- spair matrix --" << std::endl;
678#endif
679
680// if (M2_gbTrace >= 2)
681// std::cout << " (degree,level)=(" << (mThisDegree - mThisLevel) << ","
682// << mThisLevel << ") #spairs=" << mSPairs.size()
683// << " reducer= " << mReducers.size() << " x " << mReducers.size()
684// << std::endl;
685
686// if (M2_gbTrace >= 2) std::cout << " gauss reduce matrix" << std::endl;
687
688 timeA = timer();
689 gaussReduce();
690 timeB = timer();
691 mFrame.timeGaussMatrix += seconds(timeB - timeA);
692
693 if (M2_gbTrace >= 2)
694 std::cout << " gauss (" << lev << "," << degree-lev << "): " << seconds(timeB - timeA) << " sec"
695 << std::endl;
696// std::cout << " time: " << seconds(timeB - timeA) << " sec" << std::endl;
697 // mFrame.show(-1);
698
699 timeA = timer();
700 clearMatrix();
701 timeB = timer();
702 mFrame.timeClearMatrix += seconds(timeB - timeA);
703}
704
706{
707 std::cout << "-- reducers(rows) -- " << std::endl;
708 auto end = mReducers.cend();
709 for (auto i = mReducers.cbegin(); i != end; ++i)
710 {
711 monoid().showAlpha((*i).mLeadTerm);
712 std::cout << std::endl;
713 }
714}
716{
717 std::cout << "-- columns --" << std::endl;
718 auto end = mColumns.cend();
719 for (auto i = mColumns.cbegin(); i != end; ++i)
720 {
721 monoid().showAlpha((*i));
722 std::cout << std::endl;
723 }
724}
725
726void F4Res::debugOutputMatrixSparse(std::vector<Row>& rows)
727{
728 for (ComponentIndex i = 0; i < rows.size(); i++)
729 {
730 std::cout << "coeffs[" << i << "] = ";
731 mRing.vectorArithmetic().displayElementArray(std::cout, rows[i].mCoeffs);
732 std::cout << " comps = ";
733 for (long j = 0; j < rows[i].mComponents.size(); ++j)
734 std::cout << rows[i].mComponents[j] << " ";
735 std::cout << std::endl;
736 }
737}
738
739void F4Res::debugOutputMatrix(std::vector<Row>& rows)
740{
741 for (ComponentIndex i = 0; i < rows.size(); i++)
742 {
743 mRing.vectorArithmetic().displayAsDenseArray(std::cout,
744 static_cast<int>(mColumns.size()),
745 rows[i].mCoeffs,
746 Range(rows[i].mComponents.data(), rows[i].mComponents.data() + rows[i].mComponents.size()));
747 }
748}
751
752// Local Variables:
753// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
754// indent-tabs-mode: nil
755// End:
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
bool isNull() const
Type-erased owning handle to a dense coefficient vector held by a ConcreteVectorArithmetic<Ring>.
void debugOutputReducers()
Definition res-f4.cpp:705
void resetMatrix(int lev, int degree)
Definition res-f4.cpp:69
MonomialHashTable< ResMonomialsWithComponent > mHashTable
Definition res-f4.hpp:173
ComponentIndex processMonomialProduct(res_const_packed_monomial m, res_const_packed_monomial n, int &result_sign_if_skew)
Definition res-f4.cpp:154
void gaussReduce()
Definition res-f4.cpp:579
void reorderColumns()
Definition res-f4.cpp:300
F4Res(SchreyerFrame &res)
Definition res-f4.cpp:50
void construct(int lev, int degree)
Definition res-f4.cpp:640
int mThisDegree
Definition res-f4.hpp:165
const VectorArithmetic & vectorArithmetic() const
Definition res-f4.hpp:102
const ResPolyRing & ring() const
Definition res-f4.hpp:104
~F4Res()
Definition res-f4.cpp:64
void debugOutputColumns()
Definition res-f4.cpp:715
int mThisLevel
Definition res-f4.hpp:164
std::unique_ptr< const ResMonomialsWithComponent > mSchreyerRes
Definition res-f4.hpp:170
const ResMonoid & monoid() const
Definition res-f4.hpp:103
std::vector< res_packed_monomial > mColumns
Definition res-f4.hpp:184
void debugOutputMatrixSparse(std::vector< Row > &)
Definition res-f4.cpp:726
MonomialMemorySpace mMonomSpace2
Definition res-f4.hpp:188
void makeMatrix()
Definition res-f4.cpp:408
std::vector< Row > mReducers
Definition res-f4.hpp:179
bool findDivisor(res_const_packed_monomial m, res_packed_monomial result)
findDivisor
Definition res-f4.cpp:109
SchreyerFrame & mFrame
Definition res-f4.hpp:159
void gaussReduceRow(int index, ElementArray &dense, bool onlyConstantMaps, const std::vector< bool > &track)
Definition res-f4.cpp:465
const ResPolyRing & mRing
Definition res-f4.hpp:161
void debugOutputMatrix(std::vector< Row > &)
Definition res-f4.cpp:739
void clearMatrix()
Definition res-f4.cpp:76
std::vector< long > mSPairComponents
Definition res-f4.hpp:182
void loadRow(Row &r)
Definition res-f4.cpp:226
void debugOutputSPairMatrix()
Definition res-f4.cpp:750
ComponentIndex processCurrentMonomial(res_packed_monomial thisMonom)
Definition res-f4.cpp:192
void debugOutputReducerMatrix()
Definition res-f4.cpp:749
SchreyerFrame & frame()
Definition res-f4.hpp:92
long mNextReducerToProcess
Definition res-f4.hpp:166
std::vector< Row > mSPairs
Definition res-f4.hpp:181
component_index get_component(res_const_packed_monomial m) const
void showAlpha(res_const_packed_monomial m) const
void set_component(component_index component, res_packed_monomial m) const
bool is_divisible_by_var_in_range(res_const_packed_monomial monom, int lo, int hi) const
void unchecked_mult(res_const_packed_monomial m, res_const_packed_monomial n, res_packed_monomial result) const
int skew_mult_sign(const SkewMultiplication *skew, res_const_packed_monomial m, res_const_packed_monomial n) const
Sorter that orders res_packed_monomials by their total (Schreyer) monomial, with a stable tiebreaker ...
MonHashTable trait for the resolution engine's res_packed_monomials, with components included.
const VectorArithmetic & vectorArithmetic() const
Builder that accumulates terms into a ResPolynomial and finalises the layout in one shot via setPoly.
Forward iterator over the terms of a ResPolynomial.
State container for the in-progress free resolution built by the F4 resolution engine.
ElementArray allocateElementArray(ComponentIndex nelems) const
Create a coefficient vector with room for nelems coefficients.
void pushBackMinusOne(ElementArray &coeffs) const
int p
VALGRIND_MAKE_MEM_DEFINED & result(result)
int M2_gbTrace
Definition m2-types.cpp:52
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition mpreal.h:3244
volatile int x
static void applyPermutation(ComponentIndex *permutation, std::vector< ComponentIndex > &entries)
Definition res-f4.cpp:281
F4Res — F4-style matrix-reduction worker over a SchreyerFrame.
Schreyer-order column sorters for the F4 resolution Macaulay matrix.
const res_monomial_word * res_const_packed_monomial
res_monomial_word * res_packed_monomial
int ComponentIndex
SchreyerFrame — in-progress representation of a free resolution organised by (level,...
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
std::vector< ComponentIndex > mComponents
Definition res-f4.hpp:123
ElementArray mCoeffs
Definition res-f4.hpp:124
res_packed_monomial mLeadTerm
Definition res-f4.hpp:121
One row of the Macaulay matrix built by F4Res::construct.
Definition res-f4.hpp:119
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
std::chrono::steady_clock::time_point timer()
Definition timing.hpp:35
double seconds(DurationType time_diff)
Definition timing.hpp:59
Inline std::chrono::steady_clock wrappers and elapsed-time conversion helpers.