source: git/Singular/LIB/fpadim.lib @ 1bf4c54

spielwiese
Last change on this file since 1bf4c54 was 1bf4c54, checked in by Karim Abou Zeid <karim23697@…>, 6 years ago
Fix prime/semi-prime for a special case
  • Property mode set to 100644
File size: 113.0 KB
Line 
1///////////////////////////////////////////////////////
2version="$Id$";
3category="Noncommutative";
4info="
5LIBRARY: fpadim.lib     Algorithms for quotient algebras in the letterplace case
6AUTHORS: Grischa Studzinski,       grischa.studzinski@rwth-aachen.de
7@*       Viktor Levandovskyy,      viktor.levandovskyy@math.rwth-aachen.de
8@*       Karim Abou Zeid,          karim.abou.zeid@rwth-aachen.de
9
10Support: Joint projects LE 2697/2-1 and KR 1907/3-1 of the Priority Programme SPP 1489:
11@* 'Algorithmische und Experimentelle Methoden in Algebra, Geometrie und Zahlentheorie'
12@* of the German DFG
13
14OVERVIEW: Given the free algebra A = K<x_1,...,x_n> and a (finite) Groebner basis
15@*      GB = {g_1,..,g_w}, one is interested in the K-dimension and in the
16@*      explicit K-basis of A/<GB>.
17@*      Therefore one is interested in the following data:
18@*      - the Ufnarovskij graph induced by GB
19@*      - the mistletoes of A/<GB>
20@*      - the K-dimension of A/<GB>
21@*      - the Hilbert series of A/<GB>
22@*
23@*      The Ufnarovskij graph is used to determine whether A/<GB> has finite
24@*      K-dimension. One has to check if the graph contains cycles.
25@*      For the whole theory we refer to [ufna]. Given a
26@*      reduced set of monomials GB one can define the basis tree, whose vertex
27@*      set V consists of all normal monomials w.r.t. GB. For every two
28@*      monomials m_1, m_2 in V there is a direct edge from m_1 to m_2, if and
29@*      only if there exists x_k in {x_1,..,x_n}, such that m_1*x_k = m_2. The
30@*      set M = {m in V | there is no edge from m to another monomial in V} is
31@*      called the set of mistletoes. As one can easily see it consists of
32@*      the endpoints of the graph. Since there is a unique path to every
33@*      monomial in V the whole graph can be described only from the knowledge
34@*      of the mistletoes. Note that V corresponds to a basis of A/<GB>, so
35@*      knowing the mistletoes we know a K-basis. The name mistletoes was given
36@*      to those points because of these miraculous value and the algorithm is
37@*      named sickle, because a sickle is the tool to harvest mistletoes.
38@*      For more details see [studzins]. This package uses the Letterplace
39@*      format introduced by [lls]. The algebra can either be represented as a
40@*      Letterplace ring or via integer vectors: Every variable will only be
41@*      represented by its number, so variable one is represented as 1,
42@*      variable two as 2 and so on. The monomial x_1*x_3*x_2 for example will
43@*      be stored as (1,3,2). Multiplication is concatenation. Note that there
44@*      is no algorithm for computing the normal form yet, but for our case it
45@*      is not needed. Note that the name fpadim.lib is short for dimensions of
46@*      finite presented algebras.
47@*
48
49REFERENCES:
50
51@*   [ufna] Ufnarovskij: Combinatorical and asymptotic methods in algebra, 1990
52@*   [lls] Levandovskyy, La Scala: Letterplace ideals and non-commutative
53Groebner bases, 2009
54@*   [studzins] Studzinski: Dimension computations in non-commutative,
55associative algebras, Diploma thesis, RWTH Aachen, 2010
56
57ASSUMPTIONS:
58@* - basering is always a Letterplace ring
59@* - all intvecs correspond to Letterplace monomials
60@* - if you specify a different degree bound d,
61d <= attrib(basering,uptodeg) holds
62@* In the procedures below, 'iv' stands for intvec representation
63and 'lp' for the letterplace representation of monomials
64
65PROCEDURES:
66
67lpGkDim(G);                        computes the Gelfand Kirillov dimension of A/<G>
68ivDHilbert(L,n[,d]);       computes the K-dimension and the Hilbert series
69ivDHilbertSickle(L,n[,d]); computes mistletoes, K-dimension and Hilbert series
70ivDimCheck(L,n);           checks if the K-dimension of A/<L> is infinite
71lpGlDimBound(G);           computes upper bound of global dimension of A/<G>
72ivHilbert(L,n[,d]);        computes the Hilbert series of A/<L> in intvec format
73ivKDim(L,n[,d]);           computes the K-dimension of A/<L> in intvec format
74ivMis2Base(M);             computes a K-basis of the factor algebra
75ivMis2Dim(M);              computes the K-dimension of the factor algebra
76ivOrdMisLex(M);            orders a list of intvecs lexicographically
77ivSickle(L,n[,d]);         computes the mistletoes of A/<L> in intvec format
78ivSickleHil(L,n[,d]);      computes the mistletoes and Hilbert series of A/<L>
79ivSickleDim(L,n[,d]);      computes the mistletoes and the K-dimension of A/<L>
80lpDHilbert(G[,d,n]);       computes the K-dimension and Hilbert series of A/<G>
81lpDHilbertSickle(G[,d,n]); computes mistletoes, K-dimension and Hilbert series
82lpHilbert(G[,d,n]);        computes the Hilbert series of A/<G> in lp format
83lpDimCheck(G);             checks if the K-dimension of A/<G> is infinite
84lpKDim(G[,d,n]);           computes the K-dimension of A/<G> in lp format
85lpMis2Base(M);             computes a K-basis of the factor algebra
86lpMis2Dim(M);              computes the K-dimension of the factor algebra
87lpOrdMisLex(M);            orders an ideal of lp-monomials lexicographically
88lpSickle(G[,d,n]);         computes the mistletoes of A/<G> in lp format
89lpSickleHil(G[,d,n]);      computes the mistletoes and Hilbert series of A/<G>
90lpSickleDim(G[,d,n]);      computes the mistletoes and the K-dimension of A/<G>
91sickle(G[,m,d,h]);         can be used to access all lp main procedures
92
93
94ivL2lpI(L);           transforms a list of intvecs into an ideal of lp monomials
95iv2lp(I);             transforms an intvec into the corresponding monomial
96iv2lpList(L);         transforms a list of intmats into an ideal of lp monomials
97iv2lpMat(M);          transforms an intmat into an ideal of lp monomials
98lp2iv(p);             transforms a polynomial into the corresponding intvec
99lp2ivId(G);           transforms an ideal into the corresponding list of intmats
100lpId2ivLi(G);         transforms a lp-ideal into the corresponding list of intvecs
101
102SEE ALSO: freegb_lib
103";
104
105LIB "freegb.lib"; //for letterplace rings
106LIB "general.lib";//for sorting mistletoes
107
108/////////////////////////////////////////////////////////
109
110
111//--------------- auxiliary procedures ------------------
112
113static proc allVars(list L, intvec P, int n)
114"USAGE: allVars(L,P,n); L a list of intmats, P an intvec, n an integer
115RETURN: int, 0 if all variables are contained in the quotient algebra, 1 otherwise
116"
117{int i,j,r;
118  intvec V;
119  for (i = 1; i <= size(P); i++) {if (P[i] == 1){ j = i; break;}}
120  V = L[j][1..nrows(L[j]),1];
121  for (i = 1; i <= n; i++) {if (isInVec(i,V) == 0) {r = 1; break;}}
122  if (r == 0) {return(1);}
123  else {return(0);}
124}
125
126static proc checkAssumptions(int d, list L)
127"PURPOSE: Checks, if all the Assumptions are holding
128"
129{if (typeof(attrib(basering,"isLetterplaceRing"))=="string") {ERROR("Basering is not a Letterplace ring!");}
130  if (d > attrib(basering,"uptodeg")) {ERROR("Specified degree bound exceeds ring parameter!");}
131  int i;
132  for (i = 1; i <= size(L); i++)
133  {if (entryViolation(L[i], attrib(basering,"lV")))
134    {ERROR("Not allowed monomial/intvec found!");}
135  }
136  return();
137}
138
139static proc createStartMat(int d, int n)
140"USAGE: createStartMat(d,n); d, n integers
141RETURN: intmat
142PURPOSE:Creating the intmat with all normal monomials in n variables and of degree d to start with
143NOTE:   d has to be > 0
144"
145{intmat M[(n^d)][d];
146  int i1,i2,i3,i4;
147  for (i1 = 1; i1 <= d; i1++)  //Spalten
148  {i2 = 1; //durchlaeuft Zeilen
149    while (i2 <= (n^d))
150    {for (i3 = 1; i3 <= n; i3++)
151      {for (i4 = 1; i4 <= (n^(i1-1)); i4++)
152        {M[i2,i1] = i3;
153          i2 = i2 + 1;
154        }
155      }
156    }
157  }
158  return(M);
159}
160
161static proc createStartMat1(int n, intmat M)
162"USAGE: createStartMat1(n,M); n an integer, M an intmat
163RETURN: intmat, with all variables except those in M
164"
165{int i;
166  intvec V,Vt;
167  V = M[(1..nrows(M)),1];
168  for (i = 1; i <= size(V); i++) {if (isInVec(i,V) == 0) {Vt = Vt,i;}}
169  if (Vt == 0) {intmat S; return(S);}
170  else {Vt = Vt[2..size(Vt)]; intmat S [size(Vt)][1]; S[1..size(Vt),1] = Vt; return(S);}
171}
172
173static proc entryViolation(intmat M, int n)
174"PURPOSE:checks, if all entries in M are variable-related
175"
176{int i,j;
177  for (i = 1; i <= nrows(M); i++)
178  {for (j = 1; j <= ncols(M); j++)
179    {if(!((1<=M[i,j])&&(M[i,j]<=n))) {return(1);}}
180  }
181  return(0);
182}
183
184static proc findDimen(intvec V, int n, list L, intvec P, list #)
185"USAGE: findDimen(V,n,L,P,degbound); V,P intvecs, n, an integer, L a list,
186@*      degbound an optional integer
187RETURN: int
188PURPOSE:Computing the K-dimension of the quotient algebra
189"
190{int degbound = 0;
191  if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}}
192  int dimen,i,j,w,it;
193  intvec Vt,Vt2;
194  module M;
195  if (degbound == 0)
196  {for (i = 1; i <= n; i++)
197    {Vt = V, i; w = 0;
198      for (j = 1; j<= size(P); j++)
199      {if (P[j] <= size(Vt))
200        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
201          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
202        }
203      }
204      if (w == 0)
205      {vector Vtt;
206        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
207        M = M,Vtt;
208        kill Vtt;
209      }
210    }
211    if (size(M) == 0) {return(0);}
212    else
213    {M = simplify(M,2);
214      for (i = 1; i <= size(M); i++)
215      {kill Vt; intvec Vt;
216        for (j =1; j <= size(M[i]); j++){Vt[j] =  int(leadcoef(M[i][j]));}
217        dimen = dimen + 1 + findDimen(Vt,n,L,P);
218      }
219      return(dimen);
220    }
221  }
222  else
223  {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");}
224    if (size(V) == degbound) {return(0);}
225    for (i = 1; i <= n; i++)
226    {Vt = V, i; w = 0;
227      for (j = 1; j<= size(P); j++)
228      {if (P[j] <= size(Vt))
229        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
230          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
231        }
232      }
233      if (w == 0) {vector Vtt;
234        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
235        M = M,Vtt;
236        kill Vtt;
237      }
238    }
239    if (size(M) == 0) {return(0);}
240    else
241    {M = simplify(M,2);
242      for (i = 1; i <= size(M); i++)
243      {kill Vt; intvec Vt;
244        for (j =1; j <= size(M[i]); j++){Vt[j] =  int(leadcoef(M[i][j]));}
245        dimen = dimen + 1 + findDimen(Vt,n,L,P,degbound);
246      }
247      return(dimen);
248    }
249  }
250}
251
252static proc findCycle(intvec V, list L, intvec P, int n, int ld, module M)
253"USAGE:
254RETURN: int, 1 if Ufn-graph contains a cycle, or 0 otherwise
255PURPOSE:Searching the Ufnarovskij graph for cycles
256"
257{int i,j,w,r;intvec Vt,Vt2;
258  int it, it2;
259  if (size(V) < ld)
260  {for (i = 1; i <= n; i++)
261    {Vt = V,i; w = 0;
262      for (j = 1; j <= size(P); j++)
263      {if (P[j] <= size(Vt))
264        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
265          if (isInMat(Vt2,L[j]) > 0)
266          {w = 1; break;}
267        }
268      }
269      if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);}
270      if (r == 1) {break;}
271    }
272    return(r);
273  }
274  else
275  {j = size(M);
276    if (j > 0)
277    {
278      intmat Mt[j][nrows(M)];
279      for (it = 1; it <= j; it++)
280      { for(it2 = 1; it2 <= nrows(M);it2++)
281        {Mt[it,it2] = int(leadcoef(M[it2,it]));}
282      }
283      Vt = V[(size(V)-ld+1)..size(V)];
284      //Mt; type(Mt);Vt;type(Vt);
285      if (isInMat(Vt,Mt) > 0) {return(1);}
286      else
287      {vector Vtt;
288        for (it =1; it <= size(Vt); it++)
289        {Vtt = Vtt + Vt[it]*gen(it);}
290        M = M,Vtt;
291        kill Vtt;
292        for (i = 1; i <= n; i++)
293        {Vt = V,i; w = 0;
294          for (j = 1; j <= size(P); j++)
295          {if (P[j] <= size(Vt))
296            {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
297              //L[j]; type(L[j]);Vt2;type(Vt2);
298              if (isInMat(Vt2,L[j]) > 0)
299              {w = 1; break;}
300            }
301          }
302          if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);}
303          if (r == 1) {break;}
304        }
305        return(r);
306      }
307    }
308    else
309    { Vt = V[(size(V)-ld+1)..size(V)];
310      vector Vtt;
311      for (it = 1; it <= size(Vt); it++)
312      {Vtt = Vtt + Vt[it]*gen(it);}
313      M = Vtt;
314      kill Vtt;
315      for (i = 1; i <= n; i++)
316      {Vt = V,i; w = 0;
317        for (j = 1; j <= size(P); j++)
318        {if (P[j] <= size(Vt))
319          {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
320            //L[j]; type(L[j]);Vt2;type(Vt2);
321            if (isInMat(Vt2,L[j]) > 0)
322            {w = 1; break;}
323          }
324        }
325        if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);}
326        if (r == 1) {break;}
327      }
328      return(r);
329    }
330  }
331}
332
333
334static proc findCycleDFS(int i, intmat T, intvec V)
335"
336PURPOSE:
337this is a classical deep-first search for cycles contained in a graph given by an intmat
338"
339{
340  intvec rV;
341  int k,k1,t;
342  int j = V[size(V)];
343  if (T[j,i] > 0) {return(V);}
344  else
345  {
346    for (k = 1; k <= ncols(T); k++)
347    {
348      t = 0;
349      if (T[j,k] > 0)
350      {
351        for (k1 = 1; k1 <= size(V); k1++) {if (V[k1] == k) {t = 1; break;}}
352        if (t == 0)
353        {
354          rV = V;
355          rV[size(rV)+1] = k;
356          rV = findCycleDFS(i,T,rV);
357          if (rV[1] > -1) {return(rV);}
358        }
359      }
360    }
361  }
362  return(intvec(-1));
363}
364
365
366
367static proc findHCoeff(intvec V,int n,list L,intvec P,intvec H,list #)
368"USAGE: findHCoeff(V,n,L,P,H,degbound); L a list of intmats, degbound an integer
369RETURN: intvec
370PURPOSE:Computing the coefficient of the Hilbert series (upto degree degbound)
371NOTE:   Starting with a part of the Hilbert series we change the coefficient
372@*      depending on how many basis elements we found on the actual branch
373"
374{int degbound = 0;
375  if (size(#) > 0){if (#[1] > 0){degbound = #[1];}}
376  int i,w,j,it;
377  int h1 = 0;
378  intvec Vt,Vt2,H1;
379  module M;
380  if (degbound == 0)
381  {for (i = 1; i <= n; i++)
382    {Vt = V, i; w = 0;
383      for (j = 1; j<= size(P); j++)
384      {if (P[j] <= size(Vt))
385        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
386          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
387        }
388      }
389      if (w == 0)
390      {vector Vtt;
391        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
392        M = M,Vtt;
393        kill Vtt;
394      }
395    }
396    if (size(M) == 0) {return(H);}
397    else
398    {M = simplify(M,2);
399      for (i = 1; i <= size(M); i++)
400      {kill Vt; intvec Vt;
401        for (j =1; j <= size(M[i]); j++) {Vt[j] =  int(leadcoef(M[i][j]));}
402        h1 = h1 + 1; H1 = findHCoeff(Vt,n,L,P,H1);
403      }
404      if (size(H1) < (size(V)+2)) {H1[(size(V)+2)] = h1;}
405      else {H1[(size(V)+2)] = H1[(size(V)+2)] + h1;}
406      H1 = H1 + H;
407      return(H1);
408    }
409  }
410  else
411  {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");}
412    if (size(V) == degbound) {return(H);}
413    for (i = 1; i <= n; i++)
414    {Vt = V, i; w = 0;
415      for (j = 1; j<= size(P); j++)
416      {if (P[j] <= size(Vt))
417        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
418          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
419        }
420      }
421      if (w == 0)
422      {vector Vtt;
423        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
424        M = M,Vtt;
425        kill Vtt;
426      }
427    }
428    if (size(M) == 0) {return(H);}
429    else
430    {M = simplify(M,2);
431      for (i = 1; i <= size(M); i++)
432      {kill Vt; intvec Vt;
433        for (j =1; j <= size(M[i]); j++)
434        {Vt[j] =  int(leadcoef(M[i][j]));}
435        h1 = h1 + 1; H1 = findHCoeff(Vt,n,L,P,H1,degbound);
436      }
437      if (size(H1) < (size(V)+2)) { H1[(size(V)+2)] = h1;}
438      else {H1[(size(V)+2)] = H1[(size(V)+2)] + h1;}
439      H1 = H1 + H;
440      return(H1);
441    }
442  }
443}
444
445static proc findHCoeffMis(intvec V, int n, list L, intvec P, list R,list #)
446"USAGE: findHCoeffMis(V,n,L,P,R,degbound); degbound an optional integer, L a
447@*      list of Intmats, R
448RETURN: list
449PURPOSE:Computing the coefficients of the Hilbert series and the Mistletoes all
450@*      at once
451"
452{int degbound = 0;
453  if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}}
454  int i,w,j,h1;
455  intvec Vt,Vt2,H1; int it;
456  module M;
457  if (degbound == 0)
458  {for (i = 1; i <= n; i++)
459    {Vt = V, i; w = 0;
460      for (j = 1; j<= size(P); j++)
461      {if (P[j] <= size(Vt))
462        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
463          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
464        }
465      }
466      if (w == 0)
467      {vector Vtt;
468        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
469        M = M,Vtt;
470        kill Vtt;
471      }
472    }
473    if (size(M) == 0) {if (size(R) < 2){R[2] = list(V);} else {R[2] = R[2] + list(V);} return(R);}
474    else
475    {M = simplify(M,2);
476      for (i = 1; i <= size(M); i++)
477      {kill Vt; intvec Vt;
478        for (j =1; j <= size(M[i]); j++)
479        {Vt[j] =  int(leadcoef(M[i][j]));}
480        if (size(R[1]) < (size(V)+2)) { R[1][(size(V)+2)] = 1;}
481        else
482        {R[1][(size(V)+2)] = R[1][(size(V)+2)] + 1;}
483        R = findHCoeffMis(Vt,n,L,P,R);
484      }
485      return(R);
486    }
487  }
488  else
489  {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");}
490    if (size(V) == degbound)
491    {if (size(R) < 2){R[2] = list (V);}
492      else{R[2] = R[2] + list (V);}
493      return(R);
494    }
495    for (i = 1; i <= n; i++)
496    {Vt = V, i; w = 0;
497      for (j = 1; j<= size(P); j++)
498      {if (P[j] <= size(Vt))
499        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
500          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
501        }
502      }
503      if (w == 0)
504      {vector Vtt;
505        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
506        M = M,Vtt;
507        kill Vtt;
508      }
509    }
510    if (size(M) == 0) {if (size(R) < 2){R[2] = list(V);} else {R[2] = R[2] + list(V);} return(R);}
511    else
512    {M = simplify(M,2);
513      for (i = 1; i <= ncols(M); i++)
514      {kill Vt; intvec Vt;
515        for (j =1; j <= size(M[i]); j++)
516        {Vt[j] =  int(leadcoef(M[i][j]));}
517        if (size(R[1]) < (size(V)+2)) { R[1][(size(V)+2)] = 1;}
518        else
519        {R[1][(size(V)+2)] = R[1][(size(V)+2)] + 1;}
520        R = findHCoeffMis(Vt,n,L,P,R,degbound);
521      }
522      return(R);
523    }
524  }
525}
526
527
528static proc findMisDim(intvec V,int n,list L,intvec P,list R,list #)
529"USAGE:
530RETURN: list
531PURPOSE:Computing the K-dimension and the Mistletoes all at once
532"
533{int degbound = 0;
534  if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}}
535  int dimen,i,j,w;
536  intvec Vt,Vt2; int it;
537  module M;
538  if (degbound == 0)
539  {for (i = 1; i <= n; i++)
540    {Vt = V, i; w = 0;
541      for (j = 1; j<= size(P); j++)
542      {if (P[j] <= size(Vt))
543        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
544          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
545        }
546      }
547      if (w == 0)
548      {vector Vtt;
549        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
550        M = M,Vtt;
551        kill Vtt;
552      }
553    }
554    if (size(M) == 0)
555    {if (size(R) < 2){R[2] = list (V);}
556      else{R[2] = R[2] + list(V);}
557      return(R);
558    }
559    else
560    {M = simplify(M,2);
561      for (i = 1; i <= size(M); i++)
562      {kill Vt; intvec Vt;
563        for (j =1; j <= size(M[i]); j++){Vt[j] =  int(leadcoef(M[i][j]));}
564        R[1] = R[1] + 1; R = findMisDim(Vt,n,L,P,R);
565      }
566      return(R);
567    }
568  }
569  else
570  {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");}
571    if (size(V) == degbound)
572    {if (size(R) < 2){R[2] = list (V);}
573      else{R[2] = R[2] + list (V);}
574      return(R);
575    }
576    for (i = 1; i <= n; i++)
577    {Vt = V, i; w = 0;
578      for (j = 1; j<= size(P); j++)
579      {if (P[j] <= size(Vt))
580        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
581          if (isInMat(Vt2,L[j]) > 0) {w = 1; break;}
582        }
583      }
584      if (w == 0)
585      {vector Vtt;
586        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
587        M = M,Vtt;
588        kill Vtt;
589      }
590    }
591    if (size(M) == 0)
592    {if (size(R) < 2){R[2] = list (V);}
593      else{R[2] = R[2] + list(V);}
594      return(R);
595    }
596    else
597    {M = simplify(M,2);
598      for (i = 1; i <= size(M); i++)
599      {kill Vt; intvec Vt;
600        for (j =1; j <= size(M[i]); j++){Vt[j] =  int(leadcoef(M[i][j]));}
601        R[1] = R[1] + 1; R = findMisDim(Vt,n,L,P,R,degbound);
602      }
603      return(R);
604    }
605  }
606}
607
608
609static proc findmistletoes(intvec V, int n, list L, intvec P, list #)
610"USAGE: findmistletoes(V,n,L,P,degbound); V a normal word, n the number of
611@*      variables, L the GB, P the occuring degrees,
612@*      and degbound the (optional) degreebound
613RETURN:  list
614PURPOSE:Computing mistletoes starting in V
615NOTE:   V has to be normal w.r.t. L, it will not be checked for being so
616"
617{int degbound = 0;
618  if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}}
619  list R; intvec Vt,Vt2; int it;
620  int i,j;
621  module M;
622  if (degbound == 0)
623  {int w;
624    for (i = 1; i <= n; i++)
625    {Vt = V,i; w = 0;
626      for (j = 1; j <= size(P); j++)
627      {if (P[j] <= size(Vt))
628        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
629          if (isInMat(Vt2,L[j]) > 0)
630          {w = 1; break;}
631        }
632      }
633      if (w == 0)
634      {vector Vtt;
635        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
636        M = M,Vtt;
637        kill Vtt;
638      }
639    }
640    if (size(M)==0) {R = V; return(R);}
641    else
642    {M = simplify(M,2);
643      for (i = 1; i <= size(M); i++)
644      {kill Vt; intvec Vt;
645        for (j =1; j <= size(M[i]); j++){Vt[j] =  int(leadcoef(M[i][j]));}
646        R = R + findmistletoes(Vt,n,L,P);
647      }
648      return(R);
649    }
650  }
651  else
652  {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");}
653    if (size(V) == degbound) {R = V; return(R);}
654    int w;
655    for (i = 1; i <= n; i++)
656    {Vt = V,i; w = 0;
657      for (j = 1; j <= size(P); j++)
658      {if (P[j] <= size(Vt))
659        {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)];
660          if (isInMat(Vt2,L[j]) > 0){w = 1; break;}
661        }
662      }
663      if (w == 0)
664      {vector Vtt;
665        for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);}
666        M = M,Vtt;
667        kill Vtt;
668      }
669    }
670    if (size(M) == 0) {R = V; return(R);}
671    else
672    {M = simplify(M,2);
673      for (i = 1; i <= ncols(M); i++)
674      {kill Vt; intvec Vt;
675        for (j =1; j <= size(M[i]); j++)
676        {Vt[j] =  int(leadcoef(M[i][j]));}
677        //Vt; typeof(Vt); size(Vt);
678        R = R + findmistletoes(Vt,n,L,P,degbound);
679      }
680      return(R);
681    }
682  }
683}
684
685static proc growthAlg(intmat T, list #)
686"
687real algorithm for checking the growth of an algebra
688"
689{
690  int s = 1;
691  if (size(#) > 0) { s = #[1];}
692  int j;
693  int n = ncols(T);
694  intvec NV,C; NV[n] = 0; int m,i;
695  intmat T2[n][n] = T[1..n,1..n]; intmat N[n][n];
696  if (T2 == N)
697  {
698    for (i = 1; i <= n; i++)
699    {
700      if (m <  T[n+1,i]) { m = T[n+1,i];}
701    }
702    return(m);
703  }
704
705  //first part: the diagonals
706  for (i = s; i <= n; i++)
707  {
708    if (T[i,i] > 0)
709    {
710      if ((T[i,i] >= 1) && (T[n+1,i] > 0)) {return(-1);}
711      if ((T[i,i] == 1) && (T[n+1,i] == 0))
712      {
713        T[i,i] = 0;
714        T[n+1,i] = 1;
715        return(growthAlg(T));
716      }
717    }
718  }
719
720  //second part: searching for the last but one vertices
721  T2 = T2*T2;
722  for (i = s; i <= n; i++)
723  {
724    if ((intvec(T[i,1..n]) <> intvec(0)) && (intvec(T2[i,1..n]) == intvec(0)))
725    {
726      for (j = 1; j <= n; j++)
727      {
728        if ((T[i,j] > 0) && (m < T[n+1,j])) {m = T[n+1,j];}
729      }
730      T[n+1,i] = T[n+1,i] + m;
731      T[i,1..n] = NV;
732      return(growthAlg(T));
733    }
734  }
735  m = 0;
736
737  //third part: searching for circles
738  for (i = s; i <= n; i++)
739  {
740    T2 = T[1..n,1..n];
741    C = findCycleDFS(i,T2, intvec(i));
742    if (C[1] > 0)
743    {
744      for (j = 2; j <= size(C); j++)
745      {
746        T[i,1..n] = T[i,1..n] + T[C[j],1..n];
747        T[C[j],1..n] = NV;
748      }
749      for (j = 2; j <= size(C); j++)
750      {
751        T[1..n,i] = T[1..n,i] + T[1..n,C[j]];
752        T[1..n,C[j]] = NV;
753      }
754      T[i,i] = T[i,i] - size(C) + 1;
755      m = 0;
756      for (j = 1; j <= size(C); j++)
757      {
758        m = m + T[n+1,C[j]];
759      }
760      for (j = 1; j <= size(C); j++)
761      {
762        T[n+1,C[j]] = m;
763      }
764      return(growthAlg(T,i));
765    }
766    else {ERROR("No Cycle found, something seems wrong! Please contact the authors.");}
767  }
768
769  m = 0;
770  for (i = 1; i <= n; i++)
771  {
772    if (m < T[n+1,i])
773    {
774      m = T[n+1,i];
775    }
776  }
777  return(m);
778}
779
780static proc GlDimSuffix(intvec v, intvec g)
781{
782  //Computes the shortest r such that g is a suffix for vr
783  //only valid for lex orderings?
784  intvec r,gt,vt,lt,g2;
785  int lg,lv,l,i,c,f;
786  lg = size(g); lv = size(v);
787  if (lg <= lv)
788  {
789    l = lv-lg;
790  }
791  else
792  {
793    l = 0; g2 = g[(lv+1)..lg];
794    g = g[1..lv]; lg = size(g);
795    c = 1;
796  }
797  while (l < lv)
798  {
799    vt = v[(l+1)..lv];
800    gt = g[1..(lv-l)];
801    lt = size(gt);
802    for (i = 1; i <= lt; i++)
803    {
804      if (vt[i]<>gt[i]) {l++; break;}
805    }
806    if (lt <=i ) { f = 1; break;}
807  }
808  if (f == 0) {return(g);}
809  r = g[(lv-l+1)..lg];
810  if (c == 1) {r = r,g2;}
811  return(r);
812}
813
814static proc isNormal(intvec V, list G)
815{
816  int i,j,k,l;
817  k = 0;
818  for (i = 1; i <= size(G); i++)
819  {
820    if ( size(G[i]) <= size(V) )
821    {
822      while ( size(G[i])+k <= size(V) )
823      {
824        if ( G[i] == V[(1+k)..size(V)] ) {return(1);}
825      }
826    }
827  }
828  return(0);
829}
830
831static proc findDChain(list L)
832{
833  list Li; int i,j;
834  for (i = 1; i <= size(L); i++) {Li[i] = size(L[i]);}
835  Li = sort(Li); Li = Li[1];
836  return(Li[size(Li)]);
837}
838
839static proc isInList(intvec V, list L)
840"USAGE: isInList(V,L); V an intvec, L a list of intvecs
841RETURN: int
842PURPOSE:Finding the position of V in L, returns 0, if V is not in M
843"
844{int i,n;
845  n = 0;
846  for (i = 1; i <= size(L); i++) {if (L[i] == V) {n = i; break;}}
847  return(n);
848}
849
850static proc isInMat(intvec V, intmat M)
851"USAGE: isInMat(V,M);V an intvec, M an intmat
852RETURN: int
853PURPOSE:Finding the position of V in M, returns 0, if V is not in M
854"
855{if (size(V) <> ncols(M)) {return(0);}
856  int i;
857  intvec Vt;
858  for (i = 1; i <= nrows(M); i++)
859  {Vt = M[i,1..ncols(M)];
860    if ((V-Vt) == 0){return(i);}
861  }
862  return(0);
863}
864
865static proc isInVec(int v,intvec V)
866"USAGE: isInVec(v,V); v an integer,V an intvec
867RETURN: int
868PURPOSE:Finding the position of v in V, returns 0, if v is not in V
869"
870{int i,n;
871  n = 0;
872  for (i = 1; i <= size(V); i++) {if (V[i] == v) {n = i; break;}}
873  return(n);
874}
875
876
877static proc isPF(intvec P, intvec I)
878"
879PURPOSE:
880checks, if a word P is a praefix of another word I
881"
882{
883  int n = size(P);
884  if (n <= 0 || P == 0) {return(1);}
885  if (size(I) < n) {return(0);}
886  intvec IP = I[1..n];
887  if (IP == P) {return(1);}
888  else {return(0);}
889}
890
891static proc isSF(intvec S, intvec I)
892"
893PURPOSE:
894checks, if a word S is a suffix of another word I
895"
896{
897  int n = size(S);
898  if (n <= 0 || S == 0) {return(1);}
899  int m = size(I);
900  if (m < n) {return(0);}
901  intvec IS = I[(m-n+1)..m];
902  if (IS == S) {return(1);}
903  else {return(0);}
904}
905
906static proc isIF(intvec IF, intvec I)
907"
908PURPOSE:
909checks, if a word IF is an infix of another word I
910"
911{
912  int n = size(IF);
913  int m = size(I);
914
915  if (n <= 0 || IF == 0) {return(1);}
916  if (m < n) {return(0);}
917
918  for (int i = 0; (n + i) <= m; i++){
919    intvec IIF = I[(1 + i)..(n + i)];
920    if (IIF == IF) {
921      return(1);
922    }
923  }
924  return(0);
925}
926
927proc ivL2lpI(list L)
928"USAGE: ivL2lpI(L); L a list of intvecs
929RETURN: ideal
930PURPOSE:Transforming a list of intvecs into an ideal of Letterplace monomials
931ASSUME: - Intvec corresponds to a Letterplace monomial
932@*      - basering has to be a Letterplace ring
933EXAMPLE: example ivL2lpI; shows examples
934"
935{checkAssumptions(0,L);
936  int i; ideal G;
937  poly p;
938  for (i = 1; i <= size(L); i++)
939  {p = iv2lp(L[i]);
940    G[(size(G) + 1)] = p;
941  }
942  return(G);
943}
944example
945{
946  "EXAMPLE:"; echo = 2;
947  ring r = 0,(x,y,z),dp;
948  def R = makeLetterplaceRing(5);// constructs a Letterplace ring
949  setring R; //sets basering to Letterplace ring
950  intvec u = 1,1,2; intvec v = 2,1,3; intvec w = 3,1,1;
951  // u = x^2y, v = yxz, w = zx^2 in intvec representation
952  list L = u,v,w;
953  ivL2lpI(L);// invokes the procedure, returns the ideal containing u,v,w
954}
955
956proc iv2lp(intvec I)
957"USAGE: iv2lp(I); I an intvec
958RETURN: poly
959PURPOSE:Transforming an intvec into the corresponding Letterplace polynomial
960ASSUME: - Intvec corresponds to a Letterplace monomial
961@*      - basering has to be a Letterplace ring
962NOTE:   - Assumptions will not be checked!
963EXAMPLE: example iv2lp; shows examples
964"
965{if (I[1] == 0) {return(1);}
966  int i = size(I);
967  if (i > attrib(basering,"uptodeg")) {ERROR("polynomial exceeds degreebound");}
968  int j; poly p = 1;
969  for (j = 1; j <= i; j++) {if (I[j] > 0) { p = lpMult(p,var(I[j]));}} //ignore zeroes, because they correspond to 1
970  return(p);
971}
972example
973{
974  "EXAMPLE:"; echo = 2;
975  ring r = 0,(x,y,z),dp;
976  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
977  setring R; //sets basering to Letterplace ring
978  intvec u = 1,1,2; intvec v = 2,1,3; intvec w = 3,1,1;
979  // u = x^2y, v = yxz, w = zx^2 in intvec representation
980  iv2lp(u); // invokes the procedure and returns the corresponding poly
981  iv2lp(v);
982  iv2lp(w);
983}
984
985proc iv2lpList(list L)
986"USAGE: iv2lpList(L); L a list of intmats
987RETURN: ideal
988PURPOSE:Converting a list of intmats into an ideal of corresponding monomials
989ASSUME: - The rows of each intmat in L must correspond to a Letterplace monomial
990@*      - basering has to be a Letterplace ring
991EXAMPLE: example iv2lpList; shows examples
992"
993{checkAssumptions(0,L);
994  ideal G;
995  int i;
996  for (i = 1; i <= size(L); i++){G = G + iv2lpMat(L[i]);}
997  return(G);
998}
999example
1000{
1001  "EXAMPLE:"; echo = 2;
1002  ring r = 0,(x,y,z),dp;
1003  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
1004  setring R; // sets basering to Letterplace ring
1005  intmat u[3][1] = 1,1,2; intmat v[1][3] = 2,1,3; intmat w[2][3] = 3,1,1,2,3,1;
1006  // defines intmats of different size containing intvec representations of
1007  // monomials as rows
1008  list L = u,v,w;
1009  print(u); print(v); print(w); // shows the intmats contained in L
1010  iv2lpList(L); // returns the corresponding monomials as an ideal
1011}
1012
1013
1014proc iv2lpMat(intmat M)
1015"USAGE: iv2lpMat(M); M an intmat
1016RETURN: ideal
1017PURPOSE:Converting an intmat into an ideal of the corresponding monomials
1018ASSUME: - The rows of M must correspond to Letterplace monomials
1019@*      - basering has to be a Letterplace ring
1020EXAMPLE: example iv2lpMat; shows examples
1021"
1022{list L = M;
1023  checkAssumptions(0,L);
1024  kill L;
1025  ideal G; poly p;
1026  int i; intvec I;
1027  for (i = 1; i <= nrows(M); i++)
1028  { I = M[i,1..ncols(M)];
1029    p = iv2lp(I);
1030    G[size(G)+1] = p;
1031  }
1032  return(G);
1033}
1034example
1035{
1036  "EXAMPLE:"; echo = 2;
1037  ring r = 0,(x,y,z),dp;
1038  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
1039  setring R; // sets basering to Letterplace ring
1040  intmat u[3][1] = 1,1,2; intmat v[1][3] = 2,1,3; intmat w[2][3] = 3,1,1,2,3,1;
1041  // defines intmats of different size containing intvec representations of
1042  // monomials as rows
1043  iv2lpMat(u); // returns the monomials contained in u
1044  iv2lpMat(v); // returns the monomials contained in v
1045  iv2lpMat(w); // returns the monomials contained in w
1046}
1047
1048proc lpId2ivLi(ideal G)
1049"USAGE: lpId2ivLi(G); G an ideal
1050RETURN: list
1051PURPOSE:Transforming an ideal into the corresponding list of intvecs
1052ASSUME: - basering has to be a Letterplace ring
1053EXAMPLE: example lpId2ivLi; shows examples
1054"
1055{
1056  int i,j,k;
1057  list M;
1058  checkAssumptions(0,M);
1059  for (i = 1; i <= size(G); i++) {M[i] = lp2iv(G[i]);}
1060  return(M);
1061}
1062example
1063{
1064  "EXAMPLE:"; echo = 2;
1065  ring r = 0,(x,y),dp;
1066  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
1067  setring R; // sets basering to Letterplace ring
1068  ideal L = x(1)*x(2),y(1)*y(2),x(1)*y(2)*x(3);
1069  lpId2ivLi(L); // returns the corresponding intvecs as a list
1070}
1071
1072proc lp2iv(poly p)
1073"USAGE: lp2iv(p); p a poly
1074RETURN: intvec
1075PURPOSE:Transforming a monomial into the corresponding intvec
1076ASSUME: - basering has to be a Letterplace ring
1077NOTE:   - Assumptions will not be checked!
1078EXAMPLE: example lp2iv; shows examples
1079"
1080{p = normalize(lead(p));
1081  intvec I;
1082  int i,j;
1083  if (deg(p) > attrib(basering,"uptodeg")) {ERROR("Monomial exceeds degreebound");}
1084  if (p == 1) {return(I);}
1085  if (p == 0) {ERROR("Monomial is not allowed to equal zero");}
1086  intvec lep = leadexp(p);
1087  for ( i = 1; i <= attrib(basering,"lV"); i++) {if (lep[i] == 1) {I = i; break;}}
1088  for (i = (attrib(basering,"lV")+1); i <= size(lep); i++)
1089  {if (lep[i] == 1)
1090    { j = (i mod attrib(basering,"lV"));
1091      if (j == 0) {I = I,attrib(basering,"lV");}
1092      else {I = I,j;}
1093    }
1094    else { if (lep[i] > 1) {ERROR("monomial has a not allowed multidegree");}}
1095  }
1096  if (I[1] == 0) {ERROR("monomial has a not allowed multidegree");}
1097
1098  return(I);
1099}
1100example
1101{
1102  "EXAMPLE:"; echo = 2;
1103  ring r = 0,(x,y,z),dp;
1104  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
1105  setring R; // sets basering to Letterplace ring
1106  poly p = x(1)*x(2)*z(3); poly q = y(1)*y(2)*x(3)*x(4);
1107  poly w= z(1)*y(2)*x(3)*z(4)*z(5);
1108  // p,q,w are some polynomials we want to transform into their
1109  // intvec representation
1110  lp2iv(p); lp2iv(q); lp2iv(w);
1111}
1112
1113proc lp2ivId(ideal G)
1114"USAGE: lp2ivId(G); G an ideal
1115RETURN: list
1116PURPOSE:Converting an ideal into an list of intmats,
1117@*      the corresponding intvecs forming the rows
1118ASSUME: - basering has to be a Letterplace ring
1119EXAMPLE: example lp2ivId; shows examples
1120"
1121{G = normalize(lead(G));
1122  intvec I; list L;
1123  checkAssumptions(0,L);
1124  int i,md;
1125  for (i = 1; i <= size(G); i++) { if (md <= deg(G[i])) {md = deg(G[i]);}}
1126  while (size(G) > 0)
1127  {ideal Gt;
1128    for (i = 1; i <= ncols(G); i++) {if (md == deg(G[i])) {Gt = Gt + G[i]; G[i] = 0;}}
1129    if (size(Gt) > 0)
1130    {G = simplify(G,2);
1131      intmat M [size(Gt)][md];
1132      for (i = 1; i <= size(Gt); i++) {M[i,1..md] = lp2iv(Gt[i]);}
1133      L = insert(L,M);
1134      kill M; kill Gt;
1135      md = md - 1;
1136    }
1137    else {kill Gt; md = md - 1;}
1138  }
1139  return(L);
1140}
1141example
1142{
1143  "EXAMPLE:"; echo = 2;
1144  ring r = 0,(x,y,z),dp;
1145  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
1146  setring R; // sets basering to Letterplace ring
1147  poly p = x(1)*x(2)*z(3); poly q = y(1)*y(2)*x(3)*x(4);
1148  poly w = z(1)*y(2)*x(3)*z(4);
1149  // p,q,w are some polynomials we want to transform into their
1150  // intvec representation
1151  ideal G = p,q,w;
1152  // define the ideal containing p,q and w
1153  lp2ivId(G); // and return the list of intmats for this ideal
1154}
1155
1156// -----------------main procedures----------------------
1157
1158proc lpNoetherian(ideal G) {
1159  // return 0 not noetherian
1160  // return 1 left
1161  // return 2 right
1162  // return 3 both
1163
1164  G = lead(G);
1165  G = simplify(G, 2+4+8);
1166
1167  // check special case 1
1168  int l = 0;
1169  for (int i = 1; i <= size(G); i++) {
1170    // find the max degree in G
1171    int d = deg(G[i]);
1172    if (d > l) {
1173      l = d;
1174    }
1175
1176    // also if G is the whole ring return noetherian
1177    if (leadmonom(G[i]) == 1) {
1178      return(3);
1179    }
1180  }
1181  // if longest word has length 1 we handle it as a special case
1182  if (l == 1) {
1183    int n = attrib(basering, "lV"); // variable count
1184    int k = size(G);
1185    if (k == n) { // only the field left
1186      return(3); // every field is noetherian
1187    }
1188    if (k == n-1) { // V = {1} with loop
1189      return(3);
1190    }
1191    if (k <= n-2) { // V = {1} with more than one loop
1192      return(0);
1193    }
1194  }
1195
1196  intmat UG = lpUfGraph(G);
1197
1198  // check special case 2
1199  intmat zero[nrows(UG)][ncols(UG)];
1200  if (UG == zero) {
1201    return (3);
1202  }
1203
1204  if (!imHasLoops(UG) && imIsUpRightTriangle(topologicalSort(UG))) {
1205    // UG is a DAG
1206    return (3);
1207  }
1208
1209  // DFS from every vertex, if cycle is found, check every vertex for incomming/outcom
1210  intvec visited;
1211  visited[ncols(UG)] = 0;
1212  int inFlag, outFlag;
1213  for (int v = 1; v <= ncols(UG) && (inFlag + outFlag) != 3; v++) {
1214    int inOutFlags = inOrOutCommingEdgeInCycle(UG, v, visited, 0);
1215    if (inOutFlags == 1) {
1216      inFlag = 1;
1217    }
1218    if (inOutFlags == 2) {
1219      outFlag = 2;
1220    }
1221    if (inOutFlags == 3) {
1222      inFlag = 1;
1223      outFlag = 2;
1224    }
1225  }
1226  return (3 - inFlag - outFlag);
1227}
1228
1229proc inOrOutCommingEdgeInCycle(intmat G, int v, intvec visited, intvec path) {
1230  // Mark the current vertex as visited
1231  visited[v] = 1;
1232
1233  // Store the current vertex in path
1234  if (path[1] == 0) {
1235    path[1] = v;
1236  } else {
1237    path[size(path) + 1] = v;
1238  }
1239
1240  int inFlag, outFlag;
1241
1242  for (int w = 1; w <= ncols(G) && (inFlag + outFlag) != 3; w++) {
1243    if (G[v,w] == 1) {
1244      if (visited[w] == 1) {
1245        // new cycle
1246        if (v == w) {
1247          for (int u = 1; u <= ncols(G); u++) {
1248            if (G[v,u] && u != v) {
1249              outFlag = 2;
1250            }
1251            if (G[u,v] && u != v) {
1252              inFlag = 1;
1253            }
1254          }
1255        } else {
1256          for (int i = size(path); i >= 1; i--) { // for each vertex in the path
1257            // check for neighbors not directly next or prev in cycle
1258            for (int u = 1; u <= ncols(G); u++) {
1259              if (G[path[i],u] == 1) { // there is an edge to u
1260                if (path[i] != v) {
1261                  if (u != path[i+1]) { // and u is not the next element in the cycle
1262                    outFlag = 2;
1263                  }
1264                } else {
1265                  if (u != w) {
1266                    outFlag = 2;
1267                  }
1268                }
1269              }
1270              if (G[u,path[i]] == 1) { // there is an edge from u
1271                if (path[i] != w) {
1272                  if (u != path[i-1]) { // and u is not the previous element in the cylce
1273                    inFlag = 1;
1274                  }
1275                } else {
1276                  if (u != v) {
1277                    inFlag = 1;
1278                  }
1279                }
1280              }
1281            }
1282            if (path[i] == w) {
1283              break;
1284            }
1285          }
1286        }
1287      } else {
1288        int inOutFlags = inOrOutCommingEdgeInCycle(G, w, visited, path);
1289        if (inOutFlags == 1) {
1290          inFlag = 1;
1291        }
1292        if (inOutFlags == 2) {
1293          outFlag = 2;
1294        }
1295        if (inOutFlags == 3) {
1296          inFlag = 1;
1297          outFlag = 2;
1298        }
1299      }
1300    }
1301  }
1302
1303  return (inFlag + outFlag);
1304}
1305
1306proc lpIsSemiPrime(ideal G)
1307{
1308  G = lead(G);
1309  G = simplify(G, 2+4+8);
1310
1311  // check special case 1
1312  int l = 0;
1313  for (int i = 1; i <= size(G); i++) {
1314    // find the max degree in G
1315    int d = deg(G[i]);
1316    if (d > l) {
1317      l = d;
1318    }
1319
1320    // also if G is the whole ring
1321    if (leadmonom(G[i]) == 1) {
1322      return(1);
1323    }
1324  }
1325  // if longest word has length 1 we handle it as a special case
1326  if (l == 1) {
1327    return(1);
1328  }
1329
1330  list VUG = lpUfGraph(G, 1);
1331  intmat UG = VUG[1]; // the Ufnarovskij graph
1332  ideal V = VUG[2]; // the vertices of UG (standard words with length = l-1)
1333
1334  list LG = lpId2ivLi(G);
1335  list SW = ivStandardWordsUpToLength(LG, maxDeg(G));
1336  list LV = lpId2ivLi(V);
1337
1338  // delete the 0 in SW
1339  int indexofzero = ivIndexOf(SW, 0);
1340  if (indexofzero > 0) { // should be always true when |SW| > 0
1341    SW = delete(SW, indexofzero);
1342  }
1343
1344  // check if each monomial in SW is cyclic
1345  for (int i = 1; i <= size(SW); i++) {
1346    if (!isCyclicInUfGraph(UG, LV, SW[i])) {
1347      return (0);
1348    }
1349  }
1350
1351  return (1);
1352}
1353
1354// checks whether a monomial is a cyclic monomial
1355proc isCyclicInUfGraph(intmat UG, list LV, intvec u)
1356{
1357  if (ncols(UG) == 0) {return (0);} // UG is empty
1358  if (u == 0) {return (0);} // 0 is never cyclic
1359
1360  int l = size(LV[1]) + 1;
1361
1362  int s = size(u);
1363  if (s <= l - 1) {
1364    for (int i = 1; i <= size(LV); i++) {
1365      // for all vertices where u is a suffix
1366      if(isSF(u, LV[i])) {
1367        if (existsRoute(UG, i, i)) {
1368          return (1);
1369        }
1370      }
1371    }
1372  } else { // size(u) > l - 1
1373    int m = s - l + 1;
1374
1375    // there must be a route from v0 to vm
1376    intvec v0 = u[1..(l-1)]; // first in route of u
1377    intvec vm = u[m+1..m+(l-1)]; // last in route of u
1378
1379    int iv0 = ivIndexOf(LV, v0);
1380    int ivm = ivIndexOf(LV, vm);
1381    if (iv0 <= 0 || ivm <= 0) {
1382      ERROR("u is not a standard word");
1383    }
1384
1385    return (existsRoute(UG, ivm, iv0));
1386  }
1387
1388  return (0);
1389}
1390
1391proc lpIsPrime(ideal G)
1392"USAGE: lpIsPrime(G); G an ideal in a Letterplace ring
1393RETURN: boolean
1394PURPOSE: Check whether R/<G> is prime, where R is the basering
1395ASSUME: - basering is a Letterplace ring
1396@*      - G is a Groebner basis
1397"
1398{
1399  G = lead(G);
1400  G = simplify(G, 2+4+8);
1401
1402  // check special case 1
1403  int l = 0;
1404  for (int i = 1; i <= size(G); i++) {
1405    // find the max degree in G
1406    int d = deg(G[i]);
1407    if (d > l) {
1408      l = d;
1409    }
1410
1411    // also if G is the whole ring
1412    if (leadmonom(G[i]) == 1) {
1413      return(1);
1414    }
1415  }
1416  // if longest word has length 1 we handle it as a special case
1417  if (l == 1) {
1418    return(1);
1419  }
1420
1421  list VUG = lpUfGraph(G, 1);
1422  intmat UG = VUG[1]; // the Ufnarovskij graph
1423  ideal V = VUG[2]; // the vertices of UG (standard words with length = l-1)
1424
1425  list LG = lpId2ivLi(G);
1426  list LV = lpId2ivLi(V);
1427
1428  int n = ncols(UG);
1429
1430  // 1) for each vi vj there exists a route from vi to vj (means UG is connected)
1431  for (int i = 1; i <= n; i++) {
1432    for (int j = 1; j <= n; j++) {
1433      if (!existsRoute(UG, i, j)) {
1434        return (0);
1435      }
1436    }
1437  }
1438
1439  // 2) any standard word with length < l-1 is a suffix of a vertex
1440  list SW = ivStandardWordsUpToLength(LG, maxDeg(G) - 2); // < maxDeg - 1
1441  if (size(SW) > 0 && size(LV) == 0) {return (0);}
1442  for (int i = 1; i <= size(SW); i++) {
1443    // check if SW[i] is a suffix of some LV
1444    for (int j = 1; j <= size(LV); j++) {
1445      if (!isSF(SW[i], LV[j])) {
1446        if (j == size(LV)) {
1447          return (0);
1448        }
1449      } else {
1450        break;
1451      }
1452    }
1453  }
1454
1455  return (1);
1456}
1457example {
1458  "EXAMPLE:"; echo = 2;
1459  ring r = 0,(x,y),dp;
1460  def R = makeLetterplaceRing(5);
1461  setring R;
1462  ideal G = x(1)*x(2), y(1)*y(2); // K<x,y>/<xx,yy> is prime
1463  lpIsPrime(G);
1464}
1465
1466static proc existsRoute(intmat G, int v, int u, list #)
1467"USAGE: existsRoute(G,v,u); G a graph, v and u vertices
1468NOTE: don't pass anything to # (internal use for recursion)
1469@*    routes always have at least one edge
1470"
1471{
1472  int n = ncols(G);
1473
1474  // init visited
1475  intvec visited;
1476  if (size(#) > 0) {
1477    if (v == u) {return (1);} // don't check on first call so |route| >= 1 holds
1478    visited = #[1];
1479  } else { // first call
1480    visited[n] = 0;
1481  }
1482
1483  // mark current vertex as visited
1484  visited[v] = 1;
1485
1486  // recursive DFS
1487  for (int i = 1; i <= n; i++) {
1488    if (G[v,i] && (!visited[i] || i == u)) { // i == u to allow routes from u to u
1489      if (existsRoute(G, i, u, visited)) {
1490        return (1);
1491      }
1492    }
1493  }
1494
1495  return (0);
1496}
1497
1498static proc lpUfGkDim(ideal G)
1499{
1500  G = lead(G);
1501  G = simplify(G, 2+4+8);
1502
1503  // check special case 1
1504  int l = 0;
1505  for (int i = 1; i <= size(G); i++) {
1506    // find the max degree in G
1507    int d = deg(G[i]);
1508    if (d > l) {
1509      l = d;
1510    }
1511
1512    // also if G is the whole ring return minus infinity
1513    if (leadmonom(G[i]) == 1) {
1514      return(-2); // minus infinity
1515    }
1516  }
1517  // if longest word has length 1 we handle it as a special case
1518  if (l == 1) {
1519    int n = attrib(basering, "lV"); // variable count
1520    int k = size(G);
1521    if (k == n) { // V = {1} no edges
1522      return(0);
1523    }
1524    if (k == n-1) { // V = {1} with loop
1525      return(1);
1526    }
1527    if (k <= n-2) { // V = {1} with more than one loop
1528      return(-1);
1529    }
1530  }
1531
1532  int t = rtimer; // DEBUG
1533  intmat UG = lpUfGraph(G);
1534  printf("lpUfGraph took %p", rtimer - t); // DEBUG
1535
1536  // check special case 2
1537  intmat zero[nrows(UG)][ncols(UG)];
1538  if (UG == zero) {
1539    return (0);
1540  }
1541
1542  // check special case 3
1543  UG = topologicalSort(UG);
1544
1545  if (imIsUpRightTriangle(UG)) {
1546    UG = eliminateZerosUpTriangle(UG);
1547    if (ncols(UG) == 0 || nrows(UG) == 0) { // when the diagonal was zero
1548      return (0)
1549    }
1550    return(UfGraphURTNZDGrowth(UG));
1551  }
1552
1553  // otherwise count cycles in the Ufnarovskij Graph
1554  int t = rtimer; // DEBUG
1555  int gkdim = UfGraphGrowth(UG);
1556  printf("UfGraphGrowth took %p", rtimer - t); // DEBUG
1557  return(gkdim);
1558}
1559
1560static proc UfGraphURTNZDGrowth(intmat UG) {
1561  // URTNZD = upper right triangle non zero diagonal
1562  for (int i = 1; i <= ncols(UG); i++) {
1563    UG[i,i] = 0; // remove all loops
1564  }
1565  intmat UGk = UG;
1566  intmat zero[nrows(UGk)][ncols(UGk)];
1567  int k = 1;
1568  while (UGk != zero) {
1569    UGk = UGk * UG;
1570    k++;
1571  }
1572  return (k);
1573}
1574
1575proc imIsUpRightTriangle(intmat M) {
1576  for (int i = 1; i <= nrows(M); i++) {
1577    for (int j = 1; j < i; j++) {
1578      if(M[i,j] != 0) { return (0); }
1579    }
1580  }
1581  return (1);
1582}
1583
1584static proc eliminateZerosUpTriangle(intmat G) {
1585  // G is expected to be an upper triangle matrix
1586  for (int i = ncols(G); i >= 1; i--) { // loop order is important because we delete entries
1587    if (G[i,i] == 0) { // i doesn't have a cycle
1588      for (int j = 1; j < i; j++) {
1589        if (G[j,i] == 1) { // j has an edge to i
1590          for (int k = i + 1; k <= nrows(G); k++) {
1591            if (G[i,k] == 1) {
1592              G[j,k] = G[i,k]; // give j all edges from i
1593            }
1594          }
1595        }
1596      }
1597      G = imDelRowCol(G,i,i); // remove vertex i
1598    }
1599  }
1600  return (G);
1601}
1602
1603static proc imDelRowCol(intmat M, int row, int col) {
1604  // row and col are expected to be > 0
1605  int nr = nrows(M);
1606  int nc = ncols(M);
1607  intmat Mdel[nr - 1][nc - 1];
1608  for (int i = 1; i <= nr; i++) {
1609    for (int j = 1; j <= nc; j++) {
1610      if(i != row && j != col) {
1611        int newi = i;
1612        int newj = j;
1613        if (i > row) { newi = i - 1; }
1614        if (j > col) { newj = j - 1; }
1615        Mdel[newi,newj] = M[i,j];
1616      }
1617    }
1618  }
1619  return (Mdel);
1620}
1621
1622static proc topologicalSort(intmat G) {
1623  // NOTE: ignores loops
1624  // NOTE: this takes O(|V^3|), can be optimized
1625  int n = ncols(G);
1626  for (int i = 1; i <= n; i++) { // only use the submat at i
1627    // find a vertex v in the submat at i with no incoming edges
1628    int v;
1629    for (int j = i; j <= n; j++) {
1630      int incoming = 0;
1631      for (int k = i; k <= n; k++) {
1632        if (k != j && G[k,j] == 1) {
1633          incoming = 1;
1634        }
1635      }
1636      if (incoming == 0) {
1637        v = j;
1638        break;
1639      } else {
1640        if (j == n) {
1641          // G contains at least one cycle, abort
1642          return (G);
1643        }
1644      }
1645    }
1646
1647    // swap v and i
1648    if (v != i) {
1649      G = imPermcol(G, v, i);
1650      G = imPermrow(G, v, i);
1651    }
1652  }
1653  return (G);
1654}
1655
1656static proc imPermcol (intmat A, int c1, int c2)
1657{
1658  intmat B = A;
1659  int k = nrows(B);
1660  B[1..k,c1] = A[1..k,c2];
1661  B[1..k,c2] = A[1..k,c1];
1662  return (B);
1663}
1664
1665static proc imPermrow (intmat A, int r1, int r2)
1666{
1667  intmat B = A;
1668  int k = ncols(B);
1669  B[r1,1..k] = A[r2,1..k];
1670  B[r2,1..k] = A[r1,1..k];
1671  return (B);
1672}
1673
1674static proc UfGraphGrowth(intmat UG)
1675{
1676  int n = ncols(UG); // number of vertices
1677  // iterate through all vertices
1678
1679  intvec visited;
1680  visited[n] = 0;
1681
1682  intvec cyclic;
1683  cyclic[n] = 0;
1684
1685  int maxCycleCount = 0;
1686  for (int v = 1; v <= n; v++) {
1687    int cycleCount = countCycles(UG, v, visited, cyclic, 0);
1688    if (cycleCount == -1) {
1689      return(-1);
1690    }
1691    if (cycleCount > maxCycleCount) {
1692      maxCycleCount = cycleCount;
1693    }
1694  }
1695  return(maxCycleCount);
1696}
1697
1698static proc countCycles(intmat G, int v, intvec visited, intvec cyclic, intvec path)
1699"USAGE: countCycles(G, v, visited, cyclic, path); G a Graph, v the vertex to
1700start. The parameter visited, cyclic and path should be 0.
1701RETURN: int
1702@*:     Maximal number of distinct cycles
1703PURPOSE: Calculate the maximal number of distinct cycles in a single path starting at v
1704ASSUME: Basering is a Letterplace ring
1705"
1706{
1707  // Mark the current vertex as visited
1708  visited[v] = 1;
1709
1710  // Store the current vertex in path
1711  if (path[1] == 0) {
1712    path[1] = v;
1713  } else {
1714    path[size(path) + 1] = v;
1715  }
1716
1717  int cycles = 0;
1718  for (int w = 1; w <= ncols(G); w++) {
1719    if (G[v,w] == 1) {
1720      if (visited[w] == 1) { // neuer zykel gefunden
1721        // 1. alle Knoten in path bis w ÃŒberprÃŒfen ob in cyclic
1722        for (int j = size(path); j >= 1; j--) {
1723          if(cyclic[path[j]] == 1) {
1724            // 1.1 falls ja return -1
1725            return (-1);
1726          }
1727          if (path[j] == w) {
1728            break;
1729          }
1730        }
1731
1732        // 2. ansonsten cycles++
1733        for (int j = size(path); j >= 1; j--) {
1734          // 2.2 Kanten in diesem Zykel entfernen; Knoten cyclic
1735          if (j == size(path)) { // Sonderfall bei der ersten Iteration
1736            cyclic[v] = 1;
1737            G[v, w] = 0;
1738          } else {
1739            cyclic[path[j]] = 1;
1740            G[path[j], path[j+1]] = 0;
1741          }
1742          if (path[j] == w) {
1743            break;
1744          }
1745        }
1746
1747        // 3. auf jedem dieser Knoten countCycles() aufrufen
1748        int maxCycleCount = 0;
1749        for (int j = size(path); j >= 1; j--) {
1750          int cycleCount = countCycles(G, path[j], visited, cyclic, path);
1751          if(cycleCount == -1) {
1752            return (-1);
1753          }
1754          if (cycleCount > maxCycleCount) {
1755            maxCycleCount = cycleCount;
1756          }
1757          if (path[j] == w) {
1758            break;
1759          }
1760        }
1761        if (maxCycleCount >= cycles) {
1762          cycles = maxCycleCount + 1;
1763        }
1764      } else {
1765        int cycleCount = countCycles(G, w, visited, cyclic, path);
1766        if (cycleCount == -1) {
1767          return(-1);
1768        }
1769        if (cycleCount > cycles) {
1770          cycles = cycleCount;
1771        }
1772      }
1773    }
1774  }
1775  // printf("Path: %s countCycles: %s", path, cycles); // DEBUG
1776  return(cycles);
1777}
1778
1779static proc lpUfGraph(ideal G, list #)
1780"USAGE: lpUfGraph(G); G a set of monomials in a letterplace ring, # an optional parameter to return the vertex list when set
1781RETURN: intmat
1782PURPOSE: Constructs the Ufnarovskij graph induced by G
1783@*      the adjacency matrix of the Ufnarovskij graph induced by G
1784ASSUME: - basering is a Letterplace ring
1785@*      - G are the leading monomials of a Groebner basis
1786"
1787{
1788  int l = maxDeg(G);
1789  list LG = lpId2ivLi(G);
1790  list SW = ivStandardWords(LG, l - 1); // vertices
1791  int n = size(SW);
1792  intmat UG[n][n]; // Ufnarovskij graph
1793  for (int i = 1; i <= n; i++) {
1794    for (int j = 1; j <= n; j++) {
1795      // [Studzinski page 76]
1796      intvec v = SW[i];
1797      intvec w = SW[j];
1798      intvec v_overlap;
1799      intvec w_overlap;
1800      //TODO how should the graph look like when l - 1 = 0 ?
1801      if (l - 1 == 0) {
1802        ERROR("Ufnarovskij graph not implemented for l = 1");
1803      }
1804      if (l - 1 > 1) {
1805        v_overlap = v[2 .. l-1];
1806        w_overlap = w[1 .. l-2];
1807      }
1808      intvec vw = v;
1809      vw[l] = w[l-1];
1810      if (v_overlap == w_overlap && !ivdivides(LG, vw)) {
1811        UG[i,j] = 1;
1812      }
1813    }
1814  }
1815  if (size(#) > 0) {
1816    if (typeof(#[1]) == "int") {
1817      if (#[1] == 1) {
1818        list ret = UG;
1819        ret[2] = ivL2lpI(SW); // the vertices
1820        return (ret);
1821      }
1822    }
1823  }
1824  return (UG);
1825}
1826
1827static proc maxDeg(ideal G)
1828{
1829  int l = 0;
1830  for (int i = 1; i <= size(G); i++) { // find the max degree in G
1831    int d = deg(G[i]);
1832    if (d > l) {
1833      l = d;
1834    }
1835  }
1836  return (l);
1837}
1838
1839static proc ivStandardWords(list G, int length)
1840"ASSUME: G is simplified
1841"
1842{
1843  if (length <= 0) {
1844    list words;
1845    if (length == 0 && !ivdivides(G,0)) {
1846      words[1] = 0; // iv = 0 means monom = 1
1847    }
1848    return (words); // no standard words
1849  }
1850  int lV = attrib(basering, "lV"); // variable count
1851  list prevWords = ivStandardWords(G, length - 1);
1852  list words;
1853  for (int i = 1; i <= lV; i++) {
1854    for (int j = 1; j <= size(prevWords); j++) {
1855      intvec word = prevWords[j];
1856      word[length] = i;
1857      // assumes that G is simplified!
1858      if (!ivdivides(G, word)) {
1859        words = insert(words, word);
1860      }
1861    }
1862  }
1863  return (words);
1864}
1865
1866static proc ivStandardWordsUpToLength(list G, int length)
1867"ASSUME: G is simplified
1868"
1869{
1870  list words = ivStandardWords(G,0);
1871  if (size(words) == 0) {return (words)}
1872  for (int i = 1; i <= length; i++) {
1873    words = words + ivStandardWords(G, i);
1874  }
1875  return (words);
1876}
1877
1878static proc ivdivides(list G, intvec iv) {
1879  for (int k = 1; k <= size(G); k++) {
1880    if (isIF(G[k], iv)) {
1881      return (1);
1882    } else {
1883      if (k == size(G)) {
1884        return (0);
1885      }
1886    }
1887  }
1888}
1889
1890static proc lpGraphOfNormalWords(ideal G)
1891"USAGE: lpGraphOfNormalWords(G); G a set of monomials in a letterplace ring
1892RETURN: intmat
1893PURPOSE: Constructs the graph of normal words induced by G
1894@*:      the adjacency matrix of the graph of normal words induced by G
1895ASSUME: - basering is a Letterplace ring
1896- G are the leading monomials of a Groebner basis
1897"
1898{
1899  // construct the Graph of normal words [Studzinski page 78]
1900  // construct set of vertices
1901  int v = attrib(basering,"lV"); int d = attrib(basering,"uptodeg");
1902  ideal V; poly p,q,w;
1903  ideal LG = lead(G);
1904  int i,j,k,b; intvec E,Et;
1905  for (i = 1; i <= v; i++){V = V, var(i);}
1906  for (i = 1; i <= size(LG); i++)
1907  {
1908    E = leadexp(LG[i]);
1909    if (E == intvec(0)) {V = V,monomial(intvec(0));}
1910    else
1911    {
1912      for (j = 1; j < d; j++)
1913      {
1914        Et = E[(j*v+1)..(d*v)];
1915        if (Et == intvec(0)) {break;}
1916        else {V = V, monomial(Et);}
1917      }
1918    }
1919  }
1920  V = simplify(V,2+4);
1921  printf("V = %p", V);
1922
1923
1924  // construct incidence matrix
1925
1926  list LV = lpId2ivLi(V);
1927  intvec Ip,Iw;
1928  int n = size(V);
1929  intmat T[n+1][n];
1930  for (i = 1; i <= n; i++)
1931  {
1932    // printf("for1 (i=%p, n=%p)", i, n);
1933    p = V[i]; Ip = lp2iv(p);
1934    for (j = 1; j <= n; j++)
1935    {
1936      // printf("for2 (j=%p, n=%p)", j, n);
1937      k = 1; b = 1;
1938      q = V[j];
1939      w = lpNF(lpMult(p,q),LG);
1940      if (w <> 0)
1941      {
1942        Iw = lp2iv(w);
1943        while (k <= n)
1944        {
1945          // printf("while (k=%p, n=%p)", k, n);
1946          if (isPF(LV[k],Iw) > 0)
1947          {if (isPF(LV[k],Ip) == 0) {b = 0; k = n+1;} else {k++;}
1948          }
1949          else {k++;}
1950        }
1951        T[i,j] = b;
1952        //  print("Incidence Matrix:");
1953        // print(T);
1954      }
1955    }
1956  }
1957  return(T);
1958}
1959
1960static proc lpNorGkDim(ideal G)
1961"USAGE: lpNorGkDim(G); G an ideal in a letterplace ring
1962RETURN: int
1963PURPOSE: Determines the Gelfand Kirillov dimension of A/<G>
1964@*:     -1 means it is infinite
1965ASSUME: - basering is a Letterplace ring
1966- G is a Groebner basis
1967"
1968{
1969  return(growthAlg(lpGraphOfNormalWords(G)));
1970}
1971
1972proc lpGkDim(ideal G, list#)
1973"USAGE: lpGkDim(G); G an ideal in a letterplace ring, method an
1974@*       optional integer. method = 0 uses the Ufnarovskij Graph
1975@*       and method = 1 uses the Graph of normal words to determine
1976@*       the Gelfand Kirillov dimension
1977RETURN: int
1978PURPOSE: Determines the Gelfand Kirillov dimension of A/<G>
1979@*      -1 means it is positive infinite
1980@*      -2 means it is negative infinite
1981ASSUME: - basering is a Letterplace ring
1982- G is a Groebner basis
1983"
1984{
1985  int method = 0;
1986  if (size(#) > 0) {
1987    if (typeof(#[1])=="int") {
1988      method = #[1];
1989    }
1990  }
1991
1992  if (method == 0) {
1993    return (lpUfGkDim(G));
1994  } else {
1995    return (lpNorGkDim(G));
1996  }
1997}
1998example
1999{
2000  "EXAMPLE:"; echo = 2;
2001  ring r = 0,(x,y,z),dp;
2002  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2003  R;
2004  setring R; // sets basering to Letterplace ring
2005  ideal I = z(1);//an example of infinite GK dimension
2006  lpGkDim(I);
2007  I = x(1),y(1),z(1); // gkDim = 0
2008  lpGkDim(I);
2009  I = x(1)*y(2), x(1)*z(2), z(1)*y(2), z(1)*z(2);//gkDim = 2
2010  lpGkDim(I);
2011}
2012
2013proc lpGlDimBound(ideal G)
2014"USAGE: lpGlDimBound(I); I an ideal
2015RETURN: int, an upper bound for the global dimension, -1 means infinity
2016PURPOSE: computing an upper bound for the global dimension
2017ASSUME: - basering is a Letterplace ring, G is a reduced Gröbner Basis
2018EXAMPLE: example lpGlDimBound; shows example
2019NOTE: if I = LM(I), then the global dimension is equal the Gelfand
2020@*    Kirillov dimension if it is finite
2021@*    Global dimension should be 0 for A/G = K and 1 for A/G = K<x1...xn>
2022"
2023{
2024  G = simplify(G,2); // remove zero generators
2025  // NOTE: Gl should be 0 for A/G = K and 1 for A/G = K<x1...xn>
2026  // G1 contains generators with single variable in LM
2027  ideal G1;
2028  for (int i = 1; i <= size(G); i++) {
2029    if (ord(G[i]) < 2) { // single variable in LM
2030      G1 = insertGenerator(G1,G[i]);
2031    }
2032  }
2033  G1 = simplify(G1,2); // remove zero generators
2034
2035  // G = NF(G,G1)
2036  for (int i = 1; i <= ncols(G); i++) { // do not use size() here
2037    G[i] = lpNF(G[i],G1);
2038  }
2039  G = simplify(G,2); // remove zero generators
2040
2041  // delete variables in LM(G1) from the ring
2042  def save = basering;
2043  ring R = basering;
2044  if (size(G1) > 0) {
2045    while (size(G1) > 0) {
2046      if (attrib(R, "lV") > 1) {
2047        ring R = lpDelVar(lp2iv(G1[1])[1]);
2048        ideal G1 = imap(save,G1);
2049        G1 = simplify(G1, 2); // remove zero generators
2050      } else {
2051        // only the field is left (no variables)
2052        return(0);
2053      }
2054    }
2055    ideal G = imap(save, G); // put this here, because when save == R this call would make G = 0
2056  }
2057
2058  // Li p. 184 if G = LM(G), then I = LM(I) and thus glDim = gkDim if it's finite
2059  for (int i = 1; i <= size(G); i++) {
2060    if (G[i] != lead(G[i])) {
2061      break;
2062    } else {
2063      if (i == size(G)) { // if last iteration
2064        print("Using gk dim"); // DEBUG
2065        int gkDim = lpGkDim(G);
2066        if (gkDim >= 0) {
2067          return (gkDim);
2068        }
2069      }
2070    }
2071  }
2072
2073  intmat GNC = lpGraphOfNChains(G);
2074
2075  // assuming GNC is connected
2076
2077  // TODO: maybe loop+cycle checking could be done more efficiently?
2078  if (!imHasLoops(GNC) && imIsUpRightTriangle(topologicalSort(GNC))) {
2079    // GNC is a DAG
2080    intmat GNCk = GNC;
2081    intmat zero[1][ncols(GNCk)];
2082    int k = 1;
2083    // while first row isn't empty
2084    while (GNCk[1,1..(ncols(GNCk))] != zero[1,1..(ncols(zero))]) {
2085      GNCk = GNCk * GNC;
2086      k++;
2087    }
2088    // k-1 = number of edges in longest path starting from 1
2089    return (k-1);
2090  } else {
2091    // GNC contains loops/cycles => there is always an n-chain
2092    return (-1); // infinity
2093  }
2094}
2095example
2096{
2097  "EXAMPLE:"; echo = 2;
2098  ring r = 0,(x,y),dp;
2099  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2100  setring R; // sets basering to Letterplace ring
2101  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
2102  //Groebner basis
2103  lpGlDimBound(G); // invokes procedure with Groebner basis G
2104}
2105
2106static proc imHasLoops(intmat A) {
2107  int n = ncols(A);
2108  for (int i = 1; i < n; i++) {
2109    if (A[i,i] == 1) {
2110      return (1);
2111    }
2112  }
2113  return (0);
2114}
2115
2116static proc lpGraphOfNChains(ideal G) // G must be reduced
2117{
2118  list LG = lpId2ivLi(lead(G));
2119  int n = attrib(basering, "lV");
2120  int degbound = attrib(basering, "uptodeg");
2121
2122  list V;
2123  for (int i = 0; i <= n; i++) {
2124    V[i+1] = i; // add 1 and all variables
2125  }
2126  for (int i = 1; i <= size(LG); i++) {
2127    intvec u = LG[i];
2128    for (int j = 2; j <= size(u); j++) {
2129      intvec v = u[j..size(u)];
2130      if (!contains(V, v)) {
2131        V = insert(V, v, size(V)); // add subword j..size
2132      }
2133    }
2134  }
2135  int nV = size(V);
2136  intmat GNC[nV][nV]; // graph of n-chains
2137
2138  // for vertex 1
2139  for (int i = 2; i <= n + 1; i++) {
2140    GNC[1,i] = 1; // 1 has an edge to all variables
2141  }
2142
2143  // for the other vertices
2144  for (int i = 2; i <= nV; i++) {
2145    for (int j = 2; j <= nV; j++) {
2146      intvec uv = V[i],V[j];
2147
2148      if (contains(LG, uv)) {
2149        GNC[i,j] = 1;
2150      } else {
2151        // Li p. 177
2152        // search for a right divisor 'w' of uv in G
2153        // then check if G doesn't divide the subword uv-1
2154
2155        // look for a right divisor in LG
2156        for (int k = 1; k <= size(LG); k++) {
2157          if (isSF(LG[k], uv)) {
2158            // w = LG[k]
2159            if(!ivdivides(LG, uv[1..(size(uv)-1)])) {
2160              // G doesn't divide uv-1
2161              GNC[i,j] = 1;
2162              break;
2163            }
2164          }
2165        }
2166      }
2167    }
2168  }
2169
2170  return(GNC);
2171}
2172
2173static proc contains(list L, def item)
2174{
2175  for (int i = 1; i <= size(L); i++) {
2176    if (L[i] == item) {
2177      return (1);
2178    }
2179  }
2180  return (0);
2181}
2182
2183
2184proc ivDHilbert(list L, int n, list #)
2185"USAGE: ivDHilbert(L,n[,degbound]); L a list of intmats, n an integer,
2186@*      degbound an optional integer
2187RETURN: list
2188PURPOSE:Computing the K-dimension and the Hilbert series
2189ASSUME: - basering is a Letterplace ring
2190@*      - all rows of each intmat correspond to a Letterplace monomial
2191@*      - if you specify a different degree bound degbound,
2192@*        degbound <= attrib(basering,uptodeg) holds
2193NOTE: - If L is the list returned, then L[1] is an integer corresponding to the
2194@*      dimension, L[2] is an intvec which contains the coefficients of the
2195@*      Hilbert series
2196@*    - If degbound is set, there will be a degree bound added. By default there
2197@*      is no degree bound
2198@*    - n is the number of variables
2199@*    - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th coefficient of
2200@*      the Hilbert series.
2201@*    - If the K-dimension is known to be infinite, a degree bound is needed
2202EXAMPLE: example ivDHilbert; shows examples
2203"
2204{int degbound = 0;
2205  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}}
2206  checkAssumptions(degbound,L);
2207  intvec H; int i,dimen;
2208  H = ivHilbert(L,n,degbound);
2209  for (i = 1; i <= size(H); i++){dimen = dimen + H[i];}
2210  L = dimen,H;
2211  return(L);
2212}
2213example
2214{
2215  "EXAMPLE:"; echo = 2;
2216  ring r = 0,(x,y),dp;
2217  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2218  R;
2219  setring R; // sets basering to Letterplace ring
2220  //some intmats, which contain monomials in intvec representation as rows
2221  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2222  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2223  print(I1);
2224  print(I2);
2225  print(J1);
2226  print(J2);
2227  list G = I1,I2; // ideal, which is already a Groebner basis
2228  list I = J1,J2; // ideal, which is already a Groebner basis
2229  //the procedure without a degree bound
2230  ivDHilbert(G,2);
2231  // the procedure with degree bound 5
2232  ivDHilbert(I,2,5);
2233}
2234
2235proc ivDHilbertSickle(list L, int n, list #)
2236"USAGE: ivDHilbertSickle(L,n[,degbound]); L a list of intmats, n an integer,
2237@*      degbound an optional integer
2238RETURN: list
2239PURPOSE:Computing K-dimension, Hilbert series and mistletoes
2240ASSUME: - basering is a Letterplace ring.
2241@*      - All rows of each intmat correspond to a Letterplace monomial.
2242@*      - If you specify a different degree bound degbound,
2243@*        degbound <= attrib(basering,uptodeg) holds.
2244NOTE: - If L is the list returned, then L[1] is an integer, L[2] is an intvec
2245@*      which contains the coefficients of the Hilbert series and L[3]
2246@*      is a list, containing the mistletoes as intvecs.
2247@*    - If degbound is set, a degree bound will be added. By default there
2248@*      is no degree bound.
2249@*    - n is the number of variables.
2250@*    - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th
2251@*      coefficient of the Hilbert series.
2252@*    - If the K-dimension is known to be infinite, a degree bound is needed
2253EXAMPLE: example ivDHilbertSickle; shows examples
2254"
2255{int degbound = 0;
2256  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}}
2257  checkAssumptions(degbound,L);
2258  int i,dimen; list R;
2259  R = ivSickleHil(L,n,degbound);
2260  for (i = 1; i <= size(R[1]); i++){dimen = dimen + R[1][i];}
2261  R[3] = R[2]; R[2] = R[1]; R[1] = dimen;
2262  return(R);
2263}
2264example
2265{
2266  "EXAMPLE:"; echo = 2;
2267  ring r = 0,(x,y),dp;
2268  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2269  R;
2270  setring R; // sets basering to Letterplace ring
2271  //some intmats, which contain monomials in intvec representation as rows
2272  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2273  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2274  print(I1);
2275  print(I2);
2276  print(J1);
2277  print(J2);
2278  list G = I1,I2;// ideal, which is already a Groebner basis
2279  list I = J1,J2; // ideal, which is already a Groebner basis
2280  ivDHilbertSickle(G,2); // invokes the procedure without a degree bound
2281  ivDHilbertSickle(I,2,3); // invokes the procedure with degree bound 3
2282}
2283
2284proc ivDimCheck(list L, int n)
2285"USAGE: ivDimCheck(L,n); L a list of intmats, n an integer
2286RETURN: int, 0 if the dimension is finite, or 1 otherwise
2287PURPOSE:Decides, whether the K-dimension is finite or not
2288ASSUME: - basering is a Letterplace ring.
2289@*      - All rows of each intmat correspond to a Letterplace monomial.
2290NOTE:   - n is the number of variables.
2291EXAMPLE: example ivDimCheck; shows examples
2292"
2293{checkAssumptions(0,L);
2294  int i,r;
2295  intvec P,H;
2296  for (i = 1; i <= size(L); i++)
2297  {P[i] = ncols(L[i]);
2298    if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}}
2299  }
2300  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2301  kill H;
2302  intmat S; int sd,ld; intvec V;
2303  sd = P[1]; ld = P[1];
2304  for (i = 2; i <= size(P); i++)
2305  {if (P[i] < sd) {sd = P[i];}
2306    if (P[i] > ld) {ld = P[i];}
2307  }
2308  sd = (sd - 1); ld = ld - 1;
2309  if (ld == 0) { return(allVars(L,P,n));}
2310  if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2311  else {S = createStartMat(sd,n);}
2312  module M;
2313  for (i = 1; i <= nrows(S); i++)
2314  {V = S[i,1..ncols(S)];
2315    if (findCycle(V,L,P,n,ld,M)) {r = 1; break;}
2316  }
2317  return(r);
2318}
2319example
2320{
2321  "EXAMPLE:"; echo = 2;
2322  ring r = 0,(x,y),dp;
2323  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2324  R;
2325  setring R; // sets basering to Letterplace ring
2326  //some intmats, which contain monomials in intvec representation as rows
2327  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2328  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2329  print(I1);
2330  print(I2);
2331  print(J1);
2332  print(J2);
2333  list G = I1,I2;// ideal, which is already a Groebner basis
2334  list I = J1,J2; // ideal, which is already a Groebner basis and which
2335  ivDimCheck(G,2); // invokes the procedure, factor is of finite K-dimension
2336  ivDimCheck(I,2); // invokes the procedure, factor is not of finite K-dimension
2337}
2338
2339proc ivHilbert(list L, int n, list #)
2340"USAGE: ivHilbert(L,n[,degbound]); L a list of intmats, n an integer,
2341@*      degbound an optional integer
2342RETURN: intvec, containing the coefficients of the Hilbert series
2343PURPOSE:Computing the Hilbert series
2344ASSUME: - basering is a Letterplace ring.
2345@*      - all rows of each intmat correspond to a Letterplace monomial
2346@*      - if you specify a different degree bound degbound,
2347@*       degbound <= attrib(basering,uptodeg) holds.
2348NOTE: - If degbound is set, a degree bound  will be added. By default there
2349@*      is no degree bound.
2350@*    - n is the number of variables.
2351@*    - If I is returned, then I[k] is the (k-1)-th coefficient of the Hilbert
2352@*      series.
2353@*    - If the K-dimension is known to be infinite, a degree bound is needed
2354EXAMPLE: example ivHilbert; shows examples
2355"
2356{int degbound = 0;
2357  if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}}
2358  intvec P,H; int i;
2359  for (i = 1; i <= size(L); i++)
2360  {P[i] = ncols(L[i]);
2361    if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}}
2362  }
2363  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2364  H[1] = 1;
2365  checkAssumptions(degbound,L);
2366  if (degbound == 0)
2367  {int sd;
2368    intmat S;
2369    sd = P[1];
2370    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2371    sd = (sd - 1);
2372    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2373    else {S = createStartMat(sd,n);}
2374    if (intvec(S) == 0) {return(H);}
2375    for (i = 1; i <= sd; i++) {H = H,(n^i);}
2376    for (i = 1; i <= nrows(S); i++)
2377    {intvec St = S[i,1..ncols(S)];
2378      H = findHCoeff(St,n,L,P,H);
2379      kill St;
2380    }
2381    return(H);
2382  }
2383  else
2384  {for (i = 1; i <= size(P); i++)
2385    {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}}
2386    int sd;
2387    intmat S;
2388    sd = P[1];
2389    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2390    sd = (sd - 1);
2391    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2392    else {S = createStartMat(sd,n);}
2393    if (intvec(S) == 0) {return(H);}
2394    for (i = 1; i <= sd; i++) {H = H,(n^i);}
2395    for (i = 1; i <= nrows(S); i++)
2396    {intvec St = S[i,1..ncols(S)];
2397      H = findHCoeff(St,n,L,P,H,degbound);
2398      kill St;
2399    }
2400    return(H);
2401  }
2402}
2403example
2404{
2405  "EXAMPLE:"; echo = 2;
2406  ring r = 0,(x,y),dp;
2407  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2408  R;
2409  setring R; // sets basering to Letterplace ring
2410  //some intmats, which contain monomials in intvec representation as rows
2411  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2412  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2413  print(I1);
2414  print(I2);
2415  print(J1);
2416  print(J2);
2417  list G = I1,I2; // ideal, which is already a Groebner basis
2418  list I = J1,J2; // ideal, which is already a Groebner basis
2419  ivHilbert(G,2); // invokes the procedure without any degree bound
2420  ivHilbert(I,2,5); // invokes the procedure with degree bound 5
2421}
2422
2423
2424proc ivKDim(list L, int n, list #)
2425"USAGE: ivKDim(L,n[,degbound]); L a list of intmats,
2426@*      n an integer, degbound an optional integer
2427RETURN: int, the K-dimension of A/<L>
2428PURPOSE:Computing the K-dimension of A/<L>
2429ASSUME: - basering is a Letterplace ring.
2430@*      - all rows of each intmat correspond to a Letterplace monomial
2431@*      - if you specify a different degree bound degbound,
2432@*        degbound <= attrib(basering,uptodeg) holds.
2433NOTE: - If degbound is set, a degree bound will be added. By default there
2434@*      is no degree bound.
2435@*    - n is the number of variables.
2436@*    - If the K-dimension is known to be infinite, a degree bound is needed
2437EXAMPLE: example ivKDim; shows examples
2438"
2439{int degbound = 0;
2440  if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}}
2441  intvec P,H; int i;
2442  for (i = 1; i <= size(L); i++)
2443  {P[i] = ncols(L[i]);
2444    if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}}
2445  }
2446  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2447  kill H;
2448  checkAssumptions(degbound,L);
2449  if (degbound == 0)
2450  {int sd; int dimen = 1;
2451    intmat S;
2452    sd = P[1];
2453    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2454    sd = (sd - 1);
2455    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2456    else {S = createStartMat(sd,n);}
2457    if (intvec(S) == 0) {return(dimen);}
2458    for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);}
2459    for (i = 1; i <= nrows(S); i++)
2460    {intvec St = S[i,1..ncols(S)];
2461      dimen = dimen + findDimen(St,n,L,P);
2462      kill St;
2463    }
2464    return(dimen);
2465  }
2466  else
2467  {for (i = 1; i <= size(P); i++)
2468    {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}}
2469    int sd; int dimen = 1;
2470    intmat S;
2471    sd = P[1];
2472    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2473    sd = (sd - 1);
2474    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2475    else {S = createStartMat(sd,n);}
2476    if (intvec(S) == 0) {return(dimen);}
2477    for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);}
2478    for (i = 1; i <= nrows(S); i++)
2479    {intvec St = S[i,1..ncols(S)];
2480      dimen = dimen + findDimen(St,n,L,P, degbound);
2481      kill St;
2482    }
2483    return(dimen);
2484  }
2485}
2486example
2487{
2488  "EXAMPLE:"; echo = 2;
2489  ring r = 0,(x,y),dp;
2490  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2491  R;
2492  setring R; // sets basering to Letterplace ring
2493  //some intmats, which contain monomials in intvec representation as rows
2494  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2495  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2496  print(I1);
2497  print(I2);
2498  print(J1);
2499  print(J2);
2500  list G = I1,I2; // ideal, which is already a Groebner basis
2501  list I = J1,J2; // ideal, which is already a Groebner basis
2502  ivKDim(G,2); // invokes the procedure without any degree bound
2503  ivKDim(I,2,5); // invokes the procedure with degree bound 5
2504}
2505
2506proc ivMis2Base(list M)
2507"USAGE: ivMis2Base(M); M a list of intvecs
2508RETURN: ideal, a K-base of the given algebra
2509PURPOSE:Computing the K-base out of given mistletoes
2510ASSUME: - The mistletoes have to be ordered lexicographically -> OrdMisLex.
2511@*        Otherwise there might some elements missing.
2512@*      - basering is a Letterplace ring.
2513@*      - mistletoes are stored as intvecs, as described in the overview
2514EXAMPLE: example ivMis2Base; shows examples
2515"
2516{
2517  //checkAssumptions(0,M);
2518  intvec L,A;
2519  if (size(M) == 0){ERROR("There are no mistletoes, so it appears your dimension is infinite!");}
2520  if (isInList(L,M) > 0) {print("1 is a mistletoe, therefore 1 is the only basis element"); return(list(intvec(0)));}
2521  int i,j,d,s;
2522  list Rt;
2523  Rt[1] = intvec(0);
2524  L = M[1];
2525  for (i = size(L); 1 <= i; i--) {Rt = insert(Rt,intvec(L[1..i]));}
2526  for (i = 2; i <= size(M); i++)
2527  {A = M[i]; L = M[i-1];
2528    s = size(A);
2529    if (s > size(L))
2530    {d = size(L);
2531      for (j = s; j > d; j--) {Rt = insert(Rt,intvec(A[1..j]));}
2532      A = A[1..d];
2533    }
2534    if (size(L) > s){L = L[1..s];}
2535    while (A <> L)
2536    {Rt = insert(Rt, intvec(A));
2537      if (size(A) > 1)
2538      {A = A[1..(size(A)-1)];
2539        L = L[1..(size(L)-1)];
2540      }
2541      else {break;}
2542    }
2543  }
2544  return(Rt);
2545}
2546example
2547{
2548  "EXAMPLE:"; echo = 2;
2549  ring r = 0,(x,y),dp;
2550  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2551  R;
2552  setring R; // sets basering to Letterplace ring
2553  intvec i1 = 1,2; intvec i2 = 2,1,2;
2554  // the mistletoes are xy and yxy, which are already ordered lexicographically
2555  list L = i1,i2;
2556  ivMis2Base(L); // returns the basis of the factor algebra
2557}
2558
2559
2560proc ivMis2Dim(list M)
2561"USAGE: ivMis2Dim(M); M a list of intvecs
2562RETURN: int, the K-dimension of the given algebra
2563PURPOSE:Computing the K-dimension out of given mistletoes
2564ASSUME: - The mistletoes have to be ordered lexicographically -> OrdMisLex.
2565@*        Otherwise the returned value may differ from the K-dimension.
2566@*      - basering is a Letterplace ring.
2567EXAMPLE: example ivMis2Dim; shows examples
2568"
2569{checkAssumptions(0,M);
2570  intvec L;
2571  if (size(M) == 0){ERROR("There are no mistletoes, so it appears your dimension is infinite!");}
2572  if (isInList(L,M) > 0) {print("1 is a mistletoe, therefore dim = 1"); return(1);}
2573  int i,j,d,s;
2574  j = 1;
2575  d = 1 + size(M[1]);
2576  for (i = 1; i < size(M); i++)
2577  {s = size(M[i]); if (s > size(M[i+1])){s = size(M[i+1]);}
2578    while ((M[i][j] == M[i+1][j]) && (j <= s)){j = j + 1;}
2579    d = d + size(M[i+1])- j + 1;
2580  }
2581  return(d);
2582}
2583example
2584{
2585  "EXAMPLE:"; echo = 2;
2586  ring r = 0,(x,y),dp;
2587  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2588  R;
2589  setring R; // sets basering to Letterplace ring
2590  intvec i1 = 1,2; intvec i2 = 2,1,2;
2591  // the mistletoes are xy and yxy, which are already ordered lexicographically
2592  list L = i1,i2;
2593  ivMis2Dim(L); // returns the dimension of the factor algebra
2594}
2595
2596proc ivOrdMisLex(list M)
2597"USAGE: ivOrdMisLex(M); M a list of intvecs
2598RETURN: list, containing the ordered intvecs of M
2599PURPOSE:Orders a given set of mistletoes lexicographically
2600ASSUME: - basering is a Letterplace ring.
2601- intvecs correspond to monomials
2602NOTE:   - This is preprocessing, it's not needed if the mistletoes are returned
2603@*        from the sickle algorithm.
2604@*      - Each entry of the list returned is an intvec.
2605EXAMPLE: example ivOrdMisLex; shows examples
2606"
2607{checkAssumptions(0,M);
2608  return(sort(M)[1]);
2609}
2610example
2611{
2612  "EXAMPLE:"; echo = 2;
2613  ring r = 0,(x,y),dp;
2614  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2615  setring R; // sets basering to Letterplace ring
2616  intvec i1 = 1,2,1; intvec i2 = 2,2,1; intvec i3 = 1,1; intvec i4 = 2,1,1,1;
2617  // the corresponding monomials are xyx,y^2x,x^2,yx^3
2618  list M = i1,i2,i3,i4;
2619  M;
2620  ivOrdMisLex(M);// orders the list of monomials
2621}
2622
2623proc ivSickle(list L, int n, list #)
2624"USAGE: ivSickle(L,n,[degbound]); L a list of intmats, n an int, degbound an
2625@*      optional integer
2626RETURN: list, containing intvecs, the mistletoes of A/<L>
2627PURPOSE:Computing the mistletoes for a given Groebner basis L
2628ASSUME: - basering is a Letterplace ring.
2629@*      - all rows of each intmat correspond to a Letterplace monomial
2630@*      - if you specify a different degree bound degbound,
2631@*        degbound <= attrib(basering,uptodeg) holds.
2632NOTE: - If degbound is set, a degree bound will be added. By default there
2633@*      is no degree bound.
2634@*    - n is the number of variables.
2635@*    - If the K-dimension is known to be infinite, a degree bound is needed
2636EXAMPLE: example ivSickle; shows examples
2637"
2638{list M;
2639  int degbound = 0;
2640  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}}
2641  int i;
2642  intvec P,H;
2643  for (i = 1; i <= size(L); i++)
2644  {P[i] = ncols(L[i]);
2645    if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}}
2646  }
2647  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2648  kill H;
2649  checkAssumptions(degbound,L);
2650  if (degbound == 0)
2651  {intmat S; int sd;
2652    sd = P[1];
2653    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2654    sd = (sd - 1);
2655    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2656    else {S = createStartMat(sd,n);}
2657    if (intvec(S) == 0) {return(list (intvec(0)));}
2658    for (i = 1; i <= nrows(S); i++)
2659    {intvec St = S[i,1..ncols(S)];
2660      M = M + findmistletoes(St,n,L,P);
2661      kill St;
2662    }
2663    return(M);
2664  }
2665  else
2666  {for (i = 1; i <= size(P); i++)
2667    {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}}
2668    intmat S; int sd;
2669    sd = P[1];
2670    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2671    sd = (sd - 1);
2672    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2673    else {S = createStartMat(sd,n);}
2674    if (intvec(S) == 0) {return(list (intvec(0)));}
2675    for (i = 1; i <= nrows(S); i++)
2676    {intvec St = S[i,1..ncols(S)];
2677      M = M + findmistletoes(St,n,L,P,degbound);
2678      kill St;
2679    }
2680    return(M);
2681  }
2682}
2683example
2684{
2685  "EXAMPLE:"; echo = 2;
2686  ring r = 0,(x,y),dp;
2687  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2688  setring R; // sets basering to Letterplace ring
2689  //some intmats, which contain monomials in intvec representation as rows
2690  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2691  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2692  print(I1);
2693  print(I2);
2694  print(J1);
2695  print(J2);
2696  list G = I1,I2; // ideal, which is already a Groebner basis
2697  list I =  J1,J2; // ideal, which is already a Groebner basis
2698  ivSickle(G,2); // invokes the procedure without any degree bound
2699  ivSickle(I,2,5); // invokes the procedure with degree bound 5
2700}
2701
2702proc ivSickleDim(list L, int n, list #)
2703"USAGE: ivSickleDim(L,n[,degbound]); L a list of intmats, n an integer, degbound
2704@*      an optional integer
2705RETURN: list
2706PURPOSE:Computing mistletoes and the K-dimension
2707ASSUME: - basering is a Letterplace ring.
2708@*      - all rows of each intmat correspond to a Letterplace monomial
2709@*      - if you specify a different degree bound degbound,
2710@*        degbound <= attrib(basering,uptodeg) holds.
2711NOTE: - If L is the list returned, then L[1] is an integer, L[2] is a list,
2712@*      containing the mistletoes as intvecs.
2713@*    - If degbound is set, a degree bound will be added. By default there
2714@*      is no degree bound.
2715@*    - n is the number of variables.
2716@*    - If the K-dimension is known to be infinite, a degree bound is needed
2717EXAMPLE: example ivSickleDim; shows examples
2718"
2719{list M;
2720  int degbound = 0;
2721  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}}
2722  int i,dimen; list R;
2723  intvec P,H;
2724  for (i = 1; i <= size(L); i++)
2725  {P[i] = ncols(L[i]);
2726    if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial, dimension equals zero");}}
2727  }
2728  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2729  kill H;
2730  checkAssumptions(degbound,L);
2731  if (degbound == 0)
2732  {int sd; dimen = 1;
2733    intmat S;
2734    sd = P[1];
2735    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2736    sd = (sd - 1);
2737    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2738    else {S = createStartMat(sd,n);}
2739    if (intvec(S) == 0) {return(list(dimen,list(intvec(0))));}
2740    for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);}
2741    R[1] = dimen;
2742    for (i = 1; i <= nrows(S); i++)
2743    {intvec St = S[i,1..ncols(S)];
2744      R = findMisDim(St,n,L,P,R);
2745      kill St;
2746    }
2747    return(R);
2748  }
2749  else
2750  {for (i = 1; i <= size(P); i++)
2751    {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}}
2752    int sd; dimen = 1;
2753    intmat S;
2754    sd = P[1];
2755    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2756    sd = (sd - 1);
2757    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2758    else {S = createStartMat(sd,n);}
2759    if (intvec(S) == 0) {return(list(dimen,list(intvec(0))));}
2760    for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);}
2761    R[1] = dimen;
2762    for (i = 1; i <= nrows(S); i++)
2763    {intvec St = S[i,1..ncols(S)];
2764      R = findMisDim(St,n,L,P,R,degbound);
2765      kill St;
2766    }
2767    return(R);
2768  }
2769}
2770example
2771{
2772  "EXAMPLE:"; echo = 2;
2773  ring r = 0,(x,y),dp;
2774  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2775  setring R; // sets basering to Letterplace ring
2776  //some intmats, which contain monomials in intvec representation as rows
2777  intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3]  = 1,2,1;
2778  intmat J1 [1][2] =  1,1; intmat J2 [2][3] = 2,1,2,1,2,1;
2779  print(I1);
2780  print(I2);
2781  print(J1);
2782  print(J2);
2783  list G = I1,I2;// ideal, which is already a Groebner basis
2784  list I =  J1,J2; // ideal, which is already a Groebner basis
2785  ivSickleDim(G,2); // invokes the procedure without any degree bound
2786  ivSickleDim(I,2,5); // invokes the procedure with degree bound 5
2787}
2788
2789proc ivSickleHil(list L, int n, list #)
2790"USAGE:ivSickleHil(L,n[,degbound]); L a list of intmats, n an integer,
2791@*     degbound an optional integer
2792RETURN: list
2793PURPOSE:Computing the mistletoes and the Hilbert series
2794ASSUME: - basering is a Letterplace ring.
2795@*      - all rows of each intmat correspond to a Letterplace monomial
2796@*      - if you specify a different degree bound degbound,
2797@*        degbound <= attrib(basering,uptodeg) holds.
2798NOTE: - If L is the list returned, then L[1] is an intvec, L[2] is a list,
2799@*      containing the mistletoes as intvecs.
2800@*    - If degbound is set, a degree bound will be added. By default there
2801@*      is no degree bound.
2802@*    - n is the number of variables.
2803@*    - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th
2804@*      coefficient of the Hilbert series.
2805@*    - If the K-dimension is known to be infinite, a degree bound is needed
2806EXAMPLE: example ivSickleHil; shows examples
2807"
2808{int degbound = 0;
2809  if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}}
2810  intvec P,H; int i; list R;
2811  for (i = 1; i <= size(L); i++)
2812  {P[i] = ncols(L[i]);
2813    if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}}
2814  }
2815  if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");}
2816  H[1] = 1;
2817  checkAssumptions(degbound,L);
2818  if (degbound == 0)
2819  {int sd;
2820    intmat S;
2821    sd = P[1];
2822    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2823    sd = (sd - 1);
2824    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2825    else {S = createStartMat(sd,n);}
2826    if (intvec(S) == 0) {return(list(H,list(intvec (0))));}
2827    for (i = 1; i <= sd; i++) {H = H,(n^i);}
2828    R[1] = H; kill H;
2829    for (i = 1; i <= nrows(S); i++)
2830    {intvec St = S[i,1..ncols(S)];
2831      R = findHCoeffMis(St,n,L,P,R);
2832      kill St;
2833    }
2834    return(R);
2835  }
2836  else
2837  {for (i = 1; i <= size(P); i++)
2838    {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}}
2839    int sd;
2840    intmat S;
2841    sd = P[1];
2842    for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}}
2843    sd = (sd - 1);
2844    if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}}
2845    else {S = createStartMat(sd,n);}
2846    if (intvec(S) == 0) {return(list(H,list(intvec(0))));}
2847    for (i = 1; i <= sd; i++) {H = H,(n^i);}
2848    R[1] = H; kill H;
2849    for (i = 1; i <= nrows(S); i++)
2850    {intvec St = S[i,1..ncols(S)];
2851      R = findHCoeffMis(St,n,L,P,R,degbound);
2852      kill St;
2853    }
2854    return(R);
2855  }
2856}
2857example
2858{
2859  "EXAMPLE:"; echo = 2;
2860  ring r = 0,(x,y),dp;
2861  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2862  setring R; // sets basering to Letterplace ring
2863  //some intmats, which contain monomials in intvec representation as rows
2864  intmat I1[2][2] = 1,1,2,2; intmat I2[1][3]  = 1,2,1;
2865  intmat J1[1][2] =  1,1; intmat J2[2][3] = 2,1,2,1,2,1;
2866  print(I1);
2867  print(I2);
2868  print(J1);
2869  print(J2);
2870  list G = I1,I2;// ideal, which is already a Groebner basis
2871  list I =  J1,J2; // ideal, which is already a Groebner basis
2872  ivSickleHil(G,2); // invokes the procedure without any degree bound
2873  ivSickleHil(I,2,5); // invokes the procedure with degree bound 5
2874}
2875
2876proc lpDHilbert(ideal G, list #)
2877"USAGE: lpDHilbert(G[,degbound,n]); G an ideal, degbound, n optional integers
2878RETURN: list
2879PURPOSE:Computing K-dimension and Hilbert series, starting with a lp-ideal
2880ASSUME: - basering is a Letterplace ring.
2881@*      - if you specify a different degree bound degbound,
2882@*        degbound <= attrib(basering,uptodeg) holds.
2883NOTE: - If L is the list returned, then L[1] is an integer corresponding to the
2884@*      dimension, L[2] is an intvec which contains the coefficients of the
2885@*      Hilbert series
2886@*    - If degbound is set, there will be a degree bound added. 0 means no
2887@*      degree bound. Default: attrib(basering,uptodeg).
2888@*    - n can be set to a different number of variables.
2889@*      Default: n = attrib(basering, lV).
2890@*    - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th
2891@*      coefficient of the Hilbert series.
2892@*    - If the K-dimension is known to be infinite, a degree bound is needed
2893EXAMPLE: example lpDHilbert; shows examples
2894"
2895{int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV");
2896  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
2897  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
2898  list L;
2899  L = lp2ivId(normalize(lead(G)));
2900  return(ivDHilbert(L,n,degbound));
2901}
2902example
2903{
2904  "EXAMPLE:"; echo = 2;
2905  ring r = 0,(x,y),dp;
2906  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2907  setring R; // sets basering to Letterplace ring
2908  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
2909  //Groebner basis
2910  lpDHilbert(G,5,2); // invokes procedure with degree bound 5 and 2 variables
2911  // note that the optional parameters are not necessary, due to the finiteness
2912  // of the K-dimension of the factor algebra
2913  lpDHilbert(G); // procedure with ring parameters
2914  lpDHilbert(G,0); // procedure without degreebound
2915}
2916
2917proc lpDHilbertSickle(ideal G, list #)
2918"USAGE: lpDHilbertSickle(G[,degbound,n]); G an ideal, degbound, n optional
2919@*      integers
2920RETURN: list
2921PURPOSE:Computing K-dimension, Hilbert series and mistletoes at once
2922ASSUME: - basering is a Letterplace ring.
2923@*      - if you specify a different degree bound degbound,
2924@*        degbound <= attrib(basering,uptodeg) holds.
2925NOTE: - If L is the list returned, then L[1] is an integer, the K-dimension,
2926@*      L[2] is an intvec, the Hilbert series and L[3] is an ideal,
2927@*      the mistletoes
2928@*    - If degbound is set, there will be a degree bound added. 0 means no
2929@*      degree bound. Default: attrib(basering,uptodeg).
2930@*    - n can be set to a different number of variables.
2931@*      Default: n = attrib(basering, lV).
2932@*    - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th
2933@*      coefficient of the Hilbert series.
2934@*    - If the K-dimension is known to be infinite, a degree bound is needed
2935EXAMPLE: example lpDHilbertSickle; shows examples
2936"
2937{int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV");
2938  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
2939  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
2940  list L;
2941  L = lp2ivId(normalize(lead(G)));
2942  L = ivDHilbertSickle(L,n,degbound);
2943  L[3] =  ivL2lpI(L[3]);
2944  return(L);
2945}
2946example
2947{
2948  "EXAMPLE:"; echo = 2;
2949  ring r = 0,(x,y),dp;
2950  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2951  setring R; // sets basering to Letterplace ring
2952  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
2953  //Groebner basis
2954  lpDHilbertSickle(G,5,2); //invokes procedure with degree bound 5 and 2 variables
2955  // note that the optional parameters are not necessary, due to the finiteness
2956  // of the K-dimension of the factor algebra
2957  lpDHilbertSickle(G); // procedure with ring parameters
2958  lpDHilbertSickle(G,0); // procedure without degreebound
2959}
2960
2961proc lpHilbert(ideal G, list #)
2962"USAGE: lpHilbert(G[,degbound,n]); G an ideal, degbound, n optional integers
2963RETURN: intvec, containing the coefficients of the Hilbert series
2964PURPOSE:Computing the Hilbert series
2965ASSUME: - basering is a Letterplace ring.
2966@*      - if you specify a different degree bound degbound,
2967@*        degbound <= attrib(basering,uptodeg) holds.
2968NOTE: - If degbound is set, there will be a degree bound added. 0 means no
2969@*      degree bound. Default: attrib(basering,uptodeg).
2970@*    - n is the number of variables, which can be set to a different number.
2971@*      Default: attrib(basering, lV).
2972@*    - If I is returned, then I[k] is the (k-1)-th coefficient of the Hilbert
2973@*      series.
2974@*    - If the K-dimension is known to be infinite, a degree bound is needed
2975EXAMPLE: example lpHilbert; shows examples
2976"
2977{int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV");
2978  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
2979  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
2980  list L;
2981  L = lp2ivId(normalize(lead(G)));
2982  return(ivHilbert(L,n,degbound));
2983}
2984example
2985{
2986  "EXAMPLE:"; echo = 2;
2987  ring r = 0,(x,y),dp;
2988  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
2989  setring R; // sets basering to Letterplace ring
2990  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
2991  //Groebner basis
2992  lpHilbert(G,5,2); // invokes procedure with degree bound 5 and 2 variables
2993  // note that the optional parameters are not necessary, due to the finiteness
2994  // of the K-dimension of the factor algebra
2995  lpDHilbert(G); // procedure with ring parameters
2996  lpDHilbert(G,0); // procedure without degreebound
2997}
2998
2999proc lpDimCheck(ideal G)
3000"USAGE: lpDimCheck(G);
3001RETURN: int, 1 if K-dimension of the factor algebra is infinite, 0 otherwise
3002PURPOSE:Checking a factor algebra for finiteness of the K-dimension
3003ASSUME: - basering is a Letterplace ring.
3004EXAMPLE: example lpDimCheck; shows examples
3005"
3006{int n = attrib(basering,"lV");
3007  list L;
3008  ideal R;
3009  R = normalize(lead(G));
3010  L = lp2ivId(R);
3011  return(ivDimCheck(L,n));
3012}
3013example
3014{
3015  "EXAMPLE:"; echo = 2;
3016  ring r = 0,(x,y),dp;
3017  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3018  setring R; // sets basering to Letterplace ring
3019  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3);
3020  // Groebner basis
3021  ideal I = x(1)*x(2), y(1)*x(2)*y(3), x(1)*y(2)*x(3);
3022  // Groebner basis
3023  lpDimCheck(G); // invokes procedure, factor algebra is of finite K-dimension
3024  lpDimCheck(I); // invokes procedure, factor algebra is of infinite Kdimension
3025}
3026
3027proc lpKDim(ideal G, list #)
3028"USAGE: lpKDim(G[,degbound, n]); G an ideal, degbound, n optional integers
3029RETURN: int, the K-dimension of the factor algebra
3030PURPOSE:Computing the K-dimension of a factor algebra, given via an ideal
3031ASSUME: - basering is a Letterplace ring
3032@*      - if you specify a different degree bound degbound,
3033@*        degbound <= attrib(basering,uptodeg) holds.
3034NOTE: - If degbound is set, there will be a degree bound added. 0 means no
3035@*      degree bound. Default: attrib(basering, uptodeg).
3036@*    - n is the number of variables, which can be set to a different number.
3037@*      Default: attrib(basering, lV).
3038@*    - If the K-dimension is known to be infinite, a degree bound is needed
3039EXAMPLE: example lpKDim; shows examples
3040"
3041{int degbound = attrib(basering, "uptodeg");int n = attrib(basering, "lV");
3042  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
3043  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
3044  list L;
3045  L = lp2ivId(normalize(lead(G)));
3046  return(ivKDim(L,n,degbound));
3047}
3048example
3049{
3050  "EXAMPLE:"; echo = 2;
3051  ring r = 0,(x,y),dp;
3052  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3053  setring R; // sets basering to Letterplace ring
3054  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3);
3055  // ideal G contains a Groebner basis
3056  lpKDim(G); //procedure invoked with ring parameters
3057  // the factor algebra is finite, so the degree bound given by the Letterplace
3058  // ring is not necessary
3059  lpKDim(G,0); // procedure without any degree bound
3060}
3061
3062proc lpMis2Base(ideal M)
3063"USAGE: lpMis2Base(M); M an ideal
3064RETURN: ideal, a K-basis of the factor algebra
3065PURPOSE:Computing a K-basis out of given mistletoes
3066ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal.
3067@*      - M contains only monomials
3068NOTE:   - The mistletoes have to be ordered lexicographically -> OrdMisLex.
3069EXAMPLE: example lpMis2Base; shows examples
3070"
3071{list L;
3072  L = lpId2ivLi(M);
3073  return(ivL2lpI(ivMis2Base(L)));
3074}
3075example
3076{
3077  "EXAMPLE:"; echo = 2;
3078  ring r = 0,(x,y),dp;
3079  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3080  setring R; // sets basering to Letterplace ring
3081  ideal L = x(1)*y(2),y(1)*x(2)*y(3);
3082  // ideal containing the mistletoes
3083  lpMis2Base(L); // returns the K-basis of the factor algebra
3084}
3085
3086proc lpMis2Dim(ideal M)
3087"USAGE: lpMis2Dim(M); M an ideal
3088RETURN: int, the K-dimension of the factor algebra
3089PURPOSE:Computing the K-dimension out of given mistletoes
3090ASSUME: - basering is a Letterplace ring.
3091@*      - M contains only monomials
3092NOTE:   - The mistletoes have to be ordered lexicographically -> OrdMisLex.
3093EXAMPLE: example lpMis2Dim; shows examples
3094"
3095{list L;
3096  L = lpId2ivLi(M);
3097  return(ivMis2Dim(L));
3098}
3099example
3100{
3101  "EXAMPLE:"; echo = 2;
3102  ring r = 0,(x,y),dp;
3103  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3104  setring R; // sets basering to Letterplace ring
3105  ideal L = x(1)*y(2),y(1)*x(2)*y(3);
3106  // ideal containing the mistletoes
3107  lpMis2Dim(L); // returns the K-dimension of the factor algebra
3108}
3109
3110proc lpOrdMisLex(ideal M)
3111"USAGE: lpOrdMisLex(M); M an ideal of mistletoes
3112RETURN: ideal, containing the mistletoes, ordered lexicographically
3113PURPOSE:A given set of mistletoes is ordered lexicographically
3114ASSUME: - basering is a Letterplace ring.
3115NOTE:   This is preprocessing, it is not needed if the mistletoes are returned
3116@*      from the sickle algorithm.
3117EXAMPLE: example lpOrdMisLex; shows examples
3118"
3119{return(ivL2lpI(sort(lpId2ivLi(M))[1]));}
3120example
3121{
3122  "EXAMPLE:"; echo = 2;
3123  ring r = 0,(x,y),dp;
3124  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3125  setring R; // sets basering to Letterplace ring
3126  ideal M = x(1)*y(2)*x(3), y(1)*y(2)*x(3), x(1)*x(2), y(1)*x(2)*x(3)*x(4);
3127  // some monomials
3128  lpOrdMisLex(M); // orders the monomials lexicographically
3129}
3130
3131proc lpSickle(ideal G,  list #)
3132"USAGE: lpSickle(G[,degbound,n]); G an ideal, degbound, n optional integers
3133RETURN: ideal
3134PURPOSE:Computing the mistletoes of K[X]/<G>
3135ASSUME: - basering is a Letterplace ring.
3136@*      - if you specify a different degree bound degbound,
3137@*        degbound <= attrib(basering,uptodeg) holds.
3138NOTE: - If degbound is set, there will be a degree bound added. 0 means no
3139@*      degree bound. Default: attrib(basering,uptodeg).
3140@*    - n is the number of variables, which can be set to a different number.
3141@*      Default: attrib(basering, lV).
3142@*    - If the K-dimension is known to be infinite, a degree bound is needed
3143EXAMPLE: example lpSickle; shows examples
3144"
3145{int degbound = attrib(basering,"uptodeg"); int n = attrib(basering, "lV");
3146  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
3147  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
3148  list L; ideal R;
3149  R = normalize(lead(G));
3150  L = lp2ivId(R);
3151  L = ivSickle(L,n,degbound);
3152  R = ivL2lpI(L);
3153  return(R);
3154}
3155example
3156{
3157  "EXAMPLE:"; echo = 2;
3158  ring r = 0,(x,y),dp;
3159  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3160  setring R; // sets basering to Letterplace ring
3161  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
3162  //Groebner basis
3163  lpSickle(G); //invokes the procedure with ring parameters
3164  // the factor algebra is finite, so the degree bound given by the Letterplace
3165  // ring is not necessary
3166  lpSickle(G,0); // procedure without any degree bound
3167}
3168
3169proc lpSickleDim(ideal G, list #)
3170"USAGE: lpSickleDim(G[,degbound,n]); G an ideal, degbound, n optional integers
3171RETURN: list
3172PURPOSE:Computing the K-dimension and the mistletoes
3173ASSUME: - basering is a Letterplace ring.
3174@*      - if you specify a different degree bound degbound,
3175@*        degbound <= attrib(basering,uptodeg) holds.
3176NOTE: - If L is the list returned, then L[1] is an integer, the K-dimension,
3177@*      L[2] is an ideal, the mistletoes.
3178@*    - If degbound is set, there will be a degree bound added. 0 means no
3179@*      degree bound. Default: attrib(basering,uptodeg).
3180@*    - n is the number of variables, which can be set to a different number.
3181@*      Default: attrib(basering, lV).
3182@*    - If the K-dimension is known to be infinite, a degree bound is needed
3183EXAMPLE: example lpSickleDim; shows examples
3184"
3185{int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV");
3186  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
3187  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
3188  list L;
3189  L = lp2ivId(normalize(lead(G)));
3190  L = ivSickleDim(L,n,degbound);
3191  L[2] = ivL2lpI(L[2]);
3192  return(L);
3193}
3194example
3195{
3196  "EXAMPLE:"; echo = 2;
3197  ring r = 0,(x,y),dp;
3198  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3199  setring R; // sets basering to Letterplace ring
3200  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
3201  //Groebner basis
3202  lpSickleDim(G); // invokes the procedure with ring parameters
3203  // the factor algebra is finite, so the degree bound given by the Letterplace
3204  // ring is not necessary
3205  lpSickleDim(G,0); // procedure without any degree bound
3206}
3207
3208proc lpSickleHil(ideal G, list #)
3209"USAGE: lpSickleHil(G);
3210RETURN: list
3211PURPOSE:Computing the Hilbert series and the mistletoes
3212ASSUME: - basering is a Letterplace ring.
3213@*      - if you specify a different degree bound degbound,
3214@*        degbound <= attrib(basering,uptodeg) holds.
3215NOTE: - If L is the list returned, then L[1] is an intvec, corresponding to the
3216@*      Hilbert series, L[2] is an ideal, the mistletoes.
3217@*    - If degbound is set, there will be a degree bound added. 0 means no
3218@*      degree bound. Default: attrib(basering,uptodeg).
3219@*    - n is the number of variables, which can be set to a different number.
3220@*      Default: attrib(basering, lV).
3221@*    - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th
3222@*      coefficient of the Hilbert series.
3223@*    - If the K-dimension is known to be infinite, a degree bound is needed
3224EXAMPLE: example lpSickleHil; shows examples
3225"
3226{int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV");
3227  if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}}
3228  if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}}
3229  list L;
3230  L = lp2ivId(normalize(lead(G)));
3231  L = ivSickleHil(L,n,degbound);
3232  L[2] =  ivL2lpI(L[2]);
3233  return(L);
3234}
3235example
3236{
3237  "EXAMPLE:"; echo = 2;
3238  ring r = 0,(x,y),dp;
3239  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3240  setring R; // sets basering to Letterplace ring
3241  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a
3242  //Groebner basis
3243  lpSickleHil(G); // invokes the procedure with ring parameters
3244  // the factor algebra is finite, so the degree bound given by the Letterplace
3245  // ring is not necessary
3246  lpSickleHil(G,0); // procedure without any degree bound
3247}
3248
3249proc sickle(ideal G, list #)
3250"USAGE: sickle(G[,m, d, h, degbound]); G an ideal; m,d,h,degbound optional
3251@*      integers
3252RETURN: list
3253PURPOSE:Allowing the user to access all procs with one command
3254ASSUME: - basering is a Letterplace ring.
3255@*      - if you specify a different degree bound degbound,
3256@*        degbound <= attrib(basering,uptodeg) holds.
3257NOTE:   The returned object will always be a list, but the entries of the
3258@*      returned list may be very different
3259@* case m=1,d=1,h=1: see lpDHilbertSickle
3260@* case m=1,d=1,h=0: see lpSickleDim
3261@* case m=1,d=0,h=1: see lpSickleHil
3262@* case m=1,d=0,h=0: see lpSickle (this is the default case)
3263@* case m=0,d=1,h=1: see lpDHilbert
3264@* case m=0,d=1,h=0: see lpKDim
3265@* case m=0,d=0,h=1: see lpHilbert
3266@* case m=0,d=0,h=0: returns an error
3267@*    - If degbound is set, there will be a degree bound added. 0 means no
3268@*      degree bound. Default: attrib(basering,uptodeg).
3269@*    - If the K-dimension is known to be infinite, a degree bound is needed
3270EXAMPLE: example sickle; shows examples
3271"
3272{int m,d,h,degbound;
3273  m = 1; d = 0; h = 0; degbound = attrib(basering,"uptodeg");
3274  if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] < 1) {m = 0;}}}
3275  if (size(#) > 1) {if (typeof(#[1])=="int"){if (#[2] > 0) {d = 1;}}}
3276  if (size(#) > 2) {if (typeof(#[1])=="int"){if (#[3] > 0) {h = 1;}}}
3277  if (size(#) > 3) {if (typeof(#[1])=="int"){if (#[4] >= 0) {degbound = #[4];}}}
3278  if (m == 1)
3279  {if (d == 0)
3280    {if (h == 0) {return(lpSickle(G,degbound,attrib(basering,"lV")));}
3281      else        {return(lpSickleHil(G,degbound,attrib(basering,"lV")));}
3282    }
3283    else
3284    {if (h == 0) {return(lpSickleDim(G,degbound,attrib(basering,"lV")));}
3285      else {return(lpDHilbertSickle(G,degbound,attrib(basering,"lV")));}
3286    }
3287  }
3288  else
3289  {if (d == 0)
3290    {if (h == 0) {ERROR("You request to do nothing, so relax and do so");}
3291      else        {return(lpHilbert(G,degbound,attrib(basering,"lV")));}
3292    }
3293    else
3294    {if (h == 0) {return(lpKDim(G,degbound,attrib(basering,"lV")));}
3295      else {return(lpDHilbert(G,degbound,attrib(basering,"lV")));}
3296    }
3297  }
3298}
3299example
3300{
3301  "EXAMPLE:"; echo = 2;
3302  ring r = 0,(x,y),dp;
3303  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3304  setring R; // sets basering to Letterplace ring
3305  ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3);
3306  // G contains a Groebner basis
3307  sickle(G,1,1,1); // computes mistletoes, K-dimension and the Hilbert series
3308  sickle(G,1,0,0); // computes mistletoes only
3309  sickle(G,0,1,0); // computes K-dimension only
3310  sickle(G,0,0,1); // computes Hilbert series only
3311}
3312
3313///////////////////////////////////////////////////////////////////////////////
3314/* vl: new stuff for conversion to Magma and to SD
3315todo: doc, example
3316 */
3317proc extractVars(r)
3318{
3319  int i = 1;
3320  int j = 1;
3321  string candidate;
3322  list result = list();
3323  for (i = 1; i<=nvars(r);i++)
3324  {
3325    candidate = string(var(i))[1,find(string(var(i)),"(")-1];
3326    if (!inList(result, candidate))
3327    {
3328      result = insert(result,candidate,size(result));
3329    }
3330  }
3331  return(result);
3332}
3333
3334proc letterPlacePoly2MagmaString(poly h)
3335{
3336  int pos;
3337  string s = string(h);
3338  while(find(s,"("))
3339  {
3340    pos = find(s,"(");
3341    while(s[pos]!=")")
3342    {
3343      s = s[1,pos-1]+s[pos+1,size(s)-pos];
3344    }
3345    if (size(s)!=pos)
3346    {
3347      s = s[1,pos-1]+s[pos+1,size(s)-pos]; // The last (")")
3348    }
3349    else
3350    {
3351      s = s[1,pos-1];
3352    }
3353  }
3354  return(s);
3355}
3356
3357proc letterPlaceIdeal2SD(ideal I, int upToDeg)
3358{
3359  int i;
3360  print("Don't forget to fill in the formal Data in the file");
3361  string result = "<?xml version=\"1.0\"?>"+newline+"<FREEALGEBRA createdAt=\"\" createdBy=\"Singular\" id=\"FREEALGEBRA/\">"+newline;
3362  result = result + "<vars>"+string(extractVars(basering))+"</vars>"+newline;
3363  result = result + "<basis>"+newline;
3364  for (i = 1;i<=size(I);i++)
3365  {
3366    result = result + "<poly>"+letterPlacePoly2MagmaString(I[i])+"</poly>"+newline;
3367  }
3368  result = result + "</basis>"+newline;
3369  result = result + "<uptoDeg>"+ string(upToDeg)+"</uptoDeg>"+newline;
3370  result = result + "<Comment></Comment>"+newline;
3371  result = result + "<Version></Version>"+newline;
3372  result = result + "</FREEALGEBRA>";
3373  return(result);
3374}
3375
3376
3377///////////////////////////////////////////////////////////////////////////////
3378
3379
3380proc tst_fpadim()
3381{
3382  example ivDHilbert;
3383  example ivDHilbertSickle;
3384  example ivDimCheck;
3385  example ivHilbert;
3386  example ivKDim;
3387  example ivMis2Base;
3388  example ivMis2Dim;
3389  example ivOrdMisLex;
3390  example ivSickle;
3391  example ivSickleHil;
3392  example ivSickleDim;
3393  example lpDHilbert;
3394  example lpDHilbertSickle;
3395  example lpHilbert;
3396  example lpDimCheck;
3397  example lpKDim;
3398  example lpMis2Base;
3399  example lpMis2Dim;
3400  example lpOrdMisLex;
3401  example lpSickle;
3402  example lpSickleHil;
3403  example lpSickleDim;
3404  example sickle;
3405  example ivL2lpI;
3406  example iv2lp;
3407  example iv2lpList;
3408  example iv2lpMat;
3409  example lp2iv;
3410  example lp2ivId;
3411  example lpId2ivLi;
3412  example lpGkDim;
3413  example lpGlDimBound;
3414  example lpSubstitute;
3415}
3416
3417
3418/*proc lpSubstituteExpandRing(poly f, list s1, list s2) {*/
3419/*int minDegBound = calcSubstDegBound(f,s1,s2);*/
3420/**/
3421/*def R = basering; // curr lp ring*/
3422/*setring ORIGINALRING; // non lp ring TODO*/
3423/*def R1 = makeLetterplaceRing(minDegBound);*/
3424/*setring R1;*/
3425/**/
3426/*poly g = lpSubstitute(imap(R,f), imap(R,s1), imap(R,s2));*/
3427/**/
3428/*return (R1); // return the new ring*/
3429/*}*/
3430
3431proc lpSubstitute(poly f, ideal s1, ideal s2, list #)
3432"USAGE: lpSubstitute(f,s1,s2[,G]); f letterplace polynomial, s1 list (ideal) of variables
3433@*      to replace, s2 list (ideal) of polynomials to replace with, G optional ideal to
3434@*      reduce with.
3435RETURN: poly, the substituted polynomial
3436ASSUME: - basering is a Letterplace ring
3437@*      - G is a groebner basis,
3438@*      - the current ring has a sufficient degbound (can be calculated with
3439    @*    calcSubstDegBound())
3440EXAMPLE: example lpSubstitute; shows examples
3441"
3442{
3443  ideal G;
3444  if (size(#) > 0) {
3445    if (typeof(#[1])=="ideal") {
3446      G = #[1];
3447    }
3448  }
3449
3450  poly fs;
3451  for (int i = 1; i <= size(f); i++) {
3452    poly fis = leadcoef(f[i]);
3453    intvec ivfi = lp2iv(f[i]);
3454    for (int j = 1; j <= size(ivfi); j++) {
3455      int varindex = ivfi[j];
3456      int subindex = lpIndexOf(s1, var(varindex));
3457      if (subindex > 0) {
3458        s2[subindex] = lpNF(s2[subindex],G);
3459        fis = lpMult(fis, s2[subindex]);
3460      } else {
3461        fis = lpMult(fis, lpNF(iv2lp(varindex),G));
3462      }
3463      /*fis = lpNF(fis,G);*/
3464    }
3465    fs = fs + fis;
3466  }
3467  fs = lpNF(fs, G);
3468  return (fs);
3469}
3470example {
3471  LIB "fpadim.lib";
3472  ring r = 0,(x,y,z),dp;
3473  def R = makeLetterplaceRing(4);
3474  setring R;
3475
3476  ideal G = x(1)*y(2); // optional
3477
3478  poly f = 3*x(1)*x(2)+y(1)*x(2);
3479  ideal s1 = x(1), y(1);
3480  ideal s2 = y(1)*z(2)*z(3), x(1);
3481
3482  // the substitution probably needs a higher degbound
3483  int minDegBound = calcSubstDegBounds(f,s1,s2);
3484  setring r;
3485  def R1 = makeLetterplaceRing(minDegBound);
3486  setring R1;
3487
3488  // the last parameter is optional
3489  lpSubstitute(imap(R,f), imap(R,s1), imap(R,s2), imap(R,G));
3490}
3491example {
3492  LIB "fpadim.lib";
3493  ring r = 0,(x,y,z),dp;
3494  def R = makeLetterplaceRing(4);
3495  setring R;
3496
3497  poly f = 3*x(1)*x(2)+y(1)*x(2);
3498  poly g = z(1)*x(2)+y(1);
3499  poly h = 7*x(1)*z(2)+x(1);
3500  ideal I = f,g,h;
3501  ideal s1 = x(1), y(1);
3502  ideal s2 = y(1)*z(2)*z(3), x(1);
3503
3504  int minDegBound = calcSubstDegBounds(I,s1,s2);
3505  setring r;
3506  def R1 = makeLetterplaceRing(minDegBound);
3507  setring R1;
3508
3509  ideal I = imap(R,I);
3510  ideal s1 = imap(R,s1);
3511  ideal s2 = imap(R,s2);
3512  for (int i = 1; i <= size(I); i++) {
3513    lpSubstitute(I[i], s1, s2);
3514  }
3515}
3516
3517static proc lpIndexOf(ideal I, poly p) {
3518  for (int i = 1; i <= size(I); i++) {
3519    if (I[i] == p) {
3520      return (i);
3521    }
3522  }
3523  return (-1);
3524}
3525
3526static proc ivIndexOf(list L, intvec iv) {
3527  for (int i = 1; i <= size(L); i++) {
3528    if (L[i] == iv) {
3529      return (i);
3530    }
3531  }
3532  return (-1);
3533}
3534
3535
3536proc calcSubstDegBound(poly f, ideal s1, ideal s2)
3537"USAGE: calcSubstDegBound(f,s1,s2); f letterplace polynomial, s1 list (ideal) of variables
3538@*      to replace, s2 list (ideal) of polynomials to replace with
3539RETURN: int, the min degbound required to perform the substitution
3540ASSUME: - basering is a Letterplace ring
3541EXAMPLE: example lpSubstitute; shows examples
3542"
3543{
3544  int maxDegBound = 0;
3545  for (int i = 1; i <= size(f); i++) {
3546    intvec ivfi = lp2iv(f[i]);
3547    int tmpDegBound;
3548    for (int j = 1; j <= size(ivfi); j++) {
3549      int varindex = ivfi[j];
3550      int subindex = lpIndexOf(s1, var(varindex));
3551      if (subindex > 0) {
3552        tmpDegBound = tmpDegBound + deg(s2[subindex]);
3553      } else {
3554        tmpDegBound = tmpDegBound + 1;
3555      }
3556    }
3557    if (tmpDegBound > maxDegBound) {
3558      maxDegBound = tmpDegBound;
3559    }
3560  }
3561
3562  // increase degbound by 50% when ideal is provided
3563  // needed for lpNF
3564  maxDegBound = maxDegBound + maxDegBound/2;
3565
3566  return (maxDegBound);
3567}
3568
3569// convenience method
3570proc calcSubstDegBounds(ideal I, ideal s1, ideal s2)
3571"USAGE: calcSubstDegBounds(I,s1,s2); I list (ideal) of letterplace polynomials, s1 list (ideal)
3572@*      of variables to replace, s2 list (ideal) of polynomials to replace with
3573RETURN: int, the min degbound required to perform all of the substitutions
3574ASSUME: - basering is a Letterplace ring
3575EXAMPLE: example lpSubstitute; shows examples
3576"
3577{
3578  int maxDegBound = 0;
3579  for (int i = 1; i <= size(I); i++) {
3580    int tmpDegBound = calcSubstDegBound(I[i], s1, s2, #);
3581    if (tmpDegBound > maxDegBound) {
3582      maxDegBound = tmpDegBound;
3583    }
3584  }
3585  return (maxDegBound);
3586}
3587
3588
3589/*
3590   Here are some examples one may try. Just copy them into your console.
3591   These are relations for braid groups, up to degree d:
3592
3593
3594   LIB "fpadim.lib";
3595   ring r = 0,(x,y,z),dp;
3596   int d =10; // degree
3597   def R = makeLetterplaceRing(d);
3598   setring R;
3599   ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*x(3) - z(1)*x(2)*y(3),
3600   z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) +
3601   z(1)*z(2)*z(3) + x(1)*y(2)*z(3);
3602   option(prot);
3603   option(redSB);option(redTail);option(mem);
3604   ideal J = system("freegb",I,d,3);
3605   lpDimCheck(J);
3606   sickle(J,1,1,1,d);//Computes mistletoes, K-dimension and the Hilbert series
3607
3608
3609
3610   LIB "fpadim.lib";
3611   ring r = 0,(x,y,z),dp;
3612   int d =11; // degree
3613   def R = makeLetterplaceRing(d);
3614   setring R;
3615   ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*z(3) - z(1)*x(2)*y(3),
3616   z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) +
3617   z(1)*z(2)*z(3) + x(1)*y(2)*z(3);
3618   option(prot);
3619   option(redSB);option(redTail);option(mem);
3620   ideal J = system("freegb",I,d,3);
3621   lpDimCheck(J);
3622   sickle(J,1,1,1,d);
3623
3624
3625
3626   LIB "fpadim.lib";
3627   ring r = 0,(x,y,z),dp;
3628   int d  = 6; // degree
3629   def R  = makeLetterplaceRing(d);
3630   setring R;
3631   ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*x(3) - z(1)*x(2)*y(3),
3632   z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) -2*y(1)*y(2)*y(3) + 3*z(1)*z(2)*z(3) -4*x(1)*y(2)*z(3) + 5*x(1)*z(2)*z(3)- 6*x(1)*y(2)*y(3) +7*x(1)*x(2)*z(3) - 8*x(1)*x(2)*y(3);
3633   option(prot);
3634   option(redSB);option(redTail);option(mem);
3635   ideal J = system("freegb",I,d,3);
3636   lpDimCheck(J);
3637   sickle(J,1,1,1,d);
3638 */
3639
3640/*
3641   Here are some examples, which can also be found in [studzins]:
3642
3643// takes up to 880Mb of memory
3644LIB "fpadim.lib";
3645ring r = 0,(x,y,z),dp;
3646int d =10; // degree
3647def R = makeLetterplaceRing(d);
3648setring R;
3649ideal I =
3650z(1)*z(2)*z(3)*z(4) + y(1)*x(2)*y(3)*x(4) - x(1)*y(2)*y(3)*x(4) - 3*z(1)*y(2)*x(3)*z(4), x(1)*x(2)*x(3) + y(1)*x(2)*y(3) - x(1)*y(2)*x(3), z(1)*y(2)*x(3)-x(1)*y(2)*z(3) + z(1)*x(2)*z(3);
3651option(prot);
3652option(redSB);option(redTail);option(mem);
3653ideal J = system("freegb",I,d,nvars(r));
3654lpDimCheck(J);
3655sickle(J,1,1,1,d); // dimension is 24872
3656
3657
3658LIB "fpadim.lib";
3659ring r = 0,(x,y,z),dp;
3660int d =10; // degree
3661def R = makeLetterplaceRing(d);
3662setring R;
3663ideal I = x(1)*y(2) + y(1)*z(2), x(1)*x(2) + x(1)*y(2) - y(1)*x(2) - y(1)*y(2);
3664option(prot);
3665option(redSB);option(redTail);option(mem);
3666ideal J = system("freegb",I,d,3);
3667lpDimCheck(J);
3668sickle(J,1,1,1,d);
3669 */
3670
3671
3672/*
3673   Example for computing GK dimension:
3674   returns a ring which contains an ideal I
3675   run gkDim(I) inside this ring and it should return 2n (the GK dimension
3676   of n-th Weyl algebra including evaluation operators).
3677
3678   proc createWeylEx(int n, int d)
3679   "
3680   "
3681   {
3682   int baseringdef;
3683   if (defined(basering)) // if a basering is defined, it should be saved for later use
3684   {
3685   def save = basering;
3686   baseringdef = 1;
3687   }
3688   ring r = 0,(d(1..n),x(1..n),e(1..n)),dp;
3689   def R = makeLetterplaceRing(d);
3690   setring R;
3691   ideal I; int i,j;
3692
3693   for (i = 1; i <= n; i++)
3694   {
3695   for (j = i+1; j<= n; j++)
3696   {
3697   I[size(I)+1] = lpMult(var(i),var(j));
3698   }
3699   }
3700
3701   for (i = 1; i <= n; i++)
3702   {
3703   for (j = i+1; j<= n; j++)
3704   {
3705   I[size(I)+1] = lpMult(var(n+i),var(n+j));
3706   }
3707   }
3708   for (i = 1; i <= n; i++)
3709   {
3710   for (j = 1; j<= n; j++)
3711   {
3712   I[size(I)+1] = lpMult(var(i),var(n+j));
3713   }
3714   }
3715   for (i = 1; i <= n; i++)
3716   {
3717   for (j = 1; j<= n; j++)
3718   {
3719   I[size(I)+1] = lpMult(var(i),var(2*n+j));
3720   }
3721   }
3722   for (i = 1; i <= n; i++)
3723   {
3724   for (j = 1; j<= n; j++)
3725   {
3726   I[size(I)+1] = lpMult(var(2*n+i),var(n+j));
3727   }
3728   }
3729   for (i = 1; i <= n; i++)
3730   {
3731   for (j = 1; j<= n; j++)
3732   {
3733   I[size(I)+1] = lpMult(var(2*n+i),var(2*n+j));
3734   }
3735   }
3736   I = simplify(I,2+4);
3737   I = letplaceGBasis(I);
3738   export(I);
3739   if (baseringdef == 1) {setring save;}
3740   return(R);
3741   }
3742
3743proc TestGKAuslander3()
3744{
3745  ring r = (0,q),(z,x,y),(dp(1),dp(2));
3746  def R = makeLetterplaceRing(5); // constructs a Letterplace ring
3747  R; setring R; // sets basering to Letterplace ring
3748  ideal I;
3749  I = q*x(1)*y(2) - y(1)*x(2), z(1)*y(2) - y(1)*z(2), z(1)*x(2) - x(1)*z(2);
3750  I = letplaceGBasis(I);
3751  lpGkDim(I); // must be 3
3752  I = x(1)*y(2)*z(3) - y(1)*x(2), z(1)*y(2) - y(1)*z(2), z(1)*x(2) - x(1)*z(2);//gkDim = 2
3753  I = letplaceGBasis(I); // not finite BUT contains a poly in x,y only
3754  lpGkDim(I); // must be 4
3755
3756  ring r = 0,(y,x,z),dp;
3757  def R = makeLetterplaceRing(10); // constructs a Letterplace ring
3758  R; setring R; // sets basering to Letterplace ring
3759  ideal I;
3760  I = x(1)*y(2)*z(3) - y(1)*x(2), z(1)*y(2) - y(1)*z(2), z(1)*x(2) - x(1)*z(2);//gkDim = 2
3761  I = letplaceGBasis(I); // computed as it would be homogenized; infinite
3762  poly p = x(1)*y(2)*y(3)*x(4)-y(1)*x(2)*x(3)*y(4);
3763  lpNF(p, I); // 0 as expected
3764
3765  // with inverse of z
3766  ring r = 0,(iz,z,x,y),dp;
3767  def R = makeLetterplaceRing(11); // constructs a Letterplace ring
3768  R; setring R; // sets basering to Letterplace ring
3769  ideal I;
3770  I = x(1)*y(2)*z(3) - y(1)*x(2), z(1)*y(2) - y(1)*z(2), z(1)*x(2) - x(1)*z(2),
3771    iz(1)*y(2) - y(1)*iz(2), iz(1)*x(2) - x(1)*iz(2), iz(1)*z(2)-1, z(1)*iz(2) -1;
3772  I = letplaceGBasis(I); //
3773  setring r;
3774  def R2 = makeLetterplaceRing(23); // constructs a Letterplace ring
3775  setring R2; // sets basering to Letterplace ring
3776  ideal I = imap(R,I);
3777  lpGkDim(I);
3778
3779
3780  ring r = 0,(t,z,x,y),(dp(2),dp(2));
3781  def R = makeLetterplaceRing(20); // constructs a Letterplace ring
3782  R; setring R; // sets basering to Letterplace ring
3783  ideal I;
3784  I = x(1)*y(2)*z(3) - y(1)*x(2)*t(3), z(1)*y(2) - y(1)*z(2), z(1)*x(2) - x(1)*z(2),
3785    t(1)*y(2) - y(1)*t(2), t(1)*x(2) - x(1)*t(2), t(1)*z(2) - z(1)*t(2);//gkDim = 2
3786  I = letplaceGBasis(I); // computed as it would be homogenized; infinite
3787  LIB "elim.lib";
3788  ideal Inoz = nselect(I,intvec(2,6,10,14,18,22,26,30));
3789  for(int i=1; i<=20; i++)
3790  {
3791    Inoz=subst(Inoz,t(i),1);
3792  }
3793  ideal J = x(1)*y(2)*y(3)*x(4)-y(1)*x(2)*x(3)*y(4);
3794  J = letplaceGBasis(J);
3795
3796  poly p = x(1)*y(2)*y(3)*x(4)-y(1)*x(2)*x(3)*y(4);
3797  lpNF(p, I); // 0 as expected
3798
3799  ring r2 = 0,(x,y),dp;
3800  def R2 = makeLetterplaceRing(50); // constructs a Letterplace ring
3801  setring R2;
3802  ideal J = x(1)*y(2)*y(3)*x(4)-y(1)*x(2)*x(3)*y(4);
3803  J = letplaceGBasis(J);
3804}
3805
3806*/
3807
3808
3809/*   actual work:
3810// downup algebra A
3811LIB "fpadim.lib";
3812ring r = (0,a,b,g),(x,y),Dp;
3813def R = makeLetterplaceRing(6); // constructs a Letterplace ring
3814setring R;
3815poly F1 = g*x(1);
3816poly F2 = g*y(1);
3817ideal J = x(1)*x(2)*y(3)-a*x(1)*y(2)*x(3) - b*y(1)*x(2)*x(3) - F1,
3818x(1)*y(2)*y(3)-a*y(1)*x(2)*y(3) - b*y(1)*y(2)*x(3) - F2;
3819J = letplaceGBasis(J);
3820lpGkDim(J); // 3 == correct
3821
3822// downup algebra B
3823LIB "fpadim.lib";
3824ring r = (0,a,b,g, p(1..7),q(1..7)),(x,y),Dp;
3825def R = makeLetterplaceRing(6); // constructs a Letterplace ring
3826setring R;
3827ideal imn = 1, y(1)*y(2)*y(3), x(1)*y(2), y(1)*x(2), x(1)*x(2), y(1)*y(2), x(1), y(1);
3828int i;
3829poly F1, F2;
3830for(i=1;i<=7;i++)
3831{
3832F1 = F1 + p(i)*imn[i];
3833F2 = F2 + q(i)*imn[i];
3834}
3835ideal J = x(1)*x(2)*y(3)-a*x(1)*y(2)*x(3) - b*y(1)*x(2)*x(3) - F1,
3836x(1)*y(2)*y(3)-a*y(1)*x(2)*y(3) - b*y(1)*y(2)*x(3) - F2;
3837J = letplaceGBasis(J);
3838lpGkDim(J); // 3 == correct
3839
3840 */
Note: See TracBrowser for help on using the repository browser.