Macaulay2 Engine
Loading...
Searching...
No Matches
gb-sugarless.cpp
Go to the documentation of this file.
1// Copyright 1996 Michael E. Stillman
2
3#include "style.hpp"
4#include "gb-sugarless.hpp"
5#include "text-io.hpp"
6#include "matrix-con.hpp"
7#include "gbweight.hpp"
8#include "interrupted.hpp"
9
10// is_min field of gb_elem:
11// 0 not a mingen (produced by an spair), not minimal gb elem
12// 1 a mingen (trimmed gen), but not minimal gb elem
13// 2 not mingen, but is a minimal gb element
14// 3 mingen and minimal gb elem
15
16static const int MINGEN_MASK = 0x1;
17static const int MINGB_MASK = 0x2;
18
20 int csyz,
21 int nsyz,
22 M2_arrayint gb_weights)
23{
24 int i;
26 if (R == nullptr)
27 {
28 ERROR("ring is not a polynomial ring");
29 // MES: throw an error here.
30 assert(0);
31 }
32 originalR = R;
33 GR = R->get_gb_ring();
34 weightInfo_ = new GBWeight(m->rows(), gb_weights);
35 M = GR->get_flattened_monoid();
36 K = GR->get_flattened_coefficients();
37
38 spairs = new s_pair_heap(M);
39
40 gb = gbLarge = new gb_elem; // List head for the GB computed so far
41 gb->next = nullptr; // (both minimal, and large GB's)
42 gb->next_min = nullptr;
43
44 if (nsyz < 0 || nsyz > m->n_cols()) nsyz = m->n_cols();
45 n_comps_per_syz = nsyz;
46
47 F = m->rows();
48
49 n_gb = n_subring = 0;
50 n_pairs = n_computed = 0;
51 last_gb_num = 0;
53
54 collect_syz = csyz;
55 is_ideal = (F->rank() == 1 && csyz == 0);
56 if (GR->is_weyl_algebra()) is_ideal = false;
57 need_resize = 0;
58
59 for (i = 0; i < F->rank(); i++) monideals.push_back(new MonomialIdeal(R));
60}
61
63 int csyz,
64 int nsyz,
65 M2_arrayint gb_weights,
66 int strat)
67{
68 strategy = strat;
69 set_up0(m, csyz, nsyz, gb_weights);
70
72
74 minimal_gb_valid = true;
75
77 n_syz = 0;
78 add_gens(0, m->n_cols() - 1, m);
79}
80
82{
83 // MES
84}
85
86void GBinhom_comp::add_gens(int lo, int hi, const Matrix *m)
87{
88 // MES
89 // First incorporate the new generators.
90 // 2. inter-reduce them, so they have different lead terms
91 // 3. insert them into gb, gbLarge
92 // 4. each insertion will also call find_pairs.
93
94 // MES: should we inter-reduce these first? Does it matter?
95 for (int i = hi; i >= lo; i--)
96 {
97 ring_elem denom;
98 gbvector *f = originalR->translate_gbvector_from_vec(F, (*m)[i], denom);
99 s_pair *p = new_gen(i, f, denom);
100 if (p != nullptr) spairs->insert(p);
101 n_pairs++;
102 }
103}
104
107 int n_rows_to_keep,
108 M2_arrayint gb_weights,
109 int strategy,
110 M2_bool use_max_degree_limit,
111 int max_degree_limit)
112{
113 (void) use_max_degree_limit;
114 (void) max_degree_limit;
116 if (P == nullptr || P->getCoefficients()->is_ZZ())
117 {
118 ERROR("expected polynomial ring over a field");
119 return nullptr;
120 }
122 new GBinhom_comp(m, collect_syz, n_rows_to_keep, gb_weights, strategy);
123 return result;
124}
125
127 int csyz,
128 int nsyz,
129 M2_arrayint gb_weights,
130 int strat)
131{
132 set_up(m, csyz, nsyz, gb_weights, strat);
133}
134
136{
137 GR->gbvector_remove(p->f);
138 GR->gbvector_remove(p->fsyz);
139 p->first = nullptr;
140 p->second = nullptr;
141 p->next = nullptr;
142 M->remove(p->lcm);
143 freemem(p);
144 p = nullptr;
145}
146
148void GBinhom_comp::resize(int /*nbits*/)
149// Resizes all (packed) monomials, and polynomials
150// to work in at least the next degree.
151{
152 // MES
153}
154
156// s pair construction //////////////////////
158
160{
161 return new_ring_pair(p, lcm);
162}
163
165{
166 s_pair *result = new s_pair;
167 result->next = nullptr;
168 result->syz_type = SPAIR_RING;
169 result->degree = weightInfo_->monomial_weight(
170 lcm,
171 p->f->comp); // M->primary_degree(lcm) + F->primary_degree(p->f->comp-1);
172 result->compare_num = 0;
173 result->first = p;
174 result->second = nullptr;
175 result->f = nullptr;
176 result->fsyz = nullptr;
177
178 result->lcm = M->make_new(lcm);
179 return result;
180}
181
183{
184 // p and q should have 'f' field defined.
185 s_pair *result = new s_pair;
186 result->next = nullptr;
187 result->syz_type = SPAIR_PAIR;
188 result->degree = weightInfo_->monomial_weight(
189 lcm,
190 p->f->comp); // M->primary_degree(lcm) + F->primary_degree(p->f->comp-1);
191 result->compare_num = 0;
192 result->first = p;
193 result->second = q;
194 result->f = nullptr;
195 result->fsyz = nullptr;
196
197 result->lcm = M->make_new(lcm);
198 return result;
199}
200
202{
203 gbvector *fsyz;
204
205 if (i < n_comps_per_syz)
206 fsyz = GR->gbvector_term(Fsyz, denom, i + 1);
207 else
208 fsyz = GR->gbvector_zero();
209
210 if (GR->gbvector_is_zero(f))
211 {
212 if (!GR->gbvector_is_zero(fsyz))
213 {
214 vec fsyzvec = originalR->translate_gbvector_to_vec(Fsyz, fsyz);
215 n_syz++;
216 syz.append(fsyzvec);
217 }
218 return nullptr;
219 }
220
221 s_pair *result = new s_pair;
222 result->next = nullptr;
223 result->syz_type = SPAIR_GEN;
224 result->degree = weightInfo_->gbvector_weight(f);
225 result->compare_num = 0;
226 result->first = nullptr;
227 result->second = nullptr;
228 result->f = f; /* NOTE THAT WE GRAB f */
229 result->fsyz = fsyz;
230
231 result->lcm = M->make_new(result->f->monom);
232
233 return result;
234}
235
237{
238 s_pair *r;
239 for (r = p->pair_list; r != nullptr; r = r->next_same)
240 if (r->second == q)
241 {
242 if (r->compare_num >= 0)
243 {
244 r->compare_num = -1;
245 if (M2_gbTrace >= 8)
246 {
247 buffer o;
248 o << "---- removed pair ";
249 debug_out(o, r);
250 emit_line(o.str());
251 }
252 return 1;
253 }
254 else
255 return 0;
256 }
257 for (r = q->pair_list; r != nullptr; r = r->next_same)
258 if (r->second == p)
259 {
260 if (r->compare_num >= 0)
261 {
262 r->compare_num = -1;
263 if (M2_gbTrace >= 8)
264 {
265 buffer o;
266 o << "---- removed pair ";
267 debug_out(o, r);
268 emit_line(o.str());
269 }
270 return 1;
271 }
272 else
273 return 0;
274 }
275 return 0;
276}
278// compute min gen set of {m | m lead(p) is in (p1, ..., pr, f1, ..., fs)}
279// (includes cases m * lead(p) = 0).
280// Returns a list of new s_pair's.
281{
282 gc_vector<Bag*> elems;
283 gc_vector<int> vplcm;
284 s_pair *q;
285 int nvars = M->n_vars();
286 monomial f_m = M->make_one();
287 monomial f_m2 = M->make_one();
288 int *find_pairs_lcm = newarray_atomic(int, nvars);
289 monomial find_pairs_mon = M->make_one();
290 int *pi = newarray_atomic(int, nvars);
291 int *pj = newarray_atomic(int, nvars);
292 int *pij = newarray_atomic(int, nvars);
293
294 GR->gbvector_get_lead_monomial(F, p->f, f_m);
295 if (GR->is_skew_commutative())
296 {
297 exponents_t find_pairs_exp = newarray_atomic(int, nvars);
298 M->to_expvector(f_m, find_pairs_exp);
299
300 for (int v = 0; v < GR->n_skew_commutative_vars(); v++)
301 {
302 int w = GR->skew_variable(v);
303 if (find_pairs_exp[w] == 0) continue;
304
305 find_pairs_exp[w]++;
306 M->from_expvector(find_pairs_exp, find_pairs_lcm);
307 find_pairs_exp[w]--;
308
309 vplcm.resize(0);
310 M->to_varpower(find_pairs_lcm, vplcm);
311 s_pair *q2 = new_var_pair(p, find_pairs_lcm);
312 elems.push_back(new Bag(q2, vplcm));
313 }
314 freemem(find_pairs_exp);
315 }
316
317// Add in syzygies arising from a base ring
318#ifdef DEVELOPMENT
319#warning "quotient ring stuff"
320#endif
321 if (originalR->is_quotient_ring())
322 {
323 for (int i = 0; i < originalR->n_quotients(); i++)
324 {
325 const gbvector *f = originalR->quotient_gbvector(i);
326 M->lcm(f->monom, f_m, find_pairs_lcm);
327 vplcm.resize(0);
328 M->to_varpower(find_pairs_lcm, vplcm);
329 s_pair *q2 = new_ring_pair(p, find_pairs_lcm);
330 elems.push_back(new Bag(q2, vplcm));
331 }
332 }
333
334 // Add in syzygies arising as s-pairs
335 for (gb_elem *s = gb->next_min; s != nullptr; s = s->next_min)
336 {
337 if (p->f->comp != s->f->comp) continue;
338
339 GR->gbvector_get_lead_monomial(F, s->f, f_m2);
340 M->lcm(f_m, f_m2, find_pairs_lcm);
341
342 vplcm.resize(0);
343 M->to_varpower(find_pairs_lcm, vplcm);
344 q = new_s_pair(p, s, find_pairs_lcm);
345 elems.push_back(new Bag(q, vplcm));
346 }
347
348 // Now minimalize these elements, and insert the minimal ones
349
350 VECTOR(Bag *) rejects;
351 MonomialIdeal mi(originalR, elems, rejects);
352 for (auto& b : rejects)
353 {
354 s_pair *q2 = reinterpret_cast<s_pair *>(b->basis_ptr());
355 remove_pair(q2);
356 delete b;
357 }
358
359 s_pair head;
360 s_pair *nextsame = &head;
361 int len = 0;
362
363 for (Bag& a : mi)
364 {
365 q = reinterpret_cast<s_pair *>(a.basis_ptr());
366 nextsame->next = q;
367 nextsame = q;
368 len++;
369 if (is_ideal && q->syz_type == SPAIR_PAIR)
370 {
371 M->gcd(q->first->f->monom, q->second->f->monom, find_pairs_mon);
372 if (M->is_one(find_pairs_mon))
373 {
374 n_saved_gcd++;
375 q->compare_num = -1; // MES: change name of field!!
376 // This means: don't compute spair.
377 if (M2_gbTrace >= 8)
378 {
379 buffer o;
380 o << "removed pair[" << q->first->me << " " << q->second->me
381 << "]";
382 emit_line(o.str());
383 }
384 }
385 }
386 }
387 n_pairs += len;
388 nextsame->next = nullptr;
389 p->pair_list = head.next;
390 spairs->sort_list(p->pair_list);
391 if (M2_gbTrace >= 8)
392 {
393 buffer o;
394 for (q = p->pair_list; q != nullptr; q = q->next)
395 {
396 o << "insert ";
397 debug_out(o, q);
398 o << newline;
399 }
400 emit(o.str());
401 }
402 for (q = p->pair_list; q != nullptr; q = q->next) q->next_same = q->next;
403 spairs->insert(p->pair_list, len);
404
405 // remove those pairs (i,j) for which gcd(p:i, p:j) = 1
406 // and for which (p,i), (p,j) are both in the previous list of add-ons.
407 // MES: this does not catch all of the un-necessary pairs...
408 // Also much optimization might be able to be done, as far as removing
409 // keeping the 'correct' minimal generator of the lcms.
410
411 for (s_pair *s1 = p->pair_list; s1 != nullptr; s1 = s1->next_same)
412 {
413 if (s1->syz_type != SPAIR_PAIR) continue;
414
415 GR->gbvector_get_lead_monomial(F, s1->second->f, f_m);
416
417 M->divide(s1->lcm, f_m, pi);
418
419 for (s_pair *t1 = s1->next_same; t1 != nullptr; t1 = t1->next_same)
420 {
421 if (t1->syz_type != SPAIR_PAIR) continue;
422 GR->gbvector_get_lead_monomial(F, t1->second->f, f_m);
423 M->divide(t1->lcm, f_m, pj);
424 M->gcd(pi, pj, pij);
425 if (M->is_one(pij))
426 {
427 if (mark_pair(s1->second, t1->second))
428 {
429 n_saved_lcm++;
430 }
431 }
432 }
433 }
434
435 // Remove the local variables
436 freemem(find_pairs_lcm);
437 freemem(pi);
438 freemem(pj);
439 freemem(pij);
440 M->remove(find_pairs_mon);
441 M->remove(f_m);
442 M->remove(f_m2);
443}
444
446{
447 if (p->f == nullptr)
448 {
449 monomial s = M->make_one();
450 M->divide(p->lcm, p->first->f->monom, s);
451
452 GR->gbvector_mult_by_term(
453 F, Fsyz, GR->one(), s, p->first->f, p->first->fsyz, p->f, p->fsyz);
454 if (p->syz_type == SPAIR_PAIR)
455 GR->gbvector_reduce_lead_term(
456 F, Fsyz, nullptr, p->f, p->fsyz, p->second->f, p->second->fsyz);
457 M->remove(s);
458 }
459}
460
462{
463 if ((strategy & STRATEGY_LONGPOLYNOMIALS) != 0) return gb_geo_reduce(f, fsyz);
464 gbvector head;
465 gbvector *result = &head;
466 result->next = nullptr;
467 gb_elem *q;
468
469 exponents_t div_totalexp = newarray_atomic(int, M->n_vars());
470 int count = 0;
471 if (M2_gbTrace == 10)
472 {
473 buffer o;
474 o << "reducing ";
475 GR->gbvector_text_out(o, F, f);
476 emit_line(o.str());
477 }
478 while (f != nullptr)
479 {
480 GR->gbvector_get_lead_exponents(F, f, div_totalexp);
481#ifdef DEVELOPMENT
482#warning "quotient ring stuff"
483#endif
484 Bag *b;
485 if (originalR->is_quotient_ring() &&
486 originalR->get_quotient_monomials()->search_expvector(div_totalexp,
487 b))
488 {
489 const gbvector *g = originalR->quotient_gbvector(b->basis_elem());
490 GR->gbvector_reduce_lead_term(F, Fsyz, head.next, f, fsyz, g, nullptr);
491 count++;
492 }
493 else if (search(div_totalexp, f->comp, q))
494 {
495 GR->gbvector_reduce_lead_term(
496 F, Fsyz, head.next, f, fsyz, q->f, q->fsyz);
497 count++;
498 }
499 else
500 {
501 result->next = f;
502 f = f->next;
503 result = result->next;
504 result->next = nullptr;
505 }
506 }
507 if (M2_gbTrace >= 4)
508 {
509 buffer o;
510 o << "." << count;
511 emit(o.str());
512 }
513
514 f = head.next;
515 freemem(div_totalexp);
516 return 1;
517}
518
520{
521 gb_elem *q;
522
523 gbvector head;
524 gbvector *result = &head;
525 result->next = nullptr;
526 exponents_t div_totalexp = newarray_atomic(int, M->n_vars());
527 int count = 0;
528
529 gbvectorHeap fb(GR, F);
530 gbvectorHeap fsyzb(GR, Fsyz);
531 fb.add(f);
532 fsyzb.add(fsyz);
533 const gbvector *lead;
534
535 while ((lead = fb.get_lead_term()) != nullptr)
536 {
537 GR->gbvector_get_lead_exponents(F, lead, div_totalexp);
538#ifdef DEVELOPMENT
539#warning "quotient ring stuff"
540#endif
541 Bag *b;
542 if (originalR->is_quotient_ring() &&
543 originalR->get_quotient_monomials()->search_expvector(div_totalexp,
544 b))
545 {
546 const gbvector *g = originalR->quotient_gbvector(b->basis_elem());
547 GR->reduce_lead_term_heap(F,
548 Fsyz,
549 lead,
550 div_totalexp, // are these two needed
551 head.next,
552 fb,
553 fsyzb,
554 g,
555 nullptr);
556 count++;
557 }
558 else if (search(div_totalexp, lead->comp, q))
559 {
560 GR->reduce_lead_term_heap(
561 F, Fsyz, lead, div_totalexp, head.next, fb, fsyzb, q->f, q->fsyz);
562 count++;
563 }
564 else
565 {
566 result->next = fb.remove_lead_term();
567 result = result->next;
568 result->next = nullptr;
569 }
570 }
571
572 if (M2_gbTrace >= 4)
573 {
574 buffer o;
575 o << "." << count;
576 emit(o.str());
577 }
578 f = head.next;
579
580 fsyz = fsyzb.value();
581 freemem(div_totalexp);
582 return 1;
583}
584
585int GBinhom_comp::compare(const gb_elem *p, const gb_elem *q) const
586{
587 int cmp = M->compare(p->f->monom, q->f->monom);
588 if (cmp == -1) return LT;
589 if (cmp == 1) return GT;
590 cmp = p->f->comp - q->f->comp;
591 if (cmp < 0) return LT;
592 if (cmp > 0) return GT;
593 return EQ;
594}
595int GBinhom_comp::search(const int *exp, int comp, gb_elem *&result)
596{
597 int nvars = M->n_vars();
598 int *exp2;
599 for (gb_elem *p = gbLarge->next; p != nullptr; p = p->next)
600 {
601 if (p->f->comp != comp) continue;
602 exp2 = p->lead_exp;
603 int is_div = 1;
604 for (int i = 0; i < nvars; i++)
605 if (exp2[i] > exp[i])
606 {
607 is_div = 0;
608 break;
609 }
610 if (is_div)
611 {
612 result = p;
613 return 1;
614 }
615 }
616 return 0;
617}
618void GBinhom_comp::gb_insert(gbvector *f, gbvector *fsyz, int minlevel)
619{
620 monomial f_m = M->make_one();
621 minlevel = (minlevel == 0 ? MINGB_MASK : MINGEN_MASK | MINGB_MASK);
622 gb_elem *p = new gb_elem(f, fsyz, minlevel);
623 p->me = last_gb_num++;
624 p->lead_exp = newarray_atomic(int, M->n_vars());
625
626 GR->gbvector_get_lead_monomial(F, p->f, f_m);
627 GR->gbvector_remove_content(p->f, p->fsyz);
628
629 M->to_expvector(f_m, p->lead_exp);
630 if (M->in_subring(1, f_m)) n_subring++;
631
632 // Next determine the new s pairs. This also deletes unneeded pairs
633 find_pairs(p);
634
635 // Insert into the Groebner basis
636 minimal_gb_valid = false;
637 gb_elem *q = gbLarge;
638 gb_elem *prevmin = gb;
639 for (;;)
640 {
641 if (q->next == nullptr || compare(p, q->next) == LT)
642 {
643 p->next = q->next;
644 q->next = p;
645 n_gb++;
646 // Now place into the minimal list as well
647 p->next_min = prevmin->next_min;
648 prevmin->next_min = p;
649 break;
650 }
651 else if (q->next->is_min & MINGB_MASK)
652 prevmin = q->next;
653 q = q->next;
654 }
655
656 M->remove(f_m);
657
658 // At this point 'p' has been inserted. Now we need to remove the
659 // non-minimal elements.
660 q = p;
661 while (q->next_min != nullptr)
662 // MES: this loop would be a good place to put in auto-reduction?
663 if (p->f->comp == q->next_min->f->comp &&
664 M->divides(p->f->monom, q->next_min->f->monom))
665 {
666 gb_elem *tmp = q->next_min;
667 q->next_min = tmp->next_min;
668 tmp->next_min = nullptr;
669 tmp->is_min ^= MINGB_MASK; // I.e. not in the minimal GB
670 n_gb--;
671 }
672 else
673 q = q->next_min;
674}
675
677// If no s-pairs left in the current degree,
678// return SPAIR_DONE.
679// Otherwise, compute the current s-pair, reduce it, and
680// dispatch the result. Return one of the other SPAIR_*
681// values.
682{
683 n_computed++;
684 if (M2_gbTrace >= 8)
685 {
686 buffer o;
687 o << "--- computing pair ";
688 debug_out(o, p);
689 o << " ----" << newline;
690 emit(o.str());
691 }
692 int minlevel = (p->syz_type == SPAIR_GEN);
693 int compute_pair = (p->compare_num >= 0); // MES: change field name
694 if (compute_pair)
695 {
697
698 if (!gb_reduce(p->f, p->fsyz)) return SPAIR_DEFERRED;
699 }
700 gbvector *f = p->f;
701 gbvector *fsyz = p->fsyz;
702 p->f = nullptr;
703 p->fsyz = nullptr;
704 if (p->first != nullptr)
705 {
706 // Then 'p' should be the first element on the p->first->pair_list
707 assert(p->first->pair_list == p);
708 p->first->pair_list = p->next_same;
709 }
710 remove_pair(p);
711
712 if (!compute_pair) return SPAIR_REMOVED;
713
714 if (!GR->gbvector_is_zero(f))
715 {
716 gb_insert(f, fsyz, minlevel);
717 if (M2_gbTrace >= 8)
718 {
719 buffer o;
720 o << " gb " << last_gb_num - 1 << " = ";
721 GR->gbvector_text_out(o, F, f);
722 emit_line(o.str());
723 }
724 return SPAIR_GB;
725 }
726 if (!GR->gbvector_is_zero(fsyz))
727 {
728 if (M2_gbTrace >= 8)
729 {
730 buffer o;
731 o << " syz = ";
732 GR->gbvector_text_out(o, Fsyz, fsyz);
733 emit_line(o.str());
734 }
735 if (collect_syz)
736 {
737 vec fsyzvec = originalR->translate_gbvector_to_vec(Fsyz, fsyz);
738 n_syz++;
739 syz.append(fsyzvec);
740 return SPAIR_SYZ;
741 }
742 else
743 GR->gbvector_remove(fsyz);
744 }
745 return SPAIR_ZERO;
746}
747
748//---- Completion testing -----------------------------
749
751// Test whether the current computation is done.
752{
753 if (stop_.basis_element_limit > 0 && n_gb >= stop_.basis_element_limit)
754 return COMP_DONE_GB_LIMIT;
755 if (stop_.syzygy_limit > 0 && n_syz >= stop_.syzygy_limit)
756 return COMP_DONE_SYZ_LIMIT;
757 if (stop_.pair_limit > 0 && n_computed >= stop_.pair_limit)
759 if (stop_.subring_limit > 0 && n_subring >= stop_.subring_limit)
761 return COMP_COMPUTING;
762}
763
764//---- state machine (roughly) for the computation ----
765
767{
769
770 for (;;)
771 {
772 if (system_interrupted())
773 {
774 is_done = COMP_INTERRUPTED;
775 break;
776 }
777
778 if (need_resize)
779 {
780 is_done = COMP_NEED_RESIZE;
781 break;
782 }
783
784 is_done = computation_complete();
785 if (is_done != COMP_COMPUTING) break;
786
787 if (error())
788 {
789 is_done = COMP_ERROR;
790 break;
791 }
792 s_pair *p = spairs->remove();
793 if (p == nullptr)
794 {
795 is_done = COMP_DONE;
796 break;
797 }
798 int stype = s_pair_step(p);
799 if (M2_gbTrace >= 3 && M2_gbTrace <= 7) switch (stype)
800 {
801 case SPAIR_GB:
802 emit_wrapped("m");
803 break;
804 case SPAIR_SYZ:
805 emit_wrapped("z");
806 break;
807 case SPAIR_ZERO:
808 emit_wrapped("o");
809 break;
810 case SPAIR_REMOVED:
811 emit_wrapped("r");
812 break;
813 default:
814 emit_wrapped("ERROR");
815 break;
816 }
817 }
818
819 // MES: complete the reduction of the GB here
820 if (M2_gbTrace >= 1) emit_line("");
821 if (M2_gbTrace >= 4)
822 {
823 buffer o;
824 o << "Number of pairs = " << n_pairs << newline;
825 o << "Number of gb elements = " << n_gb << newline;
826 o << "Number of gcd=1 pairs = " << n_saved_gcd << newline;
827 o << "Number of gcd tails=1 pairs = " << n_saved_lcm << newline;
828 o << "Number of pairs computed = " << n_computed << newline;
829 emit(o.str());
830 }
831 set_status(is_done);
832}
833
834/*******************************
835 ** Minimalization of the GB ***
836 *******************************/
838{
839 if (minimal_gb_valid) return;
840
841 VECTOR(POLY) polys;
842
843 for (gb_elem *q = gb->next_min; q != nullptr; q = q->next_min)
844 {
845 POLY g;
846 g.f = q->f;
847 g.fsyz = q->fsyz;
848 polys.push_back(g);
849 }
850
851 minimal_gb->minimalize(polys);
852 minimal_gb_valid = true;
853}
854
855//--- Reduction --------------------------
856const Matrix /* or null */ *GBinhom_comp::matrix_remainder(const Matrix *m)
857{
859 return minimal_gb->matrix_remainder(m);
860}
861
863 const Matrix /* or null */ **result_remainder,
864 const Matrix /* or null */ **result_quotient)
865{
867 return minimal_gb->matrix_lift(m, result_remainder, result_quotient);
868}
869
871// Return -1 if every column of 'm' reduces to zero.
872// Otherwise return the index of the first column that
873// does not reduce to zero.
874{
876 return minimal_gb->contains(m);
877}
878
879//--- Obtaining matrices as output -------
880
882// The computation is complete up through this degree.
883{
884#ifdef DEVELOPMENT
885#warning "not set"
886#endif
887 return 0;
888}
889
891/* This displays statistical information, and depends on the
892 M2_gbTrace value */
893{
894 (void) o;
895 stats();
896}
897
898const Matrix /* or null */ *GBinhom_comp::get_mingens()
899{
900 MatrixConstructor mat(F, 0);
901 for (gb_elem *q = gb->next; q != nullptr; q = q->next)
902 if (q->is_min & MINGEN_MASK)
903 mat.append(originalR->translate_gbvector_to_vec(F, q->f));
904 return mat.to_matrix();
905}
906
907const Matrix /* or null */ *GBinhom_comp::get_initial(int nparts)
908{
910 return minimal_gb->get_initial(nparts);
911}
912
914{
916 return minimal_gb->get_parallel_lead_terms(w);
917}
918
919const Matrix /* or null */ *GBinhom_comp::get_gb()
920{
922 // fprintf(stderr, "-- done with GB -- \n");
923 return minimal_gb->get_gb();
924}
925
926const Matrix /* or null */ *GBinhom_comp::get_change()
927{
929 return minimal_gb->get_change();
930}
931
932const Matrix /* or null */ *GBinhom_comp::get_syzygies()
933{
934#ifdef DEVELOPMENT
935#warning \
936 "this is not correct: this grabs the vectors, and so can't be called twice"
937#endif
938 return syz.to_matrix();
939}
940
942{
943 buffer o;
944 debug_out(o, q);
945 emit(o.str());
946}
947
949{
950 if (q == nullptr) return;
951 monomial m = M->make_one();
952 o << "(";
953 if (q->first != nullptr)
954 o << q->first->me;
955 else
956 o << ".";
957 o << " ";
958 if (q->second != nullptr)
959 o << q->second->me;
960 else
961 o << ".";
962 o << " ";
963 if (q->first != nullptr)
964 {
965 M->divide(q->lcm, q->first->f->monom, m);
966 M->elem_text_out(o, m);
967 o << ' ';
968 }
969 if (q->second != nullptr)
970 {
971 M->divide(q->lcm, q->second->f->monom, m);
972 M->elem_text_out(o, m);
973 o << ' ';
974 }
975 M->elem_text_out(o, q->lcm);
976 M->remove(m);
977 if (q->compare_num < 0) o << " marked";
978 o << ") ";
979}
980
982{
983 buffer o;
984 debug_pairs_out(o, p);
985 emit(o.str());
986}
988{
989 s_pair *q;
990 int n = 0;
991 for (q = p->pair_list; q != nullptr; q = q->next_same)
992 {
993 debug_out(o, q);
994 n++;
995 if (n % 10 == 0) o << newline;
996 }
997 o << newline;
998}
999
1001{
1002 buffer o;
1003 debug_pairs(o);
1004 emit(o.str());
1005}
1007{
1008 for (gb_elem *p = gbLarge->next; p != nullptr; p = p->next)
1009 debug_pairs_out(o, p);
1010
1011 for (int i = 0; i < NHEAP; i++)
1012 {
1013 s_pair *q = spairs->debug_list(i);
1014 if (q == nullptr) continue;
1015 o << "---- pairs in bin " << i << " -----" << newline;
1016 int n = 0;
1017 for (; q != nullptr; q = q->next)
1018 {
1019 debug_out(o, q);
1020 n++;
1021 if (n % 10 == 0) o << newline;
1022 }
1023 o << newline;
1024 }
1025}
1027{
1028 spairs->stats();
1029 buffer o;
1030 if (M2_gbTrace >= 5 && M2_gbTrace % 2 == 1)
1031 {
1032 int i = 0;
1033 for (gb_elem *q = gb->next_min; q != nullptr; q = q->next_min)
1034 {
1035 o << i << '\t';
1036 i++;
1037 GR->gbvector_text_out(o, F, q->f);
1038 o << newline;
1039 }
1040 }
1041 emit(o.str());
1042}
1043
1044// Local Variables:
1045// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1046// indent-tabs-mode: nil
1047// End:
exponents::Exponents exponents_t
enum ComputationStatusCode set_status(enum ComputationStatusCode)
Definition comp.cpp:66
StopConditions stop_
Definition comp.hpp:75
FreeModule * sub_space(int n) const
Definition freemod.cpp:197
Heuristic-weight evaluator for gbvectors, used during Groebner basis computation to drive the S-pair ...
Definition gbweight.hpp:67
void find_pairs(gb_elem *p)
void inter_reduce(gb_elem *&gens)
void add_gens(int lo, int hi, const Matrix *m)
void resize(int nbits)
virtual const Matrix * get_syzygies()
int compare(const gb_elem *p, const gb_elem *q) const
const Ring * K
virtual M2_bool matrix_lift(const Matrix *m, const Matrix **result_remainder, const Matrix **result_quotient)
int mark_pair(gb_elem *p, gb_elem *q) const
gb_elem * gbLarge
virtual const Matrix * matrix_remainder(const Matrix *m)
virtual int contains(const Matrix *m)
void gb_insert(gbvector *f, gbvector *fsyz, int minlevel)
const FreeModule * Fsyz
const FreeModule * F
virtual void text_out(buffer &o) const
virtual int complete_thru_degree() const
void compute_s_pair(s_pair *p)
s_pair * new_ring_pair(gb_elem *p, const int *lcm)
virtual const Matrix * get_initial(int nparts)
void debug_pairs_out(gb_elem *p) const
int gb_geo_reduce(gbvector *&f, gbvector *&fsyz)
int gb_reduce(gbvector *&f, gbvector *&fsyz)
static GBinhom_comp * create(const Matrix *m, M2_bool collect_syz, int n_rows_to_keep, M2_arrayint gb_weights, int strategy, M2_bool use_max_degree, int max_degree)
MatrixConstructor syz
GBinhom_comp(const Matrix *m, int collect_syz, int n_syz, M2_arrayint gb_weights, int strategy)
ReducedGB * minimal_gb
s_pair_heap * spairs
virtual const Matrix * get_parallel_lead_terms(M2_arrayint w)
GBWeight * weightInfo_
void debug_pairs() const
void set_up(const Matrix *m, int csyz, int nsyz, M2_arrayint gb_weights, int strategy)
virtual const Matrix * get_change()
void stats() const
void remove_pair(s_pair *&p)
s_pair * new_s_pair(gb_elem *p, gb_elem *q, const int *lcm)
const Monoid * M
virtual const Matrix * get_gb()
void start_computation()
s_pair * new_var_pair(gb_elem *p, const int *lcm)
int search(const int *exp, int comp, gb_elem *&result)
virtual const Matrix * get_mingens()
void debug_out(s_pair *q) const
ComputationStatusCode computation_complete() const
int s_pair_step(s_pair *p)
void set_up0(const Matrix *m, int csyz, int nsyz, M2_arrayint gb_weights)
const PolynomialRing * originalR
s_pair * new_gen(int i, gbvector *f, ring_elem denom)
const Ring * get_ring() const
Definition matrix.hpp:134
int n_cols() const
Definition matrix.hpp:147
const FreeModule * rows() const
Definition matrix.hpp:144
const FreeModule * cols() const
Definition matrix.hpp:145
Matrix * to_matrix()
void append(vec v)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
Engine-side monomial ideal: a decision tree of Nmi_nodes storing the (typically minimal) generators b...
Definition monideal.hpp:136
virtual GBRing * get_gb_ring() const
Definition polyring.hpp:276
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
static ReducedGB * create(const PolynomialRing *originalR0, const FreeModule *F0, const FreeModule *Fsyz0, const GBWeight *wt0=nullptr)
Definition reducedgb.cpp:11
virtual bool is_ZZ() const
Definition ring.hpp:171
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
char * str()
Definition buffer.hpp:72
gbvector * remove_lead_term()
Definition gbring.cpp:1592
gbvector * value()
Definition gbring.cpp:1603
void add(gbvector *p)
Definition gbring.cpp:1532
const gbvector * get_lead_term()
Definition gbring.cpp:1551
int basis_elem() const
Definition int-bag.hpp:66
const int SPAIR_ZERO
Definition comp-gb.hpp:53
const int SPAIR_PAIR
Definition comp-gb.hpp:56
const int SPAIR_GB
Definition comp-gb.hpp:51
const int SPAIR_SYZ
Definition comp-gb.hpp:52
const int SPAIR_DEFERRED
Definition comp-gb.hpp:59
const int SPAIR_RING
Definition comp-gb.hpp:57
const int SPAIR_GEN
Definition comp-gb.hpp:55
const int SPAIR_REMOVED
Definition comp-gb.hpp:58
@ STRATEGY_LONGPOLYNOMIALS
ComputationStatusCode
Definition computation.h:53
@ COMP_NEED_RESIZE
Definition computation.h:55
@ COMP_DONE_PAIR_LIMIT
Definition computation.h:64
@ COMP_DONE
Definition computation.h:60
@ COMP_DONE_SUBRING_LIMIT
Definition computation.h:70
@ COMP_ERROR
Definition computation.h:56
@ COMP_DONE_GB_LIMIT
Definition computation.h:65
@ COMP_DONE_SYZ_LIMIT
Definition computation.h:66
@ COMP_COMPUTING
Definition computation.h:71
@ COMP_INTERRUPTED
Definition computation.h:57
int error()
Definition error.c:48
#define Matrix
Definition factory.cpp:14
static const int MINGB_MASK
static const int MINGEN_MASK
GBinhom_comp — Buchberger GB without the sugar heuristic, primarily for inhomogeneous input.
#define monomial
Definition gb-toric.cpp:11
GBWeight — packed-weight evaluator that drives S-pair selection.
int p
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
void size_t s
Definition m2-mem.cpp:271
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
char M2_bool
Definition m2-types.h:82
MatrixConstructor — the mutable builder that produces an immutable Matrix.
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
#define POLY(q)
Definition poly.cpp:23
const int NHEAP
Definition spair.hpp:102
gbvector * fsyz
Definition gbring.hpp:99
gbvector * f
Definition gbring.hpp:98
s_pair * pair_list
Definition spair.hpp:57
gbvector * fsyz
Definition spair.hpp:59
int is_min
Definition spair.hpp:61
gb_elem * next
Definition spair.hpp:55
gbvector * f
Definition spair.hpp:58
gb_elem * next_min
Definition spair.hpp:56
int me
Definition spair.hpp:62
gbvector * next
Definition gbring.hpp:80
int monom[1]
Definition gbring.hpp:83
int comp
Definition gbring.hpp:82
int * lcm
Definition spair.hpp:95
gb_elem * second
Definition spair.hpp:97
int syz_type
Definition spair.hpp:92
s_pair * next
Definition spair.hpp:90
gb_elem * first
Definition spair.hpp:96
int compare_num
Definition spair.hpp:93
s_pair * next_same
Definition spair.hpp:91
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
void emit_wrapped(const char *s)
Definition text-io.cpp:27
void emit_line(const char *s)
Definition text-io.cpp:47
void emit(const char *s)
Definition text-io.cpp:41
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.