source: git/Singular/LIB/central.lib @ 66d68c

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