source: git/Singular/MinorInterface.cc @ a28cb4f

spielwiese
Last change on this file since a28cb4f was ebbb9c, checked in by Hans Schoenemann <hannes@…>, 12 years ago
fix: assign bigint = something should fail for 1x0 matrices fix: #427, bug in minor
  • Property mode set to 100644
File size: 21.5 KB
Line 
1// include before anything to avoid clashes with stdio.h included elsewhere
2#include <cstdio>
3
4#include <MinorInterface.h>
5#include <MinorProcessor.h>
6
7#include <kernel/polys.h>
8#include <kernel/structs.h>
9
10#include "config.h"
11#include <kernel/mod2.h>
12#include <kernel/ideals.h>
13#include <kernel/kstd1.h>
14
15bool currRingIsOverIntegralDomain ()
16{
17  if (rField_is_Ring_PtoM(currRing)) return false;
18  if (rField_is_Ring_2toM(currRing)) return false;
19  if (rField_is_Ring_ModN(currRing)) return false;
20  return true;
21}
22
23bool currRingIsOverField ()
24{
25  if (rField_is_Ring_PtoM(currRing)) return false;
26  if (rField_is_Ring_2toM(currRing)) return false;
27  if (rField_is_Ring_ModN(currRing)) return false;
28  if (rField_is_Ring_Z(currRing))    return false;
29  return true;
30}
31
32/* returns true iff the given polyArray has only number entries;
33   if so, the int's corresponding to these numbers will be written
34   into intArray[0..(length-1)];
35   the method assumes that both polyArray and intArray have valid
36   entries for the indices 0..(length-1);
37   after the call, zeroCounter contains the number of zero entries
38   in the matrix */
39bool arrayIsNumberArray (const poly* polyArray, const ideal iSB,
40                         const int length, int* intArray,
41                         poly* nfPolyArray, int& zeroCounter)
42{
43  int n = 0; if (currRing != 0) n = currRing->N;
44  int characteristic = 0; if (currRing != 0) characteristic = rChar(currRing);
45  zeroCounter = 0;
46  bool result = true;
47
48  for (int i = 0; i < length; i++)
49  {
50    nfPolyArray[i] = pCopy(polyArray[i]);
51    if (iSB != 0) nfPolyArray[i] = kNF(iSB, currRing->qideal, nfPolyArray[i]);
52    if (nfPolyArray[i] == NULL)
53    {
54      intArray[i] = 0;
55      zeroCounter++;
56    }
57    else
58    {
59      bool isConstant = true;
60      for (int j = 1; j <= n; j++)
61        if (pGetExp(nfPolyArray[i], j) > 0)
62          isConstant = false;
63      if (!isConstant) result = false;
64      else
65      {
66        intArray[i] = n_Int(pGetCoeff(nfPolyArray[i]), currRing->cf);
67        if (characteristic != 0) intArray[i] = intArray[i] % characteristic;
68        if (intArray[i] == 0) zeroCounter++;
69      }
70    }
71  }
72  return result;
73}
74
75/* special implementation for the case that the matrix has only number entries;
76   if i is not the zero pointer, then it is assumed to contain a std basis, and
77   the number entries of the matrix are then assumed to be reduced w.r.t. i and
78   modulo the characteristic of the gound field/ring;
79   this method should also work when currRing == null, i.e. when no ring has
80   been declared */
81ideal getMinorIdeal_Int (const int* intMatrix, const int rowCount,
82                         const int columnCount, const int minorSize,
83                         const int k, const char* algorithm,
84                         const ideal i, const bool allDifferent)
85{
86  /* setting up a MinorProcessor for matrices with integer entries: */
87  IntMinorProcessor mp;
88  mp.defineMatrix(rowCount, columnCount, intMatrix);
89  int *myRowIndices=new int[rowCount];
90  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
91  int *myColumnIndices=new int[columnCount];
92  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
93  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
94  mp.setMinorSize(minorSize);
95
96  /* containers for all upcoming results: */
97  IntMinorValue theMinor;
98  int value = 0;
99  int collectedMinors = 0;
100  int characteristic = 0; if (currRing != 0) characteristic = rChar(currRing);
101
102  /* the ideal to be returned: */
103  ideal iii = idInit(1);
104
105  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are requested,
106                                             omitting zero minors */
107  bool duplicatesOk = (allDifferent ? false : true);
108  int kk = ((k < 0) ? -k : k); /* absolute value of k */
109
110  /* looping over all minors: */
111  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
112  {
113    /* retrieving the next minor: */
114    theMinor = mp.getNextMinor(characteristic, i, algorithm);
115    poly f = NULL;
116    if (theMinor.getResult() != 0) f = pISet(theMinor.getResult());
117    if (idInsertPolyWithTests(iii, collectedMinors, f, zeroOk, duplicatesOk))
118      collectedMinors++;
119  }
120
121  /* before we return the result, let's omit zero generators
122     in iii which come after the computed minors */
123  ideal jjj;
124  if (collectedMinors == 0) jjj = idInit(1);
125  else                      jjj = idCopyFirstK(iii, collectedMinors);
126  idDelete(&iii);
127  delete[] myColumnIndices;
128  delete[] myRowIndices;
129  return jjj;
130}
131
132/* special implementation for the case that the matrix has non-number,
133   i.e., actual polynomial entries;
134   if i is not the zero pointer than it is assumed to be a std basis (ideal),
135   and the poly matrix is assumed to be already reduced w.r.t. i */
136ideal getMinorIdeal_Poly (const poly* polyMatrix, const int rowCount,
137                          const int columnCount, const int minorSize,
138                          const int k, const char* algorithm,
139                          const ideal i, const bool allDifferent)
140{
141  /* setting up a MinorProcessor for matrices with polynomial entries: */
142  PolyMinorProcessor mp;
143  mp.defineMatrix(rowCount, columnCount, polyMatrix);
144  int *myRowIndices=new int[rowCount];
145  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
146  int *myColumnIndices=new int[columnCount];
147  for (int j = 0; j < columnCount; j++) myColumnIndices[j] = j;
148  mp.defineSubMatrix(rowCount, myRowIndices, columnCount, myColumnIndices);
149  mp.setMinorSize(minorSize);
150
151  /* containers for all upcoming results: */
152  PolyMinorValue theMinor;
153  poly f = NULL;
154  int collectedMinors = 0;
155
156  /* the ideal to be returned: */
157  ideal iii = idInit(1);
158
159  bool zeroOk = ((k < 0) ? true : false); /* for k = 0, all minors are
160                                             requested, omitting zero minors */
161  bool duplicatesOk = (allDifferent ? false : true);
162  int kk = ((k < 0) ? -k : k); /* absolute value of k */
163#ifdef COUNT_AND_PRINT_OPERATIONS
164  printCounters ("starting", true);
165  int qqq = 0;
166#endif
167  /* looping over all minors: */
168  while (mp.hasNextMinor() && ((kk == 0) || (collectedMinors < kk)))
169  {
170    /* retrieving the next minor: */
171    theMinor = mp.getNextMinor(algorithm, i);
172#if (defined COUNT_AND_PRINT_OPERATIONS) && (COUNT_AND_PRINT_OPERATIONS > 1)
173    qqq++;
174    printf("after %d", qqq);
175    printCounters ("-th minor", false);
176#endif
177    f = theMinor.getResult();
178    if (idInsertPolyWithTests(iii, collectedMinors, pCopy(f),
179                              zeroOk, duplicatesOk))
180      collectedMinors++;
181  }
182#ifdef COUNT_AND_PRINT_OPERATIONS
183  printCounters ("ending", true);
184#endif
185
186  /* before we return the result, let's omit zero generators
187     in iii which come after the computed minors */
188  ideal jjj;
189  if (collectedMinors == 0) jjj = idInit(1);
190  else                      jjj = idCopyFirstK(iii, collectedMinors);
191  idDelete(&iii);
192  delete[] myColumnIndices;
193  delete[] myRowIndices;
194  return jjj;
195}
196
197ideal getMinorIdeal_toBeDone (const matrix mat, const int minorSize,
198                              const int k, const char* algorithm,
199                              const ideal i, const bool allDifferent)
200{
201  int rowCount = mat->nrows;
202  int columnCount = mat->ncols;
203  poly* myPolyMatrix = (poly*)(mat->m);
204  ideal iii; /* the ideal to be filled and returned */
205  int zz = 0;
206
207  /* divert to special implementations for pure number matrices and actual
208     polynomial matrices: */
209  int*  myIntMatrix  = new int [rowCount * columnCount];
210  poly* nfPolyMatrix = new poly[rowCount * columnCount];
211  if (arrayIsNumberArray(myPolyMatrix, i, rowCount * columnCount,
212                         myIntMatrix, nfPolyMatrix, zz))
213    iii = getMinorIdeal_Int(myIntMatrix, rowCount, columnCount, minorSize, k,
214                            algorithm, i, allDifferent);
215  else
216  {
217    if ((k == 0) && (strcmp(algorithm, "Bareiss") == 0)
218        && (!rField_is_Ring_Z(currRing)) && (!allDifferent))
219    {
220      /* In this case, we call an optimized procedure, dating back to
221         Wilfried Pohl. It may be used whenever
222         - all minors are requested,
223         - requested minors need not be mutually distinct, and
224         - coefficients come from a field (i.e., Z is also not allowed
225           for this implementation). */
226      iii = (i == 0 ? idMinors(mat, minorSize) : idMinors(mat, minorSize, i));
227    }
228    else
229    {
230      iii = getMinorIdeal_Poly(nfPolyMatrix, rowCount, columnCount, minorSize,
231                               k, algorithm, i, allDifferent);
232    }
233  }
234
235  /* clean up */
236  delete [] myIntMatrix;
237  for (int j = 0; j < rowCount * columnCount; j++) pDelete(&nfPolyMatrix[j]);
238  delete [] nfPolyMatrix;
239
240  return iii;
241}
242
243/* When called with algorithm == "Bareiss", the coefficients are assumed
244   to come from a field or from a ring which does not have zero-divisors
245   (other than 0), i.e. from an integral domain.
246   E.g. Bareiss may be used over fields or over Z but not over
247        Z/6 (which has non-zero zero divisors, namely 2 and 3). */
248ideal getMinorIdeal (const matrix mat, const int minorSize, const int k,
249                     const char* algorithm, const ideal iSB,
250                     const bool allDifferent)
251{
252  /* Note that this method should be replaced by getMinorIdeal_toBeDone,
253     to enable faster computations in the case of matrices which contain
254     only numbers. But so far, this method is not yet usable as it replaces
255     the numbers by ints which may result in overflows during computations
256     of minors. */
257  int rowCount = mat->nrows;
258  int columnCount = mat->ncols;
259  poly* myPolyMatrix = (poly*)(mat->m);
260  int length = rowCount * columnCount;
261  poly* nfPolyMatrix = new poly[length];
262  ideal iii; /* the ideal to be filled and returned */
263
264  /* copy all polynomials and reduce them w.r.t. iSB
265     (if iSB is present, i.e., not the NULL pointer) */
266  for (int i = 0; i < length; i++)
267  {
268    nfPolyMatrix[i] = pCopy(myPolyMatrix[i]);
269    if (iSB != 0) nfPolyMatrix[i] = kNF(iSB, currRing->qideal,
270                                        nfPolyMatrix[i]);
271  }
272
273  if ((k == 0) && (strcmp(algorithm, "Bareiss") == 0)
274      && (!rField_is_Ring_Z(currRing)) && (!allDifferent))
275  {
276    /* In this case, we call an optimized procedure, dating back to
277       Wilfried Pohl. It may be used whenever
278       - all minors are requested,
279       - requested minors need not be mutually distinct, and
280       - coefficients come from a field (i.e., the ring Z is not
281         allowed for this implementation). */
282    iii = (iSB == 0 ? idMinors(mat, minorSize) : idMinors(mat, minorSize,
283                                                          iSB));
284  }
285  else
286  {
287    iii = getMinorIdeal_Poly(nfPolyMatrix, rowCount, columnCount, minorSize,
288                             k, algorithm, iSB, allDifferent);
289  }
290
291  /* clean up */
292  for (int j = 0; j < length; j++) pDelete(&nfPolyMatrix[j]);
293  delete [] nfPolyMatrix;
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=new int[rowCount];
314  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
315  int *myColumnIndices=new int[columnCount];
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 = ((k < 0) ? -k : 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  delete[] myColumnIndices;
354  delete[] 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=new int[rowCount];
372  for (int j = 0; j < rowCount; j++) myRowIndices[j] = j;
373  int *myColumnIndices=new int[columnCount];
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 = ((k < 0) ? -k : 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    printf("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  delete[] myColumnIndices;
422  delete[] 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  = new int [rowCount * columnCount];
440  poly* nfPolyMatrix = new poly[rowCount * columnCount];
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  delete [] myIntMatrix;
453  for (int j = 0; j < rowCount * columnCount; j++) pDelete(&nfPolyMatrix[j]);
454  delete [] 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 = new poly[length];
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    nfPolyMatrix[i] = pCopy(myPolyMatrix[i]);
481    if (iSB != 0) nfPolyMatrix[i] = kNF(iSB, currRing->qideal,
482                                        nfPolyMatrix[i]);
483  }
484
485  iii = getMinorIdealCache_Poly(nfPolyMatrix, rowCount, columnCount,
486                                minorSize, k, iSB, cacheStrategy,
487                                cacheN, cacheW, allDifferent);
488
489  /* clean up */
490  for (int j = 0; j < length; j++) pDelete(&nfPolyMatrix[j]);
491  delete [] nfPolyMatrix;
492
493  return iii;
494}
495
496ideal getMinorIdealHeuristic (const matrix mat, const int minorSize,
497                              const int k, const ideal iSB,
498                              const bool allDifferent)
499{
500  int vars = 0; if (currRing != 0) vars = currRing->N;
501  int rowCount = mat->nrows;
502  int columnCount = mat->ncols;
503
504  /* here comes the heuristic, as of 29 January 2010:
505
506     integral domain and minorSize <= 2                -> Bareiss
507     integral domain and minorSize >= 3 and vars <= 2  -> Bareiss
508     field case and minorSize >= 3 and vars = 3
509       and c in {2, 3, ..., 32003}                     -> Bareiss
510
511     otherwise:
512     if not all minors are requested                   -> Laplace, no Caching
513     otherwise:
514     minorSize >= 3 and vars <= 4 and
515       (rowCount over minorSize)*(columnCount over minorSize) >= 100
516                                                       -> Laplace with Caching
517     minorSize >= 3 and vars >= 5 and
518       (rowCount over minorSize)*(columnCount over minorSize) >= 40
519                                                       -> Laplace with Caching
520
521     otherwise:                                        -> Laplace, no Caching
522  */
523
524  bool b = false; /* Bareiss */
525  bool l = false; /* Laplace without caching */
526  bool c = false; /* Laplace with caching */
527  if (currRingIsOverIntegralDomain())
528  { /* the field case or ring Z */
529    if      (minorSize <= 2)                                     b = true;
530    else if (vars <= 2)                                          b = true;
531    else if (currRingIsOverField() && (vars == 3)
532             && (currRing->cf->ch >= 2) && (currRing->cf->ch <= 32003))
533          b = true;
534  }
535  if (!b)
536  { /* the non-Bareiss cases */
537    if (k != 0) /* this means, not all minors are requested */   l = true;
538    else
539    { /* k == 0, i.e., all minors are requested */
540      int minorCount = 1;
541      for (int i = rowCount - minorSize + 1; i <= rowCount; i++)
542        minorCount = minorCount * i;
543      for (int i = 2; i <= minorSize; i++) minorCount = minorCount / i;
544      for (int i = columnCount - minorSize + 1; i <= columnCount; i++)
545        minorCount = minorCount * i;
546      for (int i = 2; i <= minorSize; i++) minorCount = minorCount / i;
547      /* now: minorCount =   (rowCount over minorSize)
548                           * (columnCount over minorSize) */
549      if      ((minorSize >= 3) && (vars <= 4)
550               && (minorCount >= 100))                           c = true;
551      else if ((minorSize >= 3) && (vars >= 5)
552               && (minorCount >= 40))                            c = true;
553      else                                                       l = true;
554    }
555  }
556
557  if      (b)    return getMinorIdeal(mat, minorSize, k, "Bareiss", iSB,
558                                      allDifferent);
559  else if (l)    return getMinorIdeal(mat, minorSize, k, "Laplace", iSB,
560                                      allDifferent);
561  else /* (c) */ return getMinorIdealCache(mat, minorSize, k, iSB,
562                                      3, 200, 100000, allDifferent);
563}
Note: See TracBrowser for help on using the repository browser.