Gröbner basis project
Codebase for research into Gröbner basis computation
hilbert_functions_old.cpp
1 #ifndef __HILBERT_FUNCTIONS_CPP_
2 #define __HILBERT_FUNCTIONS_CPP_
3 
4 #include <set>
5 #include <list>
6 #include <vector>
7 #include <cstring>
8 #include <iostream>
9 #include <algorithm>
10 
11 using std::set; using std::list; using std::vector;
12 
13 #include "system_constants.hpp"
14 
15 #include "fields.hpp"
16 #include "monomial.hpp"
17 #include "polynomial_linked_list.hpp"
18 
19 #include "hilbert_functions.hpp"
20 
21 extern list<Monomial> colon_ideal_without_ideals(
22  const list<Monomial> &,
23  const Monomial &
24 );
25 
26 bool is_zero_base_case(const list<Monomial> & T) {
27  bool result = true; // innocent until proven guilty
28  const Monomial & t = T.front();
29  NVAR_TYPE n = t.num_vars();
30  bool * d = new bool [n] {false};
31  for (const Monomial & t : T) {
32  bool found = false;
33  for (NVAR_TYPE k = 0; result and k < n; ++k) {
34  if (t.degree(k) != 0) {
35  if (found) { result = false; }
36  else {
37  found = true;
38  if (d[k]) { result = false; }
39  else { d[k] = true; }
40  }
41  }
42  }
43  }
44  delete [] d;
45  return result;
46 }
47 
48 Dense_Univariate_Integer_Polynomial * solve_one_monomial_case(
49  const list<Monomial> & T
50 ) {
51  DEG_TYPE n = T.front().total_degree() + 1;
52  DEG_TYPE d = n - 1;
55  result->set_coefficient(0, 1);
56  result->set_coefficient(d, -1);
57  return result;
58 }
59 
61  const list<Monomial> & T
62 ) {
63  DEG_TYPE n = T.front().total_degree() + 1;
64  DEG_TYPE d = n;
65  list<Monomial>::const_iterator ti = T.begin();
66  for (++ti; ti != T.end(); ++ti)
67  {
68  n += ti->total_degree();
69  if (ti->total_degree() + 1 > d)
70  d = ti->total_degree() + 1;
71  }
74  result->set_coefficient(0, 1);
77  intermediate->set_coefficient(0, 1);
78  for (ti = T.begin(); ti != T.end(); ++ti) {
79  intermediate->set_coefficient(ti->total_degree(), -1);
80  result->multiply_by(*intermediate);
81  intermediate->set_coefficient(ti->total_degree(), 0);
82  }
83  delete intermediate;
84  return result;
85 }
86 
87 list<Monomial>::const_iterator is_one_base_case(const list<Monomial> & T) {
88  list<Monomial>::const_iterator result = T.end();
89  for (
90  list<Monomial>::const_iterator ti = T.begin();
91  (result != T.end()) and ti != T.end();
92  ++ti
93  ) {
94  list<Monomial> U;
95  for (const Monomial & u : T)
96  if (not u.is_like(*ti))
97  U.push_back(u);
98  if (is_zero_base_case(U))
99  result = ti;
100  }
101  return result;
102 }
103 
105  const list<Monomial> & T, list<Monomial>::const_iterator ui
106 ) {
107  // copy T and remove the monomial that isn't a simple power
108  list<Monomial> U(T);
109  Monomial p = *ui;
110  U.erase(ui);
112  DEG_TYPE d = 0;
113  DEG_TYPE max_d = 0;
114  for (const Monomial & u : U)
115  {
116  bool found_index = false;
117  unsigned j = 0;
118  for (/* already initialized */ ; not found_index and j < u.num_vars(); ++j)
119  if (u.degree(j) != 0)
120  found_index = true;
121  --j; // to compensate for a forced increment at the end of the loop
122  DEG_TYPE e = (u.degree(j) > p.degree(j)) ?
123  u.degree(j) - p.degree(j) : 0;
124  d += e;
125  if (max_d < e)
126  max_d = e;
127  }
131  = new Dense_Univariate_Integer_Polynomial(max_d + 1);
132  fac->set_coefficient(0, 1);
133  prod->set_coefficient(0, 1);
134  for (const Monomial & u : U)
135  {
136  NVAR_TYPE k = 0;
137  for (/* */; k < u.num_vars() and u.degree(k) == 0; ++k) {
138  /* do nothing */
139  }
140  //cout << "one base case: " << *ui << " and " << p << endl;
141  fac->set_coefficient(u.degree(k) - p.degree(k), -1);
142  prod->multiply_by(*fac);
143  fac->set_coefficient(u.degree(k) - p.degree(k), 0);
144  }
145  delete fac;
147  prod->negate();
148  result->add(*prod);
149  delete(prod);
150  return result;
151 }
152 
153 list<Monomial>::const_iterator is_splitting_case(const list<Monomial> & T) {
154  list<Monomial>::const_iterator result = T.end(); // guilty until proven innocent
155  for (
156  list<Monomial>::const_iterator ti = T.begin();
157  result == T.end() and ti != T.end();
158  ++ti
159  ) {
160  // check whether other monomials are relatively prime to t
161  bool relprime = true;
162  for (
163  list<Monomial>::const_iterator ui = T.begin();
164  relprime and ui != T.end();
165  ++ui
166  ) {
167  if (ti != ui)
168  relprime = ti->is_coprime(*ui);
169  }
170  if (relprime)
171  result = ti;
172  }
173  return result;
174 }
175 
177  const list<Monomial> & T, list<Monomial>::const_iterator ui
178 ) {
179  list<Monomial> U, V;
180  for (list<Monomial>::const_iterator ti = T.begin(); ti != T.end(); ++ti)
181  if (ti != ui)
182  U.push_back(*ti);
183  else
184  V.push_back(*ti);
186  Dense_Univariate_Integer_Polynomial * other = solve_one_monomial_case(V);
187  result->multiply_by(*other);
188  delete other;
189  return result;
190 }
191 
192 Monomial choose_hilbert_pivot(const list<Monomial> & T) {
193  NVAR_TYPE n = T.front().num_vars();
194  unsigned * xcount = new unsigned [n] {0};
195  for (const Monomial & t : T)
196  for (NVAR_TYPE k = 0; k < n; ++k)
197  if (t.degree(k) != 0)
198  ++xcount[k];
199  int i = 0;
200  for (NVAR_TYPE k = 1; k < n; ++k)
201  if (xcount[k] > xcount[i])
202  i = k;
203  delete [] xcount;
204  unsigned * td = new unsigned [T.size()];
205  unsigned j = 0;
206  for (const Monomial & t : T)
207  if (t.degree(i) != 0)
208  td[j++] = t.degree(i);
209  unsigned m = j;
210  std::sort(td, td + m);
211  j = (m == 2) ? 0 : m / 2;
212  Monomial result(n);
213  result.set_exponent(i, td[j]);
214  delete [] td;
215  return result;
216 }
217 
219  const list<Monomial> & T, const WT_TYPE * grading
220 ) {
221  bool verbose = false;
222  if (verbose) {
223  cout << "T = { ";
224  for (const Monomial & t : T) cout << t << " ,";
225  cout << "}\n";
226  }
228  int i;
229  list<Monomial>::const_iterator ti;
230  if (T.size() == 1)
231  result = solve_one_monomial_case(T);
232  else if (is_zero_base_case(T))
233  result = solve_zero_base_case(T);
234  else if ((ti = is_one_base_case(T)) != T.end())
235  result = solve_one_base_case(T, ti);
236  else if ((ti = is_splitting_case(T)) != T.end())
237  result = solve_splitting_case(T, ti);
238  else {
240  if (verbose) cout << "pivot = " << p << endl;
241  // find pivot precisely
242  unsigned pi = 0;
243  while (p.degree(pi) == 0) { ++pi; }
244  list<Monomial> U, V;
245  for (const Monomial & t : T) {
246  if (not t.divisible_by(p))
247  U.push_back(t);
248  }
249  V = colon_ideal_without_ideals(T, p);
250  U.push_back(p);
251  if (verbose) {
252  cout << "U = { ";
253  for (const Monomial & u : U) cout << u << " ,";
254  cout << "}\n";
255  }
256  /*list<Monomial> Vcheck;
257  for (const Monomial & t : T)
258  if (t.degree(pi) <= p.degree(pi)) { Vcheck.push_back(t); }
259  else V.push_back(t.colon(p));
260  for (const Monomial & u : Vcheck) {
261  bool indivisible = true; // innocent until proven guilty
262  for (
263  list<Monomial>::const_iterator wci = Vcheck.begin();
264  indivisible and wci != Vcheck.end();
265  ++wci
266  ) {
267  if (not u.is_like(*wci)) {
268  Monomial v(u); v.set_exponent(pi, v.degree(pi) - p.degree(pi));
269  Monomial w(*wci); w.set_exponent(pi, w.degree(pi) - p.degree(pi));
270  if (v.divisible_by(w))
271  indivisible = false;
272  }
273  }
274  if (indivisible) { V.push_back(u.colon(p)); }
275  }*/
276  if (verbose) {
277  cout << "V = { ";
278  for (const Monomial & v : V) cout << v << " ,";
279  cout << "}\n";
280  }
281  result = hilbert_numerator_bigatti(V, grading);
282  if (verbose) cout << "result from V: " << *result << endl;
285  = hilbert_numerator_bigatti(U, grading);
286  if (verbose) cout << "result from U: " << *other << endl;
287  *result += *other;
288  delete other;
289  }
290  return result;
291 }
292 
294  NVAR_TYPE n,
296  const WT_TYPE * grading
297 ) {
300  // perform synthetic division on the Hilbert numerator
301  unsigned r = 0;
302  NVAR_TYPE i = 0;
303  for (/* */; r == 0 and i < n; ++i) {
304  COEF_TYPE a = hn->coeff(hn->degree());
307  for (unsigned j = hn->degree() - 1; j < hn->degree(); --j) {
308  COEF_TYPE b = hn->coeff(j);
309  a += b;
310  hn->set_coefficient(j, a);
311  }
312  if ((r = hn->coeff(0)) != 0) {
313  delete hn;
314  hn = tmp;
315  } else {
316  delete tmp;
317  for (unsigned j = 0; j < hn->degree(); ++j)
318  hn->set_coefficient(j, hn->coeff(j+1));
319  hn->set_coefficient(hn->degree(), 0);
320  }
321  }
322  return hn;
323 }
324 
326  NVAR_TYPE n,
329 ) {
330  return n - (h1->degree() - h2->degree());
331 }
332 
334  COEF_TYPE a, COEF_TYPE b
335 ) {
337  = new Dense_Univariate_Rational_Polynomial((b > 0) ? b : 1);
338  if (b == 0)
339  // p = 1
340  p->set_coefficient(0, 1, 1);
341  else {
342  // p = (t + a) / b
343  p->set_coefficient(0, a, b);
344  p->set_coefficient(1, 1, b);
345  // p = p * (t + a - i) / i for i = 1, ..., b
348  for (unsigned i = 1; i < b; ++i) {
349  q->set_coefficient(0, a - i, i);
350  q->set_coefficient(1, 1, i);
351  //cout << "a - i: " << a - i << " i: " << i << endl;
352  //cout << "p: " << *p << endl;
353  //cout << "q: " << *q << endl;
354  p->multiply_by(*q);
355  //cout << "p*q: " << *p << endl;
356  }
357  delete q;
358  }
359  return p;
360 }
361 
363  NVAR_TYPE n,
364  unsigned int pole_order,
365  const list<Monomial> T,
368 ) {
369  bool own_hn1 = false;
370  bool own_hn2 = false;
371  if (hn == NULL) {
372  if (T.size() == 0)
373  return NULL;
374  else {
375  own_hn1 = true;
377  }
378  }
379  if (hn2 == NULL) {
380  own_hn2 = true;
381  hn2 = hilbert_second_numerator(n, hn);
382  }
383  if (pole_order == 0)
384  pole_order = n - (hn->degree() - hn2->degree());
386  = new Dense_Univariate_Rational_Polynomial(pole_order + 1);
387  if (pole_order != 0) {
388  DEG_TYPE d = hn2->degree();
389  COEF_TYPE d1 = pole_order - 1;
390  for (DEG_TYPE i = 0; i <= d; ++i) {
391  //q = polynomial_binomial(d1 - d + i, d1);
393  //q->scale_by(hn2->coeff(d - i));
394  q->scale_by(hn2->coeff(i));
395  hp->add(*q);
396  delete q;
397  }
398  }
399  if (pole_order % 2 != n % 2)
400  hp->negate();
401  if (own_hn1) delete hn;
402  if (own_hn2) delete hn2;
403  return hp;
404 }
405 
406 
407 #endif
DEG_TYPE total_degree(NVAR_TYPE m=0) const
Sum of exponents of the first m variables.
Definition: monomial.cpp:190
void set_coefficient(DEG_TYPE k, COEF_TYPE a)
set the coefficient of to
list< Monomial >::const_iterator is_one_base_case(const list< Monomial > &T)
test for the 1-base case
void set_coefficient(DEG_TYPE k, long a, unsigned long b)
set the coefficient of to
void multiply_by_monomial_of_degree(DEG_TYPE)
a hopefully efficient multiplication algorithm
Dense_Univariate_Rational_Polynomial * hilbert_polynomial(NVAR_TYPE n, unsigned int pole_order, const list< Monomial > T, Dense_Univariate_Integer_Polynomial *hn, Dense_Univariate_Integer_Polynomial *hn2)
computes the Hilbert polynomial for an ideal
void multiply_by(const Dense_Univariate_Rational_Polynomial &)
highly inefficient polynomial multiplication ( )
list< Monomial >::const_iterator is_splitting_case(const list< Monomial > &T)
test for the “splitting case”
Dense_Univariate_Rational_Polynomial * polynomial_binomial(long long a, long long b)
computes the number of combinations
Dense_Univariate_Integer_Polynomial * solve_one_base_case(const list< Monomial > &T, list< Monomial >::const_iterator ui, const WT_TYPE *grading)
applies Bigatti’s algorithm for the 1-base case
Dense_Univariate_Integer_Polynomial * hilbert_second_numerator(NVAR_TYPE n, Dense_Univariate_Integer_Polynomial *first, const WT_TYPE *grading)
computes the second Hilbert numerator (after reduction by )
void set_exponent(NVAR_TYPE i, DEG_TYPE e)
change th exponent to
Definition: monomial.cpp:78
COEF_TYPE coeff(DEG_TYPE k) const
the th coefficient
Dense_Univariate_Integer_Polynomial * hilbert_numerator_bigatti(const list< Monomial > &T, const WT_TYPE *grading)
the Bigatti algorithm to compute the Hilbert numerator
quick-’n-dirty Dense_Univariate integer polynomial class
void multiply_by(const Dense_Univariate_Integer_Polynomial &)
highly inefficient polynomial multiplication ( )
NVAR_TYPE num_vars() const
number of variables
Definition: monomial.hpp:130
Dense_Univariate_Integer_Polynomial * solve_zero_base_case(const list< Monomial > &T, const WT_TYPE *grading)
computes Hilbert numerator when the 0-base case applies
Implementation of monomials.
Definition: monomial.hpp:69
DEG_TYPE degree(NVAR_TYPE i) const
Degree of th variable.
Definition: monomial.cpp:183
Monomial choose_hilbert_pivot(const list< Monomial > &T)
chooses a pivot for the Bigatti algorithm
void add(const Dense_Univariate_Integer_Polynomial &q)
reasonably efficient, given our dense representation
DEG_TYPE degree() const
the polynomial’s degree (exponent of largest nonzero term)
void scale_by(COEF_TYPE a)
multiplies every monomial by a constant integer
quick-’n-dirty Dense_Univariate rational polynomial class
list< Monomial > colon_ideal_without_ideals(const list< Monomial > &U, const Monomial &t)
Computes the generators of an ideal and a new generator, given the ideal&#39;s generators. No monomial ideal machinery required.
Dense_Univariate_Integer_Polynomial * solve_splitting_case(const list< Monomial > &T, list< Monomial >::const_iterator ui, const WT_TYPE *grading)
applies Bigatti’s algorithm for the 1-base case
unsigned ideal_dimension(NVAR_TYPE n, const Dense_Univariate_Integer_Polynomial *h1, const Dense_Univariate_Integer_Polynomial *h2)
computes the dimension of the ideal by subtracting the Hilbert numerators
bool is_zero_base_case(const list< Monomial > &T)
test for the 0-base case