source: git/Singular/LIB/freegb.lib @ e3b7aa

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