Macaulay2 Engine
Loading...
Searching...
No Matches
reducedgb-field-local.cpp
Go to the documentation of this file.
1// Copyright 2005, Michael E. Stillman
2
4#include "monideal.hpp"
5#include "montable.hpp"
6#include "gbweight.hpp"
7#include "polyring.hpp"
8#include <functional>
9#include <algorithm>
10#include "text-io.hpp"
11
14 const PolynomialRing *originalR0,
15 const FreeModule *F0,
16 const FreeModule *Fsyz0,
17 const GBWeight *wt0)
18 : ReducedGB_Field(R0, originalR0, F0, Fsyz0),
19 T1(nullptr),
20 wt(wt0)
21{
22 // fprintf(stderr, "creating GB with local order\n");
23 if (wt == nullptr) wt = new GBWeight(F0, nullptr);
24 for (int i = 0; i < originalR0->n_quotients(); i++)
25 {
26 int f_lead_wt;
27 const gbvector *f = originalR0->quotient_gbvector(i);
28 int d = wt->gbvector_weight(f, f_lead_wt);
29 int a = d - f_lead_wt;
30
32 t.g.f = const_cast<gbvector *>(f);
33 t.g.fsyz = nullptr;
34 t.size = R->gbvector_n_terms(f);
35 t.alpha = a;
36
37 ring_elems.push_back(t);
38 }
39}
40
54{
56 const FreeModule *F;
57 const VECTOR(POLY) & gb;
58 std::vector<int> degs;
60 const FreeModule *F0,
61 const VECTOR(POLY) & gb0)
62 : R(R0), F(F0), gb(gb0)
63 {
64 auto M = R->get_flattened_monoid();
65 for (size_t i = 0; i < gb0.size(); i++)
66 {
67 gbvector *f = gb0[i].f;
68 degs.push_back(M->simple_degree(f->monom));
69 }
70 }
71 bool operator()(int xx, int yy)
72 {
73 // this is the < operation
74 if (degs[xx] < degs[yy]) return true;
75 if (degs[xx] > degs[yy]) return false;
76 gbvector *x = gb[xx].f;
77 gbvector *y = gb[yy].f;
78 return R->gbvector_compare(F, x, y) == LT;
79 }
80};
81
83 bool auto_reduced)
84{
85 // First sort these elements via increasing lex order (or monomial order?)
86 // Next insert minimal elements into T, and polys
87
88 VECTOR(int) positions;
89 positions.reserve(polys0.size());
90
91 for (int i = 0; i < polys0.size(); i++) positions.push_back(i);
92
93 // displayElements("-- before sort --", R, polys0, [](auto& g) { return g.f;
94 // } );
95
96 std::stable_sort(positions.begin(),
97 positions.end(),
99
100 // VECTOR(gbvector*) sorted_elements_debug_only;
101 // for (int i=0; i<positions.size(); i++)
102 // sorted_elements_debug_only.push_back(polys0[positions[i]].f);
103 // displayElements("-- after sort --", R, sorted_elements_debug_only,
104 // [](auto& g) { return g; } );
105
106 // Now loop through each element, and see if the lead monomial is in T.
107 // If not, add it in , and place element into 'polys'.
108
109 for (VECTOR(int)::iterator i = positions.begin(); i != positions.end(); i++)
110 {
111 Bag *not_used;
112 gbvector *f = polys0[*i].f;
113 exponents_t e = R->exponents_make();
114 R->gbvector_get_lead_exponents(F, f, e);
115 if ((!Rideal || !Rideal->search_expvector(e, not_used)) &&
116 T->find_divisors(1, e, f->comp) == 0)
117 {
118 // Keep this element
119
120 POLY h;
121 ring_elem junk;
122
123 h.f = R->gbvector_copy(f);
124 h.fsyz = R->gbvector_copy(polys0[*i].fsyz);
125
126 if (false and auto_reduced)
127 remainder(h, false, junk); // This auto-reduces h.
128
129 R->gbvector_remove_content(h.f, h.fsyz);
130
131 T->insert(e, f->comp, INTSIZE(polys));
132 polys.push_back(h);
133 }
134 else
135 R->exponents_delete(e);
136 }
137
138 for (int i = 0; i < polys.size(); i++)
139 {
140 int f_lead_wt;
141 gbvector *f = polys[i].f;
142 int d = wt->gbvector_weight(f, f_lead_wt);
143 int a = d - f_lead_wt;
144
145 divisor_info t;
146 t.g = polys[i];
147 t.size = R->gbvector_n_terms(f);
148 t.alpha = a;
149 gb_elems.push_back(t);
150 }
151}
152
153#if 0
154// old code
156 bool auto_reduced)
157{
158 // auto_reduced flag is ignored, since it can lead to infinite loops here
159 ReducedGB_Field::minimalize(polys0,false);
160
161 //displayElements("-- after minimize in field case -- ", R, polys, [](const POLY& g) { return g.f; } );
162
163 for (int i=0; i<polys.size(); i++)
164 {
165 int f_lead_wt;
166 gbvector *f = polys[i].f;
167 int d = wt->gbvector_weight(f,f_lead_wt);
168 int a = d - f_lead_wt;
169
170 divisor_info t;
171 t.g = polys[i];
172 t.size = R->gbvector_n_terms(f);
173 t.alpha = a;
174 gb_elems.push_back(t);
175
176 // gb_elems.push_back({polys[i], R->gbvector_n_terms(f), a});
177 }
178}
179#endif
180
182 exponents_t h_exp,
183 int h_comp,
184 int h_deg,
185 int &h_alpha, // result value
186 POLY &result_g, // result value
187 int &result_g_alpha) // result value
188{
190 MonomialTable *ringtable = originalR->get_quotient_MonomialTable();
191
192 h_alpha = h_deg - wt->exponents_weight(h_exp, h_comp);
193
194 int n0 = (ringtable ? ringtable->find_divisors(-1, h_exp, 1, &divisors) : 0);
195 int n1 = T1->find_divisors(-1, h_exp, h_comp, &divisors);
196 int n2 = T->find_divisors(-1, h_exp, h_comp, &divisors);
197 int n = INTSIZE(divisors);
198 if (n == 0) return false;
199
200 divisor_info *div_info = newarray(divisor_info, divisors.size());
201
202 int next = 0;
203
204 // ring divisors
205 for (int i = 0; i < n0; i++)
206 {
207 int id = divisors[i]->_val;
208 div_info[next++] = ring_elems[id];
209 }
210 // new divisors
211 for (int i = 0; i < n1; i++)
212 {
213 int id = divisors[n0 + i]->_val;
214 div_info[next++] = new_poly_elems[id];
215 }
216 // gb divisors
217 for (int i = 0; i < n2; i++)
218 {
219 int id = divisors[n0 + n1 + i]->_val;
220 div_info[next++] = gb_elems[id];
221 }
222
223 if (M2_gbTrace >= 4)
224 {
225 buffer o;
226 o << "\nfind good divisor:";
227 if (n0 > 0)
228 {
229 o << "\n ndivisors from quotient ring elements " << n0;
230 for (int j = 0; j < n0; j++)
231 {
232 divisor_info &t = div_info[j];
233 o << "\n size " << t.size << " alpha " << t.alpha << " lead ";
234 gbvector *f = R->gbvector_lead_term(-1, F, t.g.f);
235 R->gbvector_text_out(o, F, f);
236 R->gbvector_remove(f);
237 }
238 }
239 if (n1 > 0)
240 {
241 o << "\n ndivisors from appended elements " << n1;
242 for (int j = 0; j < n1; j++)
243 {
244 divisor_info &t = div_info[n0 + j];
245 o << "\n size " << t.size << " alpha " << t.alpha << " lead ";
246 gbvector *f = R->gbvector_lead_term(-1, F, t.g.f);
247 R->gbvector_text_out(o, F, f);
248 R->gbvector_remove(f);
249 }
250 }
251 if (n2 > 0)
252 {
253 o << "\n ndivisors from gb elements " << n1;
254 for (int j = 0; j < n2; j++)
255 {
256 divisor_info &t = div_info[n0 + n1 + j];
257 o << "\n size " << t.size << " alpha " << t.alpha << " lead ";
258 gbvector *f = R->gbvector_lead_term(-1, F, t.g.f);
259 R->gbvector_text_out(o, F, f);
260 R->gbvector_remove(f);
261 }
262 }
263 emit(o.str());
264 }
265
266 // Now all of the desired elements are in div_info
267 // First, find the minimum alpha value
268 int min_alpha = div_info[0].alpha;
269 for (int i = 1; i < n; i++)
270 if (div_info[i].alpha < min_alpha) min_alpha = div_info[i].alpha;
271 result_g_alpha = min_alpha;
272
273 int min_size = -1;
274 int result_i = -1;
275 int nmatches = 0;
276 // Now, out of the ones with this alpha, find the minimum size
277 for (int i = 0; i < n; i++)
278 {
279 if (div_info[i].alpha == min_alpha)
280 {
281 int this_size = div_info[i].size;
282 if (min_size < 0 || this_size < min_size)
283 {
284 min_size = this_size;
285 result_i = i;
286 nmatches = 1;
287 }
288 else if (this_size == min_size)
289 {
290 nmatches++;
291 }
292 }
293 }
294
295 if (nmatches > 1 && M2_gbTrace == 3)
296 {
297 buffer o;
298 o << nmatches;
299 emit_wrapped(o.str());
300 }
301
302 // At this point, result_i points to the element we wish to return
303 assert(result_i >= 0);
304 result_g = div_info[result_i].g;
305
306 if (M2_gbTrace >= 4)
307 {
308 buffer o;
309 if (nmatches > 1) o << "\n nmatches " << n;
310 o << "\n chosen value: ";
311 int size = R->gbvector_n_terms(result_g.f);
312 o << "\n size " << size << " alpha " << result_g_alpha << " lead ";
313 gbvector *f = R->gbvector_lead_term(-1, F, result_g.f);
314 R->gbvector_text_out(o, F, f);
315 R->gbvector_remove(f);
316 emit(o.str());
317 }
318
319 return true;
320
321#if 0
322
323 MonomialTable *ringtable = originalR->get_quotient_MonomialTable();
324 if (ringtable)
325 {
326 n = ringtable->find_divisors(-1, h_exp, 1, &divisors);
327
328 if (n > 0)
329 {
330 POLY p;
331 p.fsyz = 0;
332 for (int i=0; i<divisors.size(); i++)
333 {
334 MonomialTable::mon_term *t = divisors[i];
335 int id = t->_val;
336 p.f = const_cast<gbvector *>(originalR->quotient_gbvector(id));
337 int g_alpha = ring_alpha[id];
338 if (g_alpha <= h_alpha)
339 {
340 result_g = p;
341 result_g_alpha = g_alpha;
342 return true;
343 }
344 if (min_alpha < 0 || g_alpha < min_alpha)
345 {
346 min_alpha = g_alpha;
347 result_g = p;
348 result_g_alpha = g_alpha;
349 }
350 }
351 }
352 }
353 divisors.clear();
354
355 if (M2_gbTrace>=4)
356 {
357 buffer o;
358 o << "\nfind good divisor:";
359 emit(o.str());
360 }
361
362 // check the new polys
363 n = T1->find_divisors(-1, h_exp, h_comp, &divisors);
364 if (n > 0)
365 {
366 POLY p;
367 if (M2_gbTrace>=4)
368 {
369 buffer o;
370 o << "\n ndivisors from appended elements " << n;
371 for (int j=0; j<n; j++)
372 {
373 MonomialTable::mon_term *t = divisors[j];
374 int id = t->_val;
375 p = newpol[id];
376 int g_alpha = newpol_alpha[id];
377 int size = R->gbvector_n_terms(p.f);
378 o << "\n size " << size << " alpha " << g_alpha << " lead ";
379 gbvector *f = R->gbvector_lead_term(-1,F,p.f);
380 R->gbvector_text_out(o,F,f);
381 }
382 emit(o.str());
383 }
384 for (int i=0; i<divisors.size(); i++)
385 {
386 MonomialTable::mon_term *t = divisors[i];
387 int id = t->_val;
388 p = newpol[id];
389 int g_alpha = newpol_alpha[id];
390 if (result_g_alpha < 0 && g_alpha <= h_alpha)
391 {
392 result_g = p;
393 result_g_alpha = g_alpha;
394 min_alpha = g_alpha;
395 //break; //return true;
396 }
397 if (min_alpha < 0 || g_alpha < min_alpha)
398 {
399 min_alpha = g_alpha;
400 result_g = p;
401 result_g_alpha = g_alpha;
402 }
403 }
404 }
405 divisors.clear();
406
407 // Now check the GB itself
408 n = T->find_divisors(-1, h_exp, h_comp, &divisors);
409 if (n > 0)
410 {
411 POLY p;
412 if (M2_gbTrace>=4)
413 {
414 buffer o;
415 o << "\n ndivisors from GB " << n;
416 for (int j=0; j<n; j++)
417 {
418 MonomialTable::mon_term *t = divisors[j];
419 int id = t->_val;
420 p = polys[id];
421 int g_alpha = alpha[id];
422 int size = R->gbvector_n_terms(p.f);
423 o << "\n size " << size << " alpha " << g_alpha << " lead ";
424 gbvector *f = R->gbvector_lead_term(-1,F,p.f);
425 R->gbvector_text_out(o,F,f);
426 }
427 emit(o.str());
428 }
429
430 for (int i=0; i<divisors.size(); i++)
431 {
432 MonomialTable::mon_term *t = divisors[i];
433 int id = t->_val;
434 p = polys[id];
435 int g_alpha = alpha[id];
436 if (result_g_alpha < 0 && g_alpha <= h_alpha)
437 {
438 result_g = p;
439 result_g_alpha = g_alpha;
440 min_alpha = g_alpha;
441 //break;
442 //return true;
443 }
444 if (min_alpha < 0 || g_alpha < min_alpha)
445 {
446 min_alpha = g_alpha;
447 result_g = p;
448 result_g_alpha = g_alpha;
449 }
450 }
451 }
452 divisors.clear();
453
454
455 if (M2_gbTrace>=4)
456 {
457 buffer o;
458 o << "\n chosen value: ";
459 int size = R->gbvector_n_terms(result_g.f);
460 o << "\n size " << size << " alpha " << result_g_alpha << " lead ";
461 gbvector *f = R->gbvector_lead_term(-1,F,result_g.f);
462 R->gbvector_text_out(o,F,f);
463 R->gbvector_remove(f);
464 emit(o.str());
465 }
466
467 return (min_alpha >= 0);
468#endif
469}
470
472{
473 new_poly_elems.clear();
474 delete T1;
475}
476
478 exponents_t h_exp,
479 int h_comp,
480 int h_alpha)
481{
482 int id = INTSIZE(new_poly_elems);
483 divisor_info t;
484 t.g.f = R->gbvector_copy(h.f);
485 t.g.fsyz = R->gbvector_copy(h.fsyz);
486 t.alpha = h_alpha;
487 t.size = R->gbvector_n_terms(t.g.f);
488 new_poly_elems.push_back(t);
489 T1->insert(h_exp, h_comp, id); // grabs h_exp
490}
491
492void ReducedGB_Field_Local::remainder(POLY &f, bool use_denom, ring_elem &denom)
493{
494 if (M2_gbTrace >= 4) {
495 buffer o;
496 text_out(o);
497 emit(o.str());
498 }
499 if (f.f == nullptr) return;
500 T1 = MonomialTable::make(R->n_vars());
501 gbvector head;
502 gbvector *frem = &head;
503 frem->next = nullptr;
504 POLY h = f;
505 exponents_t h_exp = R->exponents_make();
506 int h_alpha, g_alpha;
507 int h_deg = wt->gbvector_weight(f.f);
508 while (!R->gbvector_is_zero(h.f))
509 {
510 if (M2_gbTrace == 3) emit_wrapped(".");
511 POLY g;
512 R->gbvector_get_lead_exponents(F, h.f, h_exp);
513 int h_comp = h.f->comp;
514
515 if (M2_gbTrace >= 4)
516 {
517 buffer o;
518 o << "\nreducing ";
519 R->gbvector_text_out(o, F, h.f);
520 emit(o.str());
521 }
522
523 if (find_good_divisor(h_exp,
524 h_comp,
525 h_deg,
526 h_alpha,
527 g,
528 g_alpha)) // sets these three values
529 {
530 if (M2_gbTrace >= 4)
531 {
532 buffer o;
533 o << " h_alpha " << h_alpha << " g_alpha "
534 << g_alpha; // << " reducing using ";
535 // R->gbvector_text_out(o,F,g.f);
536 // o << newline;
537 emit(o.str());
538 }
539 if (g_alpha > h_alpha)
540 {
541 if (head.next != nullptr)
542 {
543 // In this case, we can't reduce the tail without
544 // risking an infinite loop. So we declare ourselves done
545 // Attach the rest of h.f to frem
546 frem->next = h.f;
547 break;
548 }
549 // place h into T1, and store its (value,deg,alpha) values.
550 // store_in_table copies h
551 store_in_table(h, h_exp, h_comp, h_alpha);
552 if (M2_gbTrace == 3) emit_wrapped("x");
553 if (M2_gbTrace == 4) emit("\nstored result\n");
554 h_deg += g_alpha - h_alpha;
555 h_exp = R->exponents_make();
556 }
557 R->gbvector_reduce_lead_term(
558 F, Fsyz, head.next, h.f, h.fsyz, g.f, g.fsyz, use_denom, denom);
559 }
560 else
561 {
562 frem->next = h.f;
563 frem = frem->next;
564 h.f = h.f->next;
565 frem->next = nullptr;
566 }
567 }
568
569 f.f = head.next;
570 f.fsyz = h.fsyz;
571 R->exponents_delete(h_exp);
572 reset_table();
573}
574
576 bool use_denom,
577 ring_elem &denom)
578{
579 if (f == nullptr) return;
580
581 T1 = MonomialTable::make(R->n_vars());
582 gbvector *zero = nullptr;
583 gbvector head;
584 gbvector *frem = &head;
585 frem->next = nullptr;
586 POLY h;
587 h.f = f;
588 h.fsyz = nullptr;
589 exponents_t h_exp = R->exponents_make();
590 int h_alpha, g_alpha;
591 int h_deg = wt->gbvector_weight(f);
592 while (!R->gbvector_is_zero(h.f))
593 {
594 if (M2_gbTrace == 3) emit_wrapped(".");
595 POLY g;
596 R->gbvector_get_lead_exponents(F, h.f, h_exp);
597 int h_comp = h.f->comp;
598
599 if (M2_gbTrace >= 4)
600 {
601 buffer o;
602 o << "\nreducing ";
603 R->gbvector_text_out(o, F, h.f);
604 emit(o.str());
605 }
606
607 if (find_good_divisor(h_exp,
608 h_comp,
609 h_deg,
610 h_alpha,
611 g,
612 g_alpha)) // sets these three values
613 {
614 if (M2_gbTrace >= 4)
615 {
616 buffer o;
617 o << " h_alpha " << h_alpha << " g_alpha "
618 << g_alpha; // << " reducing using ";
619 // R->gbvector_text_out(o,F,g.f);
620 // o << newline;
621 emit(o.str());
622 }
623 if (g_alpha > h_alpha)
624 {
625 if (head.next != nullptr)
626 {
627 // In this case, we can't reduce the tail without
628 // risking an infinite loop. So we declare ourselves done
629 // Attach the rest of h.f to frem
630 frem->next = h.f;
631 break;
632 }
633 // place h into T1, and store its (value,deg,alpha) values.
634 store_in_table(h, h_exp, h_comp, h_alpha);
635 if (M2_gbTrace == 3) emit_wrapped("x");
636 if (M2_gbTrace == 4) emit("\nstored result\n");
637 h_deg += g_alpha - h_alpha;
638 h_exp = R->exponents_make();
639 }
640 R->gbvector_reduce_lead_term(
641 F, Fsyz, head.next, h.f, zero, g.f, zero, use_denom, denom);
642 }
643 else
644 {
645 frem->next = h.f;
646 frem = frem->next;
647 h.f = h.f->next;
648 frem->next = nullptr;
649 }
650 }
651
652 f = head.next;
653 R->exponents_delete(h_exp);
654 reset_table();
655}
656
657// Local Variables:
658// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
659// indent-tabs-mode: nil
660// End:
exponents::Exponents exponents_t
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
int gbvector_n_terms(const gbvector *f) const
Definition gbring.cpp:392
Polynomial-ring view tuned for the inner loop of classical Buchberger Groebner-basis computations.
Definition gbring.hpp:120
int gbvector_weight(const gbvector *f) const
Definition gbweight.cpp:93
Heuristic-weight evaluator for gbvectors, used during Groebner basis computation to drive the S-pair ...
Definition gbweight.hpp:67
static MonomialTable * make(int nvars)
Definition montable.cpp:61
int find_divisors(int max, exponents_t exp, int comp, VECTOR(mon_term *) *result=nullptr)
Definition montable.cpp:152
Indexed table of monomials with fast "find a divisor" lookup, keyed by a free integer val per entry.
Definition montable.hpp:81
int n_quotients() const
Definition polyring.hpp:219
const gbvector * quotient_gbvector(int i) const
Definition polyring.hpp:221
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual void remainder(POLY &f, bool use_denom, ring_elem &denom)
ReducedGB_Field_Local(GBRing *R0, const PolynomialRing *originalR0, const FreeModule *F0, const FreeModule *Fsyz0, const GBWeight *wt0)
bool find_good_divisor(exponents_t h_exp, int h_comp, int h_deg, int &h_alpha, POLY &result_g, int &result_g_alpha)
virtual void minimalize(const VECTOR(POLY) &polys0, bool auto_reduced)
void store_in_table(const POLY &h, exponents_t h_exp, int h_comp, int h_alpha)
ReducedGB_Field(GBRing *R0, const PolynomialRing *originalR0, const FreeModule *F0, const FreeModule *Fsyz0)
virtual void minimalize(const VECTOR(POLY) &polys0, bool auto_reduced)
const MonomialIdeal * Rideal
MonomialTable * T
virtual void text_out(buffer &o) const
const FreeModule * Fsyz
Definition reducedgb.hpp:67
GBRing * R
Definition reducedgb.hpp:64
const PolynomialRing * originalR
Definition reducedgb.hpp:65
const FreeModule * F
Definition reducedgb.hpp:66
char * str()
Definition buffer.hpp:72
void gb(IntermediateBasis &F, int n)
GBWeight — packed-weight evaluator that drives S-pair selection.
int p
int zero
int_bag Bag
Definition int-bag.hpp:70
int M2_gbTrace
Definition m2-types.cpp:52
MonomialIdeal — exponent-vector-only representation of an ideal generated by monomials.
MonomialTable — leading-monomial divisor index used by the GB reducer.
#define VECTOR(T)
Definition newdelete.hpp:78
#define newarray(T, len)
Definition newdelete.hpp:82
volatile int x
#define POLY(q)
Definition poly.cpp:23
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
Doubly-linked-list node of a MonomialTable's per-component monomial list.
Definition montable.hpp:109
gbvector * fsyz
Definition gbring.hpp:99
gbvector * f
Definition gbring.hpp:98
Per-element bookkeeping record used by ReducedGB_Field_Local during local-ring GB minimisation.
ReducedGB_Field_Local_sorter(GBRing *R0, const FreeModule *F0, const VECTOR(POLY) &gb0)
Index comparator used to permute ReducedGB_Field_Local's gb array into canonical reduced-GB order for...
gbvector * next
Definition gbring.hpp:80
int monom[1]
Definition gbring.hpp:83
int comp
Definition gbring.hpp:82
const int LT
Definition style.hpp:39
#define INTSIZE(a)
Definition style.hpp:37
void emit_wrapped(const char *s)
Definition text-io.cpp:27
void emit(const char *s)
Definition text-io.cpp:41
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.