source: git/Singular/LIB/nctools.lib @ ffdadd

spielwiese
Last change on this file since ffdadd was ffdadd, checked in by Hans Schoenemann <hannes@…>, 8 years ago
fix: tr. #773 (and test)
  • Property mode set to 100644
File size: 46.7 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version nctools.lib 4.0.3.3 Sep_2016 "; // $Id$
3category="Noncommutative";
4info="
5LIBRARY: nctools.lib     General tools for noncommutative algebras
6AUTHORS:   Levandovskyy V.,     levandov@mathematik.uni-kl.de,
7@*         Lobillo, F.J.,       jlobillo@ugr.es,
8@*         Rabelo, C.,          crabelo@ugr.es,
9@*         Motsak, O.,          U@D, where U={motsak}, D={mathematik.uni-kl.de}
10
11
12OVERVIEW:
13Support: DFG (Deutsche Forschungsgesellschaft) and Metodos algebraicos y efectivos
14en grupos cuanticos, BFM2001-3141, MCYT, Jose Gomez-Torrecillas (Main researcher).
15
16PROCEDURES:
17Gweights(r);              compute weights for a compatible ordering in a G-algebra,
18weightedRing(r);          change the ordering of a ring to a weighted one,
19ndcond();                 the ideal of non-degeneracy conditions in G-algebra,
20Weyl([p]);                create Weyl algebra structure in a basering (two different realizations),
21makeWeyl(n, [p]);         return n-th Weyl algebra in (x(i),D(i)) presentation,
22makeHeisenberg(N, [p,d]); return n-th Heisenberg algebra in (x(i),y(i),h) realization,
23Exterior();               return qring, the exterior algebra of a basering,
24findimAlgebra(M,[r]);     create finite dimensional algebra structure from the basering and the multiplication matrix M,
25superCommutative([b,e,Q]);  return qring, a super-commutative algebra over a basering,
26rightStd(I);              compute right Groebner basis of an ideal,
27rightNF(f,I);             compute right normal form wrt a submodule,
28rightModulo(M,N);         compute kernel of a homomorphism of right modules,
29moduloSlim(A,B);     compute modulo command via slimgb
30ncRelations(r);      recover the non-commutative relations of a G-algebra,
31isCentral(p);        check for the commutativity of a polynomial in the G-algebra,
32isNC();              check whether basering is noncommutative,
33isCommutative();     check whether basering is commutative
34isWeyl();            check whether basering is a Weyl algebra
35UpOneMatrix();       return NxN matrix with 1's in the whole upper triagle,
36AltVarStart();       return first alternating variable of a super-commutative algebra,
37AltVarEnd();         return last alternating variable of a super-commutative algebra,
38IsSCA();             check whether current ring is a super-commutative algebra,
39makeModElimRing(R);  equip a ring with module elimination ordering,
40embedMat(M,m,n);     embeds matrix M in a left upper corner of m times n matrix
41";
42
43
44LIB "ring.lib"; // for rootofUnity
45LIB "poly.lib"; // for newtonDiag
46LIB "matrix.lib"; // for submat
47
48///////////////////////////////////////////////////////////////////////////////
49
50// This procedure computes a weights vector for a G-algebra r
51
52proc Gweights(def r)
53"USAGE:   Gweights(r); r a ring or a square matrix
54RETURN:   intvec
55PURPOSE: compute an appropriate weight int vector for a G-algebra, i.e., such that
56\foral\;i<j\;\;lm_w(d_{ij}) <_w x_i x_j.
57@*       the polynomials d_{ij} are taken from r itself, if it is of the type ring
58@*       or defined by the given square polynomial matrix
59THEORY:   @code{Gweights} returns an integer vector, whose weighting should be used to redefine the G-algebra in order
60to get the same non-commutative structure w.r.t. a weighted ordering. If the input is a matrix and the output is the zero
61vector then there is not a G-algebra structure associated to these relations with respect to the given variables.
62@*Another possibility is to use @code{weightedRing} to obtain directly a G-algebra with the new appropriate (weighted) ordering.
63EXAMPLE: example Gweights; shows examples
64SEE ALSO: weightedRing
65"{
66  int novalid=0;
67  if (typeof(r)=="ring") //a ring is admissible as input
68  {
69    setring r;
70    matrix tails;
71    def l = ncRelations(r);
72    tails = l[2]; // l=C,D we need D, the tails of the relations
73  }
74  else
75  {
76    matrix tails;
77    if ( (typeof(r)=="matrix") || (typeof(r)=="intmat") )
78    {
79      if ( nrows(r)==ncols(r) ) //the input is a square matrix
80      {
81        tails = matrix(r);
82      }
83      else
84      {
85        novalid = 1;
86      }
87    }
88    else
89    {
90      novalid=1;
91    }
92  }
93  if (novalid==0)
94  {
95    intmat IM = SimplMat(tails);
96    if ( size(IM)>1 )
97    {
98      int n  = ncols(tails);
99      int m  = nrows(IM)-1;
100      int m1 = 0;
101      int m2 = m;
102      int m3 = 0;
103      ring simplexring=(real,10),(x),lp;// The simplex procedure requires a basering of this type
104      matrix M = IM;
105      list sol = simplex (M,m,n,m1,m2,m3);
106      return(weightvector(sol));
107    }
108    else
109    {
110      "Invalid input"; //usually because the input is a one variable ring
111      return();
112    }
113  }
114  else
115  {
116    "The input must be a ring or a square matrix";
117    return();
118  }
119}
120example
121{
122  "EXAMPLE:";echo=2;
123  ring r = (0,q),(a,b,c,d),lp;
124  matrix C[4][4];
125  C[1,2]=q; C[1,3]=q; C[1,4]=1; C[2,3]=1; C[2,4]=q; C[3,4]=q;
126  matrix D[4][4];
127  D[1,4]=(q-1/q)*b*c;
128  def S = nc_algebra(C,D); setring S; S;
129  Gweights(S);
130  def D=fetch(r,D);
131  Gweights(D);
132}
133
134///////////////////////////////////////////////////////////////////////////////
135
136// This procedure take a ring r, call to Gweights(r) and use the output
137// of Gweights(r) to make a change of order in r
138// The output is a new ring, equal to r but the order
139// r must be a G-algebra
140
141proc weightedRing(def r)
142"USAGE:   weightedRing(r); r a ring
143RETURN:  ring
144PURPOSE:  equip the variables of the given ring with weights such that the relations of new ring (with weighted variables) satisfies the ordering condition for G-algebras:
145e.g. \forall\;i<j\;\;lm_w(d_{ij})<_w x_i x_j.
146NOTE:    activate this ring with the \"setring\" command
147EXAMPLE: example weightedRing; shows examples
148SEE ALSO: Gweights
149"{
150  def wv=Gweights(r);
151  if (typeof(wv)=="intvec")
152  {
153    setring r;
154    int n=nvars(r);
155    // Generating an nxn-intmat order
156    intmat m[n][n];
157    m[1,1]=wv[1];
158    int i;
159    for (i=2; i<=n; i++)
160    {
161      m[1,i]=wv[i];
162      m[i,n+2-i]=1;
163    }
164    // End of generation.
165    def lr=ncRelations(r);
166    string newringstring="ring newring=("+charstr(r)+"),("+varstr(r)+"),M("+string(m)+")";
167    execute (newringstring);
168    def lnewring=imap(r,lr);
169    return( nc_algebra(lnewring[1],lnewring[2]) );
170  }
171  else
172  {
173    "Invalid input.";//usually because the input is a one variable ring
174    return();
175  }
176}
177example
178{
179  "EXAMPLE:";echo=2;
180  ring r = (0,q),(a,b,c,d),lp;
181  matrix C[4][4];
182  C[1,2]=q; C[1,3]=q; C[1,4]=1; C[2,3]=1; C[2,4]=q; C[3,4]=q;
183  matrix D[4][4];
184  D[1,4]=(q-1/q)*b*c;
185  def S = nc_algebra(C,D); setring S; S;
186  def t=weightedRing(S);
187  setring t; t;
188}
189
190///////////////////////////////////////////////////////////////////////////////
191
192// This procedure computes ei+ej-f with f running in Newton(pij) and deletes the zero rows
193
194static proc Cij(intmat M, int i,int j)
195{
196  M=(-1)*M;
197  int nc=ncols(M);
198  intvec N;
199  int k;
200  for (k=1; k<=nrows(M); k++)
201  {
202    M[k,i]=M[k,i]+1;
203    M[k,j]=M[k,j]+1;
204    if (intvec(M[k,1..nc])!=0)
205    {
206      N=N,intvec(M[k,1..nc]);
207    } // we only want non-zero rows
208  }
209  if (size(N)>1)
210  {
211    N=N[2..size(N)]; // Deleting the zero added in the definition of N
212    M=intmat(N,size(N) div nc,nc); // Conversion from vector to matrix
213  }
214  else
215  {
216    intmat M[1][1]=0;
217  }
218  return (M);
219}
220
221///////////////////////////////////////////////////////////////////////////////
222
223// This procedure run over the matrix of pij calculating Cij
224
225static proc Ct(matrix P)
226{
227  int    k = ncols(P);
228  intvec T = 0;
229  int    i,j;
230//  int notails=1;
231  def S;
232  for (j=2; j<=k; j++)
233  {
234    for (i=1; i<j; i++)
235    {
236      if ( P[i,j] != 0 )
237      {
238//        notails=0;
239        S = newtonDiag(P[i,j]);
240        S = Cij(S,i,j);
241        if ( size(S)>1 )
242        {
243          T = T,S;
244        }
245      }
246    }
247  }
248  if ( size(T)==1 )
249  {
250    intmat C[1][1] = 0;
251  }
252  else
253  {
254    T=T[2..size(T)]; // Deleting the zero added in the definition of T
255    intmat C = intmat(T,size(T) div k,k); // Conversion from vector to matrix
256  }
257  return (C);
258}
259
260///////////////////////////////////////////////////////////////////////////////
261
262// The purpose of this procedure is to produce the input matrix required by simplex procedure
263
264static proc SimplMat(matrix P)
265{
266  intmat C=Ct(P);
267  if (size(C)>1)
268  {
269    int r = nrows(C);
270    int n = ncols(C);
271    int f = 1+n+r;
272    intmat M[f][n+1]=0;
273    int i;
274    for (i=2; i<=(n+1); i++)
275    {
276      M[1,i]=-1; // (0,-1,-1,-1,...) objective function in the first row
277    }
278    for (i=2; i<=f; i++) {M[i,1]=1;} // All the independent terms are 1
279    for (i=2; i<=(n+1); i++) {M[i,i]=-1;} // wi>=1 is an identity matrix
280    M[(n+2)..f,2..(n+1)]=(-1)*intvec(C); // <wi,a> >= 1, a in C ...
281  }
282  else
283  {
284    int n = ncols(P);
285    int f = 1+n;
286    intmat M[f][n+1]=0;
287    int i;
288    for (i=2; i<=(n+1); i++) {M[1,i]=-1;} // (0,-1,-1,-1,...) objective function in the first row
289    for (i=2; i<=f; i++) {M[i,1]=1;} // All the independent terms are 1
290    for (i=2; i<=(n+1); i++) {M[i,i]=-1;} // wi>=1 is an identity matrix
291  }
292  return (M);
293}
294
295///////////////////////////////////////////////////////////////////////////////
296
297// This procedure generates a nice output of the simplex method consisting of a vector
298// with the solutions. The vector is ordered.
299
300static proc weightvector(list l)
301"ASSUME:  l is the output of simplex.
302RETURN: if there is a solution, an intvec with it will be returned"
303{
304  matrix m=l[1];
305  intvec nv=l[3];
306  int sol=l[2];
307  int rows=nrows(m);
308  int N=l[6];
309  intmat wv[1][N]=0;
310  int i;
311  if (sol)
312  {
313    "no solution satisfies the given constraints";
314  }
315  else
316  {
317    for ( i = 2; i <= rows; i++ )
318    {
319      if ( nv[i-1] <= N )
320      {
321        wv[1,nv[i-1]]=int(m[i,1]);
322      }
323    }
324  }
325  return (intvec(wv));
326}
327
328
329
330///////////////////////////////////////////////////////////////////////////////
331
332// This procedure recover the non-conmutative relations (matrices C and D)
333
334proc ncRelations(def r)
335"USAGE:   ncRelations(r); r a ring
336RETURN:  list L with two elements, both elements are of type matrix:
337@*         L[1] = matrix of coefficients C,
338@*         L[2] = matrix of polynomials D
339PURPOSE: recover the noncommutative relations via matrices C and D from
340a noncommutative ring
341SEE ALSO: ringlist, G-algebras
342EXAMPLE: example ncRelations; shows examples
343"{
344  list l;
345  if (typeof(r)=="ring")
346  {
347    int n=nvars(r);
348    matrix C[n][n]=0;
349    matrix D[n][n]=0;
350    poly f; poly g;
351    if (n>1)
352    {
353      int i,j;
354      for (i=2; i<=n; i++)
355      {
356        for (j=1; j<i; j++)
357        {
358          f=var(i)*var(j); // yx=c*xy+...
359          g=var(j)*var(i); // xy
360          while (C[j,i]==0)
361          {
362            if (leadmonom(f)==leadmonom(g))
363            {
364              C[j,i]=leadcoef(f);
365              D[j,i]=D[j,i]+f-lead(f);
366            }
367            else
368            {
369              D[j,i]=D[j,i]+lead(f);
370              f=f-lead(f);
371            }
372          }
373        }
374      }
375      l=C,D;
376    }
377    else { "The ring must have two or more variables"; }
378  }
379  else { "The input must be of a type ring";}
380  return (l);
381}
382example
383{
384  "EXAMPLE:";echo=2;
385  ring r = 0,(x,y,z),dp;
386  matrix C[3][3]=0,1,2,0,0,-1,0,0,0;
387  print(C);
388  matrix D[3][3]=0,1,2y,0,0,-2x+y+1;
389  print(D);
390  def S=nc_algebra(C,D);setring S; S;
391  def l=ncRelations(S);
392  print (l[1]);
393  print (l[2]);
394}
395
396///////////////////////////////////////////////////////////////////////////////
397
398proc findimAlgebra(matrix M, list #)
399"USAGE:   findimAlgebra(M,[r]); M a matrix, r an optional ring
400RETURN:  ring
401PURPOSE: define a finite dimensional algebra structure on a ring
402NOTE:  the matrix M is used to define the relations x(i)*x(j) = M[i,j] in the
403basering (by default) or in the optional ring r.
404@* The procedure equips the ring with the noncommutative structure.
405@* The procedure exports the ideal (not a two-sided Groebner basis!), called @code{fdQuot}, for further qring definition.
406THEORY: finite dimensional algebra can be represented as a factor algebra
407of a G-algebra modulo certain two-sided ideal. The relations of a f.d. algebra are thus naturally divided into two groups: firstly, the relations
408on the variables of the ring, making it into G-algebra and the rest of them, which constitute the ideal which will be factored out.
409EXAMPLE: example findimAlgebra; shows examples
410"
411{
412  if (size(#) >0)
413  {
414    if ( typeof(#[1])!="ring" ) { return();}
415    else
416    {
417      def @R1 = #[1];
418      setring @R1;
419    }
420  }
421  int i,j;
422  int n=nvars(basering);
423  poly p;
424  ideal I;
425  number c;
426  matrix C[n][n];
427  matrix D[n][n];
428  for (i=1; i<=n; i++)
429  {
430    for (j=i; j<=n; j++)
431    {
432      p=var(i)*var(j)-M[i,j];
433      if ( (ncols(I)==1) && (I[1]==0) )   { I=p; }
434      else { I=I,p; }
435      if (j>i)
436      {
437        if ((M[i,j]!=0) && (M[j,i]!=0))
438        {
439          c = leadcoef(M[j,i])/leadcoef(M[i,j]);
440        }
441        else
442        {
443          c = 1;
444        }
445        C[i,j]=c;
446        D[i,j]= M[j,i] -c*M[i,j];
447      }
448    }
449  }
450  def save = basering;
451  def S = nc_algebra(C,D); setring S;
452  ideal fdQuot = fetch(save,I);
453  export fdQuot;
454  return(S);
455}
456example
457{
458  "EXAMPLE:";echo=2;
459  ring r=(0,a,b),(x(1..3)),dp;
460  matrix S[3][3];
461  S[2,3]=a*x(1); S[3,2]=-b*x(1);
462  def A=findimAlgebra(S); setring A;
463  fdQuot = twostd(fdQuot);
464  qring Qr = fdQuot;
465  Qr;
466}
467
468///////////////////////////////////////////////////////////////////////////////
469
470proc isCentral(poly p, list #)
471"USAGE:   isCentral(p); p poly
472RETURN:  int, 1 if p commutes with all variables and 0 otherwise
473PURPOSE: check whether p is central in a basering (that is, commutes with every generator of the ring)
474NOTE: if @code{printlevel} > 0, the procedure displays intermediate information (by default, @code{printlevel}=0 )
475EXAMPLE: example isCentral; shows examples
476"{
477  //v an integer (with v!=0, procedure will be verbose)
478  int N = nvars(basering);
479  int in;
480  int flag = 1;
481  poly   q = 0;
482  for (in=1; in<=N; in++)
483  {
484    q = p*var(in)-var(in)*p;
485    if (q!=0)
486    {
487      if ( (size(#) >0 ) || (printlevel>0) )
488      {
489        "Non-central at:", var(in);
490      }
491      flag = 0;
492    }
493  }
494  return(flag);
495}
496example
497{
498  "EXAMPLE:";echo=2;
499  ring r=0,(x,y,z),dp;
500  matrix D[3][3]=0;
501  D[1,2]=-z;
502  D[1,3]=2*x;
503  D[2,3]=-2*y;
504  def S = nc_algebra(1,D); setring S;
505  S; // this is U(sl_2)
506  poly c = 4*x*y+z^2-2*z;
507  printlevel = 0;
508  isCentral(c);
509  poly h = x*c;
510  printlevel = 1;
511  isCentral(h);
512}
513
514///////////////////////////////////////////////////////////////////////////////
515
516proc UpOneMatrix(int N)
517"USAGE:   UpOneMatrix(n); n an integer
518RETURN:  intmat
519PURPOSE: compute an  n x n matrix with 1's in the whole upper triangle
520NOTE: helpful for setting noncommutative algebras with complicated
521coefficient matrices
522EXAMPLE: example UpOneMatrix; shows examples
523"{
524  int ii,jj;
525  intmat U[N][N]=0;
526  for (ii=1;ii<N;ii++)
527  {
528    for (jj=ii+1;jj<=N;jj++)
529    {
530      U[ii,jj]=1;
531    }
532  }
533  return(U);
534}
535example
536{
537  "EXAMPLE:";echo=2;
538  ring   r = (0,q),(x,y,z),dp;
539  matrix C = UpOneMatrix(3);
540  C[1,3]   = q;
541  print(C);
542  def S = nc_algebra(C,0); setring S;
543  S;
544}
545
546///////////////////////////////////////////////////////////////////////////////
547proc ndcond(list #)
548"USAGE:   ndcond();
549RETURN:  ideal
550PURPOSE: compute the non-degeneracy conditions of the basering
551NOTE: if @code{printlevel} > 0, the procedure displays intermediate information (by default, @code{printlevel}=0 )
552EXAMPLE: example ndcond; shows examples
553"
554{
555  // internal documentation, for tests etc
556  // 1st arg: v an optional integer (if v!=0, will be verbose)
557  // if the second argument is given, produces ndc w.r.t. powers x^N
558  int N = 1;
559  int Verbose = 0;
560  if ( size(#)>=1 ) { Verbose = int(#[1]); }
561  if ( size(#)>=2 ) { N = int(#[2]); }
562  Verbose = ((Verbose) || (printlevel>0));
563  int cnt = 1;
564  int numvars = nvars(basering);
565  int a,b,c;
566  poly p = 1;
567  ideal res = 0;
568  for (cnt=1; cnt<=N; cnt++)
569  {
570    if (Verbose) { "Processing degree :",cnt;}
571    for (a=1; a<=numvars-2; a++)
572    {
573      for (b=a+1; b<=numvars-1; b++)
574      {
575        for(c=b+1; c<=numvars; c++)
576        {
577          p = (var(c)^cnt)*(var(b)^cnt);
578          p = p*(var(a)^cnt);
579          p = p-(var(c)^cnt)*((var(b)^cnt)*(var(a)^cnt));
580          if (Verbose) {a,".",b,".",c,".";}
581          if (p!=0)
582          {
583            if ( res==0 )
584            {
585              res[1] = p;
586            }
587            else
588            {
589              res = res,p;
590            }
591            if (Verbose) { "failed:",p; }
592          }
593        }
594      }
595    }
596    if (Verbose) { "done"; }
597  }
598  return(res);
599}
600example
601{
602  "EXAMPLE:";echo=2;
603  ring r = (0,q1,q2),(x,y,z),dp;
604  matrix C[3][3];
605  C[1,2]=q2; C[1,3]=q1; C[2,3]=1;
606  matrix D[3][3];
607  D[1,2]=x; D[1,3]=z;
608  def S = nc_algebra(C,D); setring S;
609  S;
610  ideal j=ndcond(); // the silent version
611  j;
612  printlevel=1;
613  ideal i=ndcond(); // the verbose version
614  i;
615}
616
617
618///////////////////////////////////////////////////////////////////////////////
619proc Weyl(list #)
620"USAGE:   Weyl()
621RETURN:  ring
622PURPOSE: create a Weyl algebra structure on the basering
623NOTE: Activate this ring using the command @code{setring}.
624@*Assume the number of variables of a basering is 2k.
625(if the number of variables is odd, an error message will be returned)
626@*    by default, the procedure treats first k variables as coordinates x_i and the last k as differentials d_i
627@*    if a non-zero optional argument is given, the procedure treats 2k variables of a basering as k pairs (x_i,d_i), i.e. variables with odd numbers are treated as coordinates and with even numbers as differentials
628SEE ALSO: makeWeyl
629EXAMPLE: example Weyl; shows examples
630"
631{
632  //there are two possibilities for choosing the PBW basis.
633  //The variables have names x(i) for coordinates and d(i) for partial
634  // differentiations. By default, the procedure
635  //creates a ring, where the variables are ordered as x(1..n),d(1..n).  the
636  // tensor product-like realization x(1),d(1),x(2),d(2),... is used.
637  string rname=nameof(basering);
638  if ( rname == "basering") // i.e. no ring has been set yet
639  {
640    "You have to call the procedure from the ring";
641    return();
642  }
643  int @chr = 0;
644  if ( size(#) > 0 )
645  {
646    if ( typeof( #[1] ) == "int" )
647    {
648      @chr = #[1];
649    }
650  }
651  int nv = nvars(basering);
652  int N = nv div 2;
653  if ((nv % 2) != 0)
654  {
655    "Cannot create Weyl structure for an odd number of generators";
656    return();
657  }
658  matrix @D[nv][nv];
659  int i;
660  for ( i=1; i<=N; i++ )
661  {
662    if ( @chr==0 ) // default
663    {
664      @D[i,N+i]=1;
665    }
666    else
667    {
668      @D[2*i-1,2*i]=1;
669    }
670  }
671  def @R = nc_algebra(1,@D);
672  return(@R);
673}
674example
675{
676  "EXAMPLE:";echo=2;
677  ring A1=0,(x(1..2),d(1..2)),dp;
678  def S=Weyl();
679  setring S;  S;
680  kill A1,S;
681  ring B1=0,(x1,d1,x2,d2),dp;
682  def S=Weyl(1);
683  setring S;  S;
684}
685
686///////////////////////////////////////////////////////////////////////////////
687proc makeHeisenberg(int N, list #)
688"USAGE:  makeHeisenberg(n, [p,d]); int n (setting 2n+1 variables), optional int p (field characteristic), optional int d (power of h in the commutator)
689RETURN: ring
690PURPOSE: create the n-th Heisenberg algebra in the variables x(1),y(1),...,x(n),y(n),h over the rationals Q or F_p with the relations
691\forall\;i\in\{1,2,\ldots,n\}\;\;y(j)x(i) = x(i)y(j)+h^d.
692SEE ALSO: makeWeyl
693NOTE: activate this ring with the @code{setring} command
694@*       If p is not prime, the next larger prime number will be used.
695EXAMPLE: example makeHeisenberg; shows examples
696"
697{
698  int @chr = 0;
699  int @deg = 1;
700  if ( size(#) > 0 )
701  {
702    if ( typeof( #[1] ) == "int" )
703    {
704      @chr = #[1];
705    }
706  }
707  if ( size(#) > 1 )
708  {
709    if ( typeof( #[2] ) == "int" )
710    {
711      @deg = #[2];
712      if (@deg <1) { @deg = 1; }
713    }
714  }
715  ring @@r=@chr,(x(1..N),y(1..N),h),lp;
716  matrix D[2*N+1][2*N+1];
717  int i;
718  for (i=1;i<=N;i++)
719  {
720    D[i,N+i]=h^@deg;
721  }
722  return(nc_algebra(1,D));
723}
724example
725{
726  "EXAMPLE:";echo=2;
727  def a = makeHeisenberg(2);
728  setring a;   a;
729  def H3 = makeHeisenberg(3, 7, 2);
730  setring H3;  H3;
731}
732
733
734///////////////////////////////////////////////////////////////////////////////
735proc superCommutative(list #)
736"USAGE:   superCommutative([b,[e, [Q]]]);
737RETURN:  qring
738PURPOSE:  create a super-commutative algebra (as a GR-algebra) over a basering,
739NOTE: activate this qring with the \"setring\" command.
740NOTE: if b==e then the resulting ring is commutative.
741@* By default, @code{b=1, e=nvars(basering), Q=0}.
742THEORY: given a basering, this procedure introduces the anti-commutative relations
743@* var(j)var(i)=-var(i)var(j) for all e>=j>i>=b and creates the quotient
744@* of the anti-commutative algebra modulo the two-sided ideal, generated by
745@* x(b)^2, ..., x(e)^2[ + Q]
746DISPLAY: If @code{printlevel} > 1, warning debug messages will be printed
747EXAMPLE: example superCommutative; shows examples
748"
749{
750  int fprot = (printlevel > 1); // (find(option(),"prot") != 0);
751
752  string rname=nameof(basering);
753
754  if ( rname == "basering") // i.e. no ring has been set yet
755  {
756    ERROR("You have to call the procedure from the ring");
757  }
758
759  def saveRing = basering;
760
761  int N = nvars(saveRing);
762  int b = 1;
763  int e = N;
764  int flag = 0;
765
766  ideal Q = 0;
767
768  if(size(#)>0)
769  {
770    if(typeof(#[1]) != "int")
771    {
772      ERROR("The argument 'b' must be an integer!");
773    }
774    b = #[1];
775
776    if((b < 1)||(b > N))
777    {
778      ERROR("The argument 'b' must within [1..nvars(basering)]!");
779    }
780
781  }
782
783  if(size(#)>1)
784  {
785    if(typeof(#[2]) != "int")
786    {
787      ERROR("The argument 'e' must be an integer!");
788    }
789    e = #[2];
790
791    if((e < 1)||(e > N))
792    {
793      ERROR("The argument 'e' must within [1..nvars(basering)]!");
794    }
795
796    if(e < b)
797    {
798      ERROR("The argument 'e' must be bigger or equal to 'b'!");
799    }
800  }
801
802  if(size(#)>2)
803  {
804    if(typeof(#[3]) != "ideal")
805    {
806      ERROR("The argument 'Q' must be an ideal!");
807    }
808    Q = #[3];
809  }
810
811/*  if(size(#)>3)
812  {
813    if(typeof(#[4]) != "int")
814    {
815      ERROR("The argument 'flag' must be an integer!");
816    }
817    flag = #[4];
818  }
819*/
820
821  int iSavedDegBoung = degBound;
822
823  if( (b == e) && (flag == 0) ) // commutative ring!!!
824  {
825    if( fprot == 1)
826    {
827      print("Warning: (b==e) means that the resulting ring will be commutative!");
828    }
829
830    degBound=0;
831    Q = std(Q + (var(b)^2));
832    degBound = iSavedDegBoung;
833
834    qring @EA = Q; // and it will be internally commutative as well!!!
835    option(qringNF);
836
837    return(@EA);
838  }
839
840/*
841  // Singular'(H.S.) politics: no ring copies!
842  // in future nc_algebra() should return a new ring!!!
843  list CurrRing = ringlist(basering);
844  def @R = ring(CurrRing);
845  setring @R; // @R;
846*/
847  int i, j;
848
849  if( (char(basering)==2) && (flag == 0) )// commutative ring!!!
850  {
851    if( fprot == 1)
852    {
853      print("Warning: (char == 2) means that the resulting ring will be commutative!");
854    }
855
856    ideal I;
857
858    for (i = e - b + 1; i > 0; i--)
859    {
860      I[i] = var(i + b - 1)^2;
861    }
862
863    degBound=0;
864    Q = std(I + Q);
865    degBound = iSavedDegBoung;
866
867    qring @EA = Q; // and it will be internally commutative as well!!!
868    option(qringNF);
869    return(@EA);
870  }
871
872
873
874  if( (b == 1) && (e == N) ) // just an exterior algebra?
875  {
876    def S = nc_algebra(-1, 0); // define ground G-algebra!
877    setring S;
878  } else
879  {
880    matrix @E = UpOneMatrix(N);
881
882    for ( i = b; i < e; i++ )
883    {
884      for ( j = i+1; j <= e; j++ )
885      {
886        @E[i, j] = -1;
887      }
888    }
889    def S = nc_algebra(@E, 0); // define ground G-algebra!
890    setring S;
891  }
892
893  ideal @I;
894
895  for (i = e - b + 1; i > 0; i--)
896  {
897    @I[i] = var(i + b - 1)^2;
898  }
899
900
901  degBound=0;
902  @I = twostd(@I); // must be computed within the ground G-algebra => problems with local orderings!
903  degBound = iSavedDegBoung;
904
905  qring @EA = @I;
906
907  ideal @Q = twostd(fetch(saveRing, Q));
908
909  if( size(@Q) > 0 )
910  {
911    qring @EA2 = @Q;
912  }
913
914  attrib(basering, "isSCA", 1==1);
915  attrib(basering, "iAltVarStart", b);
916  attrib(basering, "iAltVarEnd", e);
917
918   //"Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
919  return(basering);
920}
921example
922{
923  "EXAMPLE:";echo=2;
924  ring R = 0,(x(1..4)),dp; // global!
925  def ER = superCommutative(); // the same as Exterior (b = 1, e = N)
926  setring ER; ER;
927  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
928  kill R; kill ER;
929  ring R = 0,(x(1..4)),(lp(1), dp(3)); // global!
930  def ER = superCommutative(2); // b = 2, e = N
931  setring ER; ER;
932  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
933  kill R; kill ER;
934  ring R = 0,(x, y, z),(ds(1), dp(2)); // mixed!
935  def ER = superCommutative(2,3); // b = 2, e = 3
936  setring ER; ER;
937  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
938  x + 1 + z + y; // ordering on variables: y > z > 1 > x
939  std(x - x*x*x);
940  std(ideal(x - x*x*x, x*x*z + y, z + y*x*x));
941  kill R; kill ER;
942  ring R = 0,(x, y, z),(ds(1), dp(2)); // mixed!
943  def ER = superCommutative(2, 3, ideal(x - x*x, x*x*z + y, z + y*x*x )); // b = 2, e = 3
944  setring ER; ER;
945  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
946}
947
948// Please, don't throw this away!!! Needed for backward compatibility.
949proc SuperCommutative(list #)
950"USAGE:   please use @code{superCommutative} instead
951"
952{
953  "// This procedure is deprecated. Please use superCommutative instead";
954  return( superCommutative(#) );
955}
956example
957{
958  "EXAMPLE:";
959  "Procedure is deprecated. Please use superCommutative instead";
960}
961
962static proc ParseSCA()
963"
964RETURN: list {AltVarStart, AltVarEnd} is currRing is SCA, returns undef otherwise.
965NOTE: rings with only one non-commutative variable are commutative rings which are super-sommutative itself!
966"
967{
968  if(typeof(attrib(basering, "isSCA"))=="int") // workaround, if(defined()) doesn't work!!!!
969  {
970    if(typeof(attrib(basering, "iAltVarStart"))=="int")
971    {
972      if(typeof(attrib(basering, "iAltVarEnd"))=="int")
973      {
974        if(attrib(basering, "isSCA"))
975        {
976          return(list(
977            attrib(basering, "iAltVarStart"),
978            attrib(basering, "iAltVarEnd")
979                 ));
980        }
981      }
982    }
983  }
984
985  def saveRing = basering;
986
987  int i, j;
988  int N = nvars(saveRing);
989
990  int b = N+1;
991  int e =  -1;
992
993  int fprot = 0; // (find(option(),"prot") != 0);
994
995
996  if( size(ideal(saveRing)) == 0 )
997  {
998    return("SCA rings are factors by (at least) squares!"); // no squares in the factor ideal!
999  }
1000
1001  list L = ringlist(saveRing);
1002
1003  if( size(L)!=6 )
1004  {
1005    if(fprot)
1006    {
1007      print("// Warning: The current ring is internally commutative!");
1008    }
1009
1010    for( i = N; i > 0; i-- )
1011    {
1012      if( NF(var(i)^2, std(0)) == 0 )
1013      {
1014        if( (fprot == 1) and (i > 1) )
1015        {
1016          print("// Warning: the SCA representation of the current commutative factor ring may be ambiguous!");
1017        }
1018
1019        return( list(i, i) ); // this is not unique in this case! there may be other squares in the factor ideal!
1020      }
1021    }
1022
1023    return("The current commutative ring is not SCA! (Wrong quotient ideal)"); // no squares in the factor ideal!
1024  }
1025
1026  module D = simplify(L[6], 2 + 4);
1027
1028  if( size(D)>0 )
1029  {
1030    return("The current ring is not SCA! (D!=0)");
1031  }
1032
1033  matrix C = L[5];
1034  poly c;
1035
1036  for( i = 1; i < N; i++ )
1037  {
1038    for( j = i+1; j <= N; j++ )
1039    {
1040      c = C[i, j];
1041
1042      if( c == -1 )
1043      {
1044        if(i < b)
1045        {
1046          b = i;
1047        }
1048
1049        if(j > e)
1050        {
1051          e = j;
1052        }
1053      } else
1054      { // should commute
1055        if( c!=1 )
1056        {
1057          return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=1)");
1058        }
1059      }
1060    }
1061  }
1062
1063  if( (b > N) || (e < 1))
1064  {
1065    if(fprot)
1066    {
1067      print("Warning: The current ring is a commutative GR-algebra!");
1068    }
1069
1070    for( i = N; i > 0; i-- )
1071    {
1072      if( NF(var(i)^2, std(0)) == 0 )
1073      {
1074        if( (fprot == 1) and (i > 1) )
1075        {
1076          print("Warning: the SCA representation of the current factor ring may be ambiguous!");
1077        }
1078
1079        return( list(i, i) ); // this is not unique in this case! there may be other squares in the factor ideal!
1080      }
1081    }
1082
1083    return("The current commutative GR-algebra is not SCA! (Wrong quotient ideal)"); // no squares in the factor ideal!
1084  }
1085
1086  for( i = 1; i < N; i++ )
1087  {
1088    for( j = i+1; j <= N; j++ )
1089    {
1090      c = C[i, j];
1091
1092      if( (b <= i) && (j <= e) ) // S <= i < j <= E
1093      { // anticommutative part
1094        if( c!= -1 )
1095        {
1096          return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=-1)");
1097        }
1098      } else
1099      { // should commute
1100        if( c!=1 )
1101        {
1102          return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=1)");
1103        }
1104      }
1105    }
1106  }
1107
1108  for( i = b; i <= e; i++ )
1109  {
1110    if( NF(var(i)^2, std(0)) != 0 )
1111    {
1112      return("The current ring is not SCA! (Wrong quotient ideal)");
1113    }
1114  }
1115
1116  ////////////////////////////////////////////////////////////////////////
1117  // ok. this is a SCA!!!
1118
1119  return(list(b, e));
1120}
1121
1122///////////////////////////////////////////////////////////////////////////////
1123proc AltVarStart()
1124"USAGE:   AltVarStart();
1125RETURN:  int
1126PURPOSE:  returns the number of the first alternating variable of basering
1127NOTE:  basering should be a super-commutative algebra constructed by
1128@*     the procedure @code{superCommutative}, emits an error otherwise
1129EXAMPLE: example AltVarStart; shows examples
1130"
1131{
1132  def l = ParseSCA();
1133
1134  if( typeof(l) != "string" )
1135  {
1136    return(l[1]);
1137  }
1138  ERROR(l);
1139}
1140example
1141{
1142  "EXAMPLE:";echo=2;
1143  ring R = 0,(x(1..4)),dp; // global!
1144  def ER = superCommutative(2); // (b = 2, e = N)
1145  setring ER; ER;
1146  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1147  setring R;
1148  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1149  kill R, ER;
1150  //////////////////////////////////////////////////////////////////
1151  ring R = 2,(x(1..4)),dp; // the same in char. = 2!
1152  def ER = superCommutative(2); // (b = 2, e = N)
1153  setring ER; ER;
1154  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1155  setring R;
1156  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1157}
1158
1159///////////////////////////////////////////////////////////////////////////////
1160proc AltVarEnd()
1161"USAGE:   AltVarStart();
1162RETURN:  int
1163PURPOSE:  returns the number of the last alternating variable of basering
1164NOTE:  basering should be a super-commutative algebra constructed by
1165@*     the procedure @code{superCommutative}, emits an error otherwise
1166EXAMPLE: example AltVarEnd; shows examples
1167"
1168{
1169  def l = ParseSCA();
1170
1171  if( typeof(l) != "string" )
1172  {
1173    return(l[2]);
1174  }
1175  ERROR(l);
1176}
1177example
1178{
1179  "EXAMPLE:";echo=2;
1180  ring R = 0,(x(1..4)),dp; // global!
1181  def ER = superCommutative(2); // (b = 2, e = N)
1182  setring ER; ER;
1183  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1184  setring R;
1185  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1186  kill R, ER;
1187  //////////////////////////////////////////////////////////////////
1188  ring R = 2,(x(1..4)),dp; // the same in char. = 2!
1189  def ER = superCommutative(2); // (b = 2, e = N)
1190  setring ER; ER;
1191  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1192  setring R;
1193  "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "].";
1194}
1195
1196///////////////////////////////////////////////////////////////////////////////
1197proc IsSCA()
1198"USAGE:   IsSCA();
1199RETURN:  int
1200PURPOSE:  returns 1 if basering is a super-commutative algebra and 0 otherwise
1201EXAMPLE: example IsSCA; shows examples
1202"
1203{
1204  def l = ParseSCA();
1205
1206  if( typeof(l) != "string" )
1207  {
1208    return(1);
1209  }
1210
1211  if( find(option(),"prot") != 0 )
1212  {
1213    print(l);
1214  }
1215
1216  return(0);
1217}
1218example
1219{
1220  "EXAMPLE:";echo=2;
1221/////////////////////////////////////////////////////////////////////
1222  ring R = 0,(x(1..4)),dp; // commutative
1223  if(IsSCA())
1224    { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; }
1225  else
1226    { "Not a super-commutative algebra!!!"; }
1227  kill R;
1228/////////////////////////////////////////////////////////////////////
1229  ring R = 0,(x(1..4)),dp;
1230  def S = nc_algebra(1, 0); setring S; S; // still commutative!
1231  if(IsSCA())
1232    { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; }
1233  else
1234    { "Not a super-commutative algebra!!!"; }
1235  kill R, S;
1236/////////////////////////////////////////////////////////////////////
1237  ring R = 0,(x(1..4)),dp;
1238  list CurrRing = ringlist(R);
1239  def ER = ring(CurrRing);
1240  setring ER; // R;
1241
1242  matrix E = UpOneMatrix(nvars(R));
1243
1244  int i, j; int b = 2; int e = 3;
1245
1246  for ( i = b; i < e; i++ )
1247  {
1248    for ( j = i+1; j <= e; j++ )
1249    {
1250      E[i, j] = -1;
1251    }
1252  }
1253
1254  def S = nc_algebra(E,0); setring S; S;
1255
1256  if(IsSCA())
1257    { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; }
1258  else
1259    { "Not a super-commutative algebra!!!"; }
1260  kill R, ER, S;
1261/////////////////////////////////////////////////////////////////////
1262  ring R = 0,(x(1..4)),dp;
1263  def ER = superCommutative(2); // (b = 2, e = N)
1264  setring ER; ER;
1265  if(IsSCA())
1266    { "This is a SCA! Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; }
1267  else
1268    { "Not a super-commutative algebra!!!"; }
1269  kill R, ER;
1270}
1271
1272
1273
1274///////////////////////////////////////////////////////////////////////////////
1275proc Exterior(list #)
1276"USAGE:   Exterior();
1277RETURN:  qring
1278PURPOSE:  create the exterior algebra of a basering
1279NOTE:  activate this qring with the \"setring\" command
1280THEORY: given a basering, this procedure introduces the anticommutative relations x(j)x(i)=-x(i)x(j) for all j>i,
1281@* moreover, creates a factor algebra modulo the two-sided ideal, generated by x(i)^2 for all i
1282EXAMPLE: example Exterior; shows examples
1283"
1284{
1285  string rname=nameof(basering);
1286  if ( rname == "basering") // i.e. no ring has been set yet
1287  {
1288    "You have to call the procedure from the ring";
1289    return();
1290  }
1291  int N = nvars(basering);
1292  string NewRing = "ring @R=("+charstr(basering)+"),("+varstr(basering)+"),("+ordstr(basering)+");";
1293  execute(NewRing);
1294  matrix @E = UpOneMatrix(N);
1295  @E = -1*(@E);
1296  def @@RR = nc_algebra(@E,0); setring @@RR;
1297  int i;
1298  ideal Q;
1299  for ( i=1; i<=N; i++ )
1300  {
1301    Q[i] = var(i)^2;
1302  }
1303  Q = twostd(Q);
1304  qring @EA = Q;
1305  return(@EA);
1306}
1307example
1308{
1309  "EXAMPLE:";echo=2;
1310  ring R = 0,(x(1..3)),dp;
1311  def ER = Exterior();
1312  setring ER;
1313  ER;
1314}
1315
1316///////////////////////////////////////////////////////////////////////////////
1317proc makeWeyl(int n, list #)
1318"USAGE:  makeWeyl(n,[p]); n an integer, n>0; p an optional integer (field characteristic)
1319RETURN:  ring
1320PURPOSE: create the n-th Weyl algebra over the rationals Q or F_p
1321NOTE:    activate this ring with the \"setring\" command.
1322@*       The presentation of an n-th Weyl algebra is classical: D(i)x(i)=x(i)D(i)+1,
1323@*       where x(i) correspond to coordinates and D(i) to partial differentiations, i=1,...,n.
1324@*       If p is not prime, the next larger prime number will be used.
1325SEE ALSO: Weyl
1326EXAMPLE: example makeWeyl; shows examples
1327"{
1328  if (n<1)
1329  {
1330    print("Incorrect input");
1331    return();
1332  }
1333  int @p = 0;
1334  if ( size(#) > 0 )
1335  {
1336    if ( typeof( #[1] ) == "int" )
1337    {
1338      @p = #[1];
1339    }
1340  }
1341  if (n ==1)
1342  {
1343    ring @rr = @p,(x,D),dp;
1344  }
1345  else
1346  {
1347    ring @rr = @p,(x(1..n),D(1..n)),dp;
1348  }
1349  setring @rr;
1350  def @rrr = Weyl();
1351  return(@rrr);
1352}
1353example
1354{ "EXAMPLE:"; echo = 2;
1355   def a = makeWeyl(3);
1356   setring a;
1357   a;
1358}
1359
1360//////////////////////////////////////////////////////////////////////
1361proc isNC()
1362"USAGE:   isNC();
1363PURPOSE: check whether a basering is commutative or not
1364RETURN:   int, 1 if basering is noncommutative and 0 otherwise
1365EXAMPLE: example isNC; shows examples
1366"{
1367  string rname=nameof(basering);
1368  if ( rname == "basering") // i.e. no ring has been set yet
1369  {
1370    "You have to call the procedure from the ring";
1371    return();
1372  }
1373  int n = nvars(basering);
1374  int i,j;
1375  poly p;
1376  for (i=1; i<n; i++)
1377  {
1378    for (j=i+1; j<=n; j++)
1379    {
1380      p = var(j)*var(i) - var(i)*var(j);
1381      if (p!=0) { return(1);}
1382    }
1383  }
1384  return(0);
1385}
1386example
1387{ "EXAMPLE:"; echo = 2;
1388   def a = makeWeyl(2);
1389   setring a;
1390   isNC();
1391   kill a;
1392   ring r = 17,(x(1..7)),dp;
1393   isNC();
1394   kill r;
1395}
1396
1397///////////////////////////////////////////////////////////////////////////////
1398proc rightStd(def I)
1399"USAGE:  rightStd(I); I an ideal/ module
1400PURPOSE: compute a right Groebner basis of I
1401RETURN:  the same type as input
1402EXAMPLE: example rightStd; shows examples
1403"
1404{
1405  def A = basering;
1406  def Aopp = opposite(A);
1407  setring Aopp;
1408  def Iopp = oppose(A,I);
1409  def Jopp = groebner(Iopp);
1410  setring A;
1411  def J = oppose(Aopp,Jopp);
1412  return(J);
1413}
1414example
1415{ "EXAMPLE:"; echo = 2;
1416  LIB "ncalg.lib";
1417  def A = makeUsl(2);
1418  setring A;
1419  ideal I = e2,f;
1420  option(redSB);
1421  option(redTail);
1422  ideal LI = std(I);
1423  LI;
1424  ideal RI = rightStd(I);
1425  RI;
1426}
1427
1428///////////////////////////////////////////////////////////////////////////////
1429proc rightSyz(def I)
1430"USAGE:  rightSyz(I); I an ideal/ module
1431PURPOSE: compute a right syzygy module of I
1432RETURN:  the same type as input
1433EXAMPLE: example rightSyz; shows examples
1434"
1435{
1436  def A = basering;
1437  def Aopp = opposite(A);
1438  setring Aopp;
1439  def Iopp = oppose(A,I);
1440  def Jopp = syz(Iopp);
1441  setring A;
1442  def J = oppose(Aopp,Jopp);
1443  return(J);
1444}
1445example
1446{ "EXAMPLE:"; echo = 2;
1447  ring r = 0,(x,d),dp;
1448  def S = nc_algebra(1,1); setring S; // the first Weyl algebra
1449  ideal I = x,d;
1450  module LS = syz(I);
1451  print(LS);
1452  module RS = rightSyz(I);
1453  print(RS);
1454}
1455
1456///////////////////////////////////////////////////////////////////////////////
1457proc rightNF(def v, def M)
1458"USAGE:  rightNF(I); v a poly/vector, M an ideal/module
1459PURPOSE: compute a right normal form of v w.r.t. M
1460RETURN:  poly/vector (as of the 1st argument)
1461EXAMPLE: example rightNF; shows examples
1462"
1463{
1464  def A = basering;
1465  def Aopp = opposite(A);
1466  setring Aopp;
1467  def vopp = oppose(A,v);
1468  def Mopp = oppose(A,M);
1469  Mopp = std(Mopp);
1470  def wopp = NF(vopp,Mopp);
1471  setring A;
1472  def w    = oppose(Aopp,wopp);
1473  w = simplify(w,2); // skip zeros in ideal/module
1474  return(w);
1475}
1476example
1477{ "EXAMPLE:"; echo = 2;
1478  LIB "ncalg.lib";
1479  ring r = 0,(x,d),dp;
1480  def S = nc_algebra(1,1); setring S; // Weyl algebra
1481  ideal I = x; I = std(I);
1482  poly  p = x*d+1;
1483  NF(p,I); // left normal form
1484  rightNF(p,I); // right normal form
1485}
1486
1487// **********************************
1488// * NF: Example for vector/module: *
1489// **********************************
1490// module M = [x,0],[0,d]; M = std(M);
1491// vector v = (x*d+1)*[1,1];
1492// print(NF(v,M));
1493// print(rightNF(v,M));
1494
1495///////////////////////////////////////////////////////////////////////////////
1496proc rightModulo(def M, def N)
1497"USAGE:  rightModulo(M,N); M,N are ideals/modules
1498PURPOSE: compute a right representation of the module (M+N)/N
1499RETURN:  module
1500ASSUME:  M,N are presentation matrices for right modules
1501EXAMPLE: example rightModulo; shows examples
1502"
1503{
1504  def A = basering;
1505  def Aopp = opposite(A);
1506  setring Aopp;
1507  def Mopp = oppose(A,M);
1508  def Nopp = oppose(A,N);
1509  def Kopp = modulo(Mopp,Nopp);
1510  setring A;
1511  def K = oppose(Aopp,Kopp);
1512  return(K);
1513}
1514example
1515{ "EXAMPLE:"; echo = 2;
1516  LIB "ncalg.lib";
1517  def A = makeUsl(2);
1518  setring A;
1519  option(redSB);
1520  option(redTail);
1521  ideal I = e2,f2,h2-1;
1522  I = twostd(I);
1523  print(matrix(I));
1524  ideal E  = std(e);
1525  ideal TL = e,h-1; // the result of left modulo
1526  TL;
1527  ideal T = rightModulo(E,I);
1528  T = rightStd(T+I);
1529  T = rightStd(rightNF(T,I)); // make the output canonic
1530  T;
1531}
1532
1533//////////////////////////////////////////////////////////////////////
1534
1535proc isCommutative ()
1536"USAGE:  isCommutative();
1537RETURN:  int, 1 if basering is commutative, or 0 otherwise
1538PURPOSE: check whether basering is commutative
1539EXAMPLE: example isCommutative; shows an example
1540"
1541{
1542  int iscom = 1;
1543  list L = ringlist(basering);
1544  if (size(L) > 4) // basering is nc_algebra
1545  {
1546    matrix C = L[5];
1547    matrix D = L[6];
1548    if (size(module(D)) <> 0) { iscom = 0; }
1549    else
1550    {
1551      matrix U = UpOneMatrix(nvars(basering));
1552      if (size(module(C-U)) <> 0) { iscom = 0; }
1553    }
1554  }
1555  return(iscom);
1556}
1557example
1558{
1559  "EXAMPLE:"; echo = 2;
1560  ring r = 0,(x,y),dp;
1561  isCommutative();
1562  def D = Weyl(); setring D;
1563  isCommutative();
1564  setring r;
1565  def R = nc_algebra(1,0); setring R;
1566  isCommutative();
1567}
1568
1569//////////////////////////////////////////////////////////////////////
1570
1571proc isWeyl ()
1572"USAGE:  isWeyl();
1573RETURN:  int, 1 if basering is a Weyl algebra, or 0 otherwise
1574PURPOSE: check whether basering is a Weyl algebra
1575EXAMPLE: example isWeyl; shows an example
1576"
1577{
1578  int i,j;
1579  int notW = 0;
1580  int N = nvars(basering);
1581  if (N mod 2 <> 0) { return(notW); } // odd number of generators
1582  int n = N div 2;
1583  list L = ringlist(basering);
1584  if (size(L) < 6) { return(notW); } // basering is commutative
1585  matrix C = L[5];
1586  matrix D = L[6];
1587  matrix U = UpOneMatrix(N);
1588  if (size(ideal(C-U)) <> 0) { return(notW); } // lt(xy)<>lt(yx)
1589  ideal I = ideal(D);
1590  if (size(I) <> n) { return(notW); } // not n entries<>0
1591  I = simplify(I,4+2);
1592  int sI = size(I);
1593  if (sI > 2) { return(notW); }  // more than 2 distinct entries
1594  for (i=1; i<=sI; i++)
1595  {
1596    if (I[i]<>1 && I[i]<>-1) { return (notW); } // other values apart from 1,-1
1597  }
1598  ideal Ro,Co;
1599  for (i=1; i<=N; i++)
1600  {
1601    Ro = D[1..N,i];
1602    Co = D[i,1..N];
1603    if (size(Ro)>1 || size(Co)>1)
1604    {
1605      return(int(0)); // var(i) doesn't commute with more than 1 other vars
1606    }
1607  }
1608  return(int(1)); // all tests passed: basering is Weyl algebra
1609}
1610example
1611{
1612  "EXAMPLE:"; echo = 2;
1613  ring r = 0,(a,b,c,d),dp;
1614  isWeyl();
1615  def D = Weyl(1); setring D; //make from r a Weyl algebra
1616  b*a;
1617  isWeyl();
1618  ring t = 0,(Dx,x,y,Dy),dp;
1619  matrix M[4][4]; M[1,2]=-1; M[3,4]=1;
1620  def T = nc_algebra(1,M); setring T;
1621  isWeyl();
1622}
1623
1624//////////////////////////////////////////////////////////////////////
1625
1626proc embedMat(matrix A, int m, int n)
1627"USAGE:  embedMat(A,m,n); A,B matrix/module
1628RETURN:  matrix
1629PURPOSE: embed A in the left upper corner of mxn matrix
1630EXAMPLE: example embedMat; shows an example
1631"
1632{
1633  // returns A embedded in the left upper corner of mxn matrix
1634  int rA = nrows(A);
1635  int cA = ncols(A);
1636  if ((rA >m) || (cA>n))
1637  {
1638    ERROR("wrong dimensions of the new matrix");
1639  }
1640  matrix @M[m][n];
1641  int i,j;
1642  for(i=1;i<=rA; i++)
1643  {
1644    for(j=1;j<=cA; j++)
1645    {
1646      @M[i,j]=A[i,j];
1647    }
1648  }
1649  return(@M);
1650}
1651example
1652{
1653  "EXAMPLE:"; echo = 2;
1654  ring r = 0,(a,b,c,d),dp;
1655  matrix M[2][3]; M[1,1]=a; M[1,2]=b;M[2,2]=d;M[1,3]=c;
1656  print(M);
1657  print(embedMat(M,3,4));
1658  matrix N = M; N[2,2]=0;
1659  print(embedMat(N,3,4));
1660}
1661
1662//proc moduloSlim (matrix A, matrix B)
1663proc moduloSlim (module A, module B)
1664"USAGE:  moduloSlim(A,B); A,B module/matrix/ideal
1665RETURN:  module
1666PURPOSE: compute @code{modulo} with slimgb as engine
1667EXAMPLE: example moduloSlim; shows an example
1668"
1669{
1670  def save  = basering;
1671  int rA = nrows(A);  int rB = nrows(B);
1672  int cA = ncols(A);  int cB = ncols(B);
1673  int j;
1674  int dab; // difference a,b
1675  dab = rA - rB;
1676  if (dab <0)
1677  {
1678    // rA<rB: add zero rows to A
1679    dab = -dab;
1680    A = embedMat(A,rB,cA);
1681  }
1682  else
1683  {
1684    // rA>rB: add zero rows to B
1685    B = embedMat(B,rA,cB);
1686  }
1687  def mering = makeModElimRing(save);
1688  setring mering;
1689  module A = imap(save, A);
1690  module B = imap(save, B);
1691  // create matrix C
1692  //  matrix C[2*rA][cA+cB];
1693  module C;
1694  int i;
1695  for(i=1; i<= cA; i++)
1696  {
1697    C = C, A[i] + gen(rA + i);
1698  }
1699  C = C,B;
1700//   for(i=1; i<=cB; i++)
1701//   {
1702//     C = C, B[i];
1703//   }
1704  C = C[2..ncols(C)];
1705//  print(C);
1706  matrix D = slimgb(C);
1707  module E; int k;
1708  // TODO: why only first row? need smth like rA rows...
1709  for(i=1; i<= ncols(D); i++)
1710  {
1711    k=1;
1712    // determine first zero in the column
1713    while ( (D[k,i]==0) && (k<= cA+rA) )
1714    {
1715      k++;
1716    }
1717    // what can that be: k = cA+rA+1=> zero column
1718    // k<=rA => column not in ker
1719    // rA+1 <= k <= rA+cA => column in ker
1720    if ( ( k>=rA+1) && (k<=rA+cA) )
1721    {
1722      E = E,D[i];
1723    }
1724  }
1725//   for(i=1; i<= ncols(D); i++)
1726//   {
1727//     if (D[1,i]==0)
1728//     {
1729//       E = E,D[i];
1730//     }
1731//   }
1732//  // this E has 1st column and 1st row zero
1733  // use submat@matrix.lib
1734  //  E = submat(E,intvec(2..nrows(E)),intvec(2..ncols(E)));
1735  E = submat(E,intvec(rA+1..nrows(E)),intvec(2..ncols(E)));
1736  setring save;
1737  module E = imap(mering,E);
1738  kill mering;
1739  // TODO: clean components!
1740  return(E);
1741}
1742example
1743{
1744  "EXAMPLE:"; echo = 2;
1745  LIB "ncalg.lib";
1746  ring r; // first classical example for modulo
1747  ideal h1=x,y,z;    ideal h2=x;
1748  module m=moduloSlim(h1,h2);
1749  print(m);
1750  // now, a noncommutative example
1751  def A = makeUsl2(); setring A; // this algebra is U(sl_2)
1752  ideal H2 = e2,f2,h2-1; H2 = twostd(H2);
1753  print(matrix(H2)); // print H2 in a compact form
1754  ideal H1 = std(e);
1755  ideal T = moduloSlim(H1,H2);
1756  T = std( NF(std(H2+T),H2) );
1757  T;
1758  // now, a matrix example:
1759  ring r2 = 0,(x,d), (dp);
1760  def R = nc_algebra(1,1); setring R;
1761  matrix M[2][2] = d, 0, 0, d*(x*d);
1762  matrix P[2][1] = (8x+7)*d+9x, (x2+1)*d + 5*x;
1763  module X = moduloSlim(P,M);
1764  print(X);
1765}
1766
1767//////////////////////////////////////////////////////////////////////
1768
1769proc makeModElimRing(list #)
1770"USAGE:  makeModElimRing(L); L a list
1771RETURN:  ring
1772PURPOSE: create a copy of a given ring equipped with the
1773@* elimination ordering for module components @code{(c,<)}
1774NOTE: usually the list argument contains a ring to work with
1775EXAMPLE: example makeModElimRing; shows an example
1776"
1777{
1778  // supports qring;
1779  // can be extended to handle C istead of c
1780  /* input/basering business */
1781  def save; int Noinput = 0;
1782  if ( size(#)>0 )
1783  {
1784    if (typeof(#[1]) == "ring" )
1785    {
1786      save = #[1];
1787    }
1788    else
1789    {
1790      print("unsupported input type, proceeding with basering");
1791      Noinput = 1;
1792    }
1793  }
1794  if (Noinput)
1795  {
1796    if (nameof(basering)=="basering")
1797    {
1798      ERROR("no rings are given");
1799    }
1800    else
1801    {
1802      save = basering;
1803    }
1804  }
1805  /* END input/basering business */
1806  list L = ringlist(save);
1807  list Ord = L[3];
1808  int s = size(Ord); int done;
1809  // detect where module ordering is located: either 1st or last entry
1810  int i,j;
1811  for(i=1; i<=s; i++)
1812  {
1813    if ( (Ord[i][1] == "C") || (Ord[i][1] == "c") )
1814    {
1815      Ord[i][1] = "c";
1816      j = i; i=s;
1817    }
1818  }
1819  if (j==0) { ERROR("no component entry found in the ringlist"); }
1820  list N;
1821  N[1] = Ord[j];
1822  for(i=2; i<=j; i++)
1823  {
1824    N[i] = Ord[i-1];
1825  }
1826  for(i=j+1; i<=s; i++)
1827  {
1828    N[i] = Ord[i];
1829  }
1830  L[3] = N; def NR = ring(L);
1831  return(NR);
1832}
1833example
1834{
1835  "EXAMPLE:"; echo = 2;
1836  ring r1 = 0,(x,y,z),(C,Dp);
1837  def r2 = makeModElimRing(r1); setring r2; r2;   kill r2;
1838  ring r3 = 0,(z,t),(wp(2,3),c);
1839  def r2 = makeModElimRing(r3); setring r2; r2; kill r2;
1840  ring r4 = 0,(z,t,u,w),(a(1,2),C,wp(2,3,4,5));
1841  def r2 = makeModElimRing(r4); setring r2; r2;
1842}
1843
1844proc isLieType()
1845"USAGE:  isLieType();
1846RETURN:  int, 1 if basering is a G-algebra of Lie type, 0 otherwise
1847PURPOSE: G-algebra of Lie type has relations of the kind Y*X=X*Y+D
1848EXAMPLE: example isLieType; shows an example
1849"
1850{
1851  def @B    = basering; //save the name of basering
1852  int NVars = nvars(@B); //number of variables in basering
1853  int i, j;
1854
1855  int answer = 1;
1856
1857  // check basering is of Lie type:
1858  matrix @@CC[NVars][NVars];
1859  for(i=1; i<NVars; i++)
1860  {
1861    for(j=i+1; j<=NVars; j++)
1862    {
1863      @@CC[i,j]=leadcoef(var(j)*var(i));
1864    }
1865  }
1866  ideal @C@ = simplify(ideal(@@CC),2+4);// skip zeroes and repeated entries
1867  if (  (size(@C@) >1 ) || ( (size(@C@)==1) && (@C@[1]!=1) )  )
1868  {
1869    answer = 0;
1870  }
1871  return(answer);
1872}
1873example
1874{
1875  "EXAMPLE:"; echo = 2;
1876  ring r = 0,(x,y),dp;
1877  y*x;
1878  isLieType(); //yes
1879  def D = Weyl(); setring D;
1880  y*x;
1881  isLieType(); //yes
1882  setring r;
1883  def R = nc_algebra(-3,0); setring R;
1884  y*x;
1885  isLieType(); // no
1886  kill R; kill r;
1887  ring s = (0,q),(x,y),dp;
1888  def S = nc_algebra(q,0); setring S;
1889  y*x;
1890  isLieType(); //no
1891  kill S; setring s;
1892  def S = nc_algebra(q,y^2); setring S;
1893  y*x;
1894  isLieType(); //no
1895}
Note: See TracBrowser for help on using the repository browser.