source: git/Singular/LIB/finvar.lib @ 9734571

spielwiese
Last change on this file since 9734571 was 9734571, checked in by Hans Schönemann <hannes@…>, 26 years ago
* hannes: fix to a bug in idHomModule: use pTotaldegree for pLexOrder==1 * hannes/agnes: new libray finvar.lib git-svn-id: file:///usr/local/Singular/svn/trunk@970 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 214.2 KB
Line 
1// $Header: /usr/local/Singular/cvsroot/Singular/LIB/finvar.lib,v 1.1.4.1 1997/0
27/03 15:32:03 Singular Exp $
3////////////////////////////////////////////////////////////////////////////////
4
5LIBRARY:  finvar.lib       LIBRARY TO CALCULATE INVARIANT RINGS & MORE
6                           (c) Agnes Eileen Heydtmann,
7                           send bugs and comments to agnes@math.uni-sb.de
8
9  cyclotomic(...)                        cyclotomic polynomial
10  group_reynolds(...)                    finite group and Reynolds operator
11  molien(...)                            Molien series
12  reynolds_molien(...)                   Reynolds operator and Molien series
13  partial_molien(...)                    partial expansion of Molien series
14  evaluate_reynolds(...)                 image under the Reynolds operator
15  invariant_basis(...)                   basis of homogeneous invariants
16  invariant_basis_reynolds(...)          basis of homogeneous invariants
17  primary_char0(...)                     primary invariants
18  primary_charp(...)                     primary invariants
19  primary_char0_no_molien(...)           primary invariants
20  primary_charp_no_molien(...)           primary invariants
21  primary_charp_without(...)             primary invariants
22  primary_invariants(...)                primary invariants
23  primary_char0_random(...)              primary invariants
24  primary_charp_random(...)              primary invariants
25  primary_char0_no_molien_random(...)    primary invariants
26  primary_charp_no_molien_random(...)    primary invariants
27  primary_charp_without_random(...)      primary invariants
28  primary_invariants_random(...)         primary invariants
29  power_products(...)                    exponents for power products
30  secondary_char0(...)                   secondary invariants
31  secondary_charp(...)                   secondary invariants
32  secondary_no_molien(...)               secondary invariants
33  secondary_with_irreducible_ones_no_molien(...)
34                                         secondary invariants
35  secondary_not_cohen_macaulay(...)      secondary invariants
36  invariant_ring(...)                    primary and secondary invariants
37  invariant_ring_random(...)             primary and secondary invariants
38  algebra_containment(...)               answers query of algebra containment
39  module_containment(...)                answers query of module containment
40  orbit_variety(...)                     ideal of the orbit variety
41  relative_orbit_variety(...)            ideal of a relative orbit variety
42  image_of_variety(...)                  ideal of the image of a variety
43
44////////////////////////////////////////////////////////////////////////////////
45LIB "matrix.lib";
46LIB "elim.lib";
47LIB "general.lib";
48////////////////////////////////////////////////////////////////////////////////
49
50////////////////////////////////////////////////////////////////////////////////
51// Checks whether the last parameter, being a matrix, is among the previous
52// parameters, also being matrices
53////////////////////////////////////////////////////////////////////////////////
54proc unique (list #)
55{ for (int i=1;i<size(#);i=i+1)
56  { if (#[i]==#[size(#)])
57    { return(0);
58    }
59  }
60  return(1);
61}
62
63proc cyclotomic (int i)
64USAGE:   cyclotomic(i);
65         i: an <int> > 0
66RETURNS: the i-th cyclotomic polynomial (type <poly>) as one in the first ring
67         variable
68EXAMPLE: example cyclotomic; shows an example
69THEORY:  x^i-1 is divided by the j-th cyclotomic polynomial where j takes on the
70         value of proper divisors of i
71{ if (i<=0)
72  { "ERROR:   the input should be > 0.";
73    return();
74  }
75  poly v1=var(1);
76  if (i==1)
77  { return(v1-1);                      // 1-st cyclotomic polynomial
78  }
79  poly min=v1^i-1;
80  matrix s[1][2];
81  min=min/(v1-1);                      // dividing by the 1-st cyclotomic
82                                       // polynomial
83  int j=2;
84  int n;
85  poly c;
86  int flag=1;
87  while(2*j<=i)                        // there are no proper divisors of i
88  { if ((i%j)==0)                      // greater than i/2
89    { if (flag==1)
90      { n=j;                           // n stores the first proper divisor of
91      }                                // i > 1
92      flag=0;
93      c=cyclotomic(j);                 // recursive computation
94      s=min,c;
95      s=matrix(syz(ideal(s)));         // dividing
96      min=s[2,1];
97    }
98    if (n*j==i)                        // the earliest possible point to break
99    { break;
100    }
101    j=j+1;
102  }
103  min=min/leadcoef(min);               // making sure that the leading
104  return(min);                         // coefficient is 1
105}
106example
107{ echo=2;
108          ring R=0,(x,y,z),dp;
109          print(cyclotomic(25));
110}
111
112proc group_reynolds (list #)
113USAGE:   group_reynolds(G1,G2,...[,v]);
114         G1,G2,...: nxn <matrices> generating a finite matrix group, v: an
115         optional <int>
116ASSUME:  n is the number of variables of the basering, g the number of group
117         elements
118RETURN:  a <list>, the first list element will be a gxn <matrix> representing
119         the Reynolds operator if we are in the non-modular case; if the
120         characteristic is >0, minpoly==0 and the finite group non-cyclic the
121         second list element is an <int> giving the lowest common multiple of
122         the matrix group elements (used in molien); in general all other list
123         elements are nxn <matrices> listing all elements of the finite group
124DISPLAY: information if v does not equal 0
125EXAMPLE: example group_reynolds; shows an example
126THEORY:  The entire matrix group is generated by getting all left products of
127         the generators with the new elements from the last run through the loop
128         (or the generators themselves during the first run). All the ones that
129         have been generated before are thrown out and the program terminates
130         when there are no new elements found in one run. Additionally each time
131         a new group element is found the corresponding ring mapping of which
132         the Reynolds operator is made up is generated. They are stored in the
133         rows of the first return value.
134{ int ch=char(basering);               // the existance of the Reynolds operator
135                                       // is dependent on the characteristic of
136                                       // the base field
137  int gen_num;                         // number of generators
138 //------------------------ making sure the input is okay ---------------------
139  if (typeof(#[size(#)])=="int")
140  { if (size(#)==1)
141    { "ERROR:   there are no matrices given among the parameters";
142      return();
143    }
144    int v=#[size(#)];
145    gen_num=size(#)-1;
146  }
147  else                                 // last parameter is not <int>
148  { int v=0;                           // no information is default
149    gen_num=size(#);
150  }
151  if (typeof(#[1])<>"matrix")
152  { "ERROR:   the parameters must be a list of matrices and maybe an <int>";
153    return();
154  }
155  int n=nrows(#[1]);
156  if (n<>nvars(basering))
157  { "ERROR:   the number of variables of the basering needs to be the same";
158    "         as the dimension of the matrices";
159    return();
160  }
161  if (n<>ncols(#[1]))
162  { "ERROR:   matrices need to be square and of the same dimensions";
163    return();
164  }
165  matrix vars=matrix(maxideal(1));     // creating an nx1-matrix containing the
166  vars=transpose(vars);                // variables of the ring -
167  matrix REY=#[1]*vars;                // calculating the first ring mapping -
168                                       // REY will contain the Reynolds
169                                       // operator -
170  matrix G(1)=#[1];                    // G(k) are elements of the group -
171  if (ch<>0 && minpoly==0 && gen_num<>1) // finding out of which order the group
172  { matrix I=diag(1,n);                // element is
173    matrix TEST=G(1);
174    int o1=1;
175    int o2;
176    while (TEST<>I)
177    { TEST=TEST*G(1);
178      o1=o1+1;
179    }
180  }
181  int i=1;
182 // -------------- doubles among the generators should be avoided -------------
183  for (int j=2;j<=gen_num;j=j+1)       // this loop adds the parameters to the
184  {                                    // group, leaving out doubles and
185                                       // checking whether the parameters are
186                                       // compatible with the task of the
187                                       // procedure
188    if (not(typeof(#[j])=="matrix"))
189    { "ERROR:   the parameters must be a list of matrices and maybe an <int>";
190      return();
191    }
192    if ((n!=nrows(#[j])) or (n!=ncols(#[j])))
193    { "ERROR:   matrices need to be square and of the same dimensions";
194       return();
195    }
196    if (unique(G(1..i),#[j]))
197    { i=i+1;
198      matrix G(i)=#[j];
199      if (ch<>0 && minpoly==0)         // finding out of which order the group
200      { TEST=G(i);                     // element is
201        o2=1;
202        while (TEST<>I)
203        { TEST=TEST*G(i);
204          o2=o2+1;
205        }
206        o1=o1*o2/gcd(o1,o2);           // lowest common multiple of the element
207      }                                // orders -
208      REY=concat(REY,#[j]*vars);       // adding ring homomorphisms to REY
209    }
210  }
211  int g=i;                             // G(1)..G(i) are generators without
212                                       // doubles - g generally is the number
213                                       // of elements in the group so far -
214  j=i;                                 // j is the number of new elements that
215                                       // we use as factors
216  int k, m, l;
217  if (v)
218  { "";
219    "  Generating the entire matrix group and the Reynolds operator...";
220    "";
221  }
222 // -------------- main loop that finds all the group elements ----------------
223  while (1)
224  { l=0;                               // l is the number of products we get in
225                                       // one going
226    for (m=g-j+1;m<=g;m=m+1)
227    { for (k=1;k<=i;k=k+1)
228      { l=l+1;
229        matrix P(l)=G(k)*G(m);         // possible new element
230      }
231    }
232    j=0;
233    for (k=1;k<=l;k=k+1)
234    { if (unique(G(1..g),P(k)))
235      { j=j+1;                         // a new factor for next run
236        g=g+1;
237        matrix G(g)=P(k);              // a new group element -
238        if (ch<>0 && minpoly==0 && i<>1) // finding out of which order the group
239        { TEST=G(g);                   // element is
240          o2=1;
241          while (TEST<>I)
242          { TEST=TEST*G(g);
243            o2=o2+1;
244          }
245          o1=o1*o2/gcd(o1,o2);         // lowest common multiple of the element
246        }                              // orders -
247        REY=concat(REY,P(k)*vars);     // adding new mapping to REY
248        if (v)
249        { "  Group element "+string(g)+" has been found.";
250        }
251      }
252      kill P(k);
253    }
254    if (j==0)                          // when we didn't add any new elements
255    { break;                           // in one run through the while loop
256    }                                  // we are done
257  }
258  if (v)
259  { if (g<=i)
260    { "  There are only "+string(g)+" group elements.";
261    }
262    "";
263  }
264  REY=transpose(REY);                  // when we evaluate the Reynolds operator
265                                       // later on, we actually want 1xn
266                                       // matrices
267  if (ch<>0)
268  { if ((g%ch)==0)
269    { if (voice==2)
270      { "WARNING: The characteristic of the coefficient field divides the group order.";
271        "         Proceed without the Reynolds operator!";
272      }
273      else
274      { if (v)
275        { "  The characteristic of the base field divides the group order.";
276          "  We have to continue without Reynolds operator...";
277          "";
278        }
279      }
280      kill REY;
281      matrix REY[1][1]=0;
282      return(REY,G(1..g));
283    }
284    if (minpoly==0)
285    { if (i>1)
286      { return(REY,o1,G(1..g));
287      }
288      return(REY,G(1..g));
289    }
290  }
291  if (v)
292  { "  Done generating the group and the Reynolds operator.";
293    "";
294  }
295  return(REY,G(1..g));
296}
297example
298{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
299  echo=2;
300         ring R=0,(x,y,z),dp;
301         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
302         list L=group_reynolds(A);
303         print(L[1]);
304         print(L[2..size(L)]);
305}
306
307////////////////////////////////////////////////////////////////////////////////
308// Returns i such that root^i==n, i.e. it heavily relies on the right input.
309////////////////////////////////////////////////////////////////////////////////
310proc exponent(number n, number root)
311{ int i=0;
312   while((n/root^i)<>1)
313   { i=i+1;
314   }
315   return(i);
316}
317
318proc molien (list #)
319USAGE:   molien(G1,G2,...[,ringname,lcm,flags]);
320         G1,G2,...: nxn <matrices> generating a finite matrix group, ringname:
321         a <string> giving a name for a new ring of characteristic 0 for the
322         Molien series in case of prime characteristic, lcm: an <int> giving the
323         lowest common multiple of the elements' orders in case of prime
324         characteristic, minpoly==0 and a non-cyclic group, flags: an optional
325         <intvec> with three components: if the first element is not equal to 0
326         characteristic 0 is simulated, i.e. the Molien series is computed as
327         if the base field were characteristic 0 (the user must choose a field
328         of large prime characteristic, e.g. 32003), the second component should
329         give the size of intervals between canceling common factors in the
330         expansion of the Molien series, 0 (the default) means only once after
331         generating all terms, in prime characteristic also a negative number
332         can be given to indicate that common factors should always be canceled
333         when the expansion is simple (the root of the extension field does not
334         occur among the coefficients)
335ASSUME:  n is the number of variables of the basering, G1,G2... are the group
336         elements generated by group_reynolds(), lcm is the second return value
337         of group_reynolds()
338RETURN:  in case of characteristic 0 a 1x2 <matrix> giving enumerator and
339         denominator of Molien series; in case of prime characteristic a ring
340         with the name `ringname` of characteristic 0 is created where the same
341         Molien series (named M) is stored
342DISPLAY: information if the third component of flags does not equal 0
343EXAMPLE: example molien; shows an example
344THEORY:  In characteristic 0 the terms 1/det(1-xE) for all group elements of the
345         Molien series are computed in a straight forward way. In prime
346         characteristic a Brauer lift is involved. The returned matrix gives
347         enumerator and denominator of the expanded version where common factors
348         have been canceled.
349{ def br=basering;                     // the Molien series depends on the
350  int ch=char(br);                     // characteristic of the coefficient
351                                       // field -
352  int g;                               // size of the group
353 //---------------------- making sure the input is okay -----------------------
354  if (typeof(#[size(#)])=="intvec")
355  { if (size(#[size(#)])==3)
356    { int mol_flag=#[size(#)][1];
357      if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
358      { "ERROR:   the second component of <intvec> should be >=0"
359        return();
360      }
361      int interval=#[size(#)][2];
362      int v=#[size(#)][3];
363    }
364    else
365    { "ERROR:   <intvec> should have three components";
366      return();
367    }
368    if (ch<>0)
369    { if (typeof(#[size(#)-1])=="int")
370      { int r=#[size(#)-1];
371        if (typeof(#[size(#)-2])<>"string")
372        { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
373          "         ring where the Molien series can be stored";
374          return();
375        }
376        else
377        { if (#[size(#)-2]=="")
378          { "ERROR:   <string> may not be empty";
379            return();
380          }
381          string newring=#[size(#)-2];
382          g=size(#)-3;
383        }
384      }
385      else
386      { if (typeof(#[size(#)-1])<>"string")
387        { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
388          "         ring where the Molien series can be stored";
389          return();
390        }
391        else
392        { if (#[size(#)-1]=="")
393          { "ERROR:   <string> may not be empty";
394            return();
395          }
396          string newring=#[size(#)-1];
397          g=size(#)-2;
398          int r=g;
399        }
400      }
401    }
402    else                               // then <string> ist not needed
403    { g=size(#)-1;
404    }
405  }
406  else                                 // last parameter is not <intvec>
407  { int v=0;                           // no information is default
408    int mol_flag=0;                    // computing of Molien series is default
409    int interval=0;
410    if (ch<>0)
411    { if (typeof(#[size(#)])=="int")
412      { int r=#[size(#)];
413        if (typeof(#[size(#)-1])<>"string")
414        { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
415          "         ring where the Molien series can be stored";
416            return();
417        }
418        else
419        { if (#[size(#)-1]=="")
420          { "ERROR:   <string> may not be empty";
421            return();
422          }
423          string newring=#[size(#)-1];
424          g=size(#)-2;
425        }
426      }
427      else
428      { if (typeof(#[size(#)])<>"string")
429        { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
430          "         ring where the Molien series can be stored";
431          return();
432        }
433        else
434        { if (#[size(#)]=="")
435          { "ERROR:   <string> may not be empty";
436            return();
437          }
438          string newring=#[size(#)];
439          g=size(#)-1;
440          int r=g;
441        }
442      }
443    }
444    else
445    { g=size(#);
446    }
447  }
448  if (ch<>0)
449  { if ((g/r)*r<>g)
450   { "ERROR:   <int> should divide the group order."
451      return();
452    }
453  }
454  if (ch<>0)
455  { if ((g%ch)==0)
456    { if (voice==2)
457      { "WARNING: The characteristic of the coefficient field divides the group";
458        "         order. Proceed without the Molien series!";
459      }
460      else
461      { if (v)
462        { "  The characteristic of the base field divides the group order.";
463          "  We have to continue without Molien series...";
464          "";
465        }
466      }
467    }
468    if (minpoly<>0 && mol_flag==0)
469    { if (voice==2)
470      { "WARNING: It is impossible for this program to calculate the Molien series";
471        "         for finite groups over extension fields of prime characteristic.";
472      }
473      else
474      { if (v)
475        { "  Since it is impossible for this program to calculate the Molien series for";
476          "  invariant rings over extension fields of prime characteristic, we have to";
477          "  continue without it.";
478          "";
479        }
480      }
481      return();
482    }
483  }
484 //----------------------------------------------------------------------------
485  if (not(typeof(#[1])=="matrix"))
486  { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
487    return();
488  }
489  int n=nrows(#[1]);
490  if (n<>nvars(br))
491  { "ERROR:   the number of variables of the basering needs to be the same";
492    "         as the dimension of the square matrices";
493    return();
494  }
495  if (v && voice<>2)
496  { "";
497    "  Generating the Molien series...";
498    "";
499  }
500  if (v && voice==2)
501  { "";
502  }
503 //------------- calculating Molien series in characteristic 0 ----------------
504  if (ch==0)                           // when ch==0 we can calculate the Molien
505  { matrix I=diag(1,n);                // series in any case -
506    poly v1=maxideal(1)[1];            // the Molien series will be in terms of
507                                       // the first variable of the current
508                                       // ring -
509    matrix M[1][2];                    // M will contain the Molien series -
510    M[1,1]=0;                          // M[1,1] will be the numerator -
511    M[1,2]=1;                          // M[1,2] will be the denominator -
512    matrix s;                          // will help us canceling in the
513                                       // fraction
514    poly p;                            // will contain the denominator of the
515                                       // new term of the Molien series
516 //------------ computing 1/det(1+xE) for all E in the group ------------------
517    for (int j=1;j<=g;j=j+1)
518    { if (not(typeof(#[j])=="matrix"))
519      { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
520        return();
521      }
522      if ((n<>nrows(#[j])) or (n<>ncols(#[j])))
523      { "ERROR:   matrices need to be square and of the same dimensions";
524         return();
525      }
526      p=det(I-v1*#[j]);                // denominator of new term -
527      M[1,1]=M[1,1]*p+M[1,2];          // expanding M[1,1]/M[1,2] + 1/p
528      M[1,2]=M[1,2]*p;
529      if (interval<>0)                 // canceling common terms of denominator
530      { if ((j/interval)*interval==j or j==g) // and enumerator -
531        { s=matrix(syz(ideal(M)));     // once gcd() is faster than syz() these
532          M[1,1]=-s[2,1];              // three lines should be replaced by the
533          M[1,2]=s[1,1];               // following three
534          // p=gcd(M[1,1],M[1,2]);
535          // M[1,1]=M[1,1]/p;
536          // M[1,2]=M[1,2]/p;
537        }
538      }
539      if (v)
540      { "  Term "+string(j)+" of the Molien series has been computed.";
541      }
542    }
543    if (interval==0)                   // canceling common terms of denominator
544    {                                  // and enumerator -
545      s=matrix(syz(ideal(M)));         // once gcd() is faster than syz() these
546      M[1,1]=-s[2,1];                  // three lines should be replaced by the
547      M[1,2]=s[1,1];                   // following three
548      // p=gcd(M[1,1],M[1,2]);
549      // M[1,1]=M[1,1]/p;
550      // M[1,2]=M[1,2]/p;
551    }
552    map slead=br,ideal(0);
553    s=slead(M);
554    M[1,1]=1/s[1,1]*M[1,1];            // numerator and denominator have to have
555    M[1,2]=1/s[1,2]*M[1,2];            // a constant term of 1
556    if (v)
557    { "";
558      "  We are done calculating the Molien series.";
559      "";
560    }
561    return(M);
562  }
563 //---- calculating Molien series in prime characteristic with Brauer lift ----
564  if (ch<>0 && mol_flag==0)
565  { if (g<>1)
566    { matrix G(1..g)=#[1..g];
567      if (interval<0)
568      { string Mstring;
569      }
570 //------ preparing everything for Brauer lifts into characteristic 0 ---------
571      ring Q=0,x,dp;                   // we want to extend our ring as well as
572                                       // the ring of rational numbers Q to
573                                       // contain r-th primitive roots of unity
574                                       // in order to factor characteristic
575                                       // polynomials of group elements into
576                                       // linear factors and lift eigenvalues to
577                                       // characteristic 0 -
578      poly minq=cyclotomic(r);         // minq now contains the size-of-group-th
579                                       // cyclotomic polynomial of Q, it is
580                                       // irreducible there
581      ring `newring`=(0,e),x,dp;
582      map f=Q,ideal(e);
583      minpoly=number(f(minq));         // e is now a r-th primitive root of
584                                       // unity -
585      kill Q, f;                       // no longer needed -
586      poly p=1;                        // used to build the denominator of the
587                                       // new term in the Molien series
588      matrix s[1][2];                  // used for canceling -
589      matrix M[1][2]=0,1;              // will contain Molien series -
590      ring v1br=char(br),x,dp;         // we calculate the r-th cyclotomic
591      poly minp=cyclotomic(r);         // polynomial of the base field and pick
592      minp=factorize(minp)[1][2];      // an irreducible factor of it -
593      if (deg(minp)==1)                // in this case the base field contains
594      { ring bre=char(br),x,dp;        // r-th roots of unity already
595        map f1=v1br,ideal(0);
596        number e=-number((f1(minp)));  // e is a r-th primitive root of unity
597      }
598      else
599      { ring bre=(char(br),e),x,dp;
600        map f1=v1br,ideal(e);
601        minpoly=number(f1(minp));      // e is a r-th primitive root of unity
602      }
603      map f2=br,ideal(0);              // we need f2 to map our group elements
604                                       // to this new extension field bre
605      matrix xI=diag(x,n);
606      poly p;                          // used for the characteristic polynomial
607                                       // to factor -
608      list L;                          // will contain the linear factors of the
609      ideal F;                         // characteristic polynomial of the group
610      intvec C;                        // elements and their powers
611      int i, j, k;
612 // -------------- finding all the terms of the Molien series -----------------
613      for (i=1;i<=g;i=i+1)
614      { setring br;
615        if (not(typeof(#[i])=="matrix"))
616        { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
617          return();
618        }
619        if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
620        { "ERROR:   matrices need to be square and of the same dimensions";
621           return();
622        }
623        setring bre;
624        p=det(xI-f2(G(i)));            // characteristic polynomial of G(i)
625        L=factorize(p);
626        F=L[1];
627        C=L[2];
628        for (j=2;j<=ncols(F);j=j+1)
629        { F[j]=-1*(F[j]-x);            // F[j] is now an eigenvalue of G(i),
630                                       // it is a power of a primitive r-th root
631                                       // of unity -
632          k=exponent(number(F[j]),e);  // F[j]==e^k
633          setring `newring`;
634          p=p*(1-x*(e^k))^C[j];        // building the denominator of the new
635          setring bre;                 // term
636        }
637//         -----------
638//         k=0;
639//         while(k<r)
640//         { map f3=basering,ideal(e^k);
641//           while (f3(p)==0)
642//           { p=p/(x-e^k);
643//             setring `newring`;
644//             p=p*(1-x*(e^k));        // building the denominator of the new
645//             setring bre;
646//           }
647//           kill f3;
648//           if (p==1)
649//           { break;
650//           }
651//           k=k+1;
652//         }
653        setring `newring`;
654        M[1,1]=M[1,1]*p+M[1,2];        // expanding M[1,1]/M[1,2] + 1/p
655        M[1,2]=M[1,2]*p;
656        if (interval<0)
657        { if (i<>g)
658          { Mstring=string(M);
659            for (j=1;j<=size(Mstring);j=j+1)
660            { if (Mstring[j]=="e")
661              { interval=0;
662                break;
663              }
664            }
665          }
666          if (interval<>0)
667          { s=matrix(syz(ideal(M)));   // once gcd() is faster than syz()
668            M[1,1]=-s[2,1];            // these three lines should be
669            M[1,2]=s[1,1];             // replaced by the following three
670            // p=gcd(M[1,1],M[1,2]);
671            // M[1,1]=M[1,1]/p;
672            // M[1,2]=M[1,2]/p;
673          }
674          else
675          { interval=-1;
676          }
677        }
678        else
679        { if (interval<>0)             // canceling common terms of denominator
680          { if ((i/interval)*interval==i or i==g) // and enumerator
681            { s=matrix(syz(ideal(M))); // once gcd() is faster than syz()
682              M[1,1]=-s[2,1];          // these three lines should be
683              M[1,2]=s[1,1];           // replaced by the following three
684              // p=gcd(M[1,1],M[1,2]);
685              // M[1,1]=M[1,1]/p;
686              // M[1,2]=M[1,2]/p;
687            }
688          }
689        }
690        p=1;
691        setring bre;
692        if (v)
693        { "  Term "+string(i)+" of the Molien series has been computed.";
694        }
695      }
696      if (v)
697      { "";
698      }
699      setring `newring`;
700      if (interval==0)                 // canceling common terms of denominator
701      {                                // and enumerator -
702        s=matrix(syz(ideal(M)));       // once gcd() is faster than syz() these
703        M[1,1]=-s[2,1];                // three lines should be replaced by the
704        M[1,2]=s[1,1];                 // following three
705        // p=gcd(M[1,1],M[1,2]);
706        // M[1,1]=M[1,1]/p;
707        // M[1,2]=M[1,2]/p;
708      }
709      map slead=`newring`,ideal(0);
710      s=slead(M);                      // forcing the constant term of numerator
711      M[1,1]=1/s[1,1]*M[1,1];          // and denominator to be 1
712      M[1,2]=1/s[1,2]*M[1,2];
713      kill slead;
714      kill s;
715      kill p;
716    }
717    else                               // if the group only contains an identity
718    { ring `newring`=0,x,dp;           // element, it is very easy to calculate
719      matrix M[1][2]=1,(1-x)^n;        // the Molien series
720    }
721    export `newring`;                  // we keep the ring where we computed the
722    export M;                          // Molien series in such that we can
723    setring br;                        // keep it
724    if (v)
725    { "  We are done calculating the Molien series.";
726      "";
727    }
728  }
729  else                                 // i.e. char<>0 and mol_flag<>0, the user
730  {                                    // has specified that we are dealing with
731                                       // a ring of large characteristic which
732                                       // can be treated like a ring of
733                                       // characteristic 0; we'll avoid the
734                                       // Brauer lifts
735 //----------------------- simulating characteristic 0 ------------------------
736    string chst=charstr(br);
737    for (int i=1;i<=size(chst);i=i+1)
738    { if (chst[i]==",")
739      { break;
740      }
741    }
742 //----------------- generating ring of characteristic 0 ----------------------
743    if (minpoly==0)
744    { if (i>size(chst))
745      { execute "ring "+newring+"=0,("+varstr(br)+"),("+ordstr(br)+")";
746      }
747      else
748      { chst=chst[i..size(chst)];
749        execute "ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")";
750      }
751    }
752    else
753    { string minp=string(minpoly);
754      minp=minp[2..size(minp)-1];
755      chst=chst[i..size(chst)];
756      execute "ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")";
757      execute "minpoly="+minp;
758    }
759    matrix I=diag(1,n);
760    poly v1=maxideal(1)[1];            // the Molien series will be in terms of
761                                       // the first variable of the current
762                                       // ring -
763    matrix M[1][2];                    // M will contain the Molien series -
764    M[1,1]=0;                          // M[1,1] will be the numerator -
765    M[1,2]=1;                          // M[1,2] will be the denominator -
766    matrix s;                          // will help us canceling in the
767                                       // fraction
768    poly p;                            // will contain the denominator of the
769                                       // new term of the Molien series
770    int j;
771    string links, rechts;
772 //----------------- finding all terms of the Molien series -------------------
773    for (i=1;i<=g;i=i+1)
774    { setring br;
775      if (not(typeof(#[i])=="matrix"))
776      { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
777        return();
778      }
779      if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
780      { "ERROR:   matrices need to be square and of the same dimensions";
781         return();
782      }
783      string stM(i)=string(#[i]);
784      for (j=1;j<=size(stM(i));j=j+1)
785      { if (stM(i)[j]=="
786")
787        { links=stM(i)[1..j-1];
788          rechts=stM(i)[j+1..size(stM(i))];
789          stM(i)=links+rechts;
790        }
791      }
792      setring `newring`;
793      execute "matrix G(i)["+string(n)+"]["+string(n)+"]="+stM(i);
794      p=det(I-v1*G(i));                // denominator of new term -
795      M[1,1]=M[1,1]*p+M[1,2];          // expanding M[1,1]/M[1,2] + 1/p
796      M[1,2]=M[1,2]*p;
797      if (interval<>0)                 // canceling common terms of denominator
798      { if ((i/interval)*interval==i or i==g) // and enumerator
799        {
800          s=matrix(syz(ideal(M)));     // once gcd() is faster than syz() these
801          M[1,1]=-s[2,1];              // three lines should be replaced by the
802          M[1,2]=s[1,1];               // following three
803          // p=gcd(M[1,1],M[1,2]);
804          // M[1,1]=M[1,1]/p;
805          // M[1,2]=M[1,2]/p;
806        }
807      }
808      if (v)
809      { "  Term "+string(i)+" of the Molien series has been computed.";
810      }
811    }
812    if (interval==0)                   // canceling common terms of denominator
813    {                                  // and enumerator -
814      s=matrix(syz(ideal(M)));         // once gcd() is faster than syz() these
815      M[1,1]=-s[2,1];                  // three lines should be replaced by the
816      M[1,2]=s[1,1];                   // following three
817      // p=gcd(M[1,1],M[1,2]);
818      // M[1,1]=M[1,1]/p;
819      // M[1,2]=M[1,2]/p;
820    }
821    map slead=`newring`,ideal(0);
822    s=slead(M);
823    M[1,1]=1/s[1,1]*M[1,1];            // numerator and denominator have to have
824    M[1,2]=1/s[1,2]*M[1,2];            // a constant term of 1
825    if (v)
826    { "";
827      "  We are done calculating the Molien series.";
828      "";
829    }
830    kill G(1..g), s, slead, p, v1, I;
831    export `newring`;                  // we keep the ring where we computed the
832    export M;                          // the Molien series such that we can
833    setring br;                        // keep it
834  }
835}
836example
837{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
838  "         note the case of prime characteristic";
839  echo=2;
840         ring R=0,(x,y,z),dp;
841         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
842         list L=group_reynolds(A);
843         matrix M=molien(L[2..size(L)]);
844         print(M);
845         ring S=3,(x,y,z),dp;
846         string newring="alksdfjlaskdjf";
847         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
848         list L=group_reynolds(A);
849         molien(L[2..size(L)],newring);
850         setring alksdfjlaskdjf;
851         print(M);
852         setring S;
853         kill alksdfjlaskdjf;
854}
855
856proc reynolds_molien (list #)
857USAGE:   reynolds_molien(G1,G2,...[,ringname,flags]);
858         G1,G2,...: nxn <matrices> generating a finite matrix group, ringname:
859         a <string> giving a name for a new ring of characteristic 0 for the
860         Molien series in case of prime characteristic, flags: an optional
861         <intvec> with three components: if the first element is not equal to 0
862         characteristic 0 is simulated, i.e. the Molien series is computed as
863         if the base field were characteristic 0 (the user must choose a field
864         of large prime characteristic, e.g. 32003) the second component should
865         give the size of intervals between canceling common factors in the
866         expansion of the Molien series, 0 (the default) means only once after
867         generating all terms, in prime characteristic also a negative number
868         can be given to indicate that common factors should always be canceled
869         when the expansion is simple (the root of the extension field does not
870         occur among the coefficients)
871ASSUME:  n is the number of variables of the basering, G1,G2... are the group
872         elements generated by group_reynolds(), g is the size of the group
873RETURN:  a gxn <matrix> representing the Reynolds operator is the first return
874         value and in case of characteristic 0 a 1x2 <matrix> giving enumerator
875         and denominator of Molien series is the second one; in case of prime
876         characteristic a ring with the name `ringname` of characteristic 0 is
877         created where the same Molien series (named M) is stored
878DISPLAY: information if the third component of flags does not equal 0
879EXAMPLE: example reynolds_molien; shows an example
880THEORY:  The entire matrix group is generated by getting all left products of
881         the generators with the new elements from the last run through the loop
882         (or the generators themselves during the first run). All the ones that
883         have been generated before are thrown out and the program terminates
884         when there are no new elements found in one run. Additionally each time
885         a new group element is found the corresponding ring mapping of which
886         the Reynolds operator is made up is generated. They are stored in the
887         rows of the first return value. In characteristic 0 the terms
888         1/det(1-xE) is computed whenever a new element E is found. In prime
889         characteristic a Brauer lift is involved and the terms are only
890         computed after the entire matrix group is generated (to avoid the
891         modular case). The returned matrix gives enumerator and denominator of
892         the expanded version where common factors have been canceled.
893{ def br=basering;                     // the Molien series depends on the
894  int ch=char(br);                     // characteristic of the coefficient
895                                       // field
896  int gen_num;
897 //------------------- making sure the input is okay --------------------------
898  if (typeof(#[size(#)])=="intvec")
899  { if (size(#[size(#)])==3)
900    { int mol_flag=#[size(#)][1];
901      if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
902      { "ERROR:   the second component of the <intvec> should be >=0";
903        return();
904      }
905      int interval=#[size(#)][2];
906      int v=#[size(#)][3];
907    }
908    else
909    { "ERROR:   <intvec> should have three components";
910      return();
911    }
912    if (ch<>0)
913    { if (typeof(#[size(#)-1])<>"string")
914      { "ERROR:   in characteristic p a <string> must be given for the name";
915        "         of a new ring where the Molien series can be stored";
916        return();
917      }
918      else
919      { if (#[size(#)-1]=="")
920        { "ERROR:   <string> may not be empty";
921          return();
922        }
923        string newring=#[size(#)-1];
924        gen_num=size(#)-2;
925      }
926    }
927    else                               // then <string> ist not needed
928    { gen_num=size(#)-1;
929    }
930  }
931  else                                 // last parameter is not <intvec>
932  { int v=0;                           // no information is default
933    int interval;
934    int mol_flag=0;                    // computing of Molien series is default
935    if (ch<>0)
936    { if (typeof(#[size(#)])<>"string")
937      { "ERROR:   in characteristic p a <string> must be given for the name";
938        "         of a new ring where the Molien series can be stored";
939        return();
940      }
941      else
942      { if (#[size(#)]=="")
943        { "ERROR:   <string> may not be empty";
944          return();
945        }
946        string newring=#[size(#)];
947        gen_num=size(#)-1;
948      }
949    }
950    else
951    { gen_num=size(#);
952    }
953  }
954 // ----------------- computing the terms with Brauer lift --------------------
955  if (ch<>0 && mol_flag==0)
956  { list L=group_reynolds(#[1..gen_num],v);
957    if (L[1]==0)
958    { if (voice==2)
959      { "WARNING: The characteristic of the coefficient field divides the group order.";
960        "         Proceed without the Reynolds operator or the Molien series!";
961        return();
962      }
963      if (v)
964      { "  The characteristic of the base field divides the group order.";
965        "  We have to continue without Reynolds operator or the Molien series...";
966        return();
967      }
968    }
969    if (minpoly<>0)
970    { if (voice==2)
971      { "WARNING: It is impossible for this program to calculate the Molien series";
972        "         for finite groups over extension fields of prime characteristic.";
973        return(L[1]);
974      }
975      else
976      { if (v)
977        { "  Since it is impossible for this program to calculate the Molien series for";
978          "  invariant rings over extension fields of prime characteristic, we have to";
979          "  continue without it.";
980          return(L[1]);
981        }
982      }
983    }
984    if (typeof(L[2])=="int")
985    { molien(L[3..size(L)],newring,L[2],intvec(mol_flag,interval,v));
986    }
987    else
988    { molien(L[2..size(L)],newring,intvec(mol_flag,interval,v));
989    }
990    return(L[1]);
991  }
992 //----------- computing Molien series in the straight forward way ------------
993  if (ch==0)
994  { if (typeof(#[1])<>"matrix")
995    { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
996      return();
997    }
998    int n=nrows(#[1]);
999    if (n<>nvars(br))
1000    { "ERROR:   the number of variables of the basering needs to be the same";
1001      "         as the dimension of the matrices";
1002      return();
1003    }
1004    if (n<>ncols(#[1]))
1005    { "ERROR:   matrices need to be square and of the same dimensions";
1006      return();
1007    }
1008    matrix vars=matrix(maxideal(1));   // creating an nx1-matrix containing the
1009    vars=transpose(vars);              // variables of the ring -
1010    matrix A(1)=#[1]*vars;             // calculating the first ring mapping -
1011                                       // A(1) will contain the Reynolds
1012                                       // operator -
1013    poly v1=vars[1,1];                 // the Molien series will be in terms of
1014                                       // the first variable of the current
1015                                       // ring
1016    matrix I=diag(1,n);
1017    matrix A(2)[1][2];                 // A(2) will contain the Molien series -
1018    A(2)[1,1]=1;                       // A(2)[1,1] will be the numerator
1019    matrix G(1)=#[1];                  // G(k) are elements of the group -
1020    A(2)[1,2]=det(I-v1*(G(1)));        // A(2)[1,2] will be the denominator -
1021    matrix s;                          // will help us canceling in the
1022                                       // fraction
1023    poly p;                            // will contain the denominator of the
1024                                       // new term of the Molien series
1025    int i=1;
1026    for (int j=2;j<=gen_num;j=j+1)     // this loop adds the parameters to the
1027    {                                  // group, leaving out doubles and
1028                                       // checking whether the parameters are
1029                                       // compatible with the task of the
1030                                       // procedure
1031      if (not(typeof(#[j])=="matrix"))
1032      { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
1033        return();
1034      }
1035      if ((n!=nrows(#[j])) or (n!=ncols(#[j])))
1036      { "ERROR:   matrices need to be square and of the same dimensions";
1037         return();
1038      }
1039      if (unique(G(1..i),#[j]))
1040      { i=i+1;
1041        matrix G(i)=#[j];
1042        A(1)=concat(A(1),#[j]*vars);   // adding ring homomorphisms to A(1) -
1043        p=det(I-v1*#[j]);              // denominator of new term -
1044        A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; // expanding A(2)[1,1]/A(2)[1,2] +1/p
1045        A(2)[1,2]=A(2)[1,2]*p;
1046        if (interval<>0)               // canceling common terms of denominator
1047        { if ((i/interval)*interval==i) // and enumerator
1048          {
1049            s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() these
1050            A(2)[1,1]=-s[2,1];         // three lines should be replaced by the
1051            A(2)[1,2]=s[1,1];          // following three
1052            // p=gcd(A(2)[1,1],A(2)[1,2]);
1053            // A(2)[1,1]=A(2)[1,1]/p;
1054            // A(2)[1,2]=A(2)[1,2]/p;
1055          }
1056        }
1057      }
1058    }
1059    int g=i;                           // G(1)..G(i) are generators without
1060                                       // doubles - g generally is the number
1061                                       // of elements in the group so far -
1062    j=i;                               // j is the number of new elements that
1063                                       // we use as factors
1064    int k, m, l;
1065    if (v)
1066    { "";
1067      "  Generating the entire matrix group. Whenever a new group element is found,";
1068      "  the coressponding ring homomorphism of the Reynolds operator and the";
1069      "  corresponding term of the Molien series is generated.";
1070      "";
1071    }
1072 //----------- computing 1/det(I-xE) whenever a new element E is found --------
1073    while (1)
1074    { l=0;                             // l is the number of products we get in
1075                                       // one going
1076      for (m=g-j+1;m<=g;m=m+1)
1077      { for (k=1;k<=i;k=k+1)
1078        { l=l+1;
1079          matrix P(l)=G(k)*G(m);       // possible new element
1080        }
1081      }
1082      j=0;
1083      for (k=1;k<=l;k=k+1)
1084      { if (unique(G(1..g),P(k)))
1085        { j=j+1;                       // a new factor for next run
1086          g=g+1;
1087          matrix G(g)=P(k);            // a new group element -
1088          A(1)=concat(A(1),P(k)*vars); // adding new mapping to A(1)
1089          p=det(I-v1*P(k));            // denominator of new term
1090          A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2];
1091          A(2)[1,2]=A(2)[1,2]*p;       // expanding A(2)[1,1]/A(2)[1,2] + 1/p -
1092          if (interval<>0)             // canceling common terms of denominator
1093          { if ((g/interval)*interval==g) // and enumerator
1094            {
1095              s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz()
1096              A(2)[1,1]=-s[2,1];       // these three lines should be replaced
1097              A(2)[1,2]=s[1,1];        // by the following three
1098              // p=gcd(A(2)[1,1],A(2)[1,2]);
1099              // A(2)[1,1]=A(2)[1,1]/p;
1100              // A(2)[1,2]=A(2)[1,2]/p;
1101            }
1102          }
1103          if (v)
1104          { "  Group element "+string(g)+" has been found.";
1105          }
1106        }
1107        kill P(k);
1108      }
1109      if (j==0)                        // when we didn't add any new elements
1110      { break;                         // in one run through the while loop
1111      }                                // we are done
1112    }
1113    if (v)
1114    { if (g<=i)
1115      { "  There are only "+string(g)+" group elements.";
1116      }
1117      "";
1118    }
1119    A(1)=transpose(A(1));              // when we evaluate the Reynolds operator
1120                                       // later on, we actually want 1xn
1121                                       // matrices
1122    if (interval==0)                   // canceling common terms of denominator
1123    {                                  // and enumerator -
1124      s=matrix(syz(ideal(A(2))));      // once gcd() is faster than syz()
1125      A(2)[1,1]=-s[2,1];               // these three lines should be replaced
1126      A(2)[1,2]=s[1,1];                // by the following three
1127      // p=gcd(A(2)[1,1],A(2)[1,2]);
1128      // A(2)[1,1]=A(2)[1,1]/p;
1129      // A(2)[1,2]=A(2)[1,2]/p;
1130    }
1131    if (interval<>0)                   // canceling common terms of denominator
1132    { if ((g/interval)*interval<>g)    // and enumerator
1133      {
1134        s=matrix(syz(ideal(A(2))));    // once gcd() is faster than syz()
1135        A(2)[1,1]=-s[2,1];             // these three lines should be replaced
1136        A(2)[1,2]=s[1,1];              // by the following three
1137        // p=gcd(A(2)[1,1],A(2)[1,2]);
1138        // A(2)[1,1]=A(2)[1,1]/p;
1139        // A(2)[1,2]=A(2)[1,2]/p;
1140      }
1141    }
1142    map slead=br,ideal(0);
1143    s=slead(A(2));
1144    A(2)[1,1]=1/s[1,1]*A(2)[1,1];      // numerator and denominator have to have
1145    A(2)[1,2]=1/s[1,2]*A(2)[1,2];      // a constant term of 1
1146    if (v)
1147    { "  Now we are done calculating Molien series and Reynolds operator.";
1148      "";
1149    }
1150    return(A(1..2));
1151  }
1152 //------------------------ simulating characteristic 0 -----------------------
1153  else                                 // if ch<>0 and mol_flag<>0
1154  { if (typeof(#[1])<>"matrix")
1155    { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
1156      return();
1157    }
1158    int n=nrows(#[1]);
1159    if (n<>nvars(br))
1160    { "ERROR:   the number of variables of the basering needs to be the same";
1161      "         as the dimension of the matrices";
1162      return();
1163    }
1164    if (n<>ncols(#[1]))
1165    { "ERROR:   matrices need to be square and of the same dimensions";
1166      return();
1167    }
1168    matrix vars=matrix(maxideal(1));   // creating an nx1-matrix containing the
1169    vars=transpose(vars);              // variables of the ring -
1170    matrix A(1)=#[1]*vars;             // calculating the first ring mapping -
1171                                       // A(1) will contain the Reynolds
1172                                       // operator
1173    string chst=charstr(br);
1174    for (int i=1;i<=size(chst);i=i+1)
1175    { if (chst[i]==",")
1176      { break;
1177      }
1178    }
1179    if (minpoly==0)
1180    { if (i>size(chst))
1181      { execute "ring "+newring+"=0,("+varstr(br)+"),("+ordstr(br)+")";
1182      }
1183      else
1184      { chst=chst[i..size(chst)];
1185        execute "ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")";
1186      }
1187    }
1188    else
1189    { string minp=string(minpoly);
1190      minp=minp[2..size(minp)-1];
1191      chst=chst[i..size(chst)];
1192      execute "ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")";
1193      execute "minpoly="+minp;
1194    }
1195    poly v1=var(1);                    // the Molien series will be in terms of
1196                                       // the first variable of the current
1197                                       // ring
1198    matrix I=diag(1,n);
1199    int o;
1200    setring br;
1201    matrix G(1)=#[1];
1202    string links, rechts;
1203    string stM(1)=string(#[1]);
1204    for (o=1;o<=size(stM(1));o=o+1)
1205    { if (stM(1)[o]=="
1206")
1207      { links=stM(1)[1..o-1];
1208        rechts=stM(1)[o+1..size(stM(1))];
1209        stM(1)=links+rechts;
1210      }
1211    }
1212    setring `newring`;
1213    execute "matrix G(1)["+string(n)+"]["+string(n)+"]="+stM(1);
1214    matrix A(2)[1][2];                 // A(2) will contain the Molien series -
1215    A(2)[1,1]=1;                       // A(2)[1,1] will be the numerator
1216    A(2)[1,2]=det(I-v1*(G(1)));        // A(2)[1,2] will be the denominator -
1217    matrix s;                          // will help us canceling in the
1218                                       // fraction
1219    poly p;                            // will contain the denominator of the
1220                                       // new term of the Molien series
1221    i=1;
1222    for (int j=2;j<=gen_num;j=j+1)     // this loop adds the parameters to the
1223    {                                  // group, leaving out doubles and
1224                                       // checking whether the parameters are
1225                                       // compatible with the task of the
1226                                       // procedure
1227      setring br;
1228      if (not(typeof(#[j])=="matrix"))
1229      { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
1230        return();
1231      }
1232      if ((n!=nrows(#[j])) or (n!=ncols(#[j])))
1233      { "ERROR:   matrices need to be square and of the same dimensions";
1234         return();
1235      }
1236      if (unique(G(1..i),#[j]))
1237      { i=i+1;
1238        matrix G(i)=#[j];
1239        A(1)=concat(A(1),G(i)*vars);   // adding ring homomorphisms to A(1)
1240        string stM(i)=string(G(i));
1241        for (o=1;o<=size(stM(i));o=o+1)
1242        { if (stM(i)[o]=="
1243")
1244          { links=stM(i)[1..o-1];
1245            rechts=stM(i)[o+1..size(stM(i))];
1246            stM(i)=links+rechts;
1247          }
1248        }
1249        setring `newring`;
1250        execute "matrix G(i)["+string(n)+"]["+string(n)+"]="+stM(i);
1251        p=det(I-v1*G(i));              // denominator of new term -
1252        A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; // expanding A(2)[1,1]/A(2)[1,2] +1/p
1253        A(2)[1,2]=A(2)[1,2]*p;
1254        if (interval<>0)               // canceling common terms of denominator
1255        { if ((i/interval)*interval==i) // and enumerator
1256          {
1257            s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() these
1258            A(2)[1,1]=-s[2,1];         // three lines should be replaced by the
1259            A(2)[1,2]=s[1,1];          // following three
1260            // p=gcd(A(2)[1,1],A(2)[1,2]);
1261            // A(2)[1,1]=A(2)[1,1]/p;
1262            // A(2)[1,2]=A(2)[1,2]/p;
1263          }
1264        }
1265        setring br;
1266      }
1267    }
1268    int g=i;                           // G(1)..G(i) are generators without
1269                                       // doubles - g generally is the number
1270                                       // of elements in the group so far -
1271    j=i;                               // j is the number of new elements that
1272                                       // we use as factors
1273    int k, m, l;
1274    if (v)
1275    { "";
1276      "  Generating the entire matrix group. Whenever a new group element is found,";
1277      "  the coressponding ring homomorphism of the Reynolds operator and the";
1278      "  corresponding term of the Molien series is generated.";
1279      "";
1280    }
1281 // taking all elements in a ring of characteristic 0 and computing the terms
1282 // of the Molien series there
1283    while (1)
1284    { l=0;                             // l is the number of products we get in
1285                                       // one going
1286      for (m=g-j+1;m<=g;m=m+1)
1287      { for (k=1;k<=i;k=k+1)
1288        { l=l+1;
1289          matrix P(l)=G(k)*G(m);       // possible new element
1290        }
1291      }
1292      j=0;
1293      for (k=1;k<=l;k=k+1)
1294      { if (unique(G(1..g),P(k)))
1295        { j=j+1;                       // a new factor for next run
1296          g=g+1;
1297          matrix G(g)=P(k);            // a new group element -
1298          A(1)=concat(A(1),G(g)*vars); // adding new mapping to A(1)
1299          string stM(g)=string(G(g));
1300          for (o=1;o<=size(stM(g));o=o+1)
1301          { if (stM(g)[o]=="
1302")
1303            { links=stM(g)[1..o-1];
1304              rechts=stM(g)[o+1..size(stM(g))];
1305              stM(g)=links+rechts;
1306            }
1307          }
1308          setring `newring`;
1309          execute "matrix G(g)["+string(n)+"]["+string(n)+"]="+stM(g);
1310          p=det(I-v1*G(g));            // denominator of new term
1311          A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2];
1312          A(2)[1,2]=A(2)[1,2]*p;       // expanding A(2)[1,1]/A(2)[1,2] + 1/p -
1313          if (interval<>0)             // canceling common terms of denominator
1314          { if ((g/interval)*interval==g) // and enumerator
1315            {
1316              s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz()
1317              A(2)[1,1]=-s[2,1];       // these three lines should be replaced
1318              A(2)[1,2]=s[1,1];        // by the following three
1319              // p=gcd(A(2)[1,1],A(2)[1,2]);
1320              // A(2)[1,1]=A(2)[1,1]/p;
1321              // A(2)[1,2]=A(2)[1,2]/p;
1322            }
1323          }
1324          if (v)
1325          { "  Group element "+string(g)+" has been found.";
1326          }
1327          setring br;
1328        }
1329        kill P(k);
1330      }
1331      if (j==0)                        // when we didn't add any new elements
1332      { break;                         // in one run through the while loop
1333      }                                // we are done
1334    }
1335    if (v)
1336    { if (g<=i)
1337      { "  There are only "+string(g)+" group elements.";
1338      }
1339      "";
1340    }
1341    A(1)=transpose(A(1));              // when we evaluate the Reynolds operator
1342                                       // later on, we actually want 1xn
1343                                       // matrices
1344    setring `newring`;
1345    if (interval==0)                   // canceling common terms of denominator
1346    {                                  // and enumerator -
1347      s=matrix(syz(ideal(A(2))));      // once gcd() is faster than syz()
1348      A(2)[1,1]=-s[2,1];               // these three lines should be replaced
1349      A(2)[1,2]=s[1,1];                // by the following three
1350      // p=gcd(A(2)[1,1],A(2)[1,2]);
1351      // A(2)[1,1]=A(2)[1,1]/p;
1352      // A(2)[1,2]=A(2)[1,2]/p;
1353    }
1354    if (interval<>0)                   // canceling common terms of denominator
1355    { if ((g/interval)*interval<>g)    // and enumerator
1356      {
1357        s=matrix(syz(ideal(A(2))));    // once gcd() is faster than syz()
1358        A(2)[1,1]=-s[2,1];             // these three lines should be replaced
1359        A(2)[1,2]=s[1,1];              // by the following three
1360        // p=gcd(A(2)[1,1],A(2)[1,2]);
1361        // A(2)[1,1]=A(2)[1,1]/p;
1362        // A(2)[1,2]=A(2)[1,2]/p;
1363      }
1364    }
1365    map slead=`newring`,ideal(0);
1366    s=slead(A(2));
1367    A(2)[1,1]=1/s[1,1]*A(2)[1,1];      // numerator and denominator have to have
1368    A(2)[1,2]=1/s[1,2]*A(2)[1,2];      // a constant term of 1
1369    if (v)
1370    { "  Now we are done calculating Molien series and Reynolds operator.";
1371      "";
1372    }
1373    matrix M=A(2);
1374    kill G(1..g), s, slead, p, v1, I, A(2);
1375    export `newring`;                  // we keep the ring where we computed the
1376    export M;                          // the Molien series such that we can
1377    setring br;                        // keep it
1378    return(A(1));
1379  }
1380}
1381example
1382{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
1383  "         note the case of prime characteristic";
1384  echo=2;
1385         ring R=0,(x,y,z),dp;
1386         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1387         matrix REY,M=reynolds_molien(A);
1388         print(REY);
1389         print(M);
1390         ring S=3,(x,y,z),dp;
1391         string newring="Qadjoint";
1392         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1393         matrix REY=reynolds_molien(A,newring);
1394         print(REY);
1395         setring Qadjoint;
1396         print(M);
1397         setring S;
1398         kill Qadjoint;
1399}
1400
1401proc partial_molien (matrix M, int n, list #)
1402USAGE:   partial_molien(M,n[,p]);
1403         M: a 1x2 <matrix>, n: an <int> indicating  number of terms in the
1404         expansion, p: an optional <poly>
1405ASSUME:  M is the return value of molien or the second return value of
1406         reynolds_molien, p ought to be the second return value of a previous
1407         run of partial_molien and avoids recalculating known terms
1408RETURN:  n terms (type <poly>) of the partial expansion of the Molien series
1409         (first n if there is no third parameter given, otherwise the next n
1410         terms depending on a previous calculation) and an intermediate result
1411         (type <poly>) of the calculation to be used as third parameter in a next
1412         run of partial_molien
1413THEORY:  The following calculation is implemented:
1414         (1+a1x+a2x^2+...+anx^n)/(1+b1x+b2x^2+...+bmx^m)=(1+(a1-b1)x+...
1415         (1+b1x+b2x^2+...+bmx^m)
1416         -----------------------
1417            (a1-b1)x+(a2-b2)x^2+...
1418            (a1-b1)x+b1(a1-b1)x^2+...
1419EXAMPLE: example partial_molien; shows an example
1420{ poly A(2);                           // A(2) will contain the return value of
1421                                       // the intermediate result
1422  if (char(basering)<>0)
1423  { "ERROR:   you have to change to a basering of characteristic 0, one in";
1424    "         which the Molien series is defined";
1425  }
1426  if (ncols(M)==2 && nrows(M)==1 && n>0 && size(#)<2)
1427  { def br=basering;                   // keeping track of the old ring
1428    map slead=br,ideal(0);
1429    matrix s=slead(M);
1430    if (s[1,1]<>1 || s[1,2]<>1)
1431    { "ERROR:   the constant terms of enumerator and denominator are not 1";
1432      return();
1433    }
1434
1435    if (size(#)==0)
1436    { A(2)=M[1,1];                     // if a third parameter is not given, the
1437                                       // intermediate result from the last run
1438                                       // corresponds to the numerator - we need
1439    }                                  // its smallest term
1440    else
1441    { if (typeof(#[1])=="poly")
1442      { A(2)=#[1];                     // if a third term is given we 'start'
1443      }                                // with its smallest term
1444      else
1445      { "ERROR:   <poly> as third parameter expected";
1446        return();
1447      }
1448    }
1449    poly A(1)=M[1,2];                  // denominator of Molien series (for now)
1450    string mp=string(minpoly);
1451    execute "ring R=("+charstr(br)+"),("+varstr(br)+"),ds;";
1452    execute "minpoly=number("+mp+");";
1453    poly A(1)=0;                       // A(1) will contain the sum of n terms -
1454    poly min;                          // min will be our smallest term -
1455    poly A(2)=fetch(br,A(2));          // fetching A(2) and M[1,2] into R
1456    poly den=fetch(br,A(1));
1457    for (int i=1; i<=n; i=i+1)         // getting n terms and adding them up
1458    { min=lead(A(2));
1459      A(1)=A(1)+min;
1460      A(2)=A(2)-min*den;
1461    }
1462    setring br;                        // moving A(1) and A(2) back in the
1463    A(1)=fetch(R,A(1));                // actual ring for output
1464    A(2)=fetch(R,A(2));
1465    return(A(1..2));
1466  }
1467  else
1468  { "ERROR:   the first parameter has to be a 1x2-matrix, i.e. the matrix";
1469    "         returned by the procedure 'reynolds_molien', the second one";
1470    "         should be > 0 and there should be no more than 3 parameters;"
1471    return();
1472  }
1473}
1474example
1475{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
1476  echo=2;
1477         ring R=0,(x,y,z),dp;
1478         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1479         matrix REY,M=reynolds_molien(A);
1480         poly p(1..2);
1481         p(1..2)=partial_molien(M,5);
1482         p(1);
1483         p(1..2)=partial_molien(M,5,p(2));
1484         p(1);
1485}
1486
1487proc evaluate_reynolds (matrix REY, ideal I)
1488USAGE:   evaluate_reynolds(REY,I);
1489         REY: a <matrix> representing the Reynolds operator, I: an arbitrary
1490         <ideal>
1491ASSUME:  REY is the first return value of group_reynolds() or reynolds_molien()
1492RETURNS: image of the polynomials defining I under the Reynolds operator
1493         (type <ideal>)
1494NOTE:    the characteristic of the coefficient field of the polynomial ring
1495         should not divide the order of the finite matrix group
1496EXAMPLE: example evaluate_reynolds; shows an example
1497THEORY:  REY has been constructed in such a way that each row serves as a ring
1498         mapping of which the Reynolds operator is made up.
1499{ def br=basering;
1500  int n=nvars(br);
1501  if (ncols(REY)==n)
1502  { int m=nrows(REY);                  // we need m to 'cut' the ring
1503                                       // homomorphisms 'out' of REY and to
1504                                       // divide by the group order in the end
1505    int num_poly=ncols(I);
1506    matrix MI=matrix(I);
1507    matrix MiI[1][num_poly];
1508    map pREY;
1509    matrix rowREY[1][n];
1510    for (int i=1;i<=m;i=i+1)
1511    { rowREY=REY[i,1..n];
1512      pREY=br,ideal(rowREY);           // f is now the i-th ring homomorphism
1513      MiI=pREY(MI)+MiI;
1514    }
1515    MiI=(1/number(m))*MiI;
1516    return(ideal(MiI));
1517  }
1518  else
1519  { "ERROR:   the number of columns in the <matrix> should be the same as the";
1520    "         number of variables in the basering; in fact it should be first";
1521    "         return value of group_reynolds() or reynolds_molien().";
1522    return();
1523  }
1524}
1525example
1526{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
1527  echo=2;
1528         ring R=0,(x,y,z),dp;
1529         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1530         list L=group_reynolds(A);
1531         ideal I=x2,y2,z2;
1532         print(evaluate_reynolds(L[1],I));
1533}
1534
1535proc invariant_basis (int g,list #)
1536USAGE:   invariant_basis(g,G1,G2,...);
1537         g: an <int> indicating of which degree (>0) the homogeneous basis
1538         shoud be, G1,G2,...: <matrices> generating a finite matrix group
1539RETURNS: the basis (type <ideal>) of the space of invariants of degree g
1540EXAMPLE: example invariant_basis; shows an example
1541THEORY:  A general polynomial of degree g is generated and the generators of the
1542         matrix group applied. The difference ought to be 0 and this way a
1543         system of linear equations is created. It is solved by computing
1544         syzygies.
1545{ if (g<=0)
1546  { "ERROR:   the first parameter should be > 0";
1547    return();
1548  }
1549  def br=basering;
1550  ideal mon=sort(maxideal(g))[1];      // needed for constructing a general
1551  int m=ncols(mon);                    // homogeneous polynomial of degree g
1552  mon=sort(mon,intvec(m..1))[1];
1553  int a=size(#);
1554  int i;
1555  int n=nvars(br);
1556 //---------------------- checking that the input is ok -----------------------
1557  for (i=1;i<=a;i=i+1)
1558  { if (typeof(#[i])=="matrix")
1559    { if (nrows(#[i])==n && ncols(#[i])==n)
1560      { matrix G(i)=#[i];
1561      }
1562      else
1563      { "ERROR:   the number of variables of the base ring needs to be the same";
1564        "         as the dimension of the square matrices";
1565        return();
1566      }
1567    }
1568    else
1569    { "ERROR:   the last parameters should be a list of matrices";
1570      return();
1571    }
1572  }
1573 //----------------------------------------------------------------------------
1574  execute "ring T=("+charstr(br)+"),("+varstr(br)+",p(1..m)),lp;";
1575  // p(1..m) are the general coefficients of the general polynomial of degree g
1576  execute "ideal vars="+varstr(br)+";";
1577  map f;
1578  ideal mon=imap(br,mon);
1579  poly P=0;
1580  for (i=m;i>=1;i=i-1)
1581  { P=P+p(i)*mon[i];                   // P is the general polynomial
1582  }
1583  ideal I;                             // will help substituting variables in P
1584                                       // by linear combinations of variables -
1585  poly Pnew,temp;                      // Pnew is P with substitutions -
1586  matrix S[m*a][m];                    // will contain system of linear
1587                                       // equations
1588  int j,k;
1589 //------------------- building the system of linear equations ----------------
1590  for (i=1;i<=a;i=i+1)
1591  { I=ideal(matrix(vars)*transpose(imap(br,G(i))));
1592    I=I,p(1..m);
1593    f=T,I;
1594    Pnew=f(P);
1595    for (j=1;j<=m;j=j+1)
1596    { temp=P/mon[j]-Pnew/mon[j];
1597      for (k=1;k<=m;k=k+1)
1598      { S[m*(i-1)+j,k]=temp/p(k);
1599      }
1600    }
1601  }
1602 //----------------------------------------------------------------------------
1603  setring br;
1604  map f=T,ideal(0);
1605  matrix S=f(S);
1606  matrix s=matrix(syz(S));             // s contains a basis of the space of
1607                                       // solutions -
1608  ideal I=ideal(matrix(mon)*s);        // I contains a basis of homogeneous
1609  if (I[1]<>0)                         // invariants of degree d
1610  { for (i=1;i<=ncols(I);i=i+1)
1611    { I[i]=I[i]/leadcoef(I[i]);        // setting leading coefficients to 1
1612    }
1613  }
1614  return(I);
1615}
1616example
1617{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
1618  echo=2;
1619           ring R=0,(x,y,z),dp;
1620           matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1621           print(invariant_basis(2,A));
1622}
1623
1624proc invariant_basis_reynolds (matrix REY,int d,list #)
1625USAGE:   invariant_basis_reynolds(REY,d[,flags]);
1626         REY: a <matrix> representing the Reynolds operator, d: an <int>
1627         indicating of which degree (>0) the homogeneous basis shoud be, flags:
1628         an optional <intvec> with two entries: its first component gives the
1629         dimension of the space (default <0 meaning unknown) and its second
1630         component is used as the number of polynomials that should be mapped
1631         to invariants during one call of evaluate_reynolds if the dimension of
1632         the space is unknown or the number such that number x dimension
1633         polynomials are mapped to invariants during one call of
1634         evaluate_reynolds
1635ASSUME:  REY is the first return value of group_reynolds() or reynolds_molien()
1636         and flags[1] given by partial_molien
1637RETURN:  the basis (type <ideal>) of the space of invariants of degree d
1638EXAMPLE: example invariant_basis_reynolds; shows an example
1639THEORY:  Monomials of degree d are mapped to invariants with the Reynolds
1640         operator. A linearly independent set is generated with the help of
1641         minbase.
1642{
1643 //---------------------- checking that the input is ok -----------------------
1644  if (d<=0)
1645  { "  ERROR:   the second parameter should be > 0";
1646     return();
1647  }
1648  if (size(#)>1)
1649  { "  ERROR:   there should be at most three parameters";
1650    return();
1651  }
1652  if (size(#)==1)
1653  { if (typeof(#[1])<>"intvec")
1654    { "  ERROR: the third parameter should be of type <intvec>";
1655      return();
1656    }
1657    if (size(#[1])<>2)
1658    { "  ERROR: there should be two components in <intvec>";
1659      return();
1660    }
1661    else
1662    { int cd=#[1][1];
1663      int step_fac=#[1][2];
1664    }
1665    if (step_fac<=0)
1666    { "  ERROR: the second component of <intvec> should be > 0";
1667      return();
1668    }
1669    if (cd==0)
1670    { return(ideal(0));
1671    }
1672  }
1673  else
1674  { int step_fac=1;
1675    int cd=-1;
1676  }
1677  if (ncols(REY)<>nvars(basering))
1678  { "ERROR:   the number of columns in the <matrix> should be the same as the";
1679    "         number of variables in the basering; in fact it should be first";
1680    "         return value of group_reynolds() or reynolds_molien().";
1681    return();
1682  }
1683 //----------------------------------------------------------------------------
1684  ideal mon=sort(maxideal(d))[1];
1685  degBound=d;
1686  int j=ncols(mon);
1687  mon=sort(mon,intvec(j..1))[1];
1688  ideal B;                             // will contain the basis
1689  if (cd<0)
1690  { if (step_fac>j)                    // all of mon will be mapped to
1691    { B=evaluate_reynolds(REY,mon);    // invariants at once
1692      B=minbase(B);
1693      degBound=0;
1694      return(B);
1695    }
1696  }
1697  else
1698  { if (step_fac*cd>j)                 // all of mon will be mapped to
1699    { B=evaluate_reynolds(REY,mon);    // invariants at once
1700      B=minbase(B);
1701      degBound=0;
1702      return(B);
1703    }
1704  }
1705  int i,k;
1706  int upper_bound=0;
1707  int lower_bound=0;
1708  ideal part_mon;                      // a part of mon of size step_fac*cd
1709  while (1)
1710  { lower_bound=upper_bound+1;
1711    if (cd<0)
1712    { upper_bound=upper_bound+step_fac;
1713    }
1714    else
1715    { upper_bound=upper_bound+step_fac*cd;
1716    }
1717    if (upper_bound>j)
1718    { upper_bound=j;
1719    }
1720    part_mon=mon[lower_bound..upper_bound];
1721    B=minbase(B+evaluate_reynolds(REY,part_mon));
1722    if (ncols(B)==cd or upper_bound==j)
1723    { degBound=0;
1724      return(B);
1725    }
1726  }
1727}
1728example
1729{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
1730  echo=2;
1731           ring R=0,(x,y,z),dp;
1732           matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
1733           intvec flags=0,1,0;
1734           matrix REY,M=reynolds_molien(A,flags);
1735           flags=8,6;
1736           print(invariant_basis_reynolds(REY,6,flags));
1737}
1738
1739////////////////////////////////////////////////////////////////////////////////
1740// This procedure generates linearly independent invariant polynomials of degree
1741// d that do not reduce to 0 modulo the primary invariants. It does this by
1742// applying the Reynolds operator to the monomials returned by kbase(sP,d). The
1743// result is used when computing secondary invariants.
1744////////////////////////////////////////////////////////////////////////////////
1745proc sort_of_invariant_basis (ideal sP,matrix REY,int d,int step_fac)
1746{ ideal mon=kbase(sP,d);
1747  degBound=d;
1748  int j=ncols(mon);
1749  int i;
1750  mon=sort(mon,intvec(j..1))[1];
1751  ideal B;                             // will contain the "sort of basis"
1752  if (step_fac>j)
1753  { B=compress(evaluate_reynolds(REY,mon));
1754    for (i=1;i<=ncols(B);i=i+1)        // those are taken our that are o mod sP
1755    { if (reduce(B[i],sP)==0)
1756      { B[i]=0;
1757      }
1758    }
1759    B=minbase(B);                      // here are the linearly independent ones
1760    degBound=0;
1761    return(B);
1762  }
1763  int upper_bound=0;
1764  int lower_bound=0;
1765  ideal part_mon;                      // parts of mon
1766  while (1)
1767  { lower_bound=upper_bound+1;
1768    upper_bound=upper_bound+step_fac;
1769    if (upper_bound>j)
1770    { upper_bound=j;
1771    }
1772    part_mon=mon[lower_bound..upper_bound];
1773    part_mon=compress(evaluate_reynolds(REY,part_mon));
1774    for (i=1;i<=ncols(part_mon);i=i+1)
1775    { if (reduce(part_mon[i],sP)==0)
1776      { part_mon[i]=0;
1777      }
1778    }
1779    B=minbase(B+part_mon);             // here are the linearly independent ones
1780    if (upper_bound==j)
1781    { degBound=0;
1782      return(B);
1783    }
1784  }
1785}
1786
1787////////////////////////////////////////////////////////////////////////////////
1788// Procedure returning the succeeding vector after vec. It is used to list
1789// all the vectors of Z^n with first nonzero entry 1. They are listed by
1790// increasing sum of the absolute value of their entries.
1791////////////////////////////////////////////////////////////////////////////////
1792proc next_vector(intmat vec)
1793{ int n=ncols(vec);                    // p: >0, n: <0, p0: >=0, n0: <=0
1794  for (int i=1;i<=n;i=i+1)             // finding out which is the first
1795  { if (vec[1,i]<>0)                   // component <>0
1796    { break;
1797    }
1798  }
1799  intmat new[1][n];
1800  if (i>n)                             // 0,...,0 --> 1,0....,0
1801  { new[1,1]=1;
1802    return(new);
1803  }
1804  if (i==n)                            // 0,...,1 --> 1,1,0,...,0
1805  { new[1,1..2]=1,1;
1806    return(new);
1807  }
1808  if (i==n-1)
1809  { if (vec[1,n]==0)                   // 0,...,0,1,0 --> 0,...,0,1
1810    { new[1,n]=1;
1811      return(new);
1812    }
1813    if (vec[1,n]>0)                    // 0,..,0,1,p --> 0,...,0,1,-p
1814    { new[1,1..n]=vec[1,1..n-1],-vec[1,n];
1815      return(new);
1816    }
1817    new[1,1..2]=1,1-vec[1,n];          // 0,..,0,1,n --> 1,1-n,0,..,0
1818    return(new);
1819  }
1820  if (i>1)
1821  { intmat temp[1][n-i+1]=vec[1,i..n]; // 0,...,0,1,*,...,* --> 1,*,...,*
1822    temp=next_vector(temp);
1823    new[1,i..n]=temp[1,1..n-i+1];
1824    return(new);
1825  }                                    // case left: 1,*,...,*
1826  for (i=2;i<=n;i=i+1)
1827  { if (vec[1,i]>0)                    // make first positive negative and
1828    { vec[1,i]=-vec[1,i];              // return
1829      return(vec);
1830    }
1831    else
1832    { vec[1,i]=-vec[1,i];              // make all negatives before positives
1833    }                                  // positive
1834  }
1835  for (i=2;i<=n-1;i=i+1)               // case: 1,p,...,p after 1,n,...,n
1836  { if (vec[1,i]>0)
1837    { vec[1,2]=vec[1,i]-1;             // shuffleing things around...
1838      if (i>2)                         // same sum of absolute values of entries
1839      { vec[1,i]=0;
1840      }
1841      vec[1,i+1]=vec[1,i+1]+1;
1842      return(vec);
1843    }
1844  }                                    // case left: 1,0,...,0 --> 1,1,0,...,0
1845  new[1,2..3]=1,vec[1,n];              // and: 1,0,...,0,1 --> 0,1,1,0,...,0
1846  return(new);
1847}
1848
1849////////////////////////////////////////////////////////////////////////////////
1850// Maps integers to elements of the base field. It is only called if the base
1851// field is of prime characteristic. If the base field has q elements (depending
1852// on minpoly) 1..q is mapped to those q elements.
1853////////////////////////////////////////////////////////////////////////////////
1854proc int_number_map (int i)
1855{ int p=char(basering);
1856  if (minpoly==0)                      // if no minpoly is given, we have p
1857  { i=i%p;                             // elements in the field
1858    return(number(i));
1859  }
1860  int d=pardeg(minpoly);
1861  if (i<0)
1862  { int bool=1;
1863    i=(-1)*i;
1864  }
1865  i=i%p^d;                             // base field has p^d elements -
1866  number a=par(1);                     // a is the root of the minpoly - we have
1867  number out=0;                        // to construct a linear combination of
1868  int j=1;                             // a^k
1869  int k;
1870  while (1)
1871  { if (i<p^j)                         // finding an upper bound on i
1872    { for (k=0;k<j-1;k=k+1)
1873      { out=out+((i/p^k)%p)*a^k;       // finding how often p^k is contained in
1874      }                                // i
1875      out=out+(i/p^(j-1))*a^(j-1);
1876      if (defined(bool)==voice)
1877      { return((-1)*out);
1878      }
1879      return(out);
1880    }
1881    j=j+1;
1882  }
1883}
1884
1885////////////////////////////////////////////////////////////////////////////////
1886// This procedure finds dif primary invariants in degree d. It returns all
1887// primary invariants found so far. The coefficients lie in a field of
1888// characteristic 0.
1889////////////////////////////////////////////////////////////////////////////////
1890proc search (int n,int d,ideal B,int cd,ideal P,ideal sP,int i,int dif,int dB,ideal CI)
1891{ intmat vec[1][cd];                   // the coefficients for the next
1892                                       // combination -
1893  degBound=0;
1894  poly test_poly;                      // the linear combination to test
1895  int test_dim;
1896  intvec h;                            // Hilbert series
1897  int j=i+1;
1898  matrix tB=transpose(B);
1899  ideal TEST;
1900  while(j<=i+dif)
1901  { CI=CI+ideal(var(j)^d);             // homogeneous polynomial of the same
1902                                       // degree as the one we're looking for is
1903                                       // added
1904    // h=hilb(std(CI),1);
1905    dB=dB+d-1;                         // used as degBound
1906    while(1)
1907    { vec=next_vector(vec);            // next vector
1908      test_poly=(vec*tB)[1,1];
1909      // degBound=dB;
1910      TEST=sP+ideal(test_poly);
1911      attrib(TEST,"isSB",1);
1912      test_dim=dim(TEST);
1913      // degBound=0;
1914      if (n-test_dim==j)               // the dimension has been lowered by one
1915      { sP=TEST;
1916        break;
1917      }
1918      // degBound=dB;
1919      TEST=std(sP+ideal(test_poly));   // should soon be replaced by next line
1920      // TEST=std(sP,test_poly,h);        // Hilbert driven std-calculation
1921      test_dim=dim(TEST);
1922      // degBound=0;
1923      if (n-test_dim==j)               // the dimension has been lowered by one
1924      { sP=TEST;
1925        break;
1926      }
1927    }
1928    P[j]=test_poly;                    // test_poly ist added to primary
1929    j=j+1;                             // invariants
1930  }
1931  return(P,sP,CI,dB);
1932}
1933
1934////////////////////////////////////////////////////////////////////////////////
1935// This procedure finds at most dif primary invariants in degree d. It returns
1936// all primary invariants found so far. The coefficients lie in the field of
1937// characteristic p>0.
1938////////////////////////////////////////////////////////////////////////////////
1939proc p_search (int n,int d,ideal B,int cd,ideal P,ideal sP,int i,int dif,int dB,ideal CI)
1940{ def br=basering;
1941  degBound=0;
1942  matrix vec(1)[1][cd];                // starting with 0-vector -
1943  intmat new[1][cd];                   // the coefficients for the next
1944                                       // combination -
1945  matrix pnew[1][cd];                  // new needs to be mapped into br -
1946  int counter=1;                       // counts the vectors
1947  int j;
1948  int p=char(br);
1949  if (minpoly<>0)
1950  { int ext_deg=pardeg(minpoly);       // field has p^d elements
1951  }
1952  else
1953  { int ext_deg=1;                     // field has p^d elements
1954  }
1955  poly test_poly;                      // the linear combination to test
1956  int test_dim;
1957  ring R=0,x,dp;                       // just to calculate next variable
1958                                       // bound -
1959  number bound=(number(p)^(ext_deg*cd)-1)/(number(p)^ext_deg-1)+1; // this is
1960                                       // how many linearly independent vectors
1961                                       // of size cd exist having entries in the
1962                                       // base field of br
1963  setring br;
1964  intvec h;                            // Hilbert series
1965  int k=i+1;
1966  matrix tB=transpose(B);
1967  ideal TEST;
1968  while (k<=i+dif)
1969  { CI=CI+ideal(var(k)^d);             // homogeneous polynomial of the same
1970                                       // degree as the one we're looking for is
1971                                       // added
1972    // h=hilb(std(CI),1);
1973    dB=dB+d-1;                         // used as degBound
1974    setring R;
1975    while (number(counter)<>bound)     // otherwise, we are done
1976    { setring br;
1977      new=next_vector(new);
1978      for (j=1;j<=cd;j=j+1)
1979      { pnew[1,j]=int_number_map(new[1,j]); // mapping an integer into br
1980      }
1981      if (unique(vec(1..counter),pnew)) // checking whether we tried pnew before
1982      { counter=counter+1;
1983        matrix vec(counter)=pnew;      // keeping track of the ones we tried -
1984        test_poly=(vec(counter)*tB)[1,1]; // linear combination -
1985        // degBound=dB;
1986        TEST=sP+ideal(test_poly);
1987        attrib(TEST,"isSB",1);
1988        test_dim=dim(TEST);
1989        // degBound=0;
1990        if (n-test_dim==k)             // the dimension has been lowered by one
1991        { sP=TEST;
1992          setring R;
1993          break;
1994        }
1995        // degBound=dB;
1996        TEST=std(sP+ideal(test_poly)); // should soon to be replaced by next
1997                                       // line
1998        // TEST=std(sP,test_poly,h);      // Hilbert driven std-calculation
1999        test_dim=dim(TEST);
2000        // degBound=0;
2001        if (n-test_dim==k)             // the dimension has been lowered by one
2002        { sP=TEST;
2003          setring R;
2004          break;
2005        }
2006      }
2007      setring R;
2008    }
2009    if (number(counter)<=bound)
2010    { setring br;
2011      P[k]=test_poly;                  // test_poly ist added to primary
2012    }                                  // invariants
2013    else
2014    { setring br;
2015      CI=CI[1..size(CI)-1];
2016      return(P,sP,CI,dB-d+1);
2017    }
2018    k=k+1;
2019  }
2020  return(P,sP,CI,dB);
2021}
2022
2023proc primary_char0 (matrix REY,matrix M,list #)
2024USAGE:   primary_char0(REY,M[,v]);
2025         REY: a <matrix> representing the Reynolds operator, M: a 1x2 <matrix>
2026         representing the Molien series, v: an optional <int>
2027ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
2028         M the one of molien or the second one of reynolds_molien
2029DISPLAY: information about the various stages of the programme if v does not
2030         equal 0
2031RETURN:  primary invariants (type <matrix>) of the invariant ring
2032EXAMPLE: example primary_char0; shows an example
2033THEORY:  Bases of homogeneous invariants are generated successively and those
2034         are chosen as primary invariants that lower the dimension of the ideal
2035         generated by the previously found invariants (see paper "Generating a
2036         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2037         Decker, Heydtmann, Schreyer (1997) to appear in JSC).
2038{ degBound=0;
2039  if (char(basering)<>0)
2040  { "ERROR:   primary_char0 should only be used with rings of characteristic 0.";
2041    return();
2042  }
2043 //----------------- checking input and setting verbose mode ------------------
2044  if (size(#)>1)
2045  { "ERROR:   primary_char0 can only have three parameters.";
2046    return();
2047  }
2048  if (size(#)==1)
2049  { if (typeof(#[1])<>"int")
2050    { "ERROR:   The third parameter should be of type <int>.";
2051      return();
2052    }
2053    else
2054    { int v=#[1];
2055    }
2056  }
2057  else
2058  { int v=0;
2059  }
2060  int n=nvars(basering);               // n is the number of variables, as well
2061                                       // as the size of the matrices, as well
2062                                       // as the number of primary invariants,
2063                                       // we should get
2064  if (ncols(REY)<>n)
2065  { "ERROR:   First parameter ought to be the Reynolds operator."
2066    return();
2067  }
2068  if (ncols(M)<>2 or nrows(M)<>1)
2069  { "ERROR:   Second parameter ought to be the Molien series."
2070    return();
2071  }
2072 //----------------------------------------------------------------------------
2073  if (v && voice<>2)
2074  { "  We can start looking for primary invariants...";
2075    "";
2076  }
2077  if (v && voice==2)
2078  { "";
2079  }
2080 //------------------------- initializing variables ---------------------------
2081  int dB;
2082  poly p(1..2);                        // p(1) will be used for single terms of
2083                                       // the partial expansion, p(2) to store
2084  p(1..2)=partial_molien(M,1);         // the intermediate result -
2085  poly v1=var(1);                      // we need v1 to split off coefficients
2086                                       // in the partial expansion of M (which
2087                                       // is in terms of the first variable) -
2088  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
2089                                       // space of invariants of degree d,
2090                                       // newdim: dimension the ideal generated
2091                                       // the primary invariants plus basis
2092                                       // elements, dif=n-i-newdim, i.e. the
2093                                       // number of new primary invairants that
2094                                       // should be added in this degree -
2095  ideal P,Pplus,sPplus,CI,B;           // P: will contain primary invariants,
2096                                       // Pplus: P+B, CI: a complete
2097                                       // intersection with the same Hilbert
2098                                       // function as P
2099  ideal sP=std(P);
2100  dB=1;                                // used as degree bound
2101  int i=0;
2102 //-------------- loop that searches for primary invariants  ------------------
2103  while(1)                             // repeat until n primary invariants are
2104  {                                    // found -
2105    p(1..2)=partial_molien(M,1,p(2));  // next term of the partial expansion -
2106    d=deg(p(1));                       // degree where we'll search -
2107    cd=int(coef(p(1),v1)[2,1]);        // dimension of the homogeneous space of
2108                                       // inviarants of degree d
2109    if (v)
2110    { "  Computing primary invariants in degree "+string(d)+":";
2111    }
2112    B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of
2113                                       // degree d
2114    if (B[1]<>0)
2115    { Pplus=P+B;
2116      sPplus=std(Pplus);
2117      newdim=dim(sPplus);
2118      dif=n-i-newdim;
2119    }
2120    else
2121    { dif=0;
2122    }
2123    if (dif<>0)                        // we have to find dif new primary
2124    {                                  // invariants
2125      if (cd<>dif)
2126      { P,sP,CI,dB=search(n,d,B,cd,P,sP,i,dif,dB,CI); // searching for dif invariants
2127      }                                // i.e. we can take all of B
2128      else
2129      { for(j=i+1;j>i+dif;j=j+1)
2130        { CI=CI+ideal(var(j)^d);
2131        }
2132        dB=dB+dif*(d-1);
2133        P=Pplus;
2134        sP=sPplus;
2135      }
2136      if (v)
2137      { for (j=1;j<=dif;j=j+1)
2138        { "  We find: "+string(P[i+j]);
2139        }
2140      }
2141      i=i+dif;
2142      if (i==n)                        // found all primary invariants
2143      { if (v)
2144        { "";
2145          "  We found all primary invariants.";
2146          "";
2147        }
2148        return(matrix(P));
2149      }
2150    }                                  // done with degree d
2151  }
2152}
2153example
2154{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
2155  echo=2;
2156         ring R=0,(x,y,z),dp;
2157         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2158         matrix REY,M=reynolds_molien(A);
2159         matrix P=primary_char0(REY,M);
2160         print(P);
2161}
2162
2163proc primary_charp (matrix REY,string ring_name,list #)
2164USAGE:   primary_charp(REY,ringname[,v]);
2165         REY: a <matrix> representing the Reynolds operator, ringname: a
2166         <string> giving the name of a ring where the Molien series is stored,
2167         v: an optional <int>
2168ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
2169         ringname gives the name of a ring of characteristic 0 that has been
2170         created by molien or reynolds_molien
2171DISPLAY: information about the various stages of the programme if v does not
2172         equal 0
2173RETURN:  primary invariants (type <matrix>) of the invariant ring
2174EXAMPLE: example primary_charp; shows an example
2175THEORY:  Bases of homogeneous invariants are generated successively and those
2176         are chosen as primary invariants that lower the dimension of the ideal
2177         generated by the previously found invariants (see paper "Generating a
2178         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2179         Decker, Heydtmann, Schreyer (1997) to appear in JSC).
2180{ degBound=0;
2181// ---------------- checking input and setting verbose mode -------------------
2182  if (char(basering)==0)
2183  { "ERROR:   primary_charp should only be used with rings of characteristic p>0.";
2184    return();
2185  }
2186  if (size(#)>1)
2187  { "ERROR:   primary_charp can only have three parameters.";
2188    return();
2189  }
2190  if (size(#)==1)
2191  { if (typeof(#[1])<>"int")
2192    { "ERROR:   The third parameter should be of type <int>.";
2193      return();
2194    }
2195    else
2196    { int v=#[1];
2197    }
2198  }
2199  else
2200  { int v=0;
2201  }
2202  def br=basering;
2203  int n=nvars(br);                     // n is the number of variables, as well
2204                                       // as the size of the matrices, as well
2205                                       // as the number of primary invariants,
2206                                       // we should get
2207  if (ncols(REY)<>n)
2208  { "ERROR:   First parameter ought to be the Reynolds operator."
2209    return();
2210  }
2211  if (typeof(`ring_name`)<>"ring")
2212  { "ERROR:   Second parameter ought to the name of a ring where the Molien";
2213    "         is stored.";
2214    return();
2215  }
2216 //----------------------------------------------------------------------------
2217  if (v && voice<>2)
2218  { "  We can start looking for primary invariants...";
2219    "";
2220  }
2221  if (v && voice==2)
2222  { "";
2223  }
2224 //----------------------- initializing variables -----------------------------
2225  int dB;
2226  setring `ring_name`;                 // the Molien series is stores here -
2227  poly p(1..2);                        // p(1) will be used for single terms of
2228                                       // the partial expansion, p(2) to store
2229  p(1..2)=partial_molien(M,1);         // the intermediate result -
2230  poly v1=var(1);                      // we need v1 to split off coefficients
2231                                       // in the partial expansion of M (which
2232                                       // is in terms of the first variable)
2233  setring br;
2234  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
2235                                       // space of invariants of degree d,
2236                                       // newdim: dimension the ideal generated
2237                                       // the primary invariants plus basis
2238                                       // elements, dif=n-i-newdim, i.e. the
2239                                       // number of new primary invairants that
2240                                       // should be added in this degree -
2241  ideal P,Pplus,sPplus,CI,B;           // P: will contain primary invariants,
2242                                       // Pplus: P+B, CI: a complete
2243                                       // intersection with the same Hilbert
2244                                       // function as P
2245  ideal sP=std(P);
2246  dB=1;                                // used as degree bound
2247  int i=0;
2248 //---------------- loop that searches for primary invariants -----------------
2249  while(1)                             // repeat until n primary invariants are
2250  {                                    // found
2251    setring `ring_name`;
2252    p(1..2)=partial_molien(M,1,p(2));  // next term of the partial expansion -
2253    d=deg(p(1));                       // degree where we'll search -
2254    cd=int(coef(p(1),v1)[2,1]);        // dimension of the homogeneous space of
2255                                       // inviarants of degree d
2256    setring br;
2257    if (v)
2258    { "  Computing primary invariants in degree "+string(d)+":";
2259    }
2260    B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of
2261                                       // degree d
2262    if (B[1]<>0)
2263    { Pplus=P+B;
2264      sPplus=std(Pplus);
2265      newdim=dim(sPplus);
2266      dif=n-i-newdim;
2267    }
2268    else
2269    { dif=0;
2270    }
2271    if (dif<>0)                        // we have to find dif new primary
2272    {                                  // invariants
2273      if (cd<>dif)
2274      { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI);
2275      }
2276      else                             // i.e. we can take all of B
2277      { for(j=i+1;j>i+dif;j=j+1)
2278        { CI=CI+ideal(var(j)^d);
2279        }
2280        dB=dB+dif*(d-1);
2281        P=Pplus;
2282        sP=sPplus;
2283      }
2284      if (v)
2285      { for (j=1;j<=size(P)-i;j=j+1)
2286        { "  We find: "+string(P[i+j]);
2287        }
2288      }
2289      i=size(P);
2290      if (i==n)                        // found all primary invariants
2291      { if (v)
2292        { "";
2293          "  We found all primary invariants.";
2294          "";
2295        }
2296        return(matrix(P));
2297      }
2298    }                                  // done with degree d
2299  }
2300}
2301example
2302{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into";
2303  "         characteristic 3)";
2304  echo=2;
2305         ring R=3,(x,y,z),dp;
2306         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2307         list L=group_reynolds(A);
2308         string newring="alskdfj";
2309         molien(L[2..size(L)],newring);
2310         matrix P=primary_charp(L[1],newring);
2311         kill `newring`;
2312         print(P);
2313}
2314
2315proc primary_char0_no_molien (matrix REY, list #)
2316USAGE:   primary_char0_no_molien(REY[,v]);
2317         REY: a <matrix> representing the Reynolds operator, v: an optional
2318         <int>
2319ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
2320DISPLAY: information about the various stages of the programme if v does not
2321         equal 0
2322RETURN:  primary invariants (type <matrix>) of the invariant ring and an
2323         <intvec> listing some of the degrees where no non-trivial homogeneous
2324         invariants are to be found
2325EXAMPLE: example primary_char0_no_molien; shows an example
2326THEORY:  Bases of homogeneous invariants are generated successively and those
2327         are chosen as primary invariants that lower the dimension of the ideal
2328         generated by the previously found invariants (see paper "Generating a
2329         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2330         Decker, Heydtmann, Schreyer (1997) to appear in JSC).
2331{ degBound=0;
2332 //-------------- checking input and setting verbose mode ---------------------
2333  if (char(basering)<>0)
2334  { "ERROR:   primary_char0_no_molien should only be used with rings of";
2335    "         characteristic 0.";
2336    return();
2337  }
2338  if (size(#)>1)
2339  { "ERROR:   primary_char0_no_molien can only have two parameters.";
2340    return();
2341  }
2342  if (size(#)==1)
2343  { if (typeof(#[1])<>"int")
2344    { "ERROR:   The second parameter should be of type <int>.";
2345      return();
2346    }
2347    else
2348    { int v=#[1];
2349    }
2350  }
2351  else
2352  { int v=0;
2353  }
2354  int n=nvars(basering);               // n is the number of variables, as well
2355                                       // as the size of the matrices, as well
2356                                       // as the number of primary invariants,
2357                                       // we should get
2358  if (ncols(REY)<>n)
2359  { "ERROR:   First parameter ought to be the Reynolds operator."
2360    return();
2361  }
2362 //----------------------------------------------------------------------------
2363  if (v && voice<>2)
2364  { "  We can start looking for primary invariants...";
2365    "";
2366  }
2367  if (v && voice==2)
2368  { "";
2369  }
2370 //----------------------- initializing variables -----------------------------
2371  int dB;
2372  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
2373                                       // space of invariants of degree d,
2374                                       // newdim: dimension the ideal generated
2375                                       // the primary invariants plus basis
2376                                       // elements, dif=n-i-newdim, i.e. the
2377                                       // number of new primary invairants that
2378                                       // should be added in this degree -
2379  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
2380                                       // Pplus: P+B, CI: a complete
2381                                       // intersection with the same Hilbert
2382                                       // function as P
2383  ideal sP=std(P);
2384  dB=1;                                // used as degree bound -
2385  d=0;                                 // initializing
2386  int i=0;
2387  intvec deg_vector;
2388 //------------------ loop that searches for primary invariants ---------------
2389  while(1)                             // repeat until n primary invariants are
2390  {                                    // found -
2391    d=d+1;                             // degree where we'll search
2392    if (v)
2393    { "  Computing primary invariants in degree "+string(d)+":";
2394    }
2395    B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of
2396                                       // degree d
2397    if (B[1]<>0)
2398    { Pplus=P+B;
2399      newdim=dim(std(Pplus));
2400      dif=n-i-newdim;
2401    }
2402    else
2403    { dif=0;
2404      deg_vector=deg_vector,d;
2405    }
2406    if (dif<>0)                        // we have to find dif new primary
2407    {                                  // invariants
2408      cd=size(B);
2409      if (cd<>dif)
2410      { P,sP,CI,dB=search(n,d,B,cd,P,sP,i,dif,dB,CI);
2411      }
2412      else                             // i.e. we can take all of B
2413      { for(j=i+1;j<=i+dif;j=j+1)
2414        { CI=CI+ideal(var(j)^d);
2415        }
2416        dB=dB+dif*(d-1);
2417        P=Pplus;
2418        sP=std(P);
2419      }
2420      if (v)
2421      { for (j=1;j<=dif;j=j+1)
2422        { "  We find: "+string(P[i+j]);
2423        }
2424      }
2425      i=i+dif;
2426      if (i==n)                        // found all primary invariants
2427      { if (v)
2428        { "";
2429          "  We found all primary invariants.";
2430          "";
2431        }
2432        if (deg_vector==0)
2433        { return(matrix(P));
2434        }
2435        else
2436        { return(matrix(P),compress(deg_vector));
2437        }
2438      }
2439    }                                  // done with degree d
2440    else
2441    { if (v)
2442      { "  None here...";
2443      }
2444    }
2445  }
2446}
2447example
2448{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
2449  echo=2;
2450         ring R=0,(x,y,z),dp;
2451         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2452         list L=group_reynolds(A);
2453         list l=primary_char0_no_molien(L[1]);
2454         print(l[1]);
2455}
2456
2457proc primary_charp_no_molien (matrix REY, list #)
2458USAGE:   primary_charp_no_molien(REY[,v]);
2459         REY: a <matrix> representing the Reynolds operator, v: an optional
2460         <int>
2461ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
2462DISPLAY: information about the various stages of the programme if v does not
2463         equal 0
2464RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
2465         <intvec> listing some of the degrees where no non-trivial homogeneous
2466         invariants are to be found
2467EXAMPLE: example primary_charp_no_molien; shows an example
2468THEORY:  Bases of homogeneous invariants are generated successively and those
2469         are chosen as primary invariants that lower the dimension of the ideal
2470         generated by the previously found invariants (see paper "Generating a
2471         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2472         Decker, Heydtmann, Schreyer (1997) to appear in JSC).
2473{ degBound=0;
2474 //----------------- checking input and setting verbose mode ------------------
2475  if (char(basering)==0)
2476  { "ERROR:   primary_charp_no_molien should only be used with rings of";
2477    "         characteristic p>0.";
2478    return();
2479  }
2480  if (size(#)>1)
2481  { "ERROR:   primary_charp_no_molien can only have two parameters.";
2482    return();
2483  }
2484  if (size(#)==1)
2485  { if (typeof(#[1])<>"int")
2486    { "ERROR:   The second parameter should be of type <int>.";
2487      return();
2488    }
2489    else
2490    { int v=#[1];
2491    }
2492  }
2493  else
2494  { int v=0;
2495  }
2496  int n=nvars(basering);               // n is the number of variables, as well
2497                                       // as the size of the matrices, as well
2498                                       // as the number of primary invariants,
2499                                       // we should get
2500  if (ncols(REY)<>n)
2501  { "ERROR:   First parameter ought to be the Reynolds operator."
2502    return();
2503  }
2504 //----------------------------------------------------------------------------
2505  if (v && voice<>2)
2506  { "  We can start looking for primary invariants...";
2507    "";
2508  }
2509  if (v && voice==2)
2510  { "";
2511  }
2512 //-------------------- initializing variables --------------------------------
2513  int dB;
2514  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
2515                                       // space of invariants of degree d,
2516                                       // newdim: dimension the ideal generated
2517                                       // the primary invariants plus basis
2518                                       // elements, dif=n-i-newdim, i.e. the
2519                                       // number of new primary invairants that
2520                                       // should be added in this degree -
2521  ideal P,Pplus,sPplus,CI,B;           // P: will contain primary invariants,
2522                                       // Pplus: P+B, CI: a complete
2523                                       // intersection with the same Hilbert
2524                                       // function as P
2525  ideal sP=std(P);
2526  dB=1;                                // used as degree bound -
2527  d=0;                                 // initializing
2528  int i=0;
2529  intvec deg_vector;
2530 //------------------ loop that searches for primary invariants ---------------
2531  while(1)                             // repeat until n primary invariants are
2532  {                                    // found -
2533    d=d+1;                             // degree where we'll search
2534    if (v)
2535    { "  Computing primary invariants in degree "+string(d)+":";
2536    }
2537    B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of
2538                                       // degree d
2539    if (B[1]<>0)
2540    { Pplus=P+B;
2541      sPplus=std(Pplus);
2542      newdim=dim(sPplus);
2543      dif=n-i-newdim;
2544    }
2545    else
2546    { dif=0;
2547      deg_vector=deg_vector,d;
2548    }
2549    if (dif<>0)                        // we have to find dif new primary
2550    {                                  // invariants
2551      cd=size(B);
2552      if (cd<>dif)
2553      { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI);
2554      }
2555      else                             // i.e. we can take all of B
2556      { for(j=i+1;j<=i+dif;j=j+1)
2557        { CI=CI+ideal(var(j)^d);
2558        }
2559        dB=dB+dif*(d-1);
2560        P=Pplus;
2561        sP=sPplus;
2562      }
2563      if (v)
2564      { for (j=1;j<=size(P)-i;j=j+1)
2565        { "  We find: "+string(P[i+j]);
2566        }
2567      }
2568      i=size(P);
2569      if (i==n)                        // found all primary invariants
2570      { if (v)
2571        { "";
2572          "  We found all primary invariants.";
2573          "";
2574        }
2575        if (deg_vector==0)
2576        { return(matrix(P));
2577        }
2578        else
2579        { return(matrix(P),compress(deg_vector));
2580        }
2581      }
2582    }                                  // done with degree d
2583    else
2584    { if (v)
2585      { "  None here...";
2586      }
2587    }
2588  }
2589}
2590example
2591{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into";
2592  "         characteristic 3)";
2593  echo=2;
2594         ring R=3,(x,y,z),dp;
2595         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2596         list L=group_reynolds(A);
2597         list l=primary_charp_no_molien(L[1]);
2598         print(l[1]);
2599}
2600
2601proc primary_charp_without (list #)
2602USAGE:   primary_charp_without(G1,G2,...[,v]);
2603         G1,G2,...: <matrices> generating a finite matrix group, v: an optional
2604         <int>
2605DISPLAY: information about the various stages of the programme if v does not
2606         equal 0
2607RETURN:  primary invariants (type <matrix>) of the invariant ring
2608EXAMPLE: example primary_charp_without; shows an example
2609THEORY:  Bases of homogeneous invariants are generated successively and those
2610         are chosen as primary invariants that lower the dimension of the ideal
2611         generated by the previously found invariants (see paper "Generating a
2612         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2613         Decker, Heydtmann, Schreyer (1997) to appear in JSC). No Reynolds
2614         operator or Molien series is used.
2615{ degBound=0;
2616 //--------------------- checking input and setting verbose mode --------------
2617  if (char(basering)==0)
2618  { "ERROR:   primary_charp_without should only be used with rings of";
2619    "         characteristic 0.";
2620    return();
2621  }
2622  if (size(#)==0)
2623  { "ERROR:   There are no parameters.";
2624    return();
2625  }
2626  if (typeof(#[size(#)])=="int")
2627  { int v=#[size(#)];
2628    int gen_num=size(#)-1;
2629    if (gen_num==0)
2630    { "ERROR:   There are no generators of a finite matrix group given.";
2631      return();
2632    }
2633  }
2634  else
2635  { int v=0;
2636    int gen_num=size(#);
2637  }
2638  int n=nvars(basering);               // n is the number of variables, as well
2639                                       // as the size of the matrices, as well
2640                                       // as the number of primary invariants,
2641                                       // we should get
2642  for (int i=1;i<=gen_num;i=i+1)
2643  { if (typeof(#[i])=="matrix")
2644    { if (nrows(#[i])<>n or ncols(#[i])<>n)
2645      { "ERROR:   The number of variables of the base ring needs to be the same";
2646        "         as the dimension of the square matrices";
2647        return();
2648      }
2649    }
2650    else
2651    { "ERROR:   The first parameters should be a list of matrices";
2652      return();
2653    }
2654  }
2655 //----------------------------------------------------------------------------
2656  if (v && voice==2)
2657  { "";
2658  }
2659 //---------------------------- initializing variables ------------------------
2660  int dB;
2661  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
2662                                       // space of invariants of degree d,
2663                                       // newdim: dimension the ideal generated
2664                                       // the primary invariants plus basis
2665                                       // elements, dif=n-i-newdim, i.e. the
2666                                       // number of new primary invairants that
2667                                       // should be added in this degree -
2668  ideal P,Pplus,sPplus,CI,B;           // P: will contain primary invariants,
2669                                       // Pplus: P+B, CI: a complete
2670                                       // intersection with the same Hilbert
2671                                       // function as P
2672  ideal sP=std(P);
2673  dB=1;                                // used as degree bound -
2674  d=0;                                 // initializing
2675  i=0;
2676  intvec deg_vector;
2677 //-------------------- loop that searches for primary invariants -------------
2678  while(1)                             // repeat until n primary invariants are
2679  {                                    // found -
2680    d=d+1;                             // degree where we'll search
2681    if (v)
2682    { "  Computing primary invariants in degree "+string(d)+":";
2683    }
2684    B=invariant_basis(d,#[1..gen_num]); // basis of invariants of degree d
2685    if (B[1]<>0)
2686    { Pplus=P+B;
2687      sPplus=std(Pplus);
2688      newdim=dim(sPplus);
2689      dif=n-i-newdim;
2690    }
2691    else
2692    { dif=0;
2693      deg_vector=deg_vector,d;
2694    }
2695    if (dif<>0)                        // we have to find dif new primary
2696    {                                  // invariants
2697      cd=size(B);
2698      if (cd<>dif)
2699      { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI);
2700      }
2701      else                             // i.e. we can take all of B
2702      { for(j=i+1;j<=i+dif;j=j+1)
2703        { CI=CI+ideal(var(j)^d);
2704        }
2705        dB=dB+dif*(d-1);
2706        P=Pplus;
2707        sP=sPplus;
2708      }
2709      if (v)
2710      { for (j=1;j<=size(P)-i;j=j+1)
2711        { "  We find: "+string(P[i+j]);
2712        }
2713      }
2714      i=size(P);
2715      if (i==n)                        // found all primary invariants
2716      { if (v)
2717        { "";
2718          "  We found all primary invariants.";
2719          "";
2720        }
2721        return(matrix(P));
2722      }
2723    }                                  // done with degree d
2724    else
2725    { if (v)
2726      { "  None here...";
2727      }
2728    }
2729  }
2730}
2731example
2732{ echo=2;
2733         ring R=2,(x,y,z),dp;
2734         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2735         matrix P=primary_charp_without(A);
2736         print(P);
2737}
2738
2739proc primary_invariants (list #)
2740USAGE:   primary_invariants(G1,G2,...[,flags]);
2741         G1,G2,...: <matrices> generating a finite matrix group, flags: an
2742         optional <intvec> with three entries, if the first one equals 0 (also
2743         the default), the programme attempts to compute the Molien series and
2744         Reynolds operator, if it equals 1, the programme is told that the
2745         Molien series should not be computed, if it equals -1 characteristic 0
2746         is simulated, i.e. the Molien series is computed as if the base field
2747         were characteristic 0 (the user must choose a field of large prime
2748         characteristic, e.g. 32003) and if the first one is anything else, it
2749         means that the characteristic of the base field divides the group
2750         order, the second component should give the size of intervals between
2751         canceling common factors in the expansion of the Molien series, 0 (the
2752         default) means only once after generating all terms, in prime
2753         characteristic also a negative number can be given to indicate that
2754         common factors should always be canceled when the expansion is simple
2755         (the root of the extension field does not occur among the coefficients)
2756DISPLAY: information about the various stages of the programme if the third
2757         flag does not equal 0
2758RETURN:  primary invariants (type <matrix>) of the invariant ring and if
2759         computable Reynolds operator (type <matrix>) and Molien series (type
2760         <matrix>), if the first flag is 1 and we are in the non-modular case
2761         then an <intvec> is returned giving some of the degrees where no
2762         non-trivial homogeneous invariants can be found
2763EXAMPLE: example primary_invariants; shows an example
2764THEORY:  Bases of homogeneous invariants are generated successively and those
2765         are chosen as primary invariants that lower the dimension of the ideal
2766         generated by the previously found invariants (see paper "Generating a
2767         Noetherian Normalization of the Invariant Ring of a Finite Group" by
2768         Decker, Heydtmann, Schreyer (1997) to appear in JSC).
2769{
2770 // ----------------- checking input and setting flags ------------------------
2771  if (size(#)==0)
2772  { "ERROR:   There are no parameters.";
2773    return();
2774  }
2775  int ch=char(basering);               // the algorithms depend very much on the
2776                                       // characteristic of the ground field
2777  int n=nvars(basering);               // n is the number of variables, as well
2778                                       // as the size of the matrices, as well
2779                                       // as the number of primary invariants,
2780                                       // we should get
2781  int gen_num;
2782  int mol_flag,v;
2783  if (typeof(#[size(#)])=="intvec")
2784  { if (size(#[size(#)])<>3)
2785    { "ERROR:   <intvec> should have three entries.";
2786      return();
2787    }
2788    gen_num=size(#)-1;
2789    mol_flag=#[size(#)][1];
2790    if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag==-1)))
2791    { "ERROR:   the second component of <intvec> should be >=0";
2792      return();
2793    }
2794    int interval=#[size(#)][2];
2795    v=#[size(#)][3];
2796    if (gen_num==0)
2797    { "ERROR:   There are no generators of a finite matrix group given.";
2798      return();
2799    }
2800  }
2801  else
2802  { gen_num=size(#);
2803    mol_flag=0;
2804    int interval=0;
2805    v=0;
2806  }
2807  for (int i=1;i<=gen_num;i=i+1)
2808  { if (typeof(#[i])=="matrix")
2809    { if (nrows(#[i])<>n or ncols(#[i])<>n)
2810      { "ERROR:   The number of variables of the base ring needs to be the same";
2811        "         as the dimension of the square matrices";
2812        return();
2813      }
2814    }
2815    else
2816    { "ERROR:   The first parameters should be a list of matrices";
2817      return();
2818    }
2819  }
2820 //----------------------------------------------------------------------------
2821  if (mol_flag==0)
2822  { if (ch==0)
2823    { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(mol_flag,interval,v));
2824                                       // one will contain Reynolds operator and
2825                                       // the other enumerator and denominator
2826                                       // of Molien series
2827      matrix P=primary_char0(REY,M,v);
2828      return(P,REY,M);
2829    }
2830    else
2831    { list L=group_reynolds(#[1..gen_num],v);
2832      if (L[1]<>0)                     // testing whether we are in the modular
2833      { string newring="aksldfalkdsflkj"; // case
2834        if (minpoly==0)
2835        { if (v)
2836          { "  We are dealing with the non-modular case.";
2837          }
2838          if (typeof(L[2])=="int")
2839          { molien(L[3..size(L)],newring,L[2],intvec(mol_flag,interval,v));
2840          }
2841          else
2842          { molien(L[2..size(L)],newring,intvec(mol_flag,interval,v));
2843          }
2844          matrix P=primary_charp(L[1],newring,v);
2845          return(P,L[1],newring);
2846        }
2847        else
2848        { if (v)
2849          { "  Since it is impossible for this programme to calculate the Molien series for";
2850            "  invariant rings over extension fields of prime characteristic, we have to";
2851            "  continue without it.";
2852            "";
2853
2854          }
2855          list l=primary_charp_no_molien(L[1],v);
2856          if (size(l)==2)
2857          { return(l[1],L[1],l[2]);
2858          }
2859          else
2860          { return(l[1],L[1]);
2861          }
2862        }
2863      }
2864      else                             // the modular case
2865      { if (v)
2866        { "  There is also no Molien series, we can make use of...";
2867          "";
2868          "  We can start looking for primary invariants...";
2869          "";
2870        }
2871        return(primary_charp_without(#[1..gen_num],v));
2872      }
2873    }
2874  }
2875  if (mol_flag==1)                     // the user wants no calculation of the
2876  { list L=group_reynolds(#[1..gen_num],v); // Molien series
2877    if (ch==0)
2878    { list l=primary_char0_no_molien(L[1],v);
2879      if (size(l)==2)
2880      { return(l[1],L[1],l[2]);
2881      }
2882      else
2883      { return(l[1],L[1]);
2884      }
2885    }
2886    else
2887    { if (L[1]<>0)                     // testing whether we are in the modular
2888      { list l=primary_charp_no_molien(L[1],v); // case
2889        if (size(l)==2)
2890        { return(l[1],L[1],l[2]);
2891        }
2892        else
2893        { return(l[1],L[1]);
2894        }
2895      }
2896      else                             // the modular case
2897      { if (v)
2898        { "  We can start looking for primary invariants...";
2899          "";
2900        }
2901        return(primary_charp_without(#[1..gen_num],v));
2902      }
2903    }
2904  }
2905  if (mol_flag==-1)
2906  { if (ch==0)
2907    { "ERROR:   Characteristic 0 can only be simulated in characteristic p>>0.";
2908      return();
2909    }
2910    list L=group_reynolds(#[1..gen_num],v);
2911    string newring="aksldfalkdsflkj";
2912    molien(L[2..size(L)],newring,intvec(1,interval,v));
2913    matrix P=primary_charp(L[1],newring,v);
2914    return(P,L[1],newring);
2915  }
2916  else                                 // the user specified that the
2917  { if (ch==0)                         // characteristic divides the group order
2918    { "ERROR:   The characteristic cannot divide the group order when it is 0.";
2919      return();
2920    }
2921    if (v)
2922    { "";
2923    }
2924    return(primary_charp_without(#[1..gen_num],v));
2925  }
2926}
2927example
2928{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
2929  echo=2;
2930         ring R=0,(x,y,z),dp;
2931         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
2932         list L=primary_invariants(A);
2933         print(L[1]);
2934}
2935
2936////////////////////////////////////////////////////////////////////////////////
2937// This procedure finds dif primary invariants in degree d. It returns all
2938// primary invariants found so far. The coefficients lie in a field of
2939// characteristic 0.
2940////////////////////////////////////////////////////////////////////////////////
2941proc search_random (int n,int d,ideal B,int cd,ideal P,int i,int dif,int dB,ideal CI,int max)
2942{ string answer;
2943  degBound=0;
2944  int j,k,test_dim,flag;
2945  matrix test_matrix[1][dif];          // the linear combination to test
2946  intvec h;                            // Hilbert series
2947  for (j=i+1;j<=i+dif;j=j+1)
2948  { CI=CI+ideal(var(j)^d);             // homogeneous polynomial of the same
2949                                       // degree as the one we're looking for
2950                                       // is added
2951  }
2952  ideal TEST;
2953  // h=hilb(std(CI),1);
2954  dB=dB+dif*(d-1);                     // used as degBound
2955  while (1)
2956  { test_matrix=matrix(B)*random(max,cd,dif);
2957    // degBound=dB;
2958    TEST=P+ideal(test_matrix);
2959    attrib(TEST,"isSB",1);
2960    test_dim=dim(TEST);
2961    // degBound=0;
2962    if (n-test_dim==i+dif)
2963    { break;
2964    }
2965    // degBound=dB;
2966    test_dim=dim(std(TEST));
2967    // test_dim=dim(std(TEST,h));         // Hilbert driven std-calculation
2968    // degBound=0;
2969    if (n-test_dim==i+dif)
2970    { break;
2971    }
2972    else
2973    { "HELP:    The "+string(dif)+" random combination(s) of the "+string(cd)+" basis elements with";
2974      "         coefficients in the range from -"+string(max)+" to "+string(max)+" did not lower the";
2975      "         dimension by "+string(dif)+". You can abort, try again or give a new range:";
2976      answer="";
2977      while (answer<>"n
2978" && answer<>"y
2979")
2980      { "         Do you want to abort (y/n)?";
2981        answer=read("");
2982      }
2983      if (answer=="y
2984")
2985      { flag=1;
2986        break;
2987      }
2988      answer="";
2989      while (answer<>"n
2990" && answer<>"y
2991")
2992      { "         Do you want to try again (y/n)?";
2993        answer=read("");
2994      }
2995      if (answer=="n
2996")
2997      { flag=1;
2998        while (flag)
2999        { "         Give a new <int> > "+string(max)+" that bounds the range of coefficients:";
3000          answer=read("");
3001          for (j=1;j<=size(answer)-1;j=j+1)
3002          { for (k=0;k<=9;k=k+1)
3003            { if (answer[j]==string(k))
3004              { break;
3005              }
3006            }
3007            if (k>9)
3008            { flag=1;
3009              break;
3010            }
3011            flag=0;
3012          }
3013          if (not(flag))
3014          { execute "test_dim="+string(answer[1..size(answer)]);
3015            if (test_dim<=max)
3016            { flag=1;
3017            }
3018            else
3019            { max=test_dim;
3020            }
3021          }
3022        }
3023      }
3024    }
3025  }
3026  if (not(flag))
3027  { P[(i+1)..(i+dif)]=test_matrix[1,1..dif];
3028  }
3029  return(P,CI,dB);
3030}
3031
3032////////////////////////////////////////////////////////////////////////////////
3033// This procedure finds at most dif primary invariants in degree d. It returns
3034// all primary invariants found so far. The coefficients lie in the field of
3035// characteristic p>0.
3036////////////////////////////////////////////////////////////////////////////////
3037proc p_search_random (int n,int d,ideal B,int cd,ideal P,int i,int dif,int dB,ideal CI,int max)
3038{ string answer;
3039  degBound=0;
3040  int j,k,test_dim,flag;
3041  matrix test_matrix[1][dif];          // the linear combination to test
3042  intvec h;                            // Hilbert series
3043  ideal TEST;
3044  while (dif>0)
3045  { for (j=i+1;j<=i+dif;j=j+1)
3046    { CI=CI+ideal(var(j)^d);           // homogeneous polynomial of the same
3047                                       // degree as the one we're looking for
3048                                       // is added
3049    }
3050    // h=hilb(std(CI),1);
3051    dB=dB+dif*(d-1);                   // used as degBound
3052    test_matrix=matrix(B)*random(max,cd,dif);
3053    // degBound=dB;
3054    TEST=P+ideal(test_matrix);
3055    attrib(TEST,"isSB",1);
3056    test_dim=dim(TEST);
3057    // degBound=0;
3058    if (n-test_dim==i+dif)
3059    { break;
3060    }
3061    // degBound=dB;
3062    test_dim=dim(std(TEST));
3063    // test_dim=dim(std(TEST,h));         // Hilbert driven std-calculation
3064    // degBound=0;
3065    if (n-test_dim==i+dif)
3066    { break;
3067    }
3068    else
3069    { "HELP:    The "+string(dif)+" random combination(s) of the "+string(cd)+" basis elements with";
3070      "         coefficients in the range from -"+string(max)+" to "+string(max)+" did not lower the";
3071      "         dimension by "+string(dif)+". You can abort, try again, lower the number of";
3072      "         combinations searched for by 1 or give a larger coefficient range:";
3073      answer="";
3074      while (answer<>"n
3075" && answer<>"y
3076")
3077      { "         Do you want to abort (y/n)?";
3078        answer=read("");
3079      }
3080      if (answer=="y
3081")
3082      { flag=1;
3083        break;
3084      }
3085      answer="";
3086      while (answer<>"n
3087" && answer<>"y
3088")
3089      { "         Do you want to try again (y/n)?";
3090        answer=read("");
3091      }
3092      if (answer=="n
3093")
3094      { answer="";
3095        while (answer<>"n
3096" && answer<>"y
3097")
3098        { "         Do you want to lower the number of combinations by 1 (y/n)?";
3099          answer=read("");
3100        }
3101        if (answer=="y
3102")
3103        { dif=dif-1;
3104        }
3105        else
3106        { flag=1;
3107          while (flag)
3108          { "         Give a new <int> > "+string(max)+" that bounds the range of coefficients:";
3109            answer=read("");
3110            for (j=1;j<=size(answer)-1;j=j+1)
3111            { for (k=0;k<=9;k=k+1)
3112              { if (answer[j]==string(k))
3113                { break;
3114                }
3115              }
3116              if (k>9)
3117              { flag=1;
3118                break;
3119              }
3120              flag=0;
3121            }
3122            if (not(flag))
3123            { execute "test_dim="+string(answer[1..size(answer)]);
3124              if (test_dim<=max)
3125              { flag=1;
3126              }
3127              else
3128              { max=test_dim;
3129              }
3130            }
3131          }
3132        }
3133      }
3134    }
3135    CI=CI[1..i];
3136    dB=dB-dif*(d-1);
3137  }
3138  if (dif && not(flag))
3139  { P[(i+1)..(i+dif)]=test_matrix[1,1..dif];
3140  }
3141  if (dif && flag)
3142  { P[n+1]=0;
3143  }
3144  return(P,CI,dB);
3145}
3146
3147proc primary_char0_random (matrix REY,matrix M,int max,list #)
3148USAGE:   primary_char0_random(REY,M,r[,v]);
3149         REY: a <matrix> representing the Reynolds operator, M: a 1x2 <matrix>
3150         representing the Molien series, r: an <int> where -|r| to |r| is the
3151         range of coefficients of the random combinations of bases elements,
3152         v: an optional <int>
3153ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
3154         M the one of molien or the second one of reynolds_molien
3155DISPLAY: information about the various stages of the programme if v does not
3156         equal 0
3157RETURN:  primary invariants (type <matrix>) of the invariant ring
3158EXAMPLE: example primary_char0_random; shows an example
3159THEORY:  Bases of homogeneous invariants are generated successively and random
3160         linear combinations are chosen as primary invariants that lower the
3161         dimension of the ideal generated by the previously found invariants
3162         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3163         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3164         JSC).
3165{ degBound=0;
3166  if (char(basering)<>0)
3167  { "ERROR:   primary_char0_random should only be used with rings of";
3168    "         characteristic 0.";
3169    return();
3170  }
3171 //----------------- checking input and setting verbose mode ------------------
3172  if (size(#)>1)
3173  { "ERROR:   primary_char0_random can only have four parameters.";
3174    return();
3175  }
3176  if (size(#)==1)
3177  { if (typeof(#[1])<>"int")
3178    { "ERROR:   The fourth parameter should be of type <int>.";
3179      return();
3180    }
3181    else
3182    { int v=#[1];
3183    }
3184  }
3185  else
3186  { int v=0;
3187  }
3188  int n=nvars(basering);               // n is the number of variables, as well
3189                                       // as the size of the matrices, as well
3190                                       // as the number of primary invariants,
3191                                       // we should get
3192  if (ncols(REY)<>n)
3193  { "ERROR:   First parameter ought to be the Reynolds operator."
3194    return();
3195  }
3196  if (ncols(M)<>2 or nrows(M)<>1)
3197  { "ERROR:   Second parameter ought to be the Molien series."
3198    return();
3199  }
3200 //----------------------------------------------------------------------------
3201  if (v && voice<>2)
3202  { "  We can start looking for primary invariants...";
3203    "";
3204  }
3205  if (v && voice==2)
3206  { "";
3207  }
3208 //------------------------- initializing variables ---------------------------
3209  int dB;
3210  poly p(1..2);                        // p(1) will be used for single terms of
3211                                       // the partial expansion, p(2) to store
3212  p(1..2)=partial_molien(M,1);         // the intermediate result -
3213  poly v1=var(1);                      // we need v1 to split off coefficients
3214                                       // in the partial expansion of M (which
3215                                       // is in terms of the first variable) -
3216  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
3217                                       // space of invariants of degree d,
3218                                       // newdim: dimension the ideal generated
3219                                       // the primary invariants plus basis
3220                                       // elements, dif=n-i-newdim, i.e. the
3221                                       // number of new primary invairants that
3222                                       // should be added in this degree -
3223  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
3224                                       // Pplus: P+B,CI: a complete
3225                                       // intersection with the same Hilbert
3226                                       // function as P -
3227  dB=1;                                // used as degree bound
3228  int i=0;
3229 //-------------- loop that searches for primary invariants  ------------------
3230  while(1)                             // repeat until n primary invariants are
3231  {                                    // found -
3232    p(1..2)=partial_molien(M,1,p(2));  // next term of the partial expansion -
3233    d=deg(p(1));                       // degree where we'll search -
3234    cd=int(coef(p(1),v1)[2,1]);        // dimension of the homogeneous space of
3235                                       // inviarants of degree d
3236    if (v)
3237    { "  Computing primary invariants in degree "+string(d)+":";
3238    }
3239    B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of
3240                                       // degree d
3241    if (B[1]<>0)
3242    { Pplus=P+B;
3243      newdim=dim(std(Pplus));
3244      dif=n-i-newdim;
3245    }
3246    else
3247    { dif=0;
3248    }
3249    if (dif<>0)                        // we have to find dif new primary
3250    {                                  // invariants
3251      if (cd<>dif)
3252      { P,CI,dB=search_random(n,d,B,cd,P,i,dif,dB,CI,max); // searching for
3253      }                                // dif invariants -
3254      else                             // i.e. we can take all of B
3255      { for(j=i+1;j>i+dif;j=j+1)
3256        { CI=CI+ideal(var(j)^d);
3257        }
3258        dB=dB+dif*(d-1);
3259        P=Pplus;
3260      }
3261      if (ncols(P)==i)
3262      { "WARNING: The return value is not a set of primary invariants, but";
3263        "         polynomials qualifying as the first "+string(i)+" primary invariants.";
3264        return(matrix(P));
3265      }
3266      if (v)
3267      { for (j=1;j<=dif;j=j+1)
3268        { "  We find: "+string(P[i+j]);
3269        }
3270      }
3271      i=i+dif;
3272      if (i==n)                        // found all primary invariants
3273      { if (v)
3274        { "";
3275          "  We found all primary invariants.";
3276          "";
3277        }
3278        return(matrix(P));
3279      }
3280    }                                  // done with degree d
3281  }
3282}
3283example
3284{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
3285  echo=2;
3286         ring R=0,(x,y,z),dp;
3287         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
3288         matrix REY,M=reynolds_molien(A);
3289         matrix P=primary_char0_random(REY,M,1);
3290         print(P);
3291}
3292
3293proc primary_charp_random (matrix REY,string ring_name,int max,list #)
3294USAGE:   primary_charp_random(REY,ringname,r[,v]);
3295         REY: a <matrix> representing the Reynolds operator, ringname: a
3296         <string> giving the name of a ring where the Molien series is stored,
3297         r: an <int> where -|r| to |r| is the range of coefficients of the
3298         random combinations of bases elements, v: an optional <int>
3299ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
3300         ringname gives the name of a ring of characteristic 0 that has been
3301         created by molien or reynolds_molien
3302DISPLAY: information about the various stages of the programme if v does not
3303         equal 0
3304RETURN:  primary invariants (type <matrix>) of the invariant ring
3305EXAMPLE: example primary_charp_random; shows an example
3306THEORY:  Bases of homogeneous invariants are generated successively and random
3307         linear combinations are chosen as primary invariants that lower the
3308         dimension of the ideal generated by the previously found invariants
3309         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3310         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3311         JSC).
3312{ degBound=0;
3313 // ---------------- checking input and setting verbose mode ------------------
3314  if (char(basering)==0)
3315  { "ERROR:   primary_charp_random should only be used with rings of";
3316    "         characteristic p>0.";
3317    return();
3318  }
3319  if (size(#)>1)
3320  { "ERROR:   primary_charp_random can only have four parameters.";
3321    return();
3322  }
3323  if (size(#)==1)
3324  { if (typeof(#[1])<>"int")
3325    { "ERROR:   The fourth parameter should be of type <int>.";
3326      return();
3327    }
3328    else
3329    { int v=#[1];
3330    }
3331  }
3332  else
3333  { int v=0;
3334  }
3335  def br=basering;
3336  int n=nvars(br);                     // n is the number of variables, as well
3337                                       // as the size of the matrices, as well
3338                                       // as the number of primary invariants,
3339                                       // we should get
3340  if (ncols(REY)<>n)
3341  { "ERROR:   First parameter ought to be the Reynolds operator."
3342    return();
3343  }
3344  if (typeof(`ring_name`)<>"ring")
3345  { "ERROR:   Second parameter ought to the name of a ring where the Molien";
3346    "         is stored.";
3347    return();
3348  }
3349 //----------------------------------------------------------------------------
3350  if (v && voice<>2)
3351  { "  We can start looking for primary invariants...";
3352    "";
3353  }
3354  if (v && voice==2)
3355  { "";
3356  }
3357 //----------------------- initializing variables -----------------------------
3358  int dB;
3359  setring `ring_name`;                 // the Molien series is stores here -
3360  poly p(1..2);                        // p(1) will be used for single terms of
3361                                       // the partial expansion, p(2) to store
3362  p(1..2)=partial_molien(M,1);         // the intermediate result -
3363  poly v1=var(1);                      // we need v1 to split off coefficients
3364                                       // in the partial expansion of M (which
3365                                       // is in terms of the first variable)
3366  setring br;
3367  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
3368                                       // space of invariants of degree d,
3369                                       // newdim: dimension the ideal generated
3370                                       // the primary invariants plus basis
3371                                       // elements, dif=n-i-newdim, i.e. the
3372                                       // number of new primary invairants that
3373                                       // should be added in this degree -
3374  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
3375                                       // Pplus: P+B, CI: a complete
3376                                       // intersection with the same Hilbert
3377                                       // function as P -
3378  dB=1;                                // used as degree bound
3379  int i=0;
3380 //---------------- loop that searches for primary invariants -----------------
3381  while(1)                             // repeat until n primary invariants are
3382  {                                    // found
3383    setring `ring_name`;
3384    p(1..2)=partial_molien(M,1,p(2));  // next term of the partial expansion -
3385    d=deg(p(1));                       // degree where we'll search -
3386    cd=int(coef(p(1),v1)[2,1]);        // dimension of the homogeneous space of
3387                                       // inviarants of degree d
3388    setring br;
3389    if (v)
3390    { "  Computing primary invariants in degree "+string(d)+":";
3391    }
3392    B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of
3393                                       // degree d
3394    if (B[1]<>0)
3395    { Pplus=P+B;
3396      newdim=dim(std(Pplus));
3397      dif=n-i-newdim;
3398    }
3399    else
3400    { dif=0;
3401    }
3402    if (dif<>0)                        // we have to find dif new primary
3403    {                                  // invariants
3404      if (cd<>dif)
3405      { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max);
3406      }
3407      else                             // i.e. we can take all of B
3408      { for(j=i+1;j>i+dif;j=j+1)
3409        { CI=CI+ideal(var(j)^d);
3410        }
3411        dB=dB+dif*(d-1);
3412        P=Pplus;
3413      }
3414      if (ncols(P)==n+1)
3415      { "WARNING: The first return value is not a set of primary invariants,";
3416        "         but polynomials qualifying as the first "+string(i)+" primary invariants.";
3417        return(matrix(P));
3418      }
3419      if (v)
3420      { for (j=1;j<=size(P)-i;j=j+1)
3421        { "  We find: "+string(P[i+j]);
3422        }
3423      }
3424      i=size(P);
3425      if (i==n)                        // found all primary invariants
3426      { if (v)
3427        { "";
3428          "  We found all primary invariants.";
3429          "";
3430        }
3431        return(matrix(P));
3432      }
3433    }                                  // done with degree d
3434  }
3435}
3436example
3437{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into";
3438  "         characteristic 3)";
3439  echo=2;
3440         ring R=3,(x,y,z),dp;
3441         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
3442         list L=group_reynolds(A);
3443         string newring="alskdfj";
3444         molien(L[2..size(L)],newring);
3445         matrix P=primary_charp_random(L[1],newring,1);
3446         kill `newring`;
3447         print(P);
3448}
3449
3450proc primary_char0_no_molien_random (matrix REY, int max, list #)
3451USAGE:   primary_char0_no_molien_random(REY,r[,v]);
3452         REY: a <matrix> representing the Reynolds operator, r: an <int> where
3453         -|r| to |r| is the range of coefficients of the random combinations of
3454         bases elements, v: an optional <int>
3455ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
3456DISPLAY: information about the various stages of the programme if v does not
3457         equal 0
3458RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
3459         <intvec> listing some of the degrees where no non-trivial homogeneous
3460         invariants are to be found
3461EXAMPLE: example primary_char0_no_molien_random; shows an example
3462THEORY:  Bases of homogeneous invariants are generated successively and random
3463         linear combinations are chosen as primary invariants that lower the
3464         dimension of the ideal generated by the previously found invariants
3465         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3466         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3467         JSC).
3468{ degBound=0;
3469 //-------------- checking input and setting verbose mode ---------------------
3470  if (char(basering)<>0)
3471  { "ERROR:   primary_char0_no_molien_random should only be used with rings of";
3472    "         characteristic 0.";
3473    return();
3474  }
3475  if (size(#)>1)
3476  { "ERROR:   primary_char0_no_molien_random can only have three parameters.";
3477    return();
3478  }
3479  if (size(#)==1)
3480  { if (typeof(#[1])<>"int")
3481    { "ERROR:   The third parameter should be of type <int>.";
3482      return();
3483    }
3484    else
3485    { int v=#[1];
3486    }
3487  }
3488  else
3489  { int v=0;
3490  }
3491  int n=nvars(basering);               // n is the number of variables, as well
3492                                       // as the size of the matrices, as well
3493                                       // as the number of primary invariants,
3494                                       // we should get
3495  if (ncols(REY)<>n)
3496  { "ERROR:   First parameter ought to be the Reynolds operator."
3497    return();
3498  }
3499 //----------------------------------------------------------------------------
3500  if (v && voice<>2)
3501  { "  We can start looking for primary invariants...";
3502    "";
3503  }
3504  if (v && voice==2)
3505  { "";
3506  }
3507 //----------------------- initializing variables -----------------------------
3508  int dB;
3509  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
3510                                       // space of invariants of degree d,
3511                                       // newdim: dimension the ideal generated
3512                                       // the primary invariants plus basis
3513                                       // elements, dif=n-i-newdim, i.e. the
3514                                       // number of new primary invairants that
3515                                       // should be added in this degree -
3516  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
3517                                       // Pplus: P+B, CI: a complete
3518                                       // intersection with the same Hilbert
3519                                       // function as P -
3520  dB=1;                                // used as degree bound -
3521  d=0;                                 // initializing
3522  int i=0;
3523  intvec deg_vector;
3524 //------------------ loop that searches for primary invariants ---------------
3525  while(1)                             // repeat until n primary invariants are
3526  {                                    // found -
3527    d=d+1;                             // degree where we'll search
3528    if (v)
3529    { "  Computing primary invariants in degree "+string(d)+":";
3530    }
3531    B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of
3532                                       // degree d
3533    if (B[1]<>0)
3534    { Pplus=P+B;
3535      newdim=dim(std(Pplus));
3536      dif=n-i-newdim;
3537    }
3538    else
3539    { dif=0;
3540      deg_vector=deg_vector,d;
3541    }
3542    if (dif<>0)                        // we have to find dif new primary
3543    {                                  // invariants
3544      cd=size(B);
3545      if (cd<>dif)
3546      { P,CI,dB=search_random(n,d,B,cd,P,i,dif,dB,CI,max);
3547      }
3548      else                             // i.e. we can take all of B
3549      { for(j=i+1;j<=i+dif;j=j+1)
3550        { CI=CI+ideal(var(j)^d);
3551        }
3552        dB=dB+dif*(d-1);
3553        P=Pplus;
3554      }
3555      if (ncols(P)==i)
3556      { "WARNING: The first return value is not a set of primary invariants,";
3557        "         but polynomials qualifying as the first "+string(i)+" primary invariants.";
3558        return(matrix(P));
3559      }
3560      if (v)
3561      { for (j=1;j<=dif;j=j+1)
3562        { "  We find: "+string(P[i+j]);
3563        }
3564      }
3565      i=i+dif;
3566      if (i==n)                        // found all primary invariants
3567      { if (v)
3568        { "";
3569          "  We found all primary invariants.";
3570          "";
3571        }
3572        if (deg_vector==0)
3573        { return(matrix(P));
3574        }
3575        else
3576        { return(matrix(P),compress(deg_vector));
3577        }
3578      }
3579    }                                  // done with degree d
3580    else
3581    { if (v)
3582      { "  None here...";
3583      }
3584    }
3585  }
3586}
3587example
3588{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
3589  echo=2;
3590         ring R=0,(x,y,z),dp;
3591         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
3592         list L=group_reynolds(A);
3593         list l=primary_char0_no_molien_random(L[1],1);
3594         print(l[1]);
3595}
3596
3597proc primary_charp_no_molien_random (matrix REY, int max, list #)
3598USAGE:   primary_charp_no_molien_random(REY,r[,v]);
3599         REY: a <matrix> representing the Reynolds operator, r: an <int> where
3600         -|r| to |r| is the range of coefficients of the random combinations of
3601         bases elements, v: an optional <int>
3602ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
3603DISPLAY: information about the various stages of the programme if v does not
3604         equal 0
3605RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
3606         <intvec> listing some of the degrees where no non-trivial homogeneous
3607         invariants are to be found
3608EXAMPLE: example primary_charp_no_molien_random; shows an example
3609THEORY:  Bases of homogeneous invariants are generated successively and random
3610         linear combinations are chosen as primary invariants that lower the
3611         dimension of the ideal generated by the previously found invariants
3612         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3613         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3614         JSC).
3615{ degBound=0;
3616 //----------------- checking input and setting verbose mode ------------------
3617  if (char(basering)==0)
3618  { "ERROR:   primary_charp_no_molien_random should only be used with rings of";
3619    "         characteristic p>0.";
3620    return();
3621  }
3622  if (size(#)>1)
3623  { "ERROR:   primary_charp_no_molien_random can only have three parameters.";
3624    return();
3625  }
3626  if (size(#)==1)
3627  { if (typeof(#[1])<>"int")
3628    { "ERROR:   The third parameter should be of type <int>.";
3629      return();
3630    }
3631    else
3632    { int v=#[1];
3633    }
3634  }
3635  else
3636  { int v=0;
3637  }
3638  int n=nvars(basering);               // n is the number of variables, as well
3639                                       // as the size of the matrices, as well
3640                                       // as the number of primary invariants,
3641                                       // we should get
3642  if (ncols(REY)<>n)
3643  { "ERROR:   First parameter ought to be the Reynolds operator."
3644    return();
3645  }
3646 //----------------------------------------------------------------------------
3647  if (v && voice<>2)
3648  { "  We can start looking for primary invariants...";
3649    "";
3650  }
3651  if (v && voice==2)
3652  { "";
3653  }
3654 //-------------------- initializing variables --------------------------------
3655  int dB;
3656  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
3657                                       // space of invariants of degree d,
3658                                       // newdim: dimension the ideal generated
3659                                       // the primary invariants plus basis
3660                                       // elements, dif=n-i-newdim, i.e. the
3661                                       // number of new primary invairants that
3662                                       // should be added in this degree -
3663  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
3664                                       // Pplus: P+B, CI: a complete
3665                                       // intersection with the same Hilbert
3666                                       // function as P -
3667  dB=1;                                // used as degree bound -
3668  d=0;                                 // initializing
3669  int i=0;
3670  intvec deg_vector;
3671 //------------------ loop that searches for primary invariants ---------------
3672  while(1)                             // repeat until n primary invariants are
3673  {                                    // found -
3674    d=d+1;                             // degree where we'll search
3675    if (v)
3676    { "  Computing primary invariants in degree "+string(d)+":";
3677    }
3678    B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of
3679                                       // degree d
3680    if (B[1]<>0)
3681    { Pplus=P+B;
3682      newdim=dim(std(Pplus));
3683      dif=n-i-newdim;
3684    }
3685    else
3686    { dif=0;
3687      deg_vector=deg_vector,d;
3688    }
3689    if (dif<>0)                        // we have to find dif new primary
3690    {                                  // invariants
3691      cd=size(B);
3692      if (cd<>dif)
3693      { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max);
3694      }
3695      else                             // i.e. we can take all of B
3696      { for(j=i+1;j<=i+dif;j=j+1)
3697        { CI=CI+ideal(var(j)^d);
3698        }
3699        dB=dB+dif*(d-1);
3700        P=Pplus;
3701      }
3702      if (ncols(P)==n+1)
3703      { "WARNING: The first return value is not a set of primary invariants,";
3704        "         but polynomials qualifying as the first "+string(i)+" primary invariants.";
3705        return(matrix(P));
3706      }
3707      if (v)
3708      { for (j=1;j<=size(P)-i;j=j+1)
3709        { "  We find: "+string(P[i+j]);
3710        }
3711      }
3712      i=size(P);
3713      if (i==n)                        // found all primary invariants
3714      { if (v)
3715        { "";
3716          "  We found all primary invariants.";
3717          "";
3718        }
3719        if (deg_vector==0)
3720        { return(matrix(P));
3721        }
3722        else
3723        { return(matrix(P),compress(deg_vector));
3724        }
3725      }
3726    }                                  // done with degree d
3727    else
3728    { if (v)
3729      { "  None here...";
3730      }
3731    }
3732  }
3733}
3734example
3735{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into";
3736  "         characteristic 3)";
3737  echo=2;
3738         ring R=3,(x,y,z),dp;
3739         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
3740         list L=group_reynolds(A);
3741         list l=primary_charp_no_molien_random(L[1],1);
3742         print(l[1]);
3743}
3744
3745proc primary_charp_without_random (list #)
3746USAGE:   primary_charp_without_random(G1,G2,...,r[,v]);
3747         G1,G2,...: <matrices> generating a finite matrix group, r: an <int>
3748         where -|r| to |r| is the range of coefficients of the random
3749         combinations of bases elements, v: an optional <int>
3750DISPLAY: information about the various stages of the programme if v does not
3751         equal 0
3752RETURN:  primary invariants (type <matrix>) of the invariant ring
3753EXAMPLE: example primary_charp_without_random; shows an example
3754THEORY:  Bases of homogeneous invariants are generated successively and random
3755         linear combinations are chosen as primary invariants that lower the
3756         dimension of the ideal generated by the previously found invariants
3757         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3758         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3759         JSC). No Reynolds operator or Molien series is used.
3760{ degBound=0;
3761 //--------------------- checking input and setting verbose mode --------------
3762  if (char(basering)==0)
3763  { "ERROR:   primary_charp_without_random should only be used with rings of";
3764    "         characteristic 0.";
3765    return();
3766  }
3767  if (size(#)<2)
3768  { "ERROR:   There are too few parameters.";
3769    return();
3770  }
3771  if (typeof(#[size(#)])=="int" && typeof(#[size(#)-1])=="int")
3772  { int v=#[size(#)];
3773    int max=#[size(#)-1];
3774    int gen_num=size(#)-2;
3775    if (gen_num==0)
3776    { "ERROR:   There are no generators of a finite matrix group given.";
3777      return();
3778    }
3779  }
3780  else
3781  { if (typeof(#[size(#)])=="int")
3782    { int max=#[size(#)];
3783      int v=0;
3784      int gen_num=size(#)-1;
3785    }
3786    else
3787    { "ERROR:   The last parameter should be an <int>.";
3788      return();
3789    }
3790  }
3791  int n=nvars(basering);               // n is the number of variables, as well
3792                                       // as the size of the matrices, as well
3793                                       // as the number of primary invariants,
3794                                       // we should get
3795  for (int i=1;i<=gen_num;i=i+1)
3796  { if (typeof(#[i])=="matrix")
3797    { if (nrows(#[i])<>n or ncols(#[i])<>n)
3798      { "ERROR:   The number of variables of the base ring needs to be the same";
3799        "         as the dimension of the square matrices";
3800        return();
3801      }
3802    }
3803    else
3804    { "ERROR:   The first parameters should be a list of matrices";
3805      return();
3806    }
3807  }
3808 //----------------------------------------------------------------------------
3809  if (v && voice==2)
3810  { "";
3811  }
3812 //---------------------------- initializing variables ------------------------
3813  int dB;
3814  int j,d,cd,newdim,dif;               // d: current degree, cd: dimension of
3815                                       // space of invariants of degree d,
3816                                       // newdim: dimension the ideal generated
3817                                       // the primary invariants plus basis
3818                                       // elements, dif=n-i-newdim, i.e. the
3819                                       // number of new primary invairants that
3820                                       // should be added in this degree -
3821  ideal P,Pplus,CI,B;                  // P: will contain primary invariants,
3822                                       // Pplus: P+B, CI: a complete
3823                                       // intersection with the same Hilbert
3824                                       // function as P -
3825  dB=1;                                // used as degree bound -
3826  d=0;                                 // initializing
3827  i=0;
3828  intvec deg_vector;
3829 //-------------------- loop that searches for primary invariants -------------
3830  while(1)                             // repeat until n primary invariants are
3831  {                                    // found -
3832    d=d+1;                             // degree where we'll search
3833    if (v)
3834    { "  Computing primary invariants in degree "+string(d)+":";
3835    }
3836    B=invariant_basis(d,#[1..gen_num]); // basis of invariants of degree d
3837    if (B[1]<>0)
3838    { Pplus=P+B;
3839      newdim=dim(std(Pplus));
3840      dif=n-i-newdim;
3841    }
3842    else
3843    { dif=0;
3844      deg_vector=deg_vector,d;
3845    }
3846    if (dif<>0)                        // we have to find dif new primary
3847    {                                  // invariants
3848      cd=size(B);
3849      if (cd<>dif)
3850      { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max);
3851      }
3852      else                             // i.e. we can take all of B
3853      { for(j=i+1;j<=i+dif;j=j+1)
3854        { CI=CI+ideal(var(j)^d);
3855        }
3856        dB=dB+dif*(d-1);
3857        P=Pplus;
3858      }
3859      if (ncols(P)==n+1)
3860      { "WARNING: The first return value is not a set of primary invariants,";
3861        "         but polynomials qualifying as the first "+string(i)+" primary invariants.";
3862        return(matrix(P));
3863      }
3864      if (v)
3865      { for (j=1;j<=size(P)-i;j=j+1)
3866        { "  We find: "+string(P[i+j]);
3867        }
3868      }
3869      i=size(P);
3870      if (i==n)                        // found all primary invariants
3871      { if (v)
3872        { "";
3873          "  We found all primary invariants.";
3874          "";
3875        }
3876        return(matrix(P));
3877      }
3878    }                                  // done with degree d
3879    else
3880    { if (v)
3881      { "  None here...";
3882      }
3883    }
3884  }
3885}
3886example
3887{ echo=2;
3888         ring R=2,(x,y,z),dp;
3889         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
3890         matrix P=primary_charp_without_random(A,1);
3891         print(P);
3892}
3893
3894proc primary_invariants_random (list #)
3895USAGE:   primary_invariants_random(G1,G2,...,r[,flags]);
3896         G1,G2,...: <matrices> generating a finite matrix group, r: an <int>
3897         where -|r| to |r| is the range of coefficients of the random
3898         combinations of bases elements, flags: an optional <intvec> with three
3899         entries, if the first one equals 0 (also the default), the programme
3900         attempts to compute the Molien series and Reynolds operator, if it
3901         equals 1, the programme is told that the Molien series should not be
3902         computed, if it equals -1 characteristic 0 is simulated, i.e. the
3903         Molien series is computed as if the base field were characteristic 0
3904         (the user must choose a field of large prime characteristic, e.g.
3905         32003) and if the first one is anything else, it means that the
3906         characteristic of the base field divides the group order, the second
3907         component should give the size of intervals between canceling common
3908         factors in the expansion of the Molien series, 0 (the default) means
3909         only once after generating all terms, in prime characteristic also a
3910         negative number can be given to indicate that common factors should
3911         always be canceled when the expansion is simple (the root of the
3912         extension field does not occur among the coefficients)
3913DISPLAY: information about the various stages of the programme if the third
3914         flag does not equal 0
3915RETURN:  primary invariants (type <matrix>) of the invariant ring and if
3916         computable Reynolds operator (type <matrix>) and Molien series (type
3917         <matrix>), if the first flag is 1 and we are in the non-modular case
3918         then an <intvec> is returned giving some of the degrees where no
3919         non-trivial homogeneous invariants can be found
3920EXAMPLE: example primary_invariants_random; shows an example
3921THEORY:  Bases of homogeneous invariants are generated successively and random
3922         linear combinations are chosen as primary invariants that lower the
3923         dimension of the ideal generated by the previously found invariants
3924         (see paper "Generating a Noetherian Normalization of the Invariant Ring
3925         of a Finite Group" by Decker, Heydtmann, Schreyer (1997) to appear in
3926         JSC).
3927{
3928 // ----------------- checking input and setting flags ------------------------
3929  if (size(#)<2)
3930  { "ERROR:   There are too few parameters.";
3931    return();
3932  }
3933  int ch=char(basering);               // the algorithms depend very much on the
3934                                       // characteristic of the ground field
3935  int n=nvars(basering);               // n is the number of variables, as well
3936                                       // as the size of the matrices, as well
3937                                       // as the number of primary invariants,
3938                                       // we should get
3939  int gen_num;
3940  int mol_flag,v;
3941  if (typeof(#[size(#)])=="intvec" && typeof(#[size(#)-1])=="int")
3942  { if (size(#[size(#)])<>3)
3943    { "ERROR:   <intvec> should have three entries.";
3944      return();
3945    }
3946    gen_num=size(#)-2;
3947    mol_flag=#[size(#)][1];
3948    if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
3949    { "ERROR:   the second component of <intvec> should be >=0";
3950      return();
3951    }
3952    int interval=#[size(#)][2];
3953    v=#[size(#)][3];
3954    int max=#[size(#)-1];
3955    if (gen_num==0)
3956    { "ERROR:   There are no generators of a finite matrix group given.";
3957      return();
3958    }
3959  }
3960  else
3961  { if (typeof(#[size(#)])=="int")
3962    { gen_num=size(#)-1;
3963      mol_flag=0;
3964      int interval=0;
3965      v=0;
3966      int max=#[size(#)];
3967    }
3968    else
3969    { "ERROR:   If the two last parameters are not <int> and <intvec>, the last";
3970      "         parameter should be an <int>.";
3971      return();
3972    }
3973  }
3974  for (int i=1;i<=gen_num;i=i+1)
3975  { if (typeof(#[i])=="matrix")
3976    { if (nrows(#[i])<>n or ncols(#[i])<>n)
3977      { "ERROR:   The number of variables of the base ring needs to be the same";
3978        "         as the dimension of the square matrices";
3979        return();
3980      }
3981    }
3982    else
3983    { "ERROR:   The first parameters should be a list of matrices";
3984      return();
3985    }
3986  }
3987 //----------------------------------------------------------------------------
3988  if (mol_flag==0)
3989  { if (ch==0)
3990    { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v));
3991                                       // one will contain Reynolds operator and
3992                                       // the other enumerator and denominator
3993                                       // of Molien series
3994      matrix P=primary_char0_random(REY,M,max,v);
3995      return(P,REY,M);
3996    }
3997    else
3998    { list L=group_reynolds(#[1..gen_num],v);
3999      if (L[1]<>0)                     // testing whether we are in the modular
4000      { string newring="aksldfalkdsflkj"; // case
4001        if (minpoly==0)
4002        { if (v)
4003          { "  We are dealing with the non-modular case.";
4004          }
4005          molien(L[2..size(L)],newring,intvec(0,interval,v));
4006          matrix P=primary_charp_random(L[1],newring,max,v);
4007          return(P,L[1],newring);
4008        }
4009        else
4010        { if (v)
4011          { "  Since it is impossible for this programme to calculate the Molien series for";
4012            "  invariant rings over extension fields of prime characteristic, we have to";
4013            "  continue without it.";
4014            "";
4015
4016          }
4017          list l=primary_charp_no_molien_random(L[1],max,v);
4018          if (size(l)==2)
4019          { return(l[1],L[1],l[2]);
4020          }
4021          else
4022          { return(l[1],L[1]);
4023          }
4024        }
4025      }
4026      else                             // the modular case
4027      { if (v)
4028        { "  There is also no Molien series, we can make use of...";
4029          "";
4030          "  We can start looking for primary invariants...";
4031          "";
4032        }
4033        return(primary_charp_without_random(#[1..gen_num],max,v));
4034      }
4035    }
4036  }
4037  if (mol_flag==1)                     // the user wants no calculation of the
4038  { list L=group_reynolds(#[1..gen_num],v); // Molien series
4039    if (ch==0)
4040    { list l=primary_char0_no_molien_random(L[1],max,v);
4041      if (size(l)==2)
4042      { return(l[1],L[1],l[2]);
4043      }
4044      else
4045      { return(l[1],L[1]);
4046      }
4047    }
4048    else
4049    { if (L[1]<>0)                     // testing whether we are in the modular
4050      { list l=primary_charp_no_molien_random(L[1],max,v); // case
4051        if (size(l)==2)
4052        { return(l[1],L[1],l[2]);
4053        }
4054        else
4055        { return(l[1],L[1]);
4056        }
4057      }
4058      else                             // the modular case
4059      { if (v)
4060        { "  We can start looking for primary invariants...";
4061          "";
4062        }
4063        return(primary_charp_without_random(#[1..gen_num],max,v));
4064      }
4065    }
4066  }
4067  if (mol_flag==-1)
4068  { if (ch==0)
4069    { "ERROR:   Characteristic 0 can only be simulated in characteristic p>>0.";
4070      return();
4071    }
4072    list L=group_reynolds(#[1..gen_num],v);
4073    string newring="aksldfalkdsflkj";
4074    molien(L[2..size(L)],newring,intvec(1,interval,v));
4075    matrix P=primary_charp_random(L[1],newring,max,v);
4076    return(P,L[1],newring);
4077  }
4078  else                                 // the user specified that the
4079  { if (ch==0)                         // characteristic divides the group order
4080    { "ERROR:   The characteristic cannot divide the group order when it is 0.";
4081      return();
4082    }
4083    if (v)
4084    { "";
4085    }
4086    return(primary_charp_without_random(#[1..gen_num],max,v));
4087  }
4088}
4089example
4090{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
4091  echo=2;
4092         ring R=0,(x,y,z),dp;
4093         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
4094         list L=primary_invariants_random(A,1);
4095         print(L[1]);
4096}
4097
4098proc concat_intmat(intmat A,intmat B)
4099{ int n=nrows(A);
4100  int m1=ncols(A);
4101  int m2=ncols(B);
4102  intmat C[n][m1+m2];
4103  C[1..n,1..m1]=A[1..n,1..m1];
4104  C[1..n,m1+1..m1+m2]=B[1..n,1..m2];
4105  return(C);
4106}
4107
4108proc power_products(intvec deg_vec,int d)
4109USAGE:   power_products(dv,d);
4110         dv: an <intvec> giving the degrees of homogeneous polynomials, d: the
4111         degree of the desired power products
4112RETURN:  a size(dv)*m <intmat> where each column ought to be interpreted as
4113         containing the exponents of the corresponding polynomials. The product
4114         of the powers is then homogeneous of degree d.
4115EXAMPLE: example power_products; gives an example
4116{ if (d<=0)
4117  { "ERROR:   The <int> may not be <= 0";
4118    return();
4119  }
4120  int d_neu,j,nc;
4121  int s=size(deg_vec);
4122  intmat PP[s][1];
4123  intmat TEST[s][1];
4124  for (int i=1;i<=s;i=i+1)
4125  { if (i<0)
4126    { "ERROR:   The entries of <intvec> may not be <= 0";
4127      return();
4128    }
4129    d_neu=d-deg_vec[i];
4130    if (d_neu>0)
4131    { intmat PPd_neu=power_products(intvec(deg_vec[i..s]),d_neu);
4132      if (size(ideal(PPd_neu))<>0)
4133      { nc=ncols(PPd_neu);
4134        intmat PPd_neu_gross[s][nc];
4135        PPd_neu_gross[i..s,1..nc]=PPd_neu[1..s-i+1,1..nc];
4136        for (j=1;j<=nc;j=j+1)
4137        { PPd_neu_gross[i,j]=PPd_neu_gross[i,j]+1;
4138        }
4139        PP=concat_intmat(PP,PPd_neu_gross);
4140        kill PPd_neu_gross;
4141      }
4142      kill PPd_neu;
4143    }
4144    if (d_neu==0)
4145    { intmat PPd_neu[s][1];
4146      PPd_neu[i,1]=1;
4147      PP=concat_intmat(PP,PPd_neu);
4148      kill PPd_neu;
4149    }
4150  }
4151  if (matrix(PP)<>matrix(TEST))
4152  { PP=compress(PP);
4153  }
4154  return(PP);
4155}
4156example
4157{ echo=2;
4158         intvec dv=5,5,5,10,10;
4159         print(power_products(dv,10));
4160         print(power_products(dv,7));
4161}
4162
4163proc secondary_char0 (matrix P, matrix REY, matrix M, list #)
4164USAGE:   secondary_char0(P,REY,M[,v]);
4165         P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix>
4166         representing the Reynolds operator, M: a 1x2 <matrix> giving enumerator
4167         and denominator of the Molien series, v: an optional <int>
4168ASSUME:  n is the number of variables of the basering, g the size of the group,
4169         REY is the 1st return value of group_reynolds(), reynolds_molien() or
4170         the second one of primary_invariants(), M the return value of molien()
4171         or the second one of reynolds_molien() or the third one of
4172         primary_invariants()
4173RETURN:  secondary invariants of the invariant ring (type <matrix>) and
4174         irreducible secondary invariants (type <matrix>)
4175DISPLAY: information if v does not equal 0
4176EXAMPLE: example secondary_char0; shows an example
4177THEORY:  The secondary invariants are calculated by finding a basis (in terms of
4178         monomials) of the basering modulo the primary invariants, mapping those
4179         to invariants with the Reynolds operator and using these images or
4180         their power products such that they are linearly independent modulo the
4181         primary invariants (see paper "Some Algorithms in Invariant Theory of
4182         Finite Groups" by Kemper and Steel (1997)).
4183{ def br=basering;
4184  degBound=0;
4185 //----------------- checking input and setting verbose mode ------------------
4186  if (char(br)<>0)
4187  { "ERROR:   secondary_char0 should only be used with rings of characteristic 0.";
4188    return();
4189  }
4190  int i;
4191  if (size(#)>0)
4192  { if (typeof(#[size(#)])=="int")
4193    { int v=#[size(#)];
4194    }
4195    else
4196    { int v=0;
4197    }
4198  }
4199  else
4200  { int v=0;
4201  }
4202  int n=nvars(br);                     // n is the number of variables, as well
4203                                       // as the size of the matrices, as well
4204                                       // as the number of primary invariants,
4205                                       // we should get
4206  if (ncols(P)<>n)
4207  { "ERROR:   The first parameter ought to be the matrix of the primary";
4208    "         invariants."
4209    return();
4210  }
4211  if (ncols(REY)<>n)
4212  { "ERROR:   The second parameter ought to be the Reynolds operator."
4213    return();
4214  }
4215  if (ncols(M)<>2 or nrows(M)<>1)
4216  { "ERROR:   The third parameter ought to be the Molien series."
4217    return();
4218  }
4219  if (v && voice==2)
4220  { "";
4221  }
4222  int j, m, counter;
4223 //- finding the polynomial giving number and degrees of secondary invariants -
4224  poly p=1;
4225  for (j=1;j<=n;j=j+1)                 // calculating the denominator of the
4226  { p=p*(1-var(1)^deg(P[j]));          // Hilbert series of the ring generated
4227  }                                    // by the primary invariants -
4228  matrix s[1][2]=M[1,1]*p,M[1,2];      // s is used for canceling
4229  s=matrix(syz(ideal(s)));
4230  p=s[2,1];                            // the polynomial telling us where to
4231                                       // search for secondary invariants
4232  map slead=br,ideal(0);
4233  p=1/slead(p)*p;                      // smallest term of p needs to be 1
4234  if (v)
4235  { "  Polynomial telling us where to look for secondary invariants:";
4236    "   "+string(p);
4237    "";
4238  }
4239  matrix dimmat=coeffs(p,var(1));      // dimmat will contain the number of
4240                                       // secondary invariants, we need to find
4241                                       // of a certain degree -
4242  m=nrows(dimmat);                     // m-1 is the highest degree
4243  if (v)
4244  { "  In degree 0 we have: 1";
4245    "";
4246  }
4247 //-------------------------- initializing variables --------------------------
4248  intmat PP;
4249  poly pp;
4250  int k;
4251  intvec deg_vec;
4252  ideal sP=std(ideal(P));
4253  ideal TEST,B,IS;
4254  ideal S=1;                           // 1 is the first secondary invariant -
4255 //--------------------- generating secondary invariants ----------------------
4256  for (i=2;i<=m;i=i+1)                 // going through dimmat -
4257  { if (int(dimmat[i,1])<>0)           // when it is == 0 we need to find 0
4258    {                                  // elements in the current degree (i-1)
4259      if (v)
4260      { "  Searching in degree "+string(i-1)+", we need to find "+string(int(dimmat[i,1]))+" invariant(s)...";
4261      }
4262      TEST=sP;
4263      counter=0;                       // we'll count up to degvec[i]
4264      if (IS[1]<>0)
4265      { PP=power_products(deg_vec,i-1); // finding power products of irreducible
4266      }                                // secondary invariants
4267      if (size(ideal(PP))<>0)
4268      { for (j=1;j<=ncols(PP);j=j+1)   // going through all the power products
4269        { pp=1;
4270          for (k=1;k<=nrows(PP);k=k+1)
4271          { pp=pp*IS[1,k]^PP[k,j];
4272          }
4273          if (reduce(pp,TEST)<>0)
4274          { S=S,pp;
4275            counter=counter+1;
4276            if (v)
4277            { "  We find: "+string(pp);
4278            }
4279            if (int(dimmat[i,1])<>counter)
4280            { TEST=std(TEST+ideal(NF(pp,TEST))); // should be replaced by next
4281                                                 // line soon
4282            // TEST=std(TEST,NF(pp,TEST));
4283            }
4284            else
4285            { break;
4286            }
4287          }
4288        }
4289      }
4290      if (int(dimmat[i,1])<>counter)
4291      { B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6); // B contains
4292                                       // images of kbase(sP,i-1) under the
4293                                       // Reynolds operator that are linearly
4294                                       // independent and that don't reduce to
4295                                       // 0 modulo sP -
4296        if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of
4297        { S=S,B;                       // B
4298          IS=IS+B;
4299          if (deg_vec[1]==0)
4300          { deg_vec=i-1;
4301            if (v)
4302            { "  We find: "+string(B[1]);
4303            }
4304            for (j=2;j<=int(dimmat[i,1]);j=j+1)
4305            { deg_vec=deg_vec,i-1;
4306              if (v)
4307              { "  We find: "+string(B[j]);
4308              }
4309            }
4310          }
4311          else
4312          { for (j=1;j<=int(dimmat[i,1]);j=j+1)
4313            { deg_vec=deg_vec,i-1;
4314              if (v)
4315              { "  We find: "+string(B[j]);
4316              }
4317            }
4318          }
4319        }
4320        else
4321        { j=0;                         // j goes through all of B -
4322          while (int(dimmat[i,1])<>counter) // need to find dimmat[i,1]
4323          {                            // invariants that are linearly
4324                                       // independent modulo TEST
4325            j=j+1;
4326            if (reduce(B[j],TEST)<>0)  // B[j] should be added
4327            { S=S,B[j];
4328              IS=IS+ideal(B[j]);
4329              if (deg_vec[1]==0)
4330              { deg_vec[1]=i-1;
4331              }
4332              else
4333              { deg_vec=deg_vec,i-1;
4334              }
4335              counter=counter+1;
4336              if (v)
4337              { "  We find: "+string(B[j]);
4338              }
4339              if (int(dimmat[i,1])<>counter)
4340              { TEST=std(TEST+ideal(NF(B[j],TEST))); // should be replaced by
4341                                                     // next line
4342              // TEST=std(TEST,NF(B[j],TEST));
4343              }
4344            }
4345          }
4346        }
4347      }
4348      if (v)
4349      { "";
4350      }
4351    }
4352  }
4353  if (v)
4354  { "  We're done!";
4355    "";
4356  }
4357  return(matrix(S),matrix(IS));
4358}
4359example
4360{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
4361  echo=2;
4362         ring R=0,(x,y,z),dp;
4363         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
4364         list L=primary_invariants(A);
4365         matrix S,IS=secondary_char0(L[1..3]);
4366         print(S);
4367         print(IS);
4368}
4369
4370proc secondary_charp (matrix P, matrix REY, string ring_name, list #)
4371USAGE:   secondary_charp(P,REY,ringname[,v]);
4372         P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix>
4373         representing the Reynolds operator, ringname: a <string> giving the
4374         name of a ring of characteristic 0 where the Molien series is stored,
4375         v: an optional <int>
4376ASSUME:  n is the number of variables of the basering, g the size of the group,
4377         REY is the 1st return value of group_reynolds(), reynolds_molien() or
4378         the second one of primary_invariants(), `ringname` is ring of
4379         characteristic 0 that has been created by molien() or reynolds_molien()
4380         or primary_invariants()
4381RETURN:  secondary invariants of the invariant ring (type <matrix>) and
4382         irreducible secondary invariants (type <matrix>)
4383DISPLAY: information if v does not equal 0
4384EXAMPLE: example secondary_charp; shows an example
4385THEORY:  The secondary invariants are calculated by finding a basis (in terms of
4386         monomials) of the basering modulo the primary invariants, mapping those
4387         to invariants with the Reynolds operator and using these images or
4388         their power products such that they are linearly independent modulo the
4389         primary invariants (see paper "Some Algorithms in Invariant Theory of
4390         Finite Groups" by Kemper and Steel (1997)).
4391{ def br=basering;
4392  degBound=0;
4393 //---------------- checking input and setting verbose mode -------------------
4394  if (char(br)==0)
4395  { "ERROR:   secondary_charp should only be used with rings of characteristic p>0.";
4396    return();
4397  }
4398  int i;
4399  if (size(#)>0)
4400  { if (typeof(#[size(#)])=="int")
4401    { int v=#[size(#)];
4402    }
4403    else
4404    { int v=0;
4405    }
4406  }
4407  else
4408  { int v=0;
4409  }
4410  int n=nvars(br);                     // n is the number of variables, as well
4411                                       // as the size of the matrices, as well
4412                                       // as the number of primary invariants,
4413                                       // we should get
4414  if (ncols(P)<>n)
4415  { "ERROR:   The first parameter ought to be the matrix of the primary";
4416    "         invariants."
4417    return();
4418  }
4419  if (ncols(REY)<>n)
4420  { "ERROR:   The second parameter ought to be the Reynolds operator."
4421    return();
4422  }
4423  if (typeof(`ring_name`)<>"ring")
4424  { "ERROR:   The <string> should give the name of the ring where the Molien."
4425    "         series is stored.";
4426    return();
4427  }
4428  if (v && voice==2)
4429  { "";
4430  }
4431  int j, m, counter, d;
4432  intvec deg_dim_vec;
4433 //- finding the polynomial giving number and degrees of secondary invariants -
4434  for (j=1;j<=n;j=j+1)
4435  { deg_dim_vec[j]=deg(P[j]);
4436  }
4437  setring `ring_name`;
4438  poly p=1;
4439  for (j=1;j<=n;j=j+1)                 // calculating the denominator of the
4440  { p=p*(1-var(1)^deg_dim_vec[j]);     // Hilbert series of the ring generated
4441  }                                    // by the primary invariants -
4442  matrix s[1][2]=M[1,1]*p,M[1,2];      // s is used for canceling
4443  s=matrix(syz(ideal(s)));
4444  p=s[2,1];                            // the polynomial telling us where to
4445                                       // search for secondary invariants
4446  map slead=basering,ideal(0);
4447  p=1/slead(p)*p;                      // smallest term of p needs to be 1
4448  if (v)
4449  { "  Polynomial telling us where to look for secondary invariants:";
4450    "   "+string(p);
4451    "";
4452  }
4453  matrix dimmat=coeffs(p,var(1));      // dimmat will contain the number of
4454                                       // secondary invariants, we need to find
4455                                       // of a certain degree -
4456  m=nrows(dimmat);                     // m-1 is the highest degree
4457  deg_dim_vec=1;
4458  for (j=2;j<=m;j=j+1)
4459  { deg_dim_vec=deg_dim_vec,int(dimmat[j,1]);
4460  }
4461  if (v)
4462  { "  In degree 0 we have: 1";
4463    "";
4464  }
4465 //------------------------ initializing variables ----------------------------
4466  setring br;
4467  intmat PP;
4468  poly pp;
4469  int k;
4470  intvec deg_vec;
4471  ideal sP=std(ideal(P));
4472  ideal TEST,B,IS;
4473  ideal S=1;                           // 1 is the first secondary invariant
4474 //------------------- generating secondary invariants ------------------------
4475  for (i=2;i<=m;i=i+1)                 // going through deg_dim_vec -
4476  { if (deg_dim_vec[i]<>0)             // when it is == 0 we need to find 0
4477    {                                  // elements in the current degree (i-1)
4478      if (v)
4479      { "  Searching in degree "+string(i-1)+", we need to find "+string(deg_dim_vec[i])+" invariant(s)...";
4480      }
4481      TEST=sP;
4482      counter=0;                       // we'll count up to degvec[i]
4483      if (IS[1]<>0)
4484      { PP=power_products(deg_vec,i-1); // generating power products of
4485      }                                // irreducible secondary invariants
4486      if (size(ideal(PP))<>0)
4487      { for (j=1;j<=ncols(PP);j=j+1)   // going through all of those
4488        { pp=1;
4489          for (k=1;k<=nrows(PP);k=k+1)
4490          { pp=pp*IS[1,k]^PP[k,j];
4491          }
4492          if (reduce(pp,TEST)<>0)
4493          { S=S,pp;
4494            counter=counter+1;
4495            if (v)
4496            { "  We find: "+string(pp);
4497            }
4498            if (deg_dim_vec[i]<>counter)
4499            { TEST=std(TEST+ideal(NF(pp,TEST))); // should be soon replaced by
4500                                                 // next line
4501            // TEST=std(TEST,NF(pp,TEST));
4502            }
4503            else
4504            { break;
4505            }
4506          }
4507        }
4508      }
4509      if (deg_dim_vec[i]<>counter)
4510      { B=sort_of_invariant_basis(sP,REY,i-1,deg_dim_vec[i]*6); // B contains
4511                                       // images of kbase(sP,i-1) under the
4512                                       // Reynolds operator that are linearly
4513                                       // independent and that don't reduce to
4514                                       // 0 modulo sP -
4515        if (counter==0 && ncols(B)==deg_dim_vec[i]) // then we can add all of B
4516        { S=S,B;
4517          IS=IS+B;
4518          if (deg_vec[1]==0)
4519          { deg_vec=i-1;
4520            if (v)
4521            { "  We find: "+string(B[1]);
4522            }
4523            for (j=2;j<=deg_dim_vec[i];j=j+1)
4524            { deg_vec=deg_vec,i-1;
4525              if (v)
4526              { "  We find: "+string(B[j]);
4527              }
4528            }
4529          }
4530          else
4531          { for (j=1;j<=deg_dim_vec[i];j=j+1)
4532            { deg_vec=deg_vec,i-1;
4533              if (v)
4534              { "  We find: "+string(B[j]);
4535              }
4536            }
4537          }
4538        }
4539        else
4540        { j=0;                         // j goes through all of B -
4541          while (deg_dim_vec[i]<>counter) // need to find deg_dim_vec[i]
4542          {                            // invariants that are linearly
4543                                       // independent modulo TEST
4544            j=j+1;
4545            if (reduce(B[j],TEST)<>0)   // B[j] should be added
4546            { S=S,B[j];
4547              IS=IS+ideal(B[j]);
4548              if (deg_vec[1]==0)
4549              { deg_vec[1]=i-1;
4550              }
4551              else
4552              { deg_vec=deg_vec,i-1;
4553              }
4554              counter=counter+1;
4555              if (v)
4556              { "  We find: "+string(B[j]);
4557              }
4558              if (deg_dim_vec[i]<>counter)
4559              { TEST=std(TEST+ideal(NF(B[j],TEST))); // should be soon replaced
4560                                                     // by next line
4561              // TEST=std(TEST,NF(B[j],TEST));
4562              }
4563            }
4564          }
4565        }
4566      }
4567      if (v)
4568      { "";
4569      }
4570    }
4571  }
4572  if (v)
4573  { "  We're done!";
4574    "";
4575  }
4576  if (ring_name=="aksldfalkdsflkj")
4577  { kill `ring_name`;
4578  }
4579  return(matrix(S),matrix(IS));
4580}
4581example
4582{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into";
4583  "         characteristic 3)";
4584  echo=2;
4585         ring R=3,(x,y,z),dp;
4586         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
4587         list L=primary_invariants(A);
4588         matrix S,IS=secondary_charp(L[1..size(L)]);
4589         print(S);
4590         print(IS);
4591}
4592
4593proc secondary_no_molien (matrix P, matrix REY, list #)
4594USAGE:   secondary_no_molien(P,REY[,deg_vec,v]);
4595         P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix>
4596         representing the Reynolds operator, deg_vec: an optional <intvec>
4597         listing some degrees where no non-trivial homogeneous invariants can be
4598         found, v: an optional <int>
4599ASSUME:  n is the number of variables of the basering, g the size of the group,
4600         REY is the 1st return value of group_reynolds(), reynolds_molien() or
4601         the second one of primary_invariants(), deg_vec is the second return
4602         value of primary_char0_no_molien(), primary_charp_no_molien(),
4603         primary_char0_no_molien_random() or primary_charp_no_molien_random()
4604RETURN:  secondary invariants of the invariant ring (type <matrix>)
4605DISPLAY: information if v does not equal 0
4606EXAMPLE: example secondary_no_molien; shows an example
4607THEORY:  The secondary invariants are calculated by finding a basis (in terms of
4608         monomials) of the basering modulo the primary invariants, mapping those
4609         to invariants with the Reynolds operator and using these images as
4610         candidates for secondary invariants.
4611{ int i;
4612  degBound=0;
4613 //------------------ checking input and setting verbose ----------------------
4614  if (size(#)==1 or size(#)==2)
4615  { if (typeof(#[size(#)])=="int")
4616    { if (size(#)==2)
4617      { if (typeof(#[size(#)-1])=="intvec")
4618        { intvec deg_vec=#[size(#)-1];
4619        }
4620        else
4621        { "ERROR:   the third parameter should be an <intvec>";
4622          return();
4623        }
4624      }
4625      int v=#[size(#)];
4626    }
4627    else
4628    { if (size(#)==1)
4629      { if (typeof(#[size(#)])=="intvec")
4630        { intvec deg_vec=#[size(#)];
4631          int v=0;
4632        }
4633        else
4634        { "ERROR:   the third parameter should be an <intvec>";
4635          return();
4636        }
4637      }
4638      else
4639      { "ERROR:   wrong list of parameters";
4640        return();
4641      }
4642    }
4643  }
4644  else
4645  { if (size(#)>2)
4646    { "ERROR:   there are too many parameters";
4647      return();
4648    }
4649    int v=0;
4650  }
4651  int n=nvars(basering);               // n is the number of variables, as well
4652                                       // as the size of the matrices, as well
4653                                       // as the number of primary invariants,
4654                                       // we should get
4655  if (ncols(P)<>n)
4656  { "ERROR:   The first parameter ought to be the matrix of the primary";
4657    "         invariants."
4658    return();
4659  }
4660  if (ncols(REY)<>n)
4661  { "ERROR:   The second parameter ought to be the Reynolds operator."
4662    return();
4663  }
4664  if (v && voice==2)
4665  { "";
4666  }
4667  int j, m, d;
4668  int max=1;
4669  for (j=1;j<=n;j=j+1)
4670  { max=max*deg(P[j]);
4671  }
4672  max=max/nrows(REY);
4673  if (v)
4674  { "  We need to find "+string(max)+" secondary invariants.";
4675    "";
4676    "  In degree 0 we have: 1";
4677    "";
4678  }
4679 //------------------------- initializing variables ---------------------------
4680  ideal sP=std(ideal(P));
4681  ideal B, TEST;
4682  ideal S=1;                           // 1 is the first secondary invariant
4683  int counter=1;
4684  i=0;
4685  if (defined(deg_vec)<>voice)
4686  { intvec deg_vec;
4687  }
4688  int k=1;
4689 //--------------------- generating secondary invariants ----------------------
4690  while (counter<>max)
4691  { i=i+1;
4692    if (deg_vec[k]<>i)
4693    { if (v)
4694      { "  Searching in degree "+string(i)+"...";
4695      }
4696      B=sort_of_invariant_basis(sP,REY,i,max); // B contains images of
4697                                       // kbase(sP,i) under the Reynolds
4698                                       // operator that are linearly independent
4699                                       // and that don't reduce to 0 modulo sP
4700      TEST=sP;
4701      for (j=1;j<=ncols(B);j=j+1)
4702      {                                // that are linearly independent modulo
4703                                       // TEST
4704        if (reduce(B[j],TEST)<>0)      // B[j] should be added
4705        { S=S,B[j];
4706          counter=counter+1;
4707          if (v)
4708          { "  We find: "+string(B[j]);
4709          }
4710          if (counter==max)
4711          { break;
4712          }
4713          else
4714          { if (j<>ncols(B))
4715            { TEST=std(TEST+ideal(NF(B[j],TEST))); // should soon be replaced by
4716                                                   // next line
4717            // TEST=std(TEST,NF(B[j],TEST));
4718            }
4719          }
4720        }
4721      }
4722    }
4723    else
4724    { if (size(deg_vec)==k)
4725      { k=1;
4726      }
4727      else
4728      { k=k+1;
4729      }
4730    }
4731  }
4732  if (v)
4733  { "";
4734  }
4735  if (v)
4736  { "  We're done!";
4737    "";
4738  }
4739  return(matrix(S));
4740}
4741example
4742{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
4743  echo=2;
4744         ring R=0,(x,y,z),dp;
4745         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
4746         list L=primary_invariants(A,intvec(1,1,0));
4747         matrix S=secondary_no_molien(L[1..3]);
4748         print(S);
4749}
4750
4751proc secondary_with_irreducible_ones_no_molien (matrix P, matrix REY, list #)
4752USAGE:   secondary_with_irreducible_ones_no_molien(P,REY[,v]);
4753         P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix>
4754         representing the Reynolds operator, v: an optional <int>
4755ASSUME:  n is the number of variables of the basering, g the size of the group,
4756         REY is the 1st return value of group_reynolds(), reynolds_molien() or
4757         the second one of primary_invariants()
4758RETURN:  secondary invariants of the invariant ring (type <matrix>) and
4759         irreducible secondary invariants (type <matrix>)
4760DISPLAY: information if v does not equal 0
4761EXAMPLE: example secondary_with_irreducible_ones_no_molien; shows an example
4762THEORY:  The secondary invariants are calculated by finding a basis (in terms of
4763         monomials) of the basering modulo the primary invariants, mapping those
4764         to invariants with the Reynolds operator and using these images or
4765         their power products such that they are linearly independent modulo the
4766         primary invariants (see paper "Some Algorithms in Invariant Theory of
4767         Finite Groups" by Kemper and Steel (1997)).
4768{ int i;
4769  degBound=0;
4770 //--------------------- checking input and setting verbose mode --------------
4771  if (size(#)==1 or size(#)==2)
4772  { if (typeof(#[size(#)])=="int")
4773    { if (size(#)==2)
4774      { if (typeof(#[size(#)-1])=="intvec")
4775        { intvec deg_vec=#[size(#)-1];
4776        }
4777        else
4778        { "ERROR:   the third parameter should be an <intvec>";
4779          return();
4780        }
4781      }
4782      int v=#[size(#)];
4783    }
4784    else
4785    { if (size(#)==1)
4786      { if (typeof(#[size(#)])=="intvec")
4787        { intvec deg_vec=#[size(#)];
4788          int v=0;
4789        }
4790        else
4791        { "ERROR:   the third parameter should be an <intvec>";
4792          return();
4793        }
4794      }
4795      else
4796      { "ERROR:   wrong list of parameters";
4797        return();
4798      }
4799    }
4800  }
4801  else
4802  { if (size(#)>2)
4803    { "ERROR:   there are too many parameters";
4804      return();
4805    }
4806    int v=0;
4807  }
4808  int n=nvars(basering);               // n is the number of variables, as well
4809                                       // as the size of the matrices, as well
4810                                       // as the number of primary invariants,
4811                                       // we should get
4812  if (ncols(P)<>n)
4813  { "ERROR:   The first parameter ought to be the matrix of the primary";
4814    "         invariants."
4815    return();
4816  }
4817  if (ncols(REY)<>n)
4818  { "ERROR:   The second parameter ought to be the Reynolds operator."
4819    return();
4820  }
4821  if (v && voice==2)
4822  { "";
4823  }
4824  int j, m, d;
4825  int max=1;
4826  for (j=1;j<=n;j=j+1)
4827  { max=max*deg(P[j]);
4828  }
4829  max=max/nrows(REY);
4830  if (v)
4831  { "  We need to find "+string(max)+" secondary invariants.";
4832    "";
4833    "  In degree 0 we have: 1";
4834    "";
4835  }
4836 //------------------------ initializing variables ----------------------------
4837  intmat PP;
4838  poly pp;
4839  int k;
4840  intvec irreducible_deg_vec;
4841  ideal sP=std(ideal(P));
4842  ideal B,TEST,IS;
4843  ideal S=1;                           // 1 is the first secondary invariant
4844  int counter=1;
4845  i=0;
4846  if (defined(deg_vec)<>voice)
4847  { intvec deg_vec;
4848  }
4849  int l=1;
4850 //------------------- generating secondary invariants ------------------------
4851  while (counter<>max)
4852  { i=i+1;
4853    if (deg_vec[l]<>i)
4854    { if (v)
4855      { "  Searching in degree "+string(i)+"...";
4856      }
4857      TEST=sP;
4858      if (IS[1]<>0)
4859      { PP=power_products(irreducible_deg_vec,i);  // generating all power
4860      }                                // products of irreducible secondary
4861                                       // invariants
4862      if (size(ideal(PP))<>0)
4863      { for (j=1;j<=ncols(PP);j=j+1)   // going through all those power products
4864        { pp=1;
4865          for (k=1;k<=nrows(PP);k=k+1)
4866          { pp=pp*IS[1,k]^PP[k,j];
4867          }
4868          if (reduce(pp,TEST)<>0)
4869          { S=S,pp;
4870            counter=counter+1;
4871            if (v)
4872            { "  We find: "+string(pp);
4873            }
4874            if (counter<>max)
4875            { TEST=std(TEST+ideal(NF(pp,TEST))); // should soon be replaced by
4876                                                 // next line
4877            // TEST=std(TEST,NF(pp,TEST));
4878            }
4879            else
4880            { break;
4881            }
4882          }
4883        }
4884      }
4885      if (max<>counter)
4886      { B=sort_of_invariant_basis(sP,REY,i,max); // B contains images of
4887                                       // kbase(sP,i) under the Reynolds
4888                                       // operator that are linearly independent
4889                                       // and that don't reduce to 0 modulo sP
4890        for (j=1;j<=ncols(B);j=j+1)
4891        { if (reduce(B[j],TEST)<>0)    // B[j] should be added
4892          { S=S,B[j];
4893            IS=IS+ideal(B[j]);
4894            if (irreducible_deg_vec[1]==0)
4895            { irreducible_deg_vec[1]=i;
4896            }
4897            else
4898            { irreducible_deg_vec=irreducible_deg_vec,i;
4899            }
4900            counter=counter+1;
4901            if (v)
4902            { "  We find: "+string(B[j]);
4903            }
4904            if (counter==max)
4905            { break;
4906            }
4907            else
4908            { if (j<>ncols(B))
4909              { TEST=std(TEST+ideal(NF(B[j],TEST))); // should soon be replaced
4910                                                     // by next line
4911              // TEST=std(TEST,NF(B[j],TEST));
4912              }
4913            }
4914          }
4915        }
4916      }
4917    }
4918    else
4919    { if (size(deg_vec)==l)
4920      { l=1;
4921      }
4922      else
4923      { l=l+1;
4924      }
4925    }
4926  }
4927  if (v)
4928  { "";
4929  }
4930  if (v)
4931  { "  We're done!";
4932    "";
4933  }
4934  return(matrix(S),matrix(IS));
4935}
4936example
4937{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
4938  echo=2;
4939         ring R=0,(x,y,z),dp;
4940         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
4941         list L=primary_invariants(A,intvec(1,1,0));
4942         matrix S,IS=secondary_with_irreducible_ones_no_molien(L[1..2]);
4943         print(S);
4944         print(IS);
4945}
4946
4947proc secondary_not_cohen_macaulay (matrix P, list #)
4948USAGE:   secondary_not_cohen_macaulay(P,G1,G2,...[,v]);
4949         P: a 1xn <matrix> with primary invariants, G1,G2,...: nxn <matrices>
4950         generating a finite matrix group, v: an optional <int>
4951ASSUME:  n is the number of variables of the basering
4952RETURN:  secondary invariants of the invariant ring (type <matrix>)
4953DISPLAY: information if v does not equal 0
4954EXAMPLE: example secondary_not_cohen_macaulay; shows an example
4955THEORY:  The secondary invariants are generated following "Generating Invariant
4956         Rings of Finite Groups over Arbitrary Fields" by Kemper (1996, to
4957         appear in JSC).
4958{ int i, j;
4959  degBound=0;
4960  def br=basering;
4961  int n=nvars(br);                     // n is the number of variables, as well
4962                                       // as the size of the matrices, as well
4963                                       // as the number of primary invariants,
4964                                       // we should get -
4965  if (size(#)>0)                       // checking input and setting verbose
4966  { if (typeof(#[size(#)])=="int")
4967    { int gen_num=size(#)-1;
4968      if (gen_num==0)
4969      { "ERROR:   There are no generators of the finite matrix group given.";
4970        return();
4971      }
4972      int v=#[size(#)];
4973      for (i=1;i<=gen_num;i=i+1)
4974      { if (typeof(#[i])<>"matrix")
4975        { "ERROR:   These parameters should be generators of the finite matrix group.";
4976          return();
4977        }
4978        if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
4979        { "ERROR:   matrices need to be square and of the same dimensions";
4980          return();
4981        }
4982      }
4983    }
4984    else
4985    { int v=0;
4986      int gen_num=size(#);
4987      for (i=1;i<=gen_num;i=i+1)
4988      { if (typeof(#[i])<>"matrix")
4989        { "ERROR:   These parameters should be generators of the finite matrix group.";
4990          return();
4991        }
4992        if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
4993        { "ERROR:   matrices need to be square and of the same dimensions";
4994          return();
4995        }
4996      }
4997    }
4998  }
4999  else
5000  { "ERROR:   There are no generators of the finite matrix group given.";
5001    return();
5002  }
5003  if (ncols(P)<>n)
5004  { "ERROR:   The first parameter ought to be the matrix of the primary";
5005    "         invariants."
5006    return();
5007  }
5008  if (v && voice==2)
5009  { "";
5010  }
5011  ring alskdfalkdsj=0,x,dp;
5012  matrix M[1][2]=1,(1-x)^n;            // we look at our primary invariants as
5013  export alskdfalkdsj;
5014  export M;
5015  setring br;                          // such of the subgroup that only
5016  matrix REY=matrix(maxideal(1));      // contains the identity, this means that
5017                                       // ch does not divide the order anymore,
5018                                       // this means that we can make use of the
5019                                       // Molien series again - M[1,1]/M[1,2] is
5020                                       // the Molien series of that group, we
5021                                       // now calculate the secondary invariants
5022                                       // of this subgroup in the usual fashion
5023                                       // where the primary invariants are the
5024                                       // ones from the bigger group
5025  if (v)
5026  { "  The procedure secondary_charp() is called to calculate secondary invariants";
5027    "  of the invariant ring of the trivial group with respect to the primary";
5028    "  invariants found previously.";
5029    "";
5030  }
5031  matrix trivialS=secondary_charp(P,REY,"alskdfalkdsj",v);
5032  kill alskdfalkdsj;
5033  // now we have those secondary invariants
5034  int k=ncols(trivialS);               // k is the number of the secondary
5035                                       // invariants, we just calculated
5036  if (v)
5037  { "  We calculate secondary invariants from the ones found for the trivial";
5038    "  subgroup.";
5039    "";
5040  }
5041  map f;                               // used to let generators act on
5042                                       // secondary invariants with respect to
5043                                       // the trivial group -
5044  matrix M(1)[gen_num][k];             // M(1) will contain a module
5045  ideal B;
5046  for (i=1;i<=gen_num;i=i+1)
5047  { B=ideal(matrix(maxideal(1))*transpose(#[i]));   // image of the various
5048                                       // variables under the i-th generator -
5049    f=br,B;                            // the corresponding mapping -
5050    B=f(trivialS)-trivialS;            // these relations should be 0 -
5051    M(1)[i,1..k]=B[1..k];              // we will look for the syzygies of M(1)
5052  }
5053  module M(2)=res(M(1),2)[2];
5054  int m=ncols(M(2));                   // number of generators of the module
5055                                       // M(2) -
5056  // the following steps calculates the intersection of the module M(2) with
5057  // the algebra A^k where A denote the subalgebra of the usual polynomial
5058  // ring, generated by the primary invariants
5059  string mp=string(minpoly);           // generating a ring where we can do
5060                                       // elimination
5061  execute "ring R=("+charstr(br)+"),(x(1..n),y(1..n),h),dp;";
5062  execute "minpoly=number("+mp+");";
5063  map f=br,maxideal(1);                // canonical mapping
5064  matrix M[k][m+k*n];
5065  M[1..k,1..m]=matrix(f(M(2)));        // will contain a module -
5066  matrix P=f(P);                       // primary invariants in the new ring
5067  for (i=1;i<=n;i=i+1)
5068  { for (j=1;j<=k;j=j+1)
5069    { M[j,m+(i-1)*k+j]=y(i)-P[1,i];
5070    }
5071  }
5072  M=elim(module(M),1,n);               // eliminating x(1..n), std-calculation
5073                                       // is done internally -
5074  M=homog(module(M),h);                // homogenize for 'minbase'
5075  M=minbase(module(M));
5076  setring br;
5077  ideal substitute=maxideal(1),ideal(P),1;
5078  f=R,substitute;                      // replacing y(1..n) by primary
5079                                       // invariants -
5080  M(2)=f(M);                           // M(2) is the new module
5081  m=ncols(M(2));
5082  matrix S[1][m];
5083  S=matrix(trivialS)*matrix(M(2));     // S now contains the secondary
5084                                       // invariants
5085  for (i=1; i<=m;i=i+1)
5086  { S[1,i]=S[1,i]/leadcoef(S[1,i]); // making elements nice
5087  }
5088  S=sort(ideal(S))[1];
5089  if (v)
5090  { "  These are the secondary invariants: ";
5091    for (i=1;i<=m;i=i+1)
5092    { "   "+string(S[1,i]);
5093    }
5094    "";
5095    "  We're done!";
5096    "";
5097  }
5098  if ((v or (voice==2)) && (m>1))
5099  { "  WARNING: The invariant ring might not have a Hironaka decomposition";
5100    "           if the characteristic of the coefficient field divides the";
5101    "           group order.";
5102  }
5103  return(S);
5104}
5105example
5106{ echo=2;
5107           ring R=2,(x,y,z),dp;
5108           matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
5109           list L=primary_invariants(A);
5110           matrix S=secondary_not_cohen_macaulay(L[1],A);
5111           print(S);
5112}
5113
5114proc invariant_ring (list #)
5115USAGE:   invariant_ring(G1,G2,...[,flags]);
5116         G1,G2,...: <matrices> generating a finite matrix group, flags: an
5117         optional <intvec> with three entries: if the first one equals 0, the
5118         program attempts to compute the Molien series and Reynolds operator,
5119         if it equals 1, the program is told that the Molien series should not
5120         be computed, if it equals -1 characteristic 0 is simulated, i.e. the
5121         Molien series is computed as if the base field were characteristic 0
5122         (the user must choose a field of large prime characteristic, e.g.
5123         32003) and if the first one is anything else, it means that the
5124         characteristic of the base field divides the group order (i.e. it will
5125         not even be attempted to compute the Reynolds operator or Molien
5126         series), the second component should give the size of intervals
5127         between canceling common factors in the expansion of the Molien series,
5128         0 (the default) means only once after generating all terms, in prime
5129         characteristic also a negative number can be given to indicate that
5130         common factors should always be canceled when the expansion is simple
5131         (the root of the extension field does not occur among the coefficients)
5132RETURN:  primary and secondary invariants (both of type <matrix>) generating the
5133         invariant ring with respect to the matrix group generated by the
5134         matrices in the input and irreducible secondary invariants (type
5135         <matrix>) if the Molien series was available
5136DISPLAY: information about the various stages of the program if the third flag
5137         does not equal 0
5138EXAMPLE: example invariant_ring; shows an example
5139THEORY:  Bases of homogeneous invariants are generated successively and those
5140         are chosen as primary invariants that lower the dimension of the ideal
5141         generated by the previously found invariants (see paper "Generating a
5142         Noetherian Normalization of the Invariant Ring of a Finite Group" by
5143         Decker, Heydtmann, Schreyer (1997) to appear in JSC). In the
5144         non-modular case secondary invariants are calculated by finding a
5145         basis (in terms of monomials) of the basering modulo the primary
5146         invariants, mapping to invariants with the Reynolds operator and using
5147         those or their power products such that they are linearly independent
5148         modulo the primary invariants (see paper "Some Algorithms in Invariant
5149         Theory of Finite Groups" by Kemper and Steel (1997)). In the modular
5150         case they are generated according to "Generating Invariant Rings of
5151         Finite Groups over Arbitrary Fields" by Kemper (1996, to appear in
5152         JSC).
5153{ if (size(#)==0)
5154  { "ERROR:   There are no generators given.";
5155    return();
5156  }
5157  int ch=char(basering);               // the algorithms depend very much on the
5158                                       // characteristic of the ground field -
5159  int n=nvars(basering);               // n is the number of variables, as well
5160                                       // as the size of the matrices, as well
5161                                       // as the number of primary invariants,
5162                                       // we should get
5163  int gen_num;
5164  int mol_flag, v;
5165 //------------------- checking input and setting flags -----------------------
5166  if (typeof(#[size(#)])=="intvec")
5167  { if (size(#[size(#)])<>3)
5168    { "ERROR:   The <intvec> should have three entries.";
5169      return();
5170    }
5171    gen_num=size(#)-1;
5172    mol_flag=#[size(#)][1];
5173    if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
5174    { "ERROR:   the second component of <intvec> should be >=0";
5175      return();
5176    }
5177    int interval=#[size(#)][2];
5178    v=#[size(#)][3];
5179  }
5180  else
5181  { gen_num=size(#);
5182    mol_flag=0;
5183    int interval=0;
5184    v=0;
5185  }
5186 //----------------------------------------------------------------------------
5187  if (mol_flag==0)                     // calculation Molien series will be
5188  { if (ch==0)                         // attempted -
5189    { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v)); // one
5190                                       // will contain Reynolds operator and the
5191                                       // other enumerator and denominator of
5192                                       // Molien series
5193      matrix P=primary_char0(REY,M,v);
5194      matrix S,IS=secondary_char0(P,REY,M,v);
5195      return(P,S,IS);
5196    }
5197    else
5198    { list L=group_reynolds(#[1..gen_num],v);
5199      if (L[1]<>0)                     // testing whether we are in the modular
5200      { string newring="aksldfalkdsflkj"; // case
5201        if (minpoly==0)
5202        { if (v)
5203          { "  We are dealing with the non-modular case.";
5204          }
5205          molien(L[3..size(L)],newring,L[2],intvec(0,interval,v));
5206          matrix P=primary_charp(L[1],newring,v);
5207          matrix S,IS=secondary_charp(P,L[1],newring,v];
5208          if (voice==2)
5209          { kill aksldfalkdsflkj;
5210          }
5211          return(P,S,IS);
5212        }
5213        else
5214        { if (v)
5215          { "  Since it is impossible for this programme to calculate the Molien
5216 series for";
5217            "  invariant rings over extension fields of prime characteristic, we
5218 have to";
5219            "  continue without it.";
5220            "";
5221
5222          }
5223          list l=primary_charp_no_molien(L[1],v);
5224          if (size(l)==2)
5225          { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5226          }
5227          else
5228          { matix S=secondary_no_molien(l[1],L[1],v);
5229          }
5230          return(l[1],S);
5231        }
5232      }
5233      else                             // the modular case
5234      { if (v)
5235        { "  There is also no Molien series or Reynolds operator, we can make use of...";
5236          "";
5237          "  We can start looking for primary invariants...";
5238          "";
5239        }
5240        matrix P=primary_charp_without(#[1..gen_num],v);
5241        matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5242        return(P,S);
5243      }
5244    }
5245  }
5246  if (mol_flag==1)                     // the user wants no calculation of the
5247  { list L=group_reynolds(#[1..gen_num],v); // Molien series
5248    if (ch==0)
5249    { list l=primary_char0_no_molien(L[1],v);
5250      if (size(l)==2)
5251      { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5252      }
5253      else
5254      { matix S=secondary_no_molien(l[1],L[1],v);
5255      }
5256      return(l[1],S);
5257    }
5258    else
5259    { if (L[1]<>0)                     // testing whether we are in the modular
5260      { list l=primary_charp_no_molien(L[1],v); // case
5261        if (size(l)==2)
5262        { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5263        }
5264        else
5265        { matix S=secondary_no_molien(l[1],L[1],v);
5266        }
5267        return(l[1],S);
5268      }
5269      else                             // the modular case
5270      { if (v)
5271        { "  We can start looking for primary invariants...";
5272          "";
5273        }
5274        matrix P=primary_charp_without(#[1..gen_num],v);
5275        matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5276        return(L[1],S);
5277      }
5278    }
5279  }
5280  if (mol_flag==-1)
5281  { if (ch==0)
5282    { "ERROR:   Characteristic 0 can only be simulated in characteristic p>>0.
5283";
5284      return();
5285    }
5286    list L=group_reynolds(#[1..gen_num],v);
5287    string newring="aksldfalkdsflkj";
5288    molien(L[2..size(L)],newring,intvec(1,interval,v));
5289    matrix P=primary_charp(L[1],newring,v);
5290    matrix S,IS=secondary_charp(P,L[1],newring,v);
5291    kill aksldfalkdsflkj;
5292    return(P,S,IS);
5293  }
5294  else                                 // the user specified that the
5295  { if (ch==0)                         // characteristic divides the group order
5296    { "ERROR:   The characteristic cannot divide the group order when it is 0.
5297";
5298      return();
5299    }
5300    if (v)
5301    { "";
5302    }
5303    matrix P=primary_charp_without(#[1..gen_num],v);
5304    matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5305    return(L[1],S);
5306  }
5307}
5308example
5309{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
5310  echo=2;
5311         ring R=0,(x,y,z),dp;
5312         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
5313         matrix P,S,IS=invariant_ring(A);
5314         print(P);
5315         print(S);
5316         print(IS);
5317}
5318
5319proc invariant_ring_random (list #)
5320USAGE:   invariant_ring_random(G1,G2,...,r[,flags]);
5321         G1,G2,...: <matrices> generating a finite matrix group, r: an <int>
5322         where -|r| to |r| is the range of coefficients of random
5323         combinations of bases elements that serve as primary invariants,
5324         flags: an optional <intvec> with three entries: if the first one equals
5325         0, the program attempts to compute the Molien series and Reynolds
5326         operator, if it equals 1, the program is told that the Molien series
5327         should not be computed, if it equals -1 characteristic 0 is simulated,
5328         i.e. the Molien series is computed as if the base field were
5329         characteristic 0 (the user must choose a field of large prime
5330         characteristic, e.g.  32003) and if the first one is anything else, it
5331         means that the characteristic of the base field divides the group order
5332         (i.e. it will not even be attempted to compute the Reynolds operator or
5333         Molien series), the second component should give the size of intervals
5334         between canceling common factors in the expansion of the Molien series,
5335         0 (the default) means only once after generating all terms, in prime
5336         characteristic also a negative number can be given to indicate that
5337         common factors should always be canceled when the expansion is simple
5338         (the root of the extension field does not occur among the coefficients)
5339RETURN:  primary and secondary invariants (both of type <matrix>) generating the
5340         invariant ring with respect to the matrix group generated by the
5341         matrices in the input and irreducible secondary invariants (type
5342         <matrix>) if the Molien series was available
5343DISPLAY: information about the various stages of the program if the third flag
5344         does not equal 0
5345EXAMPLE: example invariant_ring_random; shows an example
5346THEORY:  is the same as for invariant_ring except that random combinations of
5347         basis elements are chosen as candidates for primary invariants and
5348         hopefully they lower the dimension of the previously found primary
5349         invariants by the right amount.
5350{ if (size(#)<2)
5351  { "ERROR:   There are too few parameters.";
5352    return();
5353  }
5354  int ch=char(basering);               // the algorithms depend very much on the
5355                                       // characteristic of the ground field
5356  int n=nvars(basering);               // n is the number of variables, as well
5357                                       // as the size of the matrices, as well
5358                                       // as the number of primary invariants,
5359                                       // we should get
5360  int gen_num;
5361  int mol_flag, v;
5362 //------------------- checking input and setting flags -----------------------
5363  if (typeof(#[size(#)])=="intvec" && typeof(#[size(#)-1])=="int")
5364  { if (size(#[size(#)])<>3)
5365    { "ERROR:   <intvec> should have three entries.";
5366      return();
5367    }
5368    gen_num=size(#)-2;
5369    mol_flag=#[size(#)][1];
5370    if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
5371    { "ERROR:   the second component of <intvec> should be >=0";
5372      return();
5373    }
5374    int interval=#[size(#)][2];
5375    v=#[size(#)][3];
5376    int max=#[size(#)-1];
5377    if (gen_num==0)
5378    { "ERROR:   There are no generators of a finite matrix group given.";
5379      return();
5380    }
5381  }
5382  else
5383  { if (typeof(#[size(#)])=="int")
5384    { gen_num=size(#)-1;
5385      mol_flag=0;
5386      int interval=0;
5387      v=0;
5388      int max=#[size(#)];
5389    }
5390   else
5391    { "ERROR:   If the two last parameters are not <int> and <intvec>, the last";
5392      "         parameter should be an <int>.";
5393      return();
5394    }
5395  }
5396  for (int i=1;i<=gen_num;i=i+1)
5397  { if (typeof(#[i])=="matrix")
5398    { if (nrows(#[i])<>n or ncols(#[i])<>n)
5399      { "ERROR:   The number of variables of the base ring needs to be the same";
5400        "         as the dimension of the square matrices";
5401        return();
5402      }
5403    }
5404    else
5405    { "ERROR:   The first parameters should be a list of matrices";
5406      return();
5407    }
5408  }
5409 //----------------------------------------------------------------------------
5410  if (mol_flag==0)
5411  { if (ch==0)
5412    { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v)); // one
5413                                       // will contain Reynolds operator and the
5414                                       // other enumerator and denominator of
5415                                       // Molien series
5416      matrix P=primary_char0_random(REY,M,max,v);
5417      matrix S,IS=secondary_char0(P,REY,M,v);
5418      return(P,S,IS);
5419    }
5420    else
5421    { list L=group_reynolds(#[1..gen_num],v);
5422      if (L[1]<>0)                     // testing whether we are in the modular
5423      { string newring="aksldfalkdsflkj"; // case
5424        if (minpoly==0)
5425        { if (v)
5426          { "  We are dealing with the non-modular case.";
5427          }
5428          molien(L[3..size(L)],newring,L[2],intvec(0,interval,v));
5429          matrix P=primary_charp_random(L[1],newring,max,v);
5430          matrix S,IS=secondary_charp(P,L[1],newring,v);
5431          if (voice==2)
5432          { kill aksldfalkdsflkj;
5433          }
5434          return(P,S,IS);
5435        }
5436        else
5437        { if (v)
5438          { "  Since it is impossible for this programme to calculate the Molien
5439 series for";
5440            "  invariant rings over extension fields of prime characteristic, we
5441 have to";
5442            "  continue without it.";
5443            "";
5444
5445          }
5446          list l=primary_charp_no_molien_random(L[1],max,v);
5447          if (size(l)==2)
5448          { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5449          }
5450          else
5451          { matix S=secondary_no_molien(l[1],L[1],v);
5452          }
5453          return(l[1],S);
5454        }
5455      }
5456      else                             // the modular case
5457      { if (v)
5458        { "  There is also no Molien series, we can make use of...";
5459          "";
5460          "  We can start looking for primary invariants...";
5461          "";
5462        }
5463        matrix P=primary_charp_without_random(#[1..gen_num],max,v);
5464        matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5465        return(L[1],S);
5466      }
5467    }
5468  }
5469  if (mol_flag==1)                     // the user wants no calculation of the
5470  { list L=group_reynolds(#[1..gen_num],v); // Molien series
5471    if (ch==0)
5472    { list l=primary_char0_no_molien_random(L[1],max,v);
5473      if (size(l)==2)
5474      { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5475      }
5476      else
5477      { matix S=secondary_no_molien(l[1],L[1],v);
5478      }
5479      return(l[1],S);
5480    }
5481    else
5482    { if (L[1]<>0)                     // testing whether we are in the modular
5483      { list l=primary_charp_no_molien_random(L[1],max,v); // case
5484        if (size(l)==2)
5485        { matix S=secondary_no_molien(l[1],L[1],l[2],v);
5486        }
5487        else
5488        { matix S=secondary_no_molien(l[1],L[1],v);
5489        }
5490        return(l[1],S);
5491      }
5492      else                             // the modular case
5493      { if (v)
5494        { "  We can start looking for primary invariants...";
5495          "";
5496        }
5497        matrix P=primary_charp_without_random(#[1..gen_num],max,v);
5498        matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5499        return(L[1],S);
5500      }
5501    }
5502  }
5503  if (mol_flag==-1)
5504  { if (ch==0)
5505    { "ERROR:   Characteristic 0 can only be simulated in characteristic p>>0.
5506";
5507      return();
5508    }
5509    list L=group_reynolds(#[1..gen_num],v);
5510    string newring="aksldfalkdsflkj";
5511    molien(L[2..size(L)],newring,intvec(1,v));
5512    matrix P=primary_charp_random(L[1],newring,max,v);
5513    matrix S,IS=secondary_charp(P,L[1],newring,v);
5514    kill aksldfalkdsflkj;
5515    return(P,S,IS);
5516  }
5517  else                                 // the user specified that the
5518  { if (ch==0)                         // characteristic divides the group order
5519    { "ERROR:   The characteristic cannot divide the group order when it is 0.
5520";
5521      return();
5522    }
5523    if (v)
5524    { "";
5525    }
5526    matrix P=primary_charp_without_random(#[1..gen_num],max,v);
5527    matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v);
5528    return(L[1],S);
5529  }
5530}
5531example
5532{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
5533  echo=2;
5534         ring R=0,(x,y,z),dp;
5535         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
5536         matrix P,S,IS=invariant_ring_random(A,1);
5537         print(P);
5538         print(S);
5539         print(IS);
5540}
5541
5542proc algebra_containment (poly p, matrix A)
5543USAGE:   algebra_containment(p,A);
5544         p: arbitrary <poly>, A: a 1xm <matrix> giving generators of a
5545         subalgebra of the basering
5546RETURN:  1 (TRUE) (type <int>) if p is contained in the subalgebra
5547         0 (FALSE) (type <int>) if <poly> is not contained
5548DISPLAY: a representation of p in terms of algebra generators A[1,i]=y(i) if p
5549         is contained in the subalgebra
5550EXAMPLE: example algebra_containment; shows an example
5551THEORY:  The ideal of algebraic relations of the algebra generators f1,...,fm
5552         given by A is computed introducing new variables y(i) and the product
5553         order: x^a*y^b > y^d*y^e if x^a > x^d or else if y^b > y^e. p reduces
5554         to a polynomial only in the y(i) <=> p is contained in the subring
5555         generated by the polynomials in A.
5556{ degBound=0;
5557  if (nrows(A)==1)
5558  { def br=basering;
5559    int n=nvars(br);
5560    int m=ncols(A);
5561    string mp=string(minpoly);
5562    execute "ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));";
5563    execute "minpoly=number("+mp+");";
5564    ring R=0,(x(1..n),y(1..m)),(dp(n),dp(m));
5565    ideal vars=x(1..n);
5566    map emb=br,vars;
5567    ideal A=ideal(emb(A));
5568    ideal check=emb(p);
5569    for (int i=1;i<=m;i=i+1)
5570    { A[i]=A[i]-y(i);
5571    }
5572    A=std(A);
5573    check[1]=reduce(check[1],A);
5574    A=elim(check,1,n);
5575    if (A[1]<>0)
5576    { "\/\/ "+string(check);
5577      return(1);
5578    }
5579    else
5580    { return(0);
5581    }
5582  }
5583  else
5584  { "ERROR:   <matrix> may only have one row";
5585    return();
5586  }
5587}
5588example
5589{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
5590  echo=2;
5591         ring R=0,(x,y,z),dp;
5592         matrix A[1][7]=x2+y2,z2,x4+y4,1,x2z-1y2z,xyz,x3y-1xy3;
5593         poly p1=x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4;
5594         algebra_containment(p1,A);
5595         poly p2=z;
5596         algebra_containment(p2,A);
5597}
5598
5599proc module_containment(poly p, matrix P, matrix S)
5600USAGE:   module_containment(p,P,S);
5601         p: arbitrary <poly>, P: a 1xn <matrix> giving generators of an algebra,
5602         S: a 1xt <matrix> giving generators of a module over the algebra
5603         generated by P
5604ASSUME:  n is the number of variables in the basering and the generators in P
5605         are algebraically independent
5606RETURNS: 1 (TRUE) (type <int>) if p is contained in the ring
5607         0 (FALSE) type <int>) if p is not contained
5608DISPLAY: the representation of p in terms of algebra generators P[1,i]=z(i) and
5609         module generators S[1,j]=y(j) if p is contained in the module
5610EXAMPLE: example module_containment; shows an example
5611THEORY:  The ideal of algebraic relations of all the generators p1,...,pn,
5612         s1,...,st given by P and S is computed introducing new variables y(j),
5613         z(i) and the product order: x^a*y^b*z^c > x^d*y^e*z^f if x^a > x^d
5614         with respect to the lp ordering or else if z^c > z^f with respect to
5615         the dp ordering or else if y^b > y^e with respect to the lp ordering
5616         again. p reduces to a polynomial only in the y(j) and z(i) linear in
5617         the z(i)) <=> p is contained in the module.
5618{ def br=basering;
5619  degBound=0;
5620  int n=nvars(br);
5621  if (ncols(P)==n and nrows(P)==1 and nrows(S)==1)
5622  { int m=ncols(S);
5623    string mp=string(minpoly);
5624    execute "ring R=("+charstr(br)+"),(x(1..n),y(1..m),z(1..n)),(lp(n),dp(m),lp(n));";
5625    execute "minpoly=number("+mp+");";
5626    ideal vars=x(1..n);
5627    map emb=br,vars;
5628    matrix P=emb(P);
5629    matrix S=emb(S);
5630    ideal check=emb(p);
5631    ideal I;
5632    for (int i=1;i<=m;i=i+1)
5633    { I[i]=S[1,i]-y(i);
5634    }
5635    for (i=1;i<=n;i=i+1)
5636    { I[m+i]=P[1,i]-z(i);
5637    }
5638    I=std(I);
5639    check[1]=reduce(check[1],I);
5640    I=elim(check,1,n);                 // checking whether all variables from
5641    if (I[1]<>0)                       // the former ring have disappeared
5642    { "\/\/ "+string(check);
5643      return(1);
5644    }
5645    else
5646    { return(0);
5647    }
5648  }
5649  else
5650  { "ERROR:   the first <matrix> must have the same number of columns as the";
5651    "         basering and both <matrices> may only have one row";
5652    return();
5653  }
5654}
5655example
5656{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
5657  echo=2;
5658         ring R=0,(x,y,z),dp;
5659         matrix P[1][3]=x2+y2,z2,x4+y4;
5660         matrix S[1][4]=1,x2z-1y2z,xyz,x3y-1xy3;
5661         poly p1=x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4;
5662         module_containment(p1,P,S);
5663         poly p2=z;
5664         module_containment(p2,P,S);
5665}
5666
5667proc orbit_variety (matrix F,string newring)
5668USAGE:   orbit_variety(F,s);
5669         F: a 1xm <matrix> defing an invariant ring, s: a <string> giving the
5670         name for a new ring
5671RETURN:  a Groebner basis (type <ideal>, named G) for the ideal defining the
5672         orbit variety (i.e. the syzygy ideal) in the new ring (named `s`)
5673EXAMPLE: example orbit_variety; shows an example
5674THEORY:  The ideal of algebraic relations of the invariant ring generators is
5675         calculated, then the variables of the original ring are eliminated and
5676         the polynomials that are left over define the orbit variety
5677{ if (newring=="")
5678  { "ERROR:   the second parameter may not be an empty <string>";
5679    return();
5680  }
5681  if (nrows(F)==1)
5682  { def br=basering;
5683    int n=nvars(br);
5684    int m=ncols(F);
5685    string mp=string(minpoly);
5686    execute "ring R=("+charstr(br)+"),("+varstr(br)+",y(1..m)),dp;";
5687    execute "minpoly=number("+mp+");";
5688    ideal I=ideal(imap(br,F));
5689    for (int i=1;i<=m;i=i+1)
5690    { I[i]=I[i]-y(i);
5691    }
5692    I=elim(I,1,n);
5693    execute "ring "+newring+"=("+charstr(br)+"),(y(1..m)),dp(m);";
5694    execute "minpoly=number("+mp+");";
5695    ideal vars;
5696    for (i=2;i<=n;i=i+1)
5697    { vars[i]=0;
5698    }
5699    vars=vars,y(1..m);
5700    map emb=R,vars;
5701    ideal G=emb(I);
5702    kill emb, vars, R;
5703    keepring `newring`;
5704    // execute "keepring "+newring+";";
5705    return();
5706  }
5707  else
5708  { "ERROR:   the <matrix> may only have one row";
5709    return();
5710  }
5711}
5712example
5713{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:";
5714  echo=2;
5715         ring R=0,(x,y,z),dp;
5716         matrix F[1][7]=x2+y2,z2,x4+y4,1,x2z-1y2z,xyz,x3y-1xy3;
5717         string newring="E";
5718         orbit_variety(F,newring);
5719         print(G);
5720         basering;
5721}
5722
5723proc relative_orbit_variety(ideal I,matrix F,string newring)
5724USAGE:   relative_orbit_variety(I,F,s);
5725         I: an <ideal> invariant under the action of a group, F: a 1xm
5726         <matrix> defining the invariant ring of this group, s: a <string>
5727         giving a name for a new ring
5728RETURN:  a Groebner basis (type <ideal>, named G) for the ideal defining the
5729         relative orbit variety with respect to I in the new ring (named s)
5730EXAMPLE: example relative_orbit_variety; shows an example
5731THEORY:  A Groebner basis of the ideal of algebraic relations of the invariant
5732         ring generators is calculated, then one of the basis elements plus the
5733         ideal generators. The variables of the original ring are eliminated and
5734         the polynomials that are left over define thecrelative orbit variety
5735         with respect to I.
5736{ if (newring=="")
5737  { "ERROR:   the third parameter may not be empty a <string>";
5738    return();
5739  }
5740  degBound=0;
5741  if (nrows(F)==1)
5742  { def br=basering;
5743    int n=nvars(br);
5744    int m=ncols(F);
5745    string mp=string(minpoly);
5746    execute "ring R=("+charstr(br)+"),("+varstr(br)+",y(1..m)),lp;";
5747    execute "minpoly=number("+mp+");";
5748    ideal J=ideal(imap(br,F));
5749    ideal I=imap(br,I);
5750    for (int i=1;i<=m;i=i+1)
5751    { J[i]=J[i]-y(i);
5752    }
5753    J=std(J);
5754    J=J,I;
5755    option(redSB);
5756    J=std(J);
5757    ideal vars;
5758    //for (i=1;i<=n;i=i+1)
5759    //{ vars[i]=0;
5760    //}
5761    vars[n]=0;
5762    vars=vars,y(1..m);
5763    map emb=R,vars;
5764    ideal G=emb(J);
5765    J=J-G;
5766    for (i=1;i<=ncols(G);i=i+1)
5767    { if (J[i]<>0)
5768      { G[i]=0;
5769      }
5770    }
5771    G=compress(G);
5772    execute "ring "+newring+"=("+charstr(br)+"),(y(1..m)),lp;";
5773    execute "minpoly=number("+mp+");";
5774    ideal vars;
5775    for (i=2;i<=n;i=i+1)
5776    { vars[i]=0;
5777    }
5778    vars=vars,y(1..m);
5779    map emb=R,vars;
5780    ideal G=emb(G);
5781    kill vars, emb;
5782    keepring `newring`;
5783    // execute "keepring "+newring+";";
5784    return();
5785  }
5786  else
5787  { "ERROR:   the <matrix> may only have one row";
5788    return();
5789  }
5790}
5791example
5792{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.6.3:";
5793  echo=2;
5794         ring R=0,(x,y,z),dp;
5795         matrix F[1][3]=x+y+z,xy+xz+yz,xyz;
5796         ideal I=x2+y2+z2-1,x2y+y2z+z2x-2x-2y-2z,xy2+yz2+zx2-2x-2y-2z;
5797         string newring="E";
5798         relative_orbit_variety(I,F,newring);
5799         print(G);
5800         basering;
5801}
5802
5803proc image_of_variety(ideal I,matrix F)
5804USAGE:   image_of_variety(I,F);
5805         I: an arbitray <ideal>, F: a 1xm <matrix> defining an invariant ring
5806         of a some matrix group
5807RETURN:  the <ideal> defining the image under that group of the variety defined
5808         by I
5809EXAMPLE: example image_of_variety; shows an example
5810THEORY:  relative_orbit_variety(I,F,s) is called and the newly introduced
5811         variables in the output are replaced by the generators of the
5812         invariant ring. This ideal in the original variables defines the image
5813         of the variety defined by I
5814{ if (nrows(F)==1)
5815  { def br=basering;
5816    int n=nvars(br);
5817    string newring="E";
5818    relative_orbit_variety(I,F,newring);
5819    execute "ring R=("+charstr(br)+"),("+varstr(br)+","+varstr(E)+"),lp;";
5820    ideal F=imap(br,F);
5821    for (int i=1;i<=n;i=i+1)
5822    { F=0,F;
5823    }
5824    setring br;
5825    map emb2=E,F;
5826    return(compress(emb2(G)));
5827  }
5828  else
5829  { "ERROR:   the <matrix> may only have one row";
5830    return();
5831  }
5832}
5833example
5834{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.6.8:";
5835  echo=2;
5836         ring R=0,(x,y,z),dp;
5837         matrix F[1][3]=x+y+z,xy+xz+yz,xyz;
5838         ideal I=xy;
5839         print(image_of_variety(I,F));
5840}
Note: See TracBrowser for help on using the repository browser.