source: git/Singular/LIB/freegb.lib

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