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

fieker-DuValspielwiese
Last change on this file since bea07f was 1fdee9, checked in by Viktor Levandovskyy <levandov@…>, 19 years ago
*levandov: suggestions by GMG implemented, additions, some procs moved to general Singular libs, rearranged and corrected git-svn-id: file:///usr/local/Singular/svn/trunk@8233 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 58.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: center.lib,v 1.16 2005-05-18 18:09:10 levandov Exp $";
3category="Noncommutative";
4info="
5LIBRARY:  center.lib      computation of central elements of G-algebras and their factor-algebras.
6AUTHOR:  Oleksandr Motsak,        motsak@mathematik.uni-kl.de.
7OVERVIEW:
8 This is a library for computing the central elements and centralizers of elements in various noncommutative algebras.
9 Implementation is based on algorithms, written in the frame of the diploma thesis by O. Motsak (advisor: Prof. S.A. Ovsienko, support: V. Levandovskyy), at Kyiv Taras Shevchenko University (Ukraine) with the title 'An algorithm for the computation of the center of noncommutative polynomial algebra'.
10
11SUPPORT: Forschungsschwerpunkt 'Mathematik und Praxis', University of Kaiserslautern
12
13PROCEDURES:
14center(MaxDeg[,N]);             computes the generators of the center of a basering,
15centralizer(f, MaxDeg[,N]);     computes the generators of the centralizer of f in a basering,
16inCenter(l);                    checks the centrality of elements of list/ideal/poly l
17inCentralizer(l, f);            checks the commutativity wrt polynomial f of polynomials of list/ideal/poly l
18
19KEYWORDS:  inCenter; inCentralizer; center; centralizer
20";
21
22/******************************************************/
23// stuff
24
25/******************************************************/
26static proc myValue ( def s, list # )
27"
28        return s or (typeof(s))(#)
29"
30{
31  def @p = s;
32  if ( size(#) > 0 )
33    {
34      if ( typeof( #[1] ) == typeof(s) )
35        {
36          @p = #[1];
37        };
38    };
39  return (@p);
40};
41
42/******************************************************/
43static proc myInt ( list # )
44  "
45        return 0 or int(#)
46"
47{
48  int @p = 0;
49  return (myValue ( @p, # ));
50};
51
52/******************************************************/
53static proc myPoly ( list # )
54  "
55        return 0 or poly(#)
56"
57{
58  poly @p = 0;
59  return (myValue( @p, # ));
60};
61
62/******************************************************/
63static proc myRing ( list # )
64  "
65        return basring or ring(#)
66"
67{
68  def @p = basering;
69  return (myValue ( @p, # ));
70};
71
72/******************************************************/
73static proc myString ( list # )
74  "
75        return basring or ring(#)
76"
77{
78  string @p = "";
79  return (myValue ( @p, # ));
80};
81
82/******************************************************/
83static proc myIdeal ( list # )
84  "
85        return 0 or ideal(#)
86"
87{
88  ideal @p;
89  return (myValue ( @p, # ));
90};
91
92/******************************************************/
93// for debug
94
95/******************************************************/
96static proc toprint()
97{
98  return (0);
99};
100
101/******************************************************/
102static proc Print( list # )
103{
104  if ( toprint() )
105    {
106      print (#);
107    };
108};
109
110/******************************************************/
111static proc BCall(string Name, list #)
112{
113  if( toprint() )
114    {
115      "CALL: ", Name, "( ", string(#), " )";
116    };
117};
118
119/******************************************************/
120static proc ECall(string Name, list #)
121{
122  if( toprint() )
123    {
124      "RET : ", Name, "(...)={ ", string(#), " }";
125    };
126};
127
128
129/******************************************************/
130// "my" degres functions and lie procedures...
131
132/******************************************************/
133static proc maxDeg( def z )
134  "
135        returns: int : max of givendeg( z_i ), among all z_i \in z
136                returns -1 if z is empty or contain only 0 polynomial
137"
138{
139  int max = -1;
140  int d;
141
142  for(int i=size(z); i>0; i-- )
143    {
144      d = deg(z[i]);
145      if( d > max )
146        {
147          max = d;
148        };
149    };
150
151  return(max);
152};
153
154/******************************************************/
155// some business for my_var
156
157/******************************************************/
158static proc myCoeff ( poly f, poly m )
159  "
160        input: poly f,
161        return: coeff at m
162"
163{
164  m = leadmonom(m);
165
166  int i = size(f);
167
168  while ( (i>0) and (leadmonom(f[i])<m) )
169    {
170      i--;
171    };
172  if( i == 0 )
173    {
174      return ( 0 );
175    };
176
177  if(leadmonom(f[i]) == m)
178    {
179      return ( leadcoef(f[i]) );
180    };
181
182  return ( 0 );
183};
184
185/******************************************************/
186static proc my_vars ()
187{
188  int  N = nvars( basering );
189  list V = list();
190
191  for ( int k = 1; k <= N; k++ )
192    {
193      V[k] = var(k);
194    };
195
196  return (V);
197};
198
199/******************************************************/
200static proc my_commutators ()
201{
202  list V = my_vars();
203  int  N = size( V );
204
205  matrix M[N][N] = 0;
206
207  poly v, d; int i;
208
209  for ( int k = 2; k <= N; k++ )
210    {
211      v = V[k];
212      for ( i = 1; i < k; i++ )
213        {
214          d = V[i];
215          M[k,i] =  v*d - d*v;        // [var(k),var(i)]
216          M[i,k] = -M[k,i];        // [var(i),var(k)] ==  -[var(k),var(i)]
217        };
218    };
219
220  return (M);
221};
222
223/******************************************************/
224static proc my_associated ()
225"
226    return list of records:
227     [1] - poly: variable,
228     [2] - bool: isCartan
229     [3] - matrix: associated matrix (basering should be compatible)
230"
231{
232  int i, j; poly a; poly d;
233
234  int N          = nvars( basering );
235  list V         = my_vars();
236  matrix M = my_commutators();
237
238  matrix A[N][N];
239
240  int cartan;
241
242  list RESULT = list();
243  int  r_begin = 1;
244  int  r_end   = N;
245
246
247  for ( int k = 1; k <= N; k++ )
248    {
249      A = 0;
250      cartan = 1;
251      for ( i = 1; i <= N; i++ )
252        {
253          d = M[k,i];
254          for ( j = 1; j <= N; j++ )
255            {
256              a = myCoeff( d, V[j] );
257              A[i,j] =  a;
258
259              if( (i!=j) and (a!=0) )
260                {
261                  cartan = 0;
262                };
263            };
264        };
265
266      if ( cartan )
267        {
268          RESULT[r_begin] = list( V[k], cartan, A );
269          r_begin++;
270        } else
271          {
272            RESULT[r_end] = list( V[k], cartan, A );
273            r_end--;
274          };
275
276    };
277
278  return (RESULT);
279
280};
281
282/******************************************************/
283static proc my_var_init()
284"
285  must be called once before using my_var!!!
286"
287{
288  if( defined( @@@SORTEDVARARRAY ) )
289    {
290      kill @@@SORTEDVARARRAY;
291    };
292
293  list @@@SORTEDVARARRAY;
294  list V = my_associated();
295
296  // cartans - first then others...
297
298  for ( int i = 1; i<= size(V); i++ )
299    {
300      @@@SORTEDVARARRAY[i] = V[i][1];
301    };
302
303  Print( "@@@SORTEDVARARRAY: " + string(@@@SORTEDVARARRAY) );
304
305  export(@@@SORTEDVARARRAY);
306};
307
308/******************************************************/
309static proc my_var(int @number )
310  "
311  'my' var (with my order of variables),
312  before use call my_var_init()
313"
314{
315  if( defined( @@@SORTEDVARARRAY ) )
316    {
317      return( @@@SORTEDVARARRAY[@number] );
318    };
319
320  Print( "Error: my_var_init() was not called before this..." );
321  return( var(@number) );
322
323};
324
325/******************************************************/
326static proc my_var_done()
327  "
328  this procedure should be called after finishing using my_var in order to clean up.
329"
330{
331  if( defined( @@@SORTEDVARARRAY ) )
332    {
333      kill @@@SORTEDVARARRAY;
334    };
335};
336
337
338/******************************************************/
339// QNF stuff
340
341/******************************************************/
342static proc myBitParam( int param, int n )
343  "
344    return: string: param in bin within no less then n digits (adding zeroes)
345"
346{
347  string s = "";
348
349  while ( param != 0 )
350    {
351      s = string ( param % 2 ) + s;
352      param = param / 2;
353      n --;
354    };
355  while ( n > 0 )
356    {
357      s = "0" + s;
358      n --;
359    };
360  return ( s );
361};
362
363/******************************************************/
364static proc QNF_init(list #)
365{
366  if( defined(@@@MY_QIDEAL) )
367    {
368      kill @@@MY_QIDEAL;
369    };
370
371  if( typeof(basering) == "qring" )
372    {
373      ideal @@@MY_QIDEAL = twostd(myIdeal(#));
374      // setup redSB, redTail options
375      export(@@@MY_QIDEAL);
376
377      option(redSB);
378      option(redTail);
379
380    };
381};
382
383/******************************************************/
384static proc QNF_done()
385{
386  if( defined(@@@MY_QIDEAL) )
387    {
388      kill @@@MY_QIDEAL;
389    };
390};
391
392/******************************************************/
393static proc QNF_poly ( poly p, list # )
394{
395  if( defined(@@@MY_QIDEAL) )
396    {
397      /*
398        int param = 1 ; // by def: reduce both 1st and 2nd entries
399        param = myValue(param, #);
400        string bits = myBitParam( param, 8 );
401      */
402      BCall( "QNF_poly", p );
403
404      p = NF( p, @@@MY_QIDEAL );
405
406      ECall( "QNF_poly", p );
407    }; // QRing
408
409  return(p);
410};
411
412
413/******************************************************/
414static proc QNF_list ( list l, list # )
415  "
416    expects list of records with two polynomial entries
417    and in case of Qring allpies NF( * , std(0) ) to entries (depends on parameter)
418
419    1234 5678
420
421+1    8 => reduce every 1st entry
422+2    7 => reduce every 2nd entry
423
424        --- (for PBW in qrings) ---
425
426+4    6 => kill out pbw entries where pbw monom (1) was affected
427
428//?? wofuer?
429+8    5 => reduce every 3rd entry
430
431"
432{
433
434  if( defined(@@@MY_QIDEAL) )
435    {
436
437      int param = 1 + 2; // by def: reduce both 1st and 2nd entries
438      param = myValue(param, #);
439
440      string bits = myBitParam( param, 8 );
441
442      BCall( "QNF_list", "list, " + bits );
443
444      poly temp;
445
446      for ( int i = size(l); i>0 ; i -- )
447        {
448
449          if ( typeof( l[i] ) == "poly" )
450            {
451
452              if ( (bits[8] == "1") or (bits[6] == "1") )
453                {
454                  temp = NF( l[i], @@@MY_QIDEAL );
455
456                  if ( bits[6] == "1" )
457                    {// for PBW in qrings: kill out pbw entries where pbw monom was reduced
458
459                      if( temp != l[i] )
460                        {
461                          l = delete( l, i );
462                          i --;
463                          continue;
464                        };
465                    };
466
467                  if ( bits[8] == "1" )
468                    {
469                      l[i] = temp;
470                    };
471                };
472            };
473
474          if ( typeof( l[i] ) == "list" )
475            {
476              // 1st
477
478              if ( size(l[i])>0 )
479                {
480                  if ( (bits[8] == "1") or (bits[6] == "1") )
481                    {
482                      if( typeof( l[i][1] ) == "poly" )
483                        {
484
485                          temp = NF( l[i][1], @@@MY_QIDEAL );
486
487                          if ( bits[6] == "1" )
488                            {// for PBW in qrings: kill out pbw entries where pbw monom was reduced
489
490                              if( temp != l[i][1] )
491                                {
492                                  l = delete( l, i );
493                                  i --;
494                                  continue;
495                                };
496                            };
497
498                          if ( bits[8] == "1" )
499                            {
500                              l[i][1] = temp;
501                            };
502
503                        };
504                    };
505                };
506
507              // 2nd
508
509              if ( size(l[i])>1 )
510                {
511                  if ( bits[7] == "1" )
512                    {
513                      if( typeof( l[i][2] ) == "poly" )
514                        {
515                          temp = NF( l[i][2], @@@MY_QIDEAL );
516
517                          l[i][2] = temp;
518                        };
519                    };
520                };
521            };
522        };
523
524      ECall( "QNF_list", "list" );
525
526    }; // Qring
527
528  return ( l );
529};
530
531/******************************************************/
532// things for zCommon
533
534/******************************************************/
535static proc index( int i )
536  "
537  i need indexing of arrays from 0 => ARRAY[ index(i) ] - everywhere...
538"
539{
540  return (i + 1);
541};
542
543/******************************************************/
544static proc uni_poly( poly p )
545  "
546        returns polynomial with the same monomials but without coefficients.
547"
548{
549  poly @tt = poly(0);
550  for ( int @k = size(p); @k > 0; @k -- )
551    {
552      @tt = @tt + leadmonom(p[@k]);
553    };
554  return (@tt);
555};
556
557/******************************************************/
558static proc get_max ( poly @t, number @def )
559{
560  int @n = size( @t );
561
562  if ( @n == 0 )
563    {
564      return (@def);
565    };
566
567  number @max = leadcoef(@t[1]);
568  number @mm;
569
570  if ( @n > 1)
571    {
572      for ( int @i = 2; @i <= @n ;@i ++ )
573        {
574          @mm = leadcoef ( @t[@i] );
575          if ( @mm < 0 )
576            {
577              @mm = -@mm;
578            };
579
580          if( @mm > @max )
581            {
582              @max = @mm;
583            };
584        };
585    };
586
587  @max = @max + 1;
588  if ( @max == 0 )
589    {
590      @max = @max + 1;
591    };
592  return ( 1/@max );
593};
594
595
596/******************************************************/
597static proc get_uni_sum(list @given, int @num)
598{
599  int @l, @k;
600
601  poly @t, @tt;
602
603  @l = size (@given);
604
605  @t = poly(0);
606  for ( @k = @l; @k > 0; @k -- )
607    {
608      if (@num == 1)
609        {
610          @tt = @given[@k];
611        } else
612          {
613            @tt = @given[@k][2];
614          };
615
616      @t = @t + uni_poly( @tt );
617    };
618
619  return ( uni_poly(@t) );
620};
621
622
623
624/******************************************************/
625static proc LM ( intvec exp )
626  "
627        input : given exponent
628        return: monom with this exponent...
629"
630{
631  poly @f = 1; int @deg;
632  for( int @i = 1; @i <= size(exp); @i ++ )
633    {
634      @deg = exp[@i];
635      if ( @deg > 0 )
636        {
637          @f = @f * (var(@i)^(@deg));
638        };
639    };
640
641  return (@f);
642};
643
644/******************************************************/
645// reduced centers - computation of "minimal" set of generators
646
647LIB "general.lib"; // for sort
648
649/******************************************************/
650static proc zSort ( list @z )
651  "
652        Sort elements of a list of polynoms,
653        and normalize
654"
655{
656  int n = size(@z);
657  if ( n < 1 )
658    {// empty list
659      return( @z );
660    };
661
662  if ( n == 1 )
663    {
664      if ( @z[1] == 0 ) // if zero => empty list
665        {
666          return(list());
667        };
668
669      @z[1] =  @z[1] * ( 1/leadcoef(@z[1]) ) ;
670
671      return( @z );
672    };
673
674  int i = 1;
675
676  while ( i<=n )
677    {
678      if (size( @z[i] ) != 0)
679        {
680          break;
681        };
682      i++;
683    };
684
685  if ( i > n )
686    { // all zeroes
687      return(list());
688    };
689
690  ideal id = @z[i];
691  i++;
692
693  while ( i<= n )
694    {
695      if( @z[i] != 0 )
696        {
697          id=@z[i],id;
698        };
699      i++;
700    };
701
702  // can sort only ideal generators:-(
703  list srt = sort(id);
704
705  poly p;
706  // convert srt[1]:ideal to result:list.
707  list result = list();
708  for ( i = size(srt[1]); i>0; i-- )
709    {
710      p = srt[1][i];
711      if ( p == 0 )
712        {
713          i --;
714          continue;
715        };
716      p = p* (1/leadcoef(p));                // normalize
717      result = list(p) + result;
718    };
719
720  //        "OUT SORT::";
721  //        result;
722
723  return ( result );
724};
725
726
727
728/******************************************************/
729static proc zRefine ( list @z )
730  "
731        kill terms by leading monomials...
732        Note: based on myCoeff
733"
734{
735  BCall("zRefine", "list");
736
737  int @i, @j;
738
739  poly @f  = 0; // leadmonom
740
741  poly @ff = 0; // polyes
742  poly @gg = 0;
743  number @nf, @ng;
744
745  int flag = 1;
746
747  while ( flag == 1 )
748    {
749      flag = 0;
750
751      @z = zSort(@z); // sort out, < ...
752
753      if( size(@z) < 2 )
754        {
755          return (@z);
756        };
757
758      for ( @i = size(@z); @i > 0; @i -- ) // at 1st the biggest ... then smallest...
759        {
760
761          @ff    = @z[@i];
762
763          if( size(@ff) == 0 )
764            {
765              @z = delete ( @z , @i );
766              @i --;
767              continue;
768            };
769
770          @ff    = @ff*(1/leadcoef(@ff));
771          @z[@i] = @ff;
772          @f         = leadmonom(@ff);
773
774          for ( @j = (@i-1); (@j>0); @j --  )
775            {
776              @gg = @z[@j];
777              @ng = myCoeff(@gg, @f); // leads?
778              if( @ng!=0 )
779                {
780                  @z[@j] = @gg - @ng * @ff;
781                  flag = 1;
782                };
783            };
784          for ( @j = (@i+1); (@j<=size(@z)); @j ++ )
785            {
786              @gg = @z[@j];
787              @ng = myCoeff(@gg, @f);
788              if( @ng!=0 )
789                {
790                  @z[@j] = @gg - @ng * @ff;
791                  flag = 1;
792                };
793            };
794
795        };
796    };
797
798  ECall("zRefine", "list");
799
800  return         ( @z );
801
802};
803
804
805/******************************************************/
806// procedures for building "bad leadmonomials" set
807
808
809/******************************************************/
810static proc checkPolyUniq( list l, poly p )
811  "
812        check whether p sits already in l, assume l to be size-sorted <
813        return: -1 if present
814                 1 if we need to add
815"
816{
817  BCall( "checkPolyUniq", "{ " + string(l) + " }, " + string(p) );
818  int n = size(l);
819  int i = 1;
820
821  int s = size(p);
822
823  while( i<= n )
824    {
825      if ( size(l[i]) >= s )
826        {
827          break;
828        };
829
830      i ++;
831    };
832
833  // now: size(l[i]) >= s
834  while( i<= n )
835    {
836      if ( size(l[i]) == s )
837        {
838          break;
839
840        };
841      if ( l[i] == p )
842        {
843          ECall( "checkPolyUniq", -1 );
844          return (-1);
845        };
846      i ++;
847    };
848
849  ECall( "checkPolyUniq", 1 );
850  return ( 1 );
851
852};
853
854/******************************************************/
855static proc addPolyUniq( list l, poly p )
856  "
857        add p into l uniquely, and keep l size-sorted <
858"
859{
860  BCall( "addPolyUniq", " { " + string(l) + " }, " + string(p) );
861
862  int n = size(l);
863
864  if ( n == 0 )
865    {
866      l = list(p);
867
868      ECall( "addPolyUniq", l );
869
870      return (l);
871    };
872
873  int s = size(p);
874
875  int i = 1;
876  while( i<= n )
877    {
878      if( size(l[i]) > s )
879        {
880          l = insert( l, p, i-1 ) ;
881          break;
882        };
883
884      if( size(l[i]) == s )
885        {
886          if ( l[i] == p )
887            {
888              break;
889            };
890        };
891
892      i++;
893    };
894
895  if( i > n )
896    {
897      l = l + list(p);
898    };
899
900  ECall( "addPolyUniq", l );
901  return(l);
902};
903
904
905/******************************************************/
906static proc mergePolysUniq( list a, list b )
907  "
908        merge lists uniq
909"
910{
911  BCall( "mergePolysUniq", "{ " + string(a) + " }, { " + string(b) + "} " );
912
913  for( int i = 1; i <= size(b); i ++ )
914    {
915      a = addPolyUniq(a, b[i]);
916    };
917
918  ECall( "mergePolysUniq", a );
919
920  return (a);
921};
922
923
924/******************************************************/
925static proc sortPolysUniq( list a )
926  "
927        sort list uniq
928"
929{
930  BCall( "sortPolysUniq", a );
931
932  if( size(a) < 2 )
933    {
934      ECall( "sortPolysUniq", a );
935      return(a);
936    };
937
938  list b = list(a[1]);
939
940  for( int i = 2; i <= size(a); i ++ )
941    {
942      b = addPolyUniq(b, a[i]);
943    };
944
945  ECall( "sortPolysUniq", b );
946
947  return (b);
948};
949
950/******************************************************/
951static proc addRecordUniq ( list leadD, list newD, intvec texp, poly tm, int kind, list prs )
952  "
953        if kind = 0 => for PBW - no products
954        if kind = 1 => with products
955"
956{
957  BCall ("addRecordUniq", "{old leads}, {new lead}, [" + string(texp) + "], " + string(tm) + ", " + string(kind) + ", {" + string(prs) + "}");
958
959  int i;
960  int f_add = 0;
961
962  prs = sortPolysUniq(prs);
963
964  // trick:
965  //  check for presens of a monomial @tm in current index poly of @leads (=> in list @leads)
966  //  if char = 0 then new_size > (if not present) or =  (if already present)
967  //  if char > 0 then new_size > (if not present) or =< (if already present)
968  // !!!!!
969  if( size(tm + leadD[2]) > size(leadD[2]) )
970    {
971      f_add = 1;
972    } else
973      {
974        if ( kind != 0 )
975          {
976            for ( i = 1; i<= size(leadD[1]); i++ )
977              {
978                if ( leadD[1][i][2] == tm )
979                  {
980                    for ( i = size(prs); i>0; i-- )
981                      {
982                        f_add = checkPolyUniq( leadD[1][i][3], prs[i] );
983                        if( f_add == -1 )
984                          {
985                            prs = delete(prs, i);
986                          };
987                      };
988
989                    break;
990                  };
991              };
992          };
993      };
994
995  if ( f_add == 1 )
996    {
997
998      list newlist ;
999      if ( kind != 0 )
1000        {
1001          newlist =  list ( list ( texp, tm, prs ) );
1002        } else
1003          {
1004            newlist =  list ( list ( texp, tm ) );
1005          };
1006
1007
1008      if ( size(newD[1]) == 0 )
1009        {
1010          newD[1] =  newlist;
1011          newD[2] =  tm;
1012        } else
1013          {
1014
1015            if( size(tm + newD[2]) > size(newD[2]) )
1016              {
1017                newD[1] = newD[1] + newlist;
1018                newD[2] = newD[2] + tm;
1019              } else
1020                {
1021                  if ( kind != 0 )
1022                    {
1023                      for ( i = 1; i<= size(newD[1]); i++ )
1024                        {
1025                          if ( newD[1][i][2] == tm )
1026                            {
1027                              newD[1][i][3] = mergePolysUniq( newD[1][i][3], prs );
1028                              break;
1029                            };
1030                        };
1031                    };
1032                };
1033          };
1034    };
1035
1036  ECall("addRecordUniq", "{new leads}");
1037  return (newD);
1038};
1039
1040
1041/******************************************************/
1042static proc mergeRecordsUniq ( list old, list new, int kind )
1043{
1044  BCall ("mergeRecordsUniq", "{old leads}, {new leads}, " + string(kind) );
1045
1046  if(  size(new[1]) > 0 )
1047    {
1048      if ( size (old[1]) == 0 )
1049        {
1050          old = new;
1051        } else
1052          {
1053            if ( kind != 0 )
1054              {
1055                int io;
1056                for ( int in = 1; in <= size( new[1] ); in ++ )
1057                  {
1058                    if( size( new[1][in][2] + old[2] ) > size( old[2] ) )
1059                      {
1060                        old[1] = old[1] + list(new[1][in]);
1061                        old[2] = old[2] + new[1][in][2];
1062                      } else
1063                        {
1064                          for( io = 1; io <= size( old[1] ); io ++ )
1065                            {
1066                              if( old[1][io][2] == new[1][in][2] )
1067                                {
1068                                  old[1][io][3] = mergePolysUniq( old[1][io][3], new[1][in][3] );
1069                                  break;
1070                                };
1071                            };
1072                        };
1073                  };
1074              } else
1075                {
1076                  old[1] = old[1] + new[1];
1077                  old[2] = old[2] + new[2];
1078                };
1079          };
1080    };
1081
1082  ECall ("mergeRecordsUniq", "{new leads}");
1083  return (old);
1084};
1085
1086
1087
1088/******************************************************/
1089static proc init_bads(int @deg)
1090"
1091    initialization of an empty 'badleads' list
1092"
1093{
1094  list @l = list();
1095  for( int @i = 0; @i <= @deg; @i ++ )
1096    {
1097      @l[index(@i)]         = list( list() , 0);
1098      // new items:
1099      // {
1100      //        list of leads,    - empty list
1101      //        sum poly "index", - poly(0)
1102      // }
1103    };
1104  return (@l);
1105};
1106
1107/******************************************************/
1108static proc zAddBad ( list @leads, list @newz, int @maxDeg, int kind )
1109  "
1110        input:
1111                @leads: graded by deg list of
1112                        rec:
1113                        {
1114                                [1] - list of
1115                                        rec:
1116                                        {
1117                                                [1] - leadexp.
1118                                                [2] - leadmonom([1])
1119                                        if kind != 0 (for zReduce) =>
1120                                                [3] - !list! of all possible products which give this leadexp
1121                                        },
1122                                [2] - summ of all in [1] ('index' poly)
1123                        }
1124                @newz: new elements for adding to @leads
1125                @maxDeg: maximal degree
1126
1127                if kind != 0 => keeps also list of all possible products which give leadexp of a record
1128
1129        return:
1130                updated @leads list
1131
1132"
1133{
1134  BCall ("zAddBad", "{old leads}, { " + string(@newz) + " }, " + string(@maxDeg) + ", " + string(kind) + "");
1135
1136  int @newSize = size(@newz);
1137  if ( @newSize < 1 )
1138    {
1139      return (@leads);
1140    };
1141
1142  int @i, @j, @k, @dd, @deg;
1143
1144
1145  poly         @m, @tm, @ttm;
1146  intvec @exp, @texp, @ttexp;
1147
1148  list @newzz;
1149  int @size, @newdeg, @mydeg;
1150
1151  poly @sum_old, @sum_new;
1152
1153  poly a, b, @temp;
1154
1155  /*
1156    if kind = 0 => for PBW - no products
1157    if kind = 1 => for zReduce - with products
1158  */
1159
1160  poly pr = 0; int pri; list prs;
1161
1162  for ( @i = @newSize; @i > 0; @i -- )
1163    {// for every new poly (@newz[@i]) do
1164
1165      @m   = leadmonom( @newz[@i] );
1166      @deg = deg(@m);
1167      @exp = leadexp(@m);
1168
1169      // newzz void new list
1170      @newzz = init_bads(@maxDeg );
1171
1172      for( @mydeg = @deg; @mydeg <= @maxDeg;  @mydeg = @mydeg + @deg )
1173        {// adding all possiblities for @newz[@i]^@j;
1174
1175          if ( @mydeg > @deg )
1176            {
1177              @texp         = @texp + @exp;
1178              @tm         = LM ( @texp );
1179              if ( kind != 0)
1180                {
1181                  pr = QNF_poly( pr * @newz[@i] ); // degrees must be there!!!
1182                };
1183            } else
1184              {
1185                @texp         = @exp;
1186                @tm         = @m;
1187                if ( kind != 0)
1188                  {
1189                    pr = @newz[@i];
1190                  };
1191              };
1192
1193          @temp =  QNF_poly(@tm);
1194          if( @temp != @tm )
1195            {
1196              break;
1197            };
1198
1199          /*!!*/                        @newzz[index(@mydeg)] =
1200                                          /*!!*/        addRecordUniq( @leads[index(@mydeg)], @newzz[index(@mydeg)], @texp, @tm, kind, list(pr) );
1201
1202          for ( @dd = 1; (@dd <= @maxDeg) and ((@dd + @mydeg) <= @maxDeg ); @dd ++ )
1203            { // for every good "deg"
1204
1205              @newdeg = @dd + @mydeg; // any deg should be additive!!!
1206
1207              for ( @k = size(@leads[index(@dd)][1]); @k > 0; @k -- )
1208                {
1209
1210                  @ttexp         = (@leads[index(@dd)][1][@k][1]) + @texp;
1211                  @ttm         = LM (@ttexp);
1212
1213                  if ( kind != 0 )
1214                    {
1215                      prs = list();
1216
1217                      for( pri = 1; pri <= size(@leads[index(@dd)][1][@k][3]); pri++)
1218                        {
1219                          // to do products into list and add one list !!!
1220                          a = QNF_poly( pr*@leads[index(@dd)][1][@k][3][pri]);
1221                          b = QNF_poly( @leads[index(@dd)][1][@k][3][pri]*pr);
1222
1223                          prs= prs + list(a);
1224
1225                          if ( a!=b )
1226                            {
1227                              prs= prs + list(b);
1228                            };
1229                        };
1230
1231                    } else
1232                      {
1233                        prs = list(pr);
1234                      };
1235
1236                  @temp =  QNF_poly(@ttm);
1237                  if( @temp == @ttm )
1238                    {
1239
1240                      /*!!*/                                                @newzz[index(@newdeg)] =
1241                                                                          /*!!*/        addRecordUniq( @leads[index(@newdeg)], @newzz[index(@newdeg)], @ttexp, @ttm, kind, prs );
1242                    };
1243
1244
1245                };
1246            }; // for
1247
1248          if ( @deg == 0 )
1249            {
1250              break;
1251            };
1252        };
1253
1254      for ( @mydeg = 0; @mydeg <= @maxDeg; @mydeg ++ )
1255        { // adding currently generated to result
1256          @leads[index(@mydeg)] = mergeRecordsUniq ( @leads[index(@mydeg)], @newzz[index(@mydeg)], kind );
1257        };
1258
1259    };
1260
1261  ECall ("zAddBad", "{new leads}");
1262
1263  return (@leads);
1264};
1265
1266
1267/******************************************************/
1268// procedure for reducing a given poly wrt already calculated "badleadings"
1269
1270/******************************************************/
1271static proc zReducePoly ( list leads, poly new, poly anfang )
1272  "
1273        reduce poly new wrt found leads,
1274        return: list of all possible reductions...
1275"
1276{
1277  poly temp = new;
1278  poly rest = anfang;
1279
1280  poly   lm;
1281  number lc;
1282
1283  list LEADS;
1284
1285  int i, n;
1286  list prs;
1287
1288  while ( size(temp) > 0 )
1289    {
1290      // do for every term... beginning with leading... 'till smallest
1291      lm = leadmonom( temp );
1292
1293      LEADS = leads[index(deg( lm ))]; // currently users bad leading products...
1294
1295      if( size(LEADS[2] + lm ) <=  size(LEADS[2]) )
1296        { // need to reduce, since leacmonom already in LEADS
1297
1298          for ( i = 1; i <= size(LEADS[1]); i++ )
1299            {
1300              if( LEADS[1][i][2] == lm )
1301                {
1302
1303                  lc = leadcoef( temp ); // no need be the unit
1304
1305                  prs = LEADS[1][i][3]; // shouldbe generated by zAddBad with kind == 1
1306                  n = size(prs) ;
1307
1308                  if ( n == 1 )
1309                    { // no recursion
1310
1311                      temp = leadcoef(prs[1]) * temp - lc * prs[1]; // leadmonom goes down
1312
1313                    } else
1314                      { // do recursion
1315
1316                        list result = list();
1317                        poly newnew;
1318                        int f_addrest = 0;
1319
1320                        for( int pri = 1; pri <= n ; pri ++ )
1321                          {
1322                            newnew = leadcoef(prs[pri]) * temp - lc * prs[pri]; // leadmonom goes down
1323
1324                            if( size( newnew ) > 0 )
1325                              {
1326                                result = result + zReducePoly(leads, newnew, rest);
1327                              } else
1328                                {
1329                                  f_addrest = 1;
1330                                };
1331                          };
1332
1333                        if ( f_addrest == 1 )
1334                          {
1335                            result = result + list(rest);
1336                          };
1337                        return ( result );
1338
1339                      };
1340                  break;
1341                };
1342            };
1343
1344        } else
1345          { // no such leadmonom in leads
1346
1347            rest = rest + lead ( temp );
1348            temp = temp - lead ( temp ); // leadcoeff goes down
1349          };
1350    };
1351
1352  return (list(rest));
1353
1354};
1355
1356
1357/******************************************************/
1358static proc zCancel ( list @tt, list @leads )
1359  "
1360        just kill entries of plane PBW base with leading monomials in @leads...
1361"
1362{
1363  int @i;
1364
1365  if ( (size(@tt) == 0) )
1366    {
1367      return (@tt);
1368    };
1369
1370  list result = list();
1371  poly g, f;
1372
1373  for ( @i = size(@tt); @i > 0 ; @i -- )
1374    // for all PBW entries:
1375    {
1376      g = leadmonom(@tt[@i][1]);    // pbw entry
1377      f = @leads[index(deg(g))][2]; // 'index' poly from @leads
1378
1379      if ( size(f + g) > size(f) ) // if g not in @leads (works only for monomials)
1380        {
1381          result = list( @tt[@i] ) + result;
1382        };
1383    };
1384
1385  return (result);
1386
1387};
1388
1389/******************************************************/
1390// procedure for computing "minimal" set of generators...
1391
1392/******************************************************/
1393static proc zReduce( list @z )
1394  "
1395        reduce a set @z - base of Center as V.S.
1396        into a minimal set!!
1397"
1398{
1399  BCall( "zReduce", @z );
1400
1401  @z = zRefine ( @z );
1402  int n = size( @z );
1403
1404  if ( n < 2 )
1405    {
1406      return (@z);
1407    };
1408
1409  int d = maxDeg( @z );
1410
1411  if( d== -1 )
1412    {
1413      return (@z);
1414    };
1415
1416  list leads = init_bads( d );
1417
1418  list @red;
1419
1420  int f_add; int j;
1421
1422  list result = list();
1423
1424  poly p;
1425
1426  for ( int i = 1; i <= n ; i++ )
1427    {// in this order... from least to maximal...
1428
1429      p = @z[i];
1430
1431      @red = zReducePoly ( leads, p, 0 );
1432
1433      f_add = 1;
1434
1435      for( j = 1; j <= size(@red); j++ )
1436        {
1437          if ( @red[j] == 0 )
1438            {
1439              f_add = 0;
1440              break; // nothing new....
1441            };
1442        };
1443
1444      @red = zRefine( @red ); // there will be no zeroes after ???
1445
1446      if( size(@red) > 0 )
1447        {
1448          leads = zAddBad( leads, @red, d, 1);
1449        };
1450
1451      if ( f_add == 1 )
1452        {
1453          // we got something new....
1454          result = result + list(@red); // ??? which one to add? => trying to add all
1455        };
1456    };
1457
1458  ECall( "zReduce", result );
1459
1460  return (result);
1461};
1462
1463
1464/******************************************************/
1465// PBW procedures ....
1466
1467/*
1468  PBW: graded by deg list of lists of PBW terms.
1469  PBW term: list of 2 polynoms: [1] = PBW monom, [2] = Ad_p( [1] ), [3] = last variable in [1] (for speed)
1470*/
1471
1472/******************************************************/
1473static proc PBW_init()
1474  "
1475PBW[ index(0) ] = PBW part of degree 0:
1476record:
1477        [1] : 1                // var(0) ;-)
1478        [2] : 0
1479        [3] : 1
1480"
1481{
1482  BCall( "PBW_init" );
1483  return (list(list(1, 0, 1)));
1484};
1485
1486
1487/******************************************************/
1488static proc PBW_sys(list VARS, poly p)
1489  "
1490        calculate the array [1..NVARS] of records:
1491record[i] =
1492                [1] = var(i)                 // i^{th} variable
1493                [2] = p*[1]-[1]*p         // [ p, var(i) ]
1494                [3] = deg(var(i))         // i^{th} variable's deg
1495
1496        ?? need debug ??
1497"
1498{
1499
1500  BCall( "PBW_sys" );
1501
1502  poly t;
1503  for (int v = size(VARS); v>0; v -- )
1504    {
1505      t            = VARS[v];
1506      VARS[v] = list( t, QNF_poly( p*t - t*p ), deg(t) ) ;
1507    };
1508
1509  return (VARS);
1510};
1511
1512/******************************************************/
1513static proc PBW_done( list PBW )
1514  "
1515        collects all together, from graded lists into plane list.
1516
1517        Note: also the last vars...
1518"
1519{
1520  BCall( "PBW_done" );
1521
1522  list result = list();
1523
1524  int n = size(PBW);
1525  for ( int i = 1; i <= n; i++)
1526    {
1527      result = result + PBW[i];
1528    };
1529
1530  return (result);
1531};
1532
1533/******************************************************/
1534static proc PBW_next ( list PBW, int k, list sys)
1535{
1536  BCall( "PBW_next", k );
1537
1538  list temp;
1539  int kk, nn, ii;
1540  list result = list(); // PBW[ index(k) ] ought to be empty ??
1541  int N = size(sys);
1542
1543  for ( int i = 1; i <= N; i ++ ) // for all vars
1544    {
1545      kk = (k - sys[i][3]);   // any deg should be additive function wrt multiplication
1546      if ( kk >= 0 )
1547        {
1548          nn = size( PBW[ index(kk) ] );
1549          for ( ii = 1; ii <= nn; ii ++ )
1550            {
1551              temp = PBW[ index(kk) ][ii];
1552
1553              if ( temp[3] <= i )
1554                {
1555                  temp[2] = temp[2]*sys[i][1] + temp[1]*sys[i][2]; // recursive [,]
1556                  temp[1] = temp[1]*sys[i][1];
1557                  temp[3] = i;
1558
1559                  result = result + list ( temp );
1560                };
1561            };
1562        };
1563    };
1564
1565  result = QNF_list( result, 2 + 4);
1566  ECall( "PBW_next", "list result" );
1567  return (result);
1568
1569};
1570
1571/******************************************************/
1572static proc PBW_base( int MaxDeg, poly p )
1573{
1574  BCall( "PBW_base", MaxDeg, p );
1575
1576  list PBW = list();
1577  list SYS = PBW_sys( my_vars(), p );
1578
1579  PBW[index(0)] = PBW_init();
1580
1581  for (int k = 1; k <= MaxDeg; k ++ )
1582    {
1583      PBW[index(k)] = PBW_next( PBW, k, SYS );
1584    };
1585
1586  return (PBW_done( PBW ));
1587};
1588
1589
1590/******************************************************/
1591// standard center procedures...
1592
1593/******************************************************/
1594static proc FSS (list @given, poly @BASE_POLY)
1595"
1596    Gauss with computation of kernel v.s basis
1597    to be optimized
1598"
1599{
1600  BCall( "FSS", "list", "basepoly: ", @BASE_POLY);
1601
1602  list @nums = list ();
1603  intvec @ones;
1604  int @j, @k,
1605    @n, @v,
1606    @a, @nn;
1607
1608  @n = size( @BASE_POLY );
1609  @v = size( @given );
1610
1611  if ( (@v == 0) or (@n == 0) )
1612    {
1613      return (@given);
1614    };
1615
1616  matrix MD[@n][@v];
1617
1618  number @max;
1619  poly @test;
1620  poly @t;
1621
1622  list LM = list(); // rec: { exp, poly }
1623
1624  for( @k = @v; @k > 0; @k -- )
1625    {
1626      LM[@k] = list();
1627      @t =  @given[@k][2];
1628      LM[@k][2]= @t;
1629      LM[@k][1]= leadexp( @t );
1630    };
1631
1632
1633  intvec @w;
1634  for ( @a = 1 ; @a <= @n ; @a ++ )
1635    {
1636      @w = leadexp(@BASE_POLY[@a]);
1637      for( @k = @v; @k > 0; @k -- )
1638        {
1639          if( @w == LM[@k][1] )
1640            {
1641              @t = LM[@k][2];
1642              MD[@a, @k] = leadcoef( @t );
1643              @t = @t - lead ( @t );
1644              LM[@k][2]  = @t;
1645
1646              LM[@k][1]  = leadexp(@t);
1647            };
1648        };
1649
1650    };
1651
1652  int @x, @y;
1653  number @min;
1654
1655  number @div;
1656  //    @nums = list();
1657
1658  // Gauss
1659//  print("Before Gauss, Matrix: ");
1660//  print( MD );
1661
1662
1663  @x = 1;
1664  @y = 1;
1665  while ( (@y <= @n) && (@x <= @v))
1666    // main Gauss loop...
1667    {
1668      @min =  leadcoef( MD[@y, @x] ); // curr diag.
1669
1670      if ( @min == 0 )
1671        // if zero on diag...
1672        {
1673          @j = 0;
1674
1675          // let's find the minimal
1676          for ( @k = @y+1; @k <= @n; @k ++ )
1677            {
1678              @max = leadcoef( MD[ @k, @x ] );
1679              if ( @max != 0 )
1680                {
1681                  @j = @k;
1682                  @min = @max;
1683                  //                    @k ++;
1684                  break; // this pure for
1685                  // continue;
1686                  // for find min
1687                };
1688            }; // for (@k) // found minimal
1689
1690          if ( @j == 0 )
1691            {
1692              // das ist gut! //
1693              @nums = @nums + list ( list ( @x, @y ) );
1694              @x ++;
1695              continue; // while
1696            } ;
1697
1698          for ( @k = @x ; @k <= @v ; @k ++ )
1699            {
1700              @t =  MD[ @j, @k ];
1701              MD[ @j, @k ] = MD[ @y, @k ];
1702              MD[ @y, @k ] = @t;
1703            };
1704
1705        }; // if diag === zero.
1706      @ones[@y] = @x;
1707
1708      if ( @min == 0 )
1709        {
1710          //            write_latex_str ( " ******************* ERROR ******************* " );
1711          quit;
1712        };
1713
1714
1715      if ( @min != 1) // let's norm the row... to make the '1' !
1716        {
1717          @min = 1 / @min;
1718          for ( @k = @x; @k <= @v; @k++ )
1719            {
1720              @max = leadcoef( MD[@y, @k] );
1721
1722              if ( @max == 0)
1723                {
1724                  @k ++ ;
1725                  continue; // for : norming the row...
1726                };
1727
1728              MD[@y, @k] = @max * @min;  // here must be Field ...
1729            };
1730
1731          //            @min = 1;
1732
1733        };
1734
1735      // here must be @min != 0;
1736      for ( @k = 1; @k <= @n; @k++ )
1737        {
1738          @max = leadcoef( MD[@k, @x] );
1739
1740          if ( ( @k == @y) || (@max == 0) )
1741            {
1742              @k ++ ;
1743              continue;
1744            };
1745
1746          for ( @j = @x; @j <= @v ; @j ++ )
1747            {
1748              MD[ @k, @j ] = MD[ @k, @j ] - @max * MD[ @y, @j ];
1749            };
1750
1751        }; //killing
1752
1753      @x ++;
1754      @y ++;
1755    }; //main while.
1756  /******************************************************/
1757
1758//  print("Gaussed Matrix: ");
1759//  print( MD );
1760
1761  // computation of kernel's basis
1762
1763  if ( @x <= @v )
1764    {
1765      for ( @k = @x; @k <= @v ; @k ++ )
1766        {
1767          @nums = @nums + list ( list ( @k, @n+1 ) );
1768        }
1769    }
1770
1771//  print("Nums: " );
1772//  print (@nums);
1773
1774  list result = list();
1775
1776  // real calculations of the Base of a Ker as V.S.
1777
1778  for ( @k = 1; @k <= size(@nums) ; @k ++ )
1779    {
1780      @x = @nums[@k][1];
1781      @j  = @nums[@k][2];
1782
1783      @t = @given[@x][1];
1784
1785      for ( @y = 1; @y < @j ; @y ++ )
1786        // for every "@x" column
1787        {
1788          @max = leadcoef( MD[@y, @x] );
1789          if ( (@max != 0) )
1790            {
1791              @a = @ones[@y];
1792              @t = @t - @max * @given[@a][1];
1793            };
1794        };
1795
1796      result[@k] = @t;
1797    };
1798
1799  ECall( "FSS", "list" );
1800  return ( result );
1801};
1802
1803/******************************************************/
1804static proc reduce_one_per_row(list @given)
1805{
1806  BCall( "reduce_one_per_row" );
1807
1808  int @k;
1809  int @l = size (@given);
1810
1811  if( @l == 0 )
1812    {
1813      return (@given);
1814    };
1815
1816  int @char = char(basering);
1817
1818  intvec @marks;
1819
1820  if ( @char == 0 )
1821    {
1822      poly @t = poly(0);
1823    };
1824
1825  list @unis = list ();
1826  poly p;
1827
1828  for ( @k = @l; @k > 0; @k -- )
1829    {
1830      p = uni_poly( @given[@k][2] );
1831      @unis[@k] = p;
1832
1833      if( p == 0 )
1834        {
1835          @marks[@k] = 2;
1836        } else
1837          {
1838            @marks[@k] = 1;
1839            if ( @char == 0 )
1840              {
1841                @t = @t + p;
1842              };
1843          };
1844    };
1845
1846  if ( @char != 0 )
1847    {
1848      def save = basering;
1849      execute( "ring NewRingWithGoodField = (0), (" + varstr(save) + "), (" + ordstr(save) + "); ");
1850      poly @t = 0;
1851
1852      if(! defined (@unis) )
1853        {
1854          list @unis = imap( save, @unis );
1855        };
1856
1857      for ( @k = @l; @k > 0; @k -- )
1858        {
1859          if( @marks[@k] == 1 )
1860            {
1861              @t = @t + @unis[@k];
1862            };
1863        };
1864    };
1865
1866  int @loop_size = size(@t);
1867  poly @for_delete, @tt;
1868  int @ll;
1869
1870  while( @loop_size > 0 )
1871    {
1872      @for_delete = poly(0);
1873      @ll = size(@t);
1874
1875      for ( @k = @ll; @k > 0; @k -- )
1876        {
1877          if ( leadcoef(@t[@k]) == 1 )
1878            {
1879              @for_delete = @for_delete + @t[@k];
1880            };
1881        };
1882
1883      @loop_size = size( @for_delete );
1884
1885      if ( @loop_size>0 )
1886        {
1887          for( @k = @l ; @k > 0 ; @k -- )
1888            {
1889              if ( @marks[@k] == 1)
1890                {
1891                  @tt = @unis[@k];
1892
1893                  if( size( @for_delete + @tt ) != ( size( @for_delete )  + size( @tt ) ) )
1894                    {
1895                      @t = @t - @tt;
1896                      @marks[@k] = 0;
1897                    };
1898                };
1899            };
1900        };
1901    };
1902
1903  if ( @char != 0 )
1904    {
1905      setring(save);
1906      kill NewRingWithGoodField;
1907    };
1908
1909  list @reduced = list();
1910
1911  for ( @k = @l ; @k>0 ; @k --)
1912    {
1913      if (@marks[@k]==2)
1914        {
1915          @reduced = list ( @given[@k] ) + @reduced ;
1916        } else
1917          {
1918            if (@marks[@k]==1)
1919              {
1920                @reduced = @reduced + list ( @given[@k] );
1921              };
1922          };
1923    };
1924
1925  ECall( "reduce_one_per_row", "structured list" );
1926  return (@reduced);
1927};
1928
1929
1930
1931/******************************************************/
1932static proc calc_base (list @AD_GIVEN)
1933  "
1934    sort out given 'pbw' into groups due to common monoms in images = ([2])s
1935"
1936{
1937  BCall( "calc_base" );
1938
1939  list @AD_CALC = list();
1940  int @ll, @k, @j, @loop_size;
1941
1942  poly @t = poly(0);
1943  poly @tt, @for_delete;
1944
1945  int @t_size;
1946
1947  list @GR, @GR_TEMP;
1948
1949  int @number = size(@AD_GIVEN);
1950
1951  while ( @number > 0 )
1952    {
1953      @tt = @AD_GIVEN[@number][2];
1954      if ( size (@tt) == 0)
1955        {
1956          @AD_CALC = @AD_CALC + list ( @AD_GIVEN[@number][1] );
1957        } else
1958          {
1959            @t = uni_poly( @tt );
1960            @t_size = size(@t);
1961
1962            @GR_TEMP = list ();
1963            @GR_TEMP[1] = @t;
1964            @GR_TEMP[2] = list ( @AD_GIVEN[@number] );
1965
1966            @loop_size = size(@GR);
1967            if ( @loop_size == 0 )
1968              {
1969                @GR = list(@GR_TEMP);
1970              } else
1971                {
1972                  for ( @k = @loop_size; @k > 0 ; @k -- )
1973                    {
1974                      @tt = @GR[@k][1];
1975                      if ( size( @t + @tt ) != ( @t_size + size(@tt) ) )
1976                        // whether @tt and @i intersencts? ( will not work in char == 2 !!!)
1977                        {
1978
1979                          if ( char(basering) == 0 )
1980                            {
1981                              @GR_TEMP[1] = @GR_TEMP[1] + @tt;
1982                            } else
1983                              {
1984                                @GR_TEMP[1] = uni_poly( @GR_TEMP[1] + @tt );
1985                              };
1986
1987                          @GR_TEMP[2] = @GR_TEMP[2] + @GR[@k][2];
1988                          @GR = delete ( @GR, @k );
1989                        };
1990                    };
1991                  @GR = @GR + list(@GR_TEMP);
1992                };
1993          };
1994      @number --;
1995    }; //  main while
1996
1997  list @res;
1998
1999  for ( @k = size(@GR); @k > 0 ; @k -- )
2000    {
2001      if ( size (@GR[@k][2]) > 1 ) // ! zeroes in AD_CALC so here must be non zero
2002        {
2003          @res = FSS ( @GR[@k][2], uni_poly(@GR[@k][1]));
2004
2005          if ( size (@res) > 0 )
2006            {
2007              @AD_CALC = @AD_CALC + @res;
2008            };
2009        };
2010    };
2011
2012  ECall( "calc_base" );
2013  return (@AD_CALC);
2014
2015};
2016
2017
2018/******************************************************/
2019static proc ApplyAd( list l, list # )
2020"
2021  Apply Ad_{#} to every element of a list of polynomils
2022"
2023{
2024  BCall( "ApplyAd", l, # );
2025
2026  if( (size(l) == 0) or (size(#) == 0) )
2027    {
2028      return (l);
2029    };
2030
2031  poly f, t;
2032
2033  if ( typeof(#[1]) == "int")
2034    {
2035      int next = #[1];
2036      f = my_var (next);
2037    } else
2038      {
2039        if ( typeof(#[1]) == "poly")
2040          {
2041            f = #[1];
2042          } else
2043            {
2044              print("Error: cannot differentiate with '" + string(#)+"'");
2045              return ();
2046            };
2047      };
2048
2049  for ( int k = size(l); k > 0; k --)
2050    {
2051      t = l[k];
2052      l[k] = list( t, f * t - t * f );
2053    };
2054
2055  ECall("ApplyAd", l );
2056  return (l);
2057};
2058
2059
2060/******************************************************/
2061static proc calc_k_base (list l, list #)
2062  "
2063     calculation of Kernel of an Ad operator as a K-Vector Space
2064"
2065{
2066  BCall( "calc_k_base", "list, " + string(#) );
2067
2068  list t = reduce_one_per_row( l, 0); // optimization (a1)
2069  return( QNF_list ( ApplyAd( calc_base(t), # ), 2) );          // calculation of groupps (a2) + gauss.
2070
2071};
2072
2073LIB "poly.lib"; // for content in proc makeIdeal
2074
2075/******************************************************/
2076static proc makeIdeal ( list l )
2077  "
2078        return: ideal: where the generators are polynomials from list, without 1 and zeroes
2079"
2080{
2081  ideal I; poly p;
2082
2083  for( int i = 1; i <= size(l); i++ )
2084    {
2085      if ( typeof( l[i] ) == "list" )
2086        {
2087          p = l[i][1]; // just take the 1st polynom...
2088        } else
2089          {
2090            p = l[i];
2091          };
2092
2093      p = cleardenom( p* (1/content(p)) );
2094      if ( (p != 1) and (p != 0) )
2095        {
2096          I = I, p;
2097        };
2098    };
2099
2100  I = simplify ( I, 2 ); // no zeroes
2101
2102  return(I);
2103};
2104
2105/******************************************************/
2106static proc inCenter_poly( poly p )
2107  "
2108  if p in center => return 1
2109      otherwise     return 0
2110"
2111{
2112  poly t;
2113  for (int k = nvars(basering); k>0; k-- )
2114    {
2115      t = var(k);
2116      if ( QNF_poly(t * p - p * t) != 0 )
2117        {
2118          if( toprint() )
2119            {
2120              "POLY: ", string (p), " is NOT in center";
2121            };
2122          return (0);
2123        };
2124    };
2125
2126  if( toprint() )
2127    {
2128      "POLY: ", string (p), " is in center";
2129    };
2130  return (1);
2131};
2132
2133/******************************************************/
2134static proc inCenter_list(def l)
2135{
2136  for ( int @i = 1; @i <= size(l); @i++ )
2137    {
2138      if ( typeof(l[@i])=="poly" )
2139        {
2140          if (! inCenter_poly(l[@i]) )
2141            {
2142              return(0);
2143            };
2144
2145        } else
2146          {
2147            if ( (typeof(l[@i])=="list") or (typeof(l[@i])=="ideal") )
2148              {
2149                if (! inCenter_list(l[@i]) )
2150                  {
2151                    return(0);
2152                  };
2153              };
2154          };
2155    };
2156  return(1);
2157};
2158
2159/******************************************************/
2160static proc inCentralizer_poly( poly p, poly f )
2161  "
2162  if p in centralizer(f) => return 1
2163      otherwise     return 0
2164"
2165{
2166  if ( QNF_poly(f * p - p * f) != 0 )
2167    {
2168      if( toprint() )
2169        {
2170          "POLY: ", string (p), " is NOT in centralizer(f)";
2171        };
2172      return (0);
2173    };
2174
2175  if( toprint() )
2176    {
2177      "POLY: ", string (p), " is in centralizer(f)";
2178    };
2179  return (1);
2180};
2181
2182/******************************************************/
2183static proc inCentralizer_list( def l, poly f )
2184{
2185  for ( int @i = 1; @i <= size(l); @i++ )
2186    {
2187      if ( typeof(l[@i])=="poly" )
2188        {
2189          if (! inCentralizer_poly(l[@i], f) )
2190            {
2191              return(0);
2192            };
2193
2194        } else
2195          {
2196            if ( (typeof(l[@i])=="list") or (typeof(l[@i])=="ideal") )
2197              {
2198                if (! inCentralizer_list(l[@i], f) )
2199                  {
2200                    return(0);
2201                  };
2202              };
2203          };
2204    };
2205  return(1);
2206};
2207
2208
2209/******************************************************/
2210/******************************************************/
2211// main algorithms
2212
2213
2214/******************************************************/
2215/******************************************************/
2216// center's computation
2217
2218/******************************************************/
2219/* static */ proc center_min_iterative( int MaxDeg, list # )
2220  "
2221        computes the 'minimal' set of central elements (of deg <= MaxDeg) in iterative way
2222        Note: based on calc_k_base, zAddBad, zRefine, zCancel, PBW_*
2223"
2224{
2225  BCall("center_min_iterative", MaxDeg, #);
2226
2227  int n = myInt(#);
2228  int m = ( MaxDeg < 0 ); // no bound on Degree
2229
2230  int MinDeg = 6; // starting guess for MaxDeg
2231  int Delta  = 4; // increment of MaxDeg
2232
2233  if( m )
2234    {
2235      // minimal guess
2236      MaxDeg = MinDeg;
2237    };
2238
2239  list @q; int @i; int N = nvars(basering);
2240
2241  my_var_init(); // setup for my_var(n)
2242  QNF_init();
2243
2244  list PBW = list();
2245  list PBW_PLAIN = list();
2246
2247  PBW[ index(0) ] = PBW_init();
2248
2249  list SYS = PBW_sys( my_vars(), my_var(1) );
2250
2251
2252  list @z = list ();                                         // center list
2253  list @l = init_bads( MaxDeg );         // verbotten leadexps...
2254
2255  @q = PBW[ index(0) ];
2256
2257  int k = 1;
2258  while( k <= ( MaxDeg+1 ) )
2259    {
2260      for ( @i = 2; @i <= N; @i ++ )
2261        {
2262          @q = calc_k_base (@q, my_var(@i));
2263        };
2264
2265      @q = zRefine (calc_k_base(@q)); // new center!
2266
2267
2268      if ( size(@q) > 0 )
2269        {
2270          @z = @z + @q; // computed central elements
2271
2272          if( (n > 0) and (size(@z) > n) )
2273            {
2274              break; // found all central elements
2275            };
2276        };
2277
2278      if( k == ( MaxDeg+1 ) )
2279        {
2280          if( (n == 0) and ( !m ) )
2281            {
2282              break; // that's all
2283            };
2284
2285          MaxDeg = MaxDeg + Delta;
2286
2287          // renew bad list
2288          @l = init_bads( MaxDeg );
2289          @l = zAddBad( @l, @z, MaxDeg, 0 );
2290
2291        } else
2292          {
2293
2294            if ( size(@q) > 0 )
2295              {
2296                @l = zAddBad( @l, @q, MaxDeg, 0 ); // add all possible 'leadexps' !
2297              };
2298
2299          };
2300
2301      PBW[index(k)] = PBW_next( PBW, k, SYS );
2302
2303      PBW_PLAIN = PBW_PLAIN + zCancel( PBW[index(k-1)] , @l );
2304
2305      @q = PBW_PLAIN + zCancel( PBW[index(k)] , @l ); // kill from @tt all entries with leadexp in @l[@d]
2306
2307      k ++;
2308    };
2309
2310  QNF_done();
2311  my_var_done();
2312
2313  return (makeIdeal(@z));
2314};
2315
2316/******************************************************/
2317static proc center_vectorspace( int MaxDeg )
2318  "
2319        pure calculation of center as a finitely dimensional Vector Space (deg <= MaxDeg )
2320"
2321{
2322  my_var_init();
2323
2324  int  N = nvars( basering );
2325  list P = PBW_base( MaxDeg, my_var(1) );
2326
2327  for( int v = 2; v <= N; v++ )
2328    {
2329      P = calc_k_base( P, my_var(v) );
2330    };
2331
2332  my_var_done();
2333
2334  return( calc_k_base ( P ) );
2335};
2336
2337/******************************************************/
2338/* static */ proc center_min_vectorspace( int MaxDeg )
2339  "
2340    computes the 'minimal' set of central elements (of deg <= MaxDeg)
2341    by reducing the set of it's generators as vector space
2342
2343    Note: based on center_vectorspace.
2344    Note: reduction by zReduce.
2345"
2346{
2347
2348  QNF_init();
2349  ideal res = makeIdeal( zReduce( center_vectorspace( MaxDeg)));
2350  QNF_done();
2351
2352  return( res );
2353};
2354
2355
2356/******************************************************/
2357/******************************************************/
2358// centralizer's computations
2359
2360/******************************************************/
2361static proc centralizer_vectorspace( poly p, int MaxDeg )
2362{
2363  return( calc_k_base( PBW_base( MaxDeg, p )));
2364};
2365
2366/******************************************************/
2367/* static */ proc centralizer_min_vectorspace( poly p, int MaxDeg )
2368{
2369
2370  QNF_init();
2371  ideal res = makeIdeal( zReduce( centralizer_vectorspace( p, MaxDeg)));
2372  QNF_done();
2373
2374  return( res );
2375};
2376
2377/******************************************************/
2378/* static */ proc centralizer_min_iterative( poly p, int MaxDeg, list # )
2379  "
2380  computes the 'minimal' set of elements (of deg <= MaxDeg) generating centralizer of p in iterative way
2381  Note: based on calc_k_base
2382
2383  !!! NEED DEBUG !!!
2384  Note: no proof that it is really centralizer and moreover 'minimal' centralizer
2385"
2386{
2387  QNF_init();
2388
2389  int n = myInt(#);
2390  int m = (MaxDeg < 0);
2391
2392  int MinDeg = 6; // starting guess for MaxDeg
2393  int Delta  = 4; // increment of MaxDeg
2394
2395  if( m )
2396    {
2397      // minimal guess
2398      MaxDeg = MinDeg;
2399    };
2400
2401  list @q;
2402
2403  list PBW = list();
2404  list PBW_PLAIN = list();
2405
2406  PBW[ index(0) ] = PBW_init();
2407
2408  list SYS = PBW_sys( my_vars(), p );
2409
2410  list @z  = list ();             // result list
2411  list @l  = init_bads( MaxDeg ); // verbotten loeadexps...
2412
2413  @q = PBW[ index(0) ];
2414
2415  for (int k = 1; k <= ( MaxDeg+1 ); k ++ )
2416    {
2417      @q = zRefine( calc_k_base(@q), 1 );
2418
2419      if ( size(@q) > 0 )
2420        {
2421          @z = @z + @q; // computed desired elements
2422
2423          if( (n > 0) and (size(@z) > n) )
2424            {
2425              break; // found needed elements
2426            };
2427        };
2428
2429      if( k == ( MaxDeg+1 ) )
2430        {
2431          if( (n == 0) or ( !m ) )
2432            {
2433              break; // that's all
2434            };
2435
2436          MaxDeg = MaxDeg + Delta;
2437
2438          // renew bad list
2439          @l = init_bads( MaxDeg );
2440          @l = zAddBad( @l, @z, MaxDeg, 0 );
2441
2442        } else
2443          {
2444
2445            if ( size(@q) > 0 )
2446              {
2447                @l = zAddBad( @l, @q, MaxDeg, 0 ); // add all possible 'leadexps' !
2448              };
2449
2450          };
2451
2452      PBW[index(k)] = PBW_next( PBW, k, SYS );
2453      PBW_PLAIN = PBW_PLAIN + zCancel( PBW[index(k-1)] , @l );
2454      @q = PBW_PLAIN + zCancel( PBW[index(k)] , @l );  // kill from @tt all entries with leadexp in @l[@d]
2455
2456    };
2457
2458  QNF_done();
2459  return (makeIdeal(@z));
2460};
2461
2462
2463
2464/******************************************************/
2465/******************************************************/
2466// main aliases
2467
2468/******************************************************/
2469proc inCenter( def a )
2470"USAGE:   inCenter(a); a poly/list/ideal
2471RETURN:  integer, 1 if a in the center, 0 otherwise
2472PURPOSE: check whether a given element is central
2473EXAMPLE: example inCenter; shows examples
2474"{
2475  QNF_init();
2476  def res;
2477
2478  if ( typeof(a) == "poly" )
2479    {
2480      res = inCenter_poly(a);
2481    } else
2482      {
2483        if ( (typeof(a)=="list") or (typeof(a)=="ideal") )
2484          {
2485            res = inCenter_list(a);
2486          } else
2487            {
2488              res = a;
2489            };
2490      };
2491
2492  QNF_done();
2493  return (res);
2494}
2495example
2496{
2497  "EXAMPLE:";echo=2;
2498  ring r=0,(x,y,z),dp;
2499  matrix D[3][3]=0;
2500  D[1,2]=-z;
2501  D[1,3]=2*x;
2502  D[2,3]=-2*y;
2503  ncalgebra(1,D); // this is U(sl_2)
2504  poly p=4*x*y+z^2-2*z;
2505  inCenter(p);
2506  poly f=4*x*y;
2507  inCenter(f);
2508  list l= list( 1, p, p^2, p^3);
2509  inCenter(l);
2510  ideal I= p, f;
2511  inCenter(I);
2512};
2513
2514
2515/******************************************************************************/
2516proc inCentralizer( def a, poly f )
2517"USAGE:   inCentralizer(a, f); a poly/list/ideal, f poly
2518RETURN:  integer, 1 if a in the centralizer(f), 0 otherwise
2519PURPOSE: check whether a given element is centralizing with respect to f
2520EXAMPLE: example inCentralizer; shows examples
2521"{
2522  QNF_init();
2523  def res;
2524
2525  if ( typeof(a) == "poly" )
2526    {
2527      res = inCentralizer_poly(a, f);
2528    } else
2529      {
2530        if ( (typeof(a)=="list") or (typeof(a)=="ideal") )
2531          {
2532            res = inCentralizer_list(a, f);
2533          } else
2534            {
2535              res = a;
2536            };
2537      };
2538
2539  QNF_done();
2540  return (res);
2541}
2542example
2543{
2544  "EXAMPLE:";echo=2;
2545  ring r=0,(x,y,z),dp;
2546  matrix D[3][3]=0;
2547  D[1,2]=-z;
2548  ncalgebra(1,D); // the Heisenberg algebra
2549  poly f = x^2;
2550  poly a = z; // we know this element if central
2551  poly b = y^2;
2552  inCentralizer(a, f);
2553  inCentralizer(b, f);
2554  list  l = list(1, a);
2555  inCentralizer(l, f);
2556  ideal I = a, b;
2557  inCentralizer(I, f);
2558};
2559
2560/******************************************************/
2561proc center(int MaxDeg, list # )
2562"USAGE:      center(MaxDeg[, N]); int MaxDeg, int N
2563RETURN:     ideal, generated by elements of degree at most MaxDeg
2564PURPOSE:    computes a minimal set of central elements up to degree MaxDeg.
2565NOTE:       In general, one cannot predict the number or the heighest degree of
2566 central elements. Hence, one has to specify a termination condition via arguments MaxDeg and/or N.
2567@*   If MaxDeg is positive, the computation stops after all central elements of degree at most MaxDeg has been found.
2568@*   If MaxDeg is negative, the termination is determined by N only.
2569@*   If N is given, the computation stops if at least N central elements has been found.
2570@* Warning: if N is given and bigger than the real number of generators, the procedure may not terminate.
2571SEE ALSO:   centralizer; inCenter
2572EXAMPLE:    example center; shows an example
2573"{
2574  if ( myInt(#) > 0 ) // given a number of central elements to compute
2575    {
2576      return ( center_min_iterative( MaxDeg, # ) );
2577    };
2578
2579  if( MaxDeg >= 0 ) // standard computation - the fastest one (often)
2580    {
2581      // return ( center_min_iterative( MaxDeg, # ) );
2582      return ( center_min_vectorspace ( MaxDeg ) );
2583    };
2584
2585  print( "Error: wrong arguments." );
2586  return();
2587}
2588example
2589{ "EXAMPLE:"; echo = 2;
2590  ring A = 0,(x,y,z,t),dp;
2591  matrix D[4][4]=0;
2592  D[1,2]=-z;  D[1,3]=2*x;  D[2,3]=-2*y;
2593  ncalgebra(1,D); // this algebra is U(sl_2) tensored with K[t]
2594  ideal Z = center(3); // find all central elements of degree <= 3
2595  Z;
2596  inCenter(Z);
2597  ideal ZZ = center(-1, 1); // find one central element of the lowest degree
2598  ZZ;
2599  inCenter(ZZ);
2600};
2601
2602
2603/******************************************************/
2604proc centralizer( poly p, int MaxDeg, list # )
2605"USAGE:      centralizer(F, MaxDeg[, N]); poly F, int MaxDeg, int N
2606RETURN:     ideal, generated by elements of degree <= MaxDeg
2607PURPOSE:    computes a minimal set of elements centralizer(F) up to degree MaxDeg.
2608NOTE:       In general, one cannot predict the number or the heighest degree of
2609 centralizing elements. Hence, one has to specify a termination condition via arguments MaxDeg and/or N.
2610@*   If MaxDeg is positive, the computation stops after all centralizing elements of degree at most MaxDeg has been found.
2611@*   If MaxDeg is negative, the termination is determined by N only.
2612@*   If N is given, the computation stops if at least N centralizing elements has been found.
2613@* Warning: if N is given and bigger than the real number of generators, the procedure may not terminate.
2614SEE ALSO:   center; inCentralizer
2615EXAMPLE:    example centralizer; shows an example
2616"{
2617
2618  if( myInt(#) > 0 )
2619    {
2620      return( centralizer_min_iterative( p, MaxDeg, # ) );
2621    };
2622
2623  if( MaxDeg >= 0 )
2624    {
2625      // return( centralizer_min_iterative( p, MaxDeg, # ) );
2626      return( centralizer_min_vectorspace( p, MaxDeg ) );
2627    };
2628
2629  print( "Error: wrong arguments." );
2630  return();
2631
2632}
2633example
2634{ "EXAMPLE:"; echo = 2;
2635 ring A = 0,(x,y,z),dp;
2636 matrix D[3][3]=0;
2637 D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y;
2638 ncalgebra(1,D); // this algebra is U(sl_2)
2639 poly f = 4*x*y+z^2-2*z; // a central polynomial
2640 f;
2641 ideal c = centralizer(f, 2); // find all elements of the centralizer of f
2642                              // of degree <= 2
2643 c;  // since f is central, the answer consists of generators of A
2644 inCentralizer(c, f);
2645 ideal cc = centralizer(f,-1,2); // find at least two elements of the centralizer of f
2646 cc;
2647 inCentralizer(cc, f);
2648 poly g = z^2-2*z; // some non-central polynomial
2649 c = centralizer(g, 2); // find all elements of the centralizer of g
2650                        // of degree <= 2
2651 c;
2652 inCentralizer(c, g);
2653 centralizer(g,-1,1); // find the element of the lowest degree in the centralizer
2654 cc = centralizer(g,-1,2); // find at least two elements of the centralizer of g
2655 cc;
2656 inCentralizer(cc, g);
2657};
Note: See TracBrowser for help on using the repository browser.