Macaulay2 Engine
Loading...
Searching...
No Matches
gb-toric.cpp
Go to the documentation of this file.
1// Copyright 1997 Michael E. Stillman
2
3#include "gb-toric.hpp"
4
5#include "ExponentVector.hpp"
6#include "text-io.hpp"
7
8#include "matrix-con.hpp"
9#include "interrupted.hpp"
10
11#define monomial monomial0
12
14// Monomials and binomials //
16
17binomial_ring::binomial_ring(const PolynomialRing *RR, int *wts, bool revlex0)
18 : R(RR),
19 F(RR->make_FreeModule(1)),
20 nvars(RR->n_vars()),
21 have_weights(wts != nullptr),
22 weights(nullptr),
23 revlex(revlex0)
24{
25 int i;
26
27 nslots = nvars + 1;
29 for (i = 0; i < nvars; i++)
30 degrees[i] = -R->getMonoid()->primary_degree_of_var(i);
31
32 if (have_weights)
33 {
34 nslots++;
36 for (i = 0; i < nvars; i++) weights[i] = -wts[i];
37 }
38
39 monstash = new stash("monomials", sizeof(int) * nslots);
40}
41
43{
44 ERROR("MES: not implemented yet");
45}
46
53
55{
56 if (m == nullptr) return;
57 monstash->delete_elem(m);
58 m = nullptr;
59}
60
62{
63 return (monomial)((const binomial_ring *)this)->monstash->new_elem();
64}
65
67{
69 for (int i = 0; i < nslots; i++) result[i] = m[i];
70 return result;
71}
72
74{
75 int i;
76 int deg = 0;
77 for (i = 0; i < nvars; i++) deg += degrees[i] * m[i];
78 m[nvars] = deg;
79 if (have_weights)
80 {
81 int wt = 0;
82 for (i = 0; i < nvars; i++) wt += weights[i] * m[i];
83 m[nvars + 1] = wt;
84 }
85}
86
88// Make a monomial from an exponent vector
89{
91 for (int i = 0; i < nvars; i++) result[i] = exp[i];
93 return result;
94}
101// allocates the monomials
102{
104}
109
111{
112 if (have_weights) return -m[nvars + 1];
113 return 0;
114}
115
116int binomial_ring::degree(monomial m) const { return -m[nvars]; }
118{
119 return exponents::mask(nvars, m);
120}
121
123{
124 for (int i = 0; i < nvars; i++)
125 if (m[i] > n[i]) return false;
126 return true;
127}
128
130// return m:n
131{
133 for (int i = 0; i < nslots; i++)
134 {
135 int x = m[i] - n[i];
136 result[i] = (x > 0 ? x : 0);
137 }
139 return result;
140}
141
143// return lcm(m,n)
144{
146 for (int i = 0; i < nvars; i++) result[i] = (m[i] > n[i] ? m[i] : n[i]);
148 return result;
149}
150
152{
154 for (int i = 0; i < nslots; i++) result[i] = m[i] - n[i];
155 return result;
156}
157
159{
161 for (int i = 0; i < nslots; i++) result[i] = m[i] + n[i];
162 return result;
163}
164
166// computes lcm - a + b
167{
169 for (int i = 0; i < nslots; i++) result[i] = lcm[i] - a[i] + b[i];
170 return result;
171}
172
174{
175 for (int i = 0; i < nslots; i++) a[i] += -b[i] + c[i];
176}
177
179{
180 // Return true if supp(m), supp(n) have empty intersection
181 for (int i = 0; i < nvars; i++)
182 if (m[i] > 0 && n[i] > 0) return false;
183 return true;
184}
186{
187 return gcd_is_one(f.lead, f.tail);
188}
189
191{
192 // If the monomials of f have a common monomial factor, remove it from each,
193 // and
194 // return true. Otherwise return false.
195 monomial m = f.lead;
196 monomial n = f.tail;
197 bool result = false;
198 for (int i = 0; i < nvars; i++)
199 {
200 if (m[i] > 0 && n[i] > 0)
201 {
202 if (m[i] > n[i])
203 {
204 m[i] -= n[i];
205 n[i] = 0;
206 }
207 else
208 {
209 n[i] -= m[i];
210 m[i] = 0;
211 }
212 result = true;
213 }
214 }
215 if (result)
216 {
217 set_weights(m); // This is an inefficient way to do this...
218 set_weights(n);
219 }
220 return result;
221}
222
224{
225 int i;
226 if (have_weights)
227 {
228 i = nvars + 1;
229 if (m[i] < n[i]) return GT;
230 if (m[i] > n[i]) return LT;
231 i--;
232 }
233 else
234 i = nvars;
235 // check degree? For now...
236 if (m[i] < n[i]) return GT; // Remember: m[nvars] is NEGATIVE of degree
237 if (m[i] > n[i]) return LT;
238 if (revlex)
239 for (; i >= 0; i--)
240 {
241 if (m[i] > n[i]) return LT;
242 if (m[i] < n[i]) return GT;
243 }
244 else
245 for (; i >= 0; i--)
246 {
247 if (m[i] > n[i]) return GT;
248 if (m[i] < n[i]) return LT;
249 }
250 return EQ;
251}
252
254{
255 int i = nvars;
256 if (m[i] < n[i]) return GT;
257 if (m[i] > n[i]) return LT;
258 if (have_weights)
259 {
260 i = nvars + 1;
261 if (m[i] < n[i]) return GT;
262 if (m[i] > n[i]) return LT;
263 i--;
264 }
265 else
266 i = nvars;
267 i--;
268 if (revlex)
269 for (; i >= 0; i--)
270 {
271 if (m[i] > n[i]) return LT;
272 if (m[i] < n[i]) return GT;
273 }
274 else
275 for (; i >= 0; i--)
276 {
277 if (m[i] > n[i]) return GT;
278 if (m[i] < n[i]) return LT;
279 }
280 return EQ;
281}
282
284 monomial &m) const
285{
286 int i;
287 if (m == nullptr) return;
289 for (i = 0; i < old_ring->nvars; i++) result[i] = m[i];
290 for (i = old_ring->nvars; i < nvars; i++) result[i] = 0;
291 old_ring->remove_monomial(m);
293 m = result;
294}
295
297 binomial &f) const
298{
299 translate_monomial(old_ring, f.lead);
300 translate_monomial(old_ring, f.tail);
301}
302
304{
305 if (m == nullptr) return nullptr;
306 ring_elem f = R->make_logical_term(
307 R->getCoefficients(), R->getCoefficients()->one(), m);
308 return R->make_vec(0, f);
309}
310
312{
313 vec v1 = monomial_to_vector(f.lead);
314 vec v2 = monomial_to_vector(f.tail);
315 R->subtract_vec_to(v1, v2);
316 return v1;
317}
319{
320 vec v1 = monomial_to_vector(f.lead);
321 bool include_tail = false;
322 if (n == 0)
323 include_tail = true;
324 else if (n == 1 && degree(f.tail) == degree(f.lead))
325 include_tail = true;
326 else if (n == 2 && degree(f.tail) == degree(f.lead) &&
327 weight(f.tail) == weight(f.lead))
328 include_tail = true;
329
330 if (include_tail)
331 {
332 vec v2 = monomial_to_vector(f.tail);
333 R->subtract_vec_to(v1, v2);
334 }
335 return v1;
336}
337
339// result should already have both monomials allocated
340// returns false if f is not a binomial, otherwise result is set.
341{
342 if (f == nullptr) return false;
343 Nterm *t = f->coeff;
344 if (t == nullptr || t->next == nullptr || t->next->next != nullptr) return false;
345
346 R->getMonoid()->to_expvector(t->monom, result.lead);
347 set_weights(result.lead);
348
349 R->getMonoid()->to_expvector(t->next->monom, result.tail);
350 set_weights(result.tail);
351
353 return true;
354}
355
357// result should be a preallocated binomial
358{
359 for (int i = 0; i < nslots; i++)
360 {
361 result.lead[i] = 0;
362 result.tail[i] = 0;
363 }
364
365 for (; f != nullptr; f = f->next)
366 {
367 std::pair<bool, long> res = globalZZ->coerceToLongInteger(f->coeff);
368 assert(res.first);
369 int e = static_cast<int>(res.second);
370
371 if (e > 0)
372 result.lead[f->comp] = e;
373 else if (e < 0)
374 result.tail[f->comp] = -e;
375 }
376
377 set_weights(result.lead);
378 set_weights(result.tail);
380}
381
383// Return false if 'f' is zero. Otherwise return true,
384// and possibly swap the terms of f so that f.lead is the lead term.
385{
386 int cmp = compare(f.lead, f.tail);
387 if (cmp == EQ) return false;
388 if (cmp == LT)
389 {
390 monomial a = f.lead;
391 f.lead = f.tail;
392 f.tail = a;
393 }
394 return true;
395}
396
398// returns false if the reduction is zero, otherwise modifies f.
399// (f might be modified in either case).
400{
401 // MES: need to consider the cases: divide by content, homog_prime.
402 for (int i = 0; i < nslots; i++) f.lead[i] += -g.lead[i] + g.tail[i];
403 return normalize(f);
404}
405
407{
408 binomial f = s.f1->f;
409 binomial g = s.f2->f;
411 for (int i = 0; i < nslots; i++)
412 {
413 result.lead[i] = s.lcm[i] - f.lead[i] + f.tail[i];
414 result.tail[i] = s.lcm[i] - g.lead[i] + g.tail[i];
415 }
416 return normalize(result);
417}
418
420{
421 if (m == nullptr) return;
424 monomial n = R->getMonoid()->make_one();
425 R->getMonoid()->from_varpower(vp.data(), n);
426 R->getMonoid()->elem_text_out(o, n);
427 R->getMonoid()->remove(n);
428}
429
431{
432 monomial_out(o, f.lead);
433 if (f.tail == nullptr) return;
434 o << "-";
435 monomial_out(o, f.tail);
436}
437
438// S pair management //
440
442 : R(RR), _prev_lcm(nullptr), _n_elems(0), _max_degree(0)
443{
444 _pairs = new s_pair_degree_list; // list header
445 _npairs.push_back(0);
446 _npairs.push_back(0);
447}
448
450{
451 const binomial_ring *old_ring = R;
452 R = newR;
453
454 old_ring->remove_monomial(_prev_lcm);
455 _prev_lcm = nullptr;
456 for (s_pair_degree_list *thisdeg = _pairs->next; thisdeg != nullptr;
457 thisdeg = thisdeg->next)
458 for (s_pair_lcm_list *thislcm = thisdeg->pairs; thislcm != nullptr;
459 thislcm = thislcm->next)
460 R->translate_monomial(old_ring, thislcm->lcm);
461}
462
464{
465 while (p->pairs != nullptr)
466 {
467 s_pair_elem *thispair = p->pairs;
468 p->pairs = thispair->next;
469 freemem(thispair);
470 }
471 R->remove_monomial(p->lcm);
472 freemem(p);
473}
475{
476 while (p->pairs != nullptr)
477 {
478 s_pair_lcm_list *thislcm = p->pairs;
479 p->pairs = thislcm->next;
480 remove_lcm_list(thislcm);
481 }
482 freemem(p);
483}
485{
486 while (_pairs != nullptr)
487 {
488 s_pair_degree_list *thisdeg = _pairs;
489 _pairs = thisdeg->next;
490 remove_pair_list(thisdeg);
491 }
492 R->remove_monomial(_prev_lcm);
493}
494
496{
497 int cmp;
498 s_pair_lcm_list head;
499 head.next = q->pairs;
500 s_pair_lcm_list *r = &head;
501 while (true)
502 {
503 if (r->next == nullptr || ((cmp = R->compare(s.lcm, r->next->lcm)) == GT))
504 {
505 // Insert new lcm node
507 r1->next = r->next;
508 r1->lcm = s.lcm;
509 r1->pairs = nullptr;
510 r->next = r1;
511 break;
512 }
513 if (cmp == EQ)
514 {
515 R->remove_monomial(s.lcm);
516 break;
517 }
518 r = r->next;
519 }
520 r = r->next;
521 s_pair_elem *s1 = new s_pair_elem(s.f1, s.f2);
522 q->pairs = head.next;
523 s1->next = r->pairs;
524 r->pairs = s1;
525}
526
528{
529 monomial lcm = R->make_monomial(R->lead_monomial(p->f));
530 binomial_s_pair s(p, nullptr, lcm);
531 insert(s);
532}
533
535{
536 int deg = R->degree(s.lcm);
537
538 // Statistics control
539 if (deg > _max_degree)
540 {
541 // Extend _npairs:
542 for (int i = 2 * _max_degree + 2; i < 2 * deg + 2; i++) _npairs.push_back(0);
543 _max_degree = deg;
544 }
545 _npairs[2 * deg]++;
546 _npairs[2 * deg + 1]++;
547
549 while (true)
550 {
551 if (q->next == nullptr || q->next->deg > deg)
552 {
553 // Insert new degree node
555 q1->next = q->next;
556 q1->deg = deg;
557 q1->pairs = nullptr;
558 q->next = q1;
559 break;
560 }
561 if (q->next->deg == deg) break;
562 q = q->next;
563 }
564 q = q->next;
565 insert_pair(q, s);
566 _n_elems++;
567 q->n_elems++;
568}
569
572 int &result_deg)
573// returns next pair in degrees <= *d, if any.
574// the caller should not free any of the three fields of the
575// s_pair!!
576{
577 if (_pairs->next == nullptr) return false;
578 if (d != nullptr && _pairs->next->deg > *d) return false;
579 s_pair_degree_list *thisdeg = _pairs->next;
580 s_pair_lcm_list *thislcm = thisdeg->pairs;
581 s_pair_elem *s = thislcm->pairs;
582 result_deg = thisdeg->deg;
583
584 thisdeg->n_elems--;
585 _n_elems--;
586 _npairs[2 * (thisdeg->deg) + 1]--;
587
588 result = binomial_s_pair(s->f1, s->f2, thislcm->lcm);
589
590 thislcm->pairs = s->next;
591 if (thislcm->pairs == nullptr)
592 {
593 // Now we must remove this set
594 thisdeg->pairs = thislcm->next;
595 R->remove_monomial(_prev_lcm);
596 _prev_lcm = thislcm->lcm;
597 thislcm->lcm = nullptr;
598 freemem(thislcm);
599
600 if (thisdeg->pairs == nullptr)
601 {
602 // Now we must remove this larger degree list
603 _pairs->next = thisdeg->next;
604 freemem(thisdeg);
605 }
606 }
607
608 freemem(s);
609 return true;
610}
611
613{
614 if (_pairs->next == nullptr) return -1;
615 return _pairs->next->deg;
616}
617
619{
621 while (p->next != nullptr && p->next->deg < d) p = p->next;
622 if (p->next == nullptr || p->next->deg != d) return 0;
623 return p->next->n_elems;
624}
625
628{
629 buffer o;
630 int np, nl;
631 np = nl = 0;
632 o << " degree"
633 << " pairs"
634 << " left"
635 << " done" << newline;
636 for (int i = 0; i <= _max_degree; i++)
637 {
638 np += _npairs[2 * i];
639 nl += _npairs[2 * i + 1];
640 o.put(i, 7);
641 o << " ";
642 o.put(_npairs[2 * i], 6);
643 o << " ";
644 o.put(_npairs[2 * i + 1], 6);
645 o << " ";
646 o.put(_npairs[2 * i] - _npairs[2 * i + 1], 6);
647 o << newline;
648 }
649 o << " total ";
650 o.put(np, 6);
651 o << " ";
652 o.put(nl, 6);
653 o << " ";
654 o.put(np - nl, 6);
655 o << newline;
656 emit(o.str());
657}
658
659// Binomial GB table //
661binomialGB::binomialGB(const binomial_ring *R0, bool bigcell, bool homogprime)
662 : R(R0),
663 first(nullptr),
664 _max_degree(0),
665 // use_bigcell(bigcell),
666 is_homogeneous_prime(homogprime)
667{
668 (void) bigcell;
669}
670
672{
673 // Do nothing much, except maybe clear out stuff
674 // so no stray pointers are around
675
676 R = nullptr;
677 first = nullptr; // MES: BUG!! We are leaking stuff here!!
678}
679
680void binomialGB::enlarge(const binomial_ring *newR) { R = newR; }
682// remove elements which have lead term divisible by in(f).
683// optionally auto-reduces the other elements as well.
684{
685 monomial m = f->f.lead;
686 gbmin_elem *fm = new gbmin_elem(f, R->mask(m));
687 gbmin_elem head, *p;
688 head.next = first;
689 int deg = R->degree(m);
690 if (deg > _max_degree) _max_degree = deg;
691 for (p = &head; p->next != nullptr; p = p->next)
692 {
693 if (R->graded_compare(m, p->next->elem->f.lead) == LT) break;
694 }
695 fm->next = p->next;
696 p->next = fm;
697 first = head.next;
698
699 p = fm;
700 while (p->next != nullptr)
701 {
702 if (R->degree(p->next->elem->f.lead) > deg &&
703 R->divides(m, p->next->elem->f.lead))
704 {
705 // remove this element
706 gbmin_elem *q = p->next;
707 binomial_gb_elem *qe = q->elem;
708 p->next = q->next;
709 q->next = nullptr;
710 qe->smaller = f;
711 }
712 else
713 {
714 reduce_monomial(p->next->elem->f.tail);
715 p = p->next;
716 }
717 }
718}
719
722 monomial m) const
723{
724 unsigned int mask = ~(R->mask(m));
725 int d = R->degree(m);
726 for (monomial_list *p = I; p != nullptr; p = p->next)
727 {
728 if (R->degree(p->m) > d) return nullptr;
729 if (mask & p->mask) continue;
730 if (R->divides(p->m, m)) return p;
731 }
732 return nullptr;
733}
734
736{
737 monomial_list *r;
739 for (int i = 0; i <= _max_degree; i++) deglist[i] = nullptr;
740
741 for (iterator p = begin(); p != end(); p++)
742 {
743 binomial_gb_elem *g = *p;
744 gbmin_elem *gm = new gbmin_elem(g, R->mask(g->f.lead));
745 monomial n = R->quotient(g->f.lead, m);
746 monomial_list *nl = new monomial_list(n, R->mask(n), gm);
747 int d = R->degree(n);
748 nl->next = deglist[d];
749 deglist[d] = nl;
750 }
751 monomial_list *result = nullptr;
752
753 for (int d = 0; d <= _max_degree; d++)
754 if (deglist[d] != nullptr)
755 {
756 monomial_list *currentresult = nullptr;
757 while (deglist[d] != nullptr)
758 {
759 monomial_list *p = deglist[d];
760 deglist[d] = p->next;
761 if (find_divisor(result, p->m))
762 {
763 R->remove_monomial(p->m);
764 freemem(p->tag); // There is only one element at this point
765 freemem(p);
766 }
767 else if ((r = find_divisor(currentresult, p->m)))
768 {
769 gbmin_elem *p1 = new gbmin_elem(p->tag->elem, p->mask);
770 R->remove_monomial(p->m);
771 freemem(p);
772 p1->next = r->tag;
773 r->tag = p1;
774 }
775 else
776 {
777 p->next = currentresult;
778 currentresult = p;
779 }
780 }
781 if (result == nullptr)
782 result = currentresult;
783 else if (currentresult != nullptr)
784 {
785 monomial_list *q;
786 for (q = result; q->next != nullptr; q = q->next)
787 ;
788 q->next = currentresult;
789 }
790 currentresult = nullptr;
791 }
792 freemem(deglist);
793 return result;
794}
795
797 binomial_gb_elem *f) const
798{
799 // Compute (a minimal generating set of)
800 // the ideal quotient in(Gmin) : in(f).
801 // Remove any that satisfy certain criteria:
802 // 1. gcd(lead terms) is 1: remove.
803 // 2. if homog_prime, gcd(tail terms) is not 1: remove.
804 // Any that pass these tests, insert into Pairs.
805
806 monomial m = f->f.lead;
808
809 for (monomial_list *q = I; q != nullptr; q = q->next)
810 {
811 gbmin_elem *ge = q->tag; // a list of possibles
812
813 binomial_gb_elem *g = ge->elem;
814
815 // Criterion 1: gcd of lead terms must be not 1.
816 if (R->gcd_is_one(R->lead_monomial(f->f), R->lead_monomial(g->f)))
817 {
818 // remove each of the elements in 'g'.
819 continue;
820 }
821
822 // Criterion 2: if a homogeneous prime,
823 // gcd of tails must be 1.
825 {
826 if (!R->gcd_is_one(f->f.tail, g->f.tail)) continue;
827 }
828
829 // Finally do the insert
830 monomial lcm = R->mult(m, q->m);
831 Pairs->insert(binomial_s_pair(f, g, lcm));
832 }
834}
835
837{
838 while (mm != nullptr)
839 {
840 R->remove_monomial(mm->m);
841 monomial_list *tmp = mm;
842 mm = mm->next;
843 freemem(tmp);
844 }
845}
846
847#if 0
848// binomial_gb_elem *binomialGB::find_divisor(monomial m) const
849// {
850// unsigned int mask = ~(R->mask(m));
851// int d = R->degree(m);
852// for (iterator p = begin(); p != end(); ++p)
853// {
854// binomial_gb_elem *g = *p;
855// if (R->degree(g->f.lead) > d) return NULL;
856// if (mask & p.this_elem()->mask) continue;
857// if (R->divides(g->f.lead, m))
858// return g;
859// }
860// return NULL;
861// }
862#endif
863
865{
866 unsigned int mask = ~(R->mask(m));
867 int d = R->degree(m);
868 for (gbmin_elem *p = first; p != nullptr; p = p->next)
869 {
870 if (R->degree(p->elem->f.lead) > d) return nullptr;
871 if (mask & p->mask) continue;
872 if (R->divides(p->elem->f.lead, m)) return p->elem;
873 }
874 return nullptr;
875}
876
878// replace m with its normal form.
879{
881 while ((p = find_divisor(m))) R->spair_to(m, p->f.lead, p->f.tail);
882}
883
885{
886 while (true)
887 {
889 if (p == nullptr)
890 {
892 return R->normalize(f);
893 }
894 else
895 {
896 // Do the division:
897 if (!R->one_reduction_step(f, p->f)) // Modifies 'f'.
898 return false;
899 }
900 }
901}
902#if 0
903// bool binomialGB::reduce(binomial &f) const
904// {
905// while (true)
906// {
907// binomial_gb_elem *p = find_divisor(f.lead);
908// if (p == NULL)
909// {
910// reduce_monomial(f.tail);
911// // The following should also check homog_prime, bigcell:
912// //
913// return R->normalize(f);
914// }
915// else
916// {
917// // Do the division:
918// if (!R->one_reduction_step(f,p->f)) // Modifies 'f'.
919// return false;
920//
921// if (is_homogeneous_prime)
922// {
923// if (!gcd_is_one(f)) return false;
924// }
925// else if (use_bigcell)
926// {
927// // if 'f' is divisible by a monomial, then we can strip this monomial.
928// remove_monomial_content(f);
929// }
930// }
931// }
932// }
933#endif
935{
936 int *masks = newarray_atomic(int, 100000);
937 buffer o;
938 unsigned int nmasks = 1;
939 masks[0] = first->mask;
940 for (gbmin_elem *p = first; p != nullptr; p = p->next)
941 {
942 o << " " << p->mask;
943 bool found = false;
944 for (unsigned int i = 0; i < nmasks && !found; i++)
945 if (masks[i] == p->mask)
946 {
947 found = true;
948 break;
949 }
950 if (!found) masks[nmasks++] = p->mask;
951 }
952 emit(o.str());
953 freemem(masks);
954 return nmasks;
955}
957{
958 buffer o;
959 for (iterator p = begin(); p != end(); p++)
960 {
961 binomial_gb_elem *g = *p;
962 R->elem_text_out(o, g->f);
963 o << newline;
964 }
965 emit(o.str());
966}
967
969// Binomial GB computation //
971
973 int *wts,
974 bool revlex,
975 unsigned int options)
976{
977 // set the flags and options
978 is_homogeneous = (options & GB_FLAG_IS_HOMOGENEOUS) != 0;
980 use_bigcell = (options & GB_FLAG_BIGCELL) != 0;
981 flag_auto_reduce = true;
982 flag_use_monideal = false;
983
984 R = new binomial_ring(RR, wts, revlex);
986 Gmin = new binomialGB(
988
989 top_degree = -1;
991}
992
994 M2_bool collect_syz,
995 int n_rows_to_keep,
996 M2_arrayint gb_weights,
997 int strategy,
998 M2_bool use_max_degree_limit,
999 int max_degree_limit)
1000{
1001 (void) gb_weights;
1002 (void) use_max_degree_limit;
1003 (void) max_degree_limit;
1004 if (collect_syz || n_rows_to_keep > 0)
1005 {
1006 ERROR("Groebner basis Algorithm=>Toric cannot keep syzygies");
1007 return nullptr;
1008 }
1010 if (R == nullptr)
1011 {
1012 ERROR("expected polynomial ring");
1013 return nullptr;
1014 }
1015 binomialGB_comp *result = new binomialGB_comp(R, nullptr, true, strategy);
1016 result->add_generators(m);
1017 return result;
1018}
1019
1021{
1022 int i;
1023 freemem(Gmin);
1024 freemem(Pairs);
1025 // remove each element of Gens
1026 for (i = 0; i < Gens.size(); i++) freemem(Gens[i]);
1027 // remove each element of G
1028 for (i = 0; i < G.size(); i++) freemem(G[i]);
1029 // The following is just to ease garbage collection
1030 for (i = 0; i < mingens.size(); i++) mingens[i] = nullptr;
1031 for (i = 0; i < mingens_subring.size(); i++) mingens_subring[i] = nullptr;
1032 freemem(R);
1033}
1034
1037// Incremental routines //
1039
1040void binomialGB_comp::enlarge(const PolynomialRing *newR, int *wts)
1041{
1042 binomial_ring *old_ring = R;
1043 R = new binomial_ring(newR, wts, old_ring->revlex);
1044
1045 // We need to change all of the monomials in sight.
1046 Gmin->enlarge(R);
1047 Pairs->enlarge(R);
1048 int i;
1049 for (i = 0; i < Gens.size(); i++)
1050 R->translate_binomial(old_ring, Gens[i]->f);
1051 for (i = 0; i < G.size(); i++) R->translate_binomial(old_ring, G[i]->f);
1052
1053 freemem(old_ring);
1054}
1055
1057{
1058 int i;
1059 binomial f;
1061 if (m->get_ring()->is_ZZ())
1062 {
1063 for (i = 0; i < m->n_cols(); i++)
1064 {
1065 f = R->make_binomial();
1066 R->intvector_to_binomial((*m)[i], f);
1067 p = new binomial_gb_elem(f);
1068 Gens.push_back(p);
1069 Pairs->insert(p);
1070 }
1071 }
1072 else
1073 {
1074 for (i = 0; i < m->n_cols(); i++)
1075 {
1076 f = R->make_binomial();
1077 if (R->vector_to_binomial((*m)[i], f))
1078 {
1079 p = new binomial_gb_elem(f);
1080 Gens.push_back(p);
1081 Pairs->insert(p);
1082 }
1083 else
1084 {
1085 ERROR("expected binomials");
1086 return;
1087 }
1088 }
1089 }
1090}
1091
1093// Computation proper //
1095
1097{
1098 bool ismin, subringmin;
1099 binomial f;
1100
1101 if (s.f2 == nullptr)
1102 {
1103 // A generator
1104 ismin = true;
1105 subringmin = true;
1106 f = R->copy_binomial(
1107 s.f1->f); // This is probably being left for garbage...
1108 }
1109 else
1110 {
1111 if (s.f1->smaller != nullptr || s.f2->smaller != nullptr)
1112 {
1113 if (s.f1->smaller != s.f2 && s.f2->smaller != s.f1)
1114 {
1115 return;
1116 }
1117 }
1118
1119 if (M2_gbTrace >= 5)
1120 {
1121 buffer o;
1122 o << "pair [";
1123 R->elem_text_out(o, s.f1->f);
1124 o << " ";
1125 R->elem_text_out(o, s.f2->f);
1126 o << "]" << newline;
1127 emit(o.str());
1128 }
1129 if (!R->calc_s_pair(s, f))
1130 {
1131 // The pair already reduces to zero.
1132 return;
1133 }
1134 ismin = false;
1135 subringmin = (R->weight(s.lcm) > 0);
1136 }
1137
1138 if (Gmin->reduce(f))
1139 {
1140 if (M2_gbTrace >= 5)
1141 {
1142 buffer o;
1143 o << " reduced to ";
1144 R->elem_text_out(o, f);
1145 emit_line(o.str());
1146 }
1147 subringmin = (subringmin && R->weight(f.lead) == 0);
1149 Gmin->make_new_pairs(Pairs, p);
1150 Gmin->minimalize_and_insert(p);
1151 if (ismin) mingens.push_back(p);
1152 if (subringmin) mingens_subring.push_back(p);
1153 G.push_back(p);
1154 }
1155 else
1156 R->remove_binomial(f);
1157}
1158
1164
1166{
1168 int *deg = nullptr;
1169 if (stop_.always_stop) return; // don't change status
1170 if (stop_.stop_after_degree) deg = &stop_.degree_limit->array[0];
1171 while (Pairs->next(deg, s, top_degree))
1172 {
1174 if (ret != COMP_COMPUTING) return;
1175 process_pair(s); // consumes 's'.
1176 if (system_interrupted())
1177 {
1179 return;
1180 }
1181 }
1182 if (Pairs->n_elems() == 0)
1184 else
1186}
1187
1189// Obtaining results //
1191
1193{
1194 // Subsequent calls will not receive duplicate elements
1195
1196 MatrixConstructor result(R->F, 0);
1197 for (int i = 0; i < mingens_subring.size(); i++)
1198 {
1199 result.append(R->binomial_to_vector(mingens_subring[i]->f));
1200 mingens_subring[i] = nullptr;
1201 }
1202 mingens_subring.clear();
1203 return result.to_matrix();
1204}
1205
1207{
1208 MatrixConstructor result(R->F, 0);
1209 for (binomialGB::iterator p = Gmin->begin(); p != Gmin->end(); p++)
1210 if (R->weight((*p)->f.lead) == 0)
1211 result.append(R->binomial_to_vector((*p)->f));
1212 return result.to_matrix();
1213}
1214
1216{
1217 (void) m;
1218 ERROR("MES: not implemented yet");
1219 return nullptr;
1220}
1221
1223{
1224 ERROR("MES: not implemented yet");
1225 return 0;
1226}
1227
1229{
1230 MatrixConstructor result(R->F, 0);
1231 for (int i = 0; i < mingens.size(); i++)
1232 result.append(R->binomial_to_vector(mingens[i]->f));
1233 return result.to_matrix();
1234}
1235
1237{
1238 MatrixConstructor result(R->F, 0);
1239 for (binomialGB::iterator p = Gmin->begin(); p != Gmin->end(); p++)
1240 result.append(R->binomial_to_vector((*p)->f, n));
1241 return result.to_matrix();
1242}
1243
1245{
1246 MatrixConstructor result(R->F, 0);
1247 for (binomialGB::iterator p = Gmin->begin(); p != Gmin->end(); p++)
1248 result.append(R->binomial_to_vector((*p)->f));
1249 return result.to_matrix();
1250}
1251
1252const Matrix *binomialGB_comp::get_change() { return nullptr; }
1253const Matrix *binomialGB_comp::get_syzygies() { return nullptr; }
1255// likely not planned to be implemented
1256{
1257 (void) m;
1258 return nullptr;
1259}
1261 const Matrix *m,
1262 const Matrix /* or null */ **result_remainder,
1263 const Matrix /* or null */ **result_quotient)
1264// not planned to be implemented
1265{
1266 (void) m;
1267 *result_remainder = nullptr;
1268 *result_quotient = nullptr;
1269 ERROR("rawGBMatrixLift not implemented for toric GB's");
1270 return false;
1271}
1272
1274{
1275 buffer o;
1276 o << "binomial GB ";
1277 if (is_homogeneous)
1278 o << "homogeneous ";
1279 else
1280 o << "inhomogeneous ";
1281 if (is_nondegenerate) o << "nondegenerate ";
1282 if (use_bigcell) o << "bigcell ";
1283 o << newline;
1284 o << "--- pairs ----" << newline;
1285 emit(o.str());
1286 Pairs->stats();
1287
1288 o.reset();
1289 o << Gmin->n_masks() << newline;
1290 emit(o.str());
1291
1292 if (M2_gbTrace >= 3) Gmin->debug_display();
1293}
1294
1295// Local Variables:
1296// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1297// indent-tabs-mode: nil
1298// End:
exponents::ConstExponents const_exponents
Dense exponent-vector template [e_0, ..., e_{nvars-1}] for monomial operations.
enum ComputationStatusCode set_status(enum ComputationStatusCode)
Definition comp.cpp:66
StopConditions stop_
Definition comp.hpp:75
static void from_expvector(int n, exponents::ConstExponents a, Vector &result)
static HashExponent mask(int nvars, ConstExponents a)
const Ring * get_ring() const
Definition matrix.hpp:134
int n_cols() const
Definition matrix.hpp:147
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual bool is_ZZ() const
Definition ring.hpp:171
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
bool gcd_is_one(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:178
void elem_text_out(buffer &o, const binomial &f) const
Definition gb-toric.cpp:430
void set_weights(monomial0 m) const
Definition gb-toric.cpp:73
monomial0 mult(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:158
bool vector_to_binomial(vec f, binomial &result) const
Definition gb-toric.cpp:338
bool normalize(binomial &f) const
Definition gb-toric.cpp:382
void remove_binomial(binomial &f) const
Definition gb-toric.cpp:95
vec monomial_to_vector(monomial0 m) const
Definition gb-toric.cpp:303
int degree(monomial0 m) const
Definition gb-toric.cpp:116
unsigned int mask(const_exponents m) const
Definition gb-toric.cpp:117
monomial0 make_monomial(const_exponents exp) const
Definition gb-toric.cpp:87
bool calc_s_pair(binomial_s_pair &s, binomial &result) const
Definition gb-toric.cpp:406
binomial make_binomial() const
Definition gb-toric.cpp:100
stash * monstash
Definition gb-toric.hpp:102
monomial0 new_monomial() const
Definition gb-toric.cpp:61
monomial0 quotient(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:129
const PolynomialRing * R
Definition gb-toric.hpp:89
void translate_binomial(const binomial_ring *old_ring, binomial &f) const
Definition gb-toric.cpp:296
bool remove_content(binomial &f) const
Definition gb-toric.cpp:190
const FreeModule * F
Definition gb-toric.hpp:90
bool have_weights
Definition gb-toric.hpp:96
monomial0 monomial_lcm(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:142
void intvector_to_binomial(vec f, binomial &result) const
Definition gb-toric.cpp:356
monomial0 copy_monomial(monomial0 m) const
Definition gb-toric.cpp:66
bool divides(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:122
void translate_monomial(const binomial_ring *old_ring, monomial0 &m) const
Definition gb-toric.cpp:283
void remove_monomial(monomial0 &m) const
Definition gb-toric.cpp:54
int weight(monomial0 m) const
Definition gb-toric.cpp:110
monomial0 spair(monomial0 lcm, monomial0 m, monomial0 n) const
Definition gb-toric.cpp:165
monomial0 divide(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:151
binomial copy_binomial(const binomial &f) const
Definition gb-toric.cpp:105
void monomial_out(buffer &o, const_exponents m) const
Definition gb-toric.cpp:419
int compare(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:223
vec binomial_to_vector(binomial f) const
Definition gb-toric.cpp:311
int graded_compare(monomial0 m, monomial0 n) const
Definition gb-toric.cpp:253
binomial_ring(const PolynomialRing *RR)
Definition gb-toric.cpp:42
void spair_to(monomial0 a, monomial0 b, monomial0 c) const
Definition gb-toric.cpp:173
bool one_reduction_step(binomial &f, binomial g) const
Definition gb-toric.cpp:397
int n_elems() const
Definition gb-toric.cpp:626
void insert_pair(s_pair_degree_list *q, binomial_s_pair &s)
Definition gb-toric.cpp:495
void insert(binomial_gb_elem *p)
Definition gb-toric.cpp:527
const binomial_ring * R
Definition gb-toric.hpp:196
void stats() const
Definition gb-toric.cpp:627
bool next(const int *d, binomial_s_pair &result, int &result_deg)
Definition gb-toric.cpp:570
void remove_lcm_list(s_pair_lcm_list *p)
Definition gb-toric.cpp:463
int lowest_degree() const
Definition gb-toric.cpp:612
binomial_s_pair_set(const binomial_ring *R)
Definition gb-toric.cpp:441
void remove_pair_list(s_pair_degree_list *p)
Definition gb-toric.cpp:474
gc_vector< int > _npairs
Definition gb-toric.hpp:204
s_pair_degree_list * _pairs
Definition gb-toric.hpp:198
void enlarge(const binomial_ring *R)
Definition gb-toric.cpp:449
binomial_ring * R
Definition gb-toric.hpp:313
void stats() const
virtual const Matrix * get_initial(int nparts)
virtual const Matrix * get_syzygies()
virtual ~binomialGB_comp()
void start_computation()
ComputationStatusCode gb_done() const
virtual const Matrix * get_mingens()
Matrix * subringGB()
virtual const Matrix * matrix_remainder(const Matrix *m)
Matrix * reduce(const Matrix *m, Matrix *&lift)
binomialGB * Gmin
Definition gb-toric.hpp:315
Matrix * subring()
binomial_s_pair_set * Pairs
Definition gb-toric.hpp:314
virtual int contains(const Matrix *m)
virtual bool stop_conditions_ok()
void enlarge(const PolynomialRing *R, int *wts)
void process_pair(binomial_s_pair p)
static binomialGB_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)
Definition gb-toric.cpp:993
virtual M2_bool matrix_lift(const Matrix *m, const Matrix **result_remainder, const Matrix **result_quotient)
virtual const Matrix * get_gb()
virtual const Matrix * get_change()
binomialGB_comp(const PolynomialRing *R, int *wts, bool revlex, unsigned int options)
Definition gb-toric.cpp:972
void add_generators(const Matrix *m)
void debug_display() const
Definition gb-toric.cpp:956
binomialGB(const binomial_ring *R, bool bigcell, bool homogprime)
Definition gb-toric.cpp:661
iterator begin() const
Definition gb-toric.hpp:296
void remove_monomial_list(monomial_list *mm) const
Definition gb-toric.cpp:836
bool reduce(binomial &f) const
Definition gb-toric.cpp:884
void reduce_monomial(monomial0 m) const
Definition gb-toric.cpp:877
monomial_list * find_divisor(monomial_list *I, monomial0 m) const
Definition gb-toric.cpp:720
int n_masks() const
Definition gb-toric.cpp:934
bool is_homogeneous_prime
Definition gb-toric.hpp:257
monomial_list * ideal_quotient(monomial0 m) const
Definition gb-toric.cpp:735
void minimalize_and_insert(binomial_gb_elem *f)
Definition gb-toric.cpp:681
void enlarge(const binomial_ring *newR)
Definition gb-toric.cpp:680
const binomial_ring * R
Definition gb-toric.hpp:252
int _max_degree
Definition gb-toric.hpp:254
gbmin_elem * first
Definition gb-toric.hpp:253
void make_new_pairs(binomial_s_pair_set *Pairs, binomial_gb_elem *f) const
Definition gb-toric.cpp:796
iterator end() const
Definition gb-toric.hpp:297
char * str()
Definition buffer.hpp:72
void reset()
Definition buffer.hpp:69
void put(const char *s)
Definition buffer.cpp:35
Definition mem.hpp:78
ComputationStatusCode
Definition computation.h:53
@ COMP_DONE
Definition computation.h:60
@ COMP_DONE_DEGREE_LIMIT
Definition computation.h:61
@ COMP_COMPUTING
Definition computation.h:71
@ COMP_NOT_STARTED
Definition computation.h:58
@ COMP_INTERRUPTED
Definition computation.h:57
#define Matrix
Definition factory.cpp:14
std::set< Pair > Pairs
RingZZ * globalZZ
Definition relem.cpp:13
#define monomial
Definition gb-toric.cpp:11
#define GB_FLAG_BIGCELL
Definition gb-toric.hpp:304
#define GB_FLAG_IS_HOMOGENEOUS
Definition gb-toric.hpp:302
#define GB_FLAG_IS_NONDEGENERATE
Definition gb-toric.hpp:303
binomialGB_comp — Buchberger GB specialised to binomial / toric ideals.
static int compare(const vecterm *t, const vecterm *s)
Definition geovec.hpp:112
int p
int p1
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 newarray(T, len)
Definition newdelete.hpp:82
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
tbb::flow::graph G
Nterm * next
Definition ringelem.hpp:157
ring_elem coeff
Definition ringelem.hpp:158
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
binomial_gb_elem * smaller
Definition gb-toric.hpp:61
monomial0 tail
Definition gb-toric.hpp:52
monomial0 lead
Definition gb-toric.hpp:51
binomial_gb_elem * elem
Definition gb-toric.hpp:234
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39
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.