Macaulay2 Engine
Loading...
Searching...
No Matches
Eschreyer.cpp
Go to the documentation of this file.
1// Copyright 1999 Michael E. Stillman
2
31
32#include "Eschreyer.hpp"
33#include "matrix.hpp"
34#include "monoid.hpp"
35#include "text-io.hpp"
36#include "gbring.hpp"
37#include "matrix-con.hpp"
38
39GBMatrix::GBMatrix(const FreeModule *F0) : F(F0) {}
40
41GBMatrix::GBMatrix(const Matrix *m) : F(m->rows())
42{
43 const PolynomialRing *R = F->get_ring()->cast_to_PolynomialRing();
44 assert(R != 0);
45 for (int i = 0; i < m->n_cols(); i++)
46 {
47 ring_elem denom;
48 gbvector *g = R->translate_gbvector_from_vec(F, m->elem(i), denom);
49 append(g);
50 }
51}
52
53void GBMatrix::append(gbvector *g) { elems.push_back(g); }
54
56{
57 const PolynomialRing *R = F->get_ring()->cast_to_PolynomialRing();
58 assert(R != 0);
60 MatrixConstructor mat(F, G);
61 for (int i = 0; i < elems.size(); i++)
62 {
63 vec v = R->translate_gbvector_to_vec(F, elems[i]);
64 mat.set_column(i, v);
65 }
66 return mat.to_matrix();
67}
68
70 : F(m->get_free_module()),
71 n_ones(0),
72 n_unique(0),
73 n_others(0),
75{
76 const PolynomialRing *R0 = F->get_ring()->cast_to_PolynomialRing();
77 GR = R0->get_gb_ring();
78 R = R0;
79 K = R->getCoefficients();
80 M = R->getMonoid();
81
83 SF = F->get_schreyer_order();
84 SG = G->get_schreyer_order();
85
86 exp_size = EXPONENT_BYTE_SIZE(M->n_vars());
87 monom_size = MONOMIAL_BYTE_SIZE(M->monomial_size());
88
89 // Set 'gb'.
90 strip_gb(m);
91}
92
94{
95 // Remove gb
96 // Remove syzygies
97 // Remove mi
98}
99
101{
102 // First find the skeleton
103 for (int i = 0; i < gb.size(); i++) new_pairs(i);
104
105 // Debug code
106 GBMatrix *mm = new GBMatrix(G);
107 for (int p = 0; p < syzygies.size(); p++)
108 mm->append(GR->gbvector_copy(syzygies[p]));
109 buffer o;
110 Matrix *m = mm->to_matrix();
111 if (M2_gbTrace >= 5)
112 {
113 o << "skeleton = " << newline;
114 m->text_out(o);
115 emit(o.str());
116 }
117
118 // Sort the skeleton now?
119
120 // Now reduce each one of these elements
121 for (int j = 0; j < syzygies.size(); j++)
122 {
123 gbvector *v = s_pair(syzygies[j]);
124 reduce(v, syzygies[j]);
125 }
126 return COMP_DONE;
127}
128
130{
131 // Make the Schreyer free module H.
132 GBMatrix *result = new GBMatrix(G);
133 for (int i = 0; i < syzygies.size(); i++)
134 {
135 result->append(syzygies[i]);
136 syzygies[i] = nullptr;
137 }
138 return result;
139}
140
142// Private routines //
146 int comp) const
147// c is an element of GR->get_flattened_coefficients()
148// (m,comp) is a Schreyer encoded monomial in Fsyz
149{
150#ifdef DEVELOPMENT
151#warning "this might add in the Schreyer up"
152#warning "the previous warning message is confusing, grammatically"
153#endif
154
155 return GR->gbvector_raw_term(c, m, comp);
156}
157
159{
160 const gc_vector<gbvector*> &g = m->elems;
161 int i;
162 int *components = newarray_atomic_clear(int, F->rank());
163 for (i = 0; i < g.size(); i++)
164 if (g[i] != nullptr) components[g[i]->comp - 1]++;
165
166 for (i = 0; i < g.size(); i++)
167 {
168 gbvector head;
169 gbvector *last = &head;
170 for (gbvector *v = g[i]; v != nullptr; v = v->next)
171 if (components[v->comp - 1] > 0)
172 {
173 gbvector *t = GR->gbvector_copy_term(v);
174 last->next = t;
175 last = t;
176 }
177 last->next = nullptr;
178 gb.push_back(head.next);
179 }
180 for (i = 0; i < F->rank(); i++) mi.push_back(new MonomialIdeal(R));
181 freemem(components);
182}
183
185// Create and insert all of the pairs which will have lead term 'gb[i]'.
186// This also places 'in(gb[i])' into the appropriate monomial ideal
187{
188 gc_vector<Bag*> elems;
189 gc_vector<int> vp; // This is 'p'.
190 gc_vector<int> thisvp;
191
192 if (SF)
193 {
195 SF->schreyer_down(gb[i]->monom, gb[i]->comp - 1, PAIRS_mon);
196 M->to_varpower(PAIRS_mon, vp);
197 }
198 else
199 M->to_varpower(gb[i]->monom, vp);
200
201 // First add in syzygies arising from exterior variables
202 // At the moment, there are none of this sort.
203
204 if (R->is_skew_commutative())
205 {
206 exponents_t find_pairs_exp = newarray_atomic(int, M->n_vars());
207
208 varpower::to_expvector(M->n_vars(), vp.data(), find_pairs_exp);
209 for (int w = 0; w < R->n_skew_commutative_vars(); w++)
210 if (find_pairs_exp[R->skew_variable(w)] > 0)
211 {
212 thisvp.resize(0);
213 varpower::var(w, 1, thisvp);
214 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
215 elems.push_back(b);
216 }
217
218 freemem(find_pairs_exp);
219 }
220
221 // Second, add in syzygies arising from the base ring, if any
222 // The baggage of each of these is NULL
223 if (R->is_quotient_ring())
224 {
225 const MonomialIdeal *Rideal = R->get_quotient_monomials();
226 for (Bag& a : *Rideal)
227 {
228 // Compute (P->quotient_ideal->monom : p->monom)
229 // and place this into a varpower and Bag, placing
230 // that into 'elems'
231 thisvp.resize(0);
232 varpower::quotient(a.monom().data(), vp.data(), thisvp);
233 if (varpower::is_equal(a.monom().data(), thisvp.data()))
234 continue;
235 Bag *b = new Bag(static_cast<void *>(nullptr), thisvp);
236 elems.push_back(b);
237 }
238 }
239
240 // Third, add in syzygies arising from previous elements of this same level
241 // The baggage of each of these is their corresponding res2_pair
242
243 MonomialIdeal *mi_orig = mi[gb[i]->comp - 1];
244 for (Bag& a : *mi_orig)
245 {
246 Bag *b = new Bag();
247 varpower::quotient(a.monom().data(), vp.data(), b->monom());
248 elems.push_back(b);
249 }
250
251 // Make this monomial ideal, and then run through each minimal generator
252 // and insert into the proper degree. (Notice that sorting does not
253 // need to be done yet: only once that degree is about to begin.
254
255 mi_orig->insert_minimal(new Bag(i, vp));
256
257 MonomialIdeal *new_mi = new MonomialIdeal(R, elems);
258
259 monomial m = M->make_one();
260 for (Bag& a : *new_mi)
261 {
262 M->from_varpower(a.monom().data(), m);
263 M->mult(m, gb[i]->monom, m);
264
266 GR->get_flattened_coefficients()->from_long(1), m, i + 1);
267 syzygies.push_back(q);
268 }
269}
270
272// S-pairs and reduction ////////////////////
274
276 const gbvector *&result)
277// If 'exp' is divisible by a ring lead term, then 1 is returned,
278// and result is set to be that ring element.
279// Otherwise 0 is returned.
280{
281 if (!R->is_quotient_ring()) return false;
282 Bag *b;
283 if (!R->get_quotient_monomials()->search_expvector(exp, b)) return false;
284 int index = b->basis_elem();
285 result = R->quotient_gbvector(index);
286 return true;
287}
288
290 const_exponents exp,
291 int &result)
292{
293 // Find all the possible matches, use some criterion for finding the best...
295 this_mi->find_all_divisors(exp, bb);
296 int ndivisors = bb.size();
297 if (ndivisors == 0) return 0;
298 result = bb[0]->basis_elem();
299 // Now search through, and find the best one. If only one, just return it.
300 if (M2_gbTrace >= 5)
301 if (this_mi->size() > 1)
302 {
303 buffer o;
304 o << ":" << this_mi->size() << "." << ndivisors << ":";
305 emit(o.str());
306 }
307 if (ndivisors == 1)
308 {
309 if (this_mi->size() == 1)
310 n_ones++;
311 else
312 n_unique++;
313 return 1;
314 }
315 n_others++;
316
317 int lowest = result;
318 for (int i = 1; i < ndivisors; i++)
319 {
320 int p = bb[i]->basis_elem();
321 if (p < lowest) lowest = p;
322 }
323 result = lowest;
324 return ndivisors;
325}
326
328{
329 gbvector *result = nullptr;
330 monomial si = M->make_one();
331 for (gbvector *f = gsyz; f != nullptr; f = f->next)
332 {
333 SG->schreyer_down(f->monom, f->comp - 1, si);
334 gbvector *h = GR->mult_by_term(F, gb[f->comp - 1], f->coeff, si, 0);
336 GR->gbvector_add_to(F, result, h);
337 }
338 M->remove(si);
339 return result;
340}
341
343{
344 // Remove every term of f (except the lead term)
345 // which is NOT divisible by an element of mi.
346 exponents_t exp = newarray_atomic(int, GR->n_vars());
347 // int nterms = 1;
348 // int nsaved = 0;
349 gbvector *g = f;
350 while (g->next != nullptr)
351 {
352 // First check to see if the term g->next is in the monideal
353 // nterms++;
354 Bag *b;
355 GR->gbvector_get_lead_exponents(F, g->next, exp);
356 if (mi[g->next->comp - 1]->search_expvector(exp, b))
357 {
358 // Want to keep the monomial
359 g = g->next;
360 }
361 else
362 {
363 // Want to dump this term
364 // nsaved++;
365 gbvector *tmp = g->next;
366 g->next = tmp->next;
367 tmp->next = nullptr;
368 GR->gbvector_remove(tmp);
369 }
370 }
371#if 0
372// if (M2_gbTrace >= 5)
373// {
374// buffer o;
375// o << "[" << nterms << ",s" << nsaved << "]";
376// emit_wrapped(o.str());
377// }
378#endif
379}
380
382{
385
386 const Ring *gbringK = GR->get_flattened_coefficients();
387 ring_elem one = gbringK->from_long(1);
388 gbvector *lastterm = fsyz; // fsyz has only ONE term.
389 const gbvector *r;
390 int q;
391
392 int nhits = 0;
393 int nremoved = 0;
394 int max_len = GR->gbvector_n_terms(f);
395
396 int count = 0;
397 if (M2_gbTrace >= 4) emit_wrapped(",");
398
399 while (f != nullptr)
400 {
401 if (SF)
402 {
403 SF->schreyer_down(f->monom, f->comp - 1, REDUCE_mon);
404 M->to_expvector(REDUCE_mon, REDUCE_exp);
405 }
406 else
407 M->to_expvector(f->monom, REDUCE_exp);
408 if (find_ring_divisor(REDUCE_exp, r))
409 {
410 ring_elem u, v;
411 // Subtract off f, leave fsyz alone
412 M->divide(f->monom, r->monom, REDUCE_mon);
413 gbringK->syzygy(f->coeff, r->coeff, u, v);
414 gbvector *h = GR->mult_by_term(F, r, v, REDUCE_mon, f->comp);
415 GR->gbvector_add_to(F, f, h);
416 if (!gbringK->is_equal(u, one))
417 {
418 GR->gbvector_mult_by_coeff_to(fsyz, u);
419 GR->gbvector_mult_by_coeff_to(f, u);
420 gbringK->remove(u);
421 gbringK->remove(v);
422 }
424 count++;
425 }
426 else if (find_divisor(mi[f->comp - 1], REDUCE_exp, q))
427 {
428 ring_elem u, v;
429 gbringK->syzygy(f->coeff, gb[q]->coeff, u, v);
430 M->divide(f->monom, gb[q]->monom, REDUCE_mon);
431 gbvector *h = GR->mult_by_term(F, gb[q], v, REDUCE_mon, 0);
432 if (!gbringK->is_equal(u, one))
433 {
434 GR->gbvector_mult_by_coeff_to(fsyz, u);
435 GR->gbvector_mult_by_coeff_to(f, u);
436 }
437 int n1 = GR->gbvector_n_terms(h);
439 int n2 = GR->gbvector_n_terms(h);
440 nremoved += (n1 - n2);
441 lastterm->next = make_syz_term(v, f->monom, q + 1); // grabs v.
442 lastterm = lastterm->next;
443 gbringK->remove(u);
444 gbringK->remove(v);
445 int n3 = GR->gbvector_n_terms(f);
446 GR->gbvector_add_to(F, f, h);
447 int n4 = GR->gbvector_n_terms(f);
448 if (n4 > max_len) max_len = n4;
449 nhits +=
450 (n2 + n3 - n4 -
451 2); // the -2 is to avoid counting the lead term cancellations.
453 count++;
454 }
455 else
456 {
457 // To get here is an ERROR!
458 f = f->next; // Just to not have an infinite loop
459 emit_line(
460 "error in Schreyer reduction: element does not reduce to zero!");
461 }
462 }
463
464 if (M2_gbTrace >= 4)
465 {
466 buffer o;
467 o << count;
468 o << "[" << max_len << " " << nhits << " " << nremoved << "]";
469 emit_wrapped(o.str());
470 }
471}
472
474{
477
478 const Ring *gbringK = GR->get_flattened_coefficients();
479 ring_elem one = gbringK->from_long(1);
480 gbvector *lastterm = fsyz; // fsyz has only ONE term.
481 const gbvector *r;
482 gbvectorHeap fb(GR, F);
483 fb.add(f);
484 f = nullptr;
485 const gbvector *lead;
486 int q;
487
488 int count = 0;
489 if (M2_gbTrace >= 4) emit_wrapped(",");
490
491 while ((lead = fb.get_lead_term()) != nullptr)
492 {
493 if (SF)
494 {
495 SF->schreyer_down(lead->monom, lead->comp - 1, REDUCE_mon);
496 M->to_expvector(REDUCE_mon, REDUCE_exp);
497 }
498 else
499 M->to_expvector(lead->monom, REDUCE_exp);
500 if (find_ring_divisor(REDUCE_exp, r))
501 {
502 ring_elem u, v;
503 // Subtract off f, leave fsyz alone
504 M->divide(lead->monom, r->monom, REDUCE_mon);
505
506 gbringK->syzygy(f->coeff, r->coeff, u, v);
507 gbvector *h = GR->mult_by_term(F, r, v, REDUCE_mon, f->comp);
508 fb.add(h);
509 if (!gbringK->is_equal(u, one))
510 {
511 GR->gbvector_mult_by_coeff_to(fsyz, u);
512 GR->gbvector_mult_by_coeff_to(f, u);
513 gbringK->remove(u);
514 gbringK->remove(v);
515 }
516
517 fb.add(h);
519 count++;
520 }
521 else if (find_divisor(mi[lead->comp - 1], REDUCE_exp, q))
522 {
523 ring_elem u, v;
524 gbringK->syzygy(f->coeff, gb[q]->coeff, u, v);
525 M->divide(lead->monom, gb[q]->monom, REDUCE_mon);
526 gbvector *h = GR->mult_by_term(F, gb[q], v, REDUCE_mon, 0);
527 if (!gbringK->is_equal(u, one))
528 {
529 GR->gbvector_mult_by_coeff_to(fsyz, u);
530 GR->gbvector_mult_by_coeff_to(f, u);
531 }
533 lastterm->next = make_syz_term(v, lead->monom, q + 1); // grabs v.
534 lastterm = lastterm->next;
535 fb.add(h);
537 count++;
538 }
539 else
540 {
541 // To get here is an ERROR!
542 fb.remove_lead_term();
543 emit_line(
544 "error in Schreyer reduction: element does not reduce to zero!");
545 }
546 }
547
548 if (M2_gbTrace >= 4)
549 {
550 buffer o;
551 o << count;
552 emit_wrapped(o.str());
553 }
554}
555
556// Local Variables:
557// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
558// indent-tabs-mode: nil
559// End:
Older Schreyer-style kernel computation, predecessor of schreyer-resolution/.
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
static void quotient(ConstExponents a, ConstExponents b, Vector &result)
static bool is_equal(ConstExponents a, ConstExponents b)
static void to_expvector(int n, ConstExponents a, exponents::Exponents result)
static void var(Exponent v, Exponent e, Vector &result)
static FreeModule * make_schreyer(const Matrix *m)
Definition freemod.cpp:53
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
int find_divisor(const MonomialIdeal *mi, const_exponents exp, int &result)
bool find_ring_divisor(const_exponents exp, const gbvector *&result)
void reduce(gbvector *&g, gbvector *&gsyz)
const FreeModule * F
Definition Eschreyer.hpp:93
void geo_reduce(gbvector *&g, gbvector *&gsyz)
gc_vector< gbvector * > syzygies
Definition Eschreyer.hpp:99
virtual ~GBKernelComputation()
Definition Eschreyer.cpp:93
const FreeModule * G
Definition Eschreyer.hpp:94
void new_pairs(int i)
void strip_gb(const gc_vector< gbvector * > &m)
const SchreyerOrder * SF
Definition Eschreyer.hpp:91
const PolynomialRing * R
Definition Eschreyer.hpp:87
GBMatrix * get_syzygies()
gc_vector< gbvector * > gb
Definition Eschreyer.hpp:98
GBKernelComputation(const GBMatrix *m)
Definition Eschreyer.cpp:69
void wipe_unneeded_terms(gbvector *&f)
const SchreyerOrder * SG
Definition Eschreyer.hpp:92
gbvector * s_pair(gbvector *syz)
gc_vector< MonomialIdeal * > mi
Definition Eschreyer.hpp:97
gbvector * make_syz_term(ring_elem c, const_monomial monom, int comp) const
const Monoid * M
Definition Eschreyer.hpp:90
ring_elem elem(int i, int j) const
Definition matrix.cpp:307
int n_cols() const
Definition matrix.hpp:147
void text_out(buffer &o) const
Definition matrix.cpp:1316
Matrix * to_matrix()
void set_column(int c, vec v)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
void insert_minimal(Bag *b)
Definition monideal.hpp:333
void find_all_divisors(const_exponents exp, VECTOR(Bag *)&b) const
Definition monideal.cpp:246
int size() const
Definition monideal.hpp:186
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 gbvector * translate_gbvector_from_vec(const FreeModule *F, const vec v, ring_elem &result_denominator) const =0
virtual vec translate_gbvector_to_vec(const FreeModule *F, const gbvector *v) const =0
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual void remove(ring_elem &f) const =0
virtual bool is_equal(const ring_elem f, const ring_elem g) const =0
virtual ring_elem from_long(long n) const =0
virtual void syzygy(const ring_elem a, const ring_elem b, ring_elem &x, ring_elem &y) const =0
xxx xxx xxx
Definition ring.hpp:102
char * str()
Definition buffer.hpp:72
gbvector * remove_lead_term()
Definition gbring.cpp:1592
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
gc_vector< int > & monom()
Definition int-bag.hpp:60
@ COMP_DONE
Definition computation.h:60
#define Matrix
Definition factory.cpp:14
#define monomial
Definition gb-toric.cpp:11
GBRing and gbvector — the GB-tuned polynomial-ring view used by classical Buchberger code.
int p
const int * const_monomial
Definition imonorder.hpp:45
int_bag Bag
Definition int-bag.hpp:70
void freemem(void *s)
Definition m2-mem.cpp:103
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
int M2_gbTrace
Definition m2-types.cpp:52
MatrixConstructor — the mutable builder that produces an immutable Matrix.
Matrix — the engine's immutable homomorphism F -> G between free modules.
#define MONOMIAL_BYTE_SIZE(mon_size)
Definition monoid.hpp:66
#define ALLOCATE_EXPONENTS(byte_len)
Definition monoid.hpp:62
#define EXPONENT_BYTE_SIZE(nvars)
Definition monoid.hpp:63
#define ALLOCATE_MONOMIAL(byte_len)
Definition monoid.hpp:65
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
#define newarray_atomic_clear(T, len)
Definition newdelete.hpp:93
typename std::vector< T, gc_allocator< T > > gc_vector
a version of the STL vector, which allocates its backing memory with gc.
Definition newdelete.hpp:76
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
tbb::flow::graph G
Matrix * to_matrix()
Definition Eschreyer.cpp:55
void append(gbvector *f)
Definition Eschreyer.cpp:53
gc_vector< gbvector * > elems
Definition Eschreyer.hpp:56
const FreeModule * F
Definition Eschreyer.hpp:55
GBMatrix(const Matrix *m)
Definition Eschreyer.cpp:41
gbvector-side matrix: a target FreeModule plus a list of gbvector* columns living in it.
Definition Eschreyer.hpp:54
ring_elem coeff
Definition gbring.hpp:81
gbvector * next
Definition gbring.hpp:80
int monom[1]
Definition gbring.hpp:83
int comp
Definition gbring.hpp:82
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.