source: git/Singular/MinorInterface.cc @ f24b9c

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