source: git/Singular/dyn_modules/freealgebra/freealgebra.cc @ 7161aca

spielwiese
Last change on this file since 7161aca was 7161aca, checked in by Karim Abou Zeid <karim23697@…>, 4 years ago
Merge branch 'spielwiese' into stable
  • Property mode set to 100644
File size: 9.9 KB
Line 
1#include "Singular/libsingular.h"
2#include <vector>
3
4#ifdef HAVE_SHIFTBBA
5static BOOLEAN freeAlgebra(leftv res, leftv args)
6{
7  const short t1[]={2,RING_CMD,INT_CMD};
8  const short t2[]={3,RING_CMD,INT_CMD,INT_CMD};
9  if (iiCheckTypes(args, t2, 0) || iiCheckTypes(args, t1, 1))
10  {
11    ring r=(ring)args->Data();
12    int d=(int)(long)args->next->Data();
13    if (d<2)
14    {
15      WerrorS("degree must be >=2");
16      return TRUE;
17    }
18    int i=0;
19    while(r->order[i]!=0)
20    {
21      if ((r->order[i]==ringorder_c) ||(r->order[i]==ringorder_C)) i++;
22      else if ((r->block0[i]==1)&&(r->block1[i]==r->N)) i++;
23      else
24      {
25        WerrorS("only for rings with a global ordering of one block");
26        return TRUE;
27      }
28    }
29    if ((r->order[i]!=0)
30    || (rHasLocalOrMixedOrdering(r)))
31    {
32      WerrorS("only for rings with a global ordering of one block");
33      //Werror("only for rings with a global ordering of one block,i=%d, o=%d",i,r->order[i]);
34      return TRUE;
35    }
36    int ncGenCount = 0; 
37    if (iiCheckTypes(args,t2,0))
38      ncGenCount = (int)(long) args->next->next->Data();
39    ring R=freeAlgebra(r,d,ncGenCount);
40    res->rtyp=RING_CMD;
41    res->data=R;
42    return R==NULL;
43  }
44  return TRUE;
45}
46
47static BOOLEAN stest(leftv res, leftv args)
48{
49  const short t[]={2,POLY_CMD,INT_CMD};
50  if (iiCheckTypes(args,t,1))
51  {
52    poly p=(poly)args->CopyD();
53    args=args->next;
54    int sh=(int)((long)(args->Data()));
55    if (sh<0)
56    {
57      WerrorS("negative shift for pLPshift");
58      return TRUE;
59    }
60    int L = pLastVblock(p);
61    if (L+sh > currRing->N/currRing->isLPring)
62    {
63      WerrorS("pLPshift: too big shift requested\n");
64      return TRUE;
65    }
66    p_LPshift(p,sh,currRing);
67    res->data = p;
68    res->rtyp = POLY_CMD;
69    return FALSE;
70  }
71  else return TRUE;
72}
73
74static BOOLEAN btest(leftv res, leftv h)
75{
76  const short t[]={1,POLY_CMD};
77  if (iiCheckTypes(h,t,1))
78  {
79    poly p=(poly)h->Data();
80    res->rtyp = INT_CMD;
81    res->data = (void*)(long)pLastVblock(p);
82    return FALSE;
83  }
84  else return TRUE;
85}
86
87static BOOLEAN p_LPDivisibleBy(ideal I, poly p, ring r)
88{
89  for(int i = 0; i < IDELEMS(I); i++)
90  {
91    if (p_LPDivisibleBy(I->m[i], p, r))
92    {
93      return TRUE;
94    }
95  }
96  return FALSE;
97}
98
99static BOOLEAN lpLmDivides(leftv res, leftv h)
100{
101  const short t1[]={2,POLY_CMD,POLY_CMD};
102  const short t2[]={2,IDEAL_CMD,POLY_CMD};
103  if (iiCheckTypes(h,t1,0))
104  {
105    poly p=(poly)h->Data();
106    poly q=(poly)h->next->Data();
107    res->rtyp = INT_CMD;
108    res->data = (void*)(long)p_LPDivisibleBy(p, q, currRing);
109    return FALSE;
110  }
111  else if (iiCheckTypes(h,t2,1))
112  {
113    ideal I=(ideal)h->Data();
114    poly q=(poly)h->next->Data();
115    res->rtyp = INT_CMD;
116    res->data=(void*)(long) p_LPDivisibleBy(I, q, currRing);
117    return FALSE;
118  }
119  else return TRUE;
120}
121
122static BOOLEAN lpVarAt(leftv res, leftv h)
123{
124  const short t[]={2,POLY_CMD,INT_CMD};
125  if (iiCheckTypes(h,t,1))
126  {
127    poly p=(poly)h->Data();
128    int pos=(int)((long)(h->next->Data()));
129    res->rtyp = POLY_CMD;
130    res->data = p_LPVarAt(p, pos, currRing);
131    return FALSE;
132  }
133  else return TRUE;
134}
135
136static void _computeStandardWords(ideal words, int n, ideal M, int& last)
137{
138  if (n <= 0){
139    words->m[0] = pOne();
140    last = 0;
141    return;
142  }
143
144  _computeStandardWords(words, n - 1, M, last);
145
146  int nVars = currRing->isLPring;
147
148  for (int j = nVars - 1; j >= 0; j--)
149  {
150    for (int i = last; i >= 0; i--)
151    {
152      int index = (j * (last + 1)) + i;
153
154      if (words->m[i] != NULL)
155      {
156        if (j > 0) {
157          words->m[index] = pCopy(words->m[i]);
158        }
159
160        int varOffset = ((n - 1) * nVars) + 1;
161        pSetExp(words->m[index], varOffset + j, 1);
162        pSetm(words->m[index]);
163        pTest(words->m[index]);
164
165        if (p_LPDivisibleBy(M, words->m[index], currRing))
166        {
167          pDelete(&words->m[index]);
168          words->m[index] = NULL;
169        }
170      }
171    }
172  }
173
174  last = nVars * last + nVars - 1;
175}
176
177static ideal computeStandardWords(int n, ideal M)
178{
179  int nVars = currRing->isLPring;
180
181  int maxElems = 1;
182  for (int i = 0; i < n; i++) // maxElems = nVars^n
183    maxElems *= nVars;
184  ideal words = idInit(maxElems);
185  int last;
186  _computeStandardWords(words, n, M, last);
187  idSkipZeroes(words);
188  return words;
189}
190
191// NULL if graph is undefined
192static intvec* ufnarovskiGraph(ideal G)
193{
194  long l = 0;
195  for (int i = 0; i < IDELEMS(G); i++)
196    l = si_max(pTotaldegree(G->m[i]), l);
197  l--;
198  if (l <= 0)
199  {
200    WerrorS("Ufnarovski graph not implemented for l <= 0");
201    return NULL;
202  }
203  int lV = currRing->isLPring;
204
205  ideal standardWords = computeStandardWords(l, G);
206
207  int n = IDELEMS(standardWords);
208  intvec* UG = new intvec(n, n, 0);
209  for (int i = 0; i < n; i++)
210  {
211    for (int j = 0; j < n; j++)
212    {
213      poly v = standardWords->m[i];
214      poly w = standardWords->m[j];
215
216      // check whether v*x1 = x2*w (overlap)
217      bool overlap = true;
218      for (int k = 1; k <= (l - 1) * lV; k++)
219      {
220        if (pGetExp(v, k + lV) != pGetExp(w, k)) {
221          overlap = false;
222          break;
223        }
224      }
225
226      if (overlap)
227      {
228        // create the overlap
229        poly p = pMult(pCopy(v), p_LPVarAt(w, l, currRing));
230
231        // check whether the overlap is normal
232        bool normal = true;
233        for (int k = 0; k < IDELEMS(G); k++)
234        {
235          if (p_LPDivisibleBy(G->m[k], p, currRing))
236          {
237            normal = false;
238            break;
239          }
240        }
241
242        if (normal)
243        {
244          IMATELEM(*UG, i + 1, j + 1) = 1;
245        }
246      }
247    }
248  }
249  return UG;
250}
251
252static std::vector<int> countCycles(const intvec* _G, int v, std::vector<int> path, std::vector<BOOLEAN> visited, std::vector<BOOLEAN> cyclic, std::vector<int> cache)
253{
254  intvec* G = ivCopy(_G); // modifications must be local
255
256  if (cache[v] != -2) return cache; // value is already cached
257
258  visited[v] = TRUE;
259  path.push_back(v);
260
261  int cycles = 0;
262  for (int w = 0; w < G->cols(); w++)
263  {
264    if (IMATELEM(*G, v + 1, w + 1)) // edge v -> w exists in G
265    {
266      if (!visited[w])
267      { // continue with w
268        cache = countCycles(G, w, path, visited, cyclic, cache);
269        if (cache[w] == -1)
270        {
271          cache[v] = -1;
272          return cache;
273        }
274        cycles = si_max(cycles, cache[w]);
275      }
276      else
277      { // found new cycle
278        int pathIndexOfW = -1;
279        for (int i = path.size() - 1; i >= 0; i--) {
280          if (cyclic[path[i]] == 1) { // found an already cyclic vertex
281            cache[v] = -1;
282            return cache;
283          }
284          cyclic[path[i]] = TRUE;
285
286          if (path[i] == w) { // end of the cycle
287            assume(IMATELEM(*G, v + 1, w + 1) != 0);
288            IMATELEM(*G, v + 1, w + 1) = 0; // remove edge v -> w
289            pathIndexOfW = i;
290            break;
291          } else {
292            assume(IMATELEM(*G, path[i - 1] + 1, path[i] + 1) != 0);
293            IMATELEM(*G, path[i - 1] + 1, path[i] + 1) = 0; // remove edge vi-1 -> vi
294          }
295        }
296        assume(pathIndexOfW != -1); // should never happen
297        for (int i = path.size() - 1; i >= pathIndexOfW; i--) {
298          cache = countCycles(G, path[i], path, visited, cyclic, cache);
299          if (cache[path[i]] == -1)
300          {
301            cache[v] = -1;
302            return cache;
303          }
304          cycles = si_max(cycles, cache[path[i]] + 1);
305        }
306      }
307    }
308  }
309  cache[v] = cycles;
310
311  delete G;
312  return cache;
313}
314
315// -1 is infinity
316static int graphGrowth(const intvec* G)
317{
318  // init
319  int n = G->cols();
320  std::vector<int> path;
321  std::vector<BOOLEAN> visited;
322  std::vector<BOOLEAN> cyclic;
323  std::vector<int> cache;
324  visited.resize(n, FALSE);
325  cyclic.resize(n, FALSE);
326  cache.resize(n, -2);
327
328  // get max number of cycles
329  int cycles = 0;
330  for (int v = 0; v < n; v++)
331  {
332    cache = countCycles(G, v, path, visited, cyclic, cache);
333    if (cache[v] == -1)
334      return -1;
335    cycles = si_max(cycles, cache[v]);
336  }
337  return cycles;
338}
339
340// -1 is infinity, -2 is error
341static int gkDim(const ideal _G)
342{
343  if (rField_is_Ring(currRing)) {
344      WerrorS("GK-Dim not implemented for rings");
345      return -2;
346  }
347
348  for (int i=IDELEMS(_G)-1;i>=0; i--)
349  {
350    if (pGetComp(_G->m[i]) != 0)
351    {
352      WerrorS("GK-Dim not implemented for modules");
353      return -2;
354    }
355  }
356
357  ideal G = id_Head(_G, currRing); // G = LM(G) (and copy)
358  idSkipZeroes(G); // remove zeros
359  id_DelLmEquals(G, currRing); // remove duplicates
360
361  // get the max deg
362  long maxDeg = 0;
363  for (int i = 0; i < IDELEMS(G); i++)
364  {
365    maxDeg = si_max(maxDeg, pTotaldegree(G->m[i]));
366
367    // also check whether G = <1>
368    if (pIsConstantComp(G->m[i]))
369    {
370      WerrorS("GK-Dim not defined for 0-ring");
371      return -2;
372    }
373  }
374
375  // early termination if G \subset X
376  if (maxDeg <= 1)
377  {
378    int lV = currRing->isLPring;
379    if (IDELEMS(G) == lV) // V = {1} no edges
380      return 0;
381    if (IDELEMS(G) == lV - 1) // V = {1} with loop
382      return 1;
383    if (IDELEMS(G) <= lV - 2) // V = {1} with more than one loop
384      return -1;
385  }
386
387  intvec* UG = ufnarovskiGraph(G);
388  if (errorreported || UG == NULL) return -2;
389  return graphGrowth(UG);
390}
391
392
393static BOOLEAN lpGkDim(leftv res, leftv h)
394{
395  const short t[]={1,IDEAL_CMD};
396  if (iiCheckTypes(h,t,1))
397  {
398    assumeStdFlag(h);
399    ideal G = (ideal) h->Data();
400    res->rtyp = INT_CMD;
401    res->data = (void*)(long) gkDim(G);
402    if (errorreported) return TRUE;
403    return FALSE;
404  }
405  else return TRUE;
406}
407#endif
408
409//------------------------------------------------------------------------
410// initialisation of the module
411extern "C" int SI_MOD_INIT(freealgebra)(SModulFunctions* p)
412{
413#ifdef HAVE_SHIFTBBA
414  p->iiAddCproc("freealgebra.so","freeAlgebra",FALSE,freeAlgebra);
415  p->iiAddCproc("freealgebra.so","lpLmDivides",FALSE,lpLmDivides);
416  p->iiAddCproc("freealgebra.so","lpVarAt",FALSE,lpVarAt);
417  p->iiAddCproc("freealgebra.so","lpGkDim",FALSE,lpGkDim);
418
419  p->iiAddCproc("freealgebra.so","stest",TRUE,stest);
420  p->iiAddCproc("freealgebra.so","btest",TRUE,btest);
421#endif
422  return (MAX_TOK);
423}
Note: See TracBrowser for help on using the repository browser.