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

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