Macaulay2 Engine
Loading...
Searching...
No Matches
gb-homog2.cpp
Go to the documentation of this file.
1// Copyright 1996-2002 Michael E. Stillman
2
3// TODO:
4// finish gbring implementation
5// remove denominators from each input polynomial
6// at the end: remember (for syzygies), to
7// keep these in mind...
8// still: make sure that syzygies do not have denominators...
9// gbmatrix. Only used for HF computation. Provide a function for
10// this w/o gbmatrix.
11// get rid of hilb_step type computations: just return the HF.
12// anyway of making this algorithm more general?
13// e.g. deal with inhomogeneous or local case?
14// make a "stop conditions" type
15// link into the new interface for GB's
16// make quotient rings
17#include "style.hpp"
18#include "gb-homog2.hpp"
19#include "hilb.hpp"
20#include "text-io.hpp"
21#include "matrix-con.hpp"
22#include "interrupted.hpp"
23
25// Creation, initialization //
27
29 int csyz,
30 int nsyz,
31 M2_arrayint gb_weights)
32{
33 int i;
35 if (R == nullptr)
36 {
37 ERROR("ring is not a polynomial ring");
38 // MES: throw an error here.
39 assert(0);
40 }
41 originalR = R;
42 _GR = R->get_gb_ring();
43 weightInfo_ = new GBWeight(m->rows(), gb_weights);
44 _M = _GR->get_flattened_monoid();
45 _K = _GR->get_flattened_coefficients();
46
47 _spairs = new s_pair_heap(_M);
48 _gens = new s_pair_heap(_M);
49
50 if (nsyz < 0 || nsyz > m->n_cols()) nsyz = m->n_cols();
51 _n_rows_per_syz = nsyz;
52
53 _F = m->rows();
54
55 _ar_i = _ar_j = _np_i = -1;
56
57 _n_gb = _n_subring = 0;
59 _n_gens_left = 0;
60 _n_reductions = 0;
61
62 _collect_syz = csyz;
63 _is_ideal = (_F->rank() == 1 && csyz == 0);
64 if (_GR->is_weyl_algebra()) _is_ideal = false;
65
66 _use_hilb = false;
67 _hilb_new_elems = false;
69
70 _n_saved_hilb = 0;
71
72 // set local variables for certain time-critical routines
73
74 _this_degree = _F->lowest_primary_degree() - 1;
75
76 for (i = 0; i <= _F->rank(); i++)
77 {
78 // The 0th one is not used.
80 _monideals.push_back(p);
81 }
82}
83
85 int csyz,
86 int nsyz,
87 M2_arrayint gb_weights,
88 int strat)
89{
90 int i;
91 _strategy = strat;
92
93 initialize0(m, csyz, nsyz, gb_weights);
94
96
98
99 for (i = 0; i < m->n_cols(); i++)
100 {
101 ring_elem denom;
102 gbvector *f = originalR->translate_gbvector_from_vec(_F, (*m)[i], denom);
103 s_pair *p = new_gen(i, f, denom);
104 if (p != nullptr)
105 {
106 _gens->insert(p);
107 _n_gens_left++;
108 }
109 }
110}
111
113 M2_bool collect_syz,
114 int n_rows_to_keep,
115 M2_arrayint gb_weights,
116 int strategy,
117 M2_bool use_max_degree_limit,
118 int max_degree_limit)
119{
120 (void) use_max_degree_limit;
121 (void) max_degree_limit;
122 GB_comp *result = new GB_comp;
123 result->initialize(m, collect_syz, n_rows_to_keep, gb_weights, strategy);
124 return result;
125}
126
128{
129 _GR->gbvector_remove(p->f);
130 _GR->gbvector_remove(p->fsyz);
131 p->first = nullptr;
132 p->second = nullptr;
133 p->next = nullptr;
134 _M->remove(p->lcm);
135 freemem(p);
136 p = nullptr;
137}
138
141// s pair construction //////////////////////
143
145{
146 return new_ring_pair(p, lcm);
147}
148
150{
151 s_pair *result = new s_pair;
152 result->next = nullptr;
153 result->syz_type = SPAIR_RING;
154 result->degree = weightInfo_->monomial_weight(
155 lcm, p->f->comp); //_M->primary_degree(lcm) +
156 //_F->primary_degree(p->f->comp-1);
157 result->compare_num = 0;
158 result->first = p;
159 result->second = nullptr;
160 result->f = nullptr;
161 result->fsyz = nullptr;
162
163 result->lcm = _M->make_new(lcm);
164 return result;
165}
166
168{
169 // p and q should have 'f' field defined.
170 s_pair *result = new s_pair;
171 result->next = nullptr;
172 result->syz_type = SPAIR_PAIR;
173 result->degree = weightInfo_->monomial_weight(
174 lcm, p->f->comp); //_M->primary_degree(lcm) +
175 //_F->primary_degree(p->f->comp-1);
176 result->compare_num = 0;
177 result->first = p;
178 result->second = q;
179 result->f = nullptr;
180 result->fsyz = nullptr;
181
182 result->lcm = _M->make_new(lcm);
183 return result;
184}
185
187{
188 gbvector *fsyz;
189
190 if (i < _n_rows_per_syz)
191 fsyz = _GR->gbvector_term(_Fsyz, denom, i + 1);
192 else
193 fsyz = _GR->gbvector_zero();
194
195 if (_GR->gbvector_is_zero(f))
196 {
197 if (!_GR->gbvector_is_zero(fsyz))
198 {
199 _syz.push_back(fsyz);
200 _n_syz++;
201 }
202 return nullptr;
203 }
204
205 s_pair *result = new s_pair;
206 result->next = nullptr;
207 result->syz_type = SPAIR_GEN;
208 result->degree = weightInfo_->gbvector_weight(f);
209 result->compare_num = 0;
210 result->first = nullptr;
211 result->second = nullptr;
212 result->f = f; /* NOTE THAT WE GRAB f */
213 result->fsyz = fsyz;
214
215 result->lcm = _M->make_new(result->f->monom);
216
217 return result;
218}
219
221// sorting the Groebner basis ///////////////
223
224int GB_comp::gb_sort_partition(int lo, int hi)
225{
226 gb_elem *pivot = _gb[lo];
227 const gbvector *pivot_elem = pivot->f;
228 int i = lo - 1;
229 int j = hi + 1;
230 for (;;)
231 {
232 do
233 {
234 j--;
235 }
236 while (_GR->gbvector_compare(_F, _gb[j]->f, pivot_elem) > 0);
237
238 do
239 {
240 i++;
241 }
242 while (_GR->gbvector_compare(_F, _gb[i]->f, pivot_elem) < 0);
243
244 if (i < j)
245 {
246 gb_elem *tmp = _gb[j];
247 _gb[j] = _gb[i];
248 _gb[i] = tmp;
249 }
250 else
251 return j;
252 }
253}
254
255void GB_comp::gb_sort(int lo, int hi)
256{
257 if (lo < hi)
258 {
259 int q = gb_sort_partition(lo, hi);
260 gb_sort(lo, q);
261 gb_sort(q + 1, hi);
262 }
263}
264
266// compute min gen set of {m | m lead(p) is in (p1, ..., pr, f1, ..., fs)}
267// (includes cases m * lead(p) = 0).
268// Returns a list of new s_pair's.
269{
270 gc_vector<Bag*> elems;
271 gc_vector<int> vplcm;
272 monomial find_pairs_m = _M->make_one();
273 monomial f_m = _M->make_one();
274 exponents_t find_pairs_exp = newarray_atomic(int, _M->n_vars());
275 int *find_pairs_lcm = newarray_atomic(int, _M->n_vars());
276
277 _GR->gbvector_get_lead_monomial(_F, p->f, f_m);
278 if (_GR->is_skew_commutative())
279 {
280 _M->to_expvector(f_m, find_pairs_exp);
281
282 for (int v = 0; v < _GR->n_skew_commutative_vars(); v++)
283 {
284 int w = _GR->skew_variable(v);
285 if (find_pairs_exp[w] == 0) continue;
286
287 find_pairs_exp[w]++;
288 _M->from_expvector(find_pairs_exp, find_pairs_lcm);
289 find_pairs_exp[w]--;
290
291 vplcm.resize(0);
292 _M->to_varpower(find_pairs_lcm, vplcm);
293 s_pair *q = new_var_pair(p, find_pairs_lcm);
294 elems.push_back(new Bag(q, vplcm));
295 }
296 }
297
298 // Add in syzygies arising from a base ring
299
300 if (originalR->is_quotient_ring())
301 {
302 for (int i = 0; i < originalR->n_quotients(); i++)
303 {
304 const gbvector *f = originalR->quotient_gbvector(i);
305 _M->lcm(f->monom, f_m, find_pairs_lcm);
306 vplcm.resize(0);
307 _M->to_varpower(find_pairs_lcm, vplcm);
308 s_pair *q = new_ring_pair(p, find_pairs_lcm);
309 elems.push_back(new Bag(q, vplcm));
310 }
311 }
312 // Add in syzygies arising as s-pairs
313 MonomialIdeal *mi1 = _monideals[p->f->comp]->mi;
314 for (Bag& a : *mi1)
315 {
316 _M->from_varpower(a.monom().data(), find_pairs_m);
317 _M->lcm(find_pairs_m, f_m, find_pairs_lcm);
318 vplcm.resize(0);
319 _M->to_varpower(find_pairs_lcm, vplcm);
320 s_pair *q =
322 reinterpret_cast<gb_elem *>(a.basis_ptr()),
323 find_pairs_lcm);
324 elems.push_back(new Bag(q, vplcm));
325 }
326
327 // Add 'p' to the correct monideal
329 _M->to_varpower(f_m, vp);
330 mi1->insert(new Bag(p, vp));
331
332 // Now minimalize these elements, and insert them into
333 // the proper degree.
334
335 VECTOR(Bag *) rejects;
336 MonomialIdeal mi(originalR, elems, rejects);
337 for (auto& b : rejects)
338 {
339 s_pair *q = reinterpret_cast<s_pair *>(b->basis_ptr());
340 remove_pair(q);
341 delete b;
342 }
343 for (Bag& a : mi)
344 {
345 s_pair *q = reinterpret_cast<s_pair *>(a.basis_ptr());
346 if (_is_ideal && q->syz_type == SPAIR_PAIR)
347 {
348 _M->gcd(q->first->f->monom, q->second->f->monom, find_pairs_m);
349 if (_M->is_one(find_pairs_m))
350 {
351 _n_saved_gcd++;
352 if (M2_gbTrace >= 8)
353 {
354 buffer o;
355 o << "removed pair[" << q->first->me << " " << q->second->me
356 << "]" << newline;
357 emit(o.str());
358 }
359 remove_pair(q);
360 }
361 else
362 _spairs->insert(q);
363 }
364 else
365 _spairs->insert(q);
366 }
367
368 // Remove the local variables
369 _M->remove(find_pairs_m);
370 _M->remove(f_m);
371 freemem(find_pairs_exp);
372 freemem(find_pairs_lcm);
373}
374
376{
377 if (p->f == nullptr)
378 {
379 monomial s = _M->make_one();
380 _M->divide(p->lcm, p->first->f->monom, s);
381
382 _GR->gbvector_mult_by_term(
383 _F, _Fsyz, _GR->one(), s, p->first->f, p->first->fsyz, p->f, p->fsyz);
384 if (p->syz_type == SPAIR_PAIR)
385 _GR->gbvector_reduce_lead_term(
386 _F, _Fsyz, nullptr, p->f, p->fsyz, p->second->f, p->second->fsyz);
387 _M->remove(s);
388 }
389}
390
392{
394 {
395 gb_geo_reduce(f, fsyz);
396 return;
397 }
398 gbvector head;
399 gbvector *result = &head;
400 result->next = nullptr;
401
402 exponents_t div_totalexp = newarray_atomic(int, _M->n_vars());
403 int count = 0;
404 if (M2_gbTrace == 10)
405 {
406 buffer o;
407 o << "reducing ";
408 _GR->gbvector_text_out(o, _F, f);
409 emit_line(o.str());
410 }
411 while (f != nullptr)
412 {
413 Bag *b;
414 _GR->gbvector_get_lead_exponents(_F, f, div_totalexp);
415 if (originalR->is_quotient_ring() &&
416 originalR->get_quotient_monomials()->search_expvector(div_totalexp,
417 b))
418 {
419 const gbvector *g = originalR->quotient_gbvector(b->basis_elem());
420 _GR->gbvector_reduce_lead_term(_F, _Fsyz, head.next, f, fsyz, g, nullptr);
421 count++;
423 }
424 else if (_monideals[f->comp]->mi_search->search_expvector(div_totalexp,
425 b))
426 {
427 gb_elem *q = reinterpret_cast<gb_elem *>(b->basis_ptr());
428 _GR->gbvector_reduce_lead_term(
429 _F, _Fsyz, head.next, f, fsyz, q->f, q->fsyz);
430 count++;
432 if (M2_gbTrace == 10)
433 {
434 buffer o;
435 o << " reduced by ";
436 _GR->gbvector_text_out(o, _F, q->f);
437 o << newline;
438 o << " giving ";
439 _GR->gbvector_text_out(o, _F, f);
440 o << newline;
441 emit(o.str());
442 }
443 }
444 else
445 {
446 result->next = f;
447 f = f->next;
448 result = result->next;
449 result->next = nullptr;
450 }
451 }
452
453 if (M2_gbTrace >= 4)
454 {
455 buffer o;
456 o << "." << count;
457 emit_wrapped(o.str());
458 }
459 f = head.next;
460 freemem(div_totalexp);
461}
462
464{
465 gbvector head;
466 gbvector *result = &head;
467 result->next = nullptr;
468
469 exponents_t div_totalexp = newarray_atomic(int, _M->n_vars());
470 int count = 0;
471
472 gbvectorHeap fb(_GR, _F);
473 gbvectorHeap fsyzb(_GR, _Fsyz);
474 fb.add(f);
475 fsyzb.add(fsyz);
476 const gbvector *lead;
477 while ((lead = fb.get_lead_term()) != nullptr)
478 {
479 Bag *b;
480 _GR->gbvector_get_lead_exponents(_F, lead, div_totalexp);
481 if (originalR->is_quotient_ring() &&
482 originalR->get_quotient_monomials()->search_expvector(div_totalexp,
483 b))
484 {
485 const gbvector *g = originalR->quotient_gbvector(b->basis_elem());
486 _GR->reduce_lead_term_heap(_F,
487 _Fsyz,
488 lead,
489 div_totalexp, // are these two needed
490 head.next,
491 fb,
492 fsyzb,
493 g,
494 nullptr);
495 count++;
496 }
497 else if (_monideals[lead->comp]->mi_search->search_expvector(div_totalexp,
498 b))
499 {
500 gb_elem *q = reinterpret_cast<gb_elem *>(b->basis_ptr());
501 _GR->reduce_lead_term_heap(_F,
502 _Fsyz,
503 lead,
504 div_totalexp,
505 head.next,
506 fb,
507 fsyzb,
508 q->f,
509 q->fsyz);
510 count++;
511 }
512 else
513 {
514 result->next = fb.remove_lead_term();
515 result = result->next;
516 result->next = nullptr;
517 }
518 }
519
520 if (M2_gbTrace >= 4)
521 {
522 buffer o;
523 o << "." << count;
524 emit_wrapped(o.str());
525 }
526 f = head.next;
527
528 fsyz = fsyzb.value();
529 freemem(div_totalexp);
530}
531
533{
534 s_pair *p;
535 while ((p = _spairs->remove()) != nullptr)
536 if (p->degree != deg)
537 {
538 _spairs->put_back(p);
539 break;
540 }
541 else
542 {
544 remove_pair(p);
545 }
546 while ((p = _gens->remove()) != nullptr)
547 if (p->degree != deg)
548 {
549 _gens->put_back(p);
550 break;
551 }
552 else
553 {
555 remove_pair(p);
556 }
557}
558
559void GB_comp::gb_insert(gbvector *f, gbvector *fsyz, int ismin)
560{
561 monomial f_m = _M->make_one();
562 gb_elem *p = new gb_elem(f, fsyz, ismin);
563
564 _GR->gbvector_get_lead_monomial(_F, p->f, f_m);
565 _GR->gbvector_remove_content(p->f, p->fsyz);
566
567 if (ismin)
568 {
569 p->is_min = 1;
570 }
571
572 if (_M->in_subring(1, f_m)) _n_subring++;
573 // insert into p->f->comp->mi_search
575 _M->to_varpower(f_m, vp);
576 _monideals[p->f->comp]->mi_search->insert(new Bag(p, vp));
577 _n_gb++;
578 _gb.push_back(p);
579 _M->remove(f_m);
580
581 // Now we must be a bit careful about this next, but we only want one
582 // copy of a GB element, since the whole thing can be quite large.
583 // Just make sure that when the GB is deleted at the end, that the 'f'
584 // field of the gb_elem's is not removed.
585
586 if (_use_hilb)
587 {
588 _hilb_new_elems = true;
590 }
591}
592
594// If no s-pairs left in the current degree,
595// return SPAIR_DONE.
596// Otherwise, compute the current s-pair, reduce it, and
597// dispatch the result. Return one of the other SPAIR_*
598// values.
599{
600 s_pair *p = _spairs->remove();
601 if (p == nullptr) return SPAIR_DONE;
602 if (p->degree != _this_degree)
603 {
604 _spairs->put_back(p);
605 return SPAIR_DONE;
606 }
607
608 if (M2_gbTrace == 100)
609 {
610 // Traces the computation, in its way
611 emit("Computing spair ");
612 debug_out(p);
613 }
616
617 gbvector *f = p->f;
618 gbvector *fsyz = p->fsyz;
619 p->f = nullptr;
620 p->fsyz = nullptr;
621 remove_pair(p);
622
623 gb_reduce(f, fsyz);
624 if (!_GR->gbvector_is_zero(f))
625 {
626 if (M2_gbTrace == 100)
627 {
628 buffer o;
629 o << " inserting GB element " << _n_gb;
630 _GR->gbvector_text_out(o, _F, f);
631 o << newline;
632 emit(o.str());
633 }
634 gb_insert(f, fsyz, 0);
635 return SPAIR_GB;
636 }
637 if (!_GR->gbvector_is_zero(fsyz))
638 {
639 if (_collect_syz)
640 {
641 // vec fsyzvec = _GR->gbvector_to_vec(_Fsyz,fsyz);
642 _syz.push_back(fsyz);
643 _n_syz++;
644 return SPAIR_SYZ;
645 }
646 else
647 _GR->gbvector_remove(fsyz);
648 }
649
650 return SPAIR_ZERO;
651}
652
654// If no gens left in the current degree,
655// return SPAIR_DONE.
656// Otherwise, compute the current s-pair, reduce it, and
657// dispatch the result. Return one of the other SPAIR_*
658// values.
659{
660 s_pair *p = _gens->remove();
661 if (p == nullptr) return SPAIR_DONE;
662 if (p->degree != _this_degree)
663 {
664 _gens->put_back(p);
665 return SPAIR_DONE;
666 }
667
669 _n_gens_left--;
670
672
673 gbvector *f = p->f;
674 gbvector *fsyz = p->fsyz;
675 p->f = nullptr;
676 p->fsyz = nullptr;
677 remove_pair(p);
678
679 gb_reduce(f, fsyz);
680 if (!_GR->gbvector_is_zero(f))
681 {
682 gb_insert(f, fsyz, 1); // 1 = minimal generator
683 return SPAIR_MINGEN;
684 }
685
686 if (!_GR->gbvector_is_zero(fsyz))
687 {
688 if (_collect_syz)
689 {
690 // vec fsyzvec = _GR->gbvector_to_vec(_Fsyz,fsyz);
691 _syz.push_back(fsyz);
692 _n_syz++;
693 return SPAIR_SYZ;
694 }
695 else
696 _GR->gbvector_remove(fsyz);
697 }
698
699 return SPAIR_ZERO;
700}
701
703// Using _ar_i, _ar_j, reduce the gb element _ar_i wrt _ar_j.
704// Increment _ar_i, _ar_j as needed. If done, return false.
705{
706 if (_ar_j >= _n_gb)
707 {
708 _ar_i++;
709 _ar_j = _ar_i + 1;
710 if (_ar_j >= _n_gb) return false;
711 }
712 // Now compute gb(i) := gb(i) - c gb(j), where
713 // c in(gb(j)) is a term in gb(i).
714 // Also compute change(i) -= c change(j).
715
716 _GR->gbvector_auto_reduce(_F,
717 _Fsyz,
718 _gb[_ar_i]->f,
719 _gb[_ar_i]->fsyz,
720 _gb[_ar_j]->f,
721 _gb[_ar_j]->fsyz);
722 _ar_j++;
723 return true;
724}
725
727// Compute the new s-pairs associated to the given gb element.
728// Increment '_np_i'. If done with all pairs in this
729// degree, return false.
730{
731 if (_np_i >= _n_gb) return false;
732 find_pairs(_gb[_np_i]);
733 _np_i++;
734 return true;
735}
736
737//---- Completion testing -----------------------------
738
740{
741 // This handles everything but _Stop.always, _Stop.degree_limit
742 if (_state == GB_COMP_DONE) return COMP_DONE;
743 if (stop_.basis_element_limit > 0 && _n_gb > stop_.basis_element_limit)
744 return COMP_DONE_GB_LIMIT;
745 if (stop_.syzygy_limit > 0 && _n_syz > stop_.syzygy_limit)
746 return COMP_DONE_SYZ_LIMIT;
747 if (stop_.pair_limit > 0 && _n_pairs_computed > stop_.pair_limit)
749 if (stop_.just_min_gens && _n_gens_left == 0) return COMP_DONE_MIN_GENS;
750 if (stop_.subring_limit > 0 && _n_subring > stop_.subring_limit)
752 if (stop_.use_codim_limit)
753 {
754 // Compute the codimension
755 int c = 0;
756 // int c = codim_of_lead_terms();
757 if (c >= stop_.codim_limit) return COMP_DONE_CODIM;
758 }
759 return COMP_COMPUTING;
760}
761
763{
764 s_pair *p, *q;
765 int result = 0;
766 p = _spairs->remove();
767 q = _gens->remove();
768 if (p != nullptr)
769 {
770 result = p->degree;
771 if (q != nullptr && q->degree < p->degree) result = q->degree;
772 }
773 else if (q != nullptr)
774 result = q->degree;
775 else
776 assert(0);
777 if (p != nullptr) _spairs->put_back(p);
778 if (q != nullptr) _gens->put_back(q);
779 return result;
780}
781
783{
784// Computes the Hilbert function of an array of gbvector's...
785// using also the degrees of _F.
786// Don't forget the quotient monomials too!
787// Returns NULL if interrupted.
788#ifdef DEVELOPMENT
789#warning "not implemented yet"
790#endif
791 return nullptr;
792}
793
794//---- state machine (roughly) for the computation ----
795
797{
799
800 for (;;)
801 {
802 if (is_done != COMP_COMPUTING) break;
803 is_done = computation_is_complete();
804 if (is_done != COMP_COMPUTING) break;
805 if (system_interrupted())
806 {
807 is_done = COMP_INTERRUPTED;
808 break;
809 }
810
811 switch (_state)
812 {
814 if (_spairs->n_elems() == 0 && _gens->n_elems() == 0)
815 {
817 is_done = COMP_DONE;
818 break;
819 }
821 if (stop_.stop_after_degree &&
822 _this_degree > stop_.degree_limit->array[0])
823 {
824 is_done = COMP_DONE_DEGREE_LIMIT;
825 break;
826 }
827
828 if (_use_hilb)
829 {
830 if (_hilb_new_elems)
831 {
832 // Recompute h, _hf_diff
834 if (h == nullptr)
835 {
836 is_done = COMP_INTERRUPTED;
837 break;
838 }
839 _hf_diff = (*h) - (*_hf_orig);
840 _hilb_new_elems = false;
841 }
843 if (error())
844 {
845 is_done = COMP_ERROR;
846 break;
847 }
849 }
850 if (M2_gbTrace >= 1)
851 {
852 buffer o;
853 o << '{' << _this_degree << '}';
854 o << '(';
855 if (_use_hilb) o << _hilb_n_in_degree << ',';
856 o << _spairs->n_elems() << ')';
857 emit_wrapped(o.str());
858 }
859
860 // Set state information for auto reduction, new pairs
861 _ar_i = _n_gb;
862 _ar_j = _ar_i + 1;
863 _np_i = _n_gb;
865 break;
866
867 case GB_COMP_S_PAIRS:
868 if (M2_gbTrace < 2)
869 {
871 }
872 else
873 switch (s_pair_step())
874 {
875 case SPAIR_MINGEN:
876 emit_wrapped("g");
877 break;
878 case SPAIR_GB:
879 emit_wrapped("m");
880 break;
881 case SPAIR_SYZ:
882 emit_wrapped("z");
883 break;
884 case SPAIR_ZERO:
885 emit_wrapped("o");
886 break;
887 case SPAIR_DONE:
889 break;
890 default:
891 emit_wrapped("ERROR");
892 break;
893 }
894 break;
895
896 case GB_COMP_GENS:
897 if (M2_gbTrace < 2)
898 {
900 }
901 else
902 switch (gen_step())
903 {
904 case SPAIR_MINGEN:
905 emit_wrapped("g");
906 break;
907 case SPAIR_SYZ:
908 emit_wrapped("z");
909 break;
910 case SPAIR_ZERO:
911 emit_wrapped("o");
912 break;
913 case SPAIR_DONE:
915 break;
916 default:
917 emit_wrapped("ERROR");
918 break;
919 }
920 break;
921
923 if (!auto_reduce_step())
924 {
926 if ((_strategy & STRATEGY_SORT) != 0)
927 {
928 gb_sort(
929 _np_i,
930 _n_gb - 1); // This is the range of elements to sort.
931 }
932 for (int j = _np_i; j < _n_gb; j++) _gb[j]->me = j;
933 }
934 break;
935
936 case GB_COMP_NEWPAIRS:
938 break;
939
940 case GB_COMP_DONE:
941 break;
942
944 is_done = COMP_NEED_RESIZE;
945 break;
946 }
947 }
948 if (M2_gbTrace >= 1) emit_line("");
949 if (M2_gbTrace >= 4)
950 {
951 buffer o;
952 o << "Number of gb elements = " << _n_gb << newline;
953 o << "Number of gcd=1 pairs = " << _n_saved_gcd << newline;
954 o << "Number of pairs computed = " << _n_pairs_computed << newline;
955 o << "Number of reductions = " << _n_reductions << newline;
956 emit(o.str());
957 }
958
959 // _GR->memstats();
960 set_status(is_done);
961}
962
963//--- Obtaining matrices as output -------
964
966{
967 if (q == nullptr) return;
968 buffer o;
969 o << "(" << q->compare_num << " ";
970 if (q->first != nullptr)
971 o << q->first->me;
972 else
973 o << ".";
974 o << " ";
975 if (q->second != nullptr)
976 o << q->second->me;
977 else
978 o << ".";
979 o << " ";
980 _M->elem_text_out(o, q->lcm);
981 o << ") ";
982 emit_wrapped(o.str());
983}
984
986// Top level Computation routines //
988
990{
991 // TODO Problems here:
992 // -- check that the ring is correct
993 // -- if the computation has already been started, this will fail
994 // So probably an error should be given, and 0 returned in this case.
995 _hf_orig = hf;
997 _use_hilb = true;
998 _hilb_new_elems = true;
999 return this;
1000}
1001
1002const Matrix /* or null */ *GB_comp::get_gb()
1003{
1005 MatrixConstructor mat(_F, 0);
1006 for (int i = 0; i < _gb.size(); i++)
1007 {
1008 vec v = originalR->translate_gbvector_to_vec(_F, _gb[i]->f);
1009 mat.append(v);
1010 }
1011 return mat.to_matrix();
1012 // TODO NOW sort it, and auto-reduce it
1013}
1014
1015const Matrix /* or null */ *GB_comp::get_mingens()
1016{
1018 MatrixConstructor mat(_F, 0);
1019 for (int i = 0; i < _gb.size(); i++)
1020 if (_gb[i]->is_min)
1021 mat.append(originalR->translate_gbvector_to_vec(_F, _gb[i]->f));
1022 return mat.to_matrix();
1023}
1024
1025const Matrix /* or null */ *GB_comp::get_change()
1026{
1028 MatrixConstructor mat(_Fsyz, 0);
1029 for (int i = 0; i < _gb.size(); i++)
1030 mat.append(originalR->translate_gbvector_to_vec(_Fsyz, _gb[i]->fsyz));
1031 return mat.to_matrix();
1032}
1033
1034const Matrix /* or null */ *GB_comp::get_syzygies()
1035{
1037 MatrixConstructor mat(_Fsyz, 0);
1038 for (int i = 0; i < _syz.size(); i++)
1039 mat.append(originalR->translate_gbvector_to_vec(_Fsyz, _syz[i]));
1040 return mat.to_matrix();
1041}
1042
1043const Matrix /* or null */ *GB_comp::get_initial(int nparts)
1044{
1046 MatrixConstructor mat(_F, 0);
1047 for (int i = 0; i < _gb.size(); i++)
1048 {
1049 gbvector *f = _GR->gbvector_lead_term(nparts, _F, _gb[i]->f);
1050 mat.append(originalR->translate_gbvector_to_vec(_F, f));
1051 }
1052 // TODO: sort this list. This sort order will affect:
1053 // get_matrix, get_change, and of course this one.
1054 return mat.to_matrix();
1055}
1056
1058{
1060 MatrixConstructor mat(_F, 0);
1061 for (int i = 0; i < _gb.size(); i++)
1062 {
1063 gbvector *f =
1064 _GR->gbvector_parallel_lead_terms(w, _F, _gb[i]->f, _gb[i]->f);
1065 mat.append(originalR->translate_gbvector_to_vec(_F, f));
1066 }
1067 return mat.to_matrix();
1068}
1069
1070const Matrix /* or null */ *GB_comp::matrix_remainder(const Matrix *m)
1071{
1072 if (m->get_ring() != originalR)
1073 {
1074 ERROR("expected matrix over the same ring");
1075 return nullptr;
1076 }
1077
1078 if (m->n_rows() != _F->rank())
1079 {
1080 ERROR("expected matrices to have same number of rows");
1081 return nullptr;
1082 }
1084 MatrixConstructor red(m->rows(), m->cols(), m->degree_shift());
1085 for (int i = 0; i < m->n_cols(); i++)
1086 {
1087 ring_elem denom;
1088 gbvector *f = originalR->translate_gbvector_from_vec(_F, (*m)[i], denom);
1089 gbvector *fsyz = _GR->gbvector_zero();
1090
1091 gb_reduce(f, fsyz);
1092
1093 vec fv = originalR->translate_gbvector_to_vec_denom(_F, f, denom);
1094 red.set_column(i, fv);
1095 }
1096 return red.to_matrix();
1097}
1098
1100 const Matrix /* or null */ **result_remainder,
1101 const Matrix /* or null */ **result_quotient)
1102{
1103 if (m->get_ring() != originalR)
1104 {
1105 ERROR("expected matrix over the same ring");
1106 *result_remainder = nullptr;
1107 *result_quotient = nullptr;
1108 return false;
1109 }
1110 if (m->n_rows() != _F->rank())
1111 {
1112 ERROR("expected matrices to have same number of rows");
1113 *result_remainder = nullptr;
1114 *result_quotient = nullptr;
1115 return false;
1116 }
1118 MatrixConstructor mat_remainder(m->rows(), m->cols(), m->degree_shift());
1119 MatrixConstructor mat_quotient(_Fsyz, 0);
1120 bool all_zeroes = true;
1121 for (int i = 0; i < m->n_cols(); i++)
1122 {
1123 ring_elem denom;
1124 gbvector *f = originalR->translate_gbvector_from_vec(_F, (*m)[i], denom);
1125 gbvector *fsyz = _GR->gbvector_zero();
1126
1127 gb_reduce(f, fsyz);
1128 if (f != nullptr) all_zeroes = false;
1129
1130 vec fv = originalR->translate_gbvector_to_vec_denom(_F, f, denom);
1131 _K->negate_to(denom);
1132 vec fsyzv =
1133 originalR->translate_gbvector_to_vec_denom(_Fsyz, fsyz, denom);
1134 mat_remainder.set_column(i, fv);
1135 mat_quotient.append(fsyzv);
1136 }
1137 *result_remainder = mat_remainder.to_matrix();
1138 *result_quotient = mat_quotient.to_matrix();
1139 return all_zeroes;
1140}
1141
1143// Return -1 if every column of 'm' reduces to zero.
1144// Otherwise return the index of the first column that
1145// does not reduce to zero.
1146{
1147 if (m->get_ring() != originalR)
1148 {
1149 ERROR("expected matrix over the same ring");
1150 return -2;
1151 }
1152 // Reduce each column of m one by one.
1154 for (int i = 0; i < m->n_cols(); i++)
1155 {
1156 ring_elem denom;
1157 gbvector *f = originalR->translate_gbvector_from_vec(_F, (*m)[i], denom);
1158 _K->remove(denom);
1159 gbvector *fsyz = nullptr;
1160 gb_reduce(f, fsyz);
1161 _GR->gbvector_remove(fsyz);
1162 if (f != nullptr)
1163 {
1164 _GR->gbvector_remove(f);
1165 return i;
1166 }
1167 }
1168 return -1;
1169}
1170
1172// The computation is complete up through this degree.
1173{
1174 return _this_degree - 1;
1175}
1176
1178/* This displays statistical information, and depends on the
1179 M2_gbTrace value */
1180{
1181 _spairs->stats();
1182 if (M2_gbTrace >= 5 && M2_gbTrace % 2 == 1)
1183 for (int i = 0; i < _gb.size(); i++)
1184 {
1185 o << i << '\t';
1186 _GR->gbvector_text_out(o, _F, _gb[i]->f);
1187 o << newline;
1188 }
1189}
1190
1191// Local Variables:
1192// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1193// indent-tabs-mode: nil
1194// End:
exponents::Exponents exponents_t
enum ComputationStatusCode set_status(enum ComputationStatusCode)
Definition comp.cpp:66
StopConditions stop_
Definition comp.hpp:75
Computation()
Definition comp.cpp:40
FreeModule * sub_space(int n) const
Definition freemod.cpp:197
virtual const Matrix * get_change()
RingElement * compute_hilbert_function() const
int _n_pairs_computed
Definition gb-homog2.hpp:94
void gb_geo_reduce(gbvector *&f, gbvector *&fsyz)
void gb_sort(int lo, int hi)
int _n_gb
Definition gb-homog2.hpp:92
void gb_reduce(gbvector *&f, gbvector *&fsyz)
int _n_syz
Definition gb-homog2.hpp:96
int _state
Definition gb-homog2.hpp:78
const Ring * _K
Definition gb-homog2.hpp:71
void start_computation()
const FreeModule * _Fsyz
Definition gb-homog2.hpp:74
s_pair * new_ring_pair(gb_elem *p, const int *lcm)
bool _hilb_new_elems
virtual const Matrix * get_gb()
virtual M2_bool matrix_lift(const Matrix *m, const Matrix **result_remainder, const Matrix **result_quotient)
int _n_subring
Definition gb-homog2.hpp:95
void remove_pair(s_pair *&p)
int s_pair_step()
const Monoid * _M
Definition gb-homog2.hpp:70
bool _collect_syz
void find_pairs(gb_elem *p)
static GB_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)
virtual const Matrix * get_initial(int nparts)
int _ar_i
Definition gb-homog2.hpp:79
void initialize0(const Matrix *m, int csyz, int nsyz, M2_arrayint gb_weights)
Definition gb-homog2.cpp:28
virtual const Matrix * get_mingens()
int _ar_j
Definition gb-homog2.hpp:79
const FreeModule * _F
Definition gb-homog2.hpp:73
void gb_insert(gbvector *f, gbvector *fsyz, int ismin)
virtual void text_out(buffer &o) const
virtual int complete_thru_degree() const
s_pair * new_var_pair(gb_elem *p, const int *lcm)
virtual int contains(const Matrix *m)
s_pair_heap * _gens
Definition gb-homog2.hpp:83
int gb_sort_partition(int lo, int hi)
int _n_gens_left
Definition gb-homog2.hpp:93
bool _use_hilb
const GBWeight * weightInfo_
Definition gb-homog2.hpp:69
int _this_degree
Definition gb-homog2.hpp:75
s_pair * new_s_pair(gb_elem *p, gb_elem *q, const int *lcm)
void compute_s_pair(s_pair *p)
int _n_rows_per_syz
int gen_step()
s_pair_heap * _spairs
Definition gb-homog2.hpp:82
GBRing * _GR
Definition gb-homog2.hpp:68
const PolynomialRing * originalR
Definition gb-homog2.hpp:67
void initialize(const Matrix *m, int csyz, int nsyz, M2_arrayint gb_weights, int strategy)
Definition gb-homog2.cpp:84
int next_degree()
RingElement * _hf_diff
virtual const Matrix * get_syzygies()
virtual const Matrix * matrix_remainder(const Matrix *m)
virtual Computation * set_hilbert_function(const RingElement *h)
ComputationStatusCode computation_is_complete() const
int _n_reductions
Definition gb-homog2.hpp:99
virtual const Matrix * get_parallel_lead_terms(M2_arrayint w)
s_pair * new_gen(int i, gbvector *f, ring_elem denom)
void flush_pairs(int deg)
int _n_saved_hilb
bool _is_ideal
bool auto_reduce_step()
int _hilb_n_in_degree
const RingElement * _hf_orig
int _np_i
Definition gb-homog2.hpp:80
bool new_pairs_step()
void debug_out(s_pair *q) const
virtual ~GB_comp()
int _strategy
int _n_saved_gcd
Definition gb-homog2.hpp:98
Heuristic-weight evaluator for gbvectors, used during Groebner basis computation to drive the S-pair ...
Definition gbweight.hpp:67
const_monomial degree_shift() const
Definition matrix.hpp:149
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
Matrix * to_matrix()
void append(vec v)
void set_column(int c, vec v)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
int insert(Bag *b)
Definition monideal.cpp:622
Nmi_node * mi
Definition monideal.hpp:138
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
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
const Ring * get_ring() const
Definition relem.hpp:81
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
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
static int coeff_of(const RingElement *h, int deg)
Definition hilb.cpp:704
int basis_elem() const
Definition int-bag.hpp:66
void * basis_ptr() const
Definition int-bag.hpp:67
const int SPAIR_ZERO
Definition comp-gb.hpp:53
const int SPAIR_PAIR
Definition comp-gb.hpp:56
const int SPAIR_DONE
Definition comp-gb.hpp:50
const int SPAIR_GB
Definition comp-gb.hpp:51
const int SPAIR_SYZ
Definition comp-gb.hpp:52
const int SPAIR_RING
Definition comp-gb.hpp:57
const int SPAIR_GEN
Definition comp-gb.hpp:55
const int SPAIR_MINGEN
Definition comp-gb.hpp:54
@ STRATEGY_LONGPOLYNOMIALS
@ STRATEGY_SORT
ComputationStatusCode
Definition computation.h:53
@ COMP_DONE_MIN_GENS
Definition computation.h:68
@ 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_DEGREE_LIMIT
Definition computation.h:61
@ COMP_DONE_CODIM
Definition computation.h:67
@ 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
const int GB_COMP_DONE
Definition gb-homog2.hpp:56
const int GB_COMP_NEWPAIRS
Definition gb-homog2.hpp:55
const int GB_COMP_GENS
Definition gb-homog2.hpp:53
const int GB_COMP_AUTO_REDUCE
Definition gb-homog2.hpp:54
const int GB_COMP_NEED_RESIZE
Definition gb-homog2.hpp:51
const int GB_COMP_S_PAIRS
Definition gb-homog2.hpp:52
const int GB_COMP_NEWDEGREE
Definition gb-homog2.hpp:50
GB_comp — Buchberger GB specialised to homogeneous input.
#define monomial
Definition gb-toric.cpp:11
int p
Hilbert-series numerator via the Bigatti-Caboara-Robbiano recursion.
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 ZERO_RINGELEM
Definition ring.hpp:677
gbvector * fsyz
Definition spair.hpp:59
gbvector * f
Definition spair.hpp:58
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
int degree
Definition spair.hpp:94
gb_elem * second
Definition spair.hpp:97
int syz_type
Definition spair.hpp:92
gb_elem * first
Definition spair.hpp:96
int compare_num
Definition spair.hpp:93
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.