source: git/kernel/linear_algebra/MinorInterface.cc @ 5cc9977

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