source: git/Singular/MinorInterface.cc @ 308a766

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