source: git/kernel/linear_algebra/MinorInterface.cc @ f45a05

fieker-DuValspielwiese
Last change on this file since f45a05 was f45a05, checked in by Hans Schoenemann <hannes@…>, 7 years ago
code cleanup for minor
  • Property mode set to 100644
File size: 21.2 KB
Line 
1
2
3
4#include <kernel/mod2.h>
5
6// include before anything to avoid clashes with stdio.h included elsewhere
7// #include <cstdio>
8
9#include <kernel/linear_algebra/MinorInterface.h>
10#include <kernel/linear_algebra/MinorProcessor.h>
11
12#include <polys/simpleideals.h>
13#include <coeffs/modulop.h> // for NV_MAX_PRIME
14
15#include <kernel/polys.h>
16#include <kernel/structs.h>
17#include <kernel/GBEngine/kstd1.h>
18#include <kernel/ideals.h>
19
20using namespace std;
21
22static inline bool currRingIsOverIntegralDomain ()
23{
24  return rField_is_Domain(currRing);
25}
26
27bool currRingIsOverField ()
28{
29  if (rField_is_Ring_PtoM(currRing)) return false;
30  if (rField_is_Ring_2toM(currRing)) return false;
31  if (rField_is_Ring_ModN(currRing)) return false;
32  if (rField_is_Ring_Z(currRing))    return false;
33  return true;
34}
35
36/* returns true iff the given polyArray has only number entries;
37   if so, the int's corresponding to these numbers will be written
38   into intArray[0..(length-1)];
39   the method assumes that both polyArray and intArray have valid
40   entries for the indices 0..(length-1);
41   after the call, zeroCounter contains the number of zero entries
42   in the matrix */
43bool arrayIsNumberArray (const poly* polyArray, const ideal iSB,
44                         const int length, int* intArray,
45                         poly* nfPolyArray, int& zeroCounter)
46{
47  int n = 0; if (currRing != 0) n = currRing->N;
48  int characteristic = 0; if (currRing != 0) characteristic = rChar(currRing);
49  zeroCounter = 0;
50  bool result = true;
51
52  for (int i = 0; i < length; i++)
53  {
54    nfPolyArray[i] = pCopy(polyArray[i]);
55    if (iSB != 0) nfPolyArray[i] = kNF(iSB, currRing->qideal, nfPolyArray[i]);
56    if (nfPolyArray[i] == NULL)
57    {
58      intArray[i] = 0;
59      zeroCounter++;
60    }
61    else
62    {
63      bool isConstant = true;
64      for (int j = 1; j <= n; j++)
65        if (pGetExp(nfPolyArray[i], j) > 0)
66          isConstant = false;
67      if (!isConstant) result = false;
68      else
69      {
70        intArray[i] = n_Int(pGetCoeff(nfPolyArray[i]), currRing->cf);
71        if (characteristic != 0) intArray[i] = intArray[i] % characteristic;
72        if (intArray[i] == 0) zeroCounter++;
73      }
74    }
75  }
76  return result;
77}
78
79/* special implementation for the case that the matrix has only number entries;
80   if i is not the zero pointer, then it is assumed to contain a std basis, and
81   the number entries of the matrix are then assumed to be reduced w.r.t. i and
82   modulo the characteristic of the gound field/ring;
83   this method should also work when currRing == null, i.e. when no ring has
84   been declared */
85ideal getMinorIdeal_Int (const int* intMatrix, const int rowCount,
86                         const int columnCount, const int minorSize,
87                         const int k, const char* algorithm,
88                         const ideal i, const bool allDifferent)
89{
90  /* setting up a MinorProcessor for matrices with integer entries: */
91  IntMinorProcessor mp;
92  mp.defineMatrix(rowCount, columnCount, intMatrix);
93  int *myRowIndices=new int[rowCount];
94  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
95  int *myColumnIndices=new int[columnCount];
96  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
97  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
98  mp.setMinorSize(minorSize);
99
100  /* containers for all upcoming results: */
101  IntMinorValue theMinor;
102  // int value = 0;
103  int collectedMinors = 0;
104  int characteristic = 0; if (currRing != 0) characteristic = rChar(currRing);
105
106  /* the ideal to be returned: */
107  ideal iii = idInit(1);
108
109  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are requested,
110                                             omitting zero minors */
111  bool duplicatesOk = (allDifferent ? false : true);
112  int kk = ((k < 0) ? -k : k); /* absolute value of k */
113
114  /* looping over all minors: */
115  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
116  {
117    /* retrieving the next minor: */
118    theMinor = mp.getNextMinor(characteristic, i, algorithm);
119    poly f = NULL;
120    if (theMinor.getResult() != 0) f = pISet(theMinor.getResult());
121    if (idInsertPolyWithTests(iii, collectedMinors, f, zeroOk, duplicatesOk))
122      collectedMinors++;
123  }
124
125  /* before we return the result, let's omit zero generators
126     in iii which come after the computed minors */
127  ideal jjj;
128  if (collectedMinors == 0) jjj = idInit(1);
129  else                      jjj = idCopyFirstK(iii, collectedMinors);
130  idDelete(&iii);
131  delete[] myColumnIndices;
132  delete[] myRowIndices;
133  return jjj;
134}
135
136/* special implementation for the case that the matrix has non-number,
137   i.e., actual polynomial entries;
138   if i is not the zero pointer than it is assumed to be a std basis (ideal),
139   and the poly matrix is assumed to be already reduced w.r.t. i */
140ideal getMinorIdeal_Poly (const poly* polyMatrix, const int rowCount,
141                          const int columnCount, const int minorSize,
142                          const int k, const char* algorithm,
143                          const ideal i, const bool allDifferent)
144{
145  /* setting up a MinorProcessor for matrices with polynomial entries: */
146  PolyMinorProcessor mp;
147  mp.defineMatrix(rowCount, columnCount, polyMatrix);
148  int *myRowIndices=new int[rowCount];
149  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
150  int *myColumnIndices=new int[columnCount];
151  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
152  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
153  mp.setMinorSize(minorSize);
154
155  /* containers for all upcoming results: */
156  PolyMinorValue theMinor;
157  poly f = NULL;
158  int collectedMinors = 0;
159
160  /* the ideal to be returned: */
161  ideal iii = idInit(1);
162
163  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are
164                                             requested, omitting zero minors */
165  bool duplicatesOk = (allDifferent ? false : true);
166  int kk = ((k < 0) ? -k : k); /* absolute value of k */
167#ifdef COUNT_AND_PRINT_OPERATIONS
168  printCounters ("starting", true);
169  int qqq = 0;
170#endif
171  /* looping over all minors: */
172  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
173  {
174    /* retrieving the next minor: */
175    theMinor = mp.getNextMinor(algorithm, i);
176#if (defined COUNT_AND_PRINT_OPERATIONS) && (COUNT_AND_PRINT_OPERATIONS > 1)
177    qqq++;
178    Print("after %d", qqq);
179    printCounters ("-th minor", false);
180#endif
181    f = theMinor.getResult();
182    if (idInsertPolyWithTests(iii, collectedMinors, pCopy(f),
183                              zeroOk, duplicatesOk))
184      collectedMinors++;
185  }
186#ifdef COUNT_AND_PRINT_OPERATIONS
187  printCounters ("ending", true);
188#endif
189
190  /* before we return the result, let's omit zero generators
191     in iii which come after the computed minors */
192  idKeepFirstK(iii, collectedMinors);
193  delete[] myColumnIndices;
194  delete[] myRowIndices;
195  return(iii);
196}
197
198ideal getMinorIdeal_toBeDone (const matrix mat, const int minorSize,
199                              const int k, const char* algorithm,
200                              const ideal i, const bool allDifferent)
201{
202  int rowCount = mat->nrows;
203  int columnCount = mat->ncols;
204  poly* myPolyMatrix = (poly*)(mat->m);
205  ideal iii; /* the ideal to be filled and returned */
206  int zz = 0;
207
208  /* divert to special implementations for pure number matrices and actual
209     polynomial matrices: */
210  int*  myIntMatrix  = new int [rowCount * columnCount];
211  poly* nfPolyMatrix = new poly[rowCount * columnCount];
212  if (arrayIsNumberArray(myPolyMatrix, i, rowCount * columnCount,
213                         myIntMatrix, nfPolyMatrix, zz))
214    iii = getMinorIdeal_Int(myIntMatrix, rowCount, columnCount, minorSize, k,
215                            algorithm, i, allDifferent);
216  else
217  {
218    if ((k == 0) && (strcmp(algorithm, "Bareiss") == 0)
219        && (!rField_is_Ring_Z(currRing)) && (!allDifferent))
220    {
221      /* In this case, we call an optimized procedure, dating back to
222         Wilfried Pohl. It may be used whenever
223         - all minors are requested,
224         - requested minors need not be mutually distinct, and
225         - coefficients come from a field (i.e., Z is also not allowed
226           for this implementation). */
227      iii = (i == 0 ? idMinors(mat, minorSize) : idMinors(mat, minorSize, i));
228    }
229    else
230    {
231      iii = getMinorIdeal_Poly(nfPolyMatrix, rowCount, columnCount, minorSize,
232                               k, algorithm, i, allDifferent);
233    }
234  }
235
236  /* clean up */
237  delete [] myIntMatrix;
238  for (int j = 0; j < rowCount * columnCount; j++) pDelete(&nfPolyMatrix[j]);
239  delete [] nfPolyMatrix;
240
241  return iii;
242}
243
244/* When called with algorithm == "Bareiss", the coefficients are assumed
245   to come from a field or from a ring which does not have zero-divisors
246   (other than 0), i.e. from an integral domain.
247   E.g. Bareiss may be used over fields or over Z but not over
248        Z/6 (which has non-zero zero divisors, namely 2 and 3). */
249ideal getMinorIdeal (const matrix mat, const int minorSize, const int k,
250                     const char* algorithm, const ideal iSB,
251                     const bool allDifferent)
252{
253  /* Note that this method should be replaced by getMinorIdeal_toBeDone,
254     to enable faster computations in the case of matrices which contain
255     only numbers. But so far, this method is not yet usable as it replaces
256     the numbers by ints which may result in overflows during computations
257     of minors. */
258  int rowCount = mat->nrows;
259  int columnCount = mat->ncols;
260  poly* myPolyMatrix = (poly*)(mat->m);
261  int length = rowCount * columnCount;
262  ideal iii; /* the ideal to be filled and returned */
263
264  if ((k == 0) && (strcmp(algorithm, "Bareiss") == 0)
265      && (!rField_is_Ring(currRing)) && (!allDifferent))
266  {
267    /* In this case, we call an optimized procedure, dating back to
268       Wilfried Pohl. It may be used whenever
269       - all minors are requested,
270       - requested minors need not be mutually distinct, and
271       - coefficients come from a field (i.e., the ring Z is not
272         allowed for this implementation). */
273    iii = (iSB == NULL ? idMinors(mat, minorSize) : idMinors(mat, minorSize,
274                                                          iSB));
275  }
276  else
277  {
278  /* copy all polynomials and reduce them w.r.t. iSB
279     (if iSB is present, i.e., not the NULL pointer) */
280
281    poly* nfPolyMatrix = new poly[length];
282    if (iSB != NULL)
283    {
284      for (int i = 0; i < length; i++)
285      {
286        nfPolyMatrix[i] = kNF(iSB, currRing->qideal,myPolyMatrix[i]);
287      }
288    }
289    else
290    {
291      for (int i = 0; i < length; i++)
292      {
293        nfPolyMatrix[i] = pCopy(myPolyMatrix[i]);
294      }
295    }
296    iii = getMinorIdeal_Poly(nfPolyMatrix, rowCount, columnCount, minorSize,
297                             k, algorithm, iSB, allDifferent);
298
299    /* clean up */
300    for (int j = length-1; j>=0; j--) pDelete(&nfPolyMatrix[j]);
301    delete [] nfPolyMatrix;
302  }
303
304  return iii;
305}
306
307/* special implementation for the case that the matrix has only number entries;
308   if i is not the zero pointer, then it is assumed to contain a std basis, and
309   the number entries of the matrix are then assumed to be reduced w.r.t. i and
310   modulo the characteristic of the gound field/ring;
311   this method should also work when currRing == null, i.e. when no ring has
312   been declared */
313ideal getMinorIdealCache_Int(const int* intMatrix, const int rowCount,
314                             const int columnCount, const int minorSize,
315                             const int k, const ideal i,
316                             const int cacheStrategy, const int cacheN,
317                             const int cacheW, const bool allDifferent)
318{
319  /* setting up a MinorProcessor for matrices with integer entries: */
320  IntMinorProcessor mp;
321  mp.defineMatrix(rowCount, columnCount, intMatrix);
322  int *myRowIndices=new int[rowCount];
323  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
324  int *myColumnIndices=new int[columnCount];
325  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
326  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
327  mp.setMinorSize(minorSize);
328  MinorValue::SetRankingStrategy(cacheStrategy);
329  Cache<MinorKey, IntMinorValue> cch(cacheN, cacheW);
330
331  /* containers for all upcoming results: */
332  IntMinorValue theMinor;
333  // int value = 0;
334  int collectedMinors = 0;
335  int characteristic = 0; if (currRing != 0) characteristic = rChar(currRing);
336
337  /* the ideal to be returned: */
338  ideal iii = idInit(1);
339
340  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are
341                                             requested, omitting zero minors */
342  bool duplicatesOk = (allDifferent ? false : true);
343  int kk = ((k < 0) ? -k : k); /* absolute value of k */
344
345  /* looping over all minors: */
346  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
347  {
348    /* retrieving the next minor: */
349    theMinor = mp.getNextMinor(cch, characteristic, i);
350    poly f = NULL;
351    if (theMinor.getResult() != 0) f = pISet(theMinor.getResult());
352    if (idInsertPolyWithTests(iii, collectedMinors, f, zeroOk, duplicatesOk))
353      collectedMinors++;
354  }
355
356  /* before we return the result, let's omit zero generators
357     in iii which come after the computed minors */
358  ideal jjj;
359  if (collectedMinors == 0) jjj = idInit(1);
360  else                      jjj = idCopyFirstK(iii, collectedMinors);
361  idDelete(&iii);
362  delete[] myColumnIndices;
363  delete[] myRowIndices;
364  return jjj;
365}
366
367/* special implementation for the case that the matrix has non-number,
368   i.e. real poly entries;
369   if i is not the zero pointer, then it is assumed to contain a std basis,
370   and the entries of the matrix are then assumed to be reduced w.r.t. i */
371ideal getMinorIdealCache_Poly(const poly* polyMatrix, const int rowCount,
372                              const int columnCount, const int minorSize,
373                              const int k, const ideal i,
374                              const int cacheStrategy, const int cacheN,
375                              const int cacheW, const bool allDifferent)
376{
377  /* setting up a MinorProcessor for matrices with polynomial entries: */
378  PolyMinorProcessor mp;
379  mp.defineMatrix(rowCount, columnCount, polyMatrix);
380  int *myRowIndices=new int[rowCount];
381  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
382  int *myColumnIndices=new int[columnCount];
383  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
384  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
385  mp.setMinorSize(minorSize);
386  MinorValue::SetRankingStrategy(cacheStrategy);
387  Cache<MinorKey, PolyMinorValue> cch(cacheN, cacheW);
388
389  /* containers for all upcoming results: */
390  PolyMinorValue theMinor;
391  poly f = NULL;
392  int collectedMinors = 0;
393
394  /* the ideal to be returned: */
395  ideal iii = idInit(1);
396
397  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are
398                                             requested, omitting zero minors */
399  bool duplicatesOk = (allDifferent ? false : true);
400  int kk = ((k < 0) ? -k : k); /* absolute value of k */
401#ifdef COUNT_AND_PRINT_OPERATIONS
402  printCounters ("starting", true);
403  int qqq = 0;
404#endif
405  /* looping over all minors: */
406  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
407  {
408    /* retrieving the next minor: */
409    theMinor = mp.getNextMinor(cch, i);
410#if (defined COUNT_AND_PRINT_OPERATIONS) && (COUNT_AND_PRINT_OPERATIONS > 1)
411    qqq++;
412    Print("after %d", qqq);
413    printCounters ("-th minor", false);
414#endif
415    f = theMinor.getResult();
416    if (idInsertPolyWithTests(iii, collectedMinors, pCopy(f), zeroOk,
417                              duplicatesOk))
418      collectedMinors++;
419  }
420#ifdef COUNT_AND_PRINT_OPERATIONS
421  printCounters ("ending", true);
422#endif
423
424  /* before we return the result, let's omit zero generators
425     in iii which come after the computed minors */
426  ideal jjj;
427  if (collectedMinors == 0) jjj = idInit(1);
428  else                      jjj = idCopyFirstK(iii, collectedMinors);
429  idDelete(&iii);
430  delete[] myColumnIndices;
431  delete[] myRowIndices;
432  return jjj;
433}
434
435ideal getMinorIdealCache_toBeDone (const matrix mat, const int minorSize,
436                                   const int k, const ideal iSB,
437                                   const int cacheStrategy, const int cacheN,
438                                   const int cacheW, const bool allDifferent)
439{
440  int rowCount = mat->nrows;
441  int columnCount = mat->ncols;
442  poly* myPolyMatrix = (poly*)(mat->m);
443  ideal iii; /* the ideal to be filled and returned */
444  int zz = 0;
445
446  /* divert to special implementation when myPolyMatrix has only number
447     entries: */
448  int*  myIntMatrix  = new int [rowCount * columnCount];
449  poly* nfPolyMatrix = new poly[rowCount * columnCount];
450  if (arrayIsNumberArray(myPolyMatrix, iSB, rowCount * columnCount,
451                         myIntMatrix, nfPolyMatrix, zz))
452    iii = getMinorIdealCache_Int(myIntMatrix, rowCount, columnCount,
453                                 minorSize, k, iSB, cacheStrategy, cacheN,
454                                 cacheW, allDifferent);
455  else
456    iii = getMinorIdealCache_Poly(nfPolyMatrix, rowCount, columnCount,
457                                  minorSize, k, iSB, cacheStrategy, cacheN,
458                                  cacheW, allDifferent);
459
460  /* clean up */
461  delete [] myIntMatrix;
462  for (int j = 0; j < rowCount * columnCount; j++) pDelete(&nfPolyMatrix[j]);
463  delete [] nfPolyMatrix;
464
465  return iii;
466}
467
468ideal getMinorIdealCache (const matrix mat, const int minorSize, const int k,
469                          const ideal iSB, const int cacheStrategy,
470                          const int cacheN, const int cacheW,
471                          const bool allDifferent)
472{
473  /* Note that this method should be replaced by getMinorIdealCache_toBeDone,
474     to enable faster computations in the case of matrices which contain
475     only numbers. But so far, this method is not yet usable as it replaces
476     the numbers by ints which may result in overflows during computations
477     of minors. */
478  int rowCount = mat->nrows;
479  int columnCount = mat->ncols;
480  poly* myPolyMatrix = (poly*)(mat->m);
481  int length = rowCount * columnCount;
482  poly* nfPolyMatrix = new poly[length];
483  ideal iii; /* the ideal to be filled and returned */
484
485  /* copy all polynomials and reduce them w.r.t. iSB
486     (if iSB is present, i.e., not the NULL pointer) */
487  for (int i = 0; i < length; i++)
488  {
489    nfPolyMatrix[i] = pCopy(myPolyMatrix[i]);
490    if (iSB != 0) nfPolyMatrix[i] = kNF(iSB, currRing->qideal,
491                                        nfPolyMatrix[i]);
492  }
493
494  iii = getMinorIdealCache_Poly(nfPolyMatrix, rowCount, columnCount,
495                                minorSize, k, iSB, cacheStrategy,
496                                cacheN, cacheW, allDifferent);
497
498  /* clean up */
499  for (int j = 0; j < length; j++) pDelete(&nfPolyMatrix[j]);
500  delete [] nfPolyMatrix;
501
502  return iii;
503}
504
505ideal getMinorIdealHeuristic (const matrix mat, const int minorSize,
506                              const int k, const ideal iSB,
507                              const bool allDifferent)
508{
509  int vars = 0; if (currRing != 0) vars = currRing->N;
510  int rowCount = mat->nrows;
511  int columnCount = mat->ncols;
512
513  /* here comes the heuristic, as of 29 January 2010:
514
515     integral domain and minorSize <= 2                -> Bareiss
516     integral domain and minorSize >= 3 and vars <= 2  -> Bareiss
517     field case and minorSize >= 3 and vars = 3
518       and c in {2, 3, ..., 32749}                     -> Bareiss
519
520     otherwise:
521     if not all minors are requested                   -> Laplace, no Caching
522     otherwise:
523     minorSize >= 3 and vars <= 4 and
524       (rowCount over minorSize)*(columnCount over minorSize) >= 100
525                                                       -> Laplace with Caching
526     minorSize >= 3 and vars >= 5 and
527       (rowCount over minorSize)*(columnCount over minorSize) >= 40
528                                                       -> Laplace with Caching
529
530     otherwise:                                        -> Laplace, no Caching
531  */
532
533  bool b = false; /* Bareiss */
534  bool l = false; /* Laplace without caching */
535  // bool c = false; /* Laplace with caching */
536  if (currRingIsOverIntegralDomain())
537  { /* the field case or ring Z */
538    if      (minorSize <= 2)                                     b = true;
539    else if (vars <= 2)                                          b = true;
540    else if (currRingIsOverField() && (vars == 3)
541             && (currRing->cf->ch >= 2) && (currRing->cf->ch <= NV_MAX_PRIME))
542          b = true;
543  }
544  if (!b)
545  { /* the non-Bareiss cases */
546    if (k != 0) /* this means, not all minors are requested */   l = true;
547    else
548    { /* k == 0, i.e., all minors are requested */
549      int minorCount = binom(rowCount, minorSize);
550      minorCount *= binom(columnCount, minorSize);
551      // if      ((minorSize >= 3) && (vars <= 4)
552      //          && (minorCount >= 100))                           c = true;
553      // else if ((minorSize >= 3) && (vars >= 5)
554      //          && (minorCount >= 40))                            c = true;
555      /*else*/                                                      l = true;
556    }
557  }
558
559  if      (b)    return getMinorIdeal(mat, minorSize, k, "Bareiss", iSB,
560                                      allDifferent);
561  else if (l)    return getMinorIdeal(mat, minorSize, k, "Laplace", iSB,
562                                      allDifferent);
563  else /* (c) */ return getMinorIdealCache(mat, minorSize, k, iSB,
564                                      3, 200, 100000, allDifferent);
565}
Note: See TracBrowser for help on using the repository browser.