source: git/Singular/LIB/center.lib @ ec9b96

spielwiese
Last change on this file since ec9b96 was ec9b96, checked in by Motsak Oleksandr <motsak@…>, 18 years ago
!: found&fixed a bug: mindeg of ideal is intmat => mindegInt git-svn-id: file:///usr/local/Singular/svn/trunk@9129 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 54.9 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: center.lib,v 1.20 2006-05-11 18:53:25 motsak Exp $"
3category="Noncommutative"
4info="
5LIBRARY:  center.lib      computation of central elements of GR-algebras
6AUTHOR:  Oleksandr Motsak,        motsak@mathematik.uni-kl.de.
7OVERVIEW: Computing elements of center and centralizers of sets of elements
8in non-commutative algebras.
9
10MAIN PROCEDURES:
11centralizeSet(F, V):          v.s. basis of the centralizer of F within V
12centralizerVS(F, D):          v.s. basis of the centralizer of F
13centralizerRed(F, D[, N]):    reduced basis of the centralizer of F
14centerVS(D):                  v.s. basis of the center
15centerRed(D[, k]):            reduced basis of the center
16
17center(D[, k]):               reduced basis of the center
18centralizer(F, D[, k]):       reduced bais of the centralizer of F
19
20sa_reduce(V):              's.a. reduction' of pairwise commuting elements
21sa_poly_reduce(p, V):      's.a. reduction' of p by pairwise commuting elements
22
23inCenter(T):                  checks the centrality of list/ideal/poly T
24inCentralizer(T, S):          checks whether list/ideal/poly T commute with S
25isCartan(p):                  checks whether polynomial p is a Cartan element
26
27AUXILIARY PROCEDURES:
28applyAdF(Basis, f):           images of elements under the k-linear map Ad_{f}
29linearMapKernel(Images):      kernel of a linear map given by images
30linearCombinations(Basis, C): k-linear combinations of elements
31
32variablesStandard():           set of algebra generators in their natural order
33variablesSorted():             heuristically sorted set of algebra generators
34
35PBW_eqDeg(Deg):                PBW monomials of given degree
36PBW_maxDeg(MaxDeg):            PBW monomials up to given degree
37PBW_maxMonom(MaxMonom):        PBW monomials up to given maximal monomial
38
39KEYWORDS:  center; centralizer; cartan; reduce; centralize; PBW
40"
41
42LIB "general.lib" // for "sort"
43LIB "poly.lib" // for "maxdeg"
44
45
46/******************************************************/
47// ::DefaultStuff:: Shortcuts to useful short functions. Just to avoid if( if( if( ... ))).
48/******************************************************/
49
50
51/******************************************************/
52static proc DefaultValue ( def s, list # ) // Process general variable parameters list
53  "
54RETURN: s or (typeof(s))(#)
55"
56{
57  def @p = s;
58  if ( size(#) > 0 )
59  {
60    if ( typeof(#[1]) == typeof(s) )
61      {
62        @p = #[1];
63      }
64  }
65  return( @p );
66}
67
68/******************************************************/
69static proc DefaultInt( list # ) // Process variable parameters list with 'int' default value
70  "
71RETURN: 0 or int(#)
72"
73{
74  int @p = 0;
75  return( DefaultValue( @p, # ) );
76}
77
78/******************************************************/
79static proc DefaultIdeal ( list # ) // Process variable parameters list with 'ideal' default value
80  "
81RETURN: 0 or ideal(#)
82"
83{
84  ideal @p = 0;
85  return( DefaultValue( @p, # ) );
86}
87
88
89
90/******************************************************/
91// ::Debug:: Shortcuts to used debugging functions.
92/******************************************************/
93
94
95/******************************************************/
96static proc toprint( int pl ) // To print or not to print?!? The answer is here!
97  "
98RETURN: 1 means to print, otherwise 0.
99"
100{
101  return( printlevel >= ( 3 -  pl) ); // voice + ?
102}
103
104/******************************************************/
105static proc DBPrint( int pl, list # ) // My 'dbprint' which uses toprint(i).
106  "
107    USAGE:     
108"
109{
110  if( toprint(pl) )
111    {
112      dbprint(1, #);
113    }
114}
115
116/******************************************************/
117static proc BCall( string Name, list # ) // This function must be called at the beginning of every 'mathematical' function.
118  "
119USAGE: Name is a name of a mathematical function to trace. # means parameters into the function.
120"
121{
122  if( toprint(0) )
123    {
124      "CALL: ", Name, "( ";
125      dbprint(1, #);
126      "     )";
127    }
128}
129
130/******************************************************/
131static proc ECall(string Name, list #) // This function must be called at the end of every 'mathematical' function.
132  "
133USAGE: Name is a name of a mathematical function to trace. # means result of the function.
134"
135{
136  if( toprint(0) )
137    {
138      "RET : ", Name, " => Result: {";
139      dbprint(1, #);
140      "    }";
141    }
142}
143
144
145
146/******************************************************/
147// ::Helpers:: Small functions used in this library.
148/******************************************************/
149
150/******************************************************/
151static proc makeNice( def l )
152  "
153RETURN: the same as input
154PURPOSE: make 'nice' polynomials, kill scalars
155"
156{
157  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "makeNice", l ); }; /*4DEBUG*/
158
159  poly p;
160   
161  if( typeof(l) == "poly" )
162    {
163      // "normal" polynomial form == no denominators, gcd of coeffs is a unit
164      l = cleardenom( l );
165      if ( deg(p) > 0 )
166        {
167          l = cleardenom( l / leadcoef(l) );
168        }
169    } else
170      {
171        if( typeof(l) == "ideal" )
172          {
173            for( int i = 1; i <= size(l); i++ )
174              {   
175                p = l[i];
176                p = cleardenom( p );
177       
178                // Now make polynomials look nice:
179                if ( deg(p) > 0 ) // throw away scalars!
180                  {
181                    // "normal" polynomial form == no denominators, gcd of coeffs is a unit
182                    p = cleardenom( p / leadcoef(p) );
183                  } else
184                    {
185                      p = 0; // no constants
186                    }
187                l[i] = p;
188
189              }
190           
191            l = simplify(l, 2 + 8);
192          }
193      }
194
195  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "makeNice", l ); }; /*4DEBUG*/
196  return( l );
197}
198
199
200
201/******************************************************/
202static proc monomialForm( def p )
203  "
204: p is either poly or ideal
205RETURN: polynomial with all monomials from p but without coefficients.
206"
207{
208  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "monomialForm", p ); }; /*4DEBUG*/
209
210  poly result = 0; int k, j; poly m;
211   
212  if( typeof(p) == "ideal" ) //
213    {
214      if( ncols(p) > 0 )
215        {
216          result = uni_poly( p[1] );
217       
218          for ( k = ncols(p); k > 1; k -- )
219            {           
220              for( j = size(p[k]); j > 0; j-- )
221                {
222                  m = leadmonom( p[k][j] );
223                   
224                  if( size(result + m) > size(result) ) // trick!
225                    {
226                      result = result + m;
227                    }
228                }
229               
230            }
231        }
232    }
233  else
234    {
235      if( typeof(p) == "poly" ) //
236        {
237          result = uni_poly(p);
238        } else
239          {
240            ERROR( "ERROR: Wrong input! Expected polynomial or ideal!" );
241          }
242    }
243   
244  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "monomialForm", result ); }; /*4DEBUG*/
245  return( result );
246}
247
248/******************************************************/
249static proc uni_poly( poly p )
250  "
251    returns polynomial with the same monomials but without coefficients.
252"
253{
254  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "uni_poly", p ); }; /*4DEBUG*/
255
256  poly result = 0;
257   
258  for ( int k = size(p); k > 0; k -- )
259    {
260      result = result + leadmonom( p[k] );
261    }
262   
263  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "uni_poly", result ); }; /*4DEBUG*/
264  return( result );
265}
266
267
268
269
270
271/******************************************************/
272static proc smoothQideal( ideal I, list #)
273  "
274PURPOSE: smooths the ideal in a current QUOTIENT(!) ring.
275"
276{
277  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "smoothQideal", I ); }; /*4DEBUG*/
278   
279  ideal A = I - NF( I, twostd(DefaultIdeal(#)), 1 ); // component wise
280
281  if( size(A) > 0 ) // Were there any changes (any non-zero component)?
282    {
283      ideal T;
284
285      int j = 1;
286   
287      for( int i = 1; i <= ncols(I); i++ )
288        {
289          if( size(A[i]) == 0 ) // keep only unchanged elements
290            {
291              T[ j ] = I[i]; j++;
292            }
293        }
294      I = T;
295    }
296   
297  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "smoothQideal", I ); }; /*4DEBUG*/
298   
299  return( I );   
300}
301
302
303
304
305/******************************************************/
306// ::PBW:: PBW basis construction.
307/******************************************************/
308
309
310
311
312/******************************************************/
313proc PBW_maxDeg( int MaxDeg )
314"USAGE: PBW_maxDeg(MaxDeg); int MaxDeg
315PURPOSE: Compute PBW elements up to a given maximal degree.
316RETURN: ideal consisting of found elements.
317NOTE: unit is omitted. Weights are ignored!
318"
319{
320  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "PBW_maxDeg", MaxDeg ); }; /*4DEBUG*/
321   
322  ideal Basis = 0;
323   
324  for (int k = 1; k <= MaxDeg; k ++ )
325    {
326      Basis = Basis + maxideal(k);
327    }
328   
329  Basis = smoothQideal( Basis );
330   
331  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "PBW_maxDeg", Basis ); }; /*4DEBUG*/
332  return( Basis );
333}
334example
335{
336  "EXAMPLE:"; echo = 2;
337  ring A = 0,(e,f,h),dp;
338  matrix D[3][3]=0;
339  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
340  ncalgebra(1,D); // this algebra is U(sl_2)
341
342  // PBW Basis of A_2 - monomials of degree <= 2, without unit:
343  PBW_maxDeg( 2 );
344}
345
346
347/******************************************************/
348proc PBW_eqDeg( int Deg )
349"USAGE: PBW_eqDeg(Deg); int Deg
350PURPOSE: Compute PBW elements of a given degree.
351RETURN: ideal consisting of found elements.
352NOTE: Unit is omitted. Weights are ignored!
353"
354{
355  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "PBW_eqDeg", Deg ); }; /*4DEBUG*/
356   
357  ideal Basis = smoothQideal( maxideal( Deg ) );
358   
359  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "PBW_eqDeg", Basis ); }; /*4DEBUG*/
360  return( Basis );
361}
362example
363{
364  "EXAMPLE:"; echo = 2;
365  ring A = 0,(e,f,h),dp;
366  matrix D[3][3]=0;
367  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
368  ncalgebra(1,D); // this algebra is U(sl_2)
369
370  // PBW Basis of A_2 \ A_1 - monomials of degree == 2:
371  PBW_eqDeg( 2 );
372}
373
374
375/******************************************************/
376proc PBW_maxMonom( poly MaxMonom )
377"USAGE: PBW_maxMonom(m); poly m
378PURPOSE: Compute PBW elements up to a given maximal one.
379RETURN: ideal consisting of found elements.
380NOTE: Unit is omitted. Weights are ignored!
381"
382{
383  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "PBW_maxMonom", MaxMonom ); }; /*4DEBUG*/
384   
385  ideal K = 0;
386   
387  intvec exp = leadexp( MaxMonom );
388   
389  for ( int k = 1; k <= size(exp); k ++ )
390    {
391      K[ 1 + size(K) ] = var(k)^( 1 + exp[k] );
392    }
393   
394  attrib(K, "isSB", 1);
395   
396  K = kbase(K);
397   
398  K = K[ (ncols(K)-1)..1]; // reverse, kill last 1
399   
400  K = smoothQideal( K );
401
402  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "PBW_maxMonom", K ); }; /*4DEBUG*/
403   
404  return( K );
405}
406example
407{
408  "EXAMPLE:"; echo = 2;
409  ring A = 0,(e,f,h),dp;
410  matrix D[3][3]=0;
411  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
412  ncalgebra(1,D); // this algebra is U(sl_2)
413
414  // At most 1st degree in e, h and at most 2nd degree in f, unit is omitted:
415  PBW_maxMonom( e*(f^2)* h );
416}
417
418
419
420
421/******************************************************/
422// ::CORE:: Core procedures...
423/******************************************************/
424
425
426
427/******************************************************/
428proc applyAdF( ideal I, poly p )
429  "
430USAGE: applyAdF( Basis, f); ideal Basis, poly f
431PURPOSE: Apply Ad_{f} to every element of Basis
432RETURN: ideal, Ad_{f}(Basis)
433SEE ALSO:   linearMapKernel; linearMapKernel
434"
435{
436  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "applyAdF", I, p ); }; /*4DEBUG*/
437
438  poly t; ideal II = 0;
439
440  for ( int k = ncols(I); k > 0; k --)
441    {
442      t = I[k];
443      II[k] = p * t - t * p; // we have to reduce smooth images in Qrings...
444    }
445   
446  II = NF( II, twostd(0) ); // ... now!
447   
448  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "applyAdF", II ); }; /*4DEBUG*/
449  return( II );
450}
451example
452{
453  "EXAMPLE:"; echo = 2;
454  ring A = 0,(e,f,h),dp;
455  matrix D[3][3]=0;
456  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
457  ncalgebra(1,D); // this algebra is U(sl_2)
458
459  // Let us consider the linear map Ad_{e} from A_2 into A.
460
461  // Compute the PBW basis of A_2:
462  ideal Basis = PBW_maxDeg( 2 ); Basis;
463
464  // Compute images of basis elements under the linear map Ad_e:
465  ideal Image = applyAdF( Basis, e ); Image;
466
467  // Now we have a linear map given by: Basis_i --> Image_i
468  // Let's compute its kernel:
469  module C = linearMapKernel( Image ); C;
470
471  // Now we can compute the kernel of Ad_e by means of basis vectors:
472  ideal K = linearCombinations(Basis, C); K;
473
474  // Let's check that Ad_e(K) is zero:
475  applyAdF( K, e );
476}
477
478
479
480/******************************************************/
481proc linearMapKernel( ideal Images )
482"USAGE: linearMapKernel( Images ); ideal Images
483PURPOSE: Computes the kernel of a linear map: e_i \mapsto Images[i],
484@* where e_i are certain basis vectors
485RETURN: syzygy module, or 0 if all images are zeroes
486SEE ALSO:   applyAdF; linearMapKernel
487"
488{
489  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "linearMapKernel", Images ); }; /*4DEBUG*/
490
491  // This must be a list of monomials in a form of polynomial (sum with coeffs == 1)   
492  poly Monomials = monomialForm( Images );
493
494  int N = size( Monomials ); // number of different monomials   
495   
496  if ( N == 0 ) // & ncols( Images ) > 0 => all Images == 0
497    {
498      int result = 0;
499       
500      /*4DEBUG*/        if( defined( @@@DEBUG ) ){ ECall( "linearMapKernel", result ); }; /*4DEBUG*/
501      return( result );
502    }
503
504  // Compute matrix MD
505  module MD; // zero
506
507  int x, y;
508   
509  vector w;
510   
511  poly p, m;
512   
513  int V = ncols(Images); // must be equal to ncols(Basis) and size(Basis)!
514   
515  // We take monomials as vector space basis of <Image>_k...
516   
517  // TODO: Is there any other way to compute a basis of it and represent images as
518  // linear combination of them???
519   
520  // Maybe some 'free resolution' stuff??? But we need linear maps only!!!
521   
522  for ( x = 1; x <= V; x++ ) // For every Image vector
523    {
524      w = 0;         
525       
526      p = Images[x];
527       
528      y = 1; // from 1st monomial in Monomials...
529       
530      while( size(p) > 0 )
531        {
532          m = leadmonom(p);
533           
534          // y < N!
535          while( Monomials[y] != m )
536            // There MUST be this monomial because of the construction of Monomials polynomial!
537            {
538              y++; // to size()
539            }
540           
541          // found monomial m at position y.
542           
543          w = w + leadcoef(p) * gen(y); // leadcoef(p) MUST be nonzero!
544          p = p - lead(p); // kill lead term           
545        }
546       
547      MD[x] = w;
548    }
549   
550  /*******************************************/
551   
552  // save options
553  intvec v = option( get );
554   
555  // set right options
556  option( redSB );
557  option( redTail );
558   
559  // compute everything in a right form
560  MD = simplify( std( syz(MD) ), 1 + 2 + 8 );
561  // note that MD is a matrix of numbers - no polynomials...
562   
563  // restore options
564  option( set, v );
565   
566  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "linearMapKernel", MD ); }; /*4DEBUG*/
567
568  return( MD );
569}
570example
571{
572  "EXAMPLE:"; echo = 2;
573  ring A = 0,(e,f,h),dp;
574  matrix D[3][3]=0;
575  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
576  ncalgebra(1,D); // this algebra is U(sl_2)
577
578  // Let us consider the linear map Ad_{e} from A_2 into A.
579
580  // Compute the PBW basis of A_2:
581  ideal Basis = PBW_maxDeg( 2 ); Basis;
582
583  // Compute images of basis elements under the linear map Ad_e:
584  ideal Image = applyAdF( Basis, e ); Image;
585
586  // Now we have a linear map given by: Basis_i --> Image_i
587  // Let's compute its kernel:
588  module C = linearMapKernel( Image ); C;
589
590  // Now we can compute the kernel of Ad_e by means of basis vectors:
591  ideal K = linearCombinations(Basis, C); K;
592
593  // Let's check that Ad_e(K) is zero:
594  ideal Z = applyAdF( K, e ); Z;
595
596  // Now linearMapKernel will return a single integer 0:
597  def CC  = linearMapKernel(Z); typeof(CC); CC;
598}
599
600
601/******************************************************/
602proc linearCombinations( ideal Basis, module KER )
603  "
604USAGE:  linearCombinations( Basis, C ); ideal Basis, module C
605PURPOSE: computes linear combinations of Basis vectors with coefficients from C
606RETURN: ideal generated by computed linear combinations
607SEE ALSO:   linearMapKernel; applyAdF
608"
609{
610   
611  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "linearCombinations", Basis, KER ); }; /*4DEBUG*/
612
613
614  number c;   
615   
616  int x, y;
617   
618  vector w;
619   
620  poly p;
621   
622  ideal result = 0;
623 
624  // Kernel' basis translation
625  for ( x = 1; x <= ncols(KER); x++ )
626    {
627      p = 0;
628      w = KER[x];
629       
630      for ( y = 1; y <= nrows(w); y++ )
631        {
632          c = leadcoef( w[y] );
633
634          if ( c != 0 )
635            {
636              p = p + c * Basis[y]; // linear combination of base vectors { Basis[y] }
637            }
638        }
639      result[ x ]  = p;
640    }
641   
642   
643  // no reduction in quotient algebras is needed. No multiplications were done!
644   
645   
646  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "linearCombinations", result ); }; /*4DEBUG*/
647   
648  return( result );
649}
650example
651{
652  "EXAMPLE:"; echo = 2;
653  ring A = 0,(e,f,h),dp;
654  matrix D[3][3]=0;
655  D[1,2]=-h;  D[1,3]=2*e;  D[2,3]=-2*f;
656  ncalgebra(1,D); // this algebra is U(sl_2)
657
658  // Let us consider the linear map Ad_{e} from A_2 into A.
659
660  // Compute the PBW basis of A_2:
661  ideal Basis = PBW_maxDeg( 2 ); Basis;
662
663  // Compute images of basis elements under the linear map Ad_e:
664  ideal Image = applyAdF( Basis, e ); Image;
665
666  // Now we have a linear map given by: Basis_i --> Image_i
667  // Let's compute its kernel:
668  module C = linearMapKernel( Image ); C;
669
670  // Now we can compute the kernel of Ad_e by means of basis vectors:
671  ideal K = linearCombinations(Basis, C); K;
672
673  // Let's check that Ad_e(K) is zero:
674  applyAdF( K, e );
675}
676
677
678
679/******************************************************/
680static proc LINEAR_MAP_KERNEL(ideal Basis, ideal Images ) // Ker of the linear map given by its values on basis vectors
681  "
682PURPOSE: Computation of the kernel basis of the linear map given by the list @given
683"
684{
685  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "LINEAR_MAP_KERNEL", Basis, Images ); }; /*4DEBUG*/
686   
687  ideal result = 0;
688   
689  if ( size( Basis ) == 0 )
690    {
691      /*4DEBUG*/        if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", result ); }; /*4DEBUG*/
692      return( result );
693    }
694   
695  // compute fundamental solutions system
696  def T = linearMapKernel( Images );
697   
698   
699  // check result of linearMapKernel
700  if( (typeof(T) == "int") and (T == 0) )
701    {
702      // All zeroes! Return Basis:
703      /*4DEBUG*/        if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", Basis ); }; /*4DEBUG*/
704      return( Basis );
705    }
706  else
707    {
708      if( typeof(T) != "module" )
709        {
710          ERROR( "Wrong output from the 'linearMapKernel' function!" );
711        }   
712    }
713   
714  result = linearCombinations( Basis, T );
715   
716  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", result ); }; /*4DEBUG*/
717  return( result );
718}
719
720
721
722
723/******************************************************/
724static proc ZeroKer( ideal Basis, ideal Images ) // VS Basis of a Kernel of the linear map AD_h, h is a Cartan element
725"
726PURPOSE: Computes VS Basis of a Kernel of the linear map AD_h, when h is a Cartan element
727NOTE: the result is a set of all basis vectors having a zero image
728"
729{
730  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "ZeroKer", Basis, Images ); }; /*4DEBUG*/
731
732  ideal result = 0;
733
734  for( int i = 1; i <= ncols( Basis ); i++ )
735    {
736      if( size( Images[i] ) == 0 ) // zero image?
737        {
738          result[ 1 + size(result) ] = Basis[i]; // take this basis vector!
739        }
740    }
741   
742  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "ZeroKer", result ); }; /*4DEBUG*/
743  return( result );
744}
745
746
747
748
749/******************************************************/
750// ::Variables:: Computes a set of variables
751/******************************************************/
752
753
754
755/******************************************************/
756proc variablesStandard() // Returns an ideal of variables in a current base ring.
757"USAGE:      variablesStandard();
758RETURN:     ideal, generated by algebra variables
759PURPOSE:    computes the set of algebra variables taken in their natural order
760SEE ALSO:   variablesSorted
761EXAMPLE:    example variablesStandard; shows an example
762"
763{
764  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "variablesStandard" ); }; /*4DEBUG*/
765
766  ideal result = maxideal(1);
767
768  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "variablesStandard", result ); }; /*4DEBUG*/
769  return( result );
770}
771example
772{
773  "EXAMPLE:"; echo = 2;
774  ring A = 0,(x,y,z),dp;
775  matrix D[3][3]=0;
776  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
777  ncalgebra(1,D); // this algebra is U(sl_2)
778  // Variables in their natural order:
779  variablesStandard();
780}
781
782/******************************************************/
783proc variablesSorted() // Sorts variables into an ideal. This is a kind of heuristics!
784"USAGE:      variablesSorted();
785RETURN:     ideal, generated by sorted algebra variables
786PURPOSE:    computes the set of algebra variables sorted so that
787@* Cartan variables go first
788NOTE:       This is a heuristics for the computation of center:
789@* it is better to compute centralizers of Cartan variables first since in this
790@* case we can omit solving the system of equations.
791SEE ALSO:   variablesStandard
792EXAMPLE:    example variablesSorted; shows an example
793"{
794  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "variablesSorted" ); }; /*4DEBUG*/
795
796  ideal V   = variablesStandard();
797  int  N    = size( V ); // == nvars( basering )
798
799  ideal result = 0;
800
801  int  r_begin = 1;
802  int  r_end   = N;
803
804  poly v;
805
806  for( int k = 1; k <= N; k++ )
807    {
808      v = V[k];
809
810      if( isCartan(v) == 1 ) // Cartan elements go 1st
811        {
812          result[r_begin] = v;
813          r_begin++;
814        } else // Other - in the end...
815          {
816            result[r_end] = v;
817            r_end--;
818          }
819    }
820
821  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "variablesSorted", result ); }; /*4DEBUG*/
822  return( result );
823}
824example
825{
826  "EXAMPLE:"; echo = 2;
827  ring A = 0,(x,y,z),dp;
828  matrix D[3][3]=0;
829  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
830  ncalgebra(1,D); // this algebra is U(sl_2)
831  // There is only one Cartan variable - z in U(sl_2),
832  // it must go 1st:
833  variablesSorted();
834}
835
836
837
838
839
840/******************************************************/
841/******************************************************/
842// ::BasicCentralizerComputation:: Basic functions for centralize' computation.
843/******************************************************/
844/******************************************************/
845
846
847
848
849
850/******************************************************/
851proc centralizeSet( ideal F, ideal V ) // HL 'core' function
852"USAGE:      centralizeSet( F, V ); ideal F, ideal V
853INPUT:      a finite set of elements F, vector space basis V
854RETURN:     ideal, generated by base elements
855PURPOSE:    computes a v.s. basis of the centralizer of F in v.s. V
856NOTE:       Cen(F,V) is computed by the formula Cen(F[N],..,Cen(F[1],V)..)
857SEE ALSO:   centralizerVS; centralizer; inCentralizer
858EXAMPLE:    example centralizeSet; shows an example
859"
860{
861  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "centralizeSet", F, V ); }; /*4DEBUG*/
862
863  int  N = size(F);
864
865  if( N == 0)
866    {
867      ERROR( "F MUST be non empty!!!" );
868    }
869   
870  DBPrint(1, "BasisSize: " + string(size(V)) );
871
872  ideal Images;
873   
874  for( int v = 1; (v <= N) and (size(V) > 0); v++ )
875    {
876      DBPrint(1, "Centralizing " + string(F[v]) );
877       
878      Images = applyAdF( V, F[v] );
879       
880      if( (isCartan(F[v]) == 1) or (size(V) == 1) )
881        {
882          V = ZeroKer( V, Images );
883        } else
884          {
885            V = LINEAR_MAP_KERNEL( V, Images );
886          }
887       
888      // Printing...
889      DBPrint(1, "Progress: [ " + string(v) + " / " + string(N) + " ]"+
890              " => BasisSize: " + string(size(V)) );       
891    }
892   
893  V = makeNice(V);
894   
895  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "centralizeSet", V ); }; /*4DEBUG*/
896   
897  return( V );
898}
899example
900{
901  "EXAMPLE:"; echo = 2;
902  ring A_4_1 = 0,(e(1..4)),dp;
903  matrix D[4][4]=0;
904  D[2,4] = -e(1);
905  D[3,4] = -e(2);
906  // This is $A_{41}$ - the first real Lie algebra of dimension $4$.
907  ncalgebra(1,D);
908 
909  ideal F = variablesSorted(); F;
910 
911  // the center of $A_{41}$ is generated by
912  // $e(1)$ and $-1/2*e(2)^2+e(1)*e(3)$
913  // therefore one may consider computing it in the following way:
914 
915  // 1. Compute PBW basis consisting of
916  //    monomials of exponent <= (1,2,1,0)
917  ideal V = PBW_maxMonom( e(1) * e(2)^ 2 * e(3) );
918 
919  // 2. Compute the centralizer of F within vector space
920  //    spanned by these monomials:
921  ideal C = centralizeSet( F, V ); C;
922 
923  inCenter(C);
924}
925
926
927
928/******************************************************/
929proc centralizerVS( ideal F, int d )
930  "USAGE:      centralizerVS( F, D ); ideal F, int D
931RETURN:     ideal, generated by elements of degree <= D
932PURPOSE:    computes a v.s. basis of the centralizer of F up to degree D.
933NOTE:       D must be non-negative
934SEE ALSO:   centerVS; centralizer; inCentralizer
935EXAMPLE:    example centralizerVS; shows an example
936"
937{
938  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "centralizerVS", F, d ); }; /*4DEBUG*/
939   
940  if( size(F) == 0)
941    {
942      ERROR( "F MUST be non-empty!!!" );
943    }
944
945  ideal V = centralizeSet( F, PBW_maxDeg( d ) ); // basis of the Centralizer of S in PBW basis
946   
947  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "centralizerVS", V ); }; /*4DEBUG*/
948   
949  return( V );
950}
951example
952{
953  "EXAMPLE:"; echo = 2;
954  ring A = 0,(x,y,z),dp;
955  matrix D[3][3]=0;
956  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
957  ncalgebra(1,D); // this algebra is U(sl_2)
958  ideal F = x, y;
959  // find all elements commuting with x and y of degree <= 4:
960  ideal C = centralizerVS(F, 4);
961  C;
962  inCentralizer(C, F);
963}
964
965
966
967
968/******************************************************/
969// ::CenterAliases:: Basic functions/aliases for center' computation.
970/******************************************************/
971
972
973
974
975/******************************************************/
976proc centerVS( int D )
977"USAGE:      centerVS( D ); int D
978RETURN:     ideal, generated by elements of degree <= D
979PURPOSE:    computes a v.s. basis of the center up to degree D.
980NOTE:       D must be non-negative
981SEE ALSO:   centralizerVS; center; inCenter
982EXAMPLE:    example centerVS; shows an example
983"
984{
985  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "centerVS", D ); }; /*4DEBUG*/
986
987
988  if( nameof( basering ) == "basering" )
989    {
990      //        ERROR( "No current ring!" );
991    }
992   
993  if( D < 0 )
994    {
995      ERROR( "Degree D must be non-negative!" );
996    }
997   
998  ideal result = centralizerVS( variablesSorted(), D );
999     
1000  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "centerVS", result ); }; /*4DEBUG*/
1001
1002  return( result );
1003}
1004example
1005{
1006  "EXAMPLE:"; echo = 2;
1007  ring A = 0,(x,y,z),dp;
1008  matrix D[3][3]=0;
1009  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
1010  ncalgebra(1,D); // this algebra is U(sl_2)
1011  // find all central elements of degree <= 4
1012  ideal Z = centerVS(4);
1013  Z;
1014  // note that the second element is the square of the first
1015  // plus the multiple of the first:
1016  Z[2] - Z[1]^2 + 8*Z[1];
1017  inCenter(Z);
1018}
1019
1020
1021/******************************************************/
1022proc centralizerRed( ideal F, int D, list # )
1023"USAGE:      centralizerRed( F, D[, N] ); ideal F, int D[, int N]
1024RETURN:     ideal, generated by computed generators
1025PURPOSE:    computes a subalgebra generators of centralizer(F) up to degree D.
1026NOTE:       In general, one cannot compute the whole centralizer(F).
1027@* Hence, one has to specify a termination condition via arguments D and/or N.
1028@* If D is positive, only centralizing elements up to degree D will be found.
1029@* If D is negative, the termination is determined by N only.
1030@* If N is given, the computation stops if at least N elements has been found.
1031@* Warning: if N is given and bigger than the actual number of generators,
1032@* the procedure may not terminate.
1033@* Current ordering must be a degree compatible well-ordering.
1034SEE ALSO:   centralizerVS; centerRed; centralizer; inCentralizer
1035EXAMPLE:    example centralizerRed; shows an example
1036"
1037{
1038  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "centralizerRed", F, D, # ); }; /*4DEBUG*/
1039   
1040  if( nameof( basering ) == "basering" )
1041    {
1042      //        ERROR( "No current ring!" );
1043    }   
1044   
1045  if( size(F) == 0)
1046    {
1047      ERROR( "F MUST be non-empty!!!" );
1048    }
1049
1050  /////////////////////////////////////////////////////////////////////////////
1051
1052  int i, j, l, d;
1053   
1054  /////////////////////////////////////////////////////////////////////////////
1055 
1056  int k = DefaultInt(#);
1057   
1058  int m = (k > 0);
1059       
1060  int @MinDeg = 1; // starting guess for Maximal Bounding Degree, 6
1061  int @Delta  = 1; // increment of it, 4
1062       
1063  if( m and (D <= 0) )
1064    {
1065      // minimal guess
1066      D = @MinDeg;
1067    }
1068   
1069  if( !m and D < 0)
1070    {
1071      ERROR("Wrong bounding condition!");
1072    }
1073
1074  /////////////////////////////////////////////////////////////////////////////
1075
1076  def NCRING = basering; // Non-commutative ring
1077  list L = ringlist( NCRING );
1078  def L1, L2, L3, L4 = L[1..4]; // General components   
1079
1080  def COMMRING = ring( list( L1, L2, L3, L4 ) ); // Underlying commutative ring
1081   
1082
1083  /////////////////////////////////////////////////////////////////////////////
1084
1085  // we keep the list of found leading monomials in the commutative ring!
1086  setring COMMRING;
1087   
1088  // Init
1089  list FOUND_LEADING_MONOMIALS = list();
1090       
1091  for( i = 1; i <= D; i++ )
1092    {
1093      FOUND_LEADING_MONOMIALS[i] = ideal();
1094    }
1095
1096  ideal FLM, NEW, T; // in COMMRING
1097   
1098  /////////////////////////////////////////////////////////////////////////////
1099
1100  setring NCRING;
1101
1102  ideal result, FLM, PBW, NEW, T, P; // in NCRING
1103   
1104  // Main loop:
1105  i = 1;
1106   
1107  while( i <= D )
1108    {
1109      DBPrint( 1, "Current degree is " + string(i) );
1110       
1111      /////////////////////////////////////////////////////////////////////////////
1112       
1113      // Compute current "reduced" PBW basis...
1114       
1115      // Prepare current found leading monomials
1116      setring COMMRING;
1117      FLM = FOUND_LEADING_MONOMIALS[i];
1118
1119      // And back to NCRing
1120      setring NCRING;       
1121       
1122      FLM = imap(COMMRING, FLM); // We cannot write imap(COMMRING, FOUND_LEADING_MONOMIALS[i]) :(((
1123
1124      attrib(FLM, "isSB", 1); // just to avoid "no standard basis" warning.
1125
1126      // degrees should not change,
1127      // no monomials should be multiplied here
1128      T = reduce( PBW_eqDeg( i ), FLM, 1 );
1129
1130      // we simply kill in T monomials occurring in FOUND_LEADING_MONOMIALS[i]
1131      P = PBW + T; // + simplifies
1132       
1133      // Compute current centralizer
1134      NEW = centralizeSet( F, P );
1135       
1136      if( size(NEW) > 0 )
1137        {
1138          // In order to speedup multiplications we are going into a commutative ring:
1139          setring COMMRING;
1140           
1141          // we can perform commutative interreduction
1142          // since no monomials should be multiplied!
1143          // degrees should not change
1144          NEW = interred( imap( NCRING, NEW ) );
1145           
1146          // Go back!
1147          setring NCRING;
1148           
1149          NEW = imap( COMMRING, NEW );
1150           
1151          DBPrint( 1, "Found: ", NEW );
1152           
1153          // Add them to result...
1154          result = result + NEW;
1155        }
1156       
1157      // Did we find needed number of generators? Or reached the bound?
1158      if( (m and (size(result) >= k)) or (!m and (i == D)) )
1159        {
1160          break; // Get out of here!!!
1161        }
1162       
1163      // otherwise we must update FOUND_LEADING_MONOMIALS
1164      if( size(NEW) > 0 )
1165        {
1166          setring COMMRING;
1167           
1168          FLM = 0;
1169           
1170          // We must update FOUND_LEADING_MONOMIALS!!!
1171          for( j = 1; j <= size(NEW); j++ )
1172            {
1173              FLM[j] = leadmonom( NEW[j] ); // we are interested in leading monomials only!
1174            }
1175           
1176          FOUND_LEADING_MONOMIALS[i] = FOUND_LEADING_MONOMIALS[i] + FLM;
1177           
1178          for( j = 1; j <= D; j = j + i ) // For every degree (j*i) of LNEW, do:
1179            {           
1180              for( l = j; (l+i) <= D; l++ )
1181                {
1182                  FOUND_LEADING_MONOMIALS[l+i] =
1183                    FOUND_LEADING_MONOMIALS[l+i] + FOUND_LEADING_MONOMIALS[l] * FLM;
1184                }
1185            }
1186           
1187          // Return to NCRING
1188          setring NCRING;
1189               
1190          FLM = imap(COMMRING, FLM);
1191          attrib(FLM, "isSB", 1);// just to avoid "no standard basis" warning.
1192
1193          // we simply kill in T monomials occurring in FOUND_LEADING_MONOMIALS[i]
1194          T = reduce( T, FLM, 1 );
1195   
1196          PBW = PBW + T;
1197        } else
1198          {
1199            PBW = P;
1200          }
1201       
1202       
1203      if( m and (i == D) ) // Was the previous estimation too small???
1204        {           
1205          // We must update FOUND_LEADING_MONOMIALS in their Commutative world:
1206          setring COMMRING;
1207
1208          // Init new grades:
1209          for( j = D + 1; j <= (D + @Delta); j++ )
1210            {
1211              FOUND_LEADING_MONOMIALS[j] = ideal();
1212            }
1213                       
1214          FLM = 0;
1215           
1216          // All previously computed elements in their order!
1217          NEW = imap( NCRING, result );
1218           
1219          for( j = 1; j <= size(NEW); j++ )
1220            {
1221              FLM[j] = leadmonom( NEW[j] ); // we are interested in leading monomials only!
1222            }
1223           
1224          while( size(FLM) > 0 )
1225            {
1226              // minimal degree:
1227              d = mindegInt(FLM);  /// ### ///
1228               
1229              // take all of minimal degree:               
1230              T = jet( FLM, d );
1231               
1232              // there are size(T) elements of smallest degree (deg(FLM[1])) in FLM!
1233               
1234              // Add them in the same way:
1235              for( j = 1; j <= (D + @Delta); j = j + d ) // For every degree (j*d) of T, do:
1236                {           
1237                  for( l = j; (l + d) <= (D + @Delta); l++ )
1238                    {
1239                      if( (l + d) > D ) // Only new should be updated!
1240                        {
1241                          FOUND_LEADING_MONOMIALS[l+d] =
1242                            FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T;
1243                        }
1244                    }
1245                }
1246               
1247              // Kill them from FLM:
1248              if( size(T) < size(FLM) )
1249                {
1250                  FLM = FLM[ (size(T)+1) .. size(FLM) ];
1251                } else
1252                  {
1253                    FLM = 0; // break;
1254                  }
1255             
1256            }   
1257           
1258          // Go back...
1259          setring NCRING;
1260
1261/*
1262    if(toprint())
1263    {
1264      typeof(@Delta); @Delta;
1265      typeof(D); D;
1266    };
1267*/   
1268          // And set new Bound
1269          D = D + @Delta;
1270        }
1271               
1272      i++;
1273    }
1274   
1275  result = makeNice(result);
1276
1277  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "centralizerRed", result ); }; /*4DEBUG*/
1278   
1279  return( result );
1280}
1281example
1282{
1283  "EXAMPLE:"; echo = 2;
1284  ring A = 0,(x,y,z),dp;
1285  matrix D[3][3]=0;
1286  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
1287  ncalgebra(1,D); // this algebra is U(sl_2)
1288  ideal F = x, y;
1289  // find subalgebra generators degree <= 4 of an algebra of
1290  // all elements commuting with x and y:
1291  ideal C = centralizerRed(F, 4);
1292  C;
1293  inCentralizer(C, F);
1294}
1295
1296
1297/******************************************************/
1298proc centerRed( int D, list # )
1299"USAGE:      centerRed( D[, N] ); int D[, int N]
1300RETURN:     ideal, generated by computed generators
1301PURPOSE:    computes a subalgebra generators of the center up to degree D.
1302NOTE:       In general, one cannot compute the whole center.
1303@* Hence, one has to specify a termination condition via arguments D and/or N.
1304@* If D is positive, only central elements up to degree D will be found.
1305@* If D is negative, the termination is determined by N only.
1306@* If N is given, the computation stops if at least N elements has been found.
1307@* Warning: if N is given and bigger than the actual number of generators,
1308@* the procedure may not terminate.
1309@* Current ordering must be a degree compatible well-ordering.
1310SEE ALSO:   centralizerRed; centerVS; center; inCenter
1311EXAMPLE:    example centerRed; shows an example
1312"
1313{
1314  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "centerRed", D, # ); }; /*4DEBUG*/
1315
1316  if( nameof( basering ) == "basering" )
1317    {
1318      //        ERROR( "No current ring!" );
1319    }
1320   
1321  ideal result = centralizerRed( variablesSorted(), D, # );
1322     
1323  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "centerRed", result ); }; /*4DEBUG*/
1324
1325  return( result );
1326}
1327example
1328{
1329  "EXAMPLE:"; echo = 2;
1330  ring A = 0,(x,y,z),dp;
1331  matrix D[3][3]=0;
1332  D[1,2]=z;
1333  ncalgebra(1,D); // it is a Heisenberg algebra
1334  // find vector space basis of center of degree <= 3
1335  ideal VSZ = centerVS(3);
1336  // There should be 3 degrees of z.
1337  VSZ;
1338  inCenter(VSZ);
1339  // find "minimal" central elements of degree <= 3
1340  ideal SAZ = centerRed(3);
1341  // Only 'z' must be computed
1342  SAZ;
1343  inCenter(SAZ);
1344}
1345
1346
1347/******************************************************/
1348/******************************************************/
1349// ::SubAlgebraReduction:: A kind of subalgebra reduction...
1350/******************************************************/
1351/******************************************************/
1352
1353/******************************************************/
1354static proc INTERRED( ideal S )
1355  "USAGE:      INTERRED( S ); ideal S
1356RETURN:      ideal, interreduced S
1357PURPOSE:     interreduction without monomial multiplication,
1358    just make every leading monomial occur in a single polynomial
1359"
1360{
1361  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "INTERRED", S ); }; /*4DEBUG*/
1362
1363  ideal result = S;
1364   
1365  int flag = 1;
1366   
1367  int i, j, N;
1368   
1369  poly p, lm;
1370   
1371  while( flag == 1 )
1372    {   
1373      flag = 0;
1374       
1375      result = sort( simplify( result, 1 + 2 + 8) )[1];       
1376      // sorting w.r.t. actual monomial ordering
1377      // generators with SMALLER(!) leading term come FIRST
1378       
1379      N = size(result);
1380       
1381      // kill leading monomials:
1382       
1383      i = 1;       
1384      while( i < N )
1385        {
1386          p = result[i];
1387          lm = leadmonom(p);
1388           
1389          j = i + 1;
1390          while( leadmonom(result[j]) == lm )
1391            {
1392              result[j] = result[j] - p; // leadcoefs are 1 because of simplify.
1393              flag = 1; // we have changed something => we do still need to care about it...
1394              j++;
1395               
1396              if( j > N )
1397                {
1398                  break;
1399                }
1400            }
1401                       
1402          i = j;           
1403        }
1404    }
1405   
1406  // We are done! No common leading monomials!
1407  // The result is sorted
1408
1409  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "INTERRED", result ); }; /*4DEBUG*/
1410
1411  return( result );
1412}
1413
1414
1415/******************************************************/
1416static proc SANF( poly p, list FOUND_LEADING_MONOMIALS )
1417  "
1418    reduce p wrt found multiples without ANY polynomial multiplications!
1419"
1420{
1421  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "SANF", p, FOUND_LEADING_MONOMIALS); }; /*4DEBUG*/
1422   
1423  poly q = p;
1424  poly head = 0;
1425   
1426  int d; int N = size(FOUND_LEADING_MONOMIALS);
1427   
1428  while( size(q) > 0 )
1429    {
1430      d = maxdegInt(p); /// ### ///
1431       
1432      if( (0 < d) and (d <= N) )
1433        {
1434          if( size(FOUND_LEADING_MONOMIALS[d]) > 0 )
1435            {
1436              attrib( FOUND_LEADING_MONOMIALS[d], "isSB", 1);
1437              q = reduce( p, FOUND_LEADING_MONOMIALS[d] );
1438            }
1439           
1440          DBPrint(1, string(p) + " --> " + string(q) );
1441        }       
1442               
1443      if( q == p )
1444        {
1445          p = lead(q);
1446           
1447          if( d > 0 )
1448            {
1449              // No scalars!
1450              head = head + p;
1451            }
1452           
1453          q = q - p;
1454        }
1455       
1456      p = q;
1457    }
1458   
1459   
1460
1461  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "SANF", head ); }; /*4DEBUG*/
1462
1463  return( head );
1464}
1465
1466
1467/******************************************************/
1468static proc maxdegInt( ideal I )
1469{   
1470  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "maxdegInt", I ); }; /*4DEBUG*/
1471
1472  intmat D = maxdeg(I);
1473   
1474  int max = D[1, 1]; int m;
1475   
1476  for( int c = 2; c <= ncols(D); c++ )
1477    {
1478      m = D[1, c];
1479       
1480      if( m > max )
1481        {
1482          max = m;
1483        }
1484    }
1485   
1486  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "maxdegInt", max ); }; /*4DEBUG*/
1487
1488  return( max );   
1489}
1490
1491
1492/******************************************************/
1493static proc mindegInt( ideal I )
1494{   
1495  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "mindegInt", I ); }; /*4DEBUG*/
1496
1497  intmat D = mindeg(I);
1498   
1499  int min = D[1, 1]; int m;
1500   
1501  for( int c = 2; c <= ncols(D); c++ )
1502    {
1503      m = D[1, c];
1504       
1505      if( m < min )
1506        {
1507          min = m;
1508        }
1509    }
1510   
1511  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "mindegInt", min ); }; /*4DEBUG*/
1512
1513  return( min );   
1514}
1515
1516/******************************************************/
1517proc sa_reduce( ideal V ) // 'subalgebra basis' computation
1518"USAGE:     sa_reduce(V); ideal V
1519RETURN:     ideal, generated by found elements
1520PURPOSE:    compute a s.a. basis of an algebra generated by V
1521NOTE:       May produce wrong result in quotient algebras.
1522SEE ALSO:   sa_poly_reduce
1523EXAMPLE:    example sa_reduce; shows an example
1524"
1525{
1526  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "sa_reduce", V ); }; /*4DEBUG*/
1527   
1528  ideal result = ideal();
1529   
1530  ideal FLM = INTERRED( V ); // The output is sorted "[1]<[2]<[3]<..."
1531   
1532  // We are bounded by maximal degree!!!
1533  int D = maxdegInt( FLM );
1534   
1535  // Init
1536  list FOUND_LEADING_MONOMIALS = list();
1537   
1538  int i;
1539   
1540  for( i = 1; i <= D; i++ )
1541    {
1542      FOUND_LEADING_MONOMIALS[i] = ideal();
1543    }   
1544   
1545  int d, j, l;
1546   
1547  poly p, q; ideal T;
1548   
1549   
1550  int c = 1;  // polynomials in FLM commute pairwise
1551   
1552  for( j = 1; (j < size(FLM)) and (c == 1); j++ )
1553    {
1554      p = FLM[j];
1555       
1556      for( l = j+1; (l <= size(FLM)) and (c == 1); l++ )
1557        {
1558          q = FLM[l];
1559       
1560          if( NF(p*q - q*p, twostd(0)) != 0  )
1561            {
1562              c = 0; // There exists non-commuting pair
1563            }           
1564        }
1565    }
1566
1567  while( size(FLM) > 0 )
1568    {
1569      // Take the 1st element of FLM...
1570      p = FLM[1]; // SANF( FLM[1], FOUND_LEADING_MONOMIALS );
1571       
1572      FLM[1] = 0; // ...and kill it from FLM
1573       
1574      d = maxdegInt( p );
1575      T = ideal(p);
1576       
1577      FOUND_LEADING_MONOMIALS[d] = FOUND_LEADING_MONOMIALS[d] + T;
1578       
1579      for( j = 1; j <= D; j = j + d ) // For every degree (j*d) of T, do:
1580        {           
1581          for( l = j; (l + d) <= D; l++ )
1582            {
1583              FOUND_LEADING_MONOMIALS[l+d] =
1584                FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T;
1585                   
1586              if( c != 1 )
1587                {
1588                  FOUND_LEADING_MONOMIALS[l+d] =
1589                    FOUND_LEADING_MONOMIALS[l+d] + T * FOUND_LEADING_MONOMIALS[l];
1590                }   
1591            }
1592        }
1593       
1594      if( size(FLM) > 0 )
1595        {
1596          for( i = 2; i <= ncols(FLM); i++ )
1597            {
1598              FLM[i] = SANF( FLM[i], FOUND_LEADING_MONOMIALS );
1599            }
1600          FLM = INTERRED( FLM );           
1601        }
1602       
1603      DBPrint(1, "Found: " + string(T) );
1604       
1605      result = result + T;
1606       
1607    }
1608   
1609  result = makeNice(result);
1610   
1611  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "sa_reduce", result ); }; /*4DEBUG*/
1612   
1613  return( result );
1614}
1615example
1616{ "EXAMPLE:"; echo = 2;
1617 ring A = 0,(x,y,z),dp;
1618 matrix D[3][3]=0;
1619 D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y;
1620 ncalgebra(1,D); // this algebra is U(sl_2)
1621 poly f = 4*x*y+z^2-2*z; // a central polynomial
1622 ideal I = f, f*f, f*f*f - 10*f*f, f+3*z^3; I;
1623 sa_reduce(I); // should be just f and z^3
1624}
1625
1626
1627
1628/******************************************************/
1629proc sa_poly_reduce( poly p, ideal V ) // subalgebra reduction of a polynomial
1630"USAGE:      sa_poly_reduce(p, V); poly p, ideal V
1631RETURN:     polynomial, a reduction of p wrt V
1632PURPOSE:    computes a reduction of polynomial p wrt V
1633NOTE:       May produce wrong result in quotient algebras.
1634SEE ALSO:   sa_reduce
1635EXAMPLE:    example sa_poly_reduce; shows an example
1636"
1637{
1638  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "sa_poly_reduce", p, V ); }; /*4DEBUG*/
1639  // As previous...
1640   
1641  ideal FLM = INTERRED( V ); // The output is sorted "[1]<[2]<[3]<..."
1642   
1643  // We are bounded by maximal degree!!!
1644  int D = maxdegInt( FLM + ideal(p)  );
1645
1646  // Init
1647  list FOUND_LEADING_MONOMIALS = list();
1648   
1649  int i;
1650   
1651  for( i = 1; i <= D; i++ )
1652    {
1653      FOUND_LEADING_MONOMIALS[i] = ideal();
1654    }   
1655   
1656  int d, j, l;
1657   
1658  poly f, q; ideal T;
1659
1660   
1661  int c = 1;  // polynomials in FLM commute pairwise
1662   
1663  for( j = 1; (j < size(FLM)) and (c == 1); j++ )
1664    {
1665      f = FLM[j];
1666       
1667      for( l = j+1; (l <= size(FLM)) and (c == 1); l++ )
1668        {
1669          q = FLM[l];
1670       
1671          if( NF(f*q - q*f, twostd(0)) != 0 )
1672            {
1673              c = 0;
1674            }           
1675        }
1676    }
1677
1678       
1679  while( size(FLM) > 0 )
1680    {
1681      // Take the 1st element of FLM...
1682      q = SANF( FLM[1], FOUND_LEADING_MONOMIALS );
1683       
1684      FLM[1] = 0; // ...and kill it from FLM
1685       
1686      d = maxdegInt(q);
1687      T = ideal(q);
1688       
1689      FOUND_LEADING_MONOMIALS[d] = FOUND_LEADING_MONOMIALS[d] + T;
1690       
1691      for( j = 1; j <= D; j = j + d ) // For every degree (j*d) of T, do:
1692        {           
1693          for( l = j; (l + d) <= D; l++ )
1694            {
1695              FOUND_LEADING_MONOMIALS[l+d] =
1696                FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T;
1697                   
1698              if( c != 1 )
1699                {
1700                  FOUND_LEADING_MONOMIALS[l+d] =
1701                    FOUND_LEADING_MONOMIALS[l+d] + T * FOUND_LEADING_MONOMIALS[l];
1702                }   
1703            }
1704        }
1705       
1706      if( size(FLM) > 0 )
1707        {
1708          for( i = 2; i <= ncols(FLM); i++ )
1709            {
1710              FLM[i] = SANF( FLM[i], FOUND_LEADING_MONOMIALS );
1711            }
1712          FLM = INTERRED( FLM );           
1713        }
1714    }
1715   
1716  poly result = SANF(p, FOUND_LEADING_MONOMIALS);
1717   
1718  result = makeNice( result );
1719
1720   
1721  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "sa_poly_reduce", result ); }; /*4DEBUG*/
1722
1723  return( result );
1724}
1725example
1726{ "EXAMPLE:"; echo = 2;
1727 ring A = 0,(x,y,z),dp;
1728 matrix D[3][3]=0;
1729 D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y;
1730 ncalgebra(1,D); // this algebra is U(sl_2)
1731 poly f = 4*x*y+z^2-2*z; // a central polynomial
1732 sa_poly_reduce(f + 3*f*f + x, ideal(f) ); // should be just 'x'
1733}
1734
1735
1736
1737
1738
1739
1740
1741/******************************************************/
1742// ::inStuff:: inCentralizer, inCenter, isCartan helpers
1743/******************************************************/
1744
1745
1746/******************************************************/
1747static proc inCentralizer_poly( poly p, ideal S )
1748  "
1749    if p in centralizer(S) => return 1, otherwise return 0
1750"
1751{
1752  poly f;
1753   
1754  for( int k = 1; k <= size(S); k++ )
1755    {
1756      f = S[k];
1757
1758      if( NF( f * p - p * f, twostd(0) ) != 0 )
1759        {
1760          DBPrint( 1, "POLY: " + string (p) +
1761                   " is NOT in the centralizer of poly {" + string(f) + "}" );
1762          return (0);
1763        }
1764    }
1765
1766  return( 1 );
1767}
1768
1769/******************************************************/
1770static proc inCentralizer_list( def l, ideal S )
1771{   
1772  for( int @i = 1; @i <= size(l); @i++ )
1773    {
1774      if( (typeof(l[@i])=="poly") or (typeof(l[@i]) == "int") or (typeof(l[@i]) == "number") )
1775        {
1776          if(! inCentralizer_poly(l[@i], S) )
1777            {
1778              return(0);
1779            }
1780
1781        } else
1782          {
1783            if( (typeof(l[@i])=="list") or (typeof(l[@i])=="ideal") )
1784              {
1785                if(! inCentralizer_list(l[@i], S) )
1786                  {
1787                    return(0);
1788                  }
1789              }
1790          }
1791    }
1792  return(1);
1793}
1794
1795
1796/******************************************************************************/
1797proc inCentralizer( def a, ideal S ) // Checks the commutativity of polynomials of a with the polynomials in S
1798"USAGE:   inCentralizer(a, S); a poly/list/ideal, S poly/ideal
1799RETURN:  integer, 1 if a in the centralizer(S), 0 otherwise
1800PURPOSE: check whether a is centralizing with respect to elements of S
1801EXAMPLE: example inCentralizer; shows examples
1802"
1803{
1804  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "inCentralizer", a, S ); }; /*4DEBUG*/
1805
1806  if( nameof( basering ) == "basering" )
1807    {
1808      //        ERROR( "No current ring!" );
1809    }
1810   
1811
1812  int res;
1813   
1814  if( (typeof(a) == "poly") or (typeof(a) == "int") or (typeof(a) == "number") )
1815    {
1816      res = inCentralizer_poly(a, S);
1817    } else
1818      {
1819        if( (typeof(a)=="list") or (typeof(a)=="ideal") )
1820          {
1821            res = inCentralizer_list(a, S);
1822          } else
1823            {
1824              res = -1;
1825            }
1826      }
1827   
1828  if( res == -1 )
1829    {
1830      ERROR( "Wrong argument!" );
1831    }
1832
1833  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "inCentralizer", res ); }; /*4DEBUG*/
1834
1835  return (res);
1836}
1837example
1838{
1839  "EXAMPLE:";echo=2;
1840  ring r=0,(x,y,z),dp;
1841  matrix D[3][3]=0;
1842  D[1,2]=-z;
1843  ncalgebra(1,D); // the Heisenberg algebra
1844  poly f = x^2;
1845  poly a = z; // 'z' is central => it lies in any centralizer!
1846  poly b = y^2;
1847  inCentralizer(a, f);
1848  inCentralizer(b, f);
1849  list  l = list(1, a);
1850  inCentralizer(l, f);
1851  ideal I = a, b;
1852  inCentralizer(I, f);
1853  printlevel = 2;
1854  inCentralizer(a, f); // yes
1855  inCentralizer(b, f); // no
1856}
1857
1858/******************************************************/
1859proc inCenter( def a ) // Checks the centrality of a
1860  "USAGE:   inCenter(a); a poly/list/ideal
1861RETURN:  integer, 1 if a in the center, 0 otherwise
1862PURPOSE: check whether a given element is central
1863EXAMPLE: example inCenter; shows examples
1864"
1865{
1866  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "inCenter", a ); }; /*4DEBUG*/
1867
1868  if( nameof( basering ) == "basering" )
1869    {
1870      //        ERROR( "No current ring!" );
1871    }
1872       
1873  int result = inCentralizer( a, variablesStandard() );
1874
1875  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "inCenter", result ); }; /*4DEBUG*/
1876
1877  return( result );
1878}
1879example
1880{
1881  "EXAMPLE:";echo=2;
1882  ring r=0,(x,y,z),dp;
1883  matrix D[3][3]=0;
1884  D[1,2]=-z;
1885  D[1,3]=2*x;
1886  D[2,3]=-2*y;
1887  ncalgebra(1,D); // this is U(sl_2)
1888  poly p=4*x*y+z^2-2*z;
1889  inCenter(p);
1890  poly f=4*x*y;
1891  inCenter(f);
1892  list l= list( 1, p, p^2, p^3);
1893  inCenter(l);
1894  ideal I= p, f;
1895  inCenter(I);
1896}
1897
1898
1899/******************************************************/
1900proc isCartan( poly f ) // Checks whether f is a Cartan element.
1901"USAGE:       isCartan(f); poly f
1902PURPOSE:     check whether f is a Cartan element.
1903RETURN:      integer, 1 if f is a Cartan element and 0 otherwise.
1904NOTE:        f is a Cartan element
1905@* iff for all g in A there exists C in K such that [f, g] = C * g
1906@* iff for all variables v_i there exist C in K such that [f, v_i] = C * v_i.
1907"
1908{
1909  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ BCall( "isCartan", f ); }; /*4DEBUG*/
1910
1911  if( nameof( basering ) == "basering" )
1912    {
1913      //        ERROR( "No current ring!" );
1914    }
1915   
1916
1917  ideal V = variablesStandard();
1918
1919  int r = 1; poly v, g;
1920
1921  for( int i = size(V); i > 0; i-- )
1922    {
1923      v = leadmonom(V[i]); // V[i] must be just a variable, but...
1924
1925      g = NF( f*v - v*f, twostd(0) ); // [f, V[i]]
1926
1927      if( size(g) > 0 )
1928        {
1929          if( size(g) > 1 ) // it is not just \alpha * v_i.
1930            {
1931              r = 0;
1932              break;
1933            }
1934
1935          if( leadmonom(g) != v ) // g = \alpha * v_j, j != i.
1936            {
1937              r = 0;
1938              break;
1939            }
1940
1941        } // else \alpha = 0
1942    }
1943   
1944  /*4DEBUG*/    if( defined( @@@DEBUG ) ){ ECall( "isCartan", r ); }; /*4DEBUG*/
1945  return( r );
1946}
1947example
1948{
1949  "EXAMPLE:";echo=2;
1950  ring r=0,(x,y,z),dp;
1951  matrix D[3][3]=0;
1952  D[1,2]=-z;
1953  D[1,3]=2*x;
1954  D[2,3]=-2*y;
1955  ncalgebra(1,D); // this is U(sl_2) with cartan - z
1956  isCartan(z); // yes!
1957  poly p=4*x*y+z^2-2*z;
1958  isCartan(p); // central elements are Cartan elements!
1959  poly f=4*x*y;
1960  isCartan(f); // no way!
1961  isCartan( 10 + p + z ); // scalar + central + cartan
1962}
1963
1964
1965
1966
1967/******************************************************/
1968/******************************************************/
1969// ::MainAliases:: The main non-static functions, visible to user are here. They are wrappers around basic functions.
1970/******************************************************/
1971/******************************************************/
1972
1973
1974
1975
1976/******************************************************/
1977proc center( int D, list # ) // Computes the generators of the center of a basering
1978"USAGE:      center(D[, N]); int D, int N
1979RETURN:     ideal, generated by elements of degree at most D
1980PURPOSE:    computes a subalgebra generators of the center up to degree D.
1981NOTE:       In general, one cannot compute the whole center.
1982@* Hence, one has to specify a termination condition via arguments D and/or N.
1983@* If D is positive, only central elements up to degree D will be found.
1984@* If D is negative, the termination is determined by N only.
1985@* If N is given, the computation stops if at least N elements has been found.
1986@* Warning: if N is given and bigger than the actual number of generators,
1987@* the procedure may not terminate.
1988@* Current ordering must be a degree compatible well-ordering.
1989SEE ALSO:   centralizer; inCenter
1990EXAMPLE:    example center; shows an example
1991"
1992{
1993  if( nameof( basering ) == "basering" )
1994    {
1995      //        ERROR( "No current ring!" ); 
1996    }
1997   
1998  if( DefaultInt( # ) > 0 )
1999    {
2000      return( centerRed( D, # ) );
2001    }
2002   
2003  if( D >= 0 )
2004    {
2005      return( sa_reduce( centerVS(D) ) ); // Experimental! May be wrong!!!
2006    }
2007   
2008  ERROR( "Wrong arguments!" );
2009}
2010example
2011{
2012  "EXAMPLE:"; echo = 2;
2013  ring A = 0,(x,y,z,t),dp;
2014  matrix D[4][4]=0;
2015  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
2016  ncalgebra(1,D); // this algebra is U(sl_2) tensored with K[t]
2017  ideal Z = center(3); // find all central elements of degree <= 3
2018  Z;
2019  inCenter(Z);
2020  ideal ZZ = center(-1, 1); // find one central element of the lowest degree
2021  ZZ;
2022  inCenter(ZZ);
2023}
2024
2025/******************************************************/
2026proc centralizer( ideal S, int D, list # ) // Computes the generators of the centralizer of S in a basering
2027"USAGE:      centralizer(F, D[, N]); poly/ideal F, int D[, int N]
2028RETURN:     ideal, generated by computed generators
2029PURPOSE:    computes a subalgebra generators of centralizer(F) up to degree D.
2030NOTE:       In general, one cannot compute the whole centralizer(F).
2031@* Hence, one has to specify a termination condition via arguments D and/or N.
2032@* If D is positive, only centralizing elements up to degree D will be found.
2033@* If D is negative, the termination is determined by N only.
2034@* If N is given, the computation stops if at least N elements has been found.
2035@* Warning: if N is given and bigger than the actual number of generators,
2036@* the procedure may not terminate.
2037@* Current ordering must be a degree compatible well-ordering.
2038SEE ALSO:   center; inCentralizer
2039EXAMPLE:    example centralizer; shows an example
2040"
2041{
2042  if( nameof( basering ) == "basering" )
2043    {
2044      //        ERROR( "No current ring!" ); 
2045    }
2046   
2047  if( DefaultInt( # ) > 0 )
2048    {
2049      return( centralizerRed( S, D, # ) );
2050    }
2051   
2052  if( D >= 0 )
2053    {
2054      return( sa_reduce( centralizerVS(S, D) ) ); // Experimental! May be wrong!!!
2055    }
2056   
2057  ERROR( "Wrong arguments!" );
2058}
2059example
2060{
2061  "EXAMPLE:"; echo = 2;
2062  ring A = 0,(x,y,z),dp;
2063  matrix D[3][3]=0;
2064  D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y;
2065  ncalgebra(1,D); // this algebra is U(sl_2)
2066  poly f = 4*x*y+z^2-2*z; // a central polynomial
2067  f;
2068  ideal c = centralizer(f, 2); // find all elements of the centralizer of f
2069  // of degree <= 2
2070  c;  // since f is central, the answer consists of generators of A
2071  inCentralizer(c, f);
2072  ideal cc = centralizer(f,-1,2); // find at least two elements of the centralizer of f
2073  cc;
2074  inCentralizer(cc, f);
2075  poly g = z^2-2*z; // some non-central polynomial
2076  c = centralizer(g, 2); // find all elements of the centralizer of g
2077  // of degree <= 2
2078  c;
2079  inCentralizer(c, g);
2080  centralizer(g,-1,1); // find the element of the lowest degree in the centralizer
2081  cc = centralizer(g,-1,2); // find at least two elements of the centralizer of g
2082  cc;
2083  inCentralizer(cc, g);
2084}
2085
2086
2087/*******************************************************
2088 // normally one should use this library together with ncalg.lib in the following way:
2089
2090LIB "ncalg.lib";
2091def Usl3 = makeUsl(3); // U(sl_3)
2092setring Usl3;
2093
2094// show current ring:
2095basering;
2096
2097LIB "center.lib";
2098
2099// easy example(few seconds), must compute two polynomials of degrees 2 and 3.
2100center(3);
2101
2102kill Usl3;
2103
2104def Ug2 = makeUg2(); // U(g_2)
2105setring Ug2;
2106
2107// show current ring:
2108basering;
2109
2110// easy example(few seconds), must compute one polynomial of degree 2.
2111center(2);
2112
2113// hard example (~hours), must compute two polynomials of degrees 2 and 6.
2114center(6);
2115
2116quit;
2117*******************************************************/
Note: See TracBrowser for help on using the repository browser.