source: git/Singular/LIB/finvar.lib @ 5480da

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