singmathic.cc
Go to the documentation of this file.
1 #include <kernel/mod2.h>
2 
3 #ifdef HAVE_MATHICGB
4 
5 #include <misc/auxiliary.h>
6 
7 #include <misc/options.h>
8 
9 #include <kernel/ideals.h>
10 #include <kernel/polys.h>
11 
12 #include <Singular/ipid.h>
13 #include <Singular/mod_lib.h>
14 
15 #include <mathicgb.h>
16 
21 
22 // Constructs a Singular ideal.
24 public:
26  mModulus(modulus),
27  mVarCount(varCount),
28  mPolyCount(0),
29  mTerm(0),
30  mIdeal(0)
31  {}
32 
34 
35  // Mathic stream interface
36 
37  Coefficient modulus() const {return mModulus;}
38  VarIndex varCount() const {return mModulus;}
39 
40  void idealBegin(size_t polyCount) {
41  deleteIdeal();
42  mIdeal = idInit(polyCount);
43  mPolyCount = 0;
44  }
45 
46  void appendPolynomialBegin(size_t termCount) {}
47 
48  void appendTermBegin() {
49  if (mTerm == 0)
50  mTerm = mIdeal->m[mPolyCount] = pInit();
51  else
52  mTerm = mTerm->next = pInit();
53  }
54 
56  pSetExp(mTerm, index + 1, exponent);
57  }
58 
59  void appendTermDone(Coefficient coefficient) {
60  mTerm->coef = reinterpret_cast<number>(coefficient);
61  pSetm(mTerm);
62  }
63 
65  ++mPolyCount;
66  mTerm = 0;
67  }
68 
69  void idealDone() {}
70 
71 
72  // Singular interface
73 
75  ::ideal id = mIdeal;
76  mIdeal = 0;
77  return id;
78  }
79 
80 private:
81  void deleteIdeal() {
82  if (mIdeal != 0) {
83  idDelete(&mIdeal);
84  mIdeal = 0;
85  }
86  }
87 
90  size_t mPolyCount;
93 };
94 
95 #include <iostream>
96 
97 bool setOrder(ring r, mgb::GroebnerConfiguration& conf) {
98  const VarIndex varCount = conf.varCount();
99 
100  bool didSetComponentBefore = false;
102  mgb::GroebnerConfiguration::RevLexDescendingBaseOrder;
103 
104  std::vector<Exponent> gradings;
105  for (int block = 0; r->order[block] != ringorder_no; ++block) {
106  // *** ringorder_no
107 
108  const rRingOrder_t type = static_cast<rRingOrder_t>(r->order[block]);
109  if (r->block0[block] < 0 || r->block1[block] < 0) {
110  WerrorS("Unexpected negative block0/block1 in ring.");
111  return false;
112  }
113  const VarIndex block0 = static_cast<VarIndex>(r->block0[block]);
114  const VarIndex block1 = static_cast<VarIndex>(r->block1[block]);
115  const int* const weights = r->wvhdl[block];
116  if (block0 > block1) {
117  WerrorS("Unexpected block0 > block1 in ring.");
118  return false;
119  }
120 
121  // *** ringorder_c and ringorder_C
122  if (type == ringorder_c || type == ringorder_C) {
123  if (block0 != 0 || block1 != 0 || weights != 0) {
124  WerrorS("Unexpected non-zero fields on c/C block in ring.");
125  return false;
126  }
127  if (didSetComponentBefore) {
128  WerrorS("Unexpected two c/C blocks in ring.");
129  return false;
130  }
131  didSetComponentBefore = true;
132  if (r->order[block + 1] == ringorder_no) {
133  conf.setComponentBefore
134  (mgb::GroebnerConfiguration::ComponentAfterBaseOrder);
135  } else
136  conf.setComponentBefore(gradings.size() / varCount);
137  conf.setComponentsAscending(type == ringorder_C);
138  continue;
139  }
140  if (block0 == 0 || block1 == 0) {
141  WerrorS("Expected block0 != 0 and block1 != 0 in ring.");
142  return false;
143  }
144  if (block1 > varCount) {
145  // todo: first handle any block types where this is not true
146  WerrorS("Expected block1 <= #vars in ring.");
147  return false;
148  }
149 
150  // dim is how many variables this block concerns.
151  const size_t dim = static_cast<size_t>(block1 - block0 + 1);
152 
153  // *** single-graded/ungraded lex/revlex orders
154  // a(w): w-graded and that's it
155  // a64(w): w-graded with 64-bit weights (not supported here)
156  // lp: lex from left (descending)
157  // Dp: 1-graded, lex from left (descending)
158  // Ds: -1-graded, lex from left (descending)
159  // Wp(w): w-graded, lex from left (descending)
160  // Ws(w): -w-graded, lex from left (descending)
161  // rp: lex from right (ascending)
162  // rs: revlex from right (descending)
163  // dp: 1-graded, revlex from right (descending)
164  // ds: -1-graded, revlex from right (descending)
165  // wp(w): w-graded, revlex from right (descending)
166  // ws(w): -w-graded, revlex from right (descending)
167  // ls: revlex from left (ascending)
168 
169  if (type == ringorder_a64) {
170  WerrorS("Block type a64 not supported for MathicGB interface.");
171  return false;
172  }
173 
174  // * handle the single-grading part
175  const bool oneGrading = (type == ringorder_Dp || type == ringorder_dp);
176  const bool minusOneGrading = (type == ringorder_Ds || type == ringorder_ds);
177  const bool wGrading =
178  (type == ringorder_a || type == ringorder_Wp || type == ringorder_wp);
179  const bool minusWGrading = (type == ringorder_ws || type == ringorder_Ws);
180  if (oneGrading || minusOneGrading || wGrading || minusWGrading) {
181  const VarIndex begin = gradings.size();
182  gradings.resize(begin + varCount);
183  if (oneGrading || minusOneGrading) {
184  if (weights != 0) {
185  WerrorS("Expect wvhdl == 0 in Dp/dp/Ds/ds-block in ring.");
186  return false;
187  }
188  const Exponent value = oneGrading ? 1 : -1;
189  for (int var = block0 - 1; var < block1; ++var)
190  gradings[begin + var] = value;
191  } else {
192  if (weights == 0) {
193  WerrorS("Expect wvhdl != 0 in a/Wp/wp/ws/Ws-block in ring.");
194  return false;
195  }
196  if (wGrading) {
197  for (int var = 0; var < dim; ++var)
198  gradings[begin + (block0 - 1) + var] = weights[var];
199  } else {
200  for (int var = 0; var < dim; ++var)
201  gradings[begin + (block0 - 1) + var] = -weights[var];
202  }
203  }
204  }
205  if (type == ringorder_a)
206  continue; // a has only the grading, so we are done already
207 
208  // * handle the lex/revlex part
209  const bool lexFromLeft =
210  type == ringorder_lp ||
211  type == ringorder_Dp ||
212  type == ringorder_Ds ||
213  type == ringorder_Wp ||
214  type == ringorder_Ws;
215  const bool lexFromRight = type == ringorder_rp;
216  const bool revlexFromLeft = type == ringorder_ls;
217  const bool revlexFromRight =
218  type == ringorder_rs ||
219  type == ringorder_dp ||
220  type == ringorder_ds ||
221  type == ringorder_wp ||
222  type == ringorder_ws;
223  if (lexFromLeft || lexFromRight || revlexFromLeft || revlexFromRight) {
224  const int next = r->order[block + 1];
225  bool final = next == ringorder_no;
226  if (!final && r->order[block + 2] == ringorder_no)
227  final = next == ringorder_c || next == ringorder_C;
228  if (final) {
229  if (lexFromRight)
230  baseOrder = mgb::GroebnerConfiguration::LexAscendingBaseOrder;
231  else if (revlexFromRight)
232  baseOrder = mgb::GroebnerConfiguration::RevLexDescendingBaseOrder;
233  else if (lexFromLeft)
234  baseOrder = mgb::GroebnerConfiguration::LexDescendingBaseOrder;
235  else
236  baseOrder = mgb::GroebnerConfiguration::RevLexAscendingBaseOrder;
237  continue;
238  }
239 
240  const size_t begin = gradings.size();
241  gradings.resize(begin + dim * varCount);
242  const Exponent value = (lexFromLeft || lexFromRight) ? 1 : -1;
243  if (lexFromLeft || revlexFromLeft) {
244  for (size_t row = 0; row < dim; ++row)
245  gradings[begin + row * varCount + (block0 - 1) + row] = value;
246  } else {
247  for (size_t row = 0; row < dim; ++row)
248  gradings[begin + row * varCount + (block1 - 1) - row] = value;
249  }
250  continue;
251  }
252 
253  // *** ringorder_M: a square invertible matrix
254  if (type == ringorder_M) {
255  if (weights == 0) {
256  WerrorS("Expected wvhdl != 0 in M-block in ring.");
257  return false;
258  }
259  const size_t begin = gradings.size();
260  gradings.resize(begin + dim * varCount);
261  for (size_t row = 0; row < dim; ++row)
262  for (size_t col = block0 - 1; col < block1; ++col)
263  gradings[begin + row * varCount + col] = weights[row * dim + col];
264  continue;
265  }
266 
267  // *** Miscellaneous unsupported or invalid block types
268  if (
269  type == ringorder_s ||
270  type == ringorder_S ||
271  type == ringorder_IS
272  ) {
273  // todo: Consider supporting this later.
274  WerrorS("Schreyer order s/S/IS not supported in MathicGB interface.");
275  return false;
276  }
277  if (type == ringorder_am) {
278  // This block is a Schreyer-like ordering only used in Spielwiese.
279  // todo: Consider supporting it later.
280  WerrorS("Block type am not supported in MathicGB interface");
281  return false;
282  }
283  if (type == ringorder_L) {
284  WerrorS("Invalid L-block found in order of ring.");
285  return false;
286  }
287  if (type == ringorder_aa) {
288  // I don't know what an aa block is supposed to do.
289  WerrorS("aa ordering not supported by the MathicGB interface.");
290  return false;
291  }
292  if (type == ringorder_unspec) {
293  WerrorS("Invalid unspec-block found in order of ring.");
294  return false;
295  }
296  WerrorS("Unknown block type found in order of ring.");
297  return false;
298  }
299 
300  if (!didSetComponentBefore) {
301  WerrorS("Expected to find a c/C block in ring.");
302  return false;
303  }
304 
305  if (!conf.setMonomialOrder(baseOrder, gradings)) {
306  WerrorS("MathicGB does not support non-global orders.");
307  return false;
308  }
309  return true;
310 }
311 
312 bool prOrderMatrix(ring r) {
313  const int varCount = r->N;
314  mgb::GroebnerConfiguration conf(101, varCount);
315  if (!setOrder(r, conf))
316  return false;
317  const std::vector<Exponent>& gradings = conf.monomialOrder().second;
318  if (gradings.size() % varCount != 0) {
319  WerrorS("Expected matrix to be a multiple of varCount.");
320  return false;
321  }
322  const size_t rowCount = gradings.size() / varCount;
323  std::cout << "Order matrix:\n";
324  for (size_t row = 0; row < rowCount; ++row) {
325  for (size_t col = 0; col < varCount; ++col)
326  std::cerr << ' ' << gradings[row * varCount + col];
327  std::cerr << '\n';
328  }
329  std::cerr
330  << "Base order: "
331  << mgb::GroebnerConfiguration::baseOrderName(conf.monomialOrder().first)
332  << '\n';
333  std::cerr << "Component before: " << conf.componentBefore() << '\n';
334  std::cerr << "Components ascending: " << conf.componentsAscending() << '\n';
335  std::cerr << "Schreyering: " << conf.schreyering() << '\n';
336 }
337 
338 void prOrder(ring r) {
339  std::cout << "Printing order of ring.\n";
340  for (int block = 0; ; ++block) {
341  switch (r->order[block]) {
342  case ringorder_no: // end of blocks
343  return;
344 
345  case ringorder_a:
346  std::cout << "a";
347  break;
348 
349  case ringorder_a64: ///< for int64 weights
350  std::cout << "a64";
351  break;
352 
353  case ringorder_c:
354  std::cout << "c";
355  break;
356 
357  case ringorder_C:
358  std::cout << "C";
359  break;
360 
361  case ringorder_M:
362  std::cout << "M";
363  break;
364 
365  case ringorder_S: ///< S?
366  std::cout << "S";
367  break;
368 
369  case ringorder_s: ///< s?
370  std::cout << "s";
371  break;
372 
373  case ringorder_lp:
374  std::cout << "lp";
375  break;
376 
377  case ringorder_dp:
378  std::cout << "dp";
379  break;
380 
381  case ringorder_rp:
382  std::cout << "rp";
383  break;
384 
385  case ringorder_Dp:
386  std::cout << "Dp";
387  break;
388 
389  case ringorder_wp:
390  std::cout << "wp";
391  break;
392 
393  case ringorder_Wp:
394  std::cout << "Wp";
395  break;
396 
397  case ringorder_ls:
398  std::cout << "ls"; // not global
399  break;
400 
401  case ringorder_ds:
402  std::cout << "ds"; // not global
403  break;
404 
405  case ringorder_Ds:
406  std::cout << "Ds"; // not global
407  break;
408 
409  case ringorder_ws:
410  std::cout << "ws"; // not global
411  break;
412 
413  case ringorder_Ws:
414  std::cout << "Ws"; // not global
415  break;
416 
417  case ringorder_am:
418  std::cout << "am";
419  break;
420 
421  case ringorder_L:
422  std::cout << "L";
423  break;
424 
425  // the following are only used internally
426  case ringorder_aa: ///< for idElimination, like a, except pFDeg, pWeigths ignore it
427  std::cout << "aa";
428  break;
429 
430  case ringorder_rs: ///< opposite of ls
431  std::cout << "rs";
432  break;
433 
434  case ringorder_IS: ///< Induced (Schreyer) ordering
435  std::cout << "IS";
436  break;
437 
438  case ringorder_unspec:
439  std::cout << "unspec";
440  break;
441  }
442  const int b0 = r->block0[block];
443  const int b1 = r->block1[block];
444  std::cout << ' ' << b0 << ':' << b1 << " (" << r->wvhdl[block] << ")" << std::flush;
445  if (r->wvhdl[block] != 0 && b0 != 0) {
446  for (int v = 0; v <= b1 - b0; ++v)
447  std::cout << ' ' << r->wvhdl[block][v];
448  } else
449  std::cout << " null";
450  std::cout << '\n';
451  }
452 }
453 
455  if (currRing == 0) {
456  WerrorS("There is no current ring.");
457  return TRUE;
458  }
459  prOrder(currRing);
461  result->rtyp=NONE;
462  return FALSE;
463 }
464 
466  currRing->OrdSgn = 1;
467  result->rtyp=NONE;
468  return FALSE;
469 }
470 
472 {
473  result->rtyp=NONE;
474 
475  if (arg == NULL || arg->next != NULL || arg->Typ() != IDEAL_CMD) {
476  WerrorS("Syntax: mathicgb(<ideal>)");
477  return TRUE;
478  }
479  if (!rField_is_Zp(currRing)) {
480  WerrorS("Polynomial ring must be over Zp.");
481  return TRUE;
482  }
483 
484  const int characteristic = n_GetChar(currRing);
485  const int varCount = currRing->N;
486  mgb::GroebnerConfiguration conf(characteristic, varCount);
487  if (!setOrder(currRing, conf))
488  return TRUE;
489  if (TEST_OPT_PROT)
490  conf.setLogging("all");
491 
492  mgb::GroebnerInputIdealStream toMathic(conf);
493 
494  const ideal id = static_cast<const ideal>(arg->Data());
495  const int size = IDELEMS(id);
496  toMathic.idealBegin(size);
497  for (int i = 0; i < size; ++i) {
498  const poly origP = id->m[i];
499  int termCount = 0;
500  for (poly p = origP; p != 0; p = pNext(p))
501  ++termCount;
502  toMathic.appendPolynomialBegin(termCount);
503 
504  for (poly p = origP; p != 0; p = pNext(p)) {
505  toMathic.appendTermBegin();
506  for (int i = 1; i <= currRing->N; ++i)
507  toMathic.appendExponent(i - 1, pGetExp(p, i));
508  const long coefLong = reinterpret_cast<long>(pGetCoeff(p));
509  toMathic.appendTermDone(static_cast<int>(coefLong));
510  }
511  toMathic.appendPolynomialDone();
512  }
513  toMathic.idealDone();
514 
515  MathicToSingStream fromMathic(characteristic, varCount);
516  mgb::computeGroebnerBasis(toMathic, fromMathic);
517 
518  result->rtyp=IDEAL_CMD;
519  result->data = fromMathic.takeIdeal();
520  return FALSE;
521 }
522 
523 template class std::vector<Exponent>;
524 template void mgb::computeGroebnerBasis<MathicToSingStream>
525  (mgb::GroebnerInputIdealStream&, MathicToSingStream&);
526 
527 int SI_MOD_INIT(singmathic)(SModulFunctions* psModulFunctions)
528 {
529  PrintS("Initializing Singular-Mathic interface Singmathic.\n");
530  psModulFunctions->iiAddCproc(
531  (currPack->libname ? currPack->libname : ""),
532  "mathicgb",
533  FALSE,
534  mathicgb
535  );
536  psModulFunctions->iiAddCproc(
537  (currPack->libname ? currPack->libname : ""),
538  "mathicgb_prOrder",
539  FALSE,
540  prOrderX
541  );
542  psModulFunctions->iiAddCproc(
543  (currPack->libname ? currPack->libname : ""),
544  "mathicgb_setRingGlobal",
545  FALSE,
547  );
548  return MAX_TOK;
549 }
550 
551 /* #else
552 
553 int SI_MOD_INIT(singmathic)(SModulFunctions* psModulFunctions)
554 {
555  WerrorS(
556  "Cannot initialize the Singular interface to MathicGB "
557  "as this Singular executable was built without support "
558  "for MathicGB."
559  );
560  return 1;
561 }
562 */
563 
564 #endif /* HAVE_MATHICGB */
for idElimination, like a, except pFDeg, pWeigths ignore it
Definition: ring.h:684
for int64 weights
Definition: ring.h:664
Class used for (list of) interpreter objects.
Definition: subexpr.h:83
#define pSetm(p)
Definition: polys.h:241
BOOLEAN prOrderX(leftv result, leftv arg)
Definition: singmathic.cc:454
#define block
Definition: scanner.cc:662
bool setOrder(ring r, mgb::GroebnerConfiguration &conf)
Definition: singmathic.cc:97
int SI_MOD_INIT() singmathic(SModulFunctions *psModulFunctions)
Definition: singmathic.cc:527
#define TEST_OPT_PROT
Definition: options.h:98
#define pSetExp(p, i, v)
Definition: polys.h:42
mgb::GroebnerConfiguration::VarIndex VarIndex
Definition: singmathic.cc:18
#define FALSE
Definition: auxiliary.h:140
Compatiblity layer for legacy polynomial operations (over currRing)
BOOLEAN setRingGlobal(leftv result, leftv arg)
Definition: singmathic.cc:465
return P p
Definition: myNF.cc:203
opposite of ls
Definition: ring.h:685
MathicToSingStream(Coefficient modulus, VarIndex varCount)
Definition: singmathic.cc:25
Definition: tok.h:167
const ideal
Definition: gb_hack.h:42
static FORCE_INLINE int n_GetChar(const coeffs r)
Return the characteristic of the coeff. domain.
Definition: coeffs.h:444
#define TRUE
Definition: auxiliary.h:144
void WerrorS(const char *s)
Definition: feFopen.cc:23
static number & pGetCoeff(poly p)
return an alias to the leading coefficient of p assumes that p != NULL NOTE: not copy ...
Definition: monomials.h:51
int Typ()
Definition: subexpr.cc:949
void idealBegin(size_t polyCount)
Definition: singmathic.cc:40
void * data
Definition: subexpr.h:89
ring currRing
Widely used global variable which specifies the current polynomial ring for Singular interpreter and ...
Definition: polys.cc:12
#define pGetExp(p, i)
Exponent.
Definition: polys.h:41
const ring r
Definition: syzextra.cc:208
void appendExponent(VarIndex index, Exponent exponent)
Definition: singmathic.cc:55
mgb::GroebnerConfiguration::Exponent Exponent
Definition: singmathic.cc:19
polyrec * poly
Definition: hilb.h:10
rRingOrder_t
order stuff
Definition: ring.h:660
void prOrder(ring r)
Definition: singmathic.cc:338
All the auxiliary stuff.
void idDelete(ideal *h, ring r=currRing)
delete an ideal
Definition: ideals.h:31
int dim(ideal I, ring r)
const VarIndex mVarCount
Definition: singmathic.cc:89
int i
Definition: cfEzgcd.cc:123
Induced (Schreyer) ordering.
Definition: ring.h:686
void PrintS(const char *s)
Definition: reporter.cc:294
void appendPolynomialBegin(size_t termCount)
Definition: singmathic.cc:46
S?
Definition: ring.h:668
BOOLEAN mathicgb(leftv result, leftv arg)
Definition: singmathic.cc:471
#define IDELEMS(i)
Definition: simpleideals.h:19
leftv next
Definition: subexpr.h:87
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:597
int size(const CanonicalForm &f, const Variable &v)
int size ( const CanonicalForm & f, const Variable & v )
Definition: cf_ops.cc:600
bool prOrderMatrix(ring r)
Definition: singmathic.cc:312
static BOOLEAN rField_is_Zp(const ring r)
Definition: ring.h:446
ideal idInit(int idsize, int rank)
Definition: simpleideals.cc:40
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:37
void appendTermBegin()
Definition: singmathic.cc:48
void appendTermDone(Coefficient coefficient)
Definition: singmathic.cc:59
#define NULL
Definition: omList.c:10
const Coefficient mModulus
Definition: singmathic.cc:88
Coefficient modulus() const
Definition: singmathic.cc:37
#define pInit()
allocates a new monomial and initializes everything to 0
Definition: polys.h:61
package currPack
Definition: ipid.cc:62
int rtyp
Definition: subexpr.h:92
VarIndex varCount() const
Definition: singmathic.cc:38
#define pNext(p)
Definition: monomials.h:43
void * Data()
Definition: subexpr.cc:1091
mgb::GroebnerConfiguration::BaseOrder BaseOrder
Definition: singmathic.cc:20
int exponent(const CanonicalForm &f, int q)
int exponent ( const CanonicalForm & f, int q )
mgb::GroebnerConfiguration::Coefficient Coefficient
Definition: singmathic.cc:17
void appendPolynomialDone()
Definition: singmathic.cc:64
int BOOLEAN
Definition: auxiliary.h:131
s?
Definition: ring.h:669
#define NONE
Definition: tok.h:170
::ideal takeIdeal()
Definition: singmathic.cc:74
return result
Definition: facAbsBiFact.cc:76
ListNode * next
Definition: janet.h:31