Gröbner basis project
Codebase for research into Gröbner basis computation
dynamic_engine.cpp
1 #ifndef __DYNAMIC_ENGINE_C__
2 #define __DYNAMIC_ENGINE_C__
3 
4 /*****************************************************************************\
5 * This file is part of DynGB. *
6 * *
7 * DynGB is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * Foobar is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
19 \*****************************************************************************/
20 
21 #include <iostream>
22 #include <list>
23 
24 using std::cout; using std::endl;
25 using std::list;
26 
27 #include "betti.hpp"
28 #include "monomial.hpp"
29 #include "polynomial.hpp"
30 #include "dynamic_engine.hpp"
31 
37 ) {
38  int result = 0;
40  HPdiff -= hp2;
41  if (not HPdiff.is_zero()) {
42  if (HPdiff.numerator(HPdiff.degree()) < 0) result = -1;
43  else result = 1;
44  } else { // use Hilbert series
45  DEG_TYPE i = 0;
46  for (/* */; i <= hn1.degree() and i <= hn2.degree() and hn1[i] == hn2[i]; i++)
47  { /* taken care of in loop */ }
48  if (i > hn1.degree()) {
49  if (i > hn2.degree()) // functions are equal
50  result = 0;
51  else
52  result = 1;
53  } else {
54  if (i > hn2.degree()) result = 1;
55  else {
56  if (hn1[i] < hn2[i]) result = -1;
57  else result = 1;
58  }
59  }
60  }
61  return result;
62 }
63 
64 bool LessByHilbert (PPWithIdeal &a, PPWithIdeal &b)
65 {
66  //cout << "Less by Hilbert then Lex\n";
67  bool result;
68  int n = a.getPP().num_vars();
69  // first check the coefficients of the Hilbert polynomial
70  int hilcheck = hilbertCmp(
73  );
74  if (hilcheck == 0) // the numerators are equal; break tie via current ordering
75  result = (a.getPP() < b.getPP());
76  else {
77  if (hilcheck == -1) result = true;
78  else result = false;
79  }
80  //cout << "\tfirst less than second? " << result << endl;
81  return result;
82 };
83 
84 bool LessBySmoothestDegrees (PPWithIdeal &a, PPWithIdeal &b)
85 {
87 };
88 
89 bool LessByLargestMaxComponent (PPWithIdeal &a, PPWithIdeal &b)
90 {
92 }
93 
95 {
96  int n = t.num_vars();
97  int m = I.size();
98  const list<Monomial> T = I.generators();
99  const vector<Monomial> I(T.begin(), T.end());
100  num_new_pairs = min_deg = 0;
101  bool * keepers = new bool [m];
102  for (int i = 0; i < m; ++i) keepers[i] = true;
103  // first main loop: apply Buchberger's lcm criterion to new pairs
104  for (int i = 0; i < m; ++i)
105  {
106  // if gcd(t,Ii) == 1 then skip i for the time being
107  if (not t.is_coprime(I[i]))
108  {
109  bool has_divisor = false;
110  for (int j=0; (not has_divisor) and j < m; ++j)
111  {
112  if (i != j and keepers[j])
113  {
114  // if some j satisfies lcm(t,Ij) | lcm(t,Ii) then do not count i
115  has_divisor = true;
116  for (int k=1; has_divisor and k <= n; ++k)
117  if // deg(lcm(t,lm(Ii))) < deg(lcm(t,lm(Ij))) ?
118  (((t[k] > I[i][k]) ? t[k] : I[i][k])
119  < ((t[k] > I[j][k]) ? t[k] : I[j][k]))
120  has_divisor = false;
121  }
122  }
123  if (has_divisor) keepers[i] = false;
124  }
125  }
126  // second main loop: apply Buchberger's gcd criterion to new pairs, count survivors
127  for (int i = 0; i < m; ++i)
128  {
129  if (keepers[i] and not t.is_coprime(I[i]))
130  {
131  int new_deg = 0;
132  // determine deg(lcm(t,Si))
133  for (int k=1; k <= n; ++k)
134  new_deg += (t[k] > I[i][k]) ? t[k] : I[i][k];
135  if (min_deg == 0 or min_deg > new_deg)
136  {
137  min_deg = new_deg; num_new_pairs = 1;
138  }
139  else if (min_deg == new_deg)
140  {
141  ++num_new_pairs;
142  //cout << '\t'; pWrite(pHead(strat->S[i]));
143  }
144  }
145  }
146  delete [] keepers;
147  // cout << "we get " << num_new_pairs << " from "; pWrite(t);
148  // third main loop: apply Buchberger's lcm criterion to old pairs, UNLESS
149  // all three lcm's are equal
150  for (Critical_Pair_Dynamic * p : pairs) {
151  const Monomial & u = p->lcm();
152  int new_deg = 0;
153  for (int k=1; k <= n; ++k) new_deg += u[k];
154  // for (int k=1; k <= n; ++k) new_deg += pGetExp(u,k) * Rx->wvhdl[0][k];
155  // no point continuing if it wouldn't change min_deg
156  if (min_deg == 0 or new_deg <= min_deg)
157  {
158  // see if new poly divides this one
159  bool has_divisor = true;
160  // see if Buchberger triple has same lcm
161  bool all_equal = true;
162  const Monomial & p1 = p->first()->leading_monomial();
163  const Monomial & p2 = (p->second() == nullptr) ?
164  p->first()->leading_monomial()
165  : p->second()->leading_monomial();
166  for (int k=1; has_divisor and all_equal and k <= n; ++k)
167  {
168  if (t[k] > u[k]) has_divisor = false;
169  else
170  {
171  // check lcm(t,lm(p1)) == lcm(t,lm(p2)) == lcm(lm(p1),lm(p2)) in xk
172  int a = (t[k] > p1[k]) ? t[k] : p1[k];
173  int b = (t[k] > p2[k]) ? t[k] : p2[k];
174  int c = (p1[k] > p2[k]) ? p1[k] : p2[k];
175  all_equal = (a == c) and (b == c);
176  }
177  }
178  if (not has_divisor or all_equal)
179  {
180  if (min_deg == 0 or min_deg > new_deg)
181  {
182  min_deg = new_deg; num_new_pairs = 1;
183  }
184  else // the only reason we'd be here is if min_deg == new_deg
185  {
186  ++num_new_pairs;
187  //cout << '\t'; pWrite(u);
188  }
189  }
190  }
191  }
192  // cout << " which makes " << num_new_pairs << " pairs total at degree " << min_deg << ".\n";
193 }
194 
195 bool LessByNumCritPairs (PPWithIdeal &a, PPWithIdeal &b)
196 {
197  bool result;
198  NVAR_TYPE n = a.getIdeal().number_of_variables();
199  // first check if the number of critical pairs has been computed
200  if (a.howManyNewPairs() < 0) a.computeNumberNewPairs();
201  if (b.howManyNewPairs() < 0) b.computeNumberNewPairs();
202  /*if (a.degOfNewPairs() < b.degOfNewPairs())
203  result = true;
204  else if (a.degOfNewPairs() > b.degOfNewPairs())
205  result = false;*/
206  // at this point, the degrees of the new pairs will be equal
207  /*else*/ if (a.howManyNewPairs() > b.howManyNewPairs())
208  result = true;
209  else if (a.howManyNewPairs() < b.howManyNewPairs())
210  result = false;
211  else // the numerators are equal; break tie via monomial ordering
212  result = a.getPP() < b.getPP();
213  //cout << "\tfirst less than second? " << result << endl;
214  return result;
215 };
216 
217 bool LessByHilbertThenDegree(PPWithIdeal &a, PPWithIdeal &b)
218 {
219  //cout << "Less by Hilbert then Deg\n";
220  bool result;
221  int n = a.getIdeal().number_of_variables();
222  // first check the coefficients of the Hilbert polynomial
223  int hilcheck = hilbertCmp(
226  );
227  if (hilcheck == -1) result = true;
228  else if (hilcheck == 1) result = false;
229  else { // the numerators are equal; break tie via monomial degree
230  if (a.getPP().total_degree() < b.getPP().total_degree())
231  result = true;
232  else if (a.getPP().total_degree() > b.getPP().total_degree())
233  result = false;
234  else
235  result = (a.getPP() < b.getPP());
236  }
237  return result;
238 };
239 
240 bool LessByGradHilbertThenDegree(PPWithIdeal &a, PPWithIdeal &b) {
241  bool result;
242  int n = a.getIdeal().number_of_variables();
243  // first check the coefficients of the Hilbert polynomial
246  int hilcheck = hilbertCmp(
247  *a.getHilbertNumerator(true), *hp1,
248  *b.getHilbertNumerator(true), *hp2
249  );
250  if (hilcheck == -1) result = true;
251  else if (hilcheck == 1) result = false;
252  else if (hilcheck == 0) { // break tie via monomial degree
255  result = true;
256  else if (a.getPP().weighted_degree(a.getOrdering().weights())
258  result = false;
259  else
260  result = a.getPP() < b.getPP();
261  }
262  return result;
263 };
264 
265 bool LessByDegreeThenHilbert(PPWithIdeal &a, PPWithIdeal &b)
266 {
267  //cout << "Less by Deg then Hilbert\n";
268  bool result;
269  int n = a.getPP().num_vars();
270  // first check the weighted degree
271  if (a.getPP().total_degree() < b.getPP().total_degree())
272  result = true;
273  else if (a.getPP().total_degree() > b.getPP().total_degree())
274  result = false;
275  else {
276  // now check the coefficients of the Hilbert polynomial
278  HPdiff -= *(b.getHilbertPolynomial());
279  if (not HPdiff.is_zero())
280  result = (HPdiff.numerator(HPdiff.degree()) < 0);
281  else // use Hilbert series
282  {
285  DEG_TYPE i = 0;
286  for ( /* already initialized */ ;
287  i <= h1->degree() and i <= h2->degree() and (*h1)[i] == (*h2)[i];
288  i++)
289  { /* taken care of in loop */ }
290  if (i > h1->degree())
291  {
292  if (i > h2->degree())
293  {
294  int i = 0;
295  while (i < n and a.getPP()[i] == b.getPP()[i]) ++i;
296  if (i == n) result = false;
297  else
298  result = (a.getPP()[i] < b.getPP()[i]);
299  }
300  else
301  result = true;
302  }
303  else
304  {
305  if (i > h2->degree()) result = false;
306  else result = (*h1)[i] < (*h2)[i];
307  }
308  }
309  }
310  return result;
311 };
312 
313 bool LessByWDegreeThenHilbert(PPWithIdeal &a, PPWithIdeal &b)
314 {
315  //cout << "Less by Deg then Hilbert\n";
316  bool result;
317  int n = a.getPP().num_vars();
318  // first check the weighted degree
321  result = true;
322  else if (a.getPP().weighted_degree(a.getOrdering().weights())
324  result = false;
325  else {
326  // now check the coefficients of the Hilbert polynomial
329  if (not HPdiff.is_zero())
330  result = (HPdiff.numerator(HPdiff.degree()) >= 0);
331  else // use Hilbert series
332  {
335  DEG_TYPE i = 0;
336  for ( /* already initialized */ ;
337  i <= h1->degree() and i <= h2->degree() and (*h1)[i] == (*h2)[i];
338  i++)
339  { /* taken care of in loop */ }
340  if (i > h1->degree())
341  {
342  if (i > h2->degree())
343  {
344  int i = 0;
345  while (i < n and a.getPP()[i] == b.getPP()[i]) ++i;
346  if (i == n) result = false;
347  else
348  result = (a.getPP()[i] < b.getPP()[i]);
349  }
350  else
351  result = true;
352  }
353  else
354  {
355  if (i > h2->degree()) result = false;
356  else result = (*h1)[i] < (*h2)[i];
357  }
358  }
359  }
360  return result;
361 };
362 
363 bool LessByDegreeThenGradHilbert(PPWithIdeal &a, PPWithIdeal &b)
364 {
365  bool result;
366  int n = a.getPP().num_vars();
367  // first check the weighted degree
370  result = true;
371  else if (a.getPP().weighted_degree(a.getOrdering().weights())
373  result = false;
374  else {
375  // now check the coefficients of the Hilbert polynomial
377  HPdiff -= *(b.getHilbertPolynomial());
378  if (not HPdiff.is_zero())
379  result = (HPdiff.numerator(HPdiff.degree()) < 0);
380  else // use Hilbert series
381  {
384  DEG_TYPE i = 0;
385  for ( /* already initialized */ ;
386  i <= h1->degree() and i <= h2->degree() and (*h1)[i] == (*h2)[i];
387  i++)
388  { /* taken care of in loop */ }
389  if (i > h1->degree())
390  {
391  if (i > h2->degree())
392  {
393  int i = 0;
394  while (i < n and a.getPP()[i] == b.getPP()[i]) ++i;
395  if (i == n) result = false;
396  else result = (a.getPP()[i] < b.getPP()[i]);
397  }
398  else
399  result = true;
400  }
401  else
402  {
403  if (i > h2->degree()) result = false;
404  else result = (*h1)[i] < (*h2)[i];
405  }
406  }
407  }
408  return result;
409 };
410 
411 bool LessByBetti (PPWithIdeal & a, PPWithIdeal & b) {
412  bool result;
413  const map<DEG_TYPE, unsigned long> & Ba = a.getIncBetti();
414  const map<DEG_TYPE, unsigned long> & Bb = b.getIncBetti();
415  auto Bai = Ba.begin();
416  auto Bbi = Bb.begin();
417  for (/* */ ;
418  Bai != Ba.end() and Bbi != Bb.end()
419  and (Bai->first == Bbi->first and Bai->second == Bbi->second);
420  ++Bai, ++Bbi
421  ) { }
422  if (Bai == Ba.end()) {
423  if (Bbi == Bb.end())
424  result = LessByHilbertThenDegree(a, b);
425  else
426  result = false;
427  } else {
428  if (Bbi == Bb.end()) {
429  result = true;
430  } else {
431  if (Bai->first < Bbi->first)
432  result = false;
433  else if (Bai->first > Bbi->first)
434  result = true;
435  else if (Bai->second < Bbi->second)
436  result = false;
437  else
438  result = a.getPP() < b.getPP();
439  }
440  }
441  return result;
442 }
443 
444 bool LessByBigBetti (PPWithIdeal & a, PPWithIdeal & b) {
445  bool result;
446  const map<DEG_TYPE, unsigned long> & Ba = a.getIncBetti();
447  const map<DEG_TYPE, unsigned long> & Bb = b.getIncBetti();
448  auto Bai = Ba.end();
449  auto Bbi = Bb.end();
450  for (/* */ ;
451  Bai != Ba.begin() and Bbi != Bb.begin()
452  and (Bai->first == Bbi->first and Bai->second == Bbi->second);
453  --Bai, --Bbi
454  ) { }
455  if (Bai == Ba.begin()) {
456  if (Bbi == Bb.begin())
457  result = LessByHilbertThenDegree(a, b);
458  else
459  result = true;
460  } else {
461  if (Bbi == Bb.begin()) {
462  result = false;
463  } else {
464  if (Bai->first < Bbi->first)
465  result = false;
466  else if (Bai->first > Bbi->first)
467  result = true;
468  else if (Bai->second < Bbi->second)
469  result = false;
470  else
471  result = a.getPP() < b.getPP();
472  }
473  }
474  return result;
475 }
476 
477 bool LessByGradBetti (PPWithIdeal & a, PPWithIdeal & b) {
478  bool result;
479  const map<DEG_TYPE, unsigned long> & Ba = a.getIncBetti(true);
480  const map<DEG_TYPE, unsigned long> & Bb = b.getIncBetti(true);
481  auto Bai = Ba.begin();
482  auto Bbi = Bb.begin();
483  for (/* */ ;
484  Bai != Ba.end() and Bbi != Bb.end()
485  and (Bai->first == Bbi->first and Bai->second == Bbi->second);
486  ++Bai, ++Bbi
487  ) { }
488  if (Bai == Ba.end()) {
489  if (Bbi == Bb.end())
490  result = LessByGradHilbertThenDegree(a, b);
491  else
492  result = false;
493  } else {
494  if (Bbi == Bb.end()) {
495  result = true;
496  } else {
497  if (Bai->first < Bbi->first)
498  result = false;
499  else if (Bai->first > Bbi->first)
500  result = true;
501  else if (Bai->second < Bbi->second)
502  result = false;
503  else
504  result = a.getPP() < b.getPP();
505  }
506  }
507  return result;
508 }
509 
511  Monomial currentLPP, // the current LPP
512  const set<Monomial> &allPPs, // the monomials to consider;
513  // some will be removed
514  const set<::ray> &bndrys, // known boundary vectors
515  set<Monomial> &result, // returned as PPs for Hilbert function
516  // ("easy" (& efficient?) to extract exps
517  set<Monomial> &boundary_mons, // boundary monomials
518  LP_Solver *skel // used for alternate refinement
519 )
520 {
521  // get the exponent vector of the current LPP, insert it
522  NVAR_TYPE n = currentLPP.num_vars();
523  ::ray aray(n, currentLPP.log());
524  set<Monomial> initial_candidates;
525  initial_candidates.insert(currentLPP);
526  // compare other monomials with LPP
527  /*for (
528  auto b_ptr = allPPs.begin();
529  b_ptr != allPPs.end();
530  ++b_ptr
531  )
532  {
533  // take the dot product of each monomial's exponents with pp,
534  // add the ones that pass muster to initial_candidates
535  //cout << '\t'; p_Write(*b_ptr, Rx);
536  p_GetExpV(*b_ptr, b, Rx);
537  for (unsigned long i = 1; i <= n; ++i) { along[i-1] = b[i]; }
538  ::ray bray(n, along);
539  bool searching = true;
540  for (
541  auto w_ptr = bndrys.begin();
542  searching and w_ptr != bndrys.end();
543  ++w_ptr
544  )
545  {
546  // check b against a with all rays
547  //cout << "checking " << bray << " against " << aray << " via " << *w_ptr << ": " << (*w_ptr) * bray << ' ' << (*w_ptr) * aray << endl;
548  if ((*w_ptr) * bray > (*w_ptr) * aray)
549  {
550  // only need one success
551  initial_candidates.insert(*b_ptr);
552  cout << "succeeded with " << bray << endl;
553  searching = false;
554  }
555  }
556  }*/
557  for (const Monomial & b : allPPs)
558  if (not b.is_like(currentLPP) and skel->makes_consistent_constraint(b, currentLPP))
559  initial_candidates.insert(b);
560  for (const Monomial & t : initial_candidates)
561  result.insert(t);
562  // (new) alternate refinement: compare remaining monomials against each other,
563  // using skeleton to ensure consistency
564  // this approach should be more efficient than the one below, yet equivalent to it
565  for (const Monomial & t : initial_candidates)
566  {
567  // cout << "testing for consistency: "; pWrite(*t);
568  bool good_constraints = true;
569  /*for (set<Monomial>::const_iterator u = initial_candidates.begin();
570  good_constraints and u != initial_candidates.end();
571  ++u)
572  if (not t.is_like(*u))
573  if (not skel->makes_consistent_constraint(t,*u))
574  good_constraints = false;*/
575  for (const Monomial & u : initial_candidates)
576  if (not t.is_like(u))
577  if (not skel->makes_consistent_constraint(t, u)) {
578  good_constraints = false;
579  break;
580  }
581  if (good_constraints)
582  {
583  boundary_mons.insert(t);
584  // cout << "\tconsistent!\n";
585  }
586  }
587  // second refinement: compare remaining monomials with each other
588  /*for (auto p_ptr = initial_candidates.begin(); p_ptr != initial_candidates.end(); ++p_ptr)
589  {
590  p_GetExpV(*p_ptr, a, Rx);
591  for (unsigned long i = 1; i <= n; ++i) { along[i-1] = a[i]; }
592  ::ray pray(n, along);
593  bool cleared_the_hurdle = false;
594  for (auto w_ptr = bndrys.begin();
595  not cleared_the_hurdle and w_ptr != bndrys.end(); ++w_ptr)
596  {
597  bool maybe_this_vector = true;
598  ::ray w = *w_ptr;
599  for (auto q_ptr = initial_candidates.begin();
600  maybe_this_vector and not cleared_the_hurdle and q_ptr != initial_candidates.end(); ++q_ptr)
601  if (*p_ptr != *q_ptr)
602  {
603  p_GetExpV(*q_ptr, b, Rx);
604  for (unsigned long i = 1; i <= n; ++i) { along[i-1] = b[i]; }
605  ::ray qray(n, along);
606  // guard against invalid exclusions
607  unsigned long long wt = (*w_ptr) * qray;
608  if ((((*w_ptr) * pray) <= wt) and wt != 0) { maybe_this_vector = false; }
609  }
610  cleared_the_hurdle = maybe_this_vector;
611  if (not cleared_the_hurdle) boundary_mons.insert(*p_ptr);
612  }
613  if (cleared_the_hurdle) result.insert(*p_ptr);
614  } */
615  //cout << "boundary monomials:\n";
616  //for (auto piter = boundary_mons.begin(); piter != boundary_mons.end(); ++piter) pWrite(*piter);
617  //cout << "compatible monomials:\n";
618  //for (auto piter = result.begin(); piter != result.end(); ++piter) pWrite(*piter);
619  //result = initial_candidates;
620 }
621 
623  LP_Solver *skel,
624  const list<Abstract_Polynomial *> &currentPolys
625 )
626 {
627  bool consistent = true; // innocent until proven guilty
628  ::ray w = ray_sum(skel->get_rays()); // our tentative ordering
629  // cout << "Have ray " << w << endl;
630  NVAR_TYPE n = w.get_dimension();
631  RAYENT_TYPE *entries = new RAYENT_TYPE [n]; // used for entries for new rays
632  CONSTR_TYPE *coefficients = new CONSTR_TYPE [n]; // used for coefficients for new constraints
633  // loop through all polynomials; verify leading power product is unchanged
634  for (
635  auto piter = currentPolys.begin(); piter != currentPolys.end(); ++piter
636  // next line commented out for GLPK_Solver (approx skel causes issues...)
637  //Abstract_Polynomial * pp : currentPolys
638  )
639  {
640  // create a ray for the current LPP's exponents
641  Abstract_Polynomial * pp = *piter;
642  const Monomial & t = pp->leading_monomial();
643  for (NVAR_TYPE i = 0; i < n; ++i) entries[i] = t[i];
644  ::ray a(n, entries);
645  // loop through the polynomial's remaining monomials
646  //for (poly titer = (*piter)->next; consistent and titer != nullptr; titer = titer->next)
647  Polynomial_Iterator * ti;
648  for (
649  ti = pp->new_iterator();
650  consistent and not ti->fellOff();
651  ti->moveRight()
652  ) {
653  // don't compare with LPP; that would be Bad (TM)
654  if (pp->leading_monomial() != ti->currMonomial())
655  {
656  // create a ray for the PP's exponents
657  for (NVAR_TYPE i = 0; i < n; ++i) entries[i] = ti->currMonomial()[i];
658  ::ray b(n, entries);
659  // compare weights between a and b; if this fails,
660  // recompute the skeleton with a new constraint
661  if (a*w <= b*w)
662  {
663  if (coefficients == nullptr) // ensure we have space
664  coefficients = new CONSTR_TYPE[n];
665  for (NVAR_TYPE i = 0; i < n; ++i)
666  coefficients[i] = a[i] - b[i];
667  constraint new_constraint(n, coefficients);
668  LP_Solver * newskel;
669  if (dynamic_cast<skeleton *>(skel) != nullptr)
670  newskel = new skeleton(*static_cast<skeleton *>(skel));
671  else if (dynamic_cast<GLPK_Solver *>(skel) != nullptr) {
672  newskel = new GLPK_Solver(*static_cast<GLPK_Solver *>(skel));
673  //piter = currentPolys.begin(); break;
674  }
675  else if (dynamic_cast<PPL_Solver *>(skel) != nullptr)
676  newskel = new PPL_Solver(*static_cast<PPL_Solver *>(skel));
677  consistent = newskel->solve(new_constraint);
678  w = ray_sum(skel->get_rays());
679  //cout << "Have ray " << w << endl;
680  // if we're consistent, we need to recompute the ordering
681  if (consistent and a*w > b*w)
682  {
683  w = ray_sum(skel->get_rays());
684  //cout << "Have ray " << w << endl;
685  *skel = *newskel;
686  } // if consistent
687  else consistent = false;
688  delete newskel;
689  } // if LPP changed
690  } // if PP != LPP
691  } // loop through PPs
692  delete ti;
693  } // loop through polys
694  // cleanup
695  delete [] entries;
696  delete [] coefficients;
697  // finally done
698  return consistent;
699 }
700 
702  const PPWithIdeal &I,
703  const set<Monomial> &monomialsForComparison,
704  vector<constraint> &result
705 )
706 {
707  // setup
708  NVAR_TYPE n = I.getIdeal().number_of_variables();
709  //int * a = new int[n]; // space for exponent vectors
710  //int * b = new int[n];
711  const EXP_TYPE * a, * b;
712  CONSTR_TYPE *c = new CONSTR_TYPE[n]; // space for coefficients of constraint
713  a = I.getPP().log(); // exponent vector of candidate
714  // loop through exponent vectors of other
715  for (const Monomial & t : monomialsForComparison)
716  {
717  // insert only different PPs (since I->t should also be in that set)
718  if (t != I.getPP())
719  {
720  b = t.log();
721  for (NVAR_TYPE i = 0; i < n; ++i) c[i] = a[i] - b[i];
722  result.push_back(constraint(n,c));
723  }
724  }
725  delete [] c;
726  //delete [] b;
727  //delete [] a;
728 }
729 
731  Abstract_Polynomial * r, // changes
732  list<Monomial> & CurrentLPPs, // changes
733  Dense_Univariate_Integer_Polynomial ** current_hilbert_numerator,
734  const list<Abstract_Polynomial *> & CurrentPolys,
735  const list<Critical_Pair_Dynamic *> & crit_pairs,
736  LP_Solver * currSkel, // possibly changes
737  bool & ordering_changed,
738  DynamicHeuristic method
739 )
740 {
741  //cout << "entering selmon\n";
742  //cout << "skeleton before: " << currSkel << endl;
743  skeleton * src_skel = dynamic_cast<skeleton *>(currSkel);
744  GLPK_Solver * src_GLPK = dynamic_cast<GLPK_Solver *>(currSkel);
745  PPL_Solver * src_PPL = dynamic_cast<PPL_Solver *>(currSkel);
746  ::ray w = ray_sum(currSkel->get_rays());
747  //cout << "Have ray " << w << endl;
748  vector<WT_TYPE> ord(w.get_dimension());
749  for (NVAR_TYPE i = 0; i < w.get_dimension(); ++i) { ord.push_back(w[i]); }
750  const Monomial & currentLPP = r->leading_monomial();
751  //cout << "comparing against: "; p_Write(currentLPP, Rx);
752  set<Monomial> allPPs, boundaryPPs, compatiblePPs;
753  // transform monomials into exponent vectors
754  Polynomial_Iterator * ti;
755  for (
756  ti = r->new_iterator();
757  not ti->fellOff();
758  ti->moveRight()
759  ) {
760  allPPs.insert(ti->currMonomial());
761  }
762  delete ti;
763  // loop through all exponent vectors
764  cout << allPPs.size() << " possible monomials\n";
765  compatiblePP(currentLPP, allPPs, currSkel->get_rays(), compatiblePPs, boundaryPPs, currSkel);
766  cout << compatiblePPs.size() << " compatible monomials\n";
767  //for (auto piter = compatiblePPs.begin(); piter != compatiblePPs.end(); ++piter)
768  // p_Write(*piter, Rx);
769  // list possible future ideals, sort by Hilbert Function
770  list<PPWithIdeal> possibleIdealsBasic;
771  for (const Monomial & t : compatiblePPs)
772  {
773  PPWithIdeal newIdeal(t, CurrentLPPs, w, crit_pairs, *current_hilbert_numerator);
774  possibleIdealsBasic.push_back(newIdeal);
775  }
776  //cout << "heuristic: " << method << endl;
777  switch(method)
778  {
779  case DynamicHeuristic::ORD_HILBERT_THEN_LEX:
780  possibleIdealsBasic.sort(LessByHilbert);
781  break;
782  case DynamicHeuristic::ORD_HILBERT_THEN_DEG:
783  possibleIdealsBasic.sort(LessByHilbertThenDegree);
784  break;
785  case DynamicHeuristic::DEG_THEN_ORD_HILBERT:
786  possibleIdealsBasic.sort(LessByDegreeThenHilbert);
787  break;
788  case DynamicHeuristic::GRAD_HILB_THEN_DEG:
789  possibleIdealsBasic.sort(LessByGradHilbertThenDegree);
790  break;
791  case DynamicHeuristic::DEG_THEN_GRAD_HILB:
792  possibleIdealsBasic.sort(LessByDegreeThenGradHilbert);
793  break;
794  case DynamicHeuristic::SMOOTHEST_DEGREES:
795  possibleIdealsBasic.sort(LessBySmoothestDegrees);
796  break;
797  case DynamicHeuristic::LARGEST_MAX_COMPONENT:
798  possibleIdealsBasic.sort(LessByLargestMaxComponent);
799  break;
800  case DynamicHeuristic::MIN_CRIT_PAIRS:
801  possibleIdealsBasic.sort(LessByNumCritPairs);
802  break;
803  case DynamicHeuristic::BETTI_HILBERT_DEG:
804  possibleIdealsBasic.sort(LessByBetti);
805  break;
806  case DynamicHeuristic::GRAD_BETTI_HILBERT_DEG:
807  possibleIdealsBasic.sort(LessByGradBetti);
808  break;
809  default: possibleIdealsBasic.sort(LessByHilbert);
810  }
811  PPWithIdeal * winner = & possibleIdealsBasic.front();
812  bool searching = true;
813  if (possibleIdealsBasic.size() != 1)
814  {
815  // test each combination of LPPs for consistency
816  // one of them must work (current LPP, if nothing else -- see previous case)
817  set<Monomial> PPunion;
818  for (const Monomial & t : compatiblePPs)
819  PPunion.insert(t);
820  for (const Monomial & t : boundaryPPs)
821  PPunion.insert(t);
822  for (PPWithIdeal & I : possibleIdealsBasic) {
823  //cout << currSkel << endl;
824  LP_Solver * newSkeleton;
825  if (src_skel != nullptr)
826  newSkeleton = new skeleton(*src_skel);
827  else if (src_GLPK != nullptr)
828  newSkeleton = new GLPK_Solver(*src_GLPK);
829  else if (src_PPL != nullptr)
830  newSkeleton = new PPL_Solver(*src_PPL);
831  vector<constraint> newvecs;
832  //cout << "testing " << I.getPP() << endl;
833  ConstraintsForNewPP(I, PPunion, newvecs);
834  if (newSkeleton->solve(newvecs))
835  {
836  //cout << "consistent\n";
837  if (verifyAndModifyIfNecessary(newSkeleton, CurrentPolys))
838  {
839  searching = false;
840  if (src_skel != nullptr)
841  src_skel -> copy(newSkeleton);
842  else if (src_GLPK != nullptr)
843  src_GLPK -> copy(newSkeleton);
844  else if (src_PPL != nullptr)
845  src_PPL -> copy(newSkeleton);
846  winner = & I;
847  delete newSkeleton;
848  break;
849  }
850  }
851  else
852  {
853  //cout << "inconsistent\n";
854  // cout << newSkeleton;
855  // this monomial is not, in fact, compatible
856  compatiblePPs.erase(I.getPP());
857  }
858  delete newSkeleton;
859  }
860  }
861  else if (possibleIdealsBasic.size() == 1 and compatiblePPs.size() != 1)
862  {
863  vector<constraint> newvecs;
864  ConstraintsForNewPP(*(possibleIdealsBasic.begin()), compatiblePPs, newvecs);
865  currSkel->solve(newvecs);
866  verifyAndModifyIfNecessary(currSkel, CurrentPolys);
867  }
868 
869  // set marked lpp, new Hilbert numerator
870  CurrentLPPs.push_back(winner->getPP());
871  if (*current_hilbert_numerator != nullptr) delete *current_hilbert_numerator;
872  *current_hilbert_numerator
874  // TODO: delete elements of allPPs (not clear how: elements are in a set)
875  ::ray new_weight = ray_sum(currSkel->get_rays());
876  //cout << "Have ray " << w << endl;
877  new_weight.simplify_ray();
878  for (
879  int i = 0;
880  not ordering_changed and i < (int )(new_weight.get_dimension());
881  ++i
882  ) {
883  // w is the old ordering
884  ordering_changed = ordering_changed or (new_weight[i] != w[i]);
885  }
886  cout << "ordering changed? " << ordering_changed << endl;
887  //cout << "finished with "; pWrite(t);
888  /*for (unsigned long i = 0; i < CurrentLPPs.size(); ++i) pWrite(CurrentLPPs[i]);
889  cout << endl;
890  cout << "skeleton after:\n";
891  cout << currSkel; */
892  //cout << "returning from selmon\n";
893 }
894 
895 #endif
DEG_TYPE total_degree(NVAR_TYPE m=0) const
Sum of exponents of the first m variables.
Definition: monomial.cpp:190
The general class of a polynomial.
Definition: polynomial.hpp:101
ray ray_sum(const set< ray > &rs)
Add all the rays in a set.
Definition: lp_solver.cpp:281
void SelectMonomial(Abstract_Polynomial *r, list< Monomial > &CurrentLPPs, Dense_Univariate_Integer_Polynomial **current_hilbert_numerator, const list< Abstract_Polynomial *> &CurrentPolys, const list< Critical_Pair_Dynamic *> &crit_pairs, LP_Solver *currSkel, bool &ordering_changed, DynamicHeuristic method)
Selects a leading power product for a polynomial.
MPZCOEF_TYPE numerator(DEG_TYPE k) const
returns the th numerator
const Monomial_Ideal & getIdeal() const
the old ideal of leading monomials
DEG_TYPE weighted_degree(const WT_TYPE *weights, NVAR_TYPE m=0) const
Definition: monomial.cpp:199
int howManyNewPairs() const
estimate of the number of new critical pairs generated by adding the monomial to the ideal ...
approximate skeleton of a polyhedral cone, using PPL linear solver
Definition: ppl_solver.hpp:38
virtual Polynomial_Iterator * new_iterator() const =0
An iterator that poses no risk of modifying the polynomial.
virtual void moveRight()=0
Moves right in the polynomial, to the next smaller monomial.
bool is_zero() const
indicates whether the polynomial is zero
int getDifferenceInDegree()
computes the difference in degree between the first and last monomials of the ideal ...
int num_new_pairs
estimate of number of new pairs
NVAR_TYPE number_of_variables() const
number of variables in each Monomial
const list< Critical_Pair_Dynamic * > & pairs
the list of critical pairs of at this point in the algorithm
const map< DEG_TYPE, unsigned long > & getIncBetti(bool graded=false)
the incremental Betti numbers obtained by adding the monomial to the ideal
Dense_Univariate_Rational_Polynomial * getHilbertPolynomial()
the Hilbert polynomial obtained by adding the monomial to the ideal
unsigned size() const
number of generators
virtual const set< ray > & get_rays()
Returns the rays that define the skeleton.
Definition: lp_solver.cpp:378
virtual Monomial & leading_monomial() const =0
leading monomial – call after sort_by_order()!
Monomial_Ideal I
the ideal of leading terms
Controls the creation of s-polynomials, specialized for the dynamic algorithm.
approximate skeleton of a polyhedral cone, using GLPK linear solver
Definition: glpk_solver.hpp:37
quick-’n-dirty Dense_Univariate integer polynomial class
inline ::ray getOrdering()
the current monomial ordering
a constraint
Definition: lp_solver.hpp:53
skeleton of a polyhedral cone, with methods allowing definition and refinement
Definition: skeleton.hpp:178
int min_deg
minimum weighted degree of monomials in ideal
void compatiblePP(Monomial currentLPP, const set< Monomial > &allPPs, const set<::ray > &bndrys, set< Monomial > &result, set< Monomial > &boundary_mons, LP_Solver *skel)
DynamicHeuristic
exact or approximate polyhedral cone solution, with methods allowing definition and refinement ...
Definition: lp_solver.hpp:504
NVAR_TYPE num_vars() const
number of variables
Definition: monomial.hpp:130
Dense_Univariate_Integer_Polynomial * getHilbertNumerator(bool graded=false)
the Hilbert numerator obtained by adding the monomial to the ideal (numerator is not reduced) ...
virtual bool fellOff() const =0
virtual bool makes_consistent_constraint(const Monomial &t, const Monomial &u, bool show_data=false)
tests for consistency of a constraint generated by two monomials.
Definition: lp_solver.hpp:578
Implementation of monomials.
Definition: monomial.hpp:69
bool verifyAndModifyIfNecessary(LP_Solver *skel, const list< Abstract_Polynomial *> &currentPolys)
bool is_coprime(const Monomial &other) const
true iff this has no common factor with other.
Definition: monomial.cpp:243
NVAR_TYPE get_dimension() const
Returns the dimension of this ray.
Definition: lp_solver.hpp:259
int hilbertCmp(const Dense_Univariate_Integer_Polynomial &hn1, const Dense_Univariate_Rational_Polynomial &hp1, const Dense_Univariate_Integer_Polynomial &hn2, const Dense_Univariate_Rational_Polynomial &hp2)
Monomial lcm(const Monomial &u) const
Least common multiple: largest exponents.
Definition: monomial.cpp:365
const EXP_TYPE * log() const
Direct access to the exponents, for whatever reason.
Definition: monomial.hpp:157
const Monomial & getPP() const
the leading monomial being added to the ideal
void computeNumberNewPairs()
Computes the number of critical pairs the monomial would add.
const list< Monomial > & generators() const
returns the list of generators
Used to iterate through a polynomial.
Definition: polynomial.hpp:224
DEG_TYPE degree() const
the polynomial’s degree (exponent of largest nonzero term)
void ConstraintsForNewPP(const PPWithIdeal &I, const set< Monomial > &monomialsForComparison, vector< constraint > &result)
virtual const Monomial & currMonomial() const =0
Reports the monomial at the current position.
quick-’n-dirty Dense_Univariate rational polynomial class
Monomial t
the last monomial added to
bool is_like(const Monomial &other) const
Have same variables, same powers? Synonymous with operator==().
Definition: monomial.cpp:247
DEG_TYPE degree() const
returns the polynomial’s degree
virtual bool solve(constraint &)=0
Adds the indicated constraint (singular!) and re-computes the solution.
void simplify_ray()
Simplifies the ray by dividing its components by the least common denominator.
Definition: lp_solver.cpp:186
const RAYENT_TYPE * weights() const
Returns the weights.
Definition: lp_solver.hpp:265
a ray defined by nonnegative coordinates
Definition: lp_solver.hpp:190