source: git/Singular/LIB/center.lib @ 3c4dcc

spielwiese
Last change on this file since 3c4dcc was 3c4dcc, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: DOS->UNIX and white space cleanup git-svn-id: file:///usr/local/Singular/svn/trunk@8073 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 57.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: center.lib,v 1.14 2005-05-06 14:38:08 hannes Exp $";
3category="Noncommutative";
4info="
5LIBRARY:  center.lib      computation of central elements of G-algebras and Q-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'
12
13PROCEDURES:
14        center(MaxDeg[,N]);             computes the generators of the center of a basering,
15        centralizer(f, MaxDeg[,N]);     computes the generators of the centralizer of f in a basering,
16        inCenter(l);                    checks the centrality of elements of list/ideal/poly l
17        inCentralizer(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)
2472EXAMPLE: example inCenter; shows examples"
2473{
2474  QNF_init();
2475  def res;
2476
2477  if ( typeof(a) == "poly" )
2478    {
2479      res = inCenter_poly(a);
2480    } else
2481      {
2482        if ( (typeof(a)=="list") or (typeof(a)=="ideal") )
2483          {
2484            res = inCenter_list(a);
2485          } else
2486            {
2487              res = a;
2488            };
2489      };
2490
2491  QNF_done();
2492  return (res);
2493}
2494example
2495{
2496  "EXAMPLE:";echo=2;
2497  ring r=0,(x,y,z),dp;
2498  matrix D[3][3]=0;
2499  D[1,2]=-z;
2500  D[1,3]=2*x;
2501  D[2,3]=-2*y;
2502  ncalgebra(1,D); // this is U(sl_2)
2503  poly p=4*x*y+z^2-2*z;
2504  inCenter(p);
2505  poly f=4*x*y;
2506  inCenter(f);
2507  list l= list( 1, p, p^2, p^3);
2508  inCenter(l);
2509  ideal I= p, f;
2510  inCenter(I);
2511};
2512
2513
2514/******************************************************************************/
2515proc inCentralizer( def a, poly f )
2516"USAGE:   inCentralizer(a, f); a poly/list/ideal, f poly
2517RETURN:  integer (1 if a in the centralizer(f), 0 otherwise)
2518EXAMPLE: example inCentralizer; shows examples"
2519{
2520  QNF_init();
2521  def res;
2522
2523  if ( typeof(a) == "poly" )
2524    {
2525      res = inCentralizer_poly(a, f);
2526    } else
2527      {
2528        if ( (typeof(a)=="list") or (typeof(a)=="ideal") )
2529          {
2530            res = inCentralizer_list(a, f);
2531          } else
2532            {
2533              res = a;
2534            };
2535      };
2536
2537  QNF_done();
2538  return (res);
2539}
2540example
2541{
2542  "EXAMPLE:";echo=2;
2543  ring r=0,(x,y,z),dp;
2544  matrix D[3][3]=0;
2545  D[1,2]=-z;
2546  ncalgebra(1,D); // the Heisenberg algebra
2547  poly f = x^2;
2548  poly a = z; // lies in center
2549  poly b = y^2;
2550  inCentralizer(a, f);
2551  inCentralizer(b, f);
2552  list  l = list(1, a);
2553  inCentralizer(l, f);
2554  ideal I = a, b;
2555  inCentralizer(I, f);
2556};
2557
2558/******************************************************/
2559proc center(int MaxDeg, list # )
2560"USAGE:      center(MaxDeg[, N]); int MaxDeg, int N
2561RETURN:     ideal generated by found elements
2562NOTE:       computes the 'minimal' set of central elements.
2563            Since in general algorithms knows nothing about the number and degrees of
2564            desired polynomials one have to specify any kind of termination condition:
2565            1. MaxDeg - maximal degree of desired elements or/and
2566            2. n - the minimal number of desired elements to find.
2567SEE ALSO:   centralizer; inCenter
2568EXAMPLE:    example center; shows an example
2569"
2570{
2571  if ( myInt(#) > 0 ) // given a number of central elements to compute
2572    {
2573      return ( center_min_iterative( MaxDeg, # ) );
2574    };
2575
2576  if( MaxDeg >= 0 ) // standard computation - the fastest one (often)
2577    {
2578      // return ( center_min_iterative( MaxDeg, # ) );
2579      return ( center_min_vectorspace ( MaxDeg ) );
2580    };
2581
2582  print( "Error: wrong arguments." );
2583  return();
2584
2585}
2586example
2587{ "EXAMPLE:"; echo = 2;
2588 ring a=0,(x,y,z),dp;
2589 matrix D[3][3]=0;
2590 D[1,2]=-z;
2591 D[1,3]=2*x;
2592 D[2,3]=-2*y;
2593 ncalgebra(1,D); // this is U(sl_2)
2594 ideal Z = center(2); // find all central elements of degree <= 2
2595 Z;
2596 inCenter(Z);
2597 ideal ZZ = center(-1, 1 ); // find the first non trivial central element
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 found elements
2607NOTE:       computes the 'minimal' set of elements of centralizer(F).
2608            Since in general algorithms knows nothing about the number and degrees of
2609            desired polynomials one have to specify any kind of termination condition:
2610            1. MaxDeg - maximal degree of desired elements or/and
2611            2. n - the minimal number of desired elements to find.
2612SEE ALSO:   center; inCentralizer
2613EXAMPLE:    example centralizer; shows an example"
2614{
2615
2616  if( myInt(#) > 0 )
2617    {
2618      return( centralizer_min_iterative( p, MaxDeg, # ) );
2619    };
2620
2621  if( MaxDeg >= 0 )
2622    {
2623      // return( centralizer_min_iterative( p, MaxDeg, # ) );
2624      return( centralizer_min_vectorspace( p, MaxDeg ) );
2625    };
2626
2627  print( "Error: wrong arguments." );
2628  return();
2629
2630}
2631example
2632{ "EXAMPLE:"; echo = 2;
2633 ring a=0,(x,y,z),dp;
2634 matrix D[3][3]=0;
2635 D[1,2]=-z;
2636 D[1,3]=2*x;
2637 D[2,3]=-2*y;
2638 ncalgebra(1,D); // this is U(sl_2)
2639 poly f = 4*x*y+z^2-2*z; // central polynomial
2640 f;
2641 ideal c = centralizer(f, 2); // find all elements of degree <= 2 which lies in centralizer of f
2642 c;
2643 inCentralizer(c, f);
2644 ideal cc = centralizer(f, -1, 2 ); // find at least first two non trivial elements of the centralizer of f
2645 cc;
2646 inCentralizer(cc, f);
2647 poly g = z^2-2*z; // any polynomial
2648 g; "";
2649 c = centralizer(g, 2); // find all elements of degree <= 2 which lies in centralizer of g
2650 c; "";
2651 inCentralizer(c, g);
2652 cc = centralizer(g, -1, 2 ); // find at least first two non trivial elements of the centralizer of g
2653 cc; "";
2654 inCentralizer(cc, g);
2655};
Note: See TracBrowser for help on using the repository browser.