Gröbner basis project
Codebase for research into Gröbner basis computation
test_cyclicn.cpp
1 /*****************************************************************************\
2 * This file is part of DynGB. *
3 * *
4 * DynGB is free software: you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation, either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * Foobar is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
16 \*****************************************************************************/
17 
18 #include <set>
19 #include <cstring>
20 #include <iostream>
21 
22 using std::set;
23 using std::cout; using std::endl;
24 
25 #include "system_constants.hpp"
26 
27 #include "cyclic_n.hpp"
28 #include "polynomial.hpp"
29 #include "strategies.hpp"
30 #include "monomial_ordering.hpp"
31 #include "particular_orderings.hpp"
32 #include "algorithm_buchberger_basic.hpp"
33 #include "f4_reduction.hpp"
34 #include "algorithm_buchberger_explorer_serial.hpp"
35 
36 extern Monomial_Ordering * generic_grevlex_ptr;
37 
38 // Forward declarations
39 bool meaningful_arguments(
40  int argc, char *argv[], bool & homogeneous, int & modulus, int & numvars,
41  SPolyCreationFlags & method, bool &f4, bool &xplor,
42  Monomial_Ordering ** mord, StrategyFlags & strategy,
43  WT_TYPE ** grading
44 );
45 void give_help();
46 
47 int main(int argc, char *argv[]) {
48  bool homog;
49  bool f4 = false;
50  bool xplor = false;
51  int modulus, numvars;
52  SPolyCreationFlags method = SPolyCreationFlags::GEOBUCKETS;
53  StrategyFlags strategy = StrategyFlags::SUGAR_STRATEGY;
54  WT_TYPE *grading;
55  Monomial_Ordering * mord = generic_grevlex_ptr;
56  if (not meaningful_arguments(
57  argc, argv, homog, modulus, numvars, method, f4, xplor,
58  &mord, strategy, &grading
59  )) {
60  give_help();
61  } else {
62  Prime_Field FF = Prime_Field(modulus);
63  // set up the basis
64  list<Abstract_Polynomial *> F = cyclic_n(numvars, FF, homog, mord);
65  // message
66  cout << "Computing a Groebner basis for:\n";
67  for (Abstract_Polynomial * f : F)
68  cout << '\t' << *f << endl;
69  // compute basis
70  //set<Constant_Polynomial *, smaller_lm> G = buchberger(F, method);
71  list<Constant_Polynomial *> G;
72  if (f4)
73  G = f4_control(F);
74  else if (xplor)
75  G = buchberger_explorer(F, method, strategy, grading);
76  else
77  G = buchberger(F, method, strategy, grading);
78  // display basis
79  cout << G.size() << " polynomials in basis:\n";
80  /*for (list<Constant_Polynomial *>::const_iterator g = G.begin(); g != G.end(); ++g)
81  cout << '\t' << *(*g) << endl;*/
82  Polynomial_Ring * R = & (G.front()->base_ring());
83  cout << G.size() << " leading monomials:\n";
84  for (Constant_Polynomial * g : G) {
85  cout << g->leading_monomial() << ", ";
86  bool verbose = false;
87  if (verbose) cout << '\t' << *g << endl;
88  delete g;
89  }
90  for (Abstract_Polynomial * f : F) delete f;
91  delete R;
92  }
93  if (mord != generic_grevlex_ptr)
94  delete mord;
95  cout << "bye\n";
96 }
97 
98 enum order_flags { GENERIC_GREVLEX = 0, GREVLEX, LEX, WGREVLEX };
99 
100 bool meaningful_arguments(int argc, char *argv[], bool & homogeneous,
101  int & modulus, int & numvars,
102  SPolyCreationFlags & method, bool &f4, bool &xplor,
103  Monomial_Ordering ** mord, StrategyFlags & strategy,
104  WT_TYPE ** grading
105  )
106 {
107  modulus = 43;
108  method = SPolyCreationFlags::LINKED_LST;
109  homogeneous = false;
110  WT_TYPE * weights = nullptr;
111  unsigned int order_flag = 0;
112  bool good_args = (argc > 1);
113  if (good_args) {
114  for (int i = 1; good_args and i < argc; ++i) {
115  if (!strcmp(argv[i],"hom") or !strcmp(argv[i],"homog")
116  or !strcmp(argv[i],"homogeneous"))
117  homogeneous = true;
118  else if (!strcmp(argv[i],"f4"))
119  f4 = true;
120  else if (!strcmp(argv[i],"xplor"))
121  xplor = true;
122  else {
123  int j = 0;
124  for (/* */; argv[i][j] != '=' and argv[i][j] != '\0'; ++j) { /* */ }
125  if (argv[i][j] != '=') {
126  good_args = false;
127  cout << "Arguments must have form <option>=<value>.\n";
128  }
129  else {
130  argv[i][j] = '\0';
131  if (!strcmp(argv[i],"n") or !strcmp(argv[i],"num")
132  or !strcmp(argv[i],"numvars")) {
133  numvars = atoi(&(argv[i][j+1]));
134  if (numvars < 3) {
135  good_args = false;
136  cout << "Invalid number of variables: must be at least 3.\n";
137  }
138  }
139  else if (!strcmp(argv[i],"m") or !strcmp(argv[i],"mod")
140  or !strcmp(argv[i],"modulus"))
141  {
142  modulus = atoi(&(argv[i][j+1]));
143  if (modulus < 2) {
144  good_args = false;
145  cout << "Invalid modulus; must be at least 2.\n";
146  }
147  }
148  else if (!strcmp(argv[i],"r") or !strcmp(argv[i],"repr")
149  or !strcmp(argv[i], "representation"))
150  {
151  method = (SPolyCreationFlags )atoi(&(argv[i][j+1]));
152  if (
153  method <= SPolyCreationFlags::MIN_SPCREATE_FLAG or
154  method >= SPolyCreationFlags::MAX_SPCREATE_FLAG
155  ) {
156  good_args = false;
157  cout << "Invalid method; must be at least 1 and at most 3.\n";
158  }
159  }
160  else if (!strcmp(argv[i],"ord") or !strcmp(argv[i],"order")
161  or !strcmp(argv[i],"ordering"))
162  {
163  char * request = &(argv[i][j+1]);
164  if (!strcmp(request, "generic"))
165  order_flag = GENERIC_GREVLEX;
166  else if (!strcmp(request, "grevlex"))
167  order_flag = GREVLEX;
168  else if (!strcmp(request, "lex"))
169  order_flag = LEX;
170  else if (!strcmp(request, "wgrevlex")) {
171  order_flag = WGREVLEX;
172  unsigned n = (homogeneous) ? numvars + 1 : numvars;
173  weights = new WT_TYPE [n];
174  unsigned k = ++i;
175  for (/* */; k < i + n and k < argc; ++k)
176  weights[k - i] = atoi(argv[k]);
177  if (k - i < n)
178  good_args = false;
179  i = k;
180  }
181  else {
182  good_args = false;
183  cout << "Ordering must be 'generic', 'grevlex', "
184  << "'lex', or 'wgrevlex'.\n"
185  << "(Matrix orderings not yet supported via command line.)\n"
186  << "When using 'wgrevlex', follow it with a list of 'n' "
187  << "positive integers.\n";
188  }
189  }
190  else if (!strcmp(argv[i],"strat") or !strcmp(argv[i],"strategy")) {
191  char * request = &(argv[i][j+1]);
192  if (!strcmp(request, "normal") or !strcmp(request, "norm"))
193  strategy = StrategyFlags::NORMAL_STRATEGY;
194  else if (!strcmp(request, "sugar") or !strcmp(request, "sug"))
195  strategy = StrategyFlags::SUGAR_STRATEGY;
196  else if (!strcmp(request, "wsugar") or !strcmp(request, "wsug")) {
197  strategy = StrategyFlags::WSUGAR_STRATEGY;
198  unsigned n = (homogeneous) ? numvars + 1 : numvars;
199  *grading = new WT_TYPE [n];
200  unsigned k = ++i;
201  for (/* */; k < i + n and k < argc; ++k)
202  (*grading)[k - i] = atoi(argv[k]);
203  if (k - i < n)
204  good_args = false;
205  i = k;
206  }
207  else {
208  good_args = false;
209  cout << "Strategy must be 'normal' or 'sugar'.";
210  }
211  }
212  else {
213  cout << "Unrecognized argument.\n"; good_args = false;
214  }
215  }
216  }
217  }
218  }
219  if (good_args) {
220  unsigned n = (homogeneous) ? numvars + 1 : numvars;
221  switch (order_flag) {
222  case GENERIC_GREVLEX: *mord = generic_grevlex_ptr; break;
223  case GREVLEX: *mord = new Grevlex_Ordering(n); break;
224  case LEX: *mord = new Lex_Ordering(n); break;
225  case WGREVLEX: *mord = new CachedWGrevlex_Ordering(n, weights); break;
226  default: *mord = generic_grevlex_ptr;
227  }
228  }
229  return good_args;
230 }
231 
232 void give_help() {
233  cout << "Call with options n=<num> m=<mod> r=<repr>\n";
234  cout << "You *must* specify <num> vars, an integer greater than 2.\n";
235  cout << "You can add optional <mod>ulus (please make it prime).\n";
236  cout << "The option <hom>ogenize will give you a homogenized ideal.\n";
237  cout << "You can also select the <repr>esentation of s-polynomials:\n";
238  cout << "\t1) linked lists,\n";
239  cout << "\t2) geobuckets, or\n";
240  cout << "\t3) double-buffered polynomials.\n";
241  cout << "So 'test_cyclicn n=6 m=43 r=2' would compute the Groebner basis\n";
242  cout << "of the Cyclic-n ideal in 6 variables, modulo 43,";
243  cout << "using geobuckets.\n";
244  cout << "You can also specify the strategy ('normal', 'sugar', 'wsugar')\n";
245  cout << "('wsugar' requires a list of <num> integers, where <num> is as above,";
246  cout << "and the term ordering ('generic', 'grevlex', 'lex', 'wgrevlex').\n";
247  cout << "('wgrevlex' requires a list of <num> integers, where <num>";
248  cout << " is as above.\n";
249  cout << "The 'f4' option runs the F4 algorithm.\n";
250 }
The general class of a polynomial.
Definition: polynomial.hpp:101
list< Constant_Polynomial * > buchberger_explorer(const vector< Abstract_Polynomial *> &F, SPolyCreationFlags method, StrategyFlags strategy, WT_TYPE *strategy_weights, const int comm_id, const int comm_size)
Alternate implementation of Buchberger’s algorithm, for parallelization.
A Constant_Polynomial is a polynomial that should not change.
list< Constant_Polynomial * > buchberger(const list< Abstract_Polynomial *> &F, SPolyCreationFlags method, StrategyFlags strategy, WT_TYPE *strategy_weights)
Implementation of Buchberger’s algorithm.
Information necessary for a field modulo a prime.
Definition: fields.hpp:49
StrategyFlags
flag indicating which strategy to use for computation
Definition: strategies.hpp:34
SPolyCreationFlags
flag indicating which structure to use for an s-polynomial
interface to a monomial ordering
Encapsulates information about a polynomial ring for easy access: ground field, number of indetermina...
the lex ordering for a specified number of variables
the grevlex ordering for a specified number of variables
list< Constant_Polynomial * > f4_control(const list< Abstract_Polynomial *> &F)
equivalent to buchberger(), but for Faugère’s F4 algorithm
the weighted grevlex ordering for a specified number of variables, with cached weights for each monom...
list< Abstract_Polynomial * > cyclic_n(NVAR_TYPE n, Prime_Field &F, bool homog, Monomial_Ordering *mord=generic_grevlex_ptr)
generates the Cyclic- system
Definition: cyclic_n.hpp:57