Macaulay2 Engine
Loading...
Searching...
No Matches
res-a1.cpp
Go to the documentation of this file.
1// Copyright 1996. Michael E. Stillman
2
3#include "res-a1.hpp"
4
5#include "ExponentVector.hpp"
6#include "res-a1-poly.hpp"
7#include "text-io.hpp"
8#include "interrupted.hpp"
9
11// Initialization of a computation /////////
13
14void res_comp::initialize(const Matrix *mat, int LengthLimit, int /*strategy*/)
15{
16 int i;
17
19 assert(P != NULL);
20 R = new res_poly(const_cast<PolynomialRing *>(P));
21 M = P->getMonoid();
22 K = P->getCoefficientRing();
23 generator_matrix = mat;
24
25 // These next two lines may be added next (5/2/06)
26 // res_degree_stash = new stash("resDegree", sizeof(res_degree));
27 // res_level_stash = new stash("resLevel", sizeof(res_level));
28 res_pair_stash = new stash("respair", sizeof(res_pair));
29 mi_stash = new stash("res minodes", sizeof(Nmi_node));
30
31 for (i = 0; i <= LengthLimit; i++) resn.push_back(new res_level);
32
33 max_degree = M->max_degree();
34 length_limit = LengthLimit;
35 if (mat->n_rows() > 0)
36 {
37 lodegree = mat->rows()->primary_degree(0);
38 for (i = 1; i < mat->n_rows(); i++)
39 if (lodegree > mat->rows()->primary_degree(i))
40 lodegree = mat->rows()->primary_degree(i);
41 }
42 else
43 lodegree = 0;
44
45 for (i = 0; i < mat->n_cols(); i++)
46 if (lodegree > mat->cols()->primary_degree(i) - 1)
47 lodegree = mat->cols()->primary_degree(i) - 1;
48
50 n_level = 2;
52
55 const SchreyerOrder *S = mat->rows()->get_schreyer_order();
56 for (i = 0; i < mat->n_rows(); i++)
57 {
59
60 p->me = component_number++;
61 p->minimal_me = p->me;
62 next_me_number++; // this and 'component_number' should still be equal
63 // here.
64 p->compare_num = i;
65
66 if (S == nullptr)
67 p->base_monom = M->make_one();
68 else
69 p->base_monom = M->make_new(S->base_monom(i));
70 p->mi = new MonomialIdeal(P, mi_stash);
71 p->syz_type = SYZ_MINIMAL;
72 p->base_comp = p;
73 base_components.push_back(p);
74 search_mi.push_back(new MonomialIdeal(P, mi_stash));
75
76 int d = mat->rows()->primary_degree(i);
77 res_degree *mypairs = make_degree_set(0, d);
78 p->next = mypairs->first;
79 mypairs->first = p;
80 mypairs->npairs++;
81 resn[0]->npairs++;
82 npairs++;
83 }
84
85 nleft = 0;
86 npairs = 0;
87 nminimal = 0;
88
89 for (i = 0; i < mat->n_cols(); i++)
90 if ((*mat)[i] != nullptr)
91 {
92 res_pair *p = new_res_pair(i); // Makes a generator 'pair'
93 int d = mat->cols()->primary_degree(i);
94 res_degree *mypairs = make_degree_set(1, d - 1);
95 p->next = mypairs->next_gen;
96 mypairs->next_gen = p;
97 mypairs->nleft++;
98 mypairs->npairs++;
99 resn[1]->nleft++;
100 resn[1]->npairs++;
101 nleft++;
102 npairs++;
103 }
104
105 for (i = 0; i < base_components.size(); i++)
106 {
107 res_pair *p = base_components[i];
108 p->compare_num = i;
109 }
110
111 exp_size = EXPONENT_BYTE_SIZE(P->n_vars());
112 monom_size = MONOMIAL_BYTE_SIZE(M->monomial_size());
113
114 compare_type = 0;
115}
116
117res_comp::res_comp(const Matrix *m, int LengthLimit, int strategy)
118{
119 initialize(m, LengthLimit, strategy);
120}
121
123{
124 int i;
125 for (i = 0; i < resn.size(); i++) remove_res_level(resn[i]);
126
127 for (i = 0; i < search_mi.size(); i++) delete search_mi[i];
128
129 delete res_pair_stash;
130 delete mi_stash;
131 delete R;
132
133 // base_components have all been removed by this point
134 // Since they appear in resn[0].
135}
136
138{
139 if (p == nullptr) return;
140 delete p->mi;
141 R->remove(p->syz);
142 R->remove(p->stripped_syz);
143 M->remove(p->base_monom);
144 res_pair_stash->delete_elem(p);
145}
146
148{
149 if (p == nullptr) return;
150 while (p->first != nullptr)
151 {
152 res_pair *tmp = p->first;
153 p->first = tmp->next;
154 remove_res_pair(tmp);
155 }
156 freemem(p);
157}
158
160{
161 if (lev == nullptr) return;
162 int i;
163 for (i = 0; i < lev->bin.size(); i++)
164 {
165 res_degree *mypairs = lev->bin[i];
166 remove_res_degree(mypairs);
167 }
168 freemem(lev);
169}
170
172// Data structure insertion and access /////
174
176// If there is such a res_degree, return it.
177// If not, first create it, and then return it.
178{
179 int i;
180 if (level >= resn.size())
181 {
182 // Create new res_levels
183 for (i = resn.size(); i <= level; i++) resn.push_back(new res_level);
184 }
185 res_level *lev = resn[level];
186
187 deg -= lodegree;
188 assert(deg >= 0); // This would be an internal error
189 if (deg >= lev->bin.size())
190 {
191 // Create new res_degrees
192 for (i = lev->bin.size(); i <= deg; i++)
193 lev->bin.push_back(new res_degree);
194 if (deg + lodegree > hidegree) hidegree = deg + lodegree;
195 }
196
197 return lev->bin[deg];
198}
199
200res_degree *res_comp::get_degree_set(int level, int d) const
201// find (level,d) pair set, where 'd' is the slanted degree
202{
203 if (level < 0 || level >= resn.size()) return nullptr;
204 res_level *lev = resn[level];
205 d -= lodegree;
206 if (d < 0 || d >= lev->bin.size()) return nullptr;
207 return lev->bin[d];
208}
209
211{
212 res_pair *result = reinterpret_cast<res_pair *>(res_pair_stash->new_elem());
213 result->me = 0;
214 result->compare_num = 0;
215 result->base_monom = nullptr;
216 result->next = nullptr;
217 result->first = nullptr;
218 result->second = nullptr;
219 result->base_comp = nullptr;
220 result->syz_type = 0;
221 result->mi2 = nullptr;
222 result->next_mi = nullptr;
223 result->syz = nullptr;
224 result->minimal_me = 0;
225 result->pivot_term = nullptr;
226 result->stripped_syz = nullptr;
227 return result;
228}
229
230res_pair *res_comp::new_res_pair(int syztype, res_pair *first, res_pair *second)
231{
233 result->me = component_number++;
234 result->base_monom = M->make_one();
235 result->first = first;
236 result->second = second;
237 result->base_comp = first->base_comp;
238 result->syz_type = syztype;
239 result->mi = new MonomialIdeal(P, mi_stash);
240 return result;
241}
242
244{
245 res_pair *p = new_res_pair(); // Fills in almost all fields
246 p->syz_type = SYZ_GEN;
247 p->me = component_number++;
248 p->compare_num = i;
249 p->syz = R->from_vector(base_components, (*generator_matrix)[i]);
250 p->base_monom = M->make_new(p->syz->monom);
251 p->base_comp = p->syz->comp;
252 p->first = p->base_comp;
253 p->mi = new MonomialIdeal(P, mi_stash);
254
255 return p;
256}
257
259{
260 // This is a level 1 pair.
261 res_pair *p = new_res_pair(); // Fills in almost all fields
262 p->me = component_number++;
263 p->syz_type = syztype;
264 p->syz = f;
265 p->base_monom = M->make_new(f->monom);
266 p->base_comp = f->comp->base_comp;
267 p->first = f->comp;
268 p->mi = new MonomialIdeal(P, mi_stash);
269
270 return p;
271}
272
273int res_comp::degree(const res_pair *p) const
274{
275 int result = M->primary_degree(p->base_monom);
276 result += generator_matrix->rows()->primary_degree(p->base_comp->me);
277 return result;
278}
279
281{
282 // MES: Is this correct?
283 M->multi_degree(p->base_monom, deg);
284 M->degree_monoid()->mult(
285 deg, generator_matrix->rows()->degree(p->base_comp->me), deg);
286}
287
289{
290 // First determine the degree of 'p':
291 int deg = degree(p) - level;
292
293 res_degree *mypairs = make_degree_set(level, deg);
294 p->next = mypairs->first;
295 mypairs->first = p;
296
297 if (level > 1)
298 {
299 resn[level]->npairs++;
300 resn[level]->nleft++;
301 mypairs->nleft++;
302 mypairs->npairs++;
303 npairs++;
304 nleft++;
305 }
306 else
307 {
309 M->to_varpower(p->syz->monom, vp);
310 search_mi[p->syz->comp->me]->insert_minimal(new Bag(p, vp));
311 }
312}
313
315// Sorting //////////////////////////////////
317
319{
320 exponents_t EXP1, EXP2;
321 int cmp, df, dg, i;
322 // if (f->compare_num < g->compare_num) return 1;
323 // if (f->compare_num > g->compare_num) return -1;
324 // MES: what to do if we obtain equality? Here is one way:
325 switch (compare_type)
326 {
327 case 1:
328 // Compare using descending lexicographic order
329 // on the usual set of variables
332 M->to_expvector(f->base_monom, EXP1);
333 M->to_expvector(g->base_monom, EXP2);
334 for (i = 0; i < M->n_vars(); i++)
335 {
336 if (EXP1[i] < EXP2[i]) return -1;
337 if (EXP1[i] > EXP2[i]) return 1;
338 }
339 return 0;
340 case 2:
341 // Compare using ascending lexicographic order
342 // on the usual set of variables
345 M->to_expvector(f->base_monom, EXP1);
346 M->to_expvector(g->base_monom, EXP2);
347 for (i = 0; i < M->n_vars(); i++)
348 {
349 if (EXP1[i] < EXP2[i]) return 1;
350 if (EXP1[i] > EXP2[i]) return -1;
351 }
352 return 0;
353 case 3:
354 // Compare using descending lexicographic order
355 // on the reversed set of variables
358 M->to_expvector(f->base_monom, EXP1);
359 M->to_expvector(g->base_monom, EXP2);
360 for (i = M->n_vars() - 1; i >= 0; i--)
361 {
362 if (EXP1[i] < EXP2[i]) return -1;
363 if (EXP1[i] > EXP2[i]) return 1;
364 }
365 return 0;
366 case 4:
367 // Compare using ascending lexicographic order
368 // on the reversed set of variables
371 M->to_expvector(f->base_monom, EXP1);
372 M->to_expvector(g->base_monom, EXP2);
373 for (i = M->n_vars() - 1; i >= 0; i--)
374 {
375 if (EXP1[i] < EXP2[i]) return 1;
376 if (EXP1[i] > EXP2[i]) return -1;
377 }
378 return 0;
379 case 5:
380 // The original method, but with degree added, since
381 // the new skeleton code doesn't just sort elements of
382 // the same degree.
383 df = degree(f);
384 dg = degree(g);
385 if (df > dg) return -1;
386 if (df < dg) return 1;
387 cmp = M->compare(f->base_monom, g->base_monom);
388 if (cmp != 0) return cmp;
389 cmp = f->first->compare_num - g->first->compare_num;
390 if (cmp < 0) return 1;
391 if (cmp > 0) return -1;
392 return 0;
393 default:
394 cmp = M->compare(f->base_monom, g->base_monom);
395 if (cmp != 0) return cmp;
396 cmp = f->first->compare_num - g->first->compare_num;
397 if (cmp < 0) return 1;
398 if (cmp > 0) return -1;
399 return 0;
400 }
401 return 0;
402}
403
405{
406 if (g == nullptr) return f;
407 if (f == nullptr) return g;
408 res_pair head;
409 res_pair *result = &head;
410 while (1) switch (compare_res_pairs(f, g))
411 {
412 case 0:
413 case -1:
414 result->next = g;
415 result = result->next;
416 g = g->next;
417 if (g == nullptr)
418 {
419 result->next = f;
420 return head.next;
421 }
422 break;
423 case 1:
424 result->next = f;
425 result = result->next;
426 f = f->next;
427 if (f == nullptr)
428 {
429 result->next = g;
430 return head.next;
431 }
432 break;
433 // case 0:
434 // assert(0);
435 }
436}
437
439{
440 // These elements are sorted in ascending 'me' values
441 if (p == nullptr || p->next == nullptr) return;
442 res_pair *p1 = nullptr;
443 res_pair *p2 = nullptr;
444 while (p != nullptr)
445 {
446 res_pair *tmp = p;
447 p = p->next;
448 tmp->next = p1;
449 p1 = tmp;
450
451 if (p == nullptr) break;
452 tmp = p;
453 p = p->next;
454 tmp->next = p2;
455 p2 = tmp;
456 }
457
459 sort_res_pairs(p2);
460 p = merge_res_pairs(p1, p2);
461}
462
463int res_comp::sort_value(res_pair *p, const std::vector<int> sort_order) const
464{
466 M->to_expvector(p->base_monom, REDUCE_exp);
467 return exponents::weight(P->n_vars(), REDUCE_exp, sort_order);
468}
469
471{
472 if (mypairs == nullptr) return;
473 res_pair *p = mypairs->next_gen;
474 if (p == nullptr || p->next == nullptr) return;
475 // for (res_pair *q = p; q!=NULL; q=q->next)
476 // q->compare_num = sort_value(q, s_pair_order); // MES: to be written
477
478 sort_res_pairs(mypairs->next_gen);
479}
480
481void res_comp::sort_pairs(int level, int deg)
482{
483 res_degree *mypairs = get_degree_set(level, deg);
484 if (mypairs == nullptr) return;
485 if (mypairs->is_sorted) return;
486 res_pair *p = mypairs->first;
487 if (p != nullptr && p->next != nullptr) sort_res_pairs(mypairs->first);
488
489 mypairs->next_pair = mypairs->first;
490 mypairs->next_new_pair = mypairs->first;
491 mypairs->is_sorted = 1;
492
493 set_compare_nums(level, deg);
494}
495
497// Sorting Compare nums /////////////////////
499
501{
502 int cmp = f->first->compare_num - g->first->compare_num;
503 if (cmp < 0) return 1;
504 if (cmp > 0) return -1;
505 cmp = f->me - g->me;
506 if (cmp < 0) return 1;
507 if (cmp > 0) return -1;
508 return 0;
509}
510
512{
513 if (g == nullptr) return f;
514 if (f == nullptr) return g;
515 res_pair head;
516 res_pair *result = &head;
517 while (1) switch (compare_compares(f, g))
518 {
519 case -1:
520 result->next_compare = g;
521 result = result->next_compare;
522 g = g->next_compare;
523 if (g == nullptr)
524 {
525 result->next_compare = f;
526 return head.next_compare;
527 }
528 break;
529 case 1:
530 result->next_compare = f;
531 result = result->next_compare;
532 f = f->next_compare;
533 if (f == nullptr)
534 {
535 result->next_compare = g;
536 return head.next_compare;
537 }
538 break;
539 case 0:
540 assert(0);
541 }
542}
543
545{
546 // These elements are sorted in ascending 'me' values
547 if (p == nullptr || p->next_compare == nullptr) return;
548 res_pair *p1 = nullptr;
549 res_pair *p2 = nullptr;
550 while (p != nullptr)
551 {
552 res_pair *tmp = p;
553 p = p->next_compare;
554 tmp->next_compare = p1;
555 p1 = tmp;
556
557 if (p == nullptr) break;
558 tmp = p;
559 p = p->next_compare;
560 tmp->next_compare = p2;
561 p2 = tmp;
562 }
563
565 sort_compares(p2);
566 p = merge_compares(p1, p2);
567}
568
569void res_comp::set_compare_nums(int level, int deg)
570// Set ALL of the compare_num fields at this level.
571// This will possibly change previous compare_num fields,
572// but that should not (!) affect the monomial order...
573{
574 if (level == 0) return;
575
576 // This assumes that the pairs at level 'level' are ordered already
577 // and that all previous pairs at this level (i.e. of lower degree)
578 // are sorted on the 'next_compare' field, in ascending order
579
580 // First, place the new pairs onto a 'next_compare' list, sort, and then merge
581 // them into the previous list, using (first->compare_num, me) in ascending
582 // order.
583
584 res_degree *mypairs = get_degree_set(level, deg);
585 if (mypairs == nullptr) return;
586
587 res_pair *p;
588 res_pair *compare_num_list = mypairs->first;
589 for (p = mypairs->first; p != nullptr; p = p->next)
590 {
591 p->next_compare = p->next;
592 p->me = next_me_number++;
593 }
594 sort_compares(compare_num_list);
595 resn[level]->compare_num_list =
596 merge_compares(resn[level]->compare_num_list, compare_num_list);
597
598 int next = 0;
599 for (p = resn[level]->compare_num_list; p != nullptr; p = p->next_compare)
600 p->compare_num = next++;
601}
602
603// Creation of new pairs ////////////////////
605
607// Create and insert all of the pairs which will have lead term 'p'.
608// This also places 'p' into the appropriate monomial ideal
609
610// Assumption: 'p' lies in a sorted list among its own degree/level
611// and only pairs with elements before this in the sorting order
612// will be considered.
613{
614 gc_vector<Bag*> elems;
615 gc_vector<int> vp; // This is 'p'.
616 gc_vector<int> thisvp;
617
619
620 if (M2_gbTrace >= 10)
621 {
622 buffer o;
623 o << "Computing pairs with first = " << p->me << newline;
624 emit(o.str());
625 }
626 M->divide(p->base_monom, p->first->base_monom, PAIRS_mon);
627 M->to_varpower(PAIRS_mon, vp);
628
629 // First add in syzygies arising from exterior variables
630 // At the moment, there are none of this sort.
631
632 if (P->is_skew_commutative())
633 {
634 exponents_t exp = newarray_atomic(int, M->n_vars());
635 varpower::to_expvector(M->n_vars(), vp.data(), exp);
636
637 int nskew = P->n_skew_commutative_vars();
638 for (int v = 0; v < nskew; v++)
639 {
640 int w = P->skew_variable(v);
641 if (exp[w] > 0)
642 {
643 thisvp.resize(0);
644 varpower::var(w, 1, thisvp);
645 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
646 elems.push_back(b);
647 }
648 }
649 freemem(exp);
650 }
651
652 // Second, add in syzygies arising from the base ring, if any
653 // The baggage of each of these is NULL
654 if (P->is_quotient_ring())
655 {
656 const MonomialIdeal *Rideal = P->get_quotient_monomials();
657 for (Bag& a : *Rideal)
658 {
659 // Compute (P->quotient_ideal->monom : p->monom)
660 // and place this into a varpower and Bag, placing
661 // that into 'elems'
662 thisvp.resize(0);
663 varpower::quotient(a.monom().data(), vp.data(), thisvp);
664 if (varpower::is_equal(a.monom().data(), thisvp.data()))
665 continue;
666 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
667 elems.push_back(b);
668 }
669 }
670 // Third, add in syzygies arising from previous elements of this same level
671 // The baggage of each of these is their corresponding res_pair
672
673 MonomialIdeal *mi_orig = p->first->mi;
674 for (Bag& a : *mi_orig)
675 {
676 Bag *b = new Bag(a.basis_ptr());
677 varpower::quotient(a.monom().data(), vp.data(), b->monom());
678 elems.push_back(b);
679 }
680
681 // Make this monomial ideal, and then run through each minimal generator
682 // and insert into the proper degree. (Notice that sorting does not
683 // need to be done yet: only once that degree is about to begin.
684
685 mi_orig->insert_minimal(new Bag(p, vp));
686
687 VECTOR(Bag *) rejects;
688 MonomialIdeal *mi = new MonomialIdeal(P, elems, rejects, mi_stash);
689 for (auto& b : rejects)
690 delete b;
691
692 if (M2_gbTrace >= 11) mi->debug_out(1);
693
694 for (Bag& a : *mi)
695 {
696 res_pair *second = reinterpret_cast<res_pair *>(a.basis_ptr());
697 res_pair *q = new_res_pair(SYZ_S_PAIR, p, second);
698 // That set most fields except base_monom:
699 M->from_varpower(a.monom().data(), q->base_monom);
700 M->mult(q->base_monom, p->base_monom, q->base_monom);
702 }
703 delete mi;
704}
705
707// S-pairs and reduction ////////////////////
709
711// If 'exp' is divisible by a ring lead term, then 1 is returned,
712// and result is set to be that ring element.
713// Otherwise 0 is returned.
714{
715 if (!P->is_quotient_ring()) return 0;
716 Bag *b;
717 if (!P->get_quotient_monomials()->search_expvector(exp, b)) return 0;
718 result.poly_val = P->quotient_element(b->basis_elem());
719 return 1;
720}
721
723// This sets p->syz to be the one or two term syzygy, and
724// returns this value multiplied out.
725// Care is of course taken with the Schreyer order
726{
727 p->syz = R->new_term(K->from_long(1), p->base_monom, p->first);
728 monomial si = M->make_one();
729 M->divide(p->base_monom, p->first->base_monom, si);
730 resterm *result = R->mult_by_monomial(p->first->syz, si);
731 ring_elem one = K->from_long(1);
732 if (p->second != nullptr)
733 {
734 p->syz->next = R->new_term(K->from_long(-1), p->base_monom, p->second);
735 M->divide(p->base_monom, p->second->base_monom, si);
736 R->subtract_multiple_to(result, one, si, p->second->syz);
737 }
738 M->remove(si);
739 K->remove(one);
740 return result;
741}
742
744// Reduce f, placing the reduction history in fsyz.
745// Returns NULL if f reduces to 0, otherwise
746// returns the res_pair at the previous level (f will "fill in" that pair), and
747// place a pointer to the corresponding term in "pivot".
748{
749 // 'lastterm' is used to append the next monomial to fsyz->syz
752
753 resterm *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
754
755 res_pair *q;
756 ring_elem rg;
757 Bag *b;
758
759 while (f != nullptr)
760 {
761 M->divide(f->monom, f->comp->base_monom, REDUCE_mon);
762 M->to_expvector(REDUCE_mon, REDUCE_exp);
763 if (find_ring_divisor(REDUCE_exp, rg))
764 {
765 // Subtract off f, leave fsyz alone
766 Nterm *r = rg;
767 M->divide(f->monom, r->monom, REDUCE_mon);
768 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
769 }
770 else if (f->comp->mi->search_expvector(REDUCE_exp, b))
771 {
772 q = reinterpret_cast<res_pair *>(b->basis_ptr());
773 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
774 lastterm = lastterm->next;
775 pivot = lastterm;
776 if (q->syz_type == SYZ_S_PAIR) return q; // i.e. not computed yet
777 M->divide(f->monom, q->syz->monom, REDUCE_mon);
778 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->syz);
779 }
780 else
781 {
782 // level 1: monomial not seen yet
783 q = new_res_pair(SYZ_S_PAIR, f);
784 insert_res_pair(1, q);
785 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
786 lastterm = lastterm->next;
787 return q;
788 }
789 }
790 return nullptr;
791}
792
793// MES: Uugh.... This should not be a separate routine....?
794
796 resterm *&fsyz,
797 resterm *&pivot)
798{
799 // 'lastterm' is used to append the next monomial to fsyz->syz
802
803 resterm *lastterm = (fsyz->next == nullptr ? fsyz : fsyz->next);
804
805 res_pair *q;
806 ring_elem rg;
807 Bag *b;
808
809 while (f != nullptr)
810 {
811 M->divide(f->monom, f->comp->base_monom, REDUCE_mon);
812 M->to_expvector(REDUCE_mon, REDUCE_exp);
813 if (find_ring_divisor(REDUCE_exp, rg))
814 {
815 // Subtract off f, leave fsyz alone
816 Nterm *r = rg;
817 M->divide(f->monom, r->monom, REDUCE_mon);
818 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
819 }
820 else if (search_mi[f->comp->me]->search_expvector(REDUCE_exp, b))
821 {
822 q = reinterpret_cast<res_pair *>(b->basis_ptr());
823 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
824 lastterm = lastterm->next;
825 pivot = lastterm;
826 if (q->syz_type == SYZ_S_PAIR) return q; // i.e. not computed yet
827 M->divide(f->monom, q->syz->monom, REDUCE_mon);
828 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->syz);
829 }
830 else
831 {
832 // level 1: monomial not seen yet
833 q = new_res_pair(SYZ_S_PAIR, f);
834 insert_res_pair(1, q);
835 lastterm->next = R->new_term(K->negate(f->coeff), f->monom, q);
836 lastterm = lastterm->next;
837 pivot = lastterm;
838 return q;
839 }
840 }
841 return nullptr;
842}
843
845{
848
849 res_pair *q;
850 ring_elem rg;
851 Bag *b;
852
853 while (f != nullptr)
854 {
855 M->divide(f->monom, f->comp->base_monom, REDUCE_mon);
856 M->to_expvector(REDUCE_mon, REDUCE_exp);
857 if (find_ring_divisor(REDUCE_exp, rg))
858 {
859 // Subtract off f, leave fsyz alone
860 Nterm *r = rg;
861 M->divide(f->monom, r->monom, REDUCE_mon);
862 R->ring_subtract_multiple_to(f, f->coeff, REDUCE_mon, f->comp, rg);
863 }
864 else if (search_mi[f->comp->me]->search_expvector(REDUCE_exp, b))
865 {
866 q = reinterpret_cast<res_pair *>(b->basis_ptr());
867 M->divide(f->monom, q->syz->monom, REDUCE_mon);
868 R->subtract_multiple_to(f, f->coeff, REDUCE_mon, q->syz);
869 }
870 else
871 break; // MES: possibly auto reduce further...
872 }
873}
874
876// Toplevel calculation and state machine ///
878
880{
881 if (stop_.length_limit != nullptr && stop_.length_limit->len > 0)
882 {
884 {
885 ERROR("resolution: cannot increase maximum level");
886 return false;
887 }
888 else
889 length_limit = stop_.length_limit->array[0];
890 }
891
892 return true;
893}
894
895int res_comp::complete_thru_degree() const { return n_degree - 1; }
896//#define DO(CALL) {int result = CALL; if (result != COMP_COMPUTING) return
897// result;}
898#define DO(CALL) \
899 { \
900 enum ComputationStatusCode result = CALL; \
901 if (result != COMP_COMPUTING) \
902 { \
903 set_status(result); \
904 return; \
905 } \
906 }
907
908#if 0
909// int res_comp::calc(const int *DegreeLimit,
910// int LengthLimit,
911// int ArgSyzygyLimit,
912// int ArgPairLimit,
913// int /*SyzLimitValue*/,
914// int /*SyzLimitLevel*/,
915// int /*SyzLimitDegree*/)
916#endif
918{
919 if (status() == COMP_DONE) return;
921 DO(gens(lodegree));
922 DO(pairs(1, lodegree)); // MES: Probably not needed...
923
924 for (; n_degree <= hidegree; n_degree++, n_level = 2)
925 {
926 if (stop_.stop_after_degree && stop_.degree_limit->array[0] < n_degree)
927 {
929 return;
930 }
931 if (M2_gbTrace >= 1)
932 {
933 buffer o;
934 o << '{' << n_degree << '}';
935 emit_wrapped(o.str());
936 }
937
938 if (n_level == 2)
939 {
941 DO(gens(n_degree + 1));
942 DO(pairs(1, n_degree + 1));
943 n_level = 3;
944 }
945
946 for (; n_level <= length_limit + 1; n_level++)
947 {
948 if (M2_gbTrace >= 1) emit_wrapped(".");
949
950 DO(pairs(n_level - 1, n_degree));
951 DO(pairs(n_level - 1, n_degree + 1));
953 }
954 }
955 if (M2_gbTrace >= 6)
956 {
957 buffer o;
958 text_out(o);
959 emit(o.str());
960 }
962}
963
965{
966 if (M2_gbTrace >= 5)
967 {
968 buffer o;
969 o << "gens(" << deg << ")" << newline;
970 emit(o.str());
971 }
972 // preconditions: reductions(2,deg), gens(deg-1)
973 res_pair *p;
974 res_degree *mypairs = get_degree_set(1, deg);
975 if (mypairs != nullptr)
976 {
977 while ((p = mypairs->next_gen) != nullptr)
978 {
979 mypairs->next_gen = p->next;
980 handle_gen(p); // Consumes 'p'
981
982 mypairs->nleft--;
983 resn[1]->nleft--;
984 nleft--;
985 if (stop_.pair_limit > 0 && npairs - nleft >= stop_.pair_limit)
987 if (stop_.syzygy_limit > 0 && nminimal >= stop_.syzygy_limit)
990 }
991
992 sort_pairs(1, deg); // Sort the level 1 GB elements
993 }
994 return COMP_COMPUTING;
995}
996
998{
999 // Preconditions: pairs should be sorted
1000 // Cases: level=1: gens(deg), pairs(1,deg-1)
1001 // level=2: pairs(1,deg)
1002 // level>2: pairs(level-1,deg), pairs(level-2,deg+1)
1003 if (M2_gbTrace >= 5)
1004 {
1005 buffer o;
1006 o << "pairs(" << level << ", " << deg << ")" << newline;
1007 emit(o.str());
1008 }
1009 res_pair *p;
1010 sort_pairs(level, deg);
1011 res_degree *mypairs = get_degree_set(level, deg);
1012 if (mypairs != nullptr)
1013 {
1014 while ((p = mypairs->next_new_pair) != nullptr)
1015 {
1016 mypairs->next_new_pair = p->next;
1017 new_pairs(p);
1019 }
1020 }
1021 return COMP_COMPUTING;
1022}
1023
1025{
1026 res_pair *p;
1027 if (M2_gbTrace >= 5)
1028 {
1029 buffer o;
1030 o << "reductions(" << level << ", " << deg << ")" << newline;
1031 emit(o.str());
1032 }
1033 sort_pairs(level, deg);
1034 res_degree *mypairs = get_degree_set(level, deg);
1035 if (mypairs != nullptr)
1036 while ((p = mypairs->next_pair) != nullptr)
1037 {
1038 mypairs->next_pair = p->next;
1039 handle_pair(p);
1040
1041 mypairs->nleft--;
1042 resn[level]->nleft--;
1043 nleft--;
1044 if (stop_.pair_limit > 0 && npairs - nleft >= stop_.pair_limit)
1045 return COMP_DONE_PAIR_LIMIT;
1046 if (stop_.syzygy_limit > 0 && nminimal >= stop_.syzygy_limit)
1049 }
1050 return COMP_COMPUTING;
1051}
1052
1054{
1055 reduce_gen(p->syz);
1056 if (p->syz != nullptr)
1057 {
1058 R->make_monic(p->syz);
1059 M->copy(p->syz->monom, p->base_monom);
1060 p->first = p->syz->comp;
1061 p->second = nullptr;
1062 p->syz_type = SYZ_MINIMAL;
1063 p->base_comp = p->syz->comp->base_comp; // MES: added 7/11/97
1064 insert_res_pair(1, p);
1065 p->minimal_me = resn[1]->nminimal++;
1066 nminimal++;
1067 if (M2_gbTrace >= 2) emit_wrapped("z");
1068 }
1069 else
1070 {
1072 if (M2_gbTrace >= 2) emit_wrapped("o");
1073 }
1074}
1076{
1077 if (p->syz_type == SYZ_NOT_NEEDED) return;
1078
1079 resterm *f = s_pair(p);
1080 res_pair *q;
1081 if (n_level == 2)
1082 q = reduce_level_one(f, p->syz, p->pivot_term);
1083 else
1084 q = reduce(f, p->syz, p->pivot_term);
1085
1086 if (f == nullptr)
1087 {
1088 // minimal syzygy
1089 p->syz_type = SYZ_MINIMAL;
1090 p->minimal_me = resn[n_level]->nminimal++;
1091 nminimal++;
1092 if (M2_gbTrace >= 2) emit_wrapped("z");
1093 }
1094 else
1095 {
1096 R->make_monic(f);
1097 p->syz_type = SYZ_NOT_MINIMAL;
1098
1099 // non-minimal syzygy
1100 q->syz = f;
1102 if (M2_gbTrace >= 2) emit_wrapped("m");
1103 // MES: need to decrement nleft for 'q'.
1104 }
1105}
1106#if 0
1107// void res_comp::skeleton()
1108// // Compute the skeleton of the resolution
1109// // Currently: this is just used for debugging
1110// {
1111// int level, deg;
1112//
1113// for (level=1; level < resn.size(); level++)
1114// {
1115// n_level = level+1;
1116// for (deg=0; deg < resn[level]->bin.length(); deg++)
1117// {
1118// deg += lodegree;
1119// res_degree *p = get_degree_set(level, deg);
1120// if (p == NULL) continue;
1121// if (level == 1)
1122// {
1123// // Get the generators back into the game
1124// p->first = p->next_gen;
1125// p->next_gen = NULL;
1126// }
1127// pairs(level, deg);
1128// }
1129// }
1130// }
1131#endif
1132
1133#include "matrix-con.hpp"
1134
1135int res_comp::n_pairs(int lev, int d) const
1136{
1137 res_degree *p = get_degree_set(lev, d);
1138 if (p == nullptr) return 0;
1139 return p->npairs;
1140}
1141
1142int res_comp::n_left(int lev, int d) const
1143{
1144 res_degree *p = get_degree_set(lev, d);
1145 if (p == nullptr) return 0;
1146
1147 int result = 0;
1148 for (res_pair *q = p->first; q != nullptr; q = q->next)
1149 if (q->syz_type == SYZ_S_PAIR || q->syz_type == SYZ_GEN) result++;
1150
1151 return result;
1152}
1153
1154int res_comp::n_minimal(int lev, int d) const
1155{
1156 res_degree *p = get_degree_set(lev, d);
1157 if (p == nullptr) return 0;
1158 int result = 0;
1159 for (res_pair *q = p->first; q != nullptr; q = q->next)
1160 if (q->syz_type == SYZ_MINIMAL) result++;
1161
1162 return result;
1163}
1164
1165int res_comp::n_monoms(int lev, int d) const
1166{
1167 res_degree *p = get_degree_set(lev, d);
1168 if (p == nullptr) return 0;
1169 int result = 0;
1170 for (res_pair *q = p->first; q != nullptr; q = q->next)
1171 result += R->n_terms(q->syz);
1172
1173 return result;
1174}
1175
1176int res_comp::max_level() const { return resn.size(); }
1177int res_comp::low_degree() const { return lodegree; }
1178int res_comp::high_degree() const { return hidegree; }
1180{
1181 int lo = low_degree();
1182 int hi = high_degree();
1183 int len = (type == 0 ? length_limit : max_level());
1184
1185 int *bettis;
1186 betti_init(lo, hi, len, bettis);
1187
1188 for (int d = lo; d <= hi; d++)
1189 for (int lev = 0; lev <= len; lev++)
1190 {
1191 int val = 0;
1192 switch (type)
1193 {
1194 case 0:
1195 val = n_minimal(lev, d);
1196 break;
1197 case 1:
1198 val = n_pairs(lev, d);
1199 break;
1200 case 2:
1201 val = n_left(lev, d);
1202 break;
1203 case 3:
1204 val = n_monoms(lev, d);
1205 break;
1206 case 4:
1207 ERROR(
1208 "cannot use Minimize=>true unless "
1209 "res(...,FastNonminimal=>true) was used");
1210 return nullptr;
1211 default:
1212 val = -1;
1213 break;
1214 }
1215 bettis[lev + (len + 1) * (d - lo)] = val;
1216 }
1217
1218 M2_arrayint result = betti_make(lo, hi, len, bettis);
1219 freemem(bettis);
1220 return result;
1221}
1222
1227void res_comp::text_out(buffer &o, const res_pair *p) const
1228{
1229 res_pair *a = p->first;
1230 res_pair *b = p->second; // possibly NULL
1231 o << p->me << ' ';
1232 if (a != nullptr)
1233 o << a->me << ' ';
1234 else
1235 o << ". ";
1236 if (b != nullptr)
1237 o << b->me << ' ';
1238 else
1239 o << ". ";
1240
1241 o << p->compare_num << ' ';
1242
1243 switch (p->syz_type)
1244 {
1245 case SYZ_S_PAIR:
1246 o << "PR";
1247 break;
1248 case SYZ_GEN:
1249 o << "GN";
1250 break;
1251 case SYZ_MINIMAL:
1252 o << "SZ";
1253 break;
1254 case SYZ_NOT_MINIMAL:
1255 o << "GB";
1256 break;
1257 case SYZ_NOT_NEEDED:
1258 o << "NO";
1259 break;
1260 default:
1261 break;
1262 }
1263
1264#if 0
1265// if (p->mi_exists)
1266#endif
1267 o << "[mi: " << p->mi->size() << "]";
1268#if 0
1269// else
1270// {
1271// res_pair *q = p->next_div;
1272// int n = 0;
1273// while (q != NULL) { n++; q = q->next_div; }
1274// o << "[midiv: " << n << "]";
1275// }
1276#endif
1277 M->elem_text_out(o, p->base_monom);
1278 if (M2_gbTrace >= 3)
1279 {
1280 // Display the vector
1281 o << " syz: ";
1282 R->elem_text_out(o, p->syz);
1283 }
1284 o << newline;
1285}
1286
1288{
1289 buffer o;
1290 text_out(o, p);
1291 emit(o.str());
1292}
1293
1295{
1296 buffer o;
1297 text_out(o);
1298 emit(o.str());
1299}
1301{
1302 o << "level/degree = " << n_level << '/' << n_degree << newline;
1303 o << "--- The total number of pairs in each level/slanted degree -----"
1304 << newline;
1306 betti_display(o, a);
1307 o << "--- The number of pairs left to compute ------------------------"
1308 << newline;
1309 a = betti_remaining();
1310 betti_display(o, a);
1311 o << "--- (Lower bounds of) the minimal betti numbers ----------" << newline;
1312 a = betti_minimal();
1313 betti_display(o, a);
1314 if (M2_gbTrace >= 1)
1315 {
1316 o << "--- Number of monomials ---------------------------------"
1317 << newline;
1318 a = betti_nmonoms();
1319 betti_display(o, a);
1320 }
1321
1322 // If the printlevel is high enough, display each element
1323 if (M2_gbTrace >= 2)
1324 for (int lev = 0; lev < resn.size(); lev++)
1325 {
1326 o << "---- level " << lev << " ----" << newline;
1327 for (int i = 0; i < resn[lev]->bin.size(); i++)
1328 {
1329 res_degree *mypairs = resn[lev]->bin[i];
1330 if (mypairs == nullptr) continue;
1331 for (res_pair *p = mypairs->first; p != nullptr; p = p->next)
1332 {
1333 o.put(i, 4);
1334 o << ' ';
1335 text_out(o, p);
1336 }
1337 }
1338 }
1339}
1340
1342{
1344 result = P->make_Schreyer_FreeModule();
1345 if (i < 0 || i >= resn.size()) return result;
1346 monomial deg = P->degree_monoid()->make_one();
1347 int n = 0;
1348 res_level *lev = resn[i];
1349 for (int j = 0; j < lev->bin.size(); j++)
1350 {
1351 res_degree *mypairs = lev->bin[j];
1352 for (res_pair *p = mypairs->first; p != nullptr; p = p->next)
1353 {
1354 multi_degree(p, deg);
1355 result->append_schreyer(deg, p->base_monom, p->compare_num);
1356 p->minimal_me = n++;
1357 }
1358 }
1359 P->degree_monoid()->remove(deg);
1360
1361 return result;
1362}
1364{
1366 if (i == 0) return generator_matrix->rows();
1367 result = P->make_FreeModule();
1368 if (i < 0 || i > length_limit) return result;
1369 monomial deg = P->degree_monoid()->make_one();
1370 int nminimals = 0;
1371 res_level *lev = resn[i];
1372 for (int j = 0; j < lev->bin.size(); j++)
1373 {
1374 res_degree *mypairs = lev->bin[j];
1375 for (res_pair *p = mypairs->first; p != nullptr; p = p->next)
1376 if (p->syz_type == SYZ_MINIMAL)
1377 {
1378 multi_degree(p, deg);
1379 result->append(deg);
1380 p->minimal_me = nminimals++;
1381 }
1382 }
1383 P->degree_monoid()->remove(deg);
1384
1385 return result;
1386}
1387
1388Matrix *res_comp::make(int level) const
1389{
1390 const FreeModule *F = free_of(level - 1);
1391 const FreeModule *G = free_of(level);
1392 MatrixConstructor result(F, G, nullptr);
1393
1394 int n = 0;
1395 if (G == nullptr) return result.to_matrix();
1396 res_level *lev = resn[level];
1397 for (int j = 0; j < lev->bin.size(); j++)
1398 {
1399 res_degree *mypairs = lev->bin[j];
1400 for (res_pair *p = mypairs->first; p != nullptr; p = p->next)
1401 result.set_column(n++, R->to_vector(p->syz, F));
1402 }
1403 return result.to_matrix();
1404}
1405
1407// Minimal resolutions //////////////////////
1409
1411 resterm *&f,
1412 VECTOR(res_pair *)& elems) const
1413{
1414 monomial MINIMAL_mon = ALLOCATE_MONOMIAL(monom_size);
1415
1416 // Reduce any components of 'f' that correspond to non minimal syzygies.
1417 const resterm *tm;
1418
1419 for (int i = x - 1; i >= 0; i--)
1420 {
1421 res_pair *p = elems[i];
1422 if (p->syz_type == SYZ_NOT_MINIMAL)
1423 while ((tm = R->component_occurs_in(p->pivot_term->comp, f)) != nullptr)
1424 {
1425 // Subtract the proper multiple to f. f = ... + c m e_y + ...
1426 // and p = ... + d n e_y
1427 // where n|m. So we want to compute f -= c/d m/n p.
1428 ring_elem c =
1429 K->divide(tm->coeff, p->pivot_term->coeff); // exact division
1430 // MES: is the following line actually needed?
1431 M->divide(tm->monom, p->pivot_term->monom, MINIMAL_mon);
1432 if (p->stripped_syz == nullptr) p->stripped_syz = R->strip(p->syz);
1433 R->subtract_multiple_to(f, c, MINIMAL_mon, p->stripped_syz);
1434 }
1435 }
1436}
1437
1439{
1440 const FreeModule *F = minimal_free_of(i - 1);
1441 const FreeModule *G = minimal_free_of(i);
1442 MatrixConstructor result(F, G, nullptr);
1443 if (i < 0 || i > length_limit) return result.to_matrix();
1444 VECTOR(res_pair *) elems;
1445
1446 res_level *lev = resn[i];
1447 for (int j = 0; j < lev->bin.size(); j++)
1448 for (res_pair *p = lev->bin[j]->first; p != nullptr; p = p->next)
1449 elems.push_back(p);
1450
1451 int thisx = 0;
1452 for (int x = 0; x < elems.size(); x++)
1453 {
1454 res_pair *p = elems[x];
1455 if (p->syz_type == SYZ_MINIMAL)
1456 {
1457 if (p->stripped_syz == nullptr)
1458 {
1459 p->stripped_syz = R->strip(p->syz);
1460 reduce_minimal(x, p->stripped_syz, elems);
1461 }
1462 result.set_column(thisx++, R->to_vector(p->stripped_syz, F, 1));
1463 }
1464 }
1465 return result.to_matrix();
1466}
1467
1469// Skeleton construction: test code //
1471
1472
1474{
1475 // Do level 0
1476 res_pair *pp = nullptr;
1477 for (auto p = base_components.rbegin(); p != base_components.rend(); ++p)
1478 {
1479 (*p)->next = pp;
1480 pp = *p;
1481 }
1482 reslevel.push_back(pp);
1483
1484 // Do level 1
1485 pp = nullptr;
1486 for (auto i = 0; i < generator_matrix->n_cols(); i++)
1487 if ((*generator_matrix)[i] != nullptr)
1488 {
1489 res_pair *p = new_res_pair(i); // Makes a generator 'pair'
1490 p->next = pp;
1491 pp = p;
1492 }
1493 reslevel.push_back(pp);
1494}
1495
1497// Create and insert all of the pairs which will have lead term 'p'.
1498// This also places 'p' into the appropriate monomial ideal
1499{
1500 gc_vector<Bag*> elems;
1501 gc_vector<int> vp; // This is 'p'.
1502 gc_vector<int> thisvp;
1503
1505
1506 if (M2_gbTrace >= 10)
1507 {
1508 buffer o;
1509 o << "Computing pairs with first = " << p->me << newline;
1510 emit(o.str());
1511 }
1512 M->divide(p->base_monom, p->first->base_monom, PAIRS_mon);
1513 M->to_varpower(PAIRS_mon, vp);
1514
1515 // First add in syzygies arising from exterior variables
1516 // At the moment, there are none of this sort.
1517
1518 if (P->is_skew_commutative())
1519 {
1520
1521 exponents_t exp = newarray_atomic(int, M->n_vars());
1522 varpower::to_expvector(M->n_vars(), vp.data(), exp);
1523
1524 int nskew = P->n_skew_commutative_vars();
1525 for (int v = 0; v < nskew; v++)
1526 {
1527 int w = P->skew_variable(v);
1528 if (exp[w] > 0)
1529 {
1530 thisvp.resize(0);
1531 varpower::var(w, 1, thisvp);
1532 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
1533 elems.push_back(b);
1534 }
1535 }
1536 freemem(exp);
1537 }
1538
1539 // Second, add in syzygies arising from the base ring, if any
1540 // The baggage of each of these is NULL
1541 if (P->is_quotient_ring())
1542 {
1543 const MonomialIdeal *Rideal = P->get_quotient_monomials();
1544 for (Bag& a : *Rideal)
1545 {
1546 // Compute (P->quotient_ideal->monom : p->monom)
1547 // and place this into a varpower and Bag, placing
1548 // that into 'elems'
1549 thisvp.resize(0);
1550 varpower::quotient(a.monom().data(), vp.data(), thisvp);
1551 if (varpower::is_equal(a.monom().data(), thisvp.data()))
1552 continue;
1553 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
1554 elems.push_back(b);
1555 }
1556 }
1557
1558 // Third, add in syzygies arising from previous elements of this same level
1559 // The baggage of each of these is their corresponding res_pair
1560
1561 MonomialIdeal *mi_orig = p->first->mi;
1562 for (Bag& a : *mi_orig)
1563 {
1564 Bag *b = new Bag(a.basis_ptr());
1565 varpower::quotient(a.monom().data(), vp.data(), b->monom());
1566 elems.push_back(b);
1567 }
1568
1569 // Make this monomial ideal, and then run through each minimal generator
1570 // and insert into the proper degree. (Notice that sorting does not
1571 // need to be done yet: only once that degree is about to begin.
1572
1573 mi_orig->insert_minimal(new Bag(p, vp));
1574
1575 MonomialIdeal *mi = new MonomialIdeal(P, elems);
1576
1577 if (M2_gbTrace >= 11) mi->debug_out(1);
1578
1579 for (Bag& a : *mi)
1580 {
1581 res_pair *second = reinterpret_cast<res_pair *>(a.basis_ptr());
1582 res_pair *q = new_res_pair(SYZ_S_PAIR, p, second);
1583 // That set most fields except base_monom:
1584 M->from_varpower(a.monom().data(), q->base_monom);
1585 M->mult(q->base_monom, p->base_monom, q->base_monom);
1586 result->next = q;
1587 result = q;
1588 }
1589
1590 delete mi;
1591}
1592
1594{
1595 int result = lodegree;
1596 for (int level = 0; level < reslevel.size(); level++)
1597 {
1598 for (res_pair *p = reslevel[level]; p != nullptr; p = p->next)
1599 {
1600 int d = degree(p);
1601 if (d - level > result) result = d - level;
1602 }
1603 }
1604 return result;
1605}
1606
1608{
1609 buffer o;
1610 int level;
1611 int maxlevel = reslevel.size() - 1;
1612 int maxdegree = skeleton_maxdegree(reslevel); // max slanted degree
1613 int *bettis = newarray_atomic_clear(int, (maxlevel + 1) * (maxdegree + 1));
1614 for (level = 0; level < reslevel.size(); level++)
1615 {
1616 for (res_pair *p = reslevel[level]; p != nullptr; p = p->next)
1617 {
1618 int d = degree(p);
1619 d -= level;
1620 d -= lodegree;
1621 bettis[level + (maxlevel + 1) * d] += 1;
1622 }
1623 }
1624
1625 // Now make an arrayint so that we may just use betti_display
1626 int lo = lodegree;
1627 int hi = maxdegree;
1628 int len = maxlevel;
1629 int totallen = 3 + (hi - lo + 1) * (len + 1);
1630 M2_arrayint betti = M2_makearrayint(totallen);
1631
1632 betti->array[0] = lo;
1633 betti->array[1] = hi;
1634 betti->array[2] = len;
1635 int next = 3;
1636
1637 for (int d = 0; d <= maxdegree - lodegree; d++)
1638 for (level = 0; level <= maxlevel; level++)
1639 betti->array[next++] = bettis[level + (maxlevel + 1) * d];
1640
1641 betti_display(o, betti);
1642 freemem(bettis);
1643
1644 for (level = 0; level <= maxlevel; level++)
1645 {
1646 o << "---- level " << level << " ----" << newline;
1647 for (res_pair *p = reslevel[level]; p != nullptr; p = p->next)
1648 {
1649 int d = degree(p);
1650 o.put(d, 4);
1651 o << ' ';
1652 text_out(o, p);
1653 }
1654 }
1655 emit(o.str());
1656}
1657
1658void res_comp::skeleton(int strategy)
1659// Compute the skeleton of the resolution
1660// Currently: this is just used for debugging
1661{
1662 int level;
1663 VECTOR(res_pair *) reslevel;
1664
1665 // First, set reslevel[0], reslevel[1].
1666 skeleton_init(reslevel);
1667
1668 // Now loop through each level, until the length limit is hit,
1669 // or there are no new pairs
1670
1671 for (level = 1; level < reslevel.size(); level++)
1672 {
1673 // Sort the pairs in the current level:
1674 res_pair *pp = reslevel[level];
1675 if (pp == nullptr) break;
1676
1677 compare_type = strategy;
1678 sort_res_pairs(pp);
1679 reslevel[level] = pp;
1680 compare_type = 0;
1681
1682 // Now compute the pairs at the next level
1683 res_pair head, *ptrhead;
1684 head.next = nullptr;
1685 ptrhead = &head;
1686 for (res_pair *p = pp; p != nullptr; p = p->next) skeleton_pairs(ptrhead, p);
1687 reslevel.push_back(head.next);
1688 }
1689
1690 // Now display the skeleton and stats on it
1691 skeleton_stats(reslevel);
1692}
1693
1694// Local Variables:
1695// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1696// indent-tabs-mode: nil
1697// End:
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
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
const SchreyerOrder * get_schreyer_order() const
Definition freemod.hpp:103
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.
int search_expvector(const_exponents m, Bag *&b) const
Definition monideal.cpp:214
void insert_minimal(Bag *b)
Definition monideal.hpp:333
void debug_out(int disp=1) const
Definition monideal.cpp:508
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_monomial base_monom(int i) const
Definition schorder.hpp:91
Per-component tie-breaker data for a Schreyer monomial order on a FreeModule.
Definition schorder.hpp:68
char * str()
Definition buffer.hpp:72
void put(const char *s)
Definition buffer.cpp:35
int basis_elem() const
Definition int-bag.hpp:66
void * basis_ptr() const
Definition int-bag.hpp:67
gc_vector< int > & monom()
Definition int-bag.hpp:60
size_t exp_size
Definition res-a1.hpp:114
M2_arrayint betti_remaining() const
Definition res-a1.cpp:1224
Matrix * make_minimal(int i) const
Definition res-a1.cpp:1438
void remove_res_level(res_level *lev)
Definition res-a1.cpp:159
int hidegree
Definition res-a1.hpp:98
int n_left(int lev, int d) const
Definition res-a1.cpp:1142
int degree(const res_pair *q) const
Definition res-a1.cpp:273
void sort_compares(res_pair *&p) const
Definition res-a1.cpp:544
res_degree * make_degree_set(int level, int deg)
Definition res-a1.cpp:175
void sort_pairs(int level, int deg)
Definition res-a1.cpp:481
int n_monoms(int lev, int d) const
Definition res-a1.cpp:1165
resterm * s_pair(res_pair *fsyz) const
Definition res-a1.cpp:722
enum ComputationStatusCode reductions(int level, int deg)
Definition res-a1.cpp:1024
int compare_type
Definition res-a1.hpp:117
int max_level() const
Definition res-a1.cpp:1176
int compare_compares(res_pair *f, res_pair *g) const
Definition res-a1.cpp:500
int component_number
Definition res-a1.hpp:108
void skeleton_stats(const VECTOR(res_pair *)&reslevel)
Definition res-a1.cpp:1607
int next_me_number
Definition res-a1.hpp:107
const Monoid * M
Definition res-a1.hpp:80
int lodegree
Definition res-a1.hpp:97
enum ComputationStatusCode pairs(int level, int deg)
Definition res-a1.cpp:997
int n_level
Definition res-a1.hpp:88
int low_degree() const
Definition res-a1.cpp:1177
void reduce_gen(resterm *&f) const
Definition res-a1.cpp:844
void skeleton_init(VECTOR(res_pair *)&reslevel)
Definition res-a1.cpp:1473
enum ComputationStatusCode gens(int deg)
Definition res-a1.cpp:964
M2_arrayint get_betti(int type) const
Definition res-a1.cpp:1179
res_pair * reduce_level_one(resterm *&f, resterm *&fsyz, resterm *&pivot)
Definition res-a1.cpp:795
const Matrix * generator_matrix
Definition res-a1.hpp:82
void sort_gens(res_degree *pairs)
Definition res-a1.cpp:470
void multi_degree(const res_pair *q, monomial result) const
Definition res-a1.cpp:280
int length_limit
Definition res-a1.hpp:99
virtual ~res_comp()
Definition res-a1.cpp:122
stash * mi_stash
Definition res-a1.hpp:85
int compare_res_pairs(res_pair *f, res_pair *g) const
Definition res-a1.cpp:318
int max_degree
Definition res-a1.hpp:102
int complete_thru_degree() const
Definition res-a1.cpp:895
stash * res_pair_stash
Definition res-a1.hpp:84
void stats() const
Definition res-a1.cpp:1294
int n_degree
Definition res-a1.hpp:89
res_poly * R
Definition res-a1.hpp:79
int n_pairs(int lev, int d) const
Definition res-a1.cpp:1135
void skeleton_pairs(res_pair *&result, res_pair *p)
Definition res-a1.cpp:1496
res_comp(const Matrix *m, int LengthLimit, int strategy)
Definition res-a1.cpp:117
int find_ring_divisor(const_exponents exp, ring_elem &result) const
Definition res-a1.cpp:710
int sort_value(res_pair *p, const std::vector< int > sort_order) const
Definition res-a1.cpp:463
const Ring * K
Definition res-a1.hpp:81
int nleft
Definition res-a1.hpp:109
int nminimal
Definition res-a1.hpp:111
void remove_res_degree(res_degree *p)
Definition res-a1.cpp:147
void skeleton(int strategy)
Definition res-a1.cpp:1658
int npairs
Definition res-a1.hpp:110
const FreeModule * free_of(int i) const
Definition res-a1.cpp:1341
void remove_res_pair(res_pair *p)
Definition res-a1.cpp:137
res_pair * new_res_pair()
Definition res-a1.cpp:210
void sort_res_pairs(res_pair *&p) const
Definition res-a1.cpp:438
void new_pairs(res_pair *p)
Definition res-a1.cpp:606
Matrix * make(int i) const
Definition res-a1.cpp:1388
int n_minimal(int lev, int d) const
Definition res-a1.cpp:1154
M2_arrayint betti_minimal() const
Definition res-a1.cpp:1225
res_pair * merge_res_pairs(res_pair *f, res_pair *g) const
Definition res-a1.cpp:404
void text_out(const res_pair *p) const
Definition res-a1.cpp:1287
res_pair * reduce(resterm *&f, resterm *&fsyz, resterm *&pivot)
Definition res-a1.cpp:743
void set_compare_nums(int level, int deg)
Definition res-a1.cpp:569
void initialize(const Matrix *mat, int LengthLimit, int strategy)
Definition res-a1.cpp:14
res_degree * get_degree_set(int level, int d) const
Definition res-a1.cpp:200
void start_computation()
Definition res-a1.cpp:917
M2_arrayint betti_nmonoms() const
Definition res-a1.cpp:1226
const PolynomialRing * P
Definition res-a1.hpp:78
const FreeModule * minimal_free_of(int i) const
Definition res-a1.cpp:1363
void reduce_minimal(int x, resterm *&f, VECTOR(res_pair *)&elems) const
Definition res-a1.cpp:1410
void handle_pair(res_pair *p)
Definition res-a1.cpp:1075
int skeleton_maxdegree(const VECTOR(res_pair *)&reslevel)
Definition res-a1.cpp:1593
void insert_res_pair(int level, res_pair *p)
Definition res-a1.cpp:288
void handle_gen(res_pair *p)
Definition res-a1.cpp:1053
M2_arrayint betti_skeleton() const
Definition res-a1.cpp:1223
res_pair * merge_compares(res_pair *f, res_pair *g) const
Definition res-a1.cpp:511
int high_degree() const
Definition res-a1.cpp:1178
bool stop_conditions_ok()
Definition res-a1.cpp:879
size_t monom_size
Definition res-a1.hpp:115
res_pair * next_new_pair
Definition res-a1.hpp:27
int npairs
Definition res-a1.hpp:32
res_pair * next_gen
Definition res-a1.hpp:29
int nleft
Definition res-a1.hpp:33
res_pair * first
Definition res-a1.hpp:25
res_pair * next_pair
Definition res-a1.hpp:28
int is_sorted
Definition res-a1.hpp:31
res_pair * next_compare
res_pair * first
res_pair * next
int compare_num
resterm * syz
res_pair * base_comp
MonomialIdeal * mi
int * base_monom
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
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)
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
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
#define newarray_atomic_clear(T, len)
Definition newdelete.hpp:93
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
#define DO(CALL)
Definition res-a0.cpp:256
@ SYZ_NOT_MINIMAL
@ SYZ_S_PAIR
@ SYZ_NOT_NEEDED
@ SYZ_MINIMAL
@ SYZ_GEN
tbb::flow::graph G
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
res_pair * comp
ring_elem coeff
int monom[1]
resterm * next
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.