source: git/Singular/LIB/freegb.lib @ 5f13434

spielwiese
Last change on this file since 5f13434 was 5f13434, checked in by Karim Abou Zeid <karim23697@…>, 6 years ago
Merge branch 'spielwiese' into letterplace_kernel_multiplication
  • Property mode set to 100644
File size: 102.6 KB
Line 
1/////////////////////////////////////////////////////////////////////////////
2version="version freegb.lib 4.1.1.0 Dec_2017 "; // $Id$
3category="Noncommutative";
4info="
5LIBRARY: freegb.lib   Compute two-sided Groebner bases in free algebras via letterplace approach
6AUTHORS: Viktor Levandovskyy,     viktor.levandovskyy@math.rwth-aachen.de
7       Grischa Studzinski,      grischa.studzinski@math.rwth-aachen.de
8
9OVERVIEW: For the theory, see chapter 'Letterplace' in the @sc{Singular} Manual
10
11Support: Joint projects LE 2697/2-1 and KR 1907/3-1 of the Priority Programme SPP 1489:
12'Algorithmische und Experimentelle Methoden in Algebra, Geometrie und Zahlentheorie'
13of the German DFG
14and Project II.6 of the transregional collaborative research centre
15SFB-TRR 195 'Symbolic Tools in Mathematics and their Application' of the German DFG
16
17PROCEDURES:
18makeLetterplaceRing(d); creates a ring with d blocks of shifted original variables
19letplaceGBasis(I); computes two-sided Groebner basis of a letterplace ideal I up to a degree bound
20lpNF(f,I); two-sided normal form of f with respect to ideal I
21setLetterplaceAttributes(R,d,b); supplies ring R with the letterplace structure
22freeGBasis(L, n);  computes two-sided Groebner basis of an ideal, encoded via list L, up to degree n
23
24lpMult(f,g);    letterplace multiplication of letterplace polynomials
25shiftPoly(p,i); compute the i-th shift of letterplace polynomial p
26lpPower(f,n);   natural power of a letterplace polynomial
27lieBracket(a,b[, N]);  compute Lie bracket ab-ba of two letterplace polynomials
28
29lp2lstr(K, s);  convert a letterplace ideal into a list of modules
30lst2str(L[, n]); convert a list (of modules) into polynomials in free algebra via strings
31mod2str(M[, n]); convert a module into a polynomial in free algebra via strings
32vct2str(M[, n]);   convert a vector into a word in free algebra
33
34serreRelations(A,z); compute the homogeneous part of Serre's relations associated to a generalized Cartan matrix A
35fullSerreRelations(A,N,C,P,d); compute the ideal of all Serre's relations associated to a generalized Cartan matrix A
36isVar(p);              check whether p is a power of a single variable
37ademRelations(i,j);    compute the ideal of Adem relations for i<2j in char 0
38
39lpPrint(ideal I, def @r); print a letterplace ideal as an easily readable string
40
41SEE ALSO: fpadim_lib, LETTERPLACE
42";
43
44// this library computes two-sided GB of an ideal
45// in a free associative algebra
46
47// a monomial is encoded via a vector V
48// where V[1] = coefficient
49// V[1+i] = the corresponding symbol
50
51LIB "qhmoduli.lib"; // for Max
52LIB "bfun.lib"; // for inForm
53LIB "fpadim.lib"; // for intvec conversion
54
55proc tstfreegb()
56{
57    /* tests all procs for consistency */
58  /* adding the new proc, add it here */
59  example makeLetterplaceRing;
60  example letplaceGBasis;
61  example lpNF;
62  example freeGBasis;
63  example setLetterplaceAttributes;
64  /* secondary */
65  example   lpMult;
66  example   shiftPoly;
67  example   lpPower;
68  example   lieBracket;
69  example   lp2lstr;
70  example   lst2str;
71  example   mod2str;
72  example   vct2str;
73  example   serreRelations;
74  example   fullSerreRelations;
75  example   isVar;
76  example   ademRelations;
77}
78
79proc setLetterplaceAttributes(def R, int uptodeg, int lV)
80"USAGE: setLetterplaceAttributes(R, d, b); R a ring, b,d integers
81RETURN: ring with special attributes set
82PURPOSE: sets attributes for a letterplace ring:
83@*      'isLetterplaceRing' = true, 'uptodeg' = d, 'lV' = b, where
84@*      'uptodeg' stands for the degree bound,
85@*      'lV' for the number of variables in the block 0.
86NOTE: Activate the resulting ring by using @code{setring}
87"
88{
89  if (uptodeg*lV != nvars(R))
90  {
91    ERROR("uptodeg and lV do not agree on the basering!");
92  }
93
94  // Set letterplace-specific attributes for the output ring!
95  // a kind of dirty hack, getting the ringlist again
96  list RL = ringlist(R);
97  attrib(RL, "isLetterplaceRing", lV);
98  attrib(RL, "maxExp", 1);
99  def @R = ring(RL);
100
101  attrib(@R, "uptodeg", uptodeg);
102  attrib(@R, "isLetterplaceRing", lV);
103  return (@R);
104}
105example
106{
107  "EXAMPLE:"; echo = 2;
108  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
109  def R = setLetterplaceAttributes(r, 4, 2); setring R;
110  attrib(R,"isLetterplaceRing");
111  lieBracket(x(1),y(1),2);
112}
113
114
115// obsolete?
116
117static proc lshift(module M, int s, string varing, def lpring)
118{
119  // FINALLY IMPLEMENTED AS A PART OT THE CODE
120  // shifts a polynomial from the ring R to s positions
121  // M lives in varing, the result in lpring
122  // to be run from varing
123  int i, j, k, sm, sv;
124  vector v;
125  //  execute("setring "+lpring);
126  setring lpring;
127  poly @@p;
128  ideal I;
129  execute("setring "+varing);
130  sm = ncols(M);
131  for (i=1; i<=s; i++)
132  {
133    // modules, e.g. free polynomials
134    for (j=1; j<=sm; j++)
135    {
136      //vectors, e.g. free monomials
137      v  = M[j];
138      sv = size(v);
139      sp = "@@p = @@p + ";
140      for (k=2; k<=sv; k++)
141      {
142        sp = sp + string(v[k])+"("+string(k-1+s)+")*";
143      }
144      sp = sp + string(v[1])+";"; // coef;
145      setring lpring;
146      //      execute("setring "+lpring);
147      execute(sp);
148      execute("setring "+varing);
149    }
150    setring lpring;
151    //    execute("setring "+lpring);
152    I = I,@@p;
153    @@p = 0;
154  }
155  setring lpring;
156  //execute("setring "+lpring);
157  export(I);
158  //  setring varing;
159  execute("setring "+varing);
160}
161
162static proc skip0(vector v)
163{
164  // skips zeros in a vector, producing another vector
165  if ( (v[1]==0) || (v==0) ) { return(vector(0)); }
166  int sv = nrows(v);
167  int sw = size(v);
168  if (sv == sw)
169  {
170    return(v);
171  }
172  int i;
173  int j=1;
174  vector w;
175  for (i=1; i<=sv; i++)
176  {
177    if (v[i] != 0)
178    {
179      w = w + v[i]*gen(j);
180      j++;
181    }
182  }
183  return(w);
184}
185
186proc lst2str(list L, list #)
187"USAGE:  lst2str(L[,n]);  L a list of modules, n an optional integer
188RETURN:  list (of strings)
189PURPOSE: convert a list (of modules) into polynomials in free algebra
190EXAMPLE: example lst2str; shows examples
191NOTE: if an optional integer is not 0, stars signs are used in multiplication
192"
193{
194  // returns a list of strings
195  // being sentences in words built from L
196  // if #[1] = 1, use * between generators
197  int useStar = 0;
198  if ( size(#)>0 )
199  {
200    if ( typeof(#[1]) != "int")
201    {
202      ERROR("Second argument of type int expected");
203    }
204    if (#[1])
205    {
206      useStar = 1;
207    }
208  }
209  int i;
210  int s    = size(L);
211  if (s<1) { return(list(""));}
212  list N;
213  for(i=1; i<=s; i++)
214  {
215    if ((typeof(L[i]) == "module") || (typeof(L[i]) == "matrix") )
216    {
217      N[i] = mod2str(L[i],useStar);
218    }
219    else
220    {
221      "module or matrix expected in the list";
222      return(N);
223    }
224  }
225  return(N);
226}
227example
228{
229  "EXAMPLE:"; echo = 2;
230  ring r = 0,(x,y,z),(dp(1),dp(2));
231  module M = [-1,x,y],[-7,y,y],[3,x,x];
232  module N = [1,x,y,x,y],[-2,y,x,y,x],[6,x,y,y,x,y];
233  list L; L[1] = M; L[2] = N;
234  lst2str(L);
235  lst2str(L[1],1);
236}
237
238
239proc mod2str(module M, list #)
240"USAGE:  mod2str(M[,n]);  M a module, n an optional integer
241RETURN:  string
242PURPOSE: convert a module into a polynomial in free algebra
243EXAMPLE: example mod2str; shows examples
244NOTE: if an optional integer is not 0, stars signs are used in multiplication
245"
246{
247  if (size(M)==0) { return(""); }
248  // returns a string
249  // a sentence in words built from M
250  // if #[1] = 1, use * between generators
251  int useStar = 0;
252  if ( size(#)>0 )
253  {
254    if ( typeof(#[1]) != "int")
255    {
256      ERROR("Second argument of type int expected");
257    }
258    if (#[1])
259    {
260      useStar = 1;
261    }
262  }
263  int i;
264  int s    = ncols(M);
265  string t;
266  string mp;
267  for(i=1; i<=s; i++)
268  {
269    mp = vct2str(M[i],useStar);
270    if (mp[1] == "-")
271    {
272      t = t + mp;
273    }
274    else
275    {
276      if (mp != "")
277      {
278         t = t + "+" + mp;
279      }
280    }
281  }
282  if (t[1]=="+")
283  {
284    t = t[2..size(t)]; // remove first "+"
285  }
286  return(t);
287}
288example
289{
290  "EXAMPLE:"; echo = 2;
291  ring r = 0,(x,y,z),(dp);
292  module M = [1,x,y,x,y],[-2,y,x,y,x],[6,x,y,y,x,y];
293  mod2str(M);
294  mod2str(M,1);
295}
296
297proc vct2str(vector v, list #)
298"USAGE:  vct2str(v[,n]);  v a vector, n an optional integer
299RETURN:  string
300PURPOSE: convert a vector into a word in free algebra
301EXAMPLE: example vct2str; shows examples
302NOTE: if an optional integer is not 0, stars signs are used in multiplication
303"
304{
305  if (v==0) { return(""); }
306  // if #[1] = 1, use * between generators
307  int useStar = 0;
308  if ( size(#)>0 )
309  {
310    if (#[1])
311    {
312      useStar = 1;
313    }
314  }
315  int ppl = printlevel-voice+2;
316  // for a word, encoded by v
317  // produces a string for it
318  v = skip0(v);
319  if (v==0) { return(string(""));}
320  number cf = leadcoef(v[1]);
321  int s = size(v);
322  string vs,vv,vp,err;
323  int i,j,p,q;
324  for (i=1; i<=s-1; i++)
325  {
326    p     = isVar(v[i+1]);
327    if (p==0)
328    {
329      err = "Error: monomial expected at nonzero position " + string(i+1);
330      ERROR(err+" in vct2str");
331      //      dbprint(ppl,err);
332      //      return("_");
333    }
334    if (p==1)
335    {
336      if (useStar && (size(vs) >0))       {   vs = vs + "*"; }
337        vs = vs + string(v[i+1]);
338    }
339    else //power
340    {
341      vv = string(v[i+1]);
342      q = find(vv,"^");
343      if (q==0)
344      {
345        q = find(vv,string(p));
346        if (q==0)
347        {
348          err = "error in find for string "+vv;
349          dbprint(ppl,err);
350          return("_");
351        }
352      }
353      // q>0
354      vp = vv[1..q-1];
355      for(j=1;j<=p;j++)
356      {
357         if (useStar && (size(vs) >0))       {   vs = vs + "*"; }
358         vs = vs + vp;
359      }
360    }
361  }
362  string scf;
363  if (cf == -1)
364  {
365    scf = "-";
366  }
367  else
368  {
369    scf = string(cf);
370    if ( (cf == 1) && (size(vs)>0) )
371    {
372      scf = "";
373    }
374  }
375  if (useStar && (size(scf) >0) && (scf!="-") )       {   scf = scf + "*"; }
376  vs = scf + vs;
377  return(vs);
378}
379example
380{
381  "EXAMPLE:"; echo = 2;
382  ring r = (0,a),(x,y3,z(1)),dp;
383  vector v = [-7,x,y3^4,x2,z(1)^3];
384  vct2str(v);
385  vct2str(v,1);
386  vector w = [-7a^5+6a,x,y3,y3,x,z(1),z(1)];
387  vct2str(w);
388  vct2str(w,1);
389}
390
391proc isVar(poly p)
392"USAGE:  isVar(p);  poly p
393RETURN:  int
394PURPOSE: check, whether leading monomial of p is a power of a single variable
395@* from the basering. Returns the exponent or 0 if p is multivariate.
396EXAMPLE: example isVar; shows examples
397"
398{
399  // checks whether p is a variable indeed
400  // if it's a power of a variable, returns the power
401  if (p==0) {  return(0); } //"p=0";
402  poly q   = leadmonom(p);
403  if ( (p-lead(p)) !=0 ) { return(0); } // "p-lm(p)>0";
404  intvec v = leadexp(p);
405  int s = size(v);
406  int i=1;
407  int cnt = 0;
408  int pwr = 0;
409  for (i=1; i<=s; i++)
410  {
411    if (v[i] != 0)
412    {
413      cnt++;
414      pwr = v[i];
415    }
416  }
417  //  "cnt:";  cnt;
418  if (cnt==1) { return(pwr); }
419  else { return(0); }
420}
421example
422{
423  "EXAMPLE:"; echo = 2;
424  ring r = 0,(x,y),dp;
425  poly f = xy+1;
426  isVar(f);
427  poly g = y^3;
428  isVar(g);
429  poly h = 7*x^3;
430  isVar(h);
431  poly i = 1;
432  isVar(i);
433}
434
435// new conversion routines
436
437static proc id2words(ideal I, int d)
438{
439  // NOT FINISHED
440  // input: ideal I of polys in letter-place notation
441  // in the ring with d real vars
442  // output: the list of strings: associative words
443  // extract names of vars
444  int i,m,n; string s; string place = "(1)";
445  list lv;
446  for(i=1; i<=d; i++)
447  {
448    s = string(var(i));
449    // get rid of place
450    n = find(s, place);
451    if (n>0)
452    {
453      s = s[1..n-1];
454    }
455    lv[i] = s;
456  }
457  poly p,q;
458  for (i=1; i<=ncols(I); i++)
459  {
460    if (I[i] != 0)
461    {
462      p = I[i];
463      while (p!=0)
464      {
465         q = leadmonom(p);
466      }
467    }
468  }
469
470  return(lv);
471}
472example
473{
474  "EXAMPLE:"; echo = 2;
475  ring r = 0,(x(1),y(1),z(1),x(2),y(2),z(2)),dp;
476  ideal I = x(1)*y(2) -z(1)*x(2);
477  id2words(I,3);
478}
479
480static proc mono2word(poly p, int d)
481{
482}
483
484proc letplaceGBasis(def I)
485"USAGE: letplaceGBasis(I);  I an ideal/module
486RETURN: ideal/module
487ASSUME: basering is a Letterplace ring, input consists of Letterplace
488@*      polynomials
489PURPOSE: compute the two-sided Groebner basis of I via Letterplace
490@*       algorithm
491NOTE: the degree bound for this computation is read off the letterplace
492@*    structure of basering
493EXAMPLE: example letplaceGBasis; shows examples
494"
495{
496  if (lpAssumeViolation())
497  {
498    ERROR("Incomplete Letterplace structure on the basering!");
499  }
500  int ppl = printlevel-voice+2;
501  def save = basering;
502  // assumes of the ring have been checked
503  // run the computation - it will test assumes on the ideal
504  int uptodeg = attrib(save,"uptodeg");
505  int lV = attrib(save,"isLetterplaceRing");
506  dbprint(ppl,"start computing GB");
507  def J = system("freegb",I,uptodeg,lV);
508  dbprint(ppl,"finished computing GB");
509  dbprint(ppl-1,"the result is:");
510  dbprint(ppl-1,J);
511  return(J);
512}
513example
514{
515  "EXAMPLE:"; echo = 2;
516  ring r = 0,(x,y,z),(dp(1),dp(2));
517  int degree_bound = 5;
518  def R = makeLetterplaceRing(5);
519  setring R;
520  ideal I = -x(1)*y(2)-7*y(1)*y(2)+3*x(1)*x(2), x(1)*y(2)*x(3)-y(1)*x(2)*y(3);
521  ideal J = letplaceGBasis(I);
522  J;
523  // now transfom letterplace polynomials into strings of words
524  lp2lstr(J,r); // export an object called @code{@LN} to the ring r
525  setring r;  // change to the ring r
526  lst2str(@LN,1);
527}
528
529// given the element -7xy^2x, it is represented as [-7,x,y^2,x] or as [-7,x,y,y,x]
530// use the orig ord on (x,y,z) and expand it blockwise to (x(i),y(i),z(i))
531
532// the correspondences:
533// monomial in K<x,y,z>    <<--->> vector in R
534// polynomial in K<x,y,z>  <<--->> list of vectors (matrix/module) in R
535// ideal in K<x,y,z>       <<--->> list of matrices/modules in R
536
537
538// 1. form a new ring
539// 2. NOP
540// 3. compute GB -> with the kernel stuff
541// 4. skip shifted elts (check that no such exist?)
542// 5. go back to orig vars, produce strings/modules
543// 6. return the result
544
545proc freeGBasis(list LM, int d)
546"USAGE:  freeGBasis(L, d);  L a list of modules, d an integer
547RETURN:  ring
548ASSUME: L has a special form. Namely, it is a list of modules, where
549
550 - each generator of every module stands for a monomial times coefficient in
551@* free algebra,
552
553 - in such a vector generator, the 1st entry is a nonzero coefficient from the
554@* ground field
555
556 - and each next entry hosts a variable from the basering.
557PURPOSE: compute the two-sided Groebner basis of an ideal, encoded by L
558@* in the free associative algebra, up to degree d
559NOTE: Apply @code{lst2str} to the output in order to obtain a better readable
560@*    presentation
561EXAMPLE: example freeGBasis; shows examples
562"
563{
564  // d = up to degree, will be shifted to d+1
565  if (d<1) {"bad d"; return(0);}
566
567  int ppl = printlevel-voice+2;
568  string err = "";
569
570  int i,j,s;
571  def save = basering;
572  // determine max no of places in the input
573  int slm = size(LM); // numbers of polys in the ideal
574  int sm;
575  intvec iv;
576  module M;
577  for (i=1; i<=slm; i++)
578  {
579    // modules, e.g. free polynomials
580    M  = LM[i];
581    sm = ncols(M);
582    for (j=1; j<=sm; j++)
583    {
584      //vectors, e.g. free monomials
585      iv = iv, size(M[j])-1; // 1 place is reserved by the coeff
586    }
587  }
588  int D = Max(iv); // max size of input words
589  if (d<D) {"bad d"; return(LM);}
590  D = D + d-1;
591  //  D = d;
592  list LR  = ringlist(save);
593  list L, tmp;
594  L[1] = LR[1]; // ground field
595  L[4] = LR[4]; // quotient ideal
596  tmp  = LR[2]; // varnames
597  s = size(LR[2]);
598  for (i=1; i<=D; i++)
599  {
600    for (j=1; j<=s; j++)
601    {
602      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
603    }
604  }
605  for (i=1; i<=s; i++)
606  {
607    tmp[i] = string(tmp[i])+"("+string(1)+")";
608  }
609  L[2] = tmp;
610  list OrigNames = LR[2];
611  // ordering: d blocks of the ord on r
612  // try to get whether the ord on r is blockord itself
613  s = size(LR[3]);
614  if (s==2)
615  {
616    // not a blockord, 1 block + module ord
617    tmp = LR[3][s]; // module ord
618    for (i=1; i<=D; i++)
619    {
620      LR[3][s-1+i] = LR[3][1];
621    }
622    LR[3][s+D] = tmp;
623  }
624  if (s>2)
625  {
626    // there are s-1 blocks
627    int nb = s-1;
628    tmp = LR[3][s]; // module ord
629    for (i=1; i<=D; i++)
630    {
631      for (j=1; j<=nb; j++)
632      {
633        LR[3][i*nb+j] = LR[3][j];
634      }
635    }
636    //    size(LR[3]);
637    LR[3][nb*(D+1)+1] = tmp;
638  }
639  L[3] = LR[3];
640  def @R = ring(L);
641  setring @R;
642  ideal I;
643  poly @p;
644  s = size(OrigNames);
645  //  "s:";s;
646  // convert LM to canonical vectors (no powers)
647  setring save;
648  kill M; // M was defined earlier
649  module M;
650  slm = size(LM); // numbers of polys in the ideal
651  int sv,k,l;
652  vector v;
653  //  poly p;
654  string sp;
655  setring @R;
656  poly @@p=0;
657  setring save;
658  for (l=1; l<=slm; l++)
659  {
660    // modules, e.g. free polynomials
661    M  = LM[l];
662    sm = ncols(M); // in intvec iv the sizes are stored
663    // modules, e.g. free polynomials
664    for (j=1; j<=sm; j++)
665    {
666      //vectors, e.g. free monomials
667      v  = M[j];
668      sv = size(v);
669      //        "sv:";sv;
670      sp = "@@p = @@p + ";
671      for (k=2; k<=sv; k++)
672      {
673        sp = sp + string(v[k])+"("+string(k-1)+")*";
674      }
675      sp = sp + string(v[1])+";"; // coef;
676      setring @R;
677      execute(sp);
678      setring save;
679    }
680    setring @R;
681    //      "@@p:"; @@p;
682    I = I,@@p;
683    @@p = 0;
684    setring save;
685  }
686  kill sp;
687  // 3. compute GB
688  setring @R;
689  dbprint(ppl,"computing GB");
690  ideal J = system("freegb",I,d,nvars(save));
691  //  ideal J = slimgb(I);
692  dbprint(ppl,J);
693  // 4. skip shifted elts
694  ideal K = select1(J,1..s); // s = size(OrigNames)
695  dbprint(ppl,K);
696  dbprint(ppl, "done with GB");
697  // K contains vars x(1),...z(1) = images of originals
698  // 5. go back to orig vars, produce strings/modules
699  if (K[1] == 0)
700  {
701    "no reasonable output, GB gives 0";
702    return(0);
703  }
704  int sk = size(K);
705  int sp, sx, a, b;
706  intvec x;
707  poly p,q;
708  poly pn;
709  // vars in 'save'
710  setring save;
711  module N;
712  list LN;
713  vector V;
714  poly pn;
715  // test and skip exponents >=2
716  setring @R;
717  for(i=1; i<=sk; i++)
718  {
719    p  = K[i];
720    while (p!=0)
721    {
722      q  = lead(p);
723      //      "processing q:";q;
724      x  = leadexp(q);
725      sx = size(x);
726      for(k=1; k<=sx; k++)
727      {
728        if ( x[k] >= 2 )
729        {
730          err = "skip: the value x[k] is " + string(x[k]);
731          dbprint(ppl,err);
732          //            return(0);
733          K[i] = 0;
734          p    = 0;
735          q    = 0;
736          break;
737        }
738      }
739      p  = p - q;
740    }
741  }
742  K  = simplify(K,2);
743  sk = size(K);
744  for(i=1; i<=sk; i++)
745  {
746    //    setring save;
747    //    V  = 0;
748    setring @R;
749    p  = K[i];
750    while (p!=0)
751    {
752      q  = lead(p);
753      err =  "processing q:" + string(q);
754      dbprint(ppl,err);
755      x  = leadexp(q);
756      sx = size(x);
757      pn = leadcoef(q);
758      setring save;
759      pn = imap(@R,pn);
760      V  = V + leadcoef(pn)*gen(1);
761      for(k=1; k<=sx; k++)
762      {
763        if (x[k] ==1)
764        {
765          a = k div s; // block number=a+1, a!=0
766          b = k % s; // remainder
767          //          printf("a: %s, b: %s",a,b);
768          if (b == 0)
769          {
770            // that is it's the last var in the block
771            b = s;
772            a = a-1;
773          }
774          V = V + var(b)*gen(a+2);
775        }
776//         else
777//         {
778//           printf("error: the value x[k] is %s", x[k]);
779//           return(0);
780//         }
781      }
782      err = "V: " + string(V);
783      dbprint(ppl,err);
784      //      printf("V: %s", string(V));
785      N = N,V;
786      V  = 0;
787      setring @R;
788      p  = p - q;
789      pn = 0;
790    }
791    setring save;
792    LN[i] = simplify(N,2);
793    N     = 0;
794  }
795  setring save;
796  return(LN);
797}
798example
799{
800  "EXAMPLE:"; echo = 2;
801  ring r = 0,(x,y,z),(dp(1),dp(2)); //  ring r = 0,(x,y,z),(a(3,0,2), dp(2));
802  module M = [-1,x,y],[-7,y,y],[3,x,x]; // stands for free poly -xy - 7yy - 3xx
803  module N = [1,x,y,x],[-1,y,x,y]; // stands for free poly xyx - yxy
804  list L; L[1] = M; L[2] = N; // list of modules stands for an ideal in free algebra
805  lst2str(L); // list to string conversion of input polynomials
806  def U = freeGBasis(L,5); // 5 is the degree bound
807  lst2str(U);
808}
809
810static proc crs(list LM, int d)
811"USAGE:  crs(L, d);  L a list of modules, d an integer
812RETURN:  ring
813PURPOSE: create a ring and shift the ideal
814EXAMPLE: example crs; shows examples
815"
816{
817  // d = up to degree, will be shifted to d+1
818  if (d<1) {"bad d"; return(0);}
819
820  int ppl = printlevel-voice+2;
821  string err = "";
822
823  int i,j,s;
824  def save = basering;
825  // determine max no of places in the input
826  int slm = size(LM); // numbers of polys in the ideal
827  int sm;
828  intvec iv;
829  module M;
830  for (i=1; i<=slm; i++)
831  {
832    // modules, e.g. free polynomials
833    M  = LM[i];
834    sm = ncols(M);
835    for (j=1; j<=sm; j++)
836    {
837      //vectors, e.g. free monomials
838      iv = iv, size(M[j])-1; // 1 place is reserved by the coeff
839    }
840  }
841  int D = Max(iv); // max size of input words
842  if (d<D) {"bad d"; return(LM);}
843  D = D + d-1;
844  //  D = d;
845  list LR  = ringlist(save);
846  list L, tmp;
847  L[1] = LR[1]; // ground field
848  L[4] = LR[4]; // quotient ideal
849  tmp  = LR[2]; // varnames
850  s = size(LR[2]);
851  for (i=1; i<=D; i++)
852  {
853    for (j=1; j<=s; j++)
854    {
855      tmp[i*s+j] = string(tmp[j])+"("+string(i)+")";
856    }
857  }
858  for (i=1; i<=s; i++)
859  {
860    tmp[i] = string(tmp[i])+"("+string(0)+")";
861  }
862  L[2] = tmp;
863  list OrigNames = LR[2];
864  // ordering: d blocks of the ord on r
865  // try to get whether the ord on r is blockord itself
866  s = size(LR[3]);
867  if (s==2)
868  {
869    // not a blockord, 1 block + module ord
870    tmp = LR[3][s]; // module ord
871    for (i=1; i<=D; i++)
872    {
873      LR[3][s-1+i] = LR[3][1];
874    }
875    LR[3][s+D] = tmp;
876  }
877  if (s>2)
878  {
879    // there are s-1 blocks
880    int nb = s-1;
881    tmp = LR[3][s]; // module ord
882    for (i=1; i<=D; i++)
883    {
884      for (j=1; j<=nb; j++)
885      {
886        LR[3][i*nb+j] = LR[3][j];
887      }
888    }
889    //    size(LR[3]);
890    LR[3][nb*(D+1)+1] = tmp;
891  }
892  L[3] = LR[3];
893  def @R = ring(L);
894  setring @R;
895  ideal I;
896  poly @p;
897  s = size(OrigNames);
898  //  "s:";s;
899  // convert LM to canonical vectors (no powers)
900  setring save;
901  kill M; // M was defined earlier
902  module M;
903  slm = size(LM); // numbers of polys in the ideal
904  int sv,k,l;
905  vector v;
906  //  poly p;
907  string sp;
908  setring @R;
909  poly @@p=0;
910  setring save;
911  for (l=1; l<=slm; l++)
912  {
913    // modules, e.g. free polynomials
914    M  = LM[l];
915    sm = ncols(M); // in intvec iv the sizes are stored
916    for (i=0; i<=d-iv[l]; i++)
917    {
918      // modules, e.g. free polynomials
919      for (j=1; j<=sm; j++)
920      {
921        //vectors, e.g. free monomials
922        v  = M[j];
923        sv = size(v);
924        //        "sv:";sv;
925        sp = "@@p = @@p + ";
926        for (k=2; k<=sv; k++)
927        {
928          sp = sp + string(v[k])+"("+string(k-2+i)+")*";
929        }
930        sp = sp + string(v[1])+";"; // coef;
931        setring @R;
932        execute(sp);
933        setring save;
934      }
935      setring @R;
936      //      "@@p:"; @@p;
937      I = I,@@p;
938      @@p = 0;
939      setring save;
940    }
941  }
942  setring @R;
943  export I;
944  return(@R);
945}
946example
947{
948  "EXAMPLE:"; echo = 2;
949  ring r = 0,(x,y,z),(dp(1),dp(2));
950  module M = [-1,x,y],[-7,y,y],[3,x,x];
951  module N = [1,x,y,x],[-1,y,x,y];
952  list L; L[1] = M; L[2] = N;
953  lst2str(L);
954  def U = crs(L,5);
955  setring U; U;
956  I;
957}
958
959static proc polylen(ideal I)
960{
961  // returns the ideal of length of polys
962  int i;
963  intvec J;
964  number s = 0;
965  for(i=1;i<=ncols(I);i++)
966  {
967    J[i] = size(I[i]);
968    s = s + J[i];
969  }
970  printf("the sum of length %s",s);
971  //  print(s);
972  return(J);
973}
974
975// new: uniting both mLR1 (homog) and mLR2 (nonhomog)
976proc makeLetterplaceRing(int d, list #)
977"USAGE:  makeLetterplaceRing(d [,h]); d an integer, h an optional integer
978RETURN:  ring
979PURPOSE: creates a ring with the ordering, used in letterplace computations
980NOTE: h = 0 (default) : Dp ordering will be used
981h = 2 : weights 1 used for all the variables, a tie breaker is a list of block of original ring
982h = 1 : the pure homogeneous letterplace block ordering (applicable in the situation of homogeneous input ideals) will be used.
983EXAMPLE: example makeLetterplaceRing; shows examples
984"
985{
986  int alternativeVersion = 0;
987  if ( size(#)>0 )
988  {
989    if (typeof(#[1]) == "int")
990    {
991      alternativeVersion = #[1];
992    }
993  }
994  if (alternativeVersion == 1)
995  {
996    def @A = makeLetterplaceRing1(d);
997  }
998  else {
999    if (alternativeVersion == 2)
1000    {
1001      def @A = makeLetterplaceRing2(d);
1002    }
1003    else {
1004      def @A = makeLetterplaceRing4(d);
1005    }
1006  }
1007  return(@A);
1008}
1009example
1010{
1011  "EXAMPLE:"; echo = 2;
1012  ring r = 0,(x,y,z),(dp(1),dp(2));
1013  def A = makeLetterplaceRing(2); // same as  makeLetterplaceRing(2,0)
1014  setring A;  A;
1015  attrib(A,"isLetterplaceRing");
1016  attrib(A,"uptodeg");  // degree bound
1017  setring r; def B = makeLetterplaceRing(2,1); // to compare:
1018  setring B;  B;
1019  attrib(B,"isLetterplaceRing");
1020  attrib(B,"uptodeg");  // degree bound
1021  setring r; def C = makeLetterplaceRing(2,2); // to compare:
1022  setring C;  C;
1023  attrib(C,"isLetterplaceRing");
1024  attrib(C,"uptodeg");  // degree bound
1025}
1026
1027static proc makeLetterplaceRing1(int d)
1028"USAGE:  makeLetterplaceRing1(d); d an integer
1029RETURN:  ring
1030PURPOSE: creates a ring with a special ordering, suitable for
1031@* the use of homogeneous letterplace (d blocks of shifted original variables)
1032EXAMPLE: example makeLetterplaceRing1; shows examples
1033"
1034{
1035  // d = up to degree, will be shifted to d+1
1036  if (d<1) {"bad d"; return(0);}
1037
1038  int uptodeg = d; int lV = nvars(basering);
1039
1040  int ppl = printlevel-voice+2;
1041  string err = "";
1042
1043  int i,j,s;
1044  def save = basering;
1045  int D = d-1;
1046  list LR  = ringlist(save);
1047  list L, tmp;
1048  L[1] = LR[1]; // ground field
1049  L[4] = LR[4]; // quotient ideal
1050  tmp  = LR[2]; // varnames
1051  s = size(LR[2]);
1052  for (i=1; i<=D; i++)
1053  {
1054    for (j=1; j<=s; j++)
1055    {
1056      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
1057    }
1058  }
1059  for (i=1; i<=s; i++)
1060  {
1061    tmp[i] = string(tmp[i])+"("+string(1)+")";
1062  }
1063  L[2] = tmp;
1064  list OrigNames = LR[2];
1065  // ordering: d blocks of the ord on r
1066  // try to get whether the ord on r is blockord itself
1067  // TODO: make L(2) ordering! exponent is maximally 2
1068  s = size(LR[3]);
1069  if (s==2)
1070  {
1071    // not a blockord, 1 block + module ord
1072    tmp = LR[3][s]; // module ord
1073    for (i=1; i<=D; i++)
1074    {
1075      LR[3][s-1+i] = LR[3][1];
1076    }
1077    LR[3][s+D] = tmp;
1078  }
1079  if (s>2)
1080  {
1081    // there are s-1 blocks
1082    int nb = s-1;
1083    tmp = LR[3][s]; // module ord
1084    for (i=1; i<=D; i++)
1085    {
1086      for (j=1; j<=nb; j++)
1087      {
1088        LR[3][i*nb+j] = LR[3][j];
1089      }
1090    }
1091    //    size(LR[3]);
1092    LR[3][nb*(D+1)+1] = tmp;
1093  }
1094  L[3] = LR[3];
1095  attrib(L,"maxExp",1);
1096  def @R = ring(L);
1097  //  setring @R;
1098  //  int uptodeg = d; int lV = nvars(basering); // were defined before
1099  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
1100  return (@@R);
1101}
1102example
1103{
1104  "EXAMPLE:"; echo = 2;
1105  ring r = 0,(x,y,z),(dp(1),dp(2));
1106  def A = makeLetterplaceRing1(2);
1107  setring A;
1108  A;
1109  attrib(A,"isLetterplaceRing");// number of variables in the main block
1110  attrib(A,"uptodeg");  // degree bound
1111}
1112
1113static proc makeLetterplaceRing2(int d)
1114"USAGE:  makeLetterplaceRing2(d); d an integer
1115RETURN:  ring
1116PURPOSE: creates a ring with a special ordering, suitable for
1117@* the use of non-homogeneous letterplace
1118NOTE: the matrix for the ordering looks as follows: first row is 1,1,...,1
1119@* then there come 'd' blocks of shifted original variables
1120EXAMPLE: example makeLetterplaceRing2; shows examples
1121"
1122{
1123
1124  // ToDo future: inherit positive weights in the orig ring
1125  // complain on nonpositive ones
1126
1127  // d = up to degree, will be shifted to d+1
1128  if (d<1) {"bad d"; return(0);}
1129
1130  int uptodeg = d; int lV = nvars(basering);
1131
1132  int ppl = printlevel-voice+2;
1133  string err = "";
1134
1135  int i,j,s;
1136  def save = basering;
1137  int D = d-1;
1138  list LR  = ringlist(save);
1139  list L, tmp, tmp2, tmp3;
1140  L[1] = LR[1]; // ground field
1141  L[4] = LR[4]; // quotient ideal
1142  tmp  = LR[2]; // varnames
1143  s = size(LR[2]);
1144  for (i=1; i<=D; i++)
1145  {
1146    for (j=1; j<=s; j++)
1147    {
1148      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
1149    }
1150  }
1151  for (i=1; i<=s; i++)
1152  {
1153    tmp[i] = string(tmp[i])+"("+string(1)+")";
1154  }
1155  L[2] = tmp;
1156  list OrigNames = LR[2];
1157  // ordering: one 1..1 a above
1158  // ordering: d blocks of the ord on r
1159  // try to get whether the ord on r is blockord itself
1160  // TODO: make L(2) ordering! exponent is maximally 2
1161  s = size(LR[3]);
1162  if (s==2)
1163  {
1164    // not a blockord, 1 block + module ord
1165    tmp = LR[3][s]; // module ord
1166    for (i=1; i<=d; i++)
1167    {
1168      LR[3][s-1+i] = LR[3][1];
1169    }
1170    //    LR[3][s+D] = tmp;
1171    LR[3][s+1+D] = tmp;
1172    LR[3][1] = list("a",intvec(1: int(d*lV))); // deg-ord
1173  }
1174  if (s>2)
1175  {
1176    // there are s-1 blocks
1177    int nb = s-1;
1178    tmp = LR[3][s]; // module ord to place at the very end
1179    tmp2 = LR[3]; tmp2 = tmp2[1..nb];
1180    tmp3[1] = list("a",intvec(1: int(d*lV))); // deg-ord, insert as the 1st
1181    for (i=1; i<=d; i++)
1182    {
1183      tmp3 = tmp3 + tmp2;
1184    }
1185    tmp3 = tmp3 + list(tmp);
1186    LR[3] = tmp3;
1187//     for (i=1; i<=d; i++)
1188//     {
1189//       for (j=1; j<=nb; j++)
1190//       {
1191//         //        LR[3][i*nb+j+1]= LR[3][j];
1192//         LR[3][i*nb+j+1]= tmp2[j];
1193//       }
1194//     }
1195//     //    size(LR[3]);
1196//     LR[3][(s-1)*d+2] = tmp;
1197//     LR[3] = list("a",intvec(1: int(d*lV))) + LR[3]; // deg-ord, insert as the 1st
1198    // remove everything behind nb*(D+1)+1 ?
1199    //    tmp = LR[3];
1200    //    LR[3] = tmp[1..size(tmp)-1];
1201  }
1202  L[3] = LR[3];
1203  attrib(L,"maxExp",1);
1204  def @R = ring(L);
1205  //  setring @R;
1206  //  int uptodeg = d; int lV = nvars(basering); // were defined before
1207  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
1208  return (@@R);
1209}
1210example
1211{
1212  "EXAMPLE:"; echo = 2;
1213  ring r = 0,(x,y,z),(dp(1),dp(2));
1214  def A = makeLetterplaceRing2(2);
1215  setring A;
1216  A;
1217  attrib(A,"isLetterplaceRing"); // number of variables in the main block
1218  attrib(A,"uptodeg");  // degree bound
1219}
1220
1221static proc makeLetterplaceRing4(int d)
1222"USAGE:  makeLetterplaceRing4(d); d an integer
1223RETURN:  ring
1224PURPOSE: creates a Letterplace ring with a Dp ordering, suitable for
1225@* the use of non-homogeneous letterplace
1226NOTE: the matrix for the ordering looks as follows: first row is 1,1,...,1
1227EXAMPLE: example makeLetterplaceRing4; shows examples
1228"
1229{
1230
1231  // ToDo future: inherit positive weights in the orig ring
1232  // complain on nonpositive ones
1233
1234  // d = up to degree, will be shifted to d+1
1235  if (d<1) {"bad d"; return(0);}
1236
1237  int uptodeg = d; int lV = nvars(basering);
1238
1239  int ppl = printlevel-voice+2;
1240  string err = "";
1241
1242  int i,j,s;
1243  def save = basering;
1244  int D = d-1;
1245  list LR  = ringlist(save);
1246  list L, tmp, tmp2, tmp3;
1247  L[1] = LR[1]; // ground field
1248  L[4] = LR[4]; // quotient ideal
1249  tmp  = LR[2]; // varnames
1250  s = size(LR[2]);
1251  for (i=1; i<=D; i++)
1252  {
1253    for (j=1; j<=s; j++)
1254    {
1255      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
1256    }
1257  }
1258  for (i=1; i<=s; i++)
1259  {
1260    tmp[i] = string(tmp[i])+"("+string(1)+")";
1261  }
1262  L[2] = tmp;
1263  list OrigNames = LR[2];
1264
1265  s = size(LR[3]);
1266  list ordering;
1267  ordering[1] = list("Dp",intvec(1: int(d*lV)));
1268  ordering[2] = LR[3][s]; // module ord to place at the very end
1269  LR[3] = ordering;
1270
1271  L[3] = LR[3];
1272  attrib(L,"maxExp",1);
1273  def @R = ring(L);
1274  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
1275  return (@@R);
1276}
1277example
1278{
1279  "EXAMPLE:"; echo = 2;
1280  ring r = 0,(x,y,z),(dp(1),dp(2));
1281  def A = makeLetterplaceRing4(2);
1282  setring A;
1283  A;
1284  attrib(A,"isLetterplaceRing"); // number of variables in the main block
1285  attrib(A,"uptodeg");  // degree bound
1286}
1287
1288// P[s;sigma] approach
1289static proc makeLetterplaceRing3(int d)
1290"USAGE:  makeLetterplaceRing3(d); d an integer
1291RETURN:  ring
1292PURPOSE: creates a ring with a special ordering, representing
1293@* the original P[s,sigma] (adds d blocks of shifted s)
1294ASSUME: basering is a letterplace ring
1295NOTE: experimental status
1296EXAMPLE: example makeLetterplaceRing3; shows examples
1297"
1298{
1299  // d = up to degree, will be shifted to d+1
1300  if (d<1) {"bad d"; return(0);}
1301
1302  int uptodeg = d; int lV = nvars(basering);
1303
1304  int ppl = printlevel-voice+2;
1305  string err = "";
1306
1307  int i,j,s;
1308  def save = basering;
1309  int D = d-1;
1310  list LR  = ringlist(save);
1311  list L, tmp;
1312  L[1] = LR[1]; // ground field
1313  L[4] = LR[4]; // quotient ideal
1314  tmp  = LR[2]; // varnames
1315  tmp[size(tmp)+1] = "s";
1316  // add s's
1317  //  string newSname = "@s";
1318  s = size(LR[2]);
1319  for (i=1; i<=D; i++)
1320  {
1321    for (j=1; j<=s; j++)
1322    {
1323      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
1324    }
1325  }
1326  // the final index is D*s+s = (D+1)*s = degBound*s
1327  for (i=1; i<=d; i++)
1328  {
1329    tmp[FIndex + i] =  string(newSname)+"("+string(i)+")";
1330  }
1331  L[2] = tmp;
1332  list OrigNames = LR[2];
1333  // ordering: d blocks of the MODIFIED ord on r
1334  // try to get whether the ord on r is blockord itself
1335  // TODO: make L(2) ordering! exponent is maximally 2
1336  s = size(LR[3]);
1337
1338  // assume: basering was a letterplace, so get its block
1339  tmp = LR[3][1]; // ASSUME: it's a nice block
1340  // modify it
1341  // add (0,..,0,1) ... as antiblock part
1342  intvec iv; list ttmp, tmp1;
1343  for (i=1; i<=d; i++)
1344  {
1345    // the position to hold 1:
1346    iv = intvec( gen( i*(lV+1)-1 ) );
1347    ttmp[1] = "a";
1348    ttmp[2] = iv;
1349    tmp1[i] = ttmp;
1350  }
1351  // finished: antiblock part //TOCONTINUE
1352
1353  if (s==2)
1354  {
1355    // not a blockord, 1 block + module ord
1356    tmp = LR[3][s]; // module ord
1357    for (i=1; i<=D; i++)
1358    {
1359      LR[3][s-1+i] = LR[3][1];
1360    }
1361    LR[3][s+D] = tmp;
1362  }
1363  if (s>2)
1364  {
1365    // there are s-1 blocks
1366    int nb = s-1;
1367    tmp = LR[3][s]; // module ord
1368    for (i=1; i<=D; i++)
1369    {
1370      for (j=1; j<=nb; j++)
1371      {
1372        LR[3][i*nb+j] = LR[3][j];
1373      }
1374    }
1375    //    size(LR[3]);
1376    LR[3][nb*(D+1)+1] = tmp;
1377  }
1378  L[3] = LR[3];
1379  attrib(L,"maxExp",1);
1380  def @R = ring(L);
1381  //  setring @R;
1382  //  int uptodeg = d; int lV = nvars(basering); // were defined before
1383  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
1384  return (@@R);
1385}
1386example
1387{
1388  "EXAMPLE:"; echo = 2;
1389  ring r = 0,(x,y,z),(dp(1),dp(2));
1390  def A = makeLetterplaceRing3(2);
1391  setring A;
1392  A;
1393  attrib(A,"isLetterplaceRing"); // number of variables in the main block
1394  attrib(A,"uptodeg");  // degree bound
1395}
1396
1397/* EXAMPLES:
1398
1399//static proc ex_shift()
1400{
1401  LIB "freegb.lib";
1402  ring r = 0,(x,y,z),(dp(1),dp(2));
1403  module M = [-1,x,y],[-7,y,y],[3,x,x];
1404  module N = [1,x,y,x],[-1,y,x,y];
1405  list L; L[1] = M; L[2] = N;
1406  lst2str(L);
1407  def U = crs(L,5);
1408  setring U; U;
1409  I;
1410  poly p = I[2]; // I[8];
1411  p;
1412  system("stest",p,7,7,3); // error -> the world is ok
1413  poly q1 = system("stest",p,1,7,3); //ok
1414  poly q6 = system("stest",p,6,7,3); //ok
1415  system("btest",p,3); //ok
1416  system("btest",q1,3); //ok
1417  system("btest",q6,3); //ok
1418}
1419
1420//static proc test_shrink()
1421{
1422  LIB "freegb.lib";
1423  ring r =0,(x,y,z),dp;
1424  int d = 5;
1425  def R = makeLetterplaceRing(d);
1426  setring R;
1427  poly p1 = x(1)*y(2)*z(3);
1428  poly p2 = x(1)*y(4)*z(5);
1429  poly p3 = x(1)*y(1)*z(3);
1430  poly p4 = x(1)*y(2)*z(2);
1431  poly p5 = x(3)*z(5);
1432  poly p6 = x(1)*y(1)*x(3)*z(5);
1433  poly p7 = x(1)*y(2)*x(3)*y(4)*z(5);
1434  poly p8 = p1+p2+p3+p4+p5 + p6 + p7;
1435  p1; system("shrinktest",p1,3);
1436  p2; system("shrinktest",p2,3);
1437  p3; system("shrinktest",p3,3);
1438  p4; system("shrinktest",p4,3);
1439  p5; system("shrinktest",p5,3);
1440  p6; system("shrinktest",p6,3);
1441  p7; system("shrinktest",p7,3);
1442  p8; system("shrinktest",p8,3);
1443  poly p9 = p1 + 2*p2 + 5*p5 + 7*p7;
1444  p9; system("shrinktest",p9,3);
1445}
1446
1447//static proc ex2()
1448{
1449  option(prot);
1450  LIB "freegb.lib";
1451  ring r = 0,(x,y),dp;
1452  module M = [-1,x,y],[3,x,x]; // 3x^2 - xy
1453  def U = freegb(M,7);
1454  lst2str(U);
1455}
1456
1457//static proc ex_nonhomog()
1458{
1459  option(prot);
1460  LIB "freegb.lib";
1461  ring r = 0,(x,y,h),dp;
1462  list L;
1463  module M;
1464  M = [-1,y,y],[1,x,x,x];  // x3-y2
1465  L[1] = M;
1466  M = [1,x,h],[-1,h,x];  // xh-hx
1467  L[2] = M;
1468  M = [1,y,h],[-1,h,y];  // yh-hy
1469  L[3] = M;
1470  def U = freegb(L,4);
1471  lst2str(U);
1472  // strange elements in the basis
1473}
1474
1475//static proc ex_nonhomog_comm()
1476{
1477  option(prot);
1478  LIB "freegb.lib";
1479  ring r = 0,(x,y),dp;
1480  module M = [-1,y,y],[1,x,x,x];
1481  def U = freegb(M,5);
1482  lst2str(U);
1483}
1484
1485//static proc ex_nonhomog_h()
1486{
1487  option(prot);
1488  LIB "freegb.lib";
1489  ring r = 0,(x,y,h),(a(1,1),dp);
1490  module M = [-1,y,y,h],[1,x,x,x]; // x3 - y2h
1491  def U = freegb(M,6);
1492  lst2str(U);
1493}
1494
1495//static proc ex_nonhomog_h2()
1496{
1497  option(prot);
1498  LIB "freegb.lib";
1499  ring r = 0,(x,y,h),(dp);
1500  list L;
1501  module M;
1502  M = [-1,y,y,h],[1,x,x,x]; // x3 - y2h
1503  L[1] = M;
1504  M = [1,x,h],[-1,h,x]; // xh - hx
1505  L[2] = M;
1506  M = [1,y,h],[-1,h,y]; // yh - hy
1507  L[3] = M;
1508  def U = freeGBasis(L,3);
1509  lst2str(U);
1510  // strange answer CHECK
1511}
1512
1513
1514//static proc ex_nonhomog_3()
1515{
1516  option(prot);
1517  LIB "./freegb.lib";
1518  ring r = 0,(x,y,z),(dp);
1519  list L;
1520  module M;
1521  M = [1,z,y],[-1,x]; // zy - x
1522  L[1] = M;
1523  M = [1,z,x],[-1,y]; // zx - y
1524  L[2] = M;
1525  M = [1,y,x],[-1,z]; // yx - z
1526  L[3] = M;
1527  lst2str(L);
1528  list U = freegb(L,4);
1529  lst2str(U);
1530  // strange answer CHECK
1531}
1532
1533//static proc ex_densep_2()
1534{
1535  option(prot);
1536  LIB "freegb.lib";
1537  ring r = (0,a,b,c),(x,y),(Dp); // deglex
1538  module M = [1,x,x], [a,x,y], [b,y,x], [c,y,y];
1539  lst2str(M);
1540  list U = freegb(M,5);
1541  lst2str(U);
1542  // a=b is important -> finite basis!!!
1543  module M = [1,x,x], [a,x,y], [a,y,x], [c,y,y];
1544  lst2str(M);
1545  list U = freegb(M,5);
1546  lst2str(U);
1547}
1548
1549// END COMMENTED EXAMPLES
1550
1551*/
1552
1553// 1. form a new ring
1554// 2. produce shifted generators
1555// 3. compute GB
1556// 4. skip shifted elts
1557// 5. go back to orig vars, produce strings/modules
1558// 6. return the result
1559
1560static proc freegbold(list LM, int d)
1561"USAGE:  freegbold(L, d);  L a list of modules, d an integer
1562RETURN:  ring
1563PURPOSE: compute the two-sided Groebner basis of an ideal, encoded by L in
1564the free associative algebra, up to degree d
1565EXAMPLE: example freegbold; shows examples
1566"
1567{
1568  // d = up to degree, will be shifted to d+1
1569  if (d<1) {"bad d"; return(0);}
1570
1571  int ppl = printlevel-voice+2;
1572  string err = "";
1573
1574  int i,j,s;
1575  def save = basering;
1576  // determine max no of places in the input
1577  int slm = size(LM); // numbers of polys in the ideal
1578  int sm;
1579  intvec iv;
1580  module M;
1581  for (i=1; i<=slm; i++)
1582  {
1583    // modules, e.g. free polynomials
1584    M  = LM[i];
1585    sm = ncols(M);
1586    for (j=1; j<=sm; j++)
1587    {
1588      //vectors, e.g. free monomials
1589      iv = iv, size(M[j])-1; // 1 place is reserved by the coeff
1590    }
1591  }
1592  int D = Max(iv); // max size of input words
1593  if (d<D) {"bad d"; return(LM);}
1594  D = D + d-1;
1595  //  D = d;
1596  list LR  = ringlist(save);
1597  list L, tmp;
1598  L[1] = LR[1]; // ground field
1599  L[4] = LR[4]; // quotient ideal
1600  tmp  = LR[2]; // varnames
1601  s = size(LR[2]);
1602  for (i=1; i<=D; i++)
1603  {
1604    for (j=1; j<=s; j++)
1605    {
1606      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
1607    }
1608  }
1609  for (i=1; i<=s; i++)
1610  {
1611    tmp[i] = string(tmp[i])+"("+string(1)+")";
1612  }
1613  L[2] = tmp;
1614  list OrigNames = LR[2];
1615  // ordering: d blocks of the ord on r
1616  // try to get whether the ord on r is blockord itself
1617  // TODO: make L(2) ordering! exponent is maximally 2
1618  s = size(LR[3]);
1619  if (s==2)
1620  {
1621    // not a blockord, 1 block + module ord
1622    tmp = LR[3][s]; // module ord
1623    for (i=1; i<=D; i++)
1624    {
1625      LR[3][s-1+i] = LR[3][1];
1626    }
1627    LR[3][s+D] = tmp;
1628  }
1629  if (s>2)
1630  {
1631    // there are s-1 blocks
1632    int nb = s-1;
1633    tmp = LR[3][s]; // module ord
1634    for (i=1; i<=D; i++)
1635    {
1636      for (j=1; j<=nb; j++)
1637      {
1638        LR[3][i*nb+j] = LR[3][j];
1639      }
1640    }
1641    //    size(LR[3]);
1642    LR[3][nb*(D+1)+1] = tmp;
1643  }
1644  L[3] = LR[3];
1645  def @R = ring(L);
1646  setring @R;
1647  ideal I;
1648  poly @p;
1649  s = size(OrigNames);
1650  //  "s:";s;
1651  // convert LM to canonical vectors (no powers)
1652  setring save;
1653  kill M; // M was defined earlier
1654  module M;
1655  slm = size(LM); // numbers of polys in the ideal
1656  int sv,k,l;
1657  vector v;
1658  //  poly p;
1659  string sp;
1660  setring @R;
1661  poly @@p=0;
1662  setring save;
1663  for (l=1; l<=slm; l++)
1664  {
1665    // modules, e.g. free polynomials
1666    M  = LM[l];
1667    sm = ncols(M); // in intvec iv the sizes are stored
1668    for (i=0; i<=d-iv[l]; i++)
1669    {
1670      // modules, e.g. free polynomials
1671      for (j=1; j<=sm; j++)
1672      {
1673        //vectors, e.g. free monomials
1674        v  = M[j];
1675        sv = size(v);
1676        //        "sv:";sv;
1677        sp = "@@p = @@p + ";
1678        for (k=2; k<=sv; k++)
1679        {
1680          sp = sp + string(v[k])+"("+string(k-1+i)+")*";
1681        }
1682        sp = sp + string(v[1])+";"; // coef;
1683        setring @R;
1684        execute(sp);
1685        setring save;
1686      }
1687      setring @R;
1688      //      "@@p:"; @@p;
1689      I = I,@@p;
1690      @@p = 0;
1691      setring save;
1692    }
1693  }
1694  kill sp;
1695  // 3. compute GB
1696  setring @R;
1697  dbprint(ppl,"computing GB");
1698  //  ideal J = groebner(I);
1699  ideal J = slimgb(I);
1700  dbprint(ppl,J);
1701  // 4. skip shifted elts
1702  ideal K = select1(J,1..s); // s = size(OrigNames)
1703  dbprint(ppl,K);
1704  dbprint(ppl, "done with GB");
1705  // K contains vars x(1),...z(1) = images of originals
1706  // 5. go back to orig vars, produce strings/modules
1707  if (K[1] == 0)
1708  {
1709    "no reasonable output, GB gives 0";
1710    return(0);
1711  }
1712  int sk = size(K);
1713  int sp, sx, a, b;
1714  intvec x;
1715  poly p,q;
1716  poly pn;
1717  // vars in 'save'
1718  setring save;
1719  module N;
1720  list LN;
1721  vector V;
1722  poly pn;
1723  // test and skip exponents >=2
1724  setring @R;
1725  for(i=1; i<=sk; i++)
1726  {
1727    p  = K[i];
1728    while (p!=0)
1729    {
1730      q  = lead(p);
1731      //      "processing q:";q;
1732      x  = leadexp(q);
1733      sx = size(x);
1734      for(k=1; k<=sx; k++)
1735      {
1736        if ( x[k] >= 2 )
1737        {
1738          err = "skip: the value x[k] is " + string(x[k]);
1739          dbprint(ppl,err);
1740          //            return(0);
1741          K[i] = 0;
1742          p    = 0;
1743          q    = 0;
1744          break;
1745        }
1746      }
1747      p  = p - q;
1748    }
1749  }
1750  K  = simplify(K,2);
1751  sk = size(K);
1752  for(i=1; i<=sk; i++)
1753  {
1754    //    setring save;
1755    //    V  = 0;
1756    setring @R;
1757    p  = K[i];
1758    while (p!=0)
1759    {
1760      q  = lead(p);
1761      err =  "processing q:" + string(q);
1762      dbprint(ppl,err);
1763      x  = leadexp(q);
1764      sx = size(x);
1765      pn = leadcoef(q);
1766      setring save;
1767      pn = imap(@R,pn);
1768      V  = V + leadcoef(pn)*gen(1);
1769      for(k=1; k<=sx; k++)
1770      {
1771        if (x[k] ==1)
1772        {
1773          a = k div s; // block number=a+1, a!=0
1774          b = k % s; // remainder
1775          //          printf("a: %s, b: %s",a,b);
1776          if (b == 0)
1777          {
1778            // that is it's the last var in the block
1779            b = s;
1780            a = a-1;
1781          }
1782          V = V + var(b)*gen(a+2);
1783        }
1784//         else
1785//         {
1786//           printf("error: the value x[k] is %s", x[k]);
1787//           return(0);
1788//         }
1789      }
1790      err = "V: " + string(V);
1791      dbprint(ppl,err);
1792      //      printf("V: %s", string(V));
1793      N = N,V;
1794      V  = 0;
1795      setring @R;
1796      p  = p - q;
1797      pn = 0;
1798    }
1799    setring save;
1800    LN[i] = simplify(N,2);
1801    N     = 0;
1802  }
1803  setring save;
1804  return(LN);
1805}
1806example
1807{
1808  "EXAMPLE:"; echo = 2;
1809  ring r = 0,(x,y,z),(dp(1),dp(2));
1810  module M = [-1,x,y],[-7,y,y],[3,x,x];
1811  module N = [1,x,y,x],[-1,y,x,y];
1812  list L; L[1] = M; L[2] = N;
1813  lst2str(L);
1814  def U = freegbold(L,5);
1815  lst2str(U);
1816}
1817
1818/* begin older procs and tests
1819
1820static proc sgb(ideal I, int d)
1821{
1822  // new code
1823  // map x_i to x_i(1) via map()
1824  //LIB "freegb.lib";
1825  def save = basering;
1826  //int d =7;// degree
1827  int nv = nvars(save);
1828  def R = makeLetterplaceRing(d);
1829  setring R;
1830  int i;
1831  ideal Imap;
1832  for (i=1; i<=nv; i++)
1833  {
1834    Imap[i] = var(i);
1835  }
1836  //ideal I = x(1)*y(2), y(1)*x(2)+z(1)*z(2);
1837  ideal I = x(1)*x(2),x(1)*y(2) + z(1)*x(2);
1838  option(prot);
1839  //option(teach);
1840  ideal J = system("freegb",I,d,nv);
1841}
1842
1843static proc checkCeq()
1844{
1845  ring r = 0,(x,y),Dp;
1846  def A = makeLetterplaceRing(4);
1847  setring A;
1848  A;
1849  // I = x2-xy
1850  ideal I = x(1)*x(2) - x(1)*y(2), x(2)*x(3) - x(2)*y(3), x(3)*x(4) - x(3)*y(4);
1851  ideal C = x(2)-x(1),x(3)-x(2),x(4)-x(3),y(2)-y(1),y(3)-y(2),y(4)-y(3);
1852  ideal K = I,C;
1853  groebner(K);
1854}
1855
1856static proc exHom1()
1857{
1858  // we start with
1859  // z*y - x, z*x - y, y*x - z
1860  LIB "freegb.lib";
1861  LIB "elim.lib";
1862  ring r = 0,(x,y,z,h),dp;
1863  list L;
1864  module M;
1865  M = [1,z,y],[-1,x,h]; // zy - xh
1866  L[1] = M;
1867  M = [1,z,x],[-1,y,h]; // zx - yh
1868  L[2] = M;
1869  M = [1,y,x],[-1,z,h]; // yx - zh
1870  L[3] = M;
1871  lst2str(L);
1872  def U = crs(L,4);
1873  setring U;
1874  I = I,
1875    y(2)*h(3)+z(2)*x(3),     y(3)*h(4)+z(3)*x(4),
1876    y(2)*x(3)-z(2)*h(3),     y(3)*x(4)-z(3)*h(4);
1877  I = simplify(I,2);
1878  ring r2 = 0,(x(0..4),y(0..4),z(0..4),h(0..4)),dp;
1879  ideal J = imap(U,I);
1880  //  ideal K = homog(J,h);
1881  option(redSB);
1882  option(redTail);
1883  ideal L = groebner(J); //(K);
1884  ideal LL = sat(L,ideal(h))[1];
1885  ideal M = subst(LL,h,1);
1886  M = simplify(M,2);
1887  setring U;
1888  ideal M = imap(r2,M);
1889  lst2str(U);
1890}
1891
1892static proc test1()
1893{
1894  LIB "freegb.lib";
1895  ring r = 0,(x,y),Dp;
1896  int d = 10; // degree
1897  def R = makeLetterplaceRing(d);
1898  setring R;
1899  ideal I = x(1)*x(2) - y(1)*y(2);
1900  option(prot);
1901  option(teach);
1902  ideal J = system("freegb",I,d,2);
1903  J;
1904}
1905
1906static proc test2()
1907{
1908  LIB "freegb.lib";
1909  ring r = 0,(x,y),Dp;
1910  int d = 10; // degree
1911  def R = makeLetterplaceRing(d);
1912  setring R;
1913  ideal I = x(1)*x(2) - x(1)*y(2);
1914  option(prot);
1915  option(teach);
1916  ideal J = system("freegb",I,d,2);
1917  J;
1918}
1919
1920static proc test3()
1921{
1922  LIB "freegb.lib";
1923  ring r = 0,(x,y,z),dp;
1924  int d =5; // degree
1925  def R = makeLetterplaceRing(d);
1926  setring R;
1927  ideal I = x(1)*y(2), y(1)*x(2)+z(1)*z(2);
1928  option(prot);
1929  option(teach);
1930  ideal J = system("freegb",I,d,3);
1931}
1932
1933static proc schur2-3()
1934{
1935  // nonhomog:
1936  //  h^4-10*h^2+9,f*e-e*f+h, h*2-e*h-2*e,h*f-f*h+2*f
1937  // homogenized with t
1938  //  h^4-10*h^2*t^2+9*t^4,f*e-e*f+h*t, h*2-e*h-2*e*t,h*f-f*h+2*f*t,
1939  // t*h - h*t, t*f - f*t, t*e - e*t
1940}
1941
1942end older procs and tests */
1943
1944proc ademRelations(int i, int j)
1945"USAGE:  ademRelations(i,j); i,j int
1946RETURN:  ring (and exports ideal)
1947ASSUME: there are at least i+j variables in the basering
1948PURPOSE: compute the ideal of Adem relations for i<2j in characteristic 0
1949@*  the ideal is exported under the name AdemRel in the output ring
1950EXAMPLE: example ademRelations; shows examples
1951"
1952{
1953  // produces Adem relations for i<2j in char 0
1954  // assume: 0<i<2j
1955  // requires presence of vars up to i+j
1956  if ( (i<0) || (i >= 2*j) )
1957  {
1958    ERROR("arguments out of range"); return(0);
1959  }
1960  ring @r = 0,(s(i+j..0)),lp;
1961  poly p,q;
1962  number n;
1963  int ii = i div 2; int k;
1964  // k=0 => s(0)=1
1965  n = binomial(j-1,i);
1966  q = n*s(i+j)*s(0);
1967  //  printf("k=0, term=%s",q);
1968  p = p + q;
1969  for (k=1; k<= ii; k++)
1970  {
1971    n = binomial(j-k-1,i-2*k);
1972    q = n*s(i+j-k)*s(k);;
1973    //    printf("k=%s, term=%s",k,q);
1974    p = p + q;
1975  }
1976  poly AdemRel = p;
1977  export AdemRel;
1978  return(@r);
1979}
1980example
1981{
1982  "EXAMPLE:"; echo = 2;
1983  def A = ademRelations(2,5);
1984  setring A;
1985  AdemRel;
1986}
1987
1988/*
19891,1: 0
19901,2: s(3)*s(0) == s(3) -> def for s(3):=s(1)s(2)
19912,1: adm
19922,2: s(3)*s(1) == s(1)s(2)s(1)
19931,3: 0 ( since 2*s(4)*s(0) = 0 mod 2)
19943,1: adm
19952,3: s(5)*s(0)+s(4)*s(1) == s(5)+s(4)*s(1)
19963,2: 0
19973,3: s(5)*s(1)
19981,4: 3*s(5)*s(0) == s(5)  -> def for s(5):=s(1)*s(4)
19994,1: adm
20002,4: 3*s(6)*s(0)+s(5)*s(1) == s(6) + s(5)*s(1) == s(6) + s(1)*s(4)*s(1)
20014,2: adm
20024,3: s(5)*s(2)
20033,4: s(7)*s(0)+2*s(6)*s(1) == s(7) -> def for s(7):=s(3)*s(4)
20044,4: s(7)*s(1)+s(6)*s(2)
2005*/
2006
2007/* s1,s2:
2008s1*s1 =0, s2*s2 = s1*s2*s1
2009*/
2010
2011/*
2012try char 0:
2013s1,s2:
2014s1*s1 =0, s2*s2 = s1*s2*s1, s(1)*s(3)== s(1)*s(1)*s(3) == 0 = 2*s(4) ->def for s(4)
2015hence 2==0! only in char 2
2016 */
2017
2018  // Adem rels modulo 2 are interesting
2019
2020static proc stringpoly2lplace(string s)
2021{
2022  // decomposes sentence into terms
2023  s = replace(s,newline,""); // get rid of newlines
2024  s = replace(s," ",""); // get rid of empties
2025  //arith symbols: +,-
2026  // decompose into words with coeffs
2027  list LS;
2028  int i,j,ie,je,k,cnt;
2029  // s[1]="-" situation
2030  if (s[1]=="-")
2031  {
2032    LS = stringpoly2lplace(string(s[2..size(s)]));
2033    LS[1] = string("-"+string(LS[1]));
2034    return(LS);
2035  }
2036  i = find(s,"-",2);
2037  // i==1 might happen if the 1st symbol coeff is negative
2038  j = find(s,"+");
2039  list LL;
2040  if (i==j)
2041  {
2042    "return a monomial";
2043    // that is both are 0 -> s is a monomial
2044    LS[1] = s;
2045    return(LS);
2046  }
2047  if (i==0)
2048  {
2049    "i==0 situation";
2050    // no minuses at all => pluses only
2051    cnt++;
2052    LS[cnt] = string(s[1..j-1]);
2053    s = s[j+1..size(s)];
2054    while (s!= "")
2055    {
2056      j = find(s,"+");
2057      cnt++;
2058      if (j==0)
2059      {
2060        LS[cnt] = string(s);
2061        s = "";
2062      }
2063      else
2064      {
2065        LS[cnt] = string(s[1..j-1]);
2066        s = s[j+1..size(s)];
2067      }
2068    }
2069    return(LS);
2070  }
2071  if (j==0)
2072  {
2073    "j==0 situation";
2074    // no pluses at all except the lead coef => the rest are minuses only
2075    cnt++;
2076    LS[cnt] = string(s[1..i-1]);
2077    s = s[i..size(s)];
2078    while (s!= "")
2079    {
2080      i = find(s,"-",2);
2081      cnt++;
2082      if (i==0)
2083      {
2084        LS[cnt] = string(s);
2085        s = "";
2086      }
2087      else
2088      {
2089        LS[cnt] = string(s[1..i-1]);
2090        s = s[i..size(s)];
2091      }
2092    }
2093    return(LS);
2094  }
2095  // now i, j are nonzero
2096  if (i>j)
2097  {
2098    "i>j situation";
2099    // + comes first, at place j
2100    cnt++;
2101    //    "cnt:"; cnt; "j:"; j;
2102    LS[cnt] = string(s[1..j-1]);
2103    s = s[j+1..size(s)];
2104    LL = stringpoly2lplace(s);
2105    LS = LS + LL;
2106    kill LL;
2107    return(LS);
2108  }
2109  else
2110  {
2111    "j>i situation";
2112    // - might come first, at place i
2113    if (i>1)
2114    {
2115      cnt++;
2116      LS[cnt] = string(s[1..i-1]);
2117      s = s[i..size(s)];
2118    }
2119    else
2120    {
2121      // i==1->  minus at leadcoef
2122      ie = find(s,"-",i+1);
2123      je = find(s,"+",i+1);
2124      if (je == ie)
2125      {
2126         "ie=je situation";
2127        //monomial
2128        cnt++;
2129        LS[cnt] = s;
2130        return(LS);
2131      }
2132      if (je < ie)
2133      {
2134         "je<ie situation";
2135        // + comes first
2136        cnt++;
2137        LS[cnt] = s[1..je-1];
2138        s = s[je+1..size(s)];
2139      }
2140      else
2141      {
2142        // ie < je
2143         "ie<je situation";
2144        cnt++;
2145        LS[cnt] = s[1..ie-1];
2146        s = s[ie..size(s)];
2147      }
2148    }
2149    "going into recursion with "+s;
2150    LL = stringpoly2lplace(s);
2151    LS = LS + LL;
2152    return(LS);
2153  }
2154}
2155example
2156{
2157  "EXAMPLE:"; echo = 2;
2158  string s = "x*y+y*z+z*t"; // + only
2159  stringpoly2lplace(s);
2160  string s2 = "x*y - y*z-z*t*w*w"; // +1, - only
2161  stringpoly2lplace(s2);
2162  string s3 = "-x*y + y - 2*x +7*w*w*w";
2163  stringpoly2lplace(s3);
2164}
2165
2166static proc addplaces(list L)
2167{
2168  // adds places to the list of strings
2169  // according to their order in the list
2170  int s = size(L);
2171  int i;
2172  for (i=1; i<=s; i++)
2173  {
2174    if (typeof(L[i]) == "string")
2175    {
2176      L[i] = L[i] + "(" + string(i) + ")";
2177    }
2178    else
2179    {
2180      ERROR("entry of type string expected");
2181      return(0);
2182    }
2183  }
2184  return(L);
2185}
2186example
2187{
2188  "EXAMPLE:"; echo = 2;
2189  string a = "f1";   string b = "f2";
2190  list L = a,b,a;
2191  addplaces(L);
2192}
2193
2194static proc sent2lplace(string s)
2195{
2196  // SENTence of words TO LetterPLACE
2197  list L =   stringpoly2lplace(s);
2198  int i; int ss = size(L);
2199  for(i=1; i<=ss; i++)
2200  {
2201    L[i] = str2lplace(L[i]);
2202  }
2203  return(L);
2204}
2205example
2206{
2207  "EXAMPLE:"; echo = 2;
2208  ring r = 0,(f2,f1),dp;
2209  string s = "f2*f1*f1 - 2*f1*f2*f1+ f1*f1*f2";
2210  sent2lplace(s);
2211}
2212
2213static proc testnumber(string s)
2214{
2215  string t;
2216  if (s[1]=="-")
2217  {
2218    // two situations: either there's a negative number
2219    t = s[2..size(s)];
2220    if (testnumber(t))
2221    {
2222      //a negative number
2223    }
2224    else
2225    {
2226      // a variable times -1
2227    }
2228    // or just a "-" for -1
2229  }
2230  t = "ring @r=(";
2231  t = t + charstr(basering)+"),";
2232  t = t + string(var(1))+",dp;";
2233  //  write(":w tstnum.tst",t);
2234  t = t+ "number @@Nn = " + s + ";"+"$";
2235  write(":w tstnum.tst",t);
2236  string runsing = system("Singular");
2237  int k;
2238  t = runsing+ " -teq <tstnum.tst >tstnum.out";
2239  k = system("sh",t);
2240  if (k!=0)
2241  {
2242    ERROR("Problems running Singular");
2243  }
2244  int i = system("sh", "grep error tstnum.out > /dev/NULL");
2245  if (i!=0)
2246  {
2247    // no error: s is a number
2248    i = 1;
2249  }
2250  k = system("sh","rm tstnum.tst tstnum.out > /dev/NULL");
2251  return(i);
2252}
2253example
2254{
2255  "EXAMPLE:"; echo = 2;
2256  ring r = (0,a),x,dp;
2257  string s = "a^2+7*a-2";
2258  testnumber(s);
2259  s = "b+a";
2260  testnumber(s);
2261}
2262
2263static proc str2lplace(string s)
2264{
2265  // converts a word (monomial) with coeff into letter-place
2266  // string: coef*var1^exp1*var2^exp2*...varN^expN
2267  s = strpower2rep(s); // expand powers
2268  if (size(s)==0) { return(0); }
2269  int i,j,k,insC;
2270  string a,b,c,d,t;
2271  // 1. get coeff
2272  i = find(s,"*");
2273  if (i==0) { return(s); }
2274  list VN;
2275  c = s[1..i-1]; // incl. the case like (-a^2+1)
2276  int tn = testnumber(c);
2277  if (tn == 0)
2278  {
2279    // failed test
2280    if (c[1]=="-")
2281    {
2282      // two situations: either there's a negative number
2283      t = c[2..size(c)];
2284      if (testnumber(t))
2285      {
2286         //a negative number
2287        // nop here
2288      }
2289      else
2290      {
2291         // a variable times -1
2292          c = "-1";
2293          j++; VN[j] = t; //string(c[2..size(c)]);
2294          insC = 1;
2295      }
2296    }
2297    else
2298    {
2299      // just a variable with coeff 1
2300          j++; VN[j] = string(c);
2301          c = "1";
2302          insC = 1;
2303    }
2304  }
2305 // get vars
2306  t = s;
2307  //  t = s[i+1..size(s)];
2308  k = size(t); //j = 0;
2309  while (k>0)
2310  {
2311    t = t[i+1..size(t)]; //next part
2312    i = find(t,"*"); // next *
2313    if (i==0)
2314    {
2315      // last monomial
2316      j++;
2317      VN[j] = t;
2318      k = size(t);
2319      break;
2320    }
2321    b = t[1..i-1];
2322    //    print(b);
2323    j++;
2324    VN[j] = b;
2325    k = size(t);
2326  }
2327  VN = addplaces(VN);
2328  VN[size(VN)+1] = string(c);
2329  return(VN);
2330}
2331example
2332{
2333  "EXAMPLE:"; echo = 2;
2334  ring r = (0,a),(f2,f1),dp;
2335  str2lplace("-2*f2^2*f1^2*f2");
2336  str2lplace("-f1*f2");
2337  str2lplace("(-a^2+7a)*f1*f2");
2338}
2339
2340static proc strpower2rep(string s)
2341{
2342  // makes x*x*x*x out of x^4 ., rep statys for repetitions
2343  // looks for "-" problem
2344  // exception: "-" as coeff
2345  string ex,t;
2346  int i,j,k;
2347
2348  i = find(s,"^"); // first ^
2349  if (i==0) { return(s); } // no ^ signs
2350
2351  if (s[1] == "-")
2352  {
2353    // either -coef or -1
2354    // got the coeff:
2355    i = find(s,"*");
2356    if (i==0)
2357    {
2358      // no *'s   => coef == -1 or s == -23
2359      i = size(s)+1;
2360    }
2361    t = string(s[2..i-1]); // without "-"
2362    if ( testnumber(t) )
2363    {
2364      // a good number
2365      t = strpower2rep(string(s[2..size(s)]));
2366      t = "-"+t;
2367      return(t);
2368    }
2369    else
2370    {
2371      // a variable
2372      t = strpower2rep(string(s[2..size(s)]));
2373      t = "-1*"+ t;
2374      return(t);
2375    }
2376  }
2377  // the case when leadcoef is a number in ()
2378  if (s[1] == "(")
2379  {
2380    i = find(s,")",2);    // must be nonzero
2381    t = s[2..i-1];
2382    if ( testnumber(t) )
2383    {
2384      // a good number
2385    }
2386    else {"strpower2rep: bad number as coef";}
2387    ex = string(s[i+2..size(s)]); // 2 because of *
2388    ex =  strpower2rep(ex);
2389    t = "("+t+")*"+ex;
2390    return(t);
2391  }
2392
2393  i = find(s,"^"); // first ^
2394  j = find(s,"*",i+1); // next * == end of ^
2395  if (j==0)
2396  {
2397    ex = s[i+1..size(s)];
2398  }
2399  else
2400  {
2401    ex = s[i+1..j-1];
2402  }
2403  execute("int @exp = " + ex + ";"); //@exp = exponent
2404  // got varname
2405  for (k=i-1; k>0; k--)
2406  {
2407    if (s[k] == "*") break;
2408  }
2409  string varn = s[k+1..i-1];
2410  //  "varn:";  varn;
2411  string pref;
2412  if (k>0)
2413  {
2414    pref = s[1..k]; // with * on the k-th place
2415  }
2416  //  "pref:";  pref;
2417  string suf;
2418  if ( (j>0) && (j+1 <= size(s)) )
2419  {
2420    suf = s[j+1..size(s)]; // without * on the 1st place
2421  }
2422  //  "suf:"; suf;
2423  string toins;
2424  for (k=1; k<=@exp; k++)
2425  {
2426    toins = toins + varn+"*";
2427  }
2428  //  "toins: ";  toins;
2429  if (size(suf) == 0)
2430  {
2431    toins = toins[1..size(toins)-1]; // get rid of trailing *
2432  }
2433  else
2434  {
2435    suf = strpower2rep(suf);
2436  }
2437  ex = pref + toins + suf;
2438  return(ex);
2439  //  return(strpower2rep(ex));
2440}
2441example
2442{
2443  "EXAMPLE:"; echo = 2;
2444  ring r = (0,a),(x,y,z,t),dp;
2445  strpower2rep("-x^4");
2446  strpower2rep("-2*x^4*y^3*z*t^2");
2447  strpower2rep("-a^2*x^4");
2448}
2449
2450proc lieBracket(poly a, poly b, list #)
2451"USAGE:  lieBracket(a,b[,N]); a,b letterplace polynomials, N an optional integer
2452RETURN:  poly
2453ASSUME: basering has a letterplace ring structure
2454PURPOSE:compute the Lie bracket [a,b] = ab - ba between letterplace polynomials
2455NOTE: if N>1 is specified, then the left normed bracket [a,[...[a,b]]]] is
2456@*    computed.
2457EXAMPLE: example lieBracket; shows examples
2458"
2459{
2460  if (lpAssumeViolation())
2461  {
2462    //    ERROR("Either 'uptodeg' or 'lV' global variables are not set!");
2463    ERROR("Incomplete Letterplace structure on the basering!");
2464  }
2465  // alias ppLiebr;
2466  //if int N is given compute [a,[...[a,b]]]] left normed bracket
2467  poly q;
2468  int N=1;
2469  if (size(#)>0)
2470  {
2471    if (typeof(#[1])=="int")
2472    {
2473      N = int(#[1]);
2474    }
2475  }
2476  if (N<=0) { return(q); }
2477  while (b!=0)
2478  {
2479    q = q + pmLiebr(a,lead(b));
2480    b = b - lead(b);
2481  }
2482  int i;
2483  if (N >1)
2484  {
2485    for(i=1; i<=N-1; i++)
2486    {
2487      q = lieBracket(a,q);
2488    }
2489  }
2490  return(q);
2491}
2492example
2493{
2494  "EXAMPLE:"; echo = 2;
2495  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
2496  def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure
2497  setring R;
2498  poly a = x(1)*y(2); poly b = y(1);
2499  lieBracket(a,b);
2500  lieBracket(x(1),y(1),2);
2501}
2502
2503static proc pmLiebr(poly a, poly b)
2504{
2505  //  a poly, b mono
2506  poly s;
2507  while (a!=0)
2508  {
2509    s = s + mmLiebr(lead(a),lead(b));
2510    a = a - lead(a);
2511  }
2512  return(s);
2513}
2514
2515proc shiftPoly(poly a, int i)
2516"USAGE:  shiftPoly(p,i); p letterplace poly, i int
2517RETURN: poly
2518ASSUME: basering has letterplace ring structure
2519PURPOSE: compute the i-th shift of letterplace polynomial p
2520EXAMPLE: example shiftPoly; shows examples
2521"
2522{
2523  // shifts a monomial a by i
2524  // calls pLPshift(p,sh,uptodeg,lVblock);
2525  if (lpAssumeViolation())
2526  {
2527    ERROR("Incomplete Letterplace structure on the basering!");
2528  }
2529  int uptodeg = attrib(basering,"uptodeg");
2530  int lV = attrib(basering,"isLetterplaceRing");
2531  return(system("stest",a,i,uptodeg,lV));
2532}
2533example
2534{
2535  "EXAMPLE:"; echo = 2;
2536  ring r = 0,(x,y,z),dp;
2537  int uptodeg = 5; int lV = 3;
2538  def R = makeLetterplaceRing(uptodeg);
2539  setring R;
2540  poly f = x(1)*z(2)*y(3) - 2*z(1)*y(2) + 3*x(1);
2541  shiftPoly(f,1);
2542  shiftPoly(f,2);
2543}
2544
2545proc lastBlock(poly p)
2546"USAGE:  lastBlock(p); p letterplace poly
2547RETURN: int
2548ASSUME: basering has letterplace ring structure
2549PURPOSE: get the number of the last block occuring in the poly
2550EXAMPLE: example lastBlock; shows examples
2551"
2552{
2553  if (lpAssumeViolation())
2554  {
2555    ERROR("Incomplete Letterplace structure on the basering!");
2556  }
2557  int lV = attrib(basering,"isLetterplaceRing");
2558  // calls pLastVblock(p,lV);
2559  return(system("btest",p,lV));
2560}
2561example
2562{
2563  "EXAMPLE:"; echo = 2;
2564  ring r = 0,(x,y,z),dp;
2565  int uptodeg = 5;
2566  def R = makeLetterplaceRing(uptodeg);
2567  setring R;
2568  poly f = x(1)*z(2)*y(3) - 2*z(1)*y(2) + 3*x(1);
2569  lastBlock(f); // should be 3
2570}
2571
2572static proc mmLiebr(poly a, poly b)
2573{
2574  // a,b, monomials
2575  a = lead(a);
2576  b = lead(b);
2577  int sa = deg(a);
2578  int sb = deg(b);
2579  poly v = a*shiftPoly(b,sa) - b*shiftPoly(a,sb);
2580  return(v);
2581}
2582
2583static proc test_shift()
2584{
2585  LIB "freegb.lib";
2586  ring r = 0,(a,b),dp;
2587  int d =5;
2588  def R = makeLetterplaceRing(d);
2589  setring R;
2590  int uptodeg = d;
2591  int lV = 2;
2592  def R = setLetterplaceAttributes(r,uptodeg,2); // supply R with letterplace structure
2593  setring R;
2594  poly p = mmLiebr(a(1),b(1));
2595  poly p = lieBracket(a(1),b(1));
2596}
2597
2598proc serreRelations(intmat A, int zu)
2599"USAGE:  serreRelations(A,z); A an intmat, z an int
2600RETURN:  ideal
2601ASSUME: basering has a letterplace ring structure and
2602@*          A is a generalized Cartan matrix with integer entries
2603PURPOSE: compute the ideal of Serre's relations associated to A
2604EXAMPLE: example serreRelations; shows examples
2605"
2606{
2607  // zu = 1 -> with commutators [f_i,f_j]; zu == 0 without them
2608  // suppose that A is cartan matrix
2609  // then Serre's relations are
2610  // (ad f_j)^{1-A_{ij}} ( f_i)
2611  int ppl = printlevel-voice+2;
2612  int n = ncols(A); // hence n variables
2613  int i,j,k,el;
2614  poly p,q;
2615  ideal I;
2616  for (i=1; i<=n; i++)
2617  {
2618    for (j=1; j<=n; j++)
2619    {
2620      el = 1 - A[i,j];
2621      //     printf("i:%s, j: %s, l: %s",i,j,l);
2622      dbprint(ppl,"i, j, l: ",i,j,el);
2623      //      if ((i!=j) && (l >0))
2624      //      if ( (i!=j) &&  ( ((zu ==0) &&  (l >=2)) || ((zu ==1) &&  (l >=1)) ) )
2625      if ((i!=j) && (el >0))
2626      {
2627        q = lieBracket(var(j),var(i));
2628        dbprint(ppl,"first bracket: ",q);
2629        //        if (l >=2)
2630        //        {
2631          for (k=1; k<=el-1; k++)
2632          {
2633            q = lieBracket(var(j),q);
2634            dbprint(ppl,"further bracket:",q);
2635          }
2636          //        }
2637      }
2638      if (q!=0) { I = I,q; q=0;}
2639    }
2640  }
2641  I = simplify(I,2);
2642  return(I);
2643}
2644example
2645{
2646  "EXAMPLE:"; echo = 2;
2647  intmat A[3][3] =
2648    2, -1, 0,
2649    -1, 2, -3,
2650    0, -1, 2; // G^1_2 Cartan matrix
2651  ring r = 0,(f1,f2,f3),dp;
2652  int uptodeg = 5;
2653  def R = makeLetterplaceRing(uptodeg);
2654  setring R;
2655  ideal I = serreRelations(A,1); I = simplify(I,1+2+8);
2656  I;
2657}
2658
2659/* setup for older example:
2660  intmat A[2][2] = 2, -1, -1, 2; // sl_3 == A_2
2661  ring r = 0,(f1,f2),dp;
2662  int uptodeg = 5; int lV = 2;
2663*/
2664
2665proc fullSerreRelations(intmat A, ideal rNegative, ideal rCartan, ideal rPositive, int uptodeg)
2666"USAGE:  fullSerreRelations(A,N,C,P,d); A an intmat, N,C,P ideals, d an int
2667RETURN:  ring (and ideal)
2668PURPOSE: compute the inhomogeneous Serre's relations associated to A in given
2669@*       variable names
2670ASSUME: three ideals in the input are of the same sizes and contain merely
2671@* variables which are interpreted as follows: N resp. P stand for negative
2672@* resp. positive roots, C stand for Cartan elements. d is the degree bound for
2673@* letterplace ring, which will be returned.
2674@* The matrix A is a generalized Cartan matrix with integer entries
2675@* The result is the ideal called 'fsRel' in the returned ring.
2676EXAMPLE: example fullSerreRelations; shows examples
2677"
2678{
2679  /* SerreRels on rNeg and rPos plus Cartans etc. */
2680  int ppl = printlevel -voice+2;
2681  /* ideals must be written in variables: assume each term is of degree 1 */
2682  int i,j,k;
2683  int N = nvars(basering);
2684  def save = basering;
2685  int comFlag = 0;
2686  /* assume:  (size(rNegative) == size(rPositive)) */
2687  /* assume:  (size(rNegative) == size(rCartan)) i.e. nonsimple Cartans */
2688  if ( (size(rNegative) != size(rPositive)) || (size(rNegative) != size(rCartan)) )
2689  {
2690    ERROR("All input ideals must be of the same size");
2691  }
2692
2693//   if (size(rNegative) != size(rPositive))
2694//   {
2695//     ERROR("The 1st and the 3rd input ideals must be of the same size");
2696//   }
2697
2698  /* assume:  2*size(rNegative) + size(rCartan) >= nvars(basering) */
2699  i = 2*size(rNegative) + size(rCartan);
2700  if (i>N)
2701  {
2702    string s1="The total number of elements in input ideals";
2703    string s2="must not exceed the dimension of the ground ring";
2704    ERROR(s1+s2);
2705  }
2706  if (i < N)
2707  {
2708    comFlag = N-i; // so many elements will commute
2709    "Warning: some elements will be treated as mutually commuting";
2710  }
2711  /* extract varnames from input ideals */
2712  intvec iNeg = varIdeal2intvec(rNegative);
2713  intvec iCartan = varIdeal2intvec(rCartan);
2714  intvec iPos = varIdeal2intvec(rPositive);
2715  /* for each vector in rNeg and rPositive, go into the corr. ring and create SerreRels */
2716  /* rNegative: */
2717  list L = ringlist(save);
2718  def LPsave = makeLetterplaceRing2(uptodeg); setring save;
2719  list LNEG = L; list tmp;
2720  /* L[1] field as is; L[2] vars: a subset; L[3] ordering: dp, L[4] as is */
2721  for (i=1; i<=size(iNeg); i++)
2722  {
2723    tmp[i] = string(var(iNeg[i]));
2724  }
2725  LNEG[2] = tmp; LNEG[3] = list(list("dp",intvec(1:size(iNeg))), list("C",0));
2726  def RNEG = ring(LNEG); setring RNEG;
2727  def RRNEG = makeLetterplaceRing2(uptodeg);
2728  setring RRNEG;
2729  ideal I = serreRelations(A,1); I = simplify(I,1+2+8);
2730  setring LPsave;
2731  ideal srNeg = imap(RRNEG,I);
2732  dbprint(ppl,"0-1 ideal of negative relations is ready");
2733  dbprint(ppl-1,srNeg);
2734  setring save; kill L,tmp,RRNEG,RNEG, LNEG;
2735  /* rPositive: */
2736  list L = ringlist(save);
2737  list LPOS = L; list tmp;
2738  /* L[1] field as is; L[2] vars: a subset; L[3] ordering: dp, L[4] as is */
2739  for (i=1; i<=size(iPos); i++)
2740  {
2741    tmp[i] = string(var(iPos[i]));
2742  }
2743  LPOS[2] = tmp; LPOS[3] = list(list("dp",intvec(1:size(iPos))), list("C",0));
2744  def RPOS = ring(LPOS); setring RPOS;
2745  def RRPOS = makeLetterplaceRing2(uptodeg);
2746  setring RRPOS;
2747  ideal I = serreRelations(A,1); I = simplify(I,1+2+8);
2748  setring LPsave;
2749  ideal srPos = imap(RRPOS,I);
2750  dbprint(ppl,"0-2 ideal of positive relations is ready");
2751  dbprint(ppl-1,srPos);
2752  setring save; kill L,tmp,RRPOS,RPOS, LPOS;
2753  string sMap = "ideal Mmap =";
2754  for (i=1; i<=nvars(save); i++)
2755  {
2756    sMap = sMap + string(var(i)) +"(1),";
2757  }
2758  sMap[size(sMap)] = ";";
2759  /* cartans: h_j h_i = h_i h_j */
2760  setring LPsave;
2761  ideal ComCartan;
2762  for (i=1; i<size(iCartan); i++)
2763  {
2764    for (j=i+1; j<=size(iCartan); j++)
2765    {
2766      ComCartan =  ComCartan + lieBracket(var(iCartan[j]),var(iCartan[i]));
2767    }
2768  }
2769  ComCartan = simplify(ComCartan,1+2+8);
2770  execute(sMap); // defines an ideal Mmap
2771  map F = save, Mmap;
2772  dbprint(ppl,"1. commuting Cartans: ");
2773  dbprint(ppl-1,ComCartan);
2774  /* [e_i, f_j] =0 if i<>j */
2775  ideal ComPosNeg; // assume: #Neg=#Pos
2776  for (i=1; i<size(iPos); i++)
2777  {
2778    for (j=1; j<=size(iPos); j++)
2779    {
2780      if (j !=i)
2781      {
2782        ComPosNeg =  ComPosNeg + lieBracket(var(iPos[i]),var(iNeg[j]));
2783        ComPosNeg =  ComPosNeg + lieBracket(var(iPos[j]),var(iNeg[i]));
2784      }
2785    }
2786  }
2787  ComPosNeg = simplify(ComPosNeg,1+2+8);
2788  dbprint(ppl,"2. commuting Positive and Negative:");
2789  dbprint(ppl-1,ComPosNeg);
2790  /* [e_i, f_i] = h_i */
2791  poly tempo;
2792  for (i=1; i<=size(iCartan); i++)
2793  {
2794    tempo = lieBracket(var(iPos[i]),var(iNeg[i])) - var(iCartan[i]);
2795    ComPosNeg =  ComPosNeg + tempo;
2796  }
2797  //  ComPosNeg = simplify(ComPosNeg,1+2+8);
2798  dbprint(ppl,"3. added sl2 triples [e_i,f_i]=h_i");
2799  dbprint(ppl-1,ComPosNeg);
2800
2801  /* [h_i, e_j] = A_ij e_j */
2802  /* [h_i, f_j] = -A_ij f_j */
2803  ideal ActCartan; // assume: #Neg=#Pos
2804  for (i=1; i<=size(iCartan); i++)
2805  {
2806    for (j=1; j<=size(iCartan); j++)
2807    {
2808      tempo = lieBracket(var(iCartan[i]),var(iPos[j])) - A[i,j]*var(iPos[j]);
2809      ActCartan = ActCartan + tempo;
2810      tempo = lieBracket(var(iCartan[i]),var(iNeg[j])) + A[i,j]*var(iNeg[j]);
2811      ActCartan = ActCartan + tempo;
2812    }
2813  }
2814  ActCartan = simplify(ActCartan,1+2+8);
2815  dbprint(ppl,"4. actions of Cartan:");
2816  dbprint(ppl-1, ActCartan);
2817
2818  /* final part: prepare the output */
2819  setring LPsave;
2820  ideal fsRel = srNeg, srPos, ComPosNeg, ComCartan, ActCartan;
2821  export fsRel;
2822  setring save;
2823  return(LPsave);
2824}
2825example
2826{
2827  "EXAMPLE:"; echo = 2;
2828  intmat A[2][2] =
2829    2, -1,
2830    -1, 2; // A_2 = sl_3 Cartan matrix
2831  ring r = 0,(f1,f2,h1,h2,e1,e2),dp;
2832  ideal negroots = f1,f2; ideal cartans = h1,h2; ideal posroots = e1,e2;
2833  int uptodeg = 5;
2834  def RS = fullSerreRelations(A,negroots,cartans,posroots,uptodeg);
2835  setring RS; fsRel;
2836}
2837
2838/* intmat A[2][2] =
2839    2, -1,
2840    -3, 2; // G_2 Cartan matrix
2841*/
2842
2843
2844static proc varIdeal2intvec(ideal I)
2845{
2846  // used in SerreRelations
2847  /* assume1:  input ideal is a list of variables of the ground ring */
2848  int i,j; intvec V;
2849  for (i=1; i<= size(I); i++)
2850  {
2851    j = univariate(I[i]);
2852    if (j<=0)
2853    {
2854      ERROR("input ideal must contain only variables");
2855    }
2856    V[i] = j;
2857  }
2858  dbprint(printlevel-voice+2,V);
2859  /* now we make a smaller list of non-repeating entries */
2860  ideal iW = simplify(ideal(V),2+4); // no zeros, no repetitions
2861  if (size(iW) < size(V))
2862  {
2863    /* extract intvec from iW */
2864    intvec inW;
2865    for(j=1; j<=size(iW); j++)
2866    {
2867      inW[j] = int(leadcoef(iW[j]));
2868    }
2869    return(inW);
2870  }
2871  return(V);
2872}
2873example
2874{
2875  "EXAMPLE:"; echo = 2;
2876  ring r = 0,(x,y,z),dp;
2877  ideal I = x,z;
2878  varIdeal2intvec(I);
2879  varIdeal2intvec(ideal(x2,y^3,x+1));
2880  varIdeal2intvec(ideal(x*y,y,x+1));
2881}
2882
2883proc lp2lstr(ideal K, def save)
2884"USAGE:  lp2lstr(K,s); K an ideal, s a ring name
2885RETURN:  nothing (exports object @LN into the ring named s)
2886ASSUME: basering has a letterplace ring structure
2887PURPOSE: converts letterplace ideal to list of modules
2888NOTE: useful as preprocessing to 'lst2str'
2889EXAMPLE: example lp2lstr; shows examples
2890"
2891{
2892  def @R = basering;
2893  string err;
2894  int s = nvars(save);
2895  int i,j,k;
2896    // K contains vars x(1),...z(1) = images of originals
2897  // 5. go back to orig vars, produce strings/modules
2898  int sk = size(K);
2899  int sp, sx, a, b;
2900  intvec x;
2901  poly p,q;
2902  poly pn;
2903  // vars in 'save'
2904  setring save;
2905  module N;
2906  list LN;
2907  vector V;
2908  poly pn;
2909  // test and skip exponents >=2
2910  setring @R;
2911  for(i=1; i<=sk; i++)
2912  {
2913    p  = K[i];
2914    while (p!=0)
2915    {
2916      q  = lead(p);
2917      //      "processing q:";q;
2918      x  = leadexp(q);
2919      sx = size(x);
2920      for(k=1; k<=sx; k++)
2921      {
2922        if ( x[k] >= 2 )
2923        {
2924          err = "skip: the value x[k] is " + string(x[k]);
2925          dbprint(ppl,err);
2926          //            return(0);
2927          K[i] = 0;
2928          p    = 0;
2929          q    = 0;
2930          break;
2931        }
2932      }
2933      p  = p - q;
2934    }
2935  }
2936  K  = simplify(K,2);
2937  sk = size(K);
2938  for(i=1; i<=sk; i++)
2939  {
2940    //    setring save;
2941    //    V  = 0;
2942    setring @R;
2943    p  = K[i];
2944    while (p!=0)
2945    {
2946      q  = lead(p);
2947      err =  "processing q:" + string(q);
2948      dbprint(ppl,err);
2949      x  = leadexp(q);
2950      sx = size(x);
2951      pn = leadcoef(q);
2952      setring save;
2953      pn = imap(@R,pn);
2954      V  = V + leadcoef(pn)*gen(1);
2955      for(k=1; k<=sx; k++)
2956      {
2957        if (x[k] ==1)
2958        {
2959          a = k div s; // block number=a+1, a!=0
2960          b = k % s; // remainder
2961          //          printf("a: %s, b: %s",a,b);
2962          if (b == 0)
2963          {
2964            // that is it's the last var in the block
2965            b = s;
2966            a = a-1;
2967          }
2968          V = V + var(b)*gen(a+2);
2969        }
2970      }
2971      err = "V: " + string(V);
2972      dbprint(ppl,err);
2973      //      printf("V: %s", string(V));
2974      N = N,V;
2975      V  = 0;
2976      setring @R;
2977      p  = p - q;
2978      pn = 0;
2979    }
2980    setring save;
2981    LN[i] = simplify(N,2);
2982    N     = 0;
2983  }
2984  setring save;
2985  list @LN = LN;
2986  export @LN;
2987  //  return(LN);
2988}
2989example
2990{
2991  "EXAMPLE:"; echo = 2;
2992  intmat A[2][2] = 2, -1, -1, 2; // sl_3 == A_2
2993  ring r = 0,(f1,f2),dp;
2994  def R = makeLetterplaceRing(3);
2995  setring R;
2996  ideal I = serreRelations(A,1);
2997  lp2lstr(I,r);
2998  setring r;
2999  lst2str(@LN,1);
3000}
3001
3002static proc strList2poly(list L)
3003{
3004  //  list L comes from sent2lplace (which takes a polynomial as input)
3005  // each entry of L is a sublist with the coef on the last place
3006  int s = size(L); int t;
3007  int i,j;
3008  list M;
3009  poly p,q;
3010  string Q;
3011  for(i=1; i<=s; i++)
3012  {
3013    M = L[i];
3014    t = size(M);
3015    //    q = M[t]; // a constant
3016    Q = string(M[t]);
3017    for(j=1; j<t; j++)
3018    {
3019      //      q = q*M[j];
3020      Q = Q+"*"+string(M[j]);
3021    }
3022    execute("q="+Q+";");
3023    //    q;
3024    p = p + q;
3025  }
3026  kill Q;
3027  return(p);
3028}
3029example
3030{
3031  "EXAMPLE:"; echo = 2;
3032  ring r =0,(x,y,z,t),Dp;
3033  def A = makeLetterplaceRing(4);
3034  setring A;
3035  string t = "-2*y*z*y*z + y*t*z*z - z*x*x*y  + 2*z*y*z*y";
3036  list L = sent2lplace(t);
3037  L;
3038  poly p = strList2poly(L);
3039  p;
3040}
3041
3042static proc file2lplace(string fname)
3043"USAGE:  file2lplace(fnm);  fnm a string
3044RETURN:  ideal
3045PURPOSE: convert the contents of the file fnm into ideal of polynomials in free algebra
3046EXAMPLE: example file2lplace; shows examples
3047"
3048{
3049  // format: from the usual string to letterplace
3050  string s = read(fname);
3051  // assume: file is a comma-sep list of polys
3052  // the vars are declared before
3053  // the file ends with ";"
3054  string t; int i;
3055  ideal I;
3056  list tst;
3057  while (s!="")
3058  {
3059    i = find(s,",");
3060    "i"; i;
3061    if (i==0)
3062    {
3063      i = find(s,";");
3064      if (i==0)
3065      {
3066        // no ; ??
3067         "no colon or semicolon found anymore";
3068         return(I);
3069      }
3070      // no "," but ";" on the i-th place
3071      t = s[1..i-1];
3072      s = "";
3073      "processing: "; t;
3074      tst = sent2lplace(t);
3075      tst;
3076      I = I, strList2poly(tst);
3077      return(I);
3078    }
3079    // here i !=0
3080    t = s[1..i-1];
3081    s = s[i+1..size(s)];
3082    "processing: "; t;
3083    tst = sent2lplace(t);
3084    tst;
3085    I = I, strList2poly(tst);
3086  }
3087  return(I);
3088}
3089example
3090{
3091  "EXAMPLE:"; echo = 2;
3092  ring r =0,(x,y,z,t),dp;
3093  def A = makeLetterplaceRing(4);
3094  setring A;
3095  string fn = "myfile";
3096  string s1 = "z*y*y*y - 3*y*z*x*y  + 3*y*y*z*y - y*x*y*z,";
3097  string s2 = "-2*y*x*y*z + y*y*z*z - z*z*y*y + 2*z*y*z*y,";
3098  string s3 = "z*y*x*t - 2*y*z*y*t + y*y*z*t - t*z*y*y + 2*t*y*z*y - t*x*y*z;";
3099  write(":w "+fn,s1);  write(":a "+fn,s2);   write(":a "+fn,s3);
3100  read(fn);
3101  ideal I = file2lplace(fn);
3102  I;
3103}
3104
3105/* EXAMPLES AGAIN:
3106//static proc get_ls3nilp()
3107{
3108//first app of file2lplace
3109  ring r =0,(x,y,z,t),dp;
3110  int d = 10;
3111  def A = makeLetterplaceRing(d);
3112  setring A;
3113  ideal I = file2lplace("./ls3nilp.bg");
3114  // and now test the correctness: go back from lplace to strings
3115  lp2lstr(I,r);
3116  setring r;
3117  lst2str(@LN,1); // agree!
3118}
3119
3120//static proc doc_example()
3121{
3122  LIB "freegb.lib";
3123  ring r = 0,(x,y,z),dp;
3124  int d =4; // degree bound
3125  def R = makeLetterplaceRing(d);
3126  setring R;
3127  ideal 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);
3128  option(redSB);option(redTail);
3129  ideal J = system("freegb",I,d,nvars(r));
3130  J;
3131  // visualization:
3132  lp2lstr(J,r); // export an object called @LN to the ring r
3133  setring r;  // change to the ring r
3134  lst2str(@LN,1); // output the strings
3135}
3136
3137*/
3138
3139static proc lpMultX(poly f, poly g)
3140{
3141  /* multiplies two polys in a very general setting correctly */
3142  /* alternative to lpMult, possibly better at non-positive orderings */
3143
3144  if (lpAssumeViolation())
3145  {
3146    ERROR("Incomplete Letterplace structure on the basering!");
3147  }
3148  // decompose f,g into graded pieces with inForm: need dmodapp.lib
3149  int b = attrib(basering,"isLetterplaceRing");  // the length of the block
3150  intvec w; // inherit the graded on the oridinal ring
3151  int i;
3152  for(i=1; i<=b; i++)
3153  {
3154    w[i] = deg(var(i));
3155  }
3156  intvec v = w;
3157  for(i=1; i< attrib(basering,"uptodeg"); i++)
3158  {
3159    v = v,w;
3160  }
3161  w = v;
3162  poly p,q,s, result;
3163  s = g;
3164  while (f!=0)
3165  {
3166    p = inForm(f,w)[1];
3167    f = f - p;
3168    s = g;
3169    while (s!=0)
3170    {
3171      q = inForm(s,w)[1];
3172      s = s - q;
3173      result = result + lpMult(p,q);
3174    }
3175  }
3176  // shrinking
3177  //  result;
3178  return( system("shrinktest",result,attrib(basering, "isLetterplaceRing")) );
3179}
3180example
3181{
3182  "EXAMPLE:"; echo = 2;
3183  // define a ring in letterplace form as follows:
3184  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
3185  def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure
3186  setring R;
3187  poly a = x(1)*y(2)+x(1)+y(1); poly b = y(1)+3;
3188  lpMultX(b,a);
3189  lpMultX(a,b);
3190}
3191
3192// multiply two letterplace polynomials, lpMult: done
3193// reduction/ Normalform? needs kernel stuff
3194
3195
3196proc lpMult(poly f, poly g)
3197"USAGE:  lpMult(f,g); f,g letterplace polynomials
3198RETURN:  poly
3199ASSUME: basering has a letterplace ring structure
3200PURPOSE: compute the letterplace form of f*g
3201EXAMPLE: example lpMult; shows examples
3202"
3203{
3204
3205  // changelog:
3206  // VL oct 2010: deg -> deg(_,w) for the length
3207  // shrink the result => don't need to decompose polys
3208  // since the shift is big enough
3209
3210  // indeed it's better to have that
3211  // ASSUME: both f and g are quasi-homogeneous
3212
3213  if (lpAssumeViolation())
3214  {
3215    ERROR("Incomplete Letterplace structure on the basering!");
3216  }
3217  intvec w = 1:nvars(basering);
3218  int sf = deg(f,w); // VL Oct 2010: we need rather length than degree
3219  int sg = deg(g,w); // esp. in the case of weighted ordering
3220  int uptodeg = attrib(basering, "uptodeg");
3221  if (sf+sg > uptodeg)
3222  {
3223    ERROR("degree bound violated by the product!");
3224  }
3225  //  if (sf>1) { sf = sf -1; }
3226  poly v = f*shiftPoly(g,sf);
3227  // bug, reported by Simon King: in nonhomog case [solved]
3228  // we need to shrink
3229  return( system("shrinktest",v,attrib(basering, "isLetterplaceRing")) );
3230}
3231example
3232{
3233  "EXAMPLE:"; echo = 2;
3234  // define a ring in letterplace form as follows:
3235  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
3236  def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure
3237  setring R;
3238  poly a = x(1)*y(2)+x(1)+y(1); poly b = y(1)+3;
3239  lpMult(b,a);
3240  lpMult(a,b);
3241}
3242
3243proc lpPower(poly f, int n)
3244"USAGE:  lpPower(f,n); f letterplace polynomial, int n
3245RETURN:  poly
3246ASSUME: basering has a letterplace ring structure
3247PURPOSE: compute the letterplace form of f^n
3248EXAMPLE: example lpPower; shows examples
3249"
3250{
3251  if (n<0) { ERROR("the power must be a natural number!"); }
3252  if (n==0) { return(poly(1)); }
3253  if (n==1) { return(f); }
3254  int i;
3255  poly p = 1;
3256  for(i=1; i<= n; i++)
3257  {
3258    p = lpMult(p,f);
3259  }
3260  return(p);
3261}
3262example
3263{
3264  "EXAMPLE:"; echo = 2;
3265  // define a ring in letterplace form as follows:
3266  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
3267  def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure
3268  setring R;
3269  poly a = x(1)*y(2) + y(1); poly b = y(1) - 1;
3270  lpPower(a,2);
3271  lpPower(b,4);
3272}
3273
3274// new: lp normal from by using shift-invariant data by Grischa Studzinski
3275
3276/////////////////////////////////////////////////////////
3277//   ASSUMPTIONS: every polynomial is an element of V',
3278//@* else there wouldn't be an dvec representation
3279
3280//Main procedure for the user
3281
3282proc lpNF(poly p, ideal G)
3283"USAGE: lpNF(p,G); f letterplace polynomial, ideal I
3284RETURN: poly
3285PURPOSE: computation of the normal form of p with respect to G
3286ASSUME: p is a Letterplace polynomial, G is a set Letterplace polynomials,
3287being a Letterplace Groebner basis (no check for this will be done)
3288NOTE: Strategy: take the smallest monomial wrt ordering for reduction
3289-     For homogenous ideals the shift does not matter
3290-     For non-homogenous ideals the first shift will be the smallest monomial
3291EXAMPLE: example lpNF; shows examples
3292"
3293{if ((p==0) || (size(G) == 0)){return(p);}
3294 checkAssumptions(p,G);
3295 G = sort(G)[1];
3296 list L = makeDVecI(G);
3297 return(lpNormalForm2(p,G,L));
3298}
3299example
3300{
3301  "EXAMPLE:"; echo = 2;
3302ring r = 0,(x,y,z),dp;
3303int d =5; // degree
3304def R = makeLetterplaceRing(d);
3305setring R;
3306ideal 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), z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) + z(1)*z(2)*z(3) + x(1)*y(2)*z(3);
3307ideal J = letplaceGBasis(I); // compute a Letterplace Groebner basis
3308poly p = y(1)*x(2)*y(3)*z(4)*y(5) - y(1)*z(2)*z(3)*y(4) + z(1)*y(2)*z(3);
3309poly q = z(1)*x(2)*z(3)*y(4)*z(5) - y(1)*z(2)*x(3)*y(4)*z(5);
3310lpNF(p,J);
3311lpNF(q,J);
3312}
3313
3314proc lpDivision(poly p, ideal I)
3315"ASSUME: I is a Groebner basis G = {g1,...,gN}, the original ring of the Letterplace ring has the name 'r' and no variable is called 'tag_i' for i in 1...N
3316RETURN: list L
3317NOTE: - L[1] NF(p,I)
3318      - L[2] list of expressions [i,l_{ij},r_{ij}] with \sum_{i,j} l_{ij} g_i r_{ij} = p - NF(p,I)
3319"
3320{
3321  if (p == 0 || size(I) == 0) {
3322    list L = 0;
3323    list empty;
3324    L[2] = empty;
3325    return (L);
3326  }
3327  poly pNF = lpNF(p,I);
3328  p = p - pNF;
3329
3330  // make new ring
3331  def save = basering;
3332  int norigvars = nvars(r);
3333  string tagvarstr = "(tag_1";
3334  for (int i = 2; i <= size(I); i++) {
3335    tagvarstr = tagvarstr + ",tag_" + string(i);
3336  } kill i;
3337  tagvarstr = tagvarstr + ")";
3338  string field = string(ringlist(r)[1]);
3339  execute("ring @tags = " + field + "," + tagvarstr + ",dp;");
3340  ring @tagged = (r + @tags);
3341  def @R = makeLetterplaceRing(attrib(save,"uptodeg")); setring @R;
3342
3343  // restore vars
3344  poly p = imap(save, p);
3345  poly pNF = imap(save, pNF);
3346  ideal I = imap(save, I);
3347  for (int i = 1; i <= size(I); i++) {
3348    I[i] = I[i] - var(norigvars + i);
3349  } kill i;
3350
3351  list summands;
3352  list L = pNF;
3353  poly pTaggedNF = lpNF(p,I);
3354  for (int i = 1; i <= size(pTaggedNF); i++) {
3355    intvec iv = lp2iv(pTaggedNF[i]);
3356    for (int j = 1; j <= size(iv); j++) {
3357      if (iv[j] > norigvars) {
3358        intvec left;
3359        intvec right;
3360        if (j > 1) {
3361          left = iv[1..(j-1)];
3362        }
3363        if (j < size(iv)) {
3364          right = iv[(j+1)..size(iv)];
3365        }
3366        list summand = (iv[j] - norigvars), leadcoef(pTaggedNF[i])*iv2lp(left), iv2lp(right);
3367        summands = insert(summands, summand, size(summands));
3368
3369        kill left;
3370        kill right;
3371        kill summand;
3372        break;
3373      }
3374    } kill j;
3375    kill iv;
3376  } kill i;
3377
3378  L[2] = summands;
3379
3380  setring save;
3381  list L = imap(@R,L);
3382  return (L);
3383}
3384
3385proc lpGBPres2Poly(list L, ideal I)
3386"ASSUME: L is a valid Groebner presentation as for example the result of lpDivision
3387RETURN: poly
3388NOTE: computes p = \sum_{i,j} l_{ij} g_i r_{ij} + NF(p,I) = \sum_{i} L[2][i][2] I[L[2][i][1]] L[2][i][3] + L[1]
3389"
3390{
3391  poly p;
3392  for (int i = 1; i <= size(L[2]); i++) {
3393    p = p + lpMult(lpMult(L[2][i][2], I[L[2][i][1]]), L[2][i][3]);
3394  }
3395  p = p + L[1];
3396  return (p);
3397}
3398
3399//procedures to convert monomials into the DVec representation, all static
3400////////////////////////////////////////////////////////
3401
3402
3403static proc getExpVecs(ideal G)
3404"USUAGE: getExpVecs(G);
3405RETURN: list of intvecs
3406PURPOSE: convert G into a list of intvecs, corresponding to the exponent vector
3407 of the leading monomials of G
3408"
3409{int i; list L;
3410 for (i = 1; i <= size(G); i++) {L[i] = leadexp(G[i]); }
3411 return(L);
3412}
3413
3414static proc delSupZero(intvec I)
3415"USUAGE:delSupZero(I);
3416RETURN: intvec
3417PURPOSE: Deletes superfluous zero blocks of an exponent vector
3418ASSUME: Intvec is an exponent vector of a letterplace monomial contained in V'
3419"
3420{if (I==intvec(0)) {return(intvec(0));}
3421 int j,k,l;
3422 int n = attrib(basering,"isLetterplaceRing"); int d = attrib(basering,"uptodeg");
3423 intvec w; j = 1;
3424 while (j <= d)
3425 {w = I[1..n];
3426  if (w<>intvec(0)){break;}
3427   else {I = I[(n+1)..(n*d)]; d = d-1; j++;}
3428 }
3429 for (j = 1; j <= d; j++)
3430  {l=(j-1)*n+1; k= j*n;
3431   w = I[l..k];
3432   if (w==intvec(0)){w = I[1..(l-1)]; return(w);}//if a zero block is found there are only zero blocks left,
3433                                                 //otherwise there would be a hole in the monomial
3434                                                 // shrink should take care that this will not happen
3435  }
3436 return(I);
3437}
3438
3439static proc delSupZeroList(list L)
3440"USUAGE:delSupZeroList(L); L a list, containing intvecs
3441RETURN: list, containing intvecs
3442PURPOSE: Deletes all superfluous zero blocks for a list of exponent vectors
3443ASSUME: All intvecs are exponent vectors of letterplace monomials contained in V'
3444"
3445{int i;
3446 for (i = size(L); 0 < i; i--){L[i] = delSupZero(L[i]);}
3447 return(L);
3448}
3449
3450
3451static proc makeDVec(intvec V)
3452"USUAGE:makeDVec(V);
3453RETURN: intvec
3454PURPOSE: Converts an modified exponent vector into an Dvec
3455NOTE: Superfluos zero blocks must have been deleted befor using this procedure
3456"
3457{int i,j,k,r1,r2; intvec D;
3458 int n = attrib(basering,"isLetterplaceRing");
3459 k = size(V) div n; r1 = 0; r2 = 0;
3460 for (i=1; i<= k; i++)
3461  {for (j=(1+((i-1)*n)); j <= (i*n); j++)
3462   {if (V[j]>0){r2 = j - ((i-1)*n); j = (j mod n); break;}
3463   }
3464   D[size(D)+1] = r1+r2;
3465   if (j == 0) {r1 = 0;} else{r1= n-j;}
3466  }
3467 D = D[2..size(D)];
3468 return(D);
3469}
3470
3471static proc makeDVecL(list L)
3472"USUAGE:makeDVecL(L); L, a list containing intvecs
3473RETURN: list, containing intvecs
3474ASSUME:
3475"
3476{int i; list R;
3477 for (i=1; i <= size(L); i++) {R[i] = makeDVec(L[i]);}
3478 return(R);
3479}
3480
3481static proc makeDVecI(ideal G)
3482"USUAGE:makeDVecI(G);
3483RETURN:list, containing intvecs
3484PURPOSE:computing the DVec representation for lead(G)
3485ASSUME:
3486"
3487{list L = delSupZeroList(getExpVecs(G));
3488 return(makeDVecL(L));
3489}
3490
3491
3492//procedures, which are dealing with the DVec representation, all static
3493
3494static proc dShiftDiv(intvec V, intvec W)
3495"USUAGE: dShiftDiv(V,W);
3496RETURN: a list,containing integers, or -1, if no shift of W divides V
3497PURPOSE: find all possible shifts s, such that s.W|V
3498ASSUME: V,W are DVecs of monomials contained in V'
3499"
3500{if(size(V)<size(W)){return(list(-1));}
3501
3502 int i,j,r; intvec T; list R;
3503 int n = attrib(basering,"isLetterplaceRing");
3504 int k = size(V) - size(W) + 1;
3505 if (intvec(V[1..size(W)])-W == 0){R[1]=0;}
3506 for (i =2; i <=k; i++)
3507 {r = 0; kill T; intvec T;
3508  for (j =1; j <= i; j++) {r = r + V[j];}
3509  //if (i==1) {T[1] = r-(i-1)*n;} else
3510  T[1] = r-(i-1)*n; if (size(W)>1) {T[2..size(W)] = V[(i+1)..(size(W)+i-1)];}
3511  if (T-W == 0) {R[size(R)+1] = i-1;}
3512 }
3513 if (size(R)>0) {return(R);}
3514 else {return(list(-1));}
3515}
3516
3517//the first normal form procedure, if a user want not to presort the ideal, just make it not static
3518
3519static proc lpNormalForm1(poly p, ideal G, list L)
3520"USUAGE:lpNormalForm1(p,G);
3521RETURN:poly
3522PURPOSE:computation of the normalform of p w.r.t. G
3523ASSUME: p is a Letterplace polynomial, G is a set of Letterplace polynomials
3524NOTE: Taking the first possible reduction
3525"
3526{
3527 if (deg(p) <1) {return(p);}
3528 else
3529  {
3530  int i; int s;
3531  intvec V = makeDVec(delSupZero(leadexp(p)));
3532  for (i = 1; i <= size(L); i++)
3533  {s = dShiftDiv(V, L[i])[1];
3534   if (s <> -1)
3535   {p = lpReduce(p,G[i],s);
3536    p = lpNormalForm1(p,G,L);
3537    break;
3538   }
3539  }
3540  p = p[1] + lpNormalForm1(p-p[1],G,L);
3541  return(p);
3542 }
3543}
3544
3545
3546// new VL; called from lpNF
3547static proc lpNormalForm2(poly pp, ideal G, list L)
3548"USUAGE:lpNormalForm2(p,G);
3549RETURN:poly
3550PURPOSE:computation of the normal form of p w.r.t. G
3551ASSUME: p is a Letterplace polynomial, G is a set of Letterplace polynomials
3552NOTE: Taking the first possible reduction
3553"
3554{
3555 poly one = 1;
3556 if ( (pp == 0) || (leadmonom(pp) == one) ) { return(pp); }
3557 poly p = pp; poly q;
3558 int i; int s; intvec V;
3559 while ( (p != 0) && (leadmonom(p) != one) )
3560 {
3561   //"entered while with p="; p;
3562   V = makeDVec(delSupZero(leadexp(p)));
3563   i = 0;
3564   s = -1;
3565   //"look for divisor";
3566   while ( (s == -1) && (i<size(L)) )
3567   {
3568     i = i+1;
3569     s = dShiftDiv(V, L[i])[1];
3570   }
3571 // now, out of here: either i=size(L) and s==-1 => no reduction
3572 // otherwise: i<=size(L) and s!= -1 => reduction
3573    //"out of divisor search: s="; s; "i="; i;
3574    if (s != -1)
3575    {
3576    //"start reducing with G[i]:";
3577      p = lpReduce(p,G[i],s); // lm-reduction
3578      //"reduced to p="; p;
3579    }
3580    else
3581    {
3582      // ie no lm-reduction possible; proceed with the tail reduction
3583      q = p-lead(p);
3584      p = lead(p);
3585      if (q!=0)
3586      {
3587        p = p + lpNormalForm2(q,G,L);
3588      }
3589      return(p);
3590    }
3591 }
3592 // out of while when p==0 or p == const
3593 return(p);
3594}
3595
3596proc isOrderingShiftInvariant(int withHoles)
3597  "USAGE: isOrderingShiftInvariant(b); b an integer interpreted as a boolean
3598  RETURN: int
3599  NOTE: Tests whether the ordering of the current ring is shift invariant, which is the case, when LM(p) > LM(p') for all p and p' where p' is p shifted by any number of places.
3600@*      If withHoles != 0 even Letterplace polynomials with holes (eg. x(1)*y(4)) are considered.
3601  ASSUME: - basering is a Letterplace ring.
3602  "
3603{
3604  int shiftInvariant = 1;
3605
3606  int n = attrib(basering, "isLetterplaceRing");
3607  int d = attrib(basering, "uptodeg");
3608
3609  ideal monomials;
3610  if (withHoles) {
3611    monomials = delete(lpMonomialsWithHoles(d-1), 1); // ignore the first element (1)
3612  } else {
3613    monomials = lpMaxIdeal(d-1, 0);
3614  }
3615
3616  for (int i = 1; i <= size(monomials); i++) {
3617    poly monom = monomials[i];
3618    int lastblock = lastBlock(monom);
3619    for (int s = 1; s <= d - lastblock; s++) {
3620      for (int s2 = 0; s2 < s; s2++) { // paranoid, check every pair
3621        poly first = shiftPoly(monom,s2);
3622        poly second = shiftPoly(monom,s);
3623        if (!(first > second)) {
3624          dbprint(string(first) + " <= " + string(second));
3625          shiftInvariant = 0;
3626        }
3627        kill first; kill second;
3628      } kill s2;
3629    } kill s;
3630    kill monom; kill lastblock;
3631  } kill i;
3632
3633  return(shiftInvariant);
3634}
3635example
3636{
3637  "EXAMPLE:"; echo = 2;
3638  ring r = 0,(x,y,z),dp;
3639  def R = makeLetterplaceRing(5);
3640  setring R;
3641  isOrderingShiftInvariant(0);// should be 1
3642
3643  ring r = 0,(x,y,z),dp;
3644  def R = makeLetterplaceRing(5);
3645  list RL = ringlist(R);
3646  RL[3][1][1] = "wp";
3647  intvec weights = 1,1,1,1,1,1,1,2,3,1,1,1,1,1,1;
3648  RL[3][1][2] = weights;
3649  def Rw = setLetterplaceAttributes(ring(RL),5,3);
3650  setring Rw;
3651  printlevel = voice + 1;
3652  isOrderingShiftInvariant(0);
3653  isOrderingShiftInvariant(1);
3654}
3655
3656static proc lpMonomialsWithHoles(int d)
3657{
3658  if (d < 0) {
3659    ERROR("d must not be negative")
3660  }
3661
3662  ideal monomials = 1;
3663  if (d == 0) {
3664     return (monomials);
3665  }
3666
3667  int lV = attrib(basering, "isLetterplaceRing"); // variable count
3668  ideal prevMonomials = lpMonomialsWithHoles(d - 1);
3669
3670  for (int i = 1; i <= size(prevMonomials); i++) {
3671    /* if (deg(prevMonomials[i]) >= d - 1) { */
3672      for (int j = 1; j <= lV; j++) {
3673        poly m = prevMonomials[i];
3674        m = m * var(j + (d-1)*lV);
3675        monomials = monomials, m;
3676        kill m;
3677      } kill j;
3678    /* } */
3679  } kill i;
3680
3681  if (d > 1) {
3682    // removes the 1
3683    monomials[1] = 0;
3684    monomials = simplify(monomials,2);
3685
3686    monomials = prevMonomials, monomials;
3687  }
3688  return (monomials);
3689}
3690
3691
3692//secundary procedures, all static
3693
3694static proc getlpCoeffs(poly q, poly p)
3695{list R; poly m; intvec cq,t,lv,rv,bla;
3696 int n = attrib(basering,"isLetterplaceRing"); int d = attrib(basering,"uptodeg");
3697 int i;
3698 m = p/q;
3699 cq = leadexp(m);
3700 for (i = 1; i<= d; i++)
3701 {bla = cq[((i-1)*n+1)..(i*n)];
3702  if (bla == 0) {lv = cq[1..i*n]; cq = cq[(i*n+1)..(d*n)]; break;}
3703 }
3704
3705 d = size(cq) div n;
3706 for (i = 1; i<= d; i++)
3707 {bla = cq[((i-1)*n+1)..(i*n)];
3708  if (bla <> 0){rv = cq[((i-1)*n+1)..(d*n)]; break;}
3709 }
3710 return(list(monomial(lv),monomial(rv)));
3711}
3712
3713static proc lpReduce(poly p, poly g, int s)
3714"NOTE: shift can not exceed the degree bound, because s*g | p
3715"
3716{poly l,r,qt; int i;
3717 list K = getlpCoeffs(lead(shiftPoly(g,s)), lead(p));
3718 l = K[1]; r = K[2];
3719 kill K;
3720 for (i = 1; i <= size(g); i++)
3721 {
3722   qt = qt + lpMult(lpMult(l,g[i]),r);
3723 }
3724 return(p - leadcoef(p)*normalize(qt));
3725}
3726
3727
3728static proc lpShrink(poly p)
3729"
3730"
3731{int n;
3732 if (attrib(basering,"isLetterplaceRing")>0)
3733 {n = attrib(basering,"isLetterplaceRing");
3734  return(system("shrinktest",p,n));
3735 }
3736 else {ERROR("Basering is not a Letterplace ring!");}
3737}
3738
3739static proc checkAssumptions(poly p, ideal G)
3740"
3741"
3742{checkLPRing();
3743 checkAssumptionPoly(p);
3744 checkAssumptionIdeal(G);
3745 return();
3746}
3747
3748static proc checkLPRing();
3749"
3750"
3751{if (attrib(basering,"isLetterplaceRing")==0) {ERROR("Basering is not a Letterplace ring!");}
3752 return();
3753}
3754
3755static proc checkAssumptionIdeal(ideal G)
3756"PURPOSE:Check if all elements of ideal are elements of V'
3757"
3758{ideal L = lead(normalize(G));
3759 int i;
3760 for (i = 1; i <= ncols(G); i++) {if (!isContainedInVp(G[i])) {ERROR("Ideal containes elements not contained in V'");}}
3761 return();
3762}
3763
3764static proc checkAssumptionPoly(poly p)
3765"PURPOSE:Check if p is an element of V'
3766"
3767{poly l = lead(normalize(p));
3768 if (!isContainedInVp(l)) {ERROR("Polynomial is not contained in V'");}
3769 return();
3770}
3771
3772static proc isContainedInVp(poly p)
3773"PURPOSE: Check monomial for holes in the places
3774"
3775{int r = 0; intvec w;
3776 intvec l = leadexp(p);
3777 int n = attrib(basering,"isLetterplaceRing"); int d = attrib(basering,"uptodeg");
3778 int i,j,c,c1;
3779 while (1 <= d)
3780 {w = l[1..n];
3781  if (w<>intvec(0)){break;}
3782   else {l = l[(n+1)..(n*d)]; d = d-1;}
3783 }
3784
3785 while (1 <= d)
3786  {for (j = 1; j <= n; j++)
3787   {if (l[j]<>0)
3788    {if (c1<>0){return(0);}
3789     if (c<>0){return(0);}
3790     if (l[j]<>1){return(0);}
3791     c=1;
3792    }
3793   }
3794   if (c == 0){c1=1;if (1 < d){l = l[(n+1)..(n*d)]; d = d-1;} else {d = d -1;}}
3795    else {c = 0; if (1 < d){l = l[(n+1)..(n*d)]; d = d-1;} else {d = d -1;}}
3796  }
3797 return(1);
3798}
3799
3800// under development for Roberto
3801static proc extractLinearPart(module M)
3802{
3803  /* returns vectors from a module whose max leadexp is 1 */
3804  /* does not take place nonlinearity into account yet */
3805  /* use rather kernel function isinV to get really nonlinear things */
3806  int i; int s = ncols(M);
3807  int answer = 1;
3808  vector v; module Ret;
3809  for(i=1; i<=s; i++)
3810  {
3811    if ( isLinearVector(M[i]) )
3812    {
3813      Ret = Ret, M[i];
3814    }
3815  }
3816  Ret = simplify(Ret,2);
3817  return(Ret);
3818}
3819
3820// under development for Roberto
3821static proc isLinearVector(vector v)
3822{
3823  /* returns true iff max leadexp is 1 */
3824  int i,j,k;
3825  intvec w;
3826  int s = size(v);
3827  poly p;
3828  int answer = 1;
3829  for(i=1; i<=s; i++)
3830  {
3831    p = v[i];
3832    while (p != 0)
3833    {
3834      w = leadexp(p);
3835      j = Max(w);
3836      if (j >=2)
3837      {
3838        answer = 0;
3839        return(answer);
3840      }
3841      p = p-lead(p);
3842    }
3843  }
3844  return(answer);
3845}
3846
3847
3848// // the following is to determine a shift of a mono/poly from the
3849// // interface
3850
3851// static proc whichshift(poly p, int numvars)
3852// {
3853// // numvars = number of vars of the orig free algebra
3854// // assume: we are in the letterplace ring
3855// // takes  monomial on the input
3856// poly q = lead(p);
3857// intvec v = leadexp(v);
3858// if (v==0) { return(int(0)); }
3859// int sv = size(v);
3860// int i=1;
3861// while ( (v[i]==0) && (i<sv) ) { i++; }
3862// i = sv div i;
3863// return(i);
3864// }
3865
3866
3867// LIB "qhmoduli.lib";
3868// static proc polyshift(poly p,  int numvars)
3869// {
3870//   poly q = p; int i = 0;
3871//   while (q!=0)
3872//   {
3873//     i = Max(i, whichshift(q,numvars));
3874//     q = q - lead(q);
3875//   }
3876//   return(q);
3877// }
3878
3879static proc lpAssumeViolation()
3880{
3881  // checks whether the global vars
3882  // uptodeg and lV are defined
3883  // returns Boolean : yes/no [for assume violation]
3884  def lpring = attrib(basering,"isLetterplaceRing");
3885  if ( typeof(lpring)!="int" )
3886  {
3887    //  if ( typeof(lpring)=="string" ) ??
3888    // basering is NOT lp Ring
3889    return(1);
3890  }
3891  def uptodeg = attrib(basering,"uptodeg");
3892  if ( typeof(uptodeg)!="int" )
3893  {
3894    return(1);
3895  }
3896  def lV = attrib(basering,"isLetterplaceRing");
3897  if ( typeof(lV)!="int" )
3898  {
3899    return(1);
3900  }
3901  //  int i = ( defined(uptodeg) && (defined(lV)) );
3902  //  return ( !i );
3903  return(0);
3904}
3905
3906static proc bugSKing()
3907{
3908  LIB "freegb.lib";
3909  ring r=0,(a,b),dp;
3910  def R = makeLetterplaceRing(5);
3911  setring R;
3912  poly p = a(1);
3913  poly q = b(1);
3914  poly p2 = lpPower(p,2);
3915  lpMult(p2+q,q)-lpMult(p2,q)-lpMult(q,q); // now its 0
3916}
3917
3918static proc bugRucker()
3919{
3920  // needs unstatic lpMultX
3921  LIB "freegb.lib";
3922  ring r=0,(a,b,c,d,p,q,r,s,t,u,v,w),(a(7,1,1,7),dp);
3923  def R=makeLetterplaceRing(20,1);
3924  setring R;
3925  option(redSB); option(redTail);
3926  ideal I=a(1)*b(2)*c(3)-p(1)*q(2)*r(3)*s(4)*t(5)*u(6),b(1)*c(2)*d(3)-v(1)*w(2);
3927  poly ttt = a(1)*v(2)*w(3)-p(1)*q(2)*r(3)*s(4)*t(5)*u(6)*d(7);
3928  // with lpMult
3929  lpMult(I[1],d(1)) - lpMult(a(1),I[2]); // spoly; has been incorrect before
3930  _ - ttt;
3931  // with lpMultX
3932  lpMultX(I[1],d(1)) - lpMultX(a(1),I[2]); // spoly; has been incorrect before
3933  _ - ttt;
3934}
3935
3936static proc checkWeightedExampleLP()
3937{
3938  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),wp(2,1,2,1,2,1,2,1);
3939  def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure
3940  setring R;
3941  poly a = x(1)*y(2)+x(1)+y(1); poly b = y(1)+3;
3942  lpMultX(b,a);
3943  lpMultX(a,b); // seems to work properly
3944}
3945
3946proc lpPrint(ideal I, def @r)
3947"USAGE: lpPrint(I, r); I an ideal, r a ring
3948RETURN: list of strings
3949PURPOSE: represent Letterplace ideal in the form of words
3950ASSUME: - basering is a Letterplace ring, r is the commutative ring
3951from which basering has been built
3952EXAMPLE: example lpPrint; shows example
3953"
3954{
3955        def save = basering;
3956        lp2lstr(I,@r); // export an object called @code{@LN} to the ring r
3957        setring @r;  // change to the ring r
3958        list @L = lst2str(@LN,1);
3959        export @L;
3960        setring save;
3961        list @@L = @L;
3962        setring @r;
3963        kill @L;
3964        kill @LN;
3965        setring save;
3966        return(@@L);
3967}
3968example
3969{
3970 "EXAMPLE:"; echo = 2;
3971 ring r = (0,a,b,g),(x,y),Dp;
3972 def R = makeLetterplaceRing(4); // constructs a Letterplace ring
3973 setring R; // downup algebra A
3974 ideal J = x(1)*x(2)*y(3)-a*x(1)*y(2)*x(3) - b*y(1)*x(2)*x(3) - g*x(1),
3975 x(1)*y(2)*y(3)-a*y(1)*x(2)*y(3) - b*y(1)*y(2)*x(3) - g*y(1);
3976 list L = lpPrint(J,r);
3977 L;
3978}
3979
3980/* THE FOLLOWING ARE UNDER DEVELOPMENT
3981// copied following from freegb_wrkcp.lib by Karim Abou Zeid on 07.04.2017:
3982// makeLetterplaceRingElim(int d)
3983// makeLetterplaceRingNDO(int d)
3984// setLetterplaceAttributesElim(def R, int uptodeg, int lV)
3985// lpElimIdeal(ideal I)
3986// makeLetterplaceRingWt(int d, intvec W)
3987
3988static proc makeLetterplaceRingElim(int d)
3989"USAGE:  makeLetterplaceRingElim(d); d integers
3990RETURN:  ring
3991PURPOSE: creates a ring with an elimination ordering
3992NOTE: the matrix for the ordering looks as follows: first row is 1,..,0,1,0,..
3993@* then 0,1,0,...,0,0,1,0... and so on, lastly its lp
3994@* this ordering is only correct if only polys with same shift are compared
3995EXAMPLE: example makeLetterplaceRingElim; shows examples
3996"
3997{
3998
3999  // ToDo future: inherit positive weights in the orig ring
4000  // complain on nonpositive ones
4001
4002  // d = up to degree, will be shifted to d+1
4003  if (d<1) {"bad d"; return(0);}
4004
4005  int uptodeg = d; int lV = nvars(basering);
4006
4007  int ppl = printlevel-voice+2;
4008  string err = "";
4009
4010  int i,j,s; intvec iV,iVl;
4011  def save = basering;
4012  int D = d-1;
4013  list LR  = ringlist(save);
4014  list L, tmp, tmp2, tmp3;
4015  L[1] = LR[1]; // ground field
4016  L[4] = LR[4]; // quotient ideal
4017  tmp  = LR[2]; // varnames
4018  s = size(LR[2]);
4019  for (i=1; i<=D; i++)
4020  {
4021    for (j=1; j<=s; j++)
4022    {
4023      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
4024    }
4025  }
4026  for (i=1; i<=s; i++)
4027  {
4028    tmp[i] = string(tmp[i])+"("+string(1)+")";
4029  }
4030  L[2] = tmp;
4031  L[3] = list();
4032  list OrigNames = LR[2];
4033  s = size(LR[3]);
4034  //creation of first block
4035
4036  if (s==2)
4037  {
4038    // not a blockord, 1 block + module ord
4039    tmp = LR[3][s]; // module ord
4040    for (i = 1; i <= lV;  i++)
4041    {
4042      iV = (0: lV);
4043      iV[i] = 1;
4044      iVl = iV;
4045      for (j = 1; j <= D; j++)
4046       { iVl = iVl,iV; }
4047      L[3][i] = list("a",iVl);
4048    }
4049//    for (i=1; i<=d; i++)
4050//    {
4051//      LR[3][s-1+i] = LR[3][1];
4052//    }
4053    //    LR[3][s+D] = tmp;
4054    //iV = (1:(d*lV));
4055    L[3][lV+1] = list("lp",(1:(d*lV)));
4056    L[3][lV+2] = tmp;
4057  }
4058  else {ERROR("Please set the ordering of basering to dp");}
4059//  if (s>2)
4060//  {
4061//    // there are s-1 blocks
4062//    int nb = s-1;
4063//    tmp = LR[3][s]; // module ord to place at the very end
4064//   tmp2 = LR[3]; tmp2 = tmp2[1..nb];
4065//    LR[3][1] = list("a",LTO);
4066//    //tmp3[1] = list("a",intvec(1: int(d*lV))); // deg-ord, insert as the 1st
4067//    for (i=1; i<=d; i++)
4068//    {
4069//      tmp3 = tmp3 + tmp2;
4070//    }
4071//    tmp3 = tmp3 + list(tmp);
4072//    LR[3] = tmp3;
4073//     for (i=1; i<=d; i++)
4074//     {
4075//       for (j=1; j<=nb; j++)
4076//       {
4077//         //        LR[3][i*nb+j+1]= LR[3][j];
4078//         LR[3][i*nb+j+1]= tmp2[j];
4079//       }
4080//     }
4081//     //    size(LR[3]);
4082//     LR[3][(s-1)*d+2] = tmp;
4083//     LR[3] = list("a",intvec(1: int(d*lV))) + LR[3]; // deg-ord, insert as the 1st
4084    // remove everything behind nb*(D+1)+1 ?
4085    //    tmp = LR[3];
4086    //    LR[3] = tmp[1..size(tmp)-1];
4087 // }
4088 // L[3] = LR[3];
4089  def @R = ring(L);
4090  //  setring @R;
4091  //  int uptodeg = d; int lV = nvars(basering); // were defined before
4092  def @@R = setLetterplaceAttributesElim(@R,uptodeg,lV);
4093  return (@@R);
4094}
4095example
4096{
4097  "EXAMPLE:"; echo = 2;
4098  ring r = 0,(x,y,z),lp;
4099  def A = makeLetterplaceRingElim(2);
4100  setring A;
4101  A;
4102  attrib(A,"isLetterplaceRing"); // number of variables in the main block
4103  attrib(A,"uptodeg");  // degree bound
4104}
4105
4106
4107
4108static proc makeLetterplaceRingNDO(int d)
4109"USAGE:  makeLetterplaceRingNDO(d); d an integer
4110RETURN:  ring
4111PURPOSE: creates a ring with a non-degree first ordering, suitable for
4112@* the use of non-homogeneous letterplace
4113NOTE: the matrix for the ordering looks as follows:
4114@*    'd' blocks of shifted original variables
4115EXAMPLE: example makeLetterplaceRingNDO; shows examples
4116"
4117{
4118
4119  // ToDo future: inherit positive weights in the orig ring
4120  // complain on nonpositive ones
4121
4122  // d = up to degree, will be shifted to d+1
4123  if (d<1) {"bad d"; return(0);}
4124
4125  int uptodeg = d; int lV = nvars(basering);
4126
4127  int ppl = printlevel-voice+2;
4128  string err = "";
4129
4130  int i,j,s;
4131  def save = basering;
4132  int D = d-1;
4133  list LR  = ringlist(save);
4134  list L, tmp, tmp2, tmp3;
4135  L[1] = LR[1]; // ground field
4136  L[4] = LR[4]; // quotient ideal
4137  tmp  = LR[2]; // varnames
4138  s = size(LR[2]);
4139  for (i=1; i<=D; i++)
4140  {
4141    for (j=1; j<=s; j++)
4142    {
4143      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
4144    }
4145  }
4146  for (i=1; i<=s; i++)
4147  {
4148    tmp[i] = string(tmp[i])+"("+string(1)+")";
4149  }
4150  L[2] = tmp;
4151  list OrigNames = LR[2];
4152  // ordering: one 1..1 a above
4153  // ordering: d blocks of the ord on r
4154  // try to get whether the ord on r is blockord itself
4155  // TODO: make L(2) ordering! exponent is maximally 2
4156  s = size(LR[3]);
4157  if (s==2)
4158  {
4159    // not a blockord, 1 block + module ord
4160    tmp = LR[3][s]; // module ord
4161    for (i=1; i<=d; i++)
4162    {
4163      LR[3][i] = LR[3][1];
4164    }
4165    //    LR[3][s+D] = tmp;
4166    LR[3][d+1] = tmp;
4167    //LR[3][1] = list("a",intvec(1: int(d*lV))); // deg-ord not wanted here
4168  }
4169  if (s>2)
4170  {
4171    // there are s-1 blocks
4172    int nb = s-1;
4173    tmp = LR[3][s]; // module ord to place at the very end
4174    tmp2 = LR[3]; tmp2 = tmp2[1..nb];
4175    //tmp3[1] = list("a",intvec(1: int(d*lV))); // deg-ord not wanted here
4176    for (i=1; i<=d; i++)
4177    {
4178      tmp3 = tmp3 + tmp2;
4179    }
4180    tmp3 = tmp3 + list(tmp);
4181    LR[3] = tmp3;
4182//     for (i=1; i<=d; i++)
4183//     {
4184//       for (j=1; j<=nb; j++)
4185//       {
4186//         //        LR[3][i*nb+j+1]= LR[3][j];
4187//         LR[3][i*nb+j+1]= tmp2[j];
4188//       }
4189//     }
4190//     //    size(LR[3]);
4191//     LR[3][(s-1)*d+2] = tmp;
4192//     LR[3] = list("a",intvec(1: int(d*lV))) + LR[3]; // deg-ord, insert as the 1st
4193    // remove everything behind nb*(D+1)+1 ?
4194    //    tmp = LR[3];
4195    //    LR[3] = tmp[1..size(tmp)-1];
4196  }
4197  L[3] = LR[3];
4198  def @R = ring(L);
4199  //  setring @R;
4200  //  int uptodeg = d; int lV = nvars(basering); // were defined before
4201  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
4202  return (@@R);
4203}
4204example
4205{
4206  "EXAMPLE:"; echo = 2;
4207  ring r = 0,(x,y,z),lp;
4208  def A = makeLetterplaceRingNDO(2);
4209  setring A;
4210  A;
4211  attrib(A,"isLetterplaceRing"); // number of variables in the main block
4212  attrib(A,"uptodeg");  // degree bound
4213}
4214
4215static proc setLetterplaceAttributesElim(def R, int uptodeg, int lV)
4216"USAGE: setLetterplaceAttributesElim(R, d, b, eV); R a ring, b,d, eV integers
4217RETURN: ring with special attributes set
4218PURPOSE: sets attributes for a letterplace ring:
4219@*      'isLetterplaceRing' = true, 'uptodeg' = d, 'lV' = b, 'eV' = eV, where
4220@*      'uptodeg' stands for the degree bound,
4221@*      'lV' for the number of variables in the block 0
4222@*      'eV' for the number of elimination variables
4223NOTE: Activate the resulting ring by using @code{setring}
4224"
4225{
4226  if (uptodeg*lV != nvars(R))
4227  {
4228    ERROR("uptodeg and lV do not agree on the basering!");
4229  }
4230
4231
4232    // Set letterplace-specific attributes for the output ring!
4233  attrib(R, "uptodeg", uptodeg);
4234  attrib(R, "isLetterplaceRing", lV);
4235  attrib(R, "HasElimOrd", 1);
4236  return (R);
4237}
4238example
4239{
4240  "EXAMPLE:"; echo = 2;
4241  ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp;
4242  def R = setLetterplaceAttributesElim(r, 4, 2, 1); setring R;
4243  attrib(R,"isLetterplaceRing");
4244  lieBracket(x(1),y(1),2);
4245}
4246
4247
4248static proc lpElimIdeal(ideal I)
4249"
4250does not work for degree reasons (deg function does not work for lp rings -> newone!)
4251"
4252{
4253  def lpring = attrib(basering,"isLetterplaceRing");
4254  def lpEO =  attrib(basering,"HasElimOrd");
4255  if ( lpring)==0 && typeof(lpEO)!="int")
4256  {
4257    ERROR("Ring is not a lp-ring with an elimination ordering");
4258  }
4259
4260  //int nE = attrib(basering, "eV");
4261
4262  return(letplaceGBasis(I));
4263}
4264
4265
4266static proc makeLetterplaceRingWt(int d, intvec W)
4267"USAGE:  makeLetterplaceRingWt(d,W); d an integer, W a vector of positive integers
4268RETURN:  ring
4269PURPOSE: creates a ring with a special ordering, suitable for
4270@* the use of non-homogeneous letterplace
4271NOTE: the matrix for the ordering looks as follows: first row is W,W,W,...
4272@* then there come 'd' blocks of shifted original variables
4273EXAMPLE: example makeLetterplaceRing2; shows examples
4274"
4275{
4276
4277  // ToDo future: inherit positive weights in the orig ring
4278  // complain on nonpositive ones
4279
4280  // d = up to degree, will be shifted to d+1
4281  if (d<1) {"bad d"; return(0);}
4282
4283  int uptodeg = d; int lV = nvars(basering);
4284
4285  //check weightvector
4286  if (size(W) <> lV) {"bad weights"; return(0);}
4287
4288  int i;
4289  for (i = 1; i <= size(W); i++) {if (W[i] < 0) {"bad weights"; return(0);}}
4290  intvec Wt = W;
4291  for (i = 2; i <= d; i++) {Wt = Wt, W;}
4292  kill i;
4293
4294  int ppl = printlevel-voice+2;
4295  string err = "";
4296
4297  int i,j,s;
4298  def save = basering;
4299  int D = d-1;
4300  list LR  = ringlist(save);
4301  list L, tmp, tmp2, tmp3;
4302  L[1] = LR[1]; // ground field
4303  L[4] = LR[4]; // quotient ideal
4304  tmp  = LR[2]; // varnames
4305  s = size(LR[2]);
4306  for (i=1; i<=D; i++)
4307  {
4308    for (j=1; j<=s; j++)
4309    {
4310      tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")";
4311    }
4312  }
4313  for (i=1; i<=s; i++)
4314  {
4315    tmp[i] = string(tmp[i])+"("+string(1)+")";
4316  }
4317  L[2] = tmp;
4318  list OrigNames = LR[2];
4319  // ordering: one 1..1 a above
4320  // ordering: d blocks of the ord on r
4321  // try to get whether the ord on r is blockord itself
4322  // TODO: make L(2) ordering! exponent is maximally 2
4323  s = size(LR[3]);
4324  if (s==2)
4325  {
4326    // not a blockord, 1 block + module ord
4327    tmp = LR[3][s]; // module ord
4328    for (i=1; i<=d; i++)
4329    {
4330      LR[3][s-1+i] = LR[3][1];
4331    }
4332    //    LR[3][s+D] = tmp;
4333    LR[3][s+1+D] = tmp;
4334    LR[3][1] = list("a",Wt); // deg-ord
4335  }
4336  if (s>2)
4337  {
4338    // there are s-1 blocks
4339    int nb = s-1;
4340    tmp = LR[3][s]; // module ord to place at the very end
4341    tmp2 = LR[3]; tmp2 = tmp2[1..nb];
4342    tmp3[1] = list("a",Wt); // deg-ord, insert as the 1st
4343    for (i=1; i<=d; i++)
4344    {
4345      tmp3 = tmp3 + tmp2;
4346    }
4347    tmp3 = tmp3 + list(tmp);
4348    LR[3] = tmp3;
4349
4350  }
4351  L[3] = LR[3];
4352  def @R = ring(L);
4353  //  setring @R;
4354  //  int uptodeg = d; int lV = nvars(basering); // were defined before
4355  def @@R = setLetterplaceAttributes(@R,uptodeg,lV);
4356  return (@@R);
4357}
4358example
4359{
4360  "EXAMPLE:"; echo = 2;
4361  ring r = 0,(x,y,z),(dp(1),dp(2));
4362  def A = makeLetterplaceRingWt(2,intvec(1,2,3));
4363  setring A;
4364  A;
4365  attrib(A,"isLetterplaceRing"); // number of variables in the main block
4366  attrib(A,"uptodeg");  // degree bound
4367}
4368*/
Note: See TracBrowser for help on using the repository browser.