Gröbner basis project
Codebase for research into Gröbner basis computation
test_dynamic.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 "goda.hpp"
28 #include "cyclic_n.hpp"
29 #include "polynomial.hpp"
30 #include "strategies.hpp"
31 #include "dynamic_engine.hpp"
32 #include "monomial_ordering.hpp"
33 #include "particular_orderings.hpp"
34 #include "polynomial_linked_list.hpp"
35 #include "algorithm_buchberger_dynamic.hpp"
36 
37 extern Monomial_Ordering * generic_grevlex_ptr;
44 
45 // Forward declarations
46 bool meaningful_arguments(
47  int, char **, bool &, int &, int &, SPolyCreationFlags &,
49 );
50 
51 void give_help();
52 
53 int main(int argc, char *argv[]) {
54  bool homog;
55  int modulus, numvars;
56  SPolyCreationFlags method;
57  StrategyFlags strategy = StrategyFlags::SUGAR_STRATEGY;
58  DynamicHeuristic heuristic = DynamicHeuristic::ORD_HILBERT_THEN_DEG;
59  DynamicSolver solver = SKELETON_SOLVER;
60  WT_TYPE * grading = nullptr;
61  CachedWGrevlex_Ordering * mord = nullptr;
62  const CachedWGrevlex_Ordering * ford = nullptr; // final ordering
63  if (not meaningful_arguments(
64  argc, argv, homog, modulus, numvars, method, strategy, heuristic, solver
65  )) {
66  give_help();
67  } else {
68  int true_numvars = (homog) ? numvars + 1 : numvars;
69  grading = new WT_TYPE [true_numvars];
70  for (NVAR_TYPE i = 0; i < true_numvars; ++i) grading[i] = 1;
71  mord = new CachedWGrevlex_Ordering(true_numvars, grading);
72  Prime_Field FF = Prime_Field(modulus);
73  // set up the basis
74  list<Abstract_Polynomial *> F = cyclic_n(numvars, FF, homog, mord);
75  // message
76  cout << "Computing a Groebner basis for:\n";
77  for (Abstract_Polynomial * f : F)
78  cout << '\t' << *f << endl;
79  cout << "Using ";
80  switch(solver) {
81  case GLPK_SOLVER: cout << "GLPK\n"; break;
82  case SKELETON_SOLVER: cout << "Skeleton\n"; break;
83  case PPL_SOLVER: cout << "PPL\n"; break;
84  default: cout << "Unknown solver\n"; break;
85  }
86  // compute basis
87  list<Constant_Polynomial *> G = buchberger_dynamic(
88  F, method, strategy, grading, (DynamicHeuristic )heuristic, solver
89  );
90  // display basis
91  cout << G.size() << " polynomials in basis:\n";
92  /*for (list<Constant_Polynomial *>::const_iterator g = G.begin(); g != G.end(); ++g)
93  cout << '\t' << *(*g) << endl;*/
94  Polynomial_Ring * R = & (G.front()->base_ring());
95  ford = static_cast<const CachedWGrevlex_Ordering *>(
96  G.front()->monomial_ordering()
97  );
98  cout << G.size() << " leading monomials:\n";
99  for (Constant_Polynomial * g : G) {
100  cout << g->leading_monomial() << ", ";
101  //cout << *g << endl;
102  delete g;
103  }
104  cout << endl;
105  for (Abstract_Polynomial * f : F) delete f;
106  delete R;
107  }
108  if (ford != nullptr) {
109  delete [] ford->order_weights();
110  delete ford;
111  }
112  if (mord != generic_grevlex_ptr) delete mord;
113  if (goda != nullptr) delete goda;
114  if (doda != nullptr) delete doda;
115  if (moda != nullptr) delete moda;
116  if (monoda != nullptr) delete monoda;
117  if (monododa != nullptr) delete monododa;
118  if (woda != nullptr) delete woda;
119  if (grading != nullptr) delete [] grading;
120  cout << "bye\n";
121 }
122 
123 enum order_flags { GENERIC_GREVLEX = 0, GREVLEX, LEX, WGREVLEX };
124 
125 bool meaningful_arguments(
126  int argc, char *argv[],
127  bool & homogeneous, int & modulus, int & numvars,
128  SPolyCreationFlags & method, StrategyFlags & strategy,
129  DynamicHeuristic & heuristic, DynamicSolver & solver
130 ) {
131  modulus = 43;
132  method = SPolyCreationFlags::GEOBUCKETS;
133  homogeneous = false;
134  WT_TYPE * weights = nullptr;
135  unsigned int order_flag = 0;
136  bool good_args = (argc > 1);
137  if (good_args) {
138  for (int i = 1; good_args and i < argc; ++i) {
139  if (!strcmp(argv[i],"hom") or !strcmp(argv[i],"homog")
140  or !strcmp(argv[i],"homogeneous"))
141  homogeneous = true;
142  else {
143  int j = 0;
144  for (/* */; argv[i][j] != '=' and argv[i][j] != '\0'; ++j) { /* */ }
145  if (argv[i][j] != '=') {
146  good_args = false;
147  cout << "Options must have form <option>=<value>.\n";
148  }
149  else {
150  argv[i][j] = '\0';
151  if (!strcmp(argv[i],"n") or !strcmp(argv[i],"num")
152  or !strcmp(argv[i],"numvars")) {
153  numvars = atoi(&(argv[i][j+1]));
154  if (numvars < 3) {
155  good_args = false;
156  cout << "Invalid number of variables: must be at least 3.\n";
157  }
158  }
159  else if (!strcmp(argv[i],"m") or !strcmp(argv[i],"mod")
160  or !strcmp(argv[i],"modulus"))
161  {
162  modulus = atoi(&(argv[i][j+1]));
163  if (modulus < 2) {
164  good_args = false;
165  cout << "Invalid modulus; must be at least 2.\n";
166  }
167  }
168  else if (!strcmp(argv[i],"r") or !strcmp(argv[i],"repr")
169  or !strcmp(argv[i], "representation"))
170  {
171  method = (SPolyCreationFlags )atoi(&(argv[i][j+1]));
172  if (
173  method <= SPolyCreationFlags::MIN_SPCREATE_FLAG or
174  method >= SPolyCreationFlags::MAX_SPCREATE_FLAG
175  ) {
176  good_args = false;
177  cout << "Invalid method; must be at least 1 and at most 3.\n";
178  }
179  }
180  else if (!strcmp(argv[i], "heur") or !strcmp(argv[i],"heuristic")) {
181  heuristic = (DynamicHeuristic)atoi(&(argv[i][j+1]));
182  if (
183  heuristic <= DynamicHeuristic::MIN_HEURISTIC or
184  heuristic >= DynamicHeuristic::MAX_HEURISTIC
185  ) {
186  good_args = false;\
187  cout << "Invalid method; must be at least 1 and at most 10.\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  }
200  else {
201  good_args = false;
202  cout << "Strategy must be 'normal' or 'sugar' or 'wsugar'.\n";
203  }
204  }
205  else if (!strcmp(argv[i],"solver")) {
206  char * request = &(argv[i][j+1]);
207  if (!strcmp(request, "skel") or !strcmp(request, "skeleton"))
208  solver = SKELETON_SOLVER;
209  else if (!strcmp(request, "glpk") or !strcmp(request, "GLPK"))
210  solver = GLPK_SOLVER;
211  else if (!strcmp(request, "ppl") or !strcmp(request, "PPL"))
212  solver = PPL_SOLVER;
213  else {
214  good_args = false;
215  cout << "Strategy must be 'skeleton' or 'glpk'.\n";
216  }
217  }
218  else {
219  cout << "Unrecognized argument.\n"; good_args = false;
220  }
221  }
222  }
223  }
224  }
225  return good_args;
226 }
227 
228 void give_help() {
229  cout << "Call with options n=<num> m=<mod> r=<repr> [hom] heur=<heur>\n";
230  cout << "You *must* specify <num> vars, an integer greater than 2.\n";
231  cout << "You can add optional <mod>ulus (please make it prime).\n";
232  cout << "The option <hom>ogenize will give you a homogenized ideal.\n";
233  cout << "You can also select the <repr>esentation of s-polynomials:\n";
234  cout << "\t1) linked lists,\n";
235  cout << "\t2) geobuckets, or\n";
236  cout << "\t3) double-buffered polynomials.\n";
237  cout << "The option <heur>istic allows you to select from the following:\n";
238  cout << "\t1) Hilbert heuristic w/ties broken by lex ordering,\n";
239  cout << "\t2) Hilbert heuristic w/ties broken by total degree,\n";
240  cout << "\t3) total degree w/ties broken by Hilbert heuristic,\n";
241  cout << "\t4) graded Hilbert heuristic w/ties broken by lex ordering,\n";
242  cout << "\t5) total degree w/ties broken by graded Hilbert heuristic,\n";
243  cout << "\t6) aiming for polynomials of smoothest degrees (nearly homogeneous),\n";
244  cout << "\t7) aiming for a polynomial with the largest maximal component,\n";
245  cout << "\t8) aiming to minimize the number of new critical pairs at min degree,\n";
246  cout << "\t9) aiming to minimize the number of new critical pairs at min graded degree,\n";
247  cout << "\t10) pseudosignature Hilbert heuristic.\n";
248  cout << "So 'test_cyclicn n=6 m=43 r=2' would compute the Groebner basis\n";
249  cout << "of the Cyclic-n ideal in 6 variables, modulo 43,";
250  cout << "using geobuckets.\n";
251  cout << "You can also specify the strategy ('normal', 'sugar', 'wsugar')\n";
252  cout << "('wsugar' requires a list of <num> integers, where <num> is as above.";
253 }
virtual const WT_TYPE * order_weights() const override
the weights that define this ordering
The general class of a polynomial.
Definition: polynomial.hpp:101
special memory pool allocator for Grevlex_Order_Data and WGrevlex_Order_Data
Definition: goda.hpp:67
Grading_Order_Data_Allocator< Monomial > * monoda
memory manager for monomials (not their exponents; see moda for that).
Definition: monomial.cpp:53
A Constant_Polynomial is a polynomial that should not change.
Grading_Order_Data_Allocator< EXP_TYPE > * moda
memory manager for monomial exponents
Definition: monomial.cpp:46
Grading_Order_Data_Allocator< DEG_TYPE > * doda
memory manager for ray entries
Definition: lp_solver.cpp:122
Information necessary for a field modulo a prime.
Definition: fields.hpp:49
Grading_Order_Data_Allocator< CachedWGrevlex_Ordering > * woda
Memory manager for graded orderings (not their data; see goda for that).
StrategyFlags
flag indicating which strategy to use for computation
Definition: strategies.hpp:34
SPolyCreationFlags
flag indicating which structure to use for an s-polynomial
DynamicHeuristic
interface to a monomial ordering
Grading_Order_Data_Allocator< WT_TYPE > * goda
Memory manager for graded ordering data.
Encapsulates information about a polynomial ring for easy access: ground field, number of indetermina...
DynamicSolver
used by buchberger_dynamic() to decide which solver to use
list< Constant_Polynomial * > buchberger_dynamic(const list< Abstract_Polynomial *> &F, SPolyCreationFlags method, StrategyFlags strategy, WT_TYPE *strategy_weights, DynamicHeuristic heuristic, DynamicSolver solver_type, bool analyze_inputs)
implementation of the dynamic Buchberger algorithm
the weighted grevlex ordering for a specified number of variables, with cached weights for each monom...
Grading_Order_Data_Allocator< Monomial_Node > * monododa
memory manager for Monomial_Node
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