Macaulay2 Engine
Loading...
Searching...
No Matches
res-a0.cpp
Go to the documentation of this file.
1// Copyright 1996. Michael E. Stillman
2
3#include "res-a0.hpp"
4
5#include "ExponentVector.hpp"
6#include "res-a0-poly.hpp"
7#include "geobucket.hpp"
8#include "buffer.hpp"
9#include "text-io.hpp"
10#include "interrupted.hpp"
11#include "betti.hpp"
12
14
16{
17 if (stop_.length_limit != nullptr && stop_.length_limit->len > 0)
18 {
19 }
20
21 return true;
22}
23
25{
26 int lo = hidegree + 1;
27 int len = resn.size() - 1;
28 for (int lev = 0; lev <= len; lev++)
29 {
30 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
31 {
32 if (p->syz_type != SYZ2_S_PAIR) continue;
33 int d = p->degree;
34 if (d < lo) lo = d;
35 }
36 }
37 return lodegree + lo - 1;
38}
39
41// Compute the skeleton of the resolution
42// returns COMP_COMPUTING or COMP_INTERRUPTED
43{
44 res2_pair *p;
45 if (resn[level]->state != RES_SKELETON) return COMP_COMPUTING;
46 // If we are new here, next_pairs will be null, so we should sort
47 if (resn[level]->next_pair == nullptr)
48 {
49 sort_skeleton(resn[level]->pairs);
50 int n = 0;
51 for (p = resn[level]->pairs; p != nullptr; p = p->next)
52 {
53 p->me = n++;
54 p->pair_num = p->me;
55 }
56 resn[level]->next_pair = resn[level]->pairs;
57 }
58
59 // Now compute the pairs at the next level
60 for (;;)
61 {
62 p = resn[level]->next_pair;
63 if (p == nullptr) break;
64 resn[level]->next_pair = p->next;
65 // The following will only insert pairs of degree > topdegree
66 // so this routine may be used to increase the degree bound
67 // note: also need to redo monomial ideals...
68 new_pairs(p);
70 }
71 resn[level]->state = RES_MONORDER;
72 return COMP_COMPUTING;
73}
74
76{
77 for (int i = resn.size(); i <= newmax + 2; i++)
78 {
79 res2_level *p = new res2_level;
80 p->pairs = nullptr;
81 p->next_pair = nullptr;
82 p->state = RES_SKELETON;
83 p->npairs = 0;
84 p->nleft = 0;
85 p->nminimal = 0;
86 p->nthrown = 0;
87 resn.push_back(p);
88 }
89 length_limit = newmax;
90}
91
93{
94 // First compute all pairs necessary for doing this (level,degree)
95 // and then actually compute the ones in that degree.
96 if (level <= 0 || level > length_limit + 1) return COMP_COMPUTING;
97 // if (degree <= 0 || degree > hidegree) return COMP_COMPUTING;
98 if (level < resn.size() && (resn[level]->next_pair == nullptr ||
99 degree < resn[level]->next_pair->degree))
100 return COMP_COMPUTING;
101 enum ComputationStatusCode ret = do_all_pairs(level, degree - 1);
102 if (ret != COMP_COMPUTING) return ret;
103 ret = do_all_pairs(level + 1, degree - 1);
104 if (ret != COMP_COMPUTING) return ret;
105 ret = do_pairs(level, degree);
106 return ret;
107}
108
110{
111 // Find the first pair in this degree, and count the number of
112 // pairs to compute in this degree.
113 // If this number is 0, continue
114 res2_pair *p;
115
116 if (M2_gbTrace >= 2)
117 {
118 p = resn[level]->next_pair;
119 int nelems = 0;
120 while (p != nullptr && p->degree == degree)
121 {
122 if (p->syz_type == SYZ2_S_PAIR || p->syz_type == SYZ2_MAYBE_MINIMAL)
123 nelems++;
124 p = p->next;
125 }
126 if (nelems > 0)
127 {
128 buffer o;
129 o << "[" << degree << " " << level << " " << nelems << "]";
130 emit(o.str());
131 }
132 }
133 for (p = resn[level]->next_pair; p != nullptr; p = p->next)
134 {
135 if (p->degree != degree) break;
136 resn[level]->next_pair = p->next;
137 if (p->syz_type == SYZ2_S_PAIR || p->syz_type == SYZ2_MAYBE_MINIMAL)
138 {
139 handle_pair(p);
140 if (stop_.pair_limit > 0 && npairs - nleft >= stop_.pair_limit)
142 // if (--PairLimit == 0) return COMP_DONE_PAIR_LIMIT;
143 if (stop_.syzygy_limit > 0 && nminimal >= stop_.syzygy_limit)
145 }
147 }
148 return COMP_COMPUTING;
149}
150
152{
153 // The pairs should be sorted in ascending monomial order
154
155 res2_pair *p;
156
157 if (M2_gbTrace >= 2)
158 {
159 int nelems = resn[level]->nleft;
160 if (nelems > 0)
161 {
162 buffer o;
163 o << "[lev " << nelems << ']';
164 emit(o.str());
165 }
166 }
167 for (p = resn[level]->next_pair; p != nullptr; p = p->next)
168 {
169 resn[level]->next_pair = p->next;
171 if (stop_.pair_limit > 0 && npairs - nleft >= stop_.pair_limit)
173 // if (--PairLimit == 0) return COMP_DONE_PAIR_LIMIT;
175 }
176
177 if (do_by_level == 2)
178 {
179 // The following is experimental
180 // Remove any term that cannot appear as a lead term.
181 // This destroys the resolution as we go, so in general, we would have
182 // to place this information elsewhere.
183 int nmonoms = 0;
184 int nkilled = 0;
185 for (p = resn[level]->pairs; p != nullptr; p = p->next)
186 {
187 res2term *f = p->syz;
188 res2term head;
189 res2term *g = &head;
190 for (f = p->syz; f != nullptr; f = f->next)
191 {
192 if (f->comp->mi->size() > 0)
193 {
194 g->next = R->new_term(K->copy(f->coeff), f->monom, f->comp);
195 g = g->next;
196 nmonoms++;
197 }
198 else
199 nkilled++;
200 }
201 g->next = nullptr;
202 p->pivot_term = head.next;
203 }
204 if (M2_gbTrace >= 3)
205 {
206 buffer o;
207 o << "[kept " << nmonoms << " killed " << nkilled << "]";
208 emit(o.str());
209 }
210 }
211 return COMP_COMPUTING;
212}
213
215{
216 // Find the first pair in this degree, and count the number of
217 // pairs to compute in this degree.
218 // If this number is 0, continue
219 res2_pair *p;
220
221 if (M2_gbTrace >= 2 && level > 1)
222 {
223 p = resn[level]->next_pair;
224 int nelems = 0;
225 while (p != nullptr && p->degree == degree)
226 {
227 nelems++;
228 p = p->next;
229 }
230 if (nelems > 0)
231 {
232 buffer o;
233 o << '[' << nelems << ']';
234 emit(o.str());
235 }
236 }
237 for (p = resn[level]->next_pair; p != nullptr; p = p->next)
238 {
239 if (p->degree != degree) break;
240 resn[level]->next_pair = p->next;
241 if (p->syz_type == SYZ2_S_PAIR || p->syz_type == SYZ2_NOT_NEEDED ||
242 (p->syz_type == SYZ2_MAYBE_MINIMAL && level < length_limit + 1))
243 {
245 if (stop_.pair_limit > 0 && npairs - nleft >= stop_.pair_limit)
247 // if (--PairLimit == 0) return COMP_DONE_PAIR_LIMIT;
248 if (stop_.syzygy_limit > 0 && nminimal >= stop_.syzygy_limit)
250 }
252 }
253 return COMP_COMPUTING;
254}
255
256#define DO(CALL) \
257 { \
258 enum ComputationStatusCode result = CALL; \
259 if (result != COMP_COMPUTING) \
260 { \
261 set_status(result); \
262 return; \
263 } \
264 }
265
267{
268 int n, level;
269 res2_pair *p;
270
271 if (status() == COMP_DONE) return;
273
274 if (stop_.length_limit->len > 0)
275 {
277 // this also sets length_limit
278 increase_level(stop_.length_limit->array[0]);
279 else
280 length_limit = stop_.length_limit->array[0];
281 }
282 int compute_level = COMPUTE_RES;
283
284 for (level = 1; level <= length_limit + 1; level++) DO(skeleton(level));
285
286 if (M2_gbTrace >= 3)
287 {
288 buffer o;
289 o << "--- The total number of pairs in each level/slanted degree -----"
290 << newline;
292 betti_display(o, a);
293 emit(o.str());
294 }
295
296 // The skeleton routine sets the following:
297 // hidegree: highest slanted degree found so far
298 // a flag for each level as to whether the level has new elements
299 // since the last time the pairs were sorted for reduction
300
301 if (compute_level <= COMPUTE_SKELETON)
302 {
304 return;
305 }
306
307 // Set the monomial order for each level, and then prepare for
308 // reductions
309 for (level = 1; level <= length_limit + 1; level++)
310 {
311 if (resn[level]->state != RES_MONORDER) continue;
312 // The sort will use compare_num's from syz->comp->compare_num
313 // and will use these numbers to break ties:
314 for (n = 0, p = resn[level]->pairs; p != nullptr; p = p->next, n++)
315 p->compare_num = n;
316 sort_monorder(resn[level]->pairs);
317 for (n = 0, p = resn[level]->pairs; p != nullptr; p = p->next, n++)
318 p->compare_num = n;
319 sort_reduction(resn[level]->pairs);
320 resn[level]->state = RES_REDUCTIONS;
321 resn[level]->next_pair = resn[level]->pairs;
322 }
323
324 for (level = 1; level <= length_limit + 1; level++)
325 {
326 resn[level]->next_pair = resn[level]->pairs;
327 }
328
329 // Here: possibly compute the resolution of the monomial ideal first.
330
331 if (compute_level <= COMPUTE_MONOMIAL_RES)
332 {
334 return;
335 }
336
337 if (do_by_level != 0)
338 {
339 for (level = 1; level <= length_limit; level++)
340 DO(do_pairs_by_level(level));
342 return;
343 }
344
345 if (do_by_degree)
346 {
347 for (int deg = 0; deg <= hidegree; deg++)
348 {
349 if (stop_.stop_after_degree &&
350 stop_.degree_limit->array[0] - lodegree < deg)
351 // if (DegreeLimit != NULL && deg > *DegreeLimit - lodegree)
352 {
354 return;
355 }
356 if (M2_gbTrace >= 1)
357 {
358 buffer o;
359 o << '{' << deg + lodegree << '}';
360 emit(o.str());
361 }
362 for (level = 1; level <= length_limit; level++)
363 DO(do_pairs_by_degree(level, deg));
364 }
366 return;
367 }
368
369 // Now do all of the reductions
370 for (int deg = 0; deg <= hidegree; deg++)
371 {
372 if (stop_.stop_after_degree &&
373 stop_.degree_limit->array[0] - lodegree < deg)
374 // if (DegreeLimit != NULL && deg > *DegreeLimit - lodegree)
375 {
377 return;
378 }
379 if (M2_gbTrace >= 1)
380 {
381 buffer o;
382 o << '{' << deg + lodegree << '}';
383 emit(o.str());
384 }
385 for (level = 1; level <= length_limit + 1; level++)
386 {
387 DO(do_all_pairs(level, deg));
388 if (level > projdim) break;
389 }
390 }
391#if 0
392// //This is the older, working version...
393// // Now do all of the reductions
394// for (int deg=0; deg<=hidegree; deg++)
395// {
396// if (DegreeLimit != NULL && deg > *DegreeLimit - lodegree)
397// {
398// set_status(COMP_DONE_DEGREE_LIMIT);
399// return;
400// }
401// if (M2_gbTrace >= 1)
402// {
403// buffer o;
404// o << '{' << deg+lodegree << '}';
405// emit(o.str());
406// }
407// for (level=1; level<=length_limit+1; level++)
408// {
409// DO(do_pairs(level,deg));
410// }
411// }
412#endif
414}
415
417// Initialization of a computation /////////
419
421 int LengthLimit,
422 bool UseDegreeLimit,
423 int SlantedDegreeLimit,
424 int SortStrategy)
425{
428 assert(P != NULL);
429 R = new res2_poly(const_cast<PolynomialRing *>(P));
430 M = P->getMonoid();
431 K = P->getCoefficientRing();
432 generator_matrix = mat;
433
434 exp_size = EXPONENT_BYTE_SIZE(P->n_vars());
435 monom_size = MONOMIAL_BYTE_SIZE(M->monomial_size());
436
437 res2_pair_stash = new stash("res2pair", sizeof(res2_pair));
438 mi_stash = new stash("res2 minodes", sizeof(Nmi_node));
439
440 length_limit = -3; // The resolution is always kept at least in range
441 // 0 .. length_limit + 2.
442 increase_level(LengthLimit);
443
444 projdim = 0;
445 max_mon_degree = M->max_degree();
446
447 if (mat->n_rows() > 0)
448 {
449 lodegree = mat->rows()->primary_degree(0);
450 for (auto i = 1; i < mat->n_rows(); i++)
451 if (lodegree > mat->rows()->primary_degree(i))
452 lodegree = mat->rows()->primary_degree(i);
453 }
454 else
455 lodegree = 0;
456
457 // This can't actually set lodegree, can it?
458 for (auto i = 0; i < mat->n_cols(); i++)
459 if (lodegree > mat->cols()->primary_degree(i) - 1)
460 lodegree = mat->cols()->primary_degree(i) - 1;
461
462 hidegree = 0; // hidegree is an offset from 'lodegree'.
463
464 have_degree_limit = UseDegreeLimit;
465 hard_degree_limit = SlantedDegreeLimit;
466
467 nleft = 0;
468 npairs = 0;
469 nminimal = 0;
471
472 n_ones = 0;
473 n_unique = 0;
474 n_others = 0;
475
476 // Do level 0
477 next_component = 0;
478 for (auto i = 0; i < mat->n_rows(); i++)
479 {
481 base_components.push_back(p);
482 }
483 for (auto p = base_components.rbegin(); p != base_components.rend(); ++p)
484 insert_pair(*p);
485
486 // Do level 1
487 for (auto i = 0; i < generator_matrix->n_cols(); i++)
488 if ((*generator_matrix)[i] != nullptr)
489 {
490 res2_pair *p = new_res2_pair(i); // Makes a generator 'pair'
491 insert_pair(p);
492 }
493
494 // Set variables for compare_res2_pairs
499
500 skeleton_sort = SortStrategy & 63;
501 reduction_sort = (SortStrategy >> 6) & 63;
502 reduction_sort |= FLAGS_DEGREE; // ALWAYS do by increasing degree.
503 do_by_level = (unsigned char)(SortStrategy & FLAGS_LEVEL ? 1 : 0);
504 if (SortStrategy & FLAGS_LEVEL_STRIP) do_by_level = 2;
505 do_by_degree = (unsigned char)(SortStrategy & FLAGS_DEGREELEVEL ? 1 : 0);
506 auto_reduce = (SortStrategy & FLAGS_AUTO) >> SHIFT_AUTO;
507 use_respolyHeaps = (unsigned char)(SortStrategy & FLAGS_GEO ? 1 : 0);
508
509 if (do_by_degree) do_by_level = 0;
510 if (M2_gbTrace >= 3)
511 {
512 buffer o;
513 o << "auto-reduce level = " << auto_reduce << newline;
514 if (do_by_level)
515 {
516 o << "computing resolution level by level" << newline;
517 if (do_by_level == 2) o << "with strip optimization" << newline;
518 }
519 if (do_by_degree)
520 o << "computing resolution degree by slanted degree" << newline;
521 if (use_respolyHeaps) o << "using heap based reduction" << newline;
522 o << "skeleton order = ";
524 o << "reduction sort = ";
526 emit(o.str());
527 }
528}
529
530void res2_comp::display_order(buffer &o, int sortval) const
531{
532 o << "[";
533 switch (sortval & FLAGS_SORT)
534 {
535 case COMPARE_LEX:
536 o << "LEX";
537 break;
539 o << "LEX1";
540 break;
542 o << "LEX2";
543 break;
544 case COMPARE_ORDER:
545 o << "ORDER";
546 break;
547 default:
548 o << "bad order";
549 break;
550 }
551 if (sortval & FLAGS_DEGREE) o << " (ascending degree first)";
552 if (sortval & FLAGS_DESCEND)
553 o << " descend";
554 else
555 o << " ascend";
556 if ((sortval & FLAGS_REVERSE) && ((sortval & FLAGS_SORT) != COMPARE_ORDER))
557 o << " reverse";
558 o << "]" << newline;
559}
560
562 int LengthLimit,
563 bool UseDegreeLimit,
564 int SlantedDegreeLimit,
565 int SortStrategy)
566{
567 initialize(m, LengthLimit, UseDegreeLimit, SlantedDegreeLimit, SortStrategy);
568}
569
571{
572 if (p == nullptr) return;
573 R->remove(p->syz);
574 delete p->mi;
575 freemem(p);
576}
577
579{
580 if (lev == nullptr) return;
581 while (lev->pairs != nullptr)
582 {
583 res2_pair *p = lev->pairs;
584 lev->pairs = p->next;
586 }
587 freemem(lev);
588}
589
591{
592 int i;
593 for (i = 0; i < resn.size(); i++) remove_res2_level(resn[i]);
594
595 delete res2_pair_stash;
596 delete mi_stash;
597 delete R;
598}
599
600// Data structure insertion and access /////
602
604 res2_pair * /* second */,
605 const int *basemon)
606{
607 res2_pair *p = new res2_pair;
608 p->next = nullptr;
609 p->me = next_component++;
610 p->pair_num = p->me;
611 p->syz_type = SYZ2_S_PAIR;
612 p->level = (unsigned char)(first->level + 1);
613 p->degree = (short unsigned int)(M->primary_degree(basemon) + first->degree -
614 M->primary_degree(first->syz->monom) - 1);
615 p->compare_num = 0; // Will be set after pairs are done
616 p->syz = R->new_term(K->from_long(1), basemon, first);
617#if 0
618// if (second != NULL)
619// p->syz->next = R->new_term(K->from_long(-1), basemon, second);
620#endif
621 p->mi = new MonomialIdeal(P, mi_stash);
622 p->pivot_term = nullptr;
623
624 return p;
625}
626
628{
629 res2_pair *p = new res2_pair;
630 p->next = nullptr;
631 p->me = next_component++;
632 p->pair_num = p->me;
633 p->syz_type = SYZ2_MINIMAL;
634 p->level = 0;
635 p->degree = (short unsigned int)(generator_matrix->rows()->primary_degree(i) -
636 lodegree);
637 p->compare_num = i;
638 monomial m = M->make_one();
639 p->syz = R->new_term(K->from_long(1), m, p); // circular link...
640 M->remove(m);
641 p->mi = new MonomialIdeal(P, mi_stash);
642 p->pivot_term = nullptr;
643 return p;
644}
645
647{
648 res2_pair *p = new res2_pair;
649 p->next = nullptr;
650 p->me = next_component++;
651 p->pair_num = p->me;
652 p->syz_type = SYZ2_S_PAIR;
653 p->level = 1;
654 p->degree = (short unsigned int)(generator_matrix->cols()->primary_degree(i) -
655 1 - lodegree);
656 p->compare_num = 0;
657 p->syz = R->from_vector(base_components, (*generator_matrix)[i]);
658 p->mi = new MonomialIdeal(P, mi_stash);
659 p->pivot_term = nullptr;
660 return p;
661}
662
664{
665 // This is where we insert the pair:
666 // If the degree is not in the range lodegree..hard_degree_limit+1
667 // then don't insert it.
668 if (q->level >= 1)
669 {
671 {
672 if (q->degree + lodegree > hard_degree_limit + 1)
673 {
674 resn[q->level]->nthrown++;
676 return;
677 }
678 if (q->degree <= hard_degree_limit && q->degree > hidegree)
679 hidegree = q->degree;
680 }
681 else if (q->degree > hidegree)
682 hidegree = q->degree;
683 }
684
685 q->next = resn[q->level]->pairs;
686 resn[q->level]->pairs = q;
687 npairs++;
688 resn[q->level]->npairs++;
689 if (q->syz_type == SYZ2_S_PAIR)
690 {
691 nleft++;
692 resn[q->level]->nleft++;
693 }
694 else
695 {
696 nminimal++;
697 resn[q->level]->nminimal++;
698 }
699}
700
701void res2_comp::multi_degree(const res2_pair *p, int *deg) const
702{
703 const res2_pair *q;
704 M->multi_degree(p->syz->monom, deg);
705 for (q = p; q->level != 0; q = q->syz->comp)
706 ;
707 get_ring()->degree_monoid()->mult(deg, generator_matrix->rows()->degree(q->me), deg);
708}
709
711// Sorting //////////////////////////////////
713
715{
716 // Lots of different orders appear here, controlled by the above
717 // static variables.
718 // if compare(f,g) returns -1, this says place g BEFORE f on the list.
719 exponents_t EXP1, EXP2, EXP3, EXP4;
720 int cmp, df, dg;
721
723 {
724 df = f->degree;
725 dg = g->degree;
726 if (df > dg) return -1;
727 if (df < dg) return 1;
728 }
729
730 switch (compare_type)
731 {
732 case COMPARE_MONORDER:
733 cmp = f->syz->comp->compare_num - g->syz->comp->compare_num;
734 if (cmp < 0) return 1;
735 if (cmp > 0)
736 return -1; // Lower compare num's should be on list earlier
737 cmp = f->compare_num - g->compare_num;
738 if (cmp < 0) return 1;
739 if (cmp > 0) return -1;
740 return 0;
741 case COMPARE_LEX:
744 M->to_expvector(f->syz->monom, EXP1);
745 M->to_expvector(g->syz->monom, EXP2);
747 {
748 for (int i = M->n_vars() - 1; i >= 0; i--)
749 {
750 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
751 if (EXP1[i] > EXP2[i]) return compare_use_descending;
752 }
753 }
754 else
755 {
756 for (int i = 0; i < M->n_vars(); i++)
757 {
758 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
759 if (EXP1[i] > EXP2[i]) return compare_use_descending;
760 }
761 }
762 [[fallthrough]];
763 case COMPARE_ORDER:
764 cmp = M->compare(f->syz->monom, g->syz->monom);
765 if (cmp != 0) return compare_use_descending * cmp;
766 cmp = f->syz->comp->compare_num - g->syz->comp->compare_num;
767 if (cmp < 0) return -compare_use_descending;
768 if (cmp > 0) return compare_use_descending;
769 return 0;
773 while (f->level >= 1)
774 {
775 M->to_expvector(f->syz->monom, EXP1);
776 M->to_expvector(g->syz->monom, EXP2);
778 {
779 for (int i = M->n_vars() - 1; i >= 0; i--)
780 {
781 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
782 if (EXP1[i] > EXP2[i]) return compare_use_descending;
783 }
784 }
785 else
786 {
787 for (int i = 0; i < M->n_vars(); i++)
788 {
789 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
790 if (EXP1[i] > EXP2[i]) return compare_use_descending;
791 }
792 }
793 // Go down one level
794 f = f->syz->comp;
795 g = g->syz->comp;
796 }
797 return 0;
803 M->to_expvector(f->syz->monom, EXP1);
804 M->to_expvector(g->syz->monom, EXP2);
806 {
807 for (int i = M->n_vars() - 1; i >= 0; i--)
808 {
809 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
810 if (EXP1[i] > EXP2[i]) return compare_use_descending;
811 }
812 }
813 else
814 {
815 for (int i = 0; i < M->n_vars(); i++)
816 {
817 if (EXP1[i] < EXP2[i]) return -compare_use_descending;
818 if (EXP1[i] > EXP2[i]) return compare_use_descending;
819 }
820 }
821 while (f->level >= 1)
822 {
823 // Go down one level
824 M->to_expvector(f->syz->monom, EXP1);
825 M->to_expvector(g->syz->monom, EXP2);
826 f = f->syz->comp;
827 g = g->syz->comp;
828 M->to_expvector(f->syz->monom, EXP3);
829 M->to_expvector(g->syz->monom, EXP4);
831 {
832 for (int i = M->n_vars() - 1; i >= 0; i--)
833 {
834 if (EXP1[i] - EXP3[i] < EXP2[i] - EXP4[i])
836 if (EXP1[i] - EXP3[i] > EXP2[i] - EXP4[i])
838 }
839 }
840 else
841 {
842 for (int i = 0; i < M->n_vars(); i++)
843 {
844 if (EXP1[i] - EXP3[i] < EXP2[i] - EXP4[i])
846 if (EXP1[i] - EXP3[i] > EXP2[i] - EXP4[i])
848 }
849 }
850 }
851 return 0;
852 default:
853 return 0;
854 }
855}
856
858{
859 if (g == nullptr) return f;
860 if (f == nullptr) return g;
861 res2_pair head;
862 res2_pair *result = &head;
863 while (1) switch (compare_res2_pairs(f, g))
864 {
865 case 0:
866 case -1:
867 result->next = g;
868 result = result->next;
869 g = g->next;
870 if (g == nullptr)
871 {
872 result->next = f;
873 return head.next;
874 }
875 break;
876 case 1:
877 result->next = f;
878 result = result->next;
879 f = f->next;
880 if (f == nullptr)
881 {
882 result->next = g;
883 return head.next;
884 }
885 break;
886 // case 0:
887 // assert(0);
888 }
889}
890
892{
893 // These elements are sorted in ascending 'me' values
894 if (p == nullptr || p->next == nullptr) return;
895 res2_pair *p1 = nullptr;
896 res2_pair *p2 = nullptr;
897 while (p != nullptr)
898 {
899 res2_pair *tmp = p;
900 p = p->next;
901 tmp->next = p1;
902 p1 = tmp;
903
904 if (p == nullptr) break;
905 tmp = p;
906 p = p->next;
907 tmp->next = p2;
908 p2 = tmp;
909 }
910
912 sort_res2_pairs(p2);
913 p = merge_res2_pairs(p1, p2);
914}
915
925{
926 // Rest of the compare_* don't matter in this case, except degree
930}
939
940int res2_comp::sort_value(res2_pair *p, const std::vector<int> sort_order) const
941{
943 M->to_expvector(p->syz->monom, REDUCE_exp);
944 return exponents::weight(P->n_vars(), REDUCE_exp, sort_order);
945}
946
948// Creation of new pairs ////////////////////
950
952// Create and insert all of the pairs which will have lead term 'p'.
953// This also places 'p' into the appropriate monomial ideal
954{
955 gc_vector<Bag*> elems;
956 gc_vector<int> vp; // This is 'p'.
957 gc_vector<int> thisvp;
958
960
961 if (M2_gbTrace >= 10)
962 {
963 buffer o;
964 o << "Computing pairs with first = " << p->pair_num << newline;
965 emit(o.str());
966 }
967 M->divide(p->syz->monom, p->syz->comp->syz->monom, PAIRS_mon);
968 M->to_varpower(PAIRS_mon, vp);
969
970 // First add in syzygies arising from exterior variables
971 // At the moment, there are none of this sort.
972
973 if (P->is_skew_commutative())
974 {
975 exponents_t exp = newarray_atomic(int, M->n_vars());
976 varpower::to_expvector(M->n_vars(), vp.data(), exp);
977
978 int nskew = P->n_skew_commutative_vars();
979 for (int v = 0; v < nskew; v++)
980 {
981 int w = P->skew_variable(v);
982 if (exp[w] > 0)
983 {
984 thisvp.resize(0);
985 varpower::var(w, 1, thisvp);
986 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
987 elems.push_back(b);
988 }
989 }
990 freemem(exp);
991 }
992
993 // Second, add in syzygies arising from the base ring, if any
994 // The baggage of each of these is NULL
995 if (P->is_quotient_ring())
996 {
997 const MonomialIdeal *Rideal = P->get_quotient_monomials();
998 for (Bag& a : *Rideal)
999 {
1000 // Compute (P->quotient_ideal->monom : p->monom)
1001 // and place this into a varpower and Bag, placing
1002 // that into 'elems'
1003 thisvp.resize(0);
1004 varpower::quotient(a.monom().data(), vp.data(), thisvp);
1005 if (varpower::is_equal(a.monom().data(), thisvp.data()))
1006 continue;
1007 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
1008 elems.push_back(b);
1009 }
1010 }
1011
1012 // Third, add in syzygies arising from previous elements of this same level
1013 // The baggage of each of these is their corresponding res2_pair
1014
1015 MonomialIdeal *mi_orig = p->syz->comp->mi;
1016 for (Bag& a : *mi_orig)
1017 {
1018 Bag *b = new Bag(a.basis_ptr());
1019 varpower::quotient(a.monom().data(), vp.data(), b->monom());
1020 elems.push_back(b);
1021 }
1022
1023 // Make this monomial ideal, and then run through each minimal generator
1024 // and insert into the proper degree. (Notice that sorting does not
1025 // need to be done yet: only once that degree is about to begin.
1026
1027 mi_orig->insert_minimal(new Bag(p, vp));
1028
1029 MonomialIdeal mi(P, elems);
1030
1031 if (M2_gbTrace >= 11) mi.debug_out(1);
1032
1033 monomial m = M->make_one();
1034 for (Bag& a : mi)
1035 {
1036 res2_pair *second = reinterpret_cast<res2_pair *>(a.basis_ptr());
1037 M->from_varpower(a.monom().data(), m);
1038 M->mult(m, p->syz->monom, m);
1039
1040 res2_pair *q = new_res2_pair(p, second, m);
1041 insert_pair(q);
1042 }
1043}
1044
1045// S-pairs and reduction ////////////////////
1047
1049// If 'exp' is divisible by a ring lead term, then 1 is returned,
1050// and result is set to be that ring element.
1051// Otherwise 0 is returned.
1052{
1053 if (!P->is_quotient_ring()) return 0;
1054 Bag *b;
1055 if (!P->get_quotient_monomials()->search_expvector(exp, b)) return 0;
1056 result.poly_val = P->quotient_element(b->basis_elem());
1057 return 1;
1058}
1059
1061 const int *exp,
1062 res2_pair *&result)
1063{
1064 // Find all the possible matches, use some criterion for finding the best...
1065 res2_pair *p;
1066 VECTOR(Bag *) bb;
1067 mi->find_all_divisors(exp, bb);
1068 if (bb.size() == 0) return 0;
1069 result = reinterpret_cast<res2_pair *>((bb[0]->basis_ptr()));
1070 // Now search through, and find the best one. If only one, just return it.
1071 if (M2_gbTrace >= 5)
1072 if (mi->size() > 1)
1073 {
1074 buffer o;
1075 o << ":" << mi->size() << "." << bb.size() << ":";
1076 emit(o.str());
1077 }
1078 if (bb.size() == 1)
1079 {
1080 if (mi->size() == 1)
1081 n_ones++;
1082 else
1083 n_unique++;
1084 return 1;
1085 }
1086 n_others++;
1087 // int n = R->n_terms(result->syz);
1088
1089 unsigned int lowest = result->pair_num;
1090 for (int i = 1; i < bb.size(); i++)
1091 {
1092 p = reinterpret_cast<res2_pair *>(bb[i]->basis_ptr());
1093 if (p->pair_num < lowest)
1094 {
1095 lowest = p->pair_num;
1096 result = p;
1097 }
1098#if 0
1099// int nt = R->n_terms(p->syz);
1100// if (nt < n)
1101// {
1102// n = nt;
1103// result = p;
1104// }
1105#endif
1106 }
1107 return 1;
1108}
1109
1111{
1112 res2term *result = nullptr;
1113 monomial si = M->make_one();
1114 while (f != nullptr)
1115 {
1116 M->divide(f->monom, f->comp->syz->monom, si);
1117 res2term *h = R->mult_by_term(f->comp->syz, f->coeff, si);
1118 R->add_to(result, h);
1119 // R->subtract_multiple_to(result, f->coeff, si, f->comp->syz);
1120 f = f->next;
1121 }
1122 M->remove(si);
1123 return result;
1124}
1125
1127 res2term *&fsyz,
1128 res2term *&pivot,
1129 res2_pair *)
1130// Reduce f, placing the reduction history in fsyz.
1131// Returns NULL if f reduces to 0, otherwise
1132// returns the res2_pair at the previous level (f will "fill in" that pair), and
1133// place a pointer to the corresponding term in "pivot".
1134{
1135 // 'lastterm' is used to append the next monomial to fsyz->syz
1138
1139 res2term *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
1140
1141 res2_pair *q;
1142 ring_elem rg;
1143 // Bag *b;
1144
1145 int count = 0;
1146 if (M2_gbTrace >= 4) emit_wrapped(",");
1147
1148 while (f != nullptr)
1149 {
1150 M->divide(f->monom, f->comp->syz->monom, REDUCE_mon);
1151 M->to_expvector(REDUCE_mon, REDUCE_exp);
1152 if (find_ring_divisor(REDUCE_exp, rg))
1153 {
1154 // Subtract off f, leave fsyz alone
1155 Nterm *r = rg;
1156 M->divide(f->monom, r->monom, REDUCE_mon);
1157 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
1159 count++;
1160 }
1161 // else if (f->comp->mi.search_expvector(REDUCE_exp, b))
1162 else if (find_divisor(f->comp->mi, REDUCE_exp, q))
1163 {
1164 // q = (res2_pair *) (b->basis_ptr());
1165 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
1166 lastterm = lastterm->next;
1167 pivot = lastterm;
1169 {
1170 if (M2_gbTrace >= 4)
1171 {
1172 buffer o;
1173 o << count;
1174 emit_wrapped(o.str());
1175 }
1176 return q; // i.e. not computed yet
1177 }
1178 M->divide(f->monom, q->syz->monom, REDUCE_mon);
1179 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->syz);
1181 count++;
1182 }
1183 else
1184 {
1185 res2term *tmp = f;
1186 f = f->next;
1187 tmp->next = nullptr;
1188 R->remove(tmp);
1189 }
1190 }
1191 if (M2_gbTrace >= 4)
1192 {
1193 buffer o;
1194 o << count;
1195 emit_wrapped(o.str());
1196 }
1197 return nullptr;
1198}
1199
1201 res2term *&fsyz,
1202 res2term *&pivot,
1203 res2_pair *)
1204// Reduce f, placing the reduction history in fsyz.
1205// Returns NULL if f reduces to 0, otherwise
1206// returns the res2_pair at the previous level (f will "fill in" that pair), and
1207// place a pointer to the corresponding term in "pivot".
1208// 'p' is just here for auto-reduction...
1209{
1210 // 'lastterm' is used to append the next monomial to fsyz->syz
1213
1214 res2term *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
1215 res2term head;
1216 res2term *red = &head;
1217 res2_pair *result = nullptr;
1218 res2_pair *q;
1219 ring_elem rg;
1220
1221 int count = 0;
1222 if (M2_gbTrace >= 4) emit_wrapped(",");
1223
1224 while (f != nullptr)
1225 {
1226 M->divide(f->monom, f->comp->syz->monom, REDUCE_mon);
1227 M->to_expvector(REDUCE_mon, REDUCE_exp);
1228 if (find_ring_divisor(REDUCE_exp, rg))
1229 {
1230 // Subtract off f, leave fsyz alone
1231 Nterm *r = rg;
1232 M->divide(f->monom, r->monom, REDUCE_mon);
1233 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
1235 count++;
1236 }
1237 else if (find_divisor(f->comp->mi, REDUCE_exp, q))
1238 {
1240 {
1241 if (result == nullptr || auto_reduce >= 2)
1242 {
1243 lastterm->next =
1244 R->new_term(K->negate(f->coeff), f->monom, q);
1245 lastterm = lastterm->next;
1246 if (result == nullptr)
1247 {
1248 // Only do this for the first non-computed pair
1249 pivot = lastterm;
1250 result = q;
1251 }
1252 else if (auto_reduce == 2)
1253 {
1254 // Keep track of this element for later reduction
1255 // Store it with q. Now for a bit of a hack:
1256 // We store it in the 'pivot_term' field, since
1257 // it cannot have been set yet, and since we don't want
1258 // to waste space.
1260 au->next =
1261 reinterpret_cast<auto_reduce_node *>(q->pivot_term);
1262 au->p = pivot->comp;
1263 au->pivot = lastterm;
1264 q->pivot_term = reinterpret_cast<res2term *>(au);
1265 }
1266 if (auto_reduce == 0)
1267 {
1268 // Time to leave: 'red' has nothing in it
1269 // with this option, and 'f' is set correctly.
1270 return result;
1271 }
1272 }
1273 red->next = f;
1274 red = red->next;
1275 f = f->next;
1276 continue;
1277 }
1278 else
1279 {
1280 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
1281 lastterm = lastterm->next;
1282 M->divide(f->monom, q->syz->monom, REDUCE_mon);
1283 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->syz);
1285 count++;
1286 }
1287 }
1288 else
1289 {
1290 red->next = f;
1291 red = red->next;
1292 f = f->next;
1293 }
1294 }
1295 red->next = nullptr;
1296 f = head.next;
1297 if (M2_gbTrace >= 4)
1298 {
1299 buffer o;
1300 o << count;
1301 emit_wrapped(o.str());
1302 }
1303 return result;
1304}
1305
1306// The 'respolyHeap' version of reduction
1307
1309 res2term *&fsyz,
1310 res2term *&pivot,
1311 res2_pair *)
1312// Reduce f, placing the reduction history in fsyz.
1313// Returns NULL if f reduces to 0, otherwise
1314// returns the res2_pair at the previous level (f will "fill in" that pair), and
1315// place a pointer to the corresponding term in "pivot".
1316{
1317 // 'lastterm' is used to append the next monomial to fsyz->syz
1320
1321 res2term *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
1322 res2term head;
1323 res2term *red = &head;
1324 res2_pair *result = nullptr;
1325 res2_pair *q;
1326 ring_elem rg;
1327 respolyHeap fb(R); // No bucket is needed for fsyz, since we
1328 // only append elements to the end of fsyz.
1329 fb.add(f);
1330 f = nullptr;
1331 res2term *lead;
1332 // Bag *b;
1333
1334 int count = 0;
1335 if (M2_gbTrace >= 4) emit_wrapped(",");
1336
1337 while ((lead = fb.remove_lead_term()) != nullptr)
1338 {
1339 M->divide(lead->monom, lead->comp->syz->monom, REDUCE_mon);
1340 M->to_expvector(REDUCE_mon, REDUCE_exp);
1341 if (find_ring_divisor(REDUCE_exp, rg))
1342 {
1343 // Subtract off f, leave fsyz alone
1344 Nterm *r = rg;
1345 M->divide(lead->monom, r->monom, REDUCE_mon);
1346 ring_elem c = K->negate(lead->coeff);
1347 res2term *h =
1348 R->ring_mult_by_term(r->next, c, REDUCE_mon, lead->comp);
1349 R->remove(lead);
1350 K->remove(c);
1351 fb.add(h);
1353 count++;
1354 }
1355 else if (find_divisor(lead->comp->mi, REDUCE_exp, q))
1356 {
1357 // q = (res2_pair *) (b->basis_ptr());
1359 {
1360 if (result == nullptr)
1361 {
1362 lastterm->next =
1363 R->new_term(K->negate(lead->coeff), lead->monom, q);
1364 lastterm = lastterm->next;
1365 pivot = lastterm;
1366 result = q;
1367 }
1368 red->next = lead;
1369 red = red->next;
1370 continue;
1371 }
1372 else
1373 {
1374 ring_elem c = K->negate(lead->coeff);
1375 M->divide(lead->monom, q->syz->monom, REDUCE_mon);
1376 res2term *h = R->mult_by_term(q->syz->next, c, REDUCE_mon);
1377 lastterm->next = R->new_term(c, lead->monom, q);
1378 lastterm = lastterm->next;
1379 R->remove(lead);
1380 fb.add(h);
1382 count++;
1383 }
1384 }
1385 else
1386 {
1387 red->next = lead;
1388 red = red->next;
1389 }
1390 }
1391 red->next = nullptr;
1392 f = head.next;
1393 if (M2_gbTrace >= 4)
1394 {
1395 buffer o;
1396 o << count;
1397 emit_wrapped(o.str());
1398 }
1399 return result;
1400}
1401
1403 res2term *&fsyz,
1404 res2term *&pivot,
1405 res2_pair *p)
1406// Reduce f, placing the reduction history in fsyz.
1407// Returns NULL if f reduces to 0, otherwise
1408// returns the res2_pair at the previous level (f will "fill in" that pair), and
1409// place a pointer to the corresponding term in "pivot".
1410// 'p' is just here for auto-reduction...
1411{
1412 // 'lastterm' is used to append the next monomial to fsyz->syz
1415
1416 res2term *lastterm = fsyz;
1417 while (lastterm->next != nullptr) lastterm = lastterm->next;
1418
1419 res2term head;
1420 res2term *red = &head;
1421 res2_pair *result = nullptr;
1422 res2_pair *q;
1423 ring_elem rg;
1424
1425 int count = total_reduce_count;
1426 if (M2_gbTrace >= 4) emit_wrapped(",");
1427
1428 while (f != nullptr)
1429 {
1430 res2term *lead = f;
1431 f = f->next;
1432 lead->next = nullptr;
1433 M->divide(lead->monom, lead->comp->syz->monom, REDUCE_mon);
1434 M->to_expvector(REDUCE_mon, REDUCE_exp);
1435 if (find_ring_divisor(REDUCE_exp, rg))
1436 {
1437 // Subtract off f, leave fsyz alone
1438 Nterm *r = rg;
1439 M->divide(lead->monom, r->monom, REDUCE_mon);
1440 ring_elem c = K->negate(lead->coeff);
1441 res2term *h =
1442 R->ring_mult_by_term(r->next, c, REDUCE_mon, lead->comp);
1443 R->remove(lead);
1444 K->remove(c);
1445 R->add_to(f, h);
1447 }
1448 else if (find_divisor(lead->comp->mi, REDUCE_exp, q))
1449 {
1450 if (q->degree == p->degree + 1)
1451 // if (q->syz_type == SYZ2_S_PAIR)
1452 {
1453 lastterm->next =
1454 R->new_term(K->negate(lead->coeff), lead->monom, q);
1455 lastterm = lastterm->next;
1456 if (result == nullptr && q->syz_type == SYZ2_S_PAIR)
1457 {
1458 // Only do this for the first non-computed pair
1459 // Question: do we really need to keep this information
1460 // around?
1461 pivot = lastterm;
1462 result = q;
1463 }
1464 red->next = lead;
1465 red = red->next;
1466 continue;
1467 }
1468 else
1469 {
1470 ring_elem c = K->negate(lead->coeff);
1471 M->divide(lead->monom, q->syz->monom, REDUCE_mon);
1472 res2term *h = R->mult_by_term(q->syz->next, c, REDUCE_mon);
1473 lastterm->next = R->new_term(c, lead->monom, q); // grabs 'c'.
1474 lastterm = lastterm->next;
1475 R->remove(lead);
1476 R->add_to(f, h);
1478 }
1479 }
1480 else
1481 {
1482 red->next = lead;
1483 red = red->next;
1484 }
1485 }
1486 red->next = nullptr;
1487 f = head.next;
1488 if (M2_gbTrace >= 4)
1489 {
1490 buffer o;
1491 o << (total_reduce_count - count);
1492 emit_wrapped(o.str());
1493 }
1494 return result;
1495}
1496
1498// Reduce f, placing the reduction history in fsyz.
1499// Returns NULL if f reduces to 0, otherwise
1500// returns the res2_pair at the previous level (f will "fill in" that pair), and
1501// place a pointer to the corresponding term in "pivot".
1502{
1503 // 'lastterm' is used to append the next monomial to fsyz->syz
1506
1507 res2term *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
1508
1509 res2_pair *q;
1510 ring_elem rg;
1511
1512 int count = 0;
1513 if (M2_gbTrace >= 4) emit_wrapped(",");
1514
1515 while (f != nullptr)
1516 {
1517 M->divide(f->monom, f->comp->syz->monom, REDUCE_mon);
1518 M->to_expvector(REDUCE_mon, REDUCE_exp);
1519 if (find_ring_divisor(REDUCE_exp, rg))
1520 {
1521 // Subtract off f, leave fsyz alone
1522 Nterm *r = rg;
1523 M->divide(f->monom, r->monom, REDUCE_mon);
1524 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
1526 count++;
1527 }
1528 else if (find_divisor(f->comp->mi, REDUCE_exp, q))
1529 {
1530 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
1531 lastterm = lastterm->next;
1532 M->divide(f->monom, q->syz->monom, REDUCE_mon);
1533 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->pivot_term);
1535 count++;
1536 }
1537 else
1538 {
1539 res2term *tmp = f;
1540 f = f->next;
1541 tmp->next = nullptr;
1542 R->remove(tmp);
1543 }
1544 }
1545 if (M2_gbTrace >= 4)
1546 {
1547 buffer o;
1548 o << count;
1549 emit_wrapped(o.str());
1550 }
1551 return nullptr;
1552}
1553
1555{
1556 // 'lastterm' is used to append the next monomial to fsyz->syz
1559
1560 res2term *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
1561 res2_pair *q;
1562 ring_elem rg;
1563 respolyHeap fb(R); // No bucket is needed for fsyz, since we
1564 // only append elements to the end of fsyz.
1565 fb.add(f);
1566 f = nullptr;
1567 res2term *lead;
1568
1569 int count = 0;
1570 if (M2_gbTrace >= 4) emit_wrapped(",");
1571
1572 while ((lead = fb.remove_lead_term()) != nullptr)
1573 {
1574 M->divide(lead->monom, lead->comp->syz->monom, REDUCE_mon);
1575 M->to_expvector(REDUCE_mon, REDUCE_exp);
1576 if (find_ring_divisor(REDUCE_exp, rg))
1577 {
1578 // Subtract off f, leave fsyz alone
1579 Nterm *r = rg;
1580 M->divide(lead->monom, r->monom, REDUCE_mon);
1581 ring_elem c = K->negate(lead->coeff);
1582 res2term *h =
1583 R->ring_mult_by_term(r->next, c, REDUCE_mon, lead->comp);
1584 R->remove(lead);
1585 K->remove(c);
1586 fb.add(h);
1588 count++;
1589 }
1590 else if (find_divisor(lead->comp->mi, REDUCE_exp, q))
1591 {
1592 ring_elem c = K->negate(lead->coeff);
1593 M->divide(lead->monom, q->syz->monom, REDUCE_mon);
1594 res2term *h = R->mult_by_term(q->pivot_term->next, c, REDUCE_mon);
1595 lastterm->next = R->new_term(c, lead->monom, q);
1596 lastterm = lastterm->next;
1597 R->remove(lead);
1598 fb.add(h);
1600 count++;
1601 }
1602 else
1603 {
1604 R->remove(lead);
1605 }
1606 }
1607 f = nullptr;
1608 if (M2_gbTrace >= 4)
1609 {
1610 buffer o;
1611 o << count;
1612 emit_wrapped(o.str());
1613 }
1614 return nullptr;
1615}
1616
1618// Toplevel calculation and state machine ///
1620
1622// For each node in 'au', remove the specified multiple of 'p->syz'.
1623{
1624 buffer o;
1625 while (au != nullptr)
1626 {
1627 auto_reduce_node *a = au;
1628 au = au->next;
1629 o << "auto reduction: " << newline << " ";
1630 R->elem_text_out(p->syz);
1631 o << newline << " ";
1632 R->elem_text_out(a->p->syz);
1633 o << newline << " by coeff = ";
1634 K->elem_text_out(o, a->pivot->coeff);
1635 ring_elem c = K->negate(a->pivot->coeff);
1636 res2term *h = R->mult_by_coefficient(p->syz, c);
1637 K->remove(c);
1638 R->add_to(a->p->syz, h);
1639 o << newline << " result = ";
1640 R->elem_text_out(a->p->syz);
1641 o << newline;
1642 freemem(a);
1643 }
1644 emit(o.str());
1645}
1646
1648{
1649 nleft--;
1650 resn[p->level]->nleft--;
1651
1652 // For level 1: any non-marked GB elements in this degree are
1653 // minimal generators, so we need to mark them as such
1654 if (p->level == 1)
1655 {
1656 p->syz_type = SYZ2_MINIMAL;
1657 if (M2_gbTrace >= 2) emit_wrapped("z");
1658 if (projdim == 0) projdim = 1;
1659 nminimal++;
1660 return;
1661 }
1662
1663 res2term *f = s_pair(p->syz);
1664 res2_pair *q;
1665
1666 // This is used only for full auto reduction type 2.
1667 auto_reduce_node *au = reinterpret_cast<auto_reduce_node *>(p->pivot_term);
1668
1669 if (use_respolyHeaps)
1670 q = reduce3(f, p->syz, p->pivot_term, p);
1671 else if (auto_reduce >= 1)
1672 q = reduce2(f, p->syz, p->pivot_term, p);
1673 else
1674 q = reduce(f, p->syz, p->pivot_term, p);
1675
1676 // Auto reduction: here is where we 'modify' the
1677 // other elements by 'p'.
1678 if (auto_reduce == 2)
1679 {
1680 do_auto_reductions(p, au);
1681 }
1682 else if (auto_reduce == 3)
1683 {
1684 }
1685
1686 if (f == nullptr)
1687 {
1688 // minimal syzygy
1689 if (p->level == length_limit + 1)
1690 {
1691 p->syz_type = SYZ2_MAYBE_MINIMAL;
1692 }
1693 else
1694 {
1695 p->syz_type = SYZ2_MINIMAL;
1696 nminimal++;
1697 if (p->level > projdim) projdim = p->level;
1698 }
1699 if (M2_gbTrace >= 2) emit_wrapped("z");
1700 }
1701 else
1702 {
1703 R->make_monic(f);
1704 p->syz_type = SYZ2_NOT_MINIMAL;
1705
1706 // non-minimal syzygy
1707 R->remove(q->syz);
1708 q->syz = f;
1710
1711 // Auto reduction: here is where we modify the
1712 // other elements by 'q'.
1713 if (auto_reduce == 2)
1714 {
1716 q, reinterpret_cast<auto_reduce_node *>(q->pivot_term));
1717 q->pivot_term = nullptr;
1718 }
1719 else if (auto_reduce == 3)
1720 {
1721 }
1722
1723 if (M2_gbTrace >= 2) emit_wrapped("m");
1724 }
1725}
1726
1728{
1729 nleft--;
1730 resn[p->level]->nleft--;
1731
1732 // level 1 is easy: just mark as minimal
1733 if (p->level == 1)
1734 {
1735 p->syz_type = SYZ2_MINIMAL;
1736 if (M2_gbTrace >= 2) emit_wrapped("z");
1737 return;
1738 }
1739
1740 res2term *f = s_pair(p->syz);
1741 if (do_by_level == 2)
1742 {
1743 if (use_respolyHeaps)
1744 reduce_heap_by_level(f, p->syz);
1745 else
1746 reduce_by_level(f, p->syz);
1747 }
1748 else
1749 reduce(f, p->syz, p->pivot_term, p);
1750
1751 if (f == nullptr)
1752 {
1753 p->syz_type = SYZ2_MINIMAL;
1754 if (M2_gbTrace >= 2) emit_wrapped("z");
1755 }
1756 else
1757 {
1758 // This should not happen at all!!
1759 buffer o;
1760 o << "handle pair: should not be here!";
1761 o << "p->syz == ";
1762 R->elem_text_out(o, p->syz);
1763 emit(o.str());
1764 }
1765}
1766
1768{
1769 nleft--;
1770 resn[p->level]->nleft--;
1771
1772 // For level 1: any non-marked GB elements in this degree are
1773 // minimal generators, so we need to mark them as such
1774 if (p->level == 1)
1775 {
1776 if (p->syz_type != SYZ2_NOT_NEEDED)
1777 {
1778 p->syz_type = SYZ2_MINIMAL;
1779 if (M2_gbTrace >= 2) emit_wrapped("z");
1780 nminimal++;
1781 }
1782 return;
1783 }
1784
1785 res2term *f = s_pair(p->syz);
1786 res2_pair *q = reduce4(f, p->syz, p->pivot_term, p);
1787 // In this version of 'reduce', the resulting value of 'f' is irrelevant.
1788 // And in fact the routine should probably read:
1789 // res2_pair *q = reduce4(p->syz, p->pivot_term);
1790 if (q == nullptr)
1791 {
1792 if (p->syz_type != SYZ2_NOT_NEEDED)
1793 {
1794 // minimal syzygy
1795 p->syz_type = SYZ2_MINIMAL;
1796 nminimal++;
1797 resn[p->level]->nminimal++;
1798 if (M2_gbTrace >= 2) emit_wrapped("z");
1799 }
1800 else
1801 {
1802 if (M2_gbTrace >= 2) emit_wrapped("o");
1803 }
1804 }
1805 else
1806 {
1807 p->syz_type = SYZ2_NOT_MINIMAL;
1809 if (M2_gbTrace >= 2) emit_wrapped("m");
1810 }
1811}
1812
1814#include "matrix-con.hpp"
1815
1817{
1818 int lo = lodegree;
1819 int hi = lo + hidegree;
1820 int len = resn.size() - 1;
1821 BettiDisplay B(lo, hi, len);
1822
1823 for (int lev = 0; lev <= len; lev++)
1824 {
1825 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
1826 {
1827 int d = p->degree;
1828 B.entry(d, lev)++;
1829 }
1830 }
1831 return B.getBetti();
1832}
1833
1835{
1836 int lo = lodegree;
1837 int hi = lo + hidegree;
1838 int len = resn.size() - 1;
1839 int *bettis;
1840 betti_init(lo, hi, len, bettis);
1841 for (int lev = 0; lev <= len; lev++)
1842 {
1843 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
1844 {
1845 if (p->syz_type != SYZ2_S_PAIR) continue;
1846 int d = p->degree;
1847 bettis[lev + (len + 1) * d]++;
1848 }
1849 }
1850 M2_arrayint result = betti_make(lo, hi, len, bettis);
1851 freemem(bettis);
1852 return result;
1853}
1854
1856// Negative numbers represent upper bounds
1857{
1858 int lo = lodegree;
1859 int hi = lo + hidegree;
1860 int len = resn.size() - 1;
1861 int *bettis;
1862 betti_init(lo, hi, len, bettis);
1863 for (int lev = 0; lev <= len; lev++)
1864 {
1865 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
1866 {
1867 if (p->syz_type != SYZ2_MINIMAL) continue;
1868 int d = p->degree;
1869 bettis[lev + (len + 1) * d]++;
1870 }
1871 }
1872 M2_arrayint result = betti_make(lo, hi, len, bettis);
1873 freemem(bettis);
1874 return result;
1875}
1876
1878{
1879 int lo = lodegree;
1880 int hi = lo + hidegree;
1881 int len = resn.size() - 1;
1882 int *bettis;
1883 betti_init(lo, hi, len, bettis);
1884 for (int lev = 0; lev <= len; lev++)
1885 {
1886 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
1887 {
1888 int d = p->degree;
1889 bettis[lev + (len + 1) * d] += R->n_terms(p->syz);
1890 }
1891 }
1892 M2_arrayint result = betti_make(lo, hi, len, bettis);
1893 freemem(bettis);
1894 return result;
1895}
1896
1898{
1899 switch (type)
1900 {
1901 case 0:
1902 return betti_minimal();
1903 case 1:
1904 return betti_skeleton();
1905 case 2:
1906 return betti_remaining();
1907 case 3:
1908 return betti_nmonoms();
1909 case 4:
1910 ERROR(
1911 "cannot use Minimize=>true unless res(...,FastNonminimal=>true) "
1912 "was used");
1913 return nullptr;
1914 }
1915 ERROR("received unknown betti type");
1916 return nullptr;
1917}
1918
1920{
1921 buffer o;
1922 text_out(o, p);
1923 emit(o.str());
1924}
1926{
1927 res2_pair *a, *b;
1928
1929 a = p->syz->comp;
1930 if (p->syz->next == nullptr)
1931 b = nullptr;
1932 else
1933 b = p->syz->next->comp;
1934
1935 o << p->me << ' ';
1936 o << p->level << ' ' << p->degree << ' ';
1937 if (a != nullptr)
1938 o << a->me << ' ';
1939 else
1940 o << ". ";
1941 if (b != nullptr)
1942 o << b->me << ' ';
1943 else
1944 o << ". ";
1945
1946 o << p->compare_num << ' ';
1947
1948 switch (p->syz_type)
1949 {
1950 case SYZ2_S_PAIR:
1951 o << "PR";
1952 break;
1953 case SYZ2_MINIMAL:
1954 o << "SZ";
1955 break;
1956 case SYZ2_NOT_MINIMAL:
1957 o << "GB";
1958 o << "(pivot " << p->pivot_term->comp->me << ")";
1959 break;
1960 case SYZ2_NOT_NEEDED:
1961 o << "NO";
1962 break;
1963 default:
1964 break;
1965 }
1966
1967#if 0
1968// if (p->mi_exists)
1969#endif
1970 o << "[mi: " << p->mi->size() << "]";
1971#if 0
1972// else
1973// {
1974// res2_pair *q = p->next_div;
1975// int n = 0;
1976// while (q != NULL) { n++; q = q->next_div; }
1977// o << "[midiv: " << n << "]";
1978// }
1979#endif
1980 M->elem_text_out(o, p->syz->monom);
1981 o << " [" << R->n_terms(p->syz) << "] ";
1982 if (M2_gbTrace >= 4)
1983 {
1984 // Display the vector
1985 o << " syz: ";
1986 R->elem_text_out(o, p->syz);
1987 }
1988 o << newline;
1989}
1990
1992{
1993 buffer o;
1994 text_out(o);
1995 emit(o.str());
1996}
1997
1999{
2000 o << "--- The total number of pairs in each level/slanted degree -----"
2001 << newline;
2003 betti_display(o, a);
2004 // o << "--- The number of pairs left to compute ------------------------" <<
2005 // newline;
2006 // a.shrink(0);
2007 // betti_remaining(a);
2008 // betti_display(o, a);
2009 o << "--- (Lower bounds of) the minimal betti numbers ----------" << newline;
2010 a = betti_minimal();
2011 betti_display(o, a);
2012 if (M2_gbTrace >= 1)
2013 {
2014 o << "-- #Reduction steps = " << total_reduce_count << "--"
2015 << " ones " << n_ones << " unique " << n_unique << " others "
2016 << n_others << " ----" << newline;
2017 o << "--- Number of monomials ---------------------------------"
2018 << newline;
2019 a = betti_nmonoms();
2020 betti_display(o, a);
2021 }
2022
2023 // If the printlevel is high enough, display each element
2024 if (M2_gbTrace >= 2)
2025 for (int lev = 0; lev < resn.size(); lev++)
2026 {
2027 if (resn[lev]->pairs == nullptr) continue;
2028 o << "---- level " << lev << " ----" << newline;
2029 for (res2_pair *p = resn[lev]->pairs; p != nullptr; p = p->next)
2030 text_out(o, p);
2031 }
2032}
2033
2035{
2037 result = P->make_Schreyer_FreeModule();
2038 if (i < 0 || i >= resn.size()) return result;
2039
2040 auto D = get_ring()->degree_monoid();
2041 monomial deg = D->make_one();
2042 int n = 0;
2043 for (res2_pair *p = resn[i]->pairs; p != nullptr; p = p->next)
2044 {
2045 multi_degree(p, deg);
2046 result->append_schreyer(deg, p->syz->monom, p->compare_num);
2047 p->me = n++;
2048 }
2049 D->remove(deg);
2050 return result;
2051}
2053{
2055 result = P->make_Schreyer_FreeModule();
2056 if (i < 0 || i >= resn.size() - 1) return result;
2057 if (do_by_level > 0) return free_of(i);
2058
2059 auto D = get_ring()->degree_monoid();
2060 monomial deg = D->make_one();
2061 int n = 0;
2062 for (res2_pair *p = resn[i]->pairs; p != nullptr; p = p->next)
2063 if (p->syz_type == SYZ2_MINIMAL)
2064 {
2065 multi_degree(p, deg);
2066 result->append_schreyer(deg, p->syz->monom, p->compare_num);
2067 p->me = n++;
2068 }
2069 D->remove(deg);
2070 return result;
2071}
2072
2073Matrix *res2_comp::make(int level) const
2074{
2075 const FreeModule *F = free_of(level - 1);
2076 const FreeModule *G = free_of(level);
2077 MatrixConstructor result(F, G, nullptr);
2078 // Matrix *result = new Matrix(free_of(level-1), free_of(level));
2079
2080 int n = 0;
2081 if (G->rank() == 0) return result.to_matrix();
2082 for (res2_pair *p = resn[level]->pairs; p != nullptr; p = p->next)
2083 result.set_column(n++, R->to_vector(p->syz, F));
2084 return result.to_matrix();
2085}
2086
2088// Minimal resolutions //////////////////////
2090
2092 res2term *&f,
2093 VECTOR(res2_pair *)& elems,
2094 VECTOR(res2term *)& stripped) const
2095{
2096 // Reduce any components of 'f' that correspond to non minimal syzygies.
2097 monomial MINIMAL_mon = ALLOCATE_MONOMIAL(monom_size);
2098 const res2term *tm;
2099
2100 for (int i = x - 1; i >= 0; i--)
2101 {
2102 res2_pair *p = elems[i];
2103 if (p->syz_type == SYZ2_NOT_MINIMAL)
2104 while ((tm = R->component_occurs_in(p->pivot_term->comp, f)) != nullptr)
2105 {
2106 // Subtract the proper multiple to f. f = ... + c m e_y + ...
2107 // and p = ... + d n e_y
2108 // where n|m. So we want to compute f -= c/d m/n p.
2109 ring_elem c =
2110 K->divide(tm->coeff, p->pivot_term->coeff); // exact division
2111 // MES: is the following line actually needed?
2112 M->divide(tm->monom, p->pivot_term->monom, MINIMAL_mon);
2113 if (stripped[p->me] == nullptr) stripped[p->me] = R->strip(p->syz);
2114 R->subtract_multiple_to(f, c, MINIMAL_mon, stripped[p->me]);
2115 }
2116 }
2117}
2118
2120{
2121 const FreeModule *F = minimal_free_of(i - 1);
2122 const FreeModule *G = minimal_free_of(i);
2123 MatrixConstructor result(F, G, nullptr);
2124 if (i <= 0 || i >= resn.size() - 1) return result.to_matrix();
2125 if (do_by_level > 0) return make(i);
2126
2127 VECTOR(res2_pair *) elems;
2128 VECTOR(res2term *) stripped;
2129
2130 int n = 0;
2131 for (res2_pair *p = resn[i]->pairs; p != nullptr; p = p->next)
2132 {
2133 p->me = n++;
2134 elems.push_back(p);
2135 stripped.push_back(static_cast<res2term *>(nullptr));
2136 }
2137
2138 int thisx = 0;
2139 for (int x = 0; x < elems.size(); x++)
2140 {
2141 res2_pair *p = elems[x];
2142 if (p->syz_type == SYZ2_MINIMAL)
2143 {
2144 if (stripped[p->me] == nullptr)
2145 {
2146 stripped[p->me] = R->strip(p->syz);
2147 reduce_minimal(x, stripped[p->me], elems, stripped);
2148 }
2149 result.set_column(thisx++, R->to_vector(stripped[p->me], F, 1));
2150 }
2151 }
2152
2153 return result.to_matrix();
2154}
2155
2157// Minimalization routines //
2159
2161// pivot -- apply a specific pivot to the resolution //
2162// //
2163// modifies the resolution //
2165
2166#if 0
2167// Matrix res2_comp::reduce_mod_vars(int level) const
2168// {
2169// // Set all variables to 0, but only take columns marked
2170// // as SZ or GB, not NO. The matrix returned is over K.
2171//
2172// // Set 'me' values for level 'level' and 'level-1'.
2173//
2174// FreeModule *rows = K->make_FreeModule();
2175// FreeModule *cols = K->make_FreeModule();
2176// Matrix result(rows, cols);
2177// for (res_pair *p = resn[level]->pairs; p != NULL; p = p->next)
2178// {
2179// if (p->syz_type == SYZ2_MINIMAL || SYZ2_NOT_MINIMAL)
2180// {
2181// result[next++] = reduce_mod_vars(result.rows(), p->syz);
2182// }
2183// }
2184// return result;
2185// }
2186// void res2_comp::set_pivots(int level)
2187// {
2188// // Determines the status of each element (SZ, GB, NO)
2189// // (given the status of each element of higher level).
2190// // Also this sets the pivot_term of each element at this level
2191//
2192// // m = reduce_mod_vars(level)
2193// // now reduce this matrix, using change of basis.
2194// // for each column of this matrix, we will set a column to SYZ2_NOT_MINIMAL,
2195// // a row to SYZ2_NOT_NEEDED, and the columns pivot_term to the chosen pivot.
2196// }
2197//
2198// void res2_comp::pivot(int level, int r, int c)
2199// {
2200// res2_pair *p;
2201//
2202// // First find the specific pivot column
2203// for (p = resn[level]->pairs; p!=NULL; p=p->next)
2204// if (p->me == c)
2205// {
2206// pivot_pair = p;
2207// break;
2208// }
2209//
2210// // Now find the pivot ring element
2211// term head;
2212// term *f = &head;
2213// for (tm = pivot_pair->syz; tm != NULL; tm=tm->next)
2214// {
2215// if (tm->comp->me == r)
2216// {
2217// pivot_row = tm->comp;
2218//
2219// // Grab this element
2220// f->next = P->term(tm->coeff, tm->monom);
2221// f = f->next;
2222// M->divide(f->monom, pivot_row->syz->monom, f->monom);
2223// }
2224// }
2225// f->next = NULL;
2226// f = head.next;
2227//
2228// // Now loop through the columns of the level th matrix,
2229// // replacing each column (other than column c) with
2230// // elem(level,i) = f*elem(level,i) - c*v,
2231// // where c = elem(level,r,i).
2232// for (res2_pair *p = resn[level]->pairs; p!=NULL; p=p->next)
2233// {
2234// if (p == pivot_pair) continue;
2235// res2term *w = p->syz;
2236// if (R->get_coefficient(w, pivot_row, g))
2237// {
2238// P->negate_to(g);
2239// res2term *h1 = R->mult(f,w);
2240// res2term *h2 = R->mult(g,pivot_pair->syz);
2241// R->add_to(h1,h2);
2242// P->remove(g);
2243// R->remove(p->syz);
2244// p->syz = h1;
2245// }
2246// }
2247//
2248// // Remove every occurrence of row 'c' in level 'level+1'.
2249// // We save these up, to remove all at once, using 'strip_matrix'.
2250// pivot_pair->syz_type = SYZ2_NOT_MINIMAL;
2251// pivot_row->syz_type = SYZ2_NOT_NEEDED;
2252//
2253// // We will never use this column again, so remove it:
2254// R->remove(pivot_pair->syz);
2255// pivot_pair->syz = NULL; // This is a bit dangerous, since
2256// // many routines use this as if it must be nonNULL...
2257// }
2258//
2259// void res2_comp::strip_matrix(int level)
2260// {
2261// // Remove all rows which are marked as SYZ2_NOT_MINIMAL
2262// for (res2_pair *p = resn[level]->pairs; p != NULL; p=p->next)
2263// {
2264// res2term *f = strip(p->syz);
2265// R->remove(p->syz);
2266// p->syz = f;
2267// }
2268// }
2269#endif
2270
2271// Local Variables:
2272// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
2273// indent-tabs-mode: nil
2274// End:
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
BettiDisplay — engine-side container and renderer for the Betti table of a free resolution.
Append-only GC-backed byte buffer used throughout the engine for text output.
M2_arrayint getBetti() const
Definition betti.cpp:82
int & entry(int deg, int lev)
Definition betti.cpp:71
Engine-side Betti table: a (degree, homological level) rectangle of integers.
Definition betti.hpp:60
enum ComputationStatusCode status() const
Definition comp.hpp:100
enum ComputationStatusCode set_status(enum ComputationStatusCode)
Definition comp.cpp:66
StopConditions stop_
Definition comp.hpp:75
static void quotient(ConstExponents a, ConstExponents b, Vector &result)
static bool is_equal(ConstExponents a, ConstExponents b)
static void to_expvector(int n, ConstExponents a, exponents::Exponents result)
static void var(Exponent v, Exponent e, Vector &result)
static Exponent weight(int nvars, ConstExponents a, const std::vector< Exponent > &wts)
int primary_degree(int i) const
Definition freemod.cpp:440
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
const Ring * get_ring() const
Definition matrix.hpp:134
int n_cols() const
Definition matrix.hpp:147
int n_rows() const
Definition matrix.hpp:146
const FreeModule * rows() const
Definition matrix.hpp:144
const FreeModule * cols() const
Definition matrix.hpp:145
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
void mult(const_monomial m, const_monomial n, monomial result) const
Definition monoid.cpp:363
void insert_minimal(Bag *b)
Definition monideal.hpp:333
void debug_out(int disp=1) const
Definition monideal.cpp:508
void find_all_divisors(const_exponents exp, VECTOR(Bag *)&b) const
Definition monideal.cpp:246
int size() const
Definition monideal.hpp:186
Engine-side monomial ideal: a decision tree of Nmi_nodes storing the (typically minimal) generators b...
Definition monideal.hpp:136
Internal tree node of the MonomialIdeal decision tree.
Definition monideal.hpp:74
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
static void betti_display(buffer &o, M2_arrayint a)
Definition comp-res.cpp:207
static void betti_init(int lo, int hi, int len, int *&bettis)
Definition comp-res.cpp:151
static M2_arrayint betti_make(int lo, int hi, int len, int *bettis)
Definition comp-res.cpp:157
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
const Monoid * degree_monoid() const
Definition ring.cpp:13
char * str()
Definition buffer.hpp:72
void add(VECTYPE p)
Definition geobucket.hpp:99
VECTYPE remove_lead_term()
int basis_elem() const
Definition int-bag.hpp:66
gc_vector< int > & monom()
Definition int-bag.hpp:60
size_t exp_size
Definition res-a0.hpp:192
int total_reduce_count
Definition res-a0.hpp:184
int skeleton_sort
Definition res-a0.hpp:167
int compare_use_degree
Definition res-a0.hpp:197
int next_component
Definition res-a0.hpp:163
res2_pair * reduce(res2term *&f, res2term *&fsyz, res2term *&pivot, res2_pair *p)
Definition res-a0.cpp:1126
int max_mon_degree
Definition res-a0.hpp:159
int compare_res2_pairs(res2_pair *f, res2_pair *g) const
Definition res-a0.cpp:714
unsigned char do_by_degree
Definition res-a0.hpp:175
int hidegree
Definition res-a0.hpp:138
void remove_res2_pair(res2_pair *p)
Definition res-a0.cpp:570
void remove_res2_level(res2_level *lev)
Definition res-a0.cpp:578
int projdim
Definition res-a0.hpp:155
res2_pair * new_res2_pair(int i)
Definition res-a0.cpp:646
FreeModule * free_of(int i) const
Definition res-a0.cpp:2034
size_t monom_size
Definition res-a0.hpp:193
const Ring * get_ring() const
Definition res-a0.hpp:357
stash * mi_stash
Definition res-a0.hpp:130
res2_poly * R
Definition res-a0.hpp:123
const Monoid * M
Definition res-a0.hpp:124
int complete_thru_degree() const
Definition res-a0.cpp:24
int auto_reduce
Definition res-a0.hpp:178
void sort_res2_pairs(res2_pair *&p) const
Definition res-a0.cpp:891
res2term * s_pair(res2term *fsyz) const
Definition res-a0.cpp:1110
int n_others
Definition res-a0.hpp:189
enum ComputationStatusCode do_pairs_by_degree(int level, int degree)
Definition res-a0.cpp:214
void handle_pair_by_level(res2_pair *p)
Definition res-a0.cpp:1727
void new_pairs(res2_pair *p)
Definition res-a0.cpp:951
int compare_use_descending
Definition res-a0.hpp:198
const PolynomialRing * P
Definition res-a0.hpp:122
res2_pair * reduce_heap_by_level(res2term *&f, res2term *&fsyz)
Definition res-a0.cpp:1554
enum ComputationStatusCode do_pairs_by_level(int level)
Definition res-a0.cpp:151
res2_pair * reduce4(res2term *&f, res2term *&fsyz, res2term *&pivot, res2_pair *p)
Definition res-a0.cpp:1402
Matrix * make(int i) const
Definition res-a0.cpp:2073
void text_out(const res2_pair *p) const
Definition res-a0.cpp:1919
const Matrix * generator_matrix
Definition res-a0.hpp:127
int length_limit
Definition res-a0.hpp:147
res2_pair * new_base_res2_pair(int i)
Definition res-a0.cpp:627
void increase_level(int newmax)
Definition res-a0.cpp:75
void insert_pair(res2_pair *p)
Definition res-a0.cpp:663
int nminimal
Definition res-a0.hpp:183
int npairs
Definition res-a0.hpp:182
void handle_pair(res2_pair *p)
Definition res-a0.cpp:1647
FreeModule * minimal_free_of(int i) const
Definition res-a0.cpp:2052
M2_arrayint get_betti(int type) const
Definition res-a0.cpp:1897
void sort_reduction(res2_pair *&p)
Definition res-a0.cpp:931
int find_ring_divisor(const int *exp, ring_elem &result) const
Definition res-a0.cpp:1048
void initialize(const Matrix *mat, int LengthLimit, bool UseDegreeLimit, int SlantedDegreeLimit, int SortStrategy)
Definition res-a0.cpp:420
virtual ~res2_comp()
Definition res-a0.cpp:590
void display_order(buffer &o, int sortval) const
Definition res-a0.cpp:530
void sort_skeleton(res2_pair *&p)
Definition res-a0.cpp:916
res2_pair * reduce3(res2term *&f, res2term *&fsyz, res2term *&pivot, res2_pair *p)
Definition res-a0.cpp:1308
int find_divisor(const MonomialIdeal *mi, const int *exp, res2_pair *&result)
Definition res-a0.cpp:1060
int reduction_sort
Definition res-a0.hpp:169
M2_arrayint betti_skeleton() const
Definition res-a0.cpp:1816
int compare_type
Definition res-a0.hpp:196
int sort_value(res2_pair *p, const std::vector< int > sort_order) const
Definition res-a0.cpp:940
int n_unique
Definition res-a0.hpp:188
void do_auto_reductions(res2_pair *p, auto_reduce_node *au)
Definition res-a0.cpp:1621
unsigned char use_respolyHeaps
Definition res-a0.hpp:177
void stats() const
Definition res-a0.cpp:1991
res2_pair * reduce_by_level(res2term *&f, res2term *&fsyz)
Definition res-a0.cpp:1497
int nleft
Definition res-a0.hpp:181
int lodegree
Definition res-a0.hpp:137
M2_arrayint betti_remaining() const
Definition res-a0.cpp:1834
res2_pair * reduce2(res2term *&f, res2term *&fsyz, res2term *&pivot, res2_pair *p)
Definition res-a0.cpp:1200
int compare_use_reverse
Definition res-a0.hpp:199
int hard_degree_limit
Definition res-a0.hpp:139
void reduce_minimal(int x, res2term *&f, VECTOR(res2_pair *)&elems, VECTOR(res2term *)&stripped) const
Definition res-a0.cpp:2091
bool have_degree_limit
Definition res-a0.hpp:143
res2_comp(const Matrix *m, int LengthLimit, bool UseDegreeLimit, int SlantedDegreeLimit, int SortStrategy)
Definition res-a0.cpp:561
enum ComputationStatusCode do_pairs(int level, int degree)
Definition res-a0.cpp:109
void handle_pair_by_degree(res2_pair *p)
Definition res-a0.cpp:1767
enum ComputationStatusCode skeleton(int level)
Definition res-a0.cpp:40
stash * res2_pair_stash
Definition res-a0.hpp:129
const Ring * K
Definition res-a0.hpp:125
unsigned char do_by_level
Definition res-a0.hpp:173
void multi_degree(const res2_pair *q, int *result) const
Definition res-a0.cpp:701
enum ComputationStatusCode do_all_pairs(int level, int degree)
Definition res-a0.cpp:92
M2_arrayint betti_minimal() const
Definition res-a0.cpp:1855
bool stop_conditions_ok()
Definition res-a0.cpp:15
M2_arrayint betti_nmonoms() const
Definition res-a0.cpp:1877
res2_pair * merge_res2_pairs(res2_pair *f, res2_pair *g) const
Definition res-a0.cpp:857
int n_ones
Definition res-a0.hpp:187
Matrix * make_minimal(int i) const
Definition res-a0.cpp:2119
void sort_monorder(res2_pair *&p)
Definition res-a0.cpp:924
void start_computation()
Definition res-a0.cpp:266
Definition mem.hpp:78
ComputationStatusCode
Definition computation.h:53
@ COMP_DONE_PAIR_LIMIT
Definition computation.h:64
@ COMP_DONE
Definition computation.h:60
@ COMP_DONE_DEGREE_LIMIT
Definition computation.h:61
@ COMP_DONE_SYZYGY_LIMIT
Definition computation.h:63
@ COMP_COMPUTING
Definition computation.h:71
@ COMP_INTERRUPTED
Definition computation.h:57
#define Matrix
Definition factory.cpp:14
#define monomial
Definition gb-toric.cpp:11
geobucket<FREEMODULETYPE, VECTYPE> — size-quadrupling bucket accumulator for fast polynomial sums.
int p
int p1
int_bag Bag
Definition int-bag.hpp:70
bool system_interrupted()
system_interrupted() — thread-safe polling predicate for Ctrl+C handling.
void freemem(void *s)
Definition m2-mem.cpp:103
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
int M2_gbTrace
Definition m2-types.cpp:52
MatrixConstructor — the mutable builder that produces an immutable Matrix.
#define MONOMIAL_BYTE_SIZE(mon_size)
Definition monoid.hpp:66
#define ALLOCATE_EXPONENTS(byte_len)
Definition monoid.hpp:62
#define EXPONENT_BYTE_SIZE(nvars)
Definition monoid.hpp:63
#define ALLOCATE_MONOMIAL(byte_len)
Definition monoid.hpp:65
typename std::vector< T, gc_allocator< T > > gc_vector
a version of the STL vector, which allocates its backing memory with gc.
Definition newdelete.hpp:76
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
static gmp_randstate_t state
Definition random.cpp:18
@ SYZ2_MAYBE_MINIMAL
@ SYZ2_NOT_NEEDED
@ SYZ2_NOT_MINIMAL
@ SYZ2_S_PAIR
@ SYZ2_MINIMAL
#define DO(CALL)
Definition res-a0.cpp:256
geobucket< const res2_poly, res2term * > respolyHeap
Definition res-a0.cpp:13
const int COMPARE_MONORDER
Definition res-a0.hpp:82
const int COMPARE_LEX
Definition res-a0.hpp:78
const int COMPUTE_RES
Definition res-a0.hpp:87
const int COMPARE_LEX_EXTENDED
Definition res-a0.hpp:79
@ RES_REDUCTIONS
Definition res-a0.hpp:55
@ RES_MONORDER
Definition res-a0.hpp:51
@ RES_SKELETON
Definition res-a0.hpp:49
const int SHIFT_AUTO
Definition res-a0.hpp:68
const int COMPUTE_MONOMIAL_RES
Definition res-a0.hpp:86
const int COMPUTE_SKELETON
Definition res-a0.hpp:84
const int COMPARE_LEX_EXTENDED2
Definition res-a0.hpp:80
const int FLAGS_DEGREE
Definition res-a0.hpp:65
const int FLAGS_DESCEND
Definition res-a0.hpp:63
const int FLAGS_GEO
Definition res-a0.hpp:69
const int FLAGS_SORT
Definition res-a0.hpp:62
const int FLAGS_DEGREELEVEL
Definition res-a0.hpp:70
const int FLAGS_LEVEL_STRIP
Definition res-a0.hpp:71
const int COMPARE_ORDER
Definition res-a0.hpp:81
const int FLAGS_REVERSE
Definition res-a0.hpp:64
const int FLAGS_AUTO
Definition res-a0.hpp:67
const int FLAGS_LEVEL
Definition res-a0.hpp:66
res2_comp — original (1996) free-resolution engine using explicit pair processing.
tbb::flow::graph G
Nterm * next
Definition ringelem.hpp:157
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
res2term * pivot
Definition res-a0.hpp:92
auto_reduce_node * next
Definition res-a0.hpp:91
res2_pair * p
Definition res-a0.hpp:93
res2_pair * pairs
Definition res-a0.hpp:99
unsigned short degree
unsigned int me
unsigned char level
MonomialIdeal * mi
res2term * syz
res2_pair * next
res2term * pivot_term
unsigned int compare_num
unsigned char syz_type
res2term * next
res2_pair * comp
ring_elem coeff
int monom[1]
void emit_wrapped(const char *s)
Definition text-io.cpp:27
void emit(const char *s)
Definition text-io.cpp:41
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.