Gröbner basis project
Codebase for research into Gröbner basis computation
user_interface.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 <list>
19 #include <string>
20 #include <iostream>
21 
22 using std::list;
23 using std::string;
24 using std::cin; using std::cout; using std::endl;
25 
26 #include "system_constants.hpp"
27 
28 #include "monomial.hpp"
29 #include "dynamic_engine.hpp"
30 #include "polynomial_array.hpp"
31 
32 #include "algorithm_buchberger_dynamic.hpp"
33 
59  UCOEF_TYPE p;
60  cout << "prime number for base field: ";
61  cin >> p;
62  NVAR_TYPE n;
63  cout << "number of indeterminates: ";
64  cin >> n;
65  char specify_names;
66  cout << "do you want to specify the indeterminates' names? (y/n) ";
67  cin >> specify_names;
68  string * names = new string[n];
69  Prime_Field F = Prime_Field(p);
70  Polynomial_Ring * P;
71  if (not specify_names) {
72  P = new Polynomial_Ring(n, F);
73  cout << "indeterminate names are: ";
74  for (NVAR_TYPE i = 0; i < n; ++i) {
75  cout << P->name(i);
76  names[i] = P->name(i);
77  }
78  } else {
79  for (NVAR_TYPE i = 0; i < n; ++i)
80  cin >> names[i];
81  P = new Polynomial_Ring(n, F, names);
82  }
83  unsigned m;
84  cout << "number of polynomials: ";
85  cin >> m;
86  cin.ignore();
87  list<Abstract_Polynomial *> I;
88  for (unsigned np = 0; np < m; ++np) {
89  cout << "please enter polynomial #" << np << ": (use spaces to separate factors) ";
90  string inpoly;
91  getline(cin, inpoly);
92  list<Monomial> M; // monomials
93  list<Prime_Field_Element> A; // coefficients
94  unsigned nt = 0; // number of terms
95  unsigned i = 0;
96  while (i < inpoly.size()) {
97  bool reading_term = true;
98  COEF_TYPE a = 1;
99  EXP_TYPE exp[n];
100  for (NVAR_TYPE i = 0; i < n; ++i) exp[i] = 0;
101  bool positive = true;
102  while (inpoly[i] == ' ') ++i;
103  while (reading_term and i < inpoly.size()) {
104  unsigned j = i;
105  if (
106  inpoly[i] == '+' or inpoly[i] == '-' or
107  (inpoly[i] >= '0' and inpoly[i] <= '9')
108  ) {
109  bool positive = true;
110  if (inpoly[i] == '-') positive = false;
111  if (inpoly[i] == '+' or inpoly[i] == '-') ++i;
112  while (inpoly[i] == ' ') ++i;
113  if (inpoly[i] >= '0' and inpoly[i] <= '9') {
114  j = i;
115  while (inpoly[j] >= '0' and inpoly[j] <= '9') ++j;
116  a *= stol(inpoly.substr(i, j - i));
117  if (not positive) a *= -1;
118  i = j;
119  }
120  }
121  else if (inpoly[i] == '*')
122  ++i;
123  else if (inpoly[i] == '\0')
124  ++i;
125  else { // should be characters
126  unsigned j = i;
127  while ((inpoly[j] >= 'a' and inpoly[j] <= 'z') or
128  (inpoly[j] >= 'A' and inpoly[j] <= 'Z') or
129  (inpoly[j] >= '0' and inpoly[j] <= '9'))
130  ++j;
131  string var_name = inpoly.substr(i, j - i);
132  bool found = false;
133  unsigned k = 0;
134  for (/* */; not found and k < n; ++k)
135  if (var_name.compare(names[k]) == 0) {
136  found = true;
137  --k;
138  }
139  i = j;
140  while (inpoly[i] == ' ') ++i;
141  if (inpoly[i] != '^')
142  exp[k] += 1;
143  else {
144  ++i;
145  while (inpoly[i] == ' ') ++i;
146  unsigned j = i;
147  while (inpoly[j] >= '0' and inpoly[j] <= '9') ++j;
148  exp[k] += stol(inpoly.substr(i, j - i));
149  i = j;
150  }
151  }
152  while (inpoly[i] == ' ') ++i;
153  if (inpoly[i] == '+' or inpoly[i] == '-') reading_term = false;
154  }
155  ++nt;
156  if (not positive) a *= -1;
157  Monomial t(n, exp);
158  M.push_back(t);
159  A.emplace_back(a, &F);
160  }
161  Abstract_Polynomial * p = new Constant_Polynomial(*P, M, A);
162  p->sort_by_order();
163  cout << "read " << *p << endl;
164  I.push_back(p);
165  }
166  string computation;
167  while (
168  computation.compare("s") and computation.compare("d")
169  and computation.compare("static") and computation.compare("dynamic")
170  ) {
171  cout << "static (s) or dynamic (d) computation? ";
172  getline(cin, computation);
173  }
174  list<Constant_Polynomial *> B;
175  bool dynamic = not (computation.compare("d") and computation.compare("dynamic"));
176  if (not dynamic) {
177  B = buchberger(I);
178  } else {
179  DynamicSolver solver;
180  string solver_choice;
181  while (
182  solver_choice.compare("skel") and solver_choice.compare("glpk")
183  and solver_choice.compare("ppl") and solver_choice.compare("skeleton")
184  ) {
185  cout << "which solver? ([skel]eton, glpk, ppl) ";
186  getline(cin, solver_choice);
187  }
188  if (not solver_choice.compare("skel") or not solver_choice.compare("skeleton"))
189  solver = SKELETON_SOLVER;
190  else if (not solver_choice.compare("glpk"))
191  solver = GLPK_SOLVER;
192  else if (not solver_choice.compare("ppl"))
193  solver = PPL_SOLVER;
194  string heur_choice;
195  DynamicHeuristic heuristic;
196  while (
197  heur_choice.compare("h") and heur_choice.compare("gh")
198  and heur_choice.compare("b") and heur_choice.compare("bb")
199  and heur_choice.compare("gb") and heur_choice.compare("c")
200  and heur_choice.compare("d")
201  ) {
202  cout << "available heuristics are\n";
203  cout << "\t h = hilbert with standard grading\n";
204  cout << "\tgh = hilbert with order-based grading\n";
205  cout << "\t b = betti with standard grading\n";
206  cout << "\tbb = \"big\" betti with standard grading\n";
207  cout << "\tgb = betti with order-based grading\n";
208  cout << "\t c = minimal number of critical pairs\n";
209  cout << "\t d = minimal degree, ties broken by hilbert\n";
210  cout << "which heuristic would you like? ";
211  getline(cin, heur_choice);
212  }
213  if (not heur_choice.compare( "h")) heuristic = DynamicHeuristic::ORD_HILBERT_THEN_DEG;
214  else if (not heur_choice.compare("gh")) heuristic = DynamicHeuristic::GRAD_HILB_THEN_DEG;
215  else if (not heur_choice.compare( "b")) heuristic = DynamicHeuristic::BETTI_HILBERT_DEG;
216  else if (not heur_choice.compare("bb")) heuristic = DynamicHeuristic::BIG_BETTI_HILBERT_DEG;
217  else if (not heur_choice.compare("gb")) heuristic = DynamicHeuristic::GRAD_BETTI_HILBERT_DEG;
218  else if (not heur_choice.compare( "c")) heuristic = DynamicHeuristic::MIN_CRIT_PAIRS;
219  else if (not heur_choice.compare( "d")) heuristic = DynamicHeuristic::DEG_THEN_ORD_HILBERT;
220  string whether_analysis;
221  bool analyze_first = false;
222  while (whether_analysis.compare("y") and whether_analysis.compare("n")) {
223  cout << "perform global analysis at the outset? (y or n) ";
224  cin >> whether_analysis;
225  }
226  if (not whether_analysis.compare("y")) analyze_first = true;
227  B = buchberger_dynamic(
228  I, SPolyCreationFlags::GEOBUCKETS, StrategyFlags::SUGAR_STRATEGY,
229  nullptr, heuristic, solver, analyze_first
230  );
231  }
232  cout << "have basis with " << B.size() << " elements:\n";
233  for (auto b : B) {
234  cout << b->leading_monomial() << ", ";
235  delete b;
236  }
237  cout << endl;
238  for (auto p : I) delete p;
239  delete P;
240  delete [] names;
241 }
242 
243 int main() {
244  user_interface();
245 }
The general class of a polynomial.
Definition: polynomial.hpp:101
A Constant_Polynomial is a polynomial that should not change.
virtual void sort_by_order()=0
sort according to the leading monomial’s ordering
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
DynamicHeuristic
virtual const string name(NVAR_TYPE i) const
name of the th indeterminate
Implementation of monomials.
Definition: monomial.hpp:69
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
void user_interface()
reads ideal definition from cin, then reads options for computation, writes Gröbner basis to cout ...