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

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