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

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