Changeset e52b9f in git


Ignore:
Timestamp:
Jan 22, 2007, 2:08:25 PM (17 years ago)
Author:
Hans Schönemann <hannes@…>
Branches:
(u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
Children:
8223cd635042d178325b09664e9e3c94114b9a5c
Parents:
05a31dd1bac7c8886acb526ecf5503742a948378
Message:
*king: new secondary_charp, irred_secondary_char0, secondary_char0


git-svn-id: file:///usr/local/Singular/svn/trunk@9742 2c84dea3-7e68-4137-9b89-c4e89433aadc
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Singular/LIB/finvar.lib

    r05a31d re52b9f  
    11///////////////////////////////////////////////////////////////////////////////
    2 version="$Id: finvar.lib,v 1.51 2006-08-02 15:40:47 Singular Exp $"
     2version="$Id: finvar.lib,v 1.52 2007-01-22 13:08:25 Singular Exp $"
    33category="Invariant theory";
    44info="
     
    4040 irred_secondary_char0()           irreducible secondary invariants in char 0
    4141 secondary_charp()                 secondary invariants in char p
     42 secondary_charp_degbound()        finds all (irred.) secondary invariants in char p
     43                                   up to a given degree bound, without using Molien
     44                                   series or Reynolds operator
    4245 secondary_no_molien()             secondary invariants, without Molien series
     46                                   but with Reynolds operator
    4347 secondary_and_irreducibles_no_molien() s.i. & irreducible s.i., without M.s.
    4448 secondary_not_cohen_macaulay()    s.i. when invariant ring not Cohen-Macaulay
     
    5458// sort_of_invariant_basis()       lin. ind. invariants of a degree mod p.i.
    5559// next_vector                     lists all of Z^n with first nonzero entry 1
    56 // int_number_map                  integers 1..q are maped to q field elements
     60// int_number_map                  integers 1..q are mapped to q field elements
    5761// search                          searches a number of p.i., char 0
    5862// p_search                        searches a number of p.i., char p
     
    9094"
    9195{ if (i<=0)
    92   { "ERROR:   the input should be > 0.";
    93     return();
     96  { ERROR("ERROR:   the input should be > 0.");
    9497  }
    9598  poly v1=var(1);
     
    138141RETURN:  a <list>, the first list element will be a gxn <matrix> representing
    139142         the Reynolds operator if we are in the non-modular case; if the
    140          characteristic is >0, minpoly==0 and the finite group is non-cyclic the
     143         characteristic is >0, minpoly==0 and the finite group non-cyclic the
    141144         second list element is an <int> giving the lowest common multiple of
    142145         the matrix group elements' order (used in molien); in general all
     
    148151         (or the generators themselves during the first run). All the ones that
    149152         have been generated before are thrown out and the program terminates
    150          when no new elements are found in one run. Additionally each time a new
     153         when no new elements found in one run. Additionally each time a new
    151154         group element is found the corresponding ring mapping of which the
    152155         Reynolds operator is made up is generated. They are stored in the rows
     
    161164  if (typeof(#[size(#)])=="int")
    162165  { if (size(#)==1)
    163     { "ERROR:   there are no matrices given among the parameters";
    164       return();
     166    { ERROR("ERROR:   there are no matrices given among the parameters");
    165167    }
    166168    int v=#[size(#)];
     
    172174  }
    173175  if (typeof(#[1])<>"matrix")
    174   { "ERROR:   The parameters must be a list of matrices and maybe an <int>";
    175     return();
     176  { ERROR("ERROR:   The parameters must be a list of matrices and maybe an <int>");
    176177  }
    177178  int n=nrows(#[1]);
    178179  if (n<>nvars(basering))
    179   { "ERROR:   the number of variables of the basering needs to be the same";
    180     "         as the dimension of the matrices";
    181     return();
     180  { ERROR("ERROR:   the number of variables of the basering needs to be the same"+newline+
     181    "         as the dimension of the matrices");
    182182  }
    183183  if (n<>ncols(#[1]))
    184   { "ERROR:   matrices need to be square and of the same dimensions";
    185     return();
     184  { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    186185  }
    187186  matrix vars=matrix(maxideal(1));     // creating an nx1-matrix containing the
     
    209208                                       // procedure
    210209    if (not(typeof(#[j])=="matrix"))
    211     { "ERROR:   The parameters must be a list of matrices and maybe an <int>";
    212       return();
     210    { ERROR("ERROR:   The parameters must be a list of matrices and maybe an <int>");
    213211    }
    214212    if ((n!=nrows(#[j])) or (n!=ncols(#[j])))
    215     { "ERROR:   matrices need to be square and of the same dimensions";
    216        return();
     213    { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    217214    }
    218215    if (unique(G(1..i),#[j]))
     
    358355         elements generated by group_reynolds(), lcm is the second return value
    359356         of group_reynolds()
    360 RETURN:  in case of characteristic 0 a 1x2 <matrix> giving numerator and
     357RETURN:  in case of characteristic 0 a 1x2 <matrix> giving enumerator and
    361358         denominator of Molien series; in case of prime characteristic a ring
    362359         with the name `ringname` of characteristic 0 is created where the same
     
    379376    { int mol_flag=#[size(#)][1];
    380377      if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
    381       { "ERROR:   the second component of <intvec> should be >=0"
    382         return();
     378      { ERROR("ERROR:   the second component of <intvec> should be >=0");
    383379      }
    384380      int interval=#[size(#)][2];
     
    386382    }
    387383    else
    388     { "ERROR:   <intvec> should have three components";
    389       return();
     384    { ERROR("ERROR:   <intvec> should have three components");
    390385    }
    391386    if (ch<>0)
     
    393388      { int r=#[size(#)-1];
    394389        if (typeof(#[size(#)-2])<>"string")
    395         { "ERROR:   In characteristic p>0 a <string> must be given for the name of a new";
    396           "         ring where the Molien series can be stored";
    397           return();
     390        { ERROR("ERROR:   In characteristic p>0 a <string> must be given for the name of a new"+newline+
     391          "         ring where the Molien series can be stored");
    398392        }
    399393        else
    400394        { if (#[size(#)-2]=="")
    401           { "ERROR:   <string> may not be empty";
    402             return();
     395          { ERROR("ERROR:   <string> may not be empty");
    403396          }
    404397          string newring=#[size(#)-2];
     
    408401      else
    409402      { if (typeof(#[size(#)-1])<>"string")
    410         { "ERROR:   In characteristic p>0 a <string> must be given for the name of a new";
    411           "         ring where the Molien series can be stored";
     403        { ERROR("ERROR:   In characteristic p>0 a <string> must be given for the name of a new"+newline+
     404          "         ring where the Molien series can be stored");
    412405          return();
    413406        }
    414407        else
    415408        { if (#[size(#)-1]=="")
    416           { "ERROR:   <string> may not be empty";
    417             return();
     409          { ERROR("ERROR:   <string> may not be empty");
    418410          }
    419411          string newring=#[size(#)-1];
     
    435427      { int r=#[size(#)];
    436428        if (typeof(#[size(#)-1])<>"string")
    437         { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
    438           "         ring where the Molien series can be stored";
    439             return();
     429        { ERROR("ERROR:   in characteristic p>0 a <string> must be given for the name of a new"+newline+
     430          "         ring where the Molien series can be stored");
    440431        }
    441432        else
    442433        { if (#[size(#)-1]=="")
    443           { "ERROR:   <string> may not be empty";
    444             return();
     434          { ERROR("ERROR:   <string> may not be empty");
    445435          }
    446436          string newring=#[size(#)-1];
     
    450440      else
    451441      { if (typeof(#[size(#)])<>"string")
    452         { "ERROR:   in characteristic p>0 a <string> must be given for the name of a new";
    453           "         ring where the Molien series can be stored";
    454           return();
     442        { ERROR("ERROR:   in characteristic p>0 a <string> must be given for the name of a new"+newline+
     443          "         ring where the Molien series can be stored");
    455444        }
    456445        else
    457446        { if (#[size(#)]=="")
    458           { "ERROR:   <string> may not be empty";
    459             return();
     447          { ERROR("ERROR:   <string> may not be empty");
    460448          }
    461449          string newring=#[size(#)];
     
    471459  if (ch<>0)
    472460  { if ((g/r)*r<>g)
    473    { "ERROR:   <int> should divide the group order."
    474       return();
     461   { ERROR("ERROR:   <int> should divide the group order.");
    475462    }
    476463  }
     
    507494 //----------------------------------------------------------------------------
    508495  if (not(typeof(#[1])=="matrix"))
    509   { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    510     return();
     496  { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    511497  }
    512498  int n=nrows(#[1]);
    513499  if (n<>nvars(br))
    514   { "ERROR:   the number of variables of the basering needs to be the same";
    515     "         as the dimension of the square matrices";
    516     return();
     500  { ERROR("ERROR:   the number of variables of the basering needs to be the same"+newline+
     501    "         as the dimension of the square matrices");
    517502  }
    518503  if (v && voice<>2)
     
    540525    for (int j=1;j<=g;j++)
    541526    { if (not(typeof(#[j])=="matrix"))
    542       { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    543         return();
     527      { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    544528      }
    545529      if ((n<>nrows(#[j])) or (n<>ncols(#[j])))
    546       { "ERROR:   matrices need to be square and of the same dimensions";
    547          return();
     530      { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    548531      }
    549532      p=det(I-v1*#[j]);                // denominator of new term -
     
    637620      { setring br;
    638621        if (not(typeof(#[i])=="matrix"))
    639         { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    640           return();
     622        { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    641623        }
    642624        if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
    643         { "ERROR:   matrices need to be square and of the same dimensions";
    644            return();
     625        { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    645626        }
    646627        setring bre;
     
    798779    { setring br;
    799780      if (not(typeof(#[i])=="matrix"))
    800       { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    801         return();
     781      { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    802782      }
    803783      if ((n<>nrows(#[i])) or (n<>ncols(#[i])))
    804       { "ERROR:   matrices need to be square and of the same dimensions";
    805          return();
     784      { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    806785      }
    807786      string stM(i)=string(#[i]);
     
    908887         new group element is found the corresponding ring mapping of which the
    909888         Reynolds operator is made up is generated. They are stored in the rows
    910          of the first return value. In characteristic 0 the term 1/det(1-xE)
     889         of the first return value. In characteristic 0 the terms 1/det(1-xE)
    911890         is computed whenever a new element E is found. In prime characteristic
    912891         a Brauer lift is involved and the terms are only computed after the
    913892         entire matrix group is generated (to avoid the modular case). The
    914          returned matrix gives numerator and denominator of the expanded
     893         returned matrix gives enumerator and denominator of the expanded
    915894         version where common factors have been canceled.
    916895EXAMPLE: example reynolds_molien; shows an example
     
    925904    { int mol_flag=#[size(#)][1];
    926905      if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0)))
    927       { "ERROR:   the second component of the <intvec> should be >=0";
    928         return();
     906      { ERROR("ERROR:   the second component of the <intvec> should be >=0");
    929907      }
    930908      int interval=#[size(#)][2];
     
    932910    }
    933911    else
    934     { "ERROR:   <intvec> should have three components";
    935       return();
     912    { ERROR("ERROR:   <intvec> should have three components");
    936913    }
    937914    if (ch<>0)
    938915    { if (typeof(#[size(#)-1])<>"string")
    939       { "ERROR:   in characteristic p a <string> must be given for the name";
     916      { ERROR("ERROR:   in characteristic p a <string> must be given for the name");
    940917        "         of a new ring where the Molien series can be stored";
    941918        return();
     
    943920      else
    944921      { if (#[size(#)-1]=="")
    945         { "ERROR:   <string> may not be empty";
     922        { ERROR("ERROR:   <string> may not be empty");
    946923          return();
    947924        }
     
    960937    if (ch<>0)
    961938    { if (typeof(#[size(#)])<>"string")
    962       { "ERROR:   in characteristic p a <string> must be given for the name";
    963         "         of a new ring where the Molien series can be stored";
    964         return();
     939      { ERROR("ERROR:   in characteristic p a <string> must be given for the name"+newline+
     940        "         of a new ring where the Molien series can be stored");
    965941      }
    966942      else
    967943      { if (#[size(#)]=="")
    968         { "ERROR:   <string> may not be empty";
    969           return();
     944        { ERROR("ERROR:   <string> may not be empty");
    970945        }
    971946        string newring=#[size(#)];
     
    1018993  if (ch==0)
    1019994  { if (typeof(#[1])<>"matrix")
    1020     { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    1021       return();
     995    { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    1022996    }
    1023997    int n=nrows(#[1]);
    1024998    if (n<>nvars(br))
    1025     { "ERROR:   the number of variables of the basering needs to be the same";
    1026       "         as the dimension of the matrices";
    1027       return();
     999    { ERROR("ERROR:   the number of variables of the basering needs to be the same"+newline+
     1000      "         as the dimension of the matrices");
    10281001    }
    10291002    if (n<>ncols(#[1]))
    1030     { "ERROR:   matrices need to be square and of the same dimensions";
    1031       return();
     1003    { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    10321004    }
    10331005    matrix vars=matrix(maxideal(1));   // creating an nx1-matrix containing the
     
    10551027                                       // procedure
    10561028      if (not(typeof(#[j])=="matrix"))
    1057       { "ERROR:   the parameters must be a list of matrices and maybe an <intvec>";
    1058         return();
     1029      { ERROR("ERROR:   the parameters must be a list of matrices and maybe an <intvec>");
    10591030      }
    10601031      if ((n!=nrows(#[j])) or (n!=ncols(#[j])))
    1061       { "ERROR:   matrices need to be square and of the same dimensions";
    1062          return();
     1032      { ERROR("ERROR:   matrices need to be square and of the same dimensions");
    10631033      }
    10641034      if (unique(G(1..i),#[j]))
     
    16511621           print(invariant_basis(2,A));
    16521622}
     1623///////////////////////////////////////////////////////////////////////////////
     1624
     1625stat proc invariant_basis_modS (int g,ideal sS, list #)
     1626"USAGE:   invariant_basis(g,sP,G1,G2,...);
     1627         g: an <int> indicating of which degree (>0) the homogeneous basis
     1628         shoud be,
     1629         sS: normal forms of subsequently found sec. inv. in degree g,
     1630         G1,G2,...: <matrices> generating a finite matrix group
     1631RETURNS: invariants of degree g
     1632THEORY:  A general polynomial of degree g is generated and the generators of
     1633         the matrix group applied. The difference ought to be 0 and this way a
     1634         system of linear equations is created. It is solved by computing
     1635         syzygies.
     1636"
     1637{ if (g<=0)
     1638  { "ERROR:   the first parameter should be > 0";
     1639    return();
     1640  }
     1641  def br=basering;
     1642  ideal mon=sort(kbase(sS,g))[1];      // needed for constructing a general
     1643  int m=ncols(mon);                    // homogeneous polynomial of degree g
     1644  mon=sort(mon,intvec(m..1))[1];
     1645  int a=size(#);
     1646  int i;
     1647  int n=nvars(br);
     1648 //---------------------- checking that the input is ok -----------------------
     1649  for (i=1;i<=a;i++)
     1650  { if (typeof(#[i])=="matrix")
     1651    { if (nrows(#[i])==n && ncols(#[i])==n)
     1652      { matrix G(i)=#[i];
     1653      }
     1654      else
     1655      { "ERROR:   the number of variables of the base ring needs to be the same";
     1656        "         as the dimension of the square matrices";
     1657        return();
     1658      }
     1659    }
     1660    else
     1661    { "ERROR:   the last parameters should be a list of matrices";
     1662      return();
     1663    }
     1664  }
     1665 //----------------------------------------------------------------------------
     1666  execute("ring T=("+charstr(br)+"),("+varstr(br)+",p(1..m)),lp;");
     1667  // p(1..m) are the general coefficients of the general polynomial of degree g
     1668  execute("ideal vars="+varstr(br)+";");
     1669  map f;
     1670  ideal mon=imap(br,mon);
     1671  poly P=0;
     1672  for (i=m;i>=1;i--)
     1673  { P=P+p(i)*mon[i];                   // P is the general polynomial
     1674  }
     1675  ideal I;                             // will help substituting variables in P
     1676                                       // by linear combinations of variables -
     1677  poly Pnew,temp;                      // Pnew is P with substitutions -
     1678  matrix S[m*a][m];                    // will contain system of linear
     1679                                       // equations
     1680  int j,k;
     1681 //------------------- building the system of linear equations ----------------
     1682  for (i=1;i<=a;i++)
     1683  { I=ideal(matrix(vars)*transpose(imap(br,G(i))));
     1684    I=I,p(1..m);
     1685    f=T,I;
     1686    Pnew=f(P);
     1687    for (j=1;j<=m;j++)
     1688    { temp=P/mon[j]-Pnew/mon[j];
     1689      for (k=1;k<=m;k++)
     1690      { S[m*(i-1)+j,k]=temp/p(k);
     1691      }
     1692    }
     1693  }
     1694 //----------------------------------------------------------------------------
     1695  setring br;
     1696  map f=T,ideal(0);
     1697  matrix S=f(S);
     1698  matrix s=matrix(syz(S));             // s contains a basis of the space of
     1699                                       // solutions -
     1700  ideal I=ideal(matrix(mon)*s);        // I contains a basis of homogeneous
     1701  if (I[1]<>0)                         // invariants of degree d
     1702  { for (i=1;i<=ncols(I);i++)
     1703    { I[i]=I[i]/leadcoef(I[i]);        // setting leading coefficients to 1
     1704    }
     1705  }
     1706  return(I);
     1707}
     1708
    16531709///////////////////////////////////////////////////////////////////////////////
    16541710
     
    20642120ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
    20652121         M the one of molien or the second one of reynolds_molien
    2066 DISPLAY: information about the various stages of the program if v does not
     2122DISPLAY: information about the various stages of the programme if v does not
    20672123         equal 0
    20682124RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    21632219      if (cd<>dif)
    21642220      { P,sP,CI,dB=search(n,d,B,cd,P,sP,i,dif,dB,CI); // searching for dif invariants
    2165       }                                // i.e. we can take all of B
    2166       else
     2221      }
     2222      else                             // i.e. we can take all of B
    21672223      { for(j=i+1;j<=i+dif;j++)
    21682224        { CI=CI+ideal(var(j)^d);
     
    22072263         ringname gives the name of a ring of characteristic 0 that has been
    22082264         created by molien or reynolds_molien
    2209 DISPLAY: information about the various stages of the program if v does not
     2265DISPLAY: information about the various stages of the programme if v does not
    22102266         equal 0
    22112267RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    22492305  }
    22502306  if (typeof(`ring_name`)<>"ring")
    2251   { "ERROR:   Second parameter ought to the name of a ring where the Molien";
    2252     "         is stored.";
     2307  { "ERROR:   Second parameter ought to be ring where ";
     2308    "         the Molien series is stored.";
    22532309    return();
    22542310  }
     
    23602416         <int>
    23612417ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
    2362 DISPLAY: information about the various stages of the program if v does not
     2418DISPLAY: information about the various stages of the programme if v does not
    23632419         equal 0
    23642420RETURN:  primary invariants (type <matrix>) of the invariant ring and an
     
    25032559         <int>
    25042560ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
    2505 DISPLAY: information about the various stages of the program if v does not
     2561DISPLAY: information about the various stages of the programme if v does not
    25062562         equal 0
    25072563RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
     
    26442700         G1,G2,...: <matrices> generating a finite matrix group, v: an optional
    26452701         <int>
    2646 DISPLAY: information about the various stages of the program if v does not
     2702DISPLAY: information about the various stages of the programme if v does not
    26472703         equal 0
    26482704RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    26582714 //--------------------- checking input and setting verbose mode --------------
    26592715  if (char(basering)==0)
    2660   { "ERROR:   primary_charp_without should only be used with rings of";
     2716  { "ERROR:   primary_charp_without should not be used with rings of";
    26612717    "         characteristic 0.";
    26622718    return();
     
    27042760                                       // space of invariants of degree d,
    27052761                                       // newdim: dimension the ideal generated
    2706                                        // the primary invariants plus basis
     2762                                       // by the primary invariants plus basis
    27072763                                       // elements, dif=n-i-newdim, i.e. the
    27082764                                       // number of new primary invairants that
     
    27842840         G1,G2,...: <matrices> generating a finite matrix group, flags: an
    27852841         optional <intvec> with three entries, if the first one equals 0 (also
    2786          the default), the program attempts to compute the Molien series and
    2787          Reynolds operator, if it equals 1, the program is told that the
     2842         the default), the programme attempts to compute the Molien series and
     2843         Reynolds operator, if it equals 1, the programme is told that the
    27882844         Molien series should not be computed, if it equals -1 characteristic 0
    27892845         is simulated, i.e. the Molien series is computed as if the base field
    27902846         were characteristic 0 (the user must choose a field of large prime
    2791          characteristic, e.g. 32003), and if the first one is anything else, it
     2847         characteristic, e.g. 32003) and if the first one is anything else, it
    27922848         means that the characteristic of the base field divides the group
    27932849         order, the second component should give the size of intervals between
     
    27972853         common factors should always be canceled when the expansion is simple
    27982854         (the root of the extension field occurs not among the coefficients)
    2799 DISPLAY: information about the various stages of the program if the third
     2855DISPLAY: information about the various stages of the programme if the third
    28002856         flag does not equal 0
    28012857RETURN:  primary invariants (type <matrix>) of the invariant ring and if
     
    28922948        else
    28932949        { if (v)
    2894           { "  Since it is impossible for this program to calculate the Molien series for";
     2950          { "  Since it is impossible for this programme to calculate the Molien series for";
    28952951            "  invariant rings over extension fields of prime characteristic, we have to";
    28962952            "  continue without it.";
     
    31993255ASSUME:  REY is the first return value of group_reynolds or reynolds_molien and
    32003256         M the one of molien or the second one of reynolds_molien
    3201 DISPLAY: information about the various stages of the program if v does not
     3257DISPLAY: information about the various stages of the programme if v does not
    32023258         equal 0
    32033259RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    33463402         ringname gives the name of a ring of characteristic 0 that has been
    33473403         created by molien or reynolds_molien
    3348 DISPLAY: information about the various stages of the program if v does not
     3404DISPLAY: information about the various stages of the programme if v does not
    33493405         equal 0
    33503406RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    34993555         bases elements, v: an optional <int>
    35003556ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
    3501 DISPLAY: information about the various stages of the program if v does not
     3557DISPLAY: information about the various stages of the programme if v does not
    35023558         equal 0
    35033559RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
     
    36463702         bases elements, v: an optional <int>
    36473703ASSUME:  REY is the first return value of group_reynolds or reynolds_molien
    3648 DISPLAY: information about the various stages of the program if v does not
     3704DISPLAY: information about the various stages of the programme if v does not
    36493705         equal 0
    36503706RETURN:  primary invariants (type <matrix>) of the invariant ring  and an
     
    37923848         where -|r| to |r| is the range of coefficients of the random
    37933849         combinations of bases elements, v: an optional <int>
    3794 DISPLAY: information about the various stages of the program if v does not
     3850DISPLAY: information about the various stages of the programme if v does not
    37953851         equal 0
    37963852RETURN:  primary invariants (type <matrix>) of the invariant ring
     
    39433999         where -|r| to |r| is the range of coefficients of the random
    39444000         combinations of bases elements, flags: an optional <intvec> with three
    3945          entries, if the first one equals 0 (also the default), the program
     4001         entries, if the first one equals 0 (also the default), the programme
    39464002         attempts to compute the Molien series and Reynolds operator, if it
    3947          equals 1, the program is told that the Molien series should not be
     4003         equals 1, the programme is told that the Molien series should not be
    39484004         computed, if it equals -1 characteristic 0 is simulated, i.e. the
    39494005         Molien series is computed as if the base field were characteristic 0
    39504006         (the user must choose a field of large prime characteristic, e.g.
    3951          32003), and if the first one is anything else, it means that the
     4007         32003) and if the first one is anything else, it means that the
    39524008         characteristic of the base field divides the group order, the second
    39534009         component should give the size of intervals between canceling common
     
    39574013         always be canceled when the expansion is simple (the root of the
    39584014         extension field does not occur among the coefficients)
    3959 DISPLAY: information about the various stages of the program if the third
     4015DISPLAY: information about the various stages of the programme if the third
    39604016         flag does not equal 0
    39614017RETURN:  primary invariants (type <matrix>) of the invariant ring and if
     
    40604116        else
    40614117        { if (v)
    4062           { "  Since it is impossible for this program to calculate the Molien series for";
     4118          { "  Since it is impossible for this programme to calculate the Molien series for";
    40634119            "  invariant rings over extension fields of prime characteristic, we have to";
    40644120            "  continue without it.";
     
    44244480proc secondary_char0 (matrix P, matrix REY, matrix M, list #)
    44254481"
    4426 USAGE:    secondary_char0(P,REY,M[,v][,\"AH\"]);
     4482USAGE:    secondary_char0(P,REY,M[,v][,\"old\"]);
    44274483@*          P: a 1xn <matrix> with homogeneous primary invariants, where
    44284484               n is the number of variables of the basering;
     
    44324488               series;
    44334489@*          v: an optional <int>;
    4434 @*          \"AH\": if this string occurs as (optional) parameter, then an
     4490@*          \"old\": if this string occurs as (optional) parameter, then an
    44354491               old version of secondary_char0 is used (for downward
    44364492               compatibility)
    4437 ASSUME:   REY is the 1st return value of group_reynolds(), reynolds_molien() or
     4493ASSUME:   The characteristic of basering is zero;
     4494          REY is the 1st return value of group_reynolds(), reynolds_molien() or
    44384495          the second one of primary_invariants();
    44394496@*        M is the return value of molien()
     
    44504507          independent modulo the primary invariants (see paper \"Some
    44514508          Algorithms in Invariant Theory of Finite Groups\" by Kemper and
    4452           Steel (1997)). The size of this set can be read off from the
    4453           Molien series.
     4509          Steel (1997)) using Groebner basis techniques. The size of this set
     4510          can be read off from the Molien series.
    44544511NOTE:     Secondary invariants are not uniquely determined by the given data.
    4455           Specifically, the output of secondary_char0(P,REY,M,"AH") will
     4512          Specifically, the output of secondary_char0(P,REY,M,\"old\") will
    44564513          differ from the output of secondary_char0(P,REY,M). However, the
    44574514          ideal generated by the irreducible homogeneous
    44584515          secondary invariants will be the same in both cases.
    4459 @*        There is an internal parameter \"pieces\" that, by default, equals 15.
    4460           Setting \"pieces\" to a smaller value might decrease the memory consumption,
    4461           but increase the running time.
     4516@*        There are three internal parameters \"pieces\", \"MonStep\" and \"IrrSwitch\".
     4517          The default values of the parameters should be fine in most cases. However,
     4518          in some cases, different values may provide a better balance of memory
     4519          consumption (smaller values) and speed (bigger values).
    44624520SEE ALSO: irred_secondary_char0;
    44634521EXAMPLE:  example secondary_char0; shows an example
    44644522"
    4465 { def br=basering;
     4523{
     4524 //----------  Internal parameters, whose choice might improve the performance -----
     4525  int pieces = 15;   // For generating reducible secondaries, blocks of #pieces# secondaries
     4526                     // are formed.
     4527                     // If this parameter is small, the memory consumption will decrease.
     4528  int MonStep = 15;  // The Reynolds operator is applied to blocks of #MonStep# monomials.
     4529                     // If this parameter is small, the memory consumption will decrease.
     4530  int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating
     4531                     // irreducible secondaries that tends to produce a smaller output
     4532                     // (which is good for subsequent computations). However, this method
     4533                     // needs to much memory in high degrees, and so we use a sparser method
     4534                     // from degree #IrrSwitch# on.
     4535
     4536  def br=basering;
    44664537
    44674538 //----------------- checking input and setting verbose mode ------------------
    44684539  if (char(br)<>0)
    4469   { "ERROR:   secondary_char0 should only be used with rings of characteristic 0.";
    4470     return();
     4540  { "ERROR:   secondary_char0 can only be used with rings of characteristic 0.";
     4541    "         Try secondary_charp";
     4542      return();
    44714543  }
    44724544  int i;
     
    44844556  if (size(#)>0)
    44854557  { if (typeof(#[size(#)])=="string")
    4486     { if (#[size(#)]=="AH")
     4558    { if (#[size(#)]=="old")
    44874559      { if (typeof(#[1])=="int")
    44884560        { matrix S,IS = old_secondary_char0(P,REY,M,#[1]);
     
    44954567      }
    44964568      else
    4497       { "ERROR:   If the last optional parameter is a string, it should be \"AH\".";
     4569      { "ERROR:   If the last optional parameter is a string, it should be \"old\".";
    44984570        return(matrix(ideal()),matrix(ideal()));
    44994571      }
     
    45614633  option(redSB);
    45624634  ideal sP = groebner(ideal(P));
     4635                           // This is the only explicit Groebner basis computation!
    45634636  ideal Reductor,SaveRed;  // sP union Reductor is a Groebner basis up to degree i-1
    45644637  int SizeSave;
     
    45764649  int ii;
    45774650  int saveAttr;
    4578   ideal B,IS;              // IS will contain all irr. sec. inv.
    4579 
    4580   int pieces = 15;   // If this parameter is small, the memory consumption will decrease.
    4581                      // In some cases, a careful choice will speed up computations
     4651  ideal mon,B,IS;              // IS will contain all irr. sec. inv.
    45824652
    45834653  for (i=1;i<m;i++)
     
    45874657      attrib(SSort[i][k],"size",0);
    45884658    }
    4589    }
     4659  }
    45904660//--------------------- generating secondary invariants ----------------------
    45914661  for (i=2;i<=m;i++)                   // going through dimmat -
     
    46424712                }
    46434713              }
    4644               ProdCand = Mul1*Mul2;
     4714//              if (i<10)
     4715                ProdCand = simplify(Mul1*Mul2,4);
     4716//              else { ProdCand = Mul1*Mul2;}
    46454717              ReducedCandidates = reduce(ProdCand,sP);
    46464718                  // sP union SaveRed union Reductor is a homogeneous Groebner basis
     
    46544726                             // invariants and previously computed secondary invariants.
    46554727                             // Otherwise ProdCand[ii] can be taken as secondary invariant.
    4656           if (size(Indicator)<>0)
     4728              if (size(Indicator)<>0)
    46574729              { for (ii=1;ii<=ncols(ProdCand);ii++)     // going through all the power products
    4658                 { helpP = reduce(Indicator[ii],Reductor);
     4730                { helpP = Indicator[ii];
    46594731                  if (helpP <> 0)
    46604732                  { counter++;
     
    46674739                    }
    46684740                    if (int(dimmat[i,1])<>counter)
    4669                     { helpint++;
    4670                       Reductor[helpint] = helpP;
     4741                    { Reductor = ideal(helpP);
    46714742                        // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a
    46724743                        // homogeneous polynomial of degree i-1 then G union NF(p,G) is
     
    46764747                        // it, save it in SaveRed, and work with a smaller Reductor. This turns
    46774748                        // out to save a little time.
    4678                       if (ncols(Reductor)>100)
    4679                       { Indicator=reduce(Indicator,Reductor);
    4680                         for (k3=1;k3<=ncols(Reductor);k3++)
    4681                         { SaveRed[SizeSave+k3] = Reductor[k3];
    4682                         }
    4683                         SizeSave=SizeSave+size(Reductor);
    4684                         Reductor = ideal(0);
    4685                         helpint = 0;
    4686                         attrib(SaveRed, "isSB",1);
    4687                         attrib(Reductor, "isSB",1);
    4688                       }
     4749                      Indicator=reduce(Indicator,Reductor);
     4750                      SizeSave++;
     4751                      SaveRed[SizeSave] = helpP;
     4752                      attrib(SaveRed, "isSB",1);
    46894753                    }
    46904754                    else
     
    46944758                }
    46954759              }
    4696               for (k3=1;k3<=size(Reductor);k3++)
    4697               { SaveRed[SizeSave+k3] = Reductor[k3];
    4698               }
    4699               SizeSave=SizeSave+size(Reductor);
    4700               Reductor = ideal(0);
    4701               helpint = 0;
    4702               attrib(SaveRed, "isSB",1);
    4703               attrib(Reductor, "isSB",1);
     4760//              attrib(SaveRed, "isSB",1);
    47044761            }
    47054762          }
     
    47124769        { "There are irreducible secondary invariants in degree ", i-1," !!";
    47134770        }
    4714         B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6);
     4771        if (i>IrrSwitch)  // use sparse algorithm
     4772        { mon = kbase(sP,i-1);
     4773//          mon = ideal(mon[ncols(mon)..1]);
     4774          if (counter==0 && ncols(mon)==int(dimmat[i,1])) // then we can use all of mon
     4775          { B=normalize(evaluate_reynolds(REY,mon));
     4776            IS=IS+B;
     4777            saveAttr = attrib(SSort[i-1][i-1],"size")+int(dimmat[i,1]);
     4778            SSort[i-1][i-1] = SSort[i-1][i-1] + B;
     4779            attrib(SSort[i-1][i-1],"size", saveAttr);
     4780            if (typeof(ISSort[i-1]) <> "none")
     4781            { ISSort[i-1] = ISSort[i-1] + B;
     4782            }
     4783            else
     4784            { ISSort[i-1] = B;
     4785            }
     4786            if (v) {"  We found: "; print(B);}
     4787          }
     4788          else
     4789          { irrcounter=0;
     4790            j=0;                         // j goes through all of mon -
     4791            // Compare the comments on the computation of reducible sec. inv.!
     4792            while (int(dimmat[i,1])<>counter)
     4793            { if ((j mod MonStep) == 0)
     4794              { if ((j+MonStep) <= ncols(mon))
     4795                { B[j+1..j+MonStep] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep])));
     4796                  ReducedCandidates[j+1..j+MonStep] = reduce(ideal(B[j+1..j+MonStep]),sP);
     4797                  Indicator[j+1..j+MonStep] = reduce(ideal(ReducedCandidates[j+1..j+MonStep]),SaveRed);
     4798                }
     4799                else
     4800                { B[j+1..ncols(mon)] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ncols(mon)])));
     4801                  ReducedCandidates[j+1..ncols(mon)] = reduce(ideal(B[j+1..ncols(mon)]),sP);
     4802                  Indicator[j+1..ncols(mon)] = reduce(ideal(ReducedCandidates[j+1..ncols(mon)]),SaveRed);
     4803                }
     4804              }
     4805              j++;
     4806              helpP = Indicator[j];
     4807              if (helpP <>0)                  // B[j] should be added
     4808              { counter++; irrcounter++;
     4809                IS=IS,B[j];
     4810                saveAttr = attrib(SSort[i-1][i-1],"size")+1;
     4811                SSort[i-1][i-1][saveAttr] = B[j];
     4812                attrib(SSort[i-1][i-1],"size",saveAttr);
     4813                if (typeof(ISSort[i-1]) <> "none")
     4814                { ISSort[i-1][irrcounter] = B[j];
     4815                }
     4816                else
     4817                { ISSort[i-1] = ideal(B[j]);
     4818                }
     4819                if (v)
     4820                { "  We found the irreducible sec. inv. "+string(B[j]);
     4821                }
     4822                Reductor = ideal(helpP);
     4823                attrib(Reductor, "isSB",1);
     4824                Indicator=reduce(Indicator,Reductor);
     4825                SizeSave++;
     4826                SaveRed[SizeSave] = helpP;
     4827                attrib(SaveRed, "isSB",1);
     4828              }
     4829              B[j]=0;
     4830              ReducedCandidates[j]=0;
     4831              Indicator[j]=0;
     4832            }
     4833          }
     4834        }  // if i>IrrSwitch
     4835        else  // use fast algorithm
     4836        { B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6);
    47154837                                       // B contains
    47164838                                       // images of kbase(sP,i-1) under the
    47174839                                       // Reynolds operator that are linearly
    4718                                        // independent and that don't reduce to
    4719                                        // 0 modulo sP -
    4720         if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of B
    4721         { IS=IS+B;
    4722           saveAttr = attrib(SSort[i-1][i-1],"size")+int(dimmat[i,1]);
    4723           SSort[i-1][i-1] = SSort[i-1][i-1] + B;
    4724           attrib(SSort[i-1][i-1],"size", saveAttr);
    4725           if (typeof(ISSort[i-1]) <> "none")
    4726           { ISSort[i-1] = ISSort[i-1] + B;
     4840                                       // independent
     4841          if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of B
     4842          { IS=IS+B;
     4843            saveAttr = attrib(SSort[i-1][i-1],"size")+int(dimmat[i,1]);
     4844            SSort[i-1][i-1] = SSort[i-1][i-1] + B;
     4845            attrib(SSort[i-1][i-1],"size", saveAttr);
     4846            if (typeof(ISSort[i-1]) <> "none")
     4847            { ISSort[i-1] = ISSort[i-1] + B;
     4848            }
     4849            else
     4850            { ISSort[i-1] = B;
     4851            }
     4852            if (v) {"  We found: "; print(B);}
    47274853          }
    47284854          else
    4729           { ISSort[i-1] = B;
    4730           }
    4731           if (v) {"  We found: "; print(B);}
    4732         }
    4733         else
    4734         { irrcounter=0;
    4735           j=0;                         // j goes through all of B -
    4736         // Compare the comments on the computation of reducible sec. inv.!
    4737           ReducedCandidates = reduce(B,sP);
    4738           Indicator = reduce(ReducedCandidates,SaveRed);
    4739           while (int(dimmat[i,1])<>counter)
    4740           { j++;
    4741             helpP = reduce(Indicator[j],Reductor);
    4742             if (helpP <>0)                  // B[j] should be added
    4743             { counter++; irrcounter++;
    4744               IS=IS,B[j];
    4745               saveAttr = attrib(SSort[i-1][i-1],"size")+1;
    4746               SSort[i-1][i-1][saveAttr] = B[j];
    4747               attrib(SSort[i-1][i-1],"size",saveAttr);
    4748               if (typeof(ISSort[i-1]) <> "none")
    4749               { ISSort[i-1][irrcounter] = B[j];
     4855          { irrcounter=0;
     4856            j=0;                         // j goes through all of B -
     4857            // Compare the comments on the computation of reducible sec. inv.!
     4858            ReducedCandidates = reduce(B,sP);
     4859            Indicator = reduce(ReducedCandidates,SaveRed);
     4860            while (int(dimmat[i,1])<>counter)
     4861            { j++;
     4862              helpP = Indicator[j];
     4863              if (helpP <>0)                  // B[j] should be added
     4864              { counter++; irrcounter++;
     4865                IS=IS,B[j];
     4866                saveAttr = attrib(SSort[i-1][i-1],"size")+1;
     4867                SSort[i-1][i-1][saveAttr] = B[j];
     4868                attrib(SSort[i-1][i-1],"size",saveAttr);
     4869                if (typeof(ISSort[i-1]) <> "none")
     4870                { ISSort[i-1][irrcounter] = B[j];
     4871                }
     4872                else
     4873                { ISSort[i-1] = ideal(B[j]);
     4874                }
     4875                if (v)
     4876                { "  We found the irreducible sec. inv. "+string(B[j]);
     4877                }
     4878                Reductor = ideal(helpP);
     4879                attrib(Reductor, "isSB",1);
     4880                Indicator=reduce(Indicator,Reductor);
     4881                SizeSave++;
     4882                SaveRed[SizeSave] = helpP;
     4883                attrib(SaveRed, "isSB",1);
    47504884              }
    4751               else
    4752               { ISSort[i-1] = ideal(B[j]);
    4753               }
    4754               if (v)
    4755               { "  We found the irreducible sec. inv. "+string(B[j]);
    4756               }
    4757               helpint++;
    4758               Reductor[helpint] = helpP;
    4759               attrib(Reductor, "isSB",1);
    4760               if (ncols(Reductor)>100)
    4761               { Indicator=reduce(Indicator,Reductor);
    4762                 for (k3=1;k3<=ncols(Reductor);k3++)
    4763                 { SaveRed[SizeSave+k3] = Reductor[k3];
    4764                 }
    4765                 SizeSave=SizeSave+size(Reductor);
    4766                 Reductor = ideal(0);
    4767                 helpint = 0;
    4768                 attrib(SaveRed, "isSB",1);
    4769                 attrib(Reductor, "isSB",1);
    4770               }
     4885              B[j]=0;
     4886              ReducedCandidates[j]=0;
     4887              Indicator[j]=0;
    47714888            }
    47724889          }
    4773         }
    4774       }
     4890        } // i<=IrrSwitch
     4891      } // Computation of irreducible secondaries
    47754892      if (v)
    47764893      { "";
    47774894      }
    4778     }
    4779   }
     4895    } // if (int(dimmat[i,1])<>0)
     4896  }  // for i
    47804897  if (v)
    47814898  { "  We're done!";
     
    47844901  degBound = dgb;
    47854902
    4786 // Prepare return:
     4903  // Prepare return:
    47874904  int TotalNumber;
    47884905  for (k=1;k<=m;k++)
     
    48064923}
    48074924
    4808 
    48094925example
    48104926{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2;
     
    48164932         print(IS);
    48174933}
    4818 //example
    4819 //{ "EXAMPLE: S. King"; echo=2;
    4820 //ring r= 0, (V1,V2,V3,V4,V5,V6),dp;
    4821 //matrix A1[6][6] = 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0;
    4822 //matrix A2[6][6] = 0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0;
    4823 //list L = primary_invariants(A1,A2); // sorry, this takes a while...
    4824 //matrix S, IS = secondary_char0(L[1],L[2],L[3],1);
    4825 //S;
    4826 //IS;
    4827 //}
     4934
     4935
    48284936///////////////////////////////////////////////////////////////////////////////
    4829 
    48304937
    48314938proc irred_secondary_char0 (matrix P, matrix REY, matrix M, list #)
     
    48414948RETURN:   Irreducible homogeneous secondary invariants of the invariant ring
    48424949          (type <matrix>)
    4843 ASSUME:   REY is the 1st return value of group_reynolds(), reynolds_molien() or
     4950ASSUME:   We are in the non-modular case, i.e., the characteristic of the basering
     4951          does not divide the group order;
     4952          REY is the 1st return value of group_reynolds(), reynolds_molien() or
    48444953          the second one of primary_invariants();
    48454954          M is the return value of molien() or the second one of
     
    48524961          independent modulo the primary invariants (see paper \"Some
    48534962          Algorithms in Invariant Theory of Finite Groups\" by Kemper and
    4854           Steel (1997)). The size of this set can be read off from the
    4855           Molien series. Here, only irreducible secondary
     4963          Steel (1997)) using Groebner basis techniques. The size of this set
     4964          can be read off from the Molien series. Here, only irreducible secondary
    48564965          invariants are explicitly computed, which saves time and memory.
    4857 NOTE:     There is an internal parameter \"pieces\" that, by default, equals 15.
    4858           Setting \"pieces\" to a smaller value might decrease the memory consumption,
    4859           but increase the running time.
     4966@*        There are three internal parameters \"pieces\", \"MonStep\" and \"IrrSwitch\".
     4967          The default values of the parameters should be fine in most cases. However,
     4968          in some cases, different values may provide a better balance of memory
     4969          consumption (smaller values) and speed (bigger values).
    48604970SEE ALSO: secondary_char0
    48614971KEYWORDS: irreducible secondary invariant
    48624972EXAMPLE:  example irred_secondary_char0; shows an example
    48634973"
    4864 { def br=basering;
    4865 
     4974{ //----------  Internal parameters, whose choice might improve the performance -----
     4975  int pieces = 15;   // For generating reducible secondaries, blocks of #pieces# secondaries
     4976                     // are formed.
     4977                     // If this parameter is small, the memory consumption will decrease.
     4978  int MonStep = 15;  // The Reynolds operator is applied to blocks of #MonStep# monomials.
     4979                     // If this parameter is small, the memory consumption will decrease.
     4980  int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating
     4981                     // irreducible secondaries that tends to produce a smaller output
     4982                     // (which is good for subsequent computations). However, this method
     4983                     // needs to much memory in high degrees, and so we use a sparser method
     4984                     // from degree #IrrSwitch# on.
     4985
     4986  def br=basering;
    48664987 //----------------- checking input and setting verbose mode ------------------
    48674988  if (char(br)<>0)
    4868   { "ERROR:   irred_secondary_char0 should only be used with rings of characteristic 0.";
    4869     return();
     4989  { "ERROR:   irred_secondary_char0 can only be used with rings of characteristic 0.";
     4990    "         Try irred_secondary_charp";
     4991      return();
    48704992  }
    48714993  int i;
     
    49585080  int ii;
    49595081  int saveAttr;
    4960   ideal B,IS;              // IS will contain all irr. sec. inv.
    4961 
    4962   int pieces = 15;   // If this parameter is small, the memory consumption will decrease.
    4963                      // In some cases, a careful choice will speed up computations
     5082  ideal mon,B,IS;              // IS will contain all irr. sec. inv.
    49645083
    49655084  for (i=1;i<m;i++)
     
    50275146                }
    50285147              }
    5029               ProdCand = Mul1*Mul2;
     5148//              if (i<10)
     5149                ProdCand = simplify(Mul1*Mul2,4);
     5150//              else { ProdCand = Mul1*Mul2;}
    50305151              ReducedCandidates = reduce(ProdCand,sP);
    50315152                  // sP union SaveRed union Reductor is a homogeneous Groebner basis
     
    50425163              if (size(Indicator)<>0)
    50435164              { for (ii=1;ii<=ncols(ProdCand);ii++)     // going through all the power products
    5044                 { helpP = reduce(Indicator[ii],Reductor);
     5165                { helpP = Indicator[ii];
    50455166                  if (helpP <> 0)
    50465167                  { counter++;
     
    50545175                    }
    50555176                    if (int(dimmat[i,1])<>counter)
    5056                     { helpint++;
    5057                       Reductor[helpint] = helpP;
     5177                    { Reductor = ideal(helpP);
    50585178                        // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a
    50595179                        // homogeneous polynomial of degree i-1 then G union NF(p,G) is
     
    50635183                        // it, save it in SaveRed, and work with a smaller Reductor. This turns
    50645184                        // out to save a little time.
    5065                       if (ncols(Reductor)>100)
    5066                       { Indicator=reduce(Indicator,Reductor);
    5067                         for (k3=1;k3<=ncols(Reductor);k3++)
    5068                         { SaveRed[SizeSave+k3] = Reductor[k3];
    5069                         }
    5070                         SizeSave=SizeSave+size(Reductor);
    5071                         Reductor = ideal(0);
    5072                         helpint = 0;
    5073                         attrib(SaveRed, "isSB",1);
    5074                         attrib(Reductor, "isSB",1);
    5075                       }
     5185                      Indicator=reduce(Indicator,Reductor);
     5186                      SizeSave++;
     5187                      SaveRed[SizeSave] = helpP;
     5188                      attrib(SaveRed, "isSB",1);
     5189                      attrib(Reductor, "isSB",1);
    50765190                    }
    50775191                    else
     
    50815195                }
    50825196              }
    5083               for (k3=1;k3<=size(Reductor);k3++)
    5084               { SaveRed[SizeSave+k3] = Reductor[k3];
    5085               }
    5086               SizeSave=SizeSave+size(Reductor);
    5087               Reductor = ideal(0);
    5088               helpint = 0;
    50895197              attrib(SaveRed, "isSB",1);
    50905198              attrib(Reductor, "isSB",1);
     
    50995207        { "There are irreducible secondary invariants in degree ", i-1," !!";
    51005208        }
    5101         B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6);
     5209        if (i>IrrSwitch)  // use sparse algorithm
     5210        { mon = kbase(sP,i-1);
     5211//          mon = ideal(mon[ncols(mon)..1]);
     5212          if (counter==0 && ncols(mon)==int(dimmat[i,1])) // then we can use all of mon
     5213          { B=normalize(evaluate_reynolds(REY,mon));
     5214            IS=IS+B;
     5215            saveAttr = attrib(RedSSort[i-1][i-1],"size")+int(dimmat[i,1]);
     5216            RedSSort[i-1][i-1] = RedSSort[i-1][i-1] + NF(B,sP);
     5217            attrib(RedSSort[i-1][i-1],"size", saveAttr);
     5218            if (typeof(RedISSort[i-1]) <> "none")
     5219            { RedISSort[i-1] = RedISSort[i-1] + NF(B,sP);
     5220            }
     5221            else
     5222            { RedISSort[i-1] = NF(B,sP);
     5223            }
     5224            if (v) {"  We found: "; print(B);}
     5225          }
     5226          else
     5227          { irrcounter=0;
     5228            j=0;                         // j goes through all of mon -
     5229          // Compare the comments on the computation of reducible sec. inv.!
     5230            while (int(dimmat[i,1])<>counter)
     5231            { if ((j mod MonStep) == 0)
     5232              { if ((j+MonStep) <= ncols(mon))
     5233                { B[j+1..j+MonStep] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep])));
     5234                  ReducedCandidates[j+1..j+MonStep] = reduce(ideal(B[j+1..j+MonStep]),sP);
     5235                  Indicator[j+1..j+MonStep] = reduce(ideal(ReducedCandidates[j+1..j+MonStep]),SaveRed);
     5236                }
     5237                else
     5238                { B[j+1..ncols(mon)] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ncols(mon)])));
     5239                  ReducedCandidates[j+1..ncols(mon)] = reduce(ideal(B[j+1..ncols(mon)]),sP);
     5240                  Indicator[j+1..ncols(mon)] = reduce(ideal(ReducedCandidates[j+1..ncols(mon)]),SaveRed);
     5241                }
     5242              }
     5243              j++;
     5244              helpP = Indicator[j];
     5245              if (helpP <>0)                     // B[j] should be added
     5246              { counter++; irrcounter++;
     5247                IS=IS,B[j];
     5248                saveAttr = attrib(RedSSort[i-1][i-1],"size")+1;
     5249                RedSSort[i-1][i-1][saveAttr] = ReducedCandidates[j];
     5250                attrib(RedSSort[i-1][i-1],"size",saveAttr);
     5251                if (typeof(RedISSort[i-1]) <> "none")
     5252                { RedISSort[i-1][irrcounter] = ReducedCandidates[j];
     5253                }
     5254                else
     5255                { RedISSort[i-1] = ideal(ReducedCandidates[j]);
     5256                }
     5257                if (v)
     5258                { "  We found the irreducible sec. inv. "+string(B[j]);
     5259                }
     5260                Reductor = ideal(helpP);
     5261                attrib(Reductor, "isSB",1);
     5262                Indicator=reduce(Indicator,Reductor);
     5263                SizeSave++;
     5264                SaveRed[SizeSave] = helpP;
     5265                attrib(SaveRed, "isSB",1);
     5266                attrib(Reductor, "isSB",1);
     5267              }
     5268              mon[j]=0;
     5269              B[j]=0;
     5270              ReducedCandidates[j]=0;
     5271              Indicator[j]=0;
     5272            }
     5273          }
     5274        }  // if i>IrrSwitch
     5275        else  // use fast algorithm
     5276        { B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6);
    51025277                                       // B is a set of
    51035278                                       // images of kbase(sP,i-1) under the
     
    51055280                                       // independent and that do not reduce to
    51065281                                       // 0 modulo sP -
    5107         if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of B
    5108         { IS=IS+B;
    5109           saveAttr = attrib(RedSSort[i-1][i-1],"size")+int(dimmat[i,1]);
    5110           RedSSort[i-1][i-1] = RedSSort[i-1][i-1] + B;
    5111           attrib(RedSSort[i-1][i-1],"size", saveAttr);
    5112           if (typeof(RedISSort[i-1]) <> "none")
    5113           { RedISSort[i-1] = RedISSort[i-1] + B;
     5282          if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of B
     5283          { IS=IS+B;
     5284            saveAttr = attrib(RedSSort[i-1][i-1],"size")+int(dimmat[i,1]);
     5285            RedSSort[i-1][i-1] = RedSSort[i-1][i-1] + B;
     5286            attrib(RedSSort[i-1][i-1],"size", saveAttr);
     5287            if (typeof(RedISSort[i-1]) <> "none")
     5288            { RedISSort[i-1] = RedISSort[i-1] + B;
     5289            }
     5290            else
     5291            { RedISSort[i-1] = B;
     5292            }
     5293            if (v) {"  We found: ";print(B);}
    51145294          }
    51155295          else
    5116           { RedISSort[i-1] = B;
    5117           }
    5118           if (v) {"  We found: ";print(B);}
    5119         }
    5120         else
    5121         { irrcounter=0;
    5122           j=0;                         // j goes through all of B -
    5123         // Compare the comments on the computation of reducible sec. inv.!
    5124           ReducedCandidates = reduce(B,sP);
    5125           Indicator = reduce(ReducedCandidates,SaveRed);
    5126           while (int(dimmat[i,1])<>counter)    // need to find dimmat[i,1]
    5127           {                                    // invariants that are linearly independent
    5128             j++;
    5129             helpP = reduce(Indicator[j],Reductor);
    5130             if (helpP <>0)                     // B[j] should be added
    5131             { counter++; irrcounter++;
    5132               IS=IS,B[j];
    5133               saveAttr = attrib(RedSSort[i-1][i-1],"size")+1;
    5134               RedSSort[i-1][i-1][saveAttr] = ReducedCandidates[j];
    5135               attrib(RedSSort[i-1][i-1],"size",saveAttr);
    5136               if (typeof(RedISSort[i-1]) <> "none")
    5137               { RedISSort[i-1][irrcounter] = ReducedCandidates[j];
    5138               }
    5139               else
    5140               { RedISSort[i-1] = ideal(ReducedCandidates[j]);
    5141               }
    5142               if (v)
    5143               { "  We found the irreducible sec. inv. "+string(B[j]);
    5144               }
    5145               helpint++;
    5146               Reductor[helpint] = helpP;
    5147               attrib(Reductor, "isSB",1);
    5148               if (ncols(Reductor)>100)
    5149               { Indicator=reduce(Indicator,Reductor);
    5150                 for (k3=1;k3<=ncols(Reductor);k3++)
    5151                 { SaveRed[SizeSave+k3] = Reductor[k3];
     5296          { irrcounter=0;
     5297            j=0;                         // j goes through all of B -
     5298            // Compare the comments on the computation of reducible sec. inv.!
     5299            ReducedCandidates = reduce(B,sP);
     5300            Indicator = reduce(ReducedCandidates,SaveRed);
     5301            while (int(dimmat[i,1])<>counter)    // need to find dimmat[i,1]
     5302            {                                    // invariants that are linearly independent
     5303              j++;
     5304              helpP = Indicator[j];
     5305              if (helpP <>0)                     // B[j] should be added
     5306              { counter++; irrcounter++;
     5307                IS=IS,B[j];
     5308                saveAttr = attrib(RedSSort[i-1][i-1],"size")+1;
     5309                RedSSort[i-1][i-1][saveAttr] = ReducedCandidates[j];
     5310                attrib(RedSSort[i-1][i-1],"size",saveAttr);
     5311                if (typeof(RedISSort[i-1]) <> "none")
     5312                { RedISSort[i-1][irrcounter] = ReducedCandidates[j];
    51525313                }
    5153                 SizeSave=SizeSave+size(Reductor);
    5154                 Reductor = ideal(0);
    5155                 helpint = 0;
     5314                else
     5315                { RedISSort[i-1] = ideal(ReducedCandidates[j]);
     5316                }
     5317                if (v)
     5318                { "  We found the irreducible sec. inv. "+string(B[j]);
     5319                }
     5320                Reductor = ideal(helpP);
     5321                attrib(Reductor, "isSB",1);
     5322                Indicator=reduce(Indicator,Reductor);
     5323                SizeSave++;
     5324                SaveRed[SizeSave] = helpP;
    51565325                attrib(SaveRed, "isSB",1);
    51575326                attrib(Reductor, "isSB",1);
    51585327              }
     5328              B[j]=0;
     5329              ReducedCandidates[j]=0;
     5330              Indicator[j]=0;
    51595331            }
    51605332          }
    5161         }
    5162       }
     5333        } // i<=IrrSwitch
     5334      } // Computation of irreducible secondaries
    51635335      if (v)
    51645336      { "";
     
    51895361matrix A1[6][6] = 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0;
    51905362matrix A2[6][6] = 0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0;
    5191 list L = primary_invariants(A1,A2); // sorry, this takes a while...
     5363list L = primary_invariants(A1,A2);
    51925364matrix IS = irred_secondary_char0(L[1],L[2],L[3],0);
    51935365IS;
     
    51975369///////////////////////////////////////////////////////////////////////////////
    51985370
    5199 
    5200 proc secondary_charp (matrix P, matrix REY, string ring_name, list #)
     5371proc old_secondary_charp (matrix P, matrix REY, string ring_name, list #)
    52015372"USAGE:   secondary_charp(P,REY,ringname[,v]);
    52025373         P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix>
     
    54215592///////////////////////////////////////////////////////////////////////////////
    54225593
     5594
     5595proc secondary_charp (matrix P, matrix REY, string ring_name, list #)
     5596"USAGE:   secondary_charp(P,REY,ringname[,v][,\"old\"]);
     5597@*          P: a 1xn <matrix> with homogeneous primary invariants, where
     5598               n is the number of variables of the basering;
     5599@*          REY: a gxn <matrix> representing the Reynolds operator, where
     5600               g the size of the corresponding group;
     5601@*          ringname: a <string> giving the name of a ring of characteristic 0
     5602               containing a 1x2 <matrix> M giving numerator and denominator of the Molien
     5603               series;
     5604@*          v: an optional <int>;
     5605@*          \"old\": if this string occurs as (optional) parameter, then an
     5606               old version of secondary_char0 is used (for downward
     5607               compatibility)
     5608ASSUME:   The characteristic of basering is not zero;
     5609          REY is the 1st return value of group_reynolds(), reynolds_molien() or
     5610          the second one of primary_invariants();
     5611@*        `ringname` is the name of a ring of characteristic 0 that has been created
     5612          by molien() or reynolds_molien() or primary_invariants()
     5613RETURN:   secondary invariants of the invariant ring (type <matrix>) and
     5614          irreducible secondary invariants (type <matrix>)
     5615DISPLAY:  information if v does not equal 0
     5616THEORY:   The secondary invariants are calculated by finding a basis (in terms
     5617          of monomials) of the basering modulo the primary invariants, mapping
     5618          those to invariants with the Reynolds operator. Among these images
     5619          or their power products we pick a maximal subset that is linearly
     5620          independent modulo the primary invariants (see paper \"Some
     5621          Algorithms in Invariant Theory of Finite Groups\" by Kemper and
     5622          Steel (1997)) using Groebner basis techniques. The size of this set
     5623          can be read off from the Molien series.
     5624EXAMPLE:  example secondary_charp; shows an example
     5625"
     5626{
     5627 //----------  Internal parameters, whose choice might improve the performance -----
     5628  int pieces = 15;   // For generating reducible secondaries, blocks of #pieces# secondaries
     5629                     // are formed.
     5630                     // If this parameter is small, the memory consumption will decrease.
     5631  int MonStep = 15;  // The Reynolds operator is applied to blocks of #MonStep# monomials.
     5632                     // If this parameter is small, the memory consumption will decrease.
     5633  int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating
     5634                     // irreducible secondaries that tends to produce a smaller output
     5635                     // (which is good for subsequent computations). However, this method
     5636                     // needs to much memory in high degrees, and so we use a sparser method
     5637                     // from degree #IrrSwitch# on.
     5638
     5639  def br=basering;
     5640
     5641 //---------------- checking input and setting verbose mode -------------------
     5642  if (char(br)==0)
     5643  { "ERROR:   secondary_charp should only be used with rings of characteristic p>0.";
     5644    return();
     5645  }
     5646  int i;
     5647  if (size(#)>0)
     5648  { if (typeof(#[size(#)])=="int")
     5649    { int v=#[size(#)];
     5650    }
     5651    else
     5652    { int v=0;
     5653    }
     5654  }
     5655  else
     5656  { int v=0;
     5657  }
     5658  if (size(#)>0)
     5659  { if (typeof(#[size(#)])=="string")
     5660    { if (#[size(#)]=="old")
     5661      { if (typeof(#[1])=="int")
     5662        { matrix S,IS = old_secondary_charp(P,REY,ring_name,#[1]);
     5663          return(S,IS);
     5664        }
     5665        else
     5666        { matrix S,IS = old_secondary_charp(P,REY,ring_name);
     5667          return(S,IS);
     5668        }
     5669      }
     5670      else
     5671      { "ERROR:   If the last optional parameter is a string, it should be \"old\".";
     5672        return(matrix(ideal()),matrix(ideal()));
     5673      }
     5674    }
     5675  }
     5676  int n=nvars(br);                     // n is the number of variables, as well
     5677                                       // as the size of the matrices, as well
     5678                                       // as the number of primary invariants,
     5679                                       // we should get
     5680  if (ncols(P)<>n)
     5681  { "ERROR:   The first parameter ought to be the matrix of the primary";
     5682    "         invariants."
     5683    return();
     5684  }
     5685  if (ncols(REY)<>n)
     5686  { "ERROR:   The second parameter ought to be the Reynolds operator."
     5687    return();
     5688  }
     5689  if (typeof(`ring_name`)<>"ring")
     5690  { "ERROR:   The <string> should give the name of the ring where the Molien."
     5691    "         series is stored.";
     5692    return();
     5693  }
     5694  if (v && voice==2)
     5695  { "";
     5696  }
     5697  int j, m, counter, irrcounter, d;
     5698  intvec deg_dim_vec;
     5699 //- finding the polynomial giving number and degrees of secondary invariants -
     5700  for (j=1;j<=n;j++)
     5701  { deg_dim_vec[j]=deg(P[j]);
     5702  }
     5703  setring `ring_name`;
     5704  poly p=1;
     5705  for (j=1;j<=n;j++)                   // calculating the denominator of the
     5706  { p=p*(1-var(1)^deg_dim_vec[j]);     // Hilbert series of the ring generated
     5707  }                                    // by the primary invariants -
     5708  matrix s[1][2]=M[1,1]*p,M[1,2];      // s is used for canceling
     5709  s=matrix(syz(ideal(s)));
     5710  p=s[2,1];                            // the polynomial telling us where to
     5711                                       // search for secondary invariants
     5712  map slead=basering,ideal(0);
     5713  p=1/slead(p)*p;                      // smallest term of p needs to be 1
     5714
     5715  matrix dimmat=coeffs(p,var(1));      // dimmat will contain the number of
     5716                                       // secondary invariants, we need to find
     5717                                       // of a certain degree -
     5718  m=nrows(dimmat);                     // m-1 is the highest degree
     5719  if (v)
     5720  { "We need to find";
     5721    for (j=1;j<=m;j++)
     5722     { if (int(dimmat[j,1])<>1)
     5723       { int(dimmat[j,1]), "secondary invariants in degree",j-1;
     5724       }
     5725       else
     5726       { "1 secondary invariant in degree",j-1;
     5727       }
     5728     }
     5729  }
     5730  deg_dim_vec=1;
     5731  for (j=2;j<=m;j++)
     5732  { deg_dim_vec=deg_dim_vec,int(dimmat[j,1]); // i.e., deg_dim_vec[i] = dimmat[i-1,1],
     5733                                              // which is the number of secondaries in degree i-1
     5734  }
     5735  if (v)
     5736  { "  In degree 0 we have: 1";
     5737    "";
     5738  }
     5739 //------------------------ initializing variables ----------------------------
     5740  setring br;
     5741  ideal ProdCand;          // contains products of secondary invariants,
     5742                           // i.e., candidates for reducible sec. inv.
     5743  ideal Mul1,Mul2;
     5744
     5745  int dgb=degBound;
     5746  degBound = 0;
     5747  option(redSB);
     5748  ideal sP = groebner(ideal(P));
     5749                           // This is the only explicit Groebner basis computation!
     5750  ideal Reductor,SaveRed;  // sP union Reductor is a Groebner basis up to degree i-1
     5751  int SizeSave;
     5752
     5753  list SSort;         // sec. inv. first sorted by degree and then sorted by the
     5754                      // minimal degree of a non-constant invariant factor.
     5755  list ISSort;        // irr. sec. inv. sorted by degree
     5756
     5757  poly helpP;
     5758  ideal helpI;
     5759  ideal Indicator;        // will tell us which candidates for sec. inv. we can choose
     5760  ideal ReducedCandidates;
     5761  int helpint;
     5762  int k,k2,k3,minD;
     5763  int ii;
     5764  int saveAttr;
     5765  ideal mon,B,IS;              // IS will contain all irr. sec. inv.
     5766
     5767  for (i=1;i<m;i++)
     5768  { SSort[i] = list();
     5769    for (k=1;k<=i;k++)
     5770    { SSort[i][k]=ideal();
     5771      attrib(SSort[i][k],"size",0);
     5772    }
     5773  }
     5774 //------------------- generating secondary invariants ------------------------
     5775  for (i=2;i<=m;i++)                   // going through deg_dim_vec -
     5776  { if (deg_dim_vec[i]<>0)             // when it is == 0 we need to find no
     5777    {                                  // elements in the current degree (i-1)
     5778      if (v)
     5779      { "  Searching in degree "+string(i-1)+", we need to find "+string(deg_dim_vec[i])+
     5780        " invariant(s)...";
     5781        "  Looking for Power Products...";
     5782      }
     5783      counter = 0;                       // we'll count up to deg_dim_vec[i]
     5784      Reductor = ideal(0);
     5785      helpint = 0;
     5786      SaveRed = Reductor;
     5787      SizeSave = 0;
     5788      attrib(Reductor,"isSB",1);
     5789      attrib(SaveRed,"isSB",1);
     5790
     5791// We start searching for reducible secondary invariants in degree i-1, i.e., those
     5792// that are power products of irreducible secondary invariants.
     5793// It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1)
     5794// with some sec. inv. (Mul2).
     5795// Moreover, we avoid to consider power products twice since we take a product
     5796// into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not
     5797// smaller than the degree of "Mul1".
     5798      for (k=1;k<i-1;k++)
     5799      { if (deg_dim_vec[i]==counter)
     5800        { break;
     5801        }
     5802        if (typeof(ISSort[k])<>"none")
     5803        { Mul1 = ISSort[k];
     5804        }
     5805        else
     5806        { Mul1 = ideal(0);
     5807        }
     5808        if ((deg_dim_vec[i-k]>0) && (Mul1[1]<>0))
     5809        { for (minD=k;minD<i-k;minD++)
     5810          { if (deg_dim_vec[i]==counter)
     5811            { break;
     5812            }
     5813            for (k2=1;k2 <= ((attrib(SSort[i-k-1][minD],"size")-1) div pieces)+1; k2++)
     5814            { if (deg_dim_vec[i]==counter)
     5815              { break;
     5816              }
     5817              Mul2=ideal(0);
     5818              if (attrib(SSort[i-k-1][minD],"size")>=k2*pieces)
     5819              { for (k3=1;k3<=pieces;k3++)
     5820                { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3];
     5821                }
     5822              }
     5823              else
     5824              { for (k3=1;k3<=(attrib(SSort[i-k-1][minD],"size") mod pieces);k3++)
     5825                { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3];
     5826                }
     5827              }
     5828//              if (i<10)
     5829                ProdCand = simplify(Mul1*Mul2,4);
     5830//              else { ProdCand = Mul1*Mul2;}
     5831              ReducedCandidates = reduce(ProdCand,sP);
     5832                  // sP union SaveRed union Reductor is a homogeneous Groebner basis
     5833                  // up to degree i-1.
     5834                  // We first reduce by sP (which is fixed, so we can do it once for all),
     5835                  // then by SaveRed resp. by Reductor (which is modified during
     5836                  // the computations).
     5837              Indicator = reduce(ReducedCandidates,SaveRed);
     5838                             // If Indicator[ii]==0 then ReducedCandidates it the reduction
     5839                             // of an invariant that is in the algebra generated by primary
     5840                             // invariants and previously computed secondary invariants.
     5841                             // Otherwise ProdCand[ii] can be taken as secondary invariant.
     5842              if (size(Indicator)<>0)
     5843              { for (ii=1;ii<=ncols(ProdCand);ii++)     // going through all the power products
     5844                { helpP = Indicator[ii];
     5845                  if (helpP <> 0)
     5846                  { counter++;
     5847                    saveAttr = attrib(SSort[i-1][k],"size")+1;
     5848                    SSort[i-1][k][saveAttr] = ProdCand[ii];
     5849                        // By construction, this is a _reducible_ s.i.
     5850                    attrib(SSort[i-1][k],"size",saveAttr);
     5851                    if (v)
     5852                    { "We found",counter, " of", deg_dim_vec[i]," secondaries in degree",i-1;
     5853                    }
     5854                    if (deg_dim_vec[i]<>counter)
     5855                    { Reductor = ideal(helpP);
     5856                        // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a
     5857                        // homogeneous polynomial of degree i-1 then G union NF(p,G) is
     5858                        // a homogeneous Groebner basis up to degree i-1.
     5859                      attrib(Reductor, "isSB",1);
     5860                        // if Reductor becomes too large, we reduce the whole of Indicator by
     5861                        // it, save it in SaveRed, and work with a smaller Reductor. This turns
     5862                        // out to save a little time.
     5863                      Indicator=reduce(Indicator,Reductor);
     5864                      SizeSave++;
     5865                      SaveRed[SizeSave] = helpP;
     5866                      attrib(SaveRed, "isSB",1);
     5867                    }
     5868                    else
     5869                    { break;
     5870                    }
     5871                  }
     5872                }
     5873              }
     5874//              attrib(SaveRed, "isSB",1);
     5875            }
     5876          }
     5877        }
     5878      }
     5879
     5880      // The remaining sec. inv. are irreducible!
     5881      if (deg_dim_vec[i]<>counter)   // need more than all the power products
     5882      { if (v)
     5883        { "There are irreducible secondary invariants in degree ", i-1," !!";
     5884        }
     5885        if (i>IrrSwitch)  // use sparse algorithm
     5886        { mon = kbase(sP,i-1);
     5887//          mon = ideal(mon[ncols(mon)..1]);
     5888          if (counter==0 && ncols(mon)==deg_dim_vec[i]) // then we can use all of mon
     5889          { B=normalize(evaluate_reynolds(REY,mon));
     5890            IS=IS+B;
     5891            saveAttr = attrib(SSort[i-1][i-1],"size")+deg_dim_vec[i];
     5892            SSort[i-1][i-1] = SSort[i-1][i-1] + B;
     5893            attrib(SSort[i-1][i-1],"size", saveAttr);
     5894            if (typeof(ISSort[i-1]) <> "none")
     5895            { ISSort[i-1] = ISSort[i-1] + B;
     5896            }
     5897            else
     5898            { ISSort[i-1] = B;
     5899            }
     5900            if (v) {"  We found: "; print(B);}
     5901          }
     5902          else
     5903          { irrcounter=0;
     5904            j=0;                         // j goes through all of mon -
     5905            // Compare the comments on the computation of reducible sec. inv.!
     5906            while (deg_dim_vec[i]<>counter)
     5907            { if ((j mod MonStep) == 0)
     5908              { if ((j+MonStep) <= ncols(mon))
     5909                { B[j+1..j+MonStep] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep])));
     5910                  ReducedCandidates[j+1..j+MonStep] = reduce(ideal(B[j+1..j+MonStep]),sP);
     5911                  Indicator[j+1..j+MonStep] = reduce(ideal(ReducedCandidates[j+1..j+MonStep]),SaveRed);
     5912                }
     5913                else
     5914                { B[j+1..ncols(mon)] = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ncols(mon)])));
     5915                  ReducedCandidates[j+1..ncols(mon)] = reduce(ideal(B[j+1..ncols(mon)]),sP);
     5916                  Indicator[j+1..ncols(mon)] = reduce(ideal(ReducedCandidates[j+1..ncols(mon)]),SaveRed);
     5917                }
     5918              }
     5919              j++;
     5920              helpP = Indicator[j];
     5921              if (helpP <>0)                  // B[j] should be added
     5922              { counter++; irrcounter++;
     5923                IS=IS,B[j];
     5924                saveAttr = attrib(SSort[i-1][i-1],"size")+1;
     5925                SSort[i-1][i-1][saveAttr] = B[j];
     5926                attrib(SSort[i-1][i-1],"size",saveAttr);
     5927                if (typeof(ISSort[i-1]) <> "none")
     5928                { ISSort[i-1][irrcounter] = B[j];
     5929                }
     5930                else
     5931                { ISSort[i-1] = ideal(B[j]);
     5932                }
     5933                if (v)
     5934                { "  We found the irreducible sec. inv. "+string(B[j]);
     5935                }
     5936                Reductor = ideal(helpP);
     5937                attrib(Reductor, "isSB",1);
     5938                Indicator=reduce(Indicator,Reductor);
     5939                SizeSave++;
     5940                SaveRed[SizeSave] = helpP;
     5941                attrib(SaveRed, "isSB",1);
     5942              }
     5943              B[j]=0;
     5944              ReducedCandidates[j]=0;
     5945              Indicator[j]=0;
     5946            }
     5947          }
     5948        }  // if i>IrrSwitch
     5949        else  // use fast algorithm
     5950        { B=sort_of_invariant_basis(sP,REY,i-1,deg_dim_vec[i]*6);
     5951                                       // B contains
     5952                                       // images of kbase(sP,i-1) under the
     5953                                       // Reynolds operator that are linearly
     5954                                       // independent
     5955          if (counter==0 && ncols(B)==deg_dim_vec[i]) // then we can take all of B
     5956          { IS=IS+B;
     5957            saveAttr = attrib(SSort[i-1][i-1],"size")+deg_dim_vec[i];
     5958            SSort[i-1][i-1] = SSort[i-1][i-1] + B;
     5959            attrib(SSort[i-1][i-1],"size", saveAttr);
     5960            if (typeof(ISSort[i-1]) <> "none")
     5961            { ISSort[i-1] = ISSort[i-1] + B;
     5962            }
     5963            else
     5964            { ISSort[i-1] = B;
     5965            }
     5966            if (v) {"  We found: "; print(B);}
     5967          }
     5968          else
     5969          { irrcounter=0;
     5970            j=0;                         // j goes through all of B -
     5971            // Compare the comments on the computation of reducible sec. inv.!
     5972            ReducedCandidates = reduce(B,sP);
     5973            Indicator = reduce(ReducedCandidates,SaveRed);
     5974            while (deg_dim_vec[i]<>counter)
     5975            { j++;
     5976              helpP = Indicator[j];
     5977              if (helpP <>0)                  // B[j] should be added
     5978              { counter++; irrcounter++;
     5979                IS=IS,B[j];
     5980                saveAttr = attrib(SSort[i-1][i-1],"size")+1;
     5981                SSort[i-1][i-1][saveAttr] = B[j];
     5982                attrib(SSort[i-1][i-1],"size",saveAttr);
     5983                if (typeof(ISSort[i-1]) <> "none")
     5984                { ISSort[i-1][irrcounter] = B[j];
     5985                }
     5986                else
     5987                { ISSort[i-1] = ideal(B[j]);
     5988                }
     5989                if (v)
     5990                { "  We found the irreducible sec. inv. "+string(B[j]);
     5991                }
     5992                Reductor = ideal(helpP);
     5993                attrib(Reductor, "isSB",1);
     5994                Indicator=reduce(Indicator,Reductor);
     5995                SizeSave++;
     5996                SaveRed[SizeSave] = helpP;
     5997                attrib(SaveRed, "isSB",1);
     5998              }
     5999              B[j]=0;
     6000              ReducedCandidates[j]=0;
     6001              Indicator[j]=0;
     6002            }
     6003          }
     6004        } // i<=IrrSwitch
     6005      } // Computation of irreducible secondaries
     6006      if (v)
     6007      { "";
     6008      }
     6009    } // if (deg_dim_vec[i]<>0)
     6010  }  // for i
     6011  if (v)
     6012  { "  We're done!";
     6013    "";
     6014  }
     6015  degBound = dgb;
     6016
     6017  // Prepare return:
     6018  int TotalNumber;
     6019  for (k=1;k<=m;k++)
     6020  { TotalNumber = TotalNumber + deg_dim_vec[k];
     6021  }
     6022  matrix S[1][TotalNumber];
     6023  S[1,1]=1;
     6024  j=1;
     6025  for (k=1;k<m;k++)
     6026  { for (k2=1;k2<=k;k2++)
     6027    { if (typeof(attrib(SSort[k][k2],"size"))=="int")
     6028     {for (i=1;i<=attrib(SSort[k][k2],"size");i++)
     6029      { j++;
     6030        S[1,j] = SSort[k][k2][i];
     6031      }
     6032      SSort[k][k2]=ideal();
     6033     }
     6034    }
     6035  }
     6036  if (ring_name=="aksldfalkdsflkj")
     6037  { kill `ring_name`;
     6038  }
     6039  return(matrix(S),matrix(compress(IS)));
     6040}
     6041example
     6042{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2;
     6043         ring R=3,(x,y,z),dp;
     6044         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
     6045         list L=primary_invariants(A);
     6046         matrix S,IS=secondary_charp(L[1..size(L)],1);
     6047         print(S);
     6048         print(IS);
     6049}
     6050///////////////////////////////////////////////////////////////////////////////
     6051
    54236052proc secondary_no_molien (matrix P, matrix REY, list #)
    54246053"USAGE:   secondary_no_molien(P,REY[,deg_vec,v]);
     
    54376066         monomials) of the basering modulo primary invariants, mapping those to
    54386067         invariants with the Reynolds operator and using these images as
    5439          candidates for secondary invariants.
     6068         candidates for secondary invariants. We have the Reynolds operator, hence,
     6069         we are in the non-modular case. Therefore, the invariant ring is Cohen-Macaulay,
     6070         hence the number of secondary invariants is the product of the degrees of
     6071         primary invariants divided by the group order.
    54406072EXAMPLE: example secondary_no_molien; shows an example
    54416073"
     
    58796511    M(1)[i,1..k]=B[1..k];              // we will look for the syzygies of M(1)
    58806512  }
    5881   //intvec save_opts=option(get);
    5882   //option(returnSB,redSB);
    5883   //module M(2)=syz(M(1));               // nres(M(1),2)[2];
    5884   //option(set,save_opts);
     6513//  intvec save_opts=option(get);
     6514//  option(returnSB,redSB);
     6515//  module M(2)=syz(M(1));               // nres(M(1),2)[2];
     6516//  option(set,save_opts);
    58856517  module M(2)=nres(M(1),2)[2];
    58866518  int m=ncols(M(2));                   // number of generators of the module
     
    59336565    "           group order.";
    59346566  }
    5935   return(S);
     6567  return(matrix(S));
    59366568}
    59376569example
     
    59546586         Molien series is computed as if the base field were characteristic 0
    59556587         (the user must choose a field of large prime characteristic, e.g.
    5956          32003), and if the first one is anything else, it means that the
     6588         32003) and if the first one is anything else, it means that the
    59576589         characteristic of the base field divides the group order (i.e. it will
    59586590         not even be attempted to compute the Reynolds operator or Molien
     
    60516683        else
    60526684        { if (v)
    6053           { "  Since it is impossible for this program to calculate the Molien
     6685          { "  Since it is impossible for this programme to calculate the Molien
    60546686 series for";
    60556687            "  invariant rings over extension fields of prime characteristic, we
     
    61716803         i.e. the Molien series is computed as if the base field were
    61726804         characteristic 0 (the user must choose a field of large prime
    6173          characteristic, e.g.  32003), and if the first one is anything else,
     6805         characteristic, e.g.  32003) and if the first one is anything else,
    61746806         then the characteristic of the base field divides the group order
    61756807         (i.e. we will not even attempt to compute the Reynolds operator or
     
    62866918        else
    62876919        { if (v)
    6288           { "  Since it is impossible for this program to calculate the Molien
     6920          { "  Since it is impossible for this programme to calculate the Molien
    62896921 series for";
    62906922            "  invariant rings over extension fields of prime characteristic, we
     
    64037035THEORY:  The ideal of algebraic relations of the invariant ring generators is
    64047036         calculated, then the variables of the original ring are eliminated and
    6405          the polynomials that are left over define the orbit variety.
     7037         the polynomials that are left over define the orbit variety
    64067038EXAMPLE: example orbit_variety; shows an example
    64077039"
     
    66207252@*       s: a <string> giving a name for a new ring
    66217253RETURN:  The procedure ends with a new ring named s.
    6622          It contains a Groebner basis (type <ideal>, named G) for the ideal
    6623          defining the relative orbit variety with respect to I in the new ring.
     7254         It contains a Groebner basis
     7255         (type <ideal>, named G) for the ideal defining the
     7256         relative orbit variety with respect to I in the new ring.
    66247257THEORY:  A Groebner basis of the ideal of algebraic relations of the invariant
    66257258         ring generators is calculated, then one of the basis elements plus the
     
    67067339@*       F: a 1xm <matrix> defining an invariant ring of some matrix group
    67077340RETURN:  The <ideal> defining the image under that group of the variety defined
    6708          by I.
     7341         by I
    67097342THEORY:  rel_orbit_variety(I,F) is called and the newly introduced
    67107343@*       variables in the output are replaced by the generators of the
    67117344@*       invariant ring. This ideal in the original variables defines the image
    6712 @*       of the variety defined by I.
     7345@*       of the variety defined by I
    67137346EXAMPLE: example image_of_variety; shows an example
    67147347"
     
    67437376
    67447377
    6745 
    6746 
     7378proc secondary_charp_degbound (matrix P, int dmax, list #)
     7379"USAGE:   secondary_charp_degbound(P,G1,...,Gk[,v]);
     7380@*          P: a 1xn <matrix> with homogeneous primary invariants, where
     7381               n is the number of variables of the basering;
     7382@*          G1,...,Gk matrices generating a matrix group for which P are homogeneous
     7383            primary invariants.
     7384@*          v: an optional <int>;
     7385ASSUME:   The characteristic of basering is not zero
     7386RETURN:   secondary invariants of the invariant ring (type <matrix>) and
     7387          irreducible secondary invariants (type <matrix>) of degree at most dmax.
     7388DISPLAY:  information if v does not equal 0
     7389THEORY:   A basis of invariants of degrees d<dmax+1 is computed using invariant_basis.
     7390          Among the basis elements and their power products we pick a maximal subset
     7391          that is linearly independent modulo the primary invariants (see paper \"Some
     7392          Algorithms in Invariant Theory of Finite Groups\" by Kemper and
     7393          Steel (1997)) using Groebner basis techniques.
     7394@*        If dmax is at least the Noether number of the invariant ring, then primary
     7395          invariants and the irreducible secondaries found by secondary_charp_degbound
     7396          are algebra generators of the invariant ring. This may work
     7397          faster than an application of secondary_not_cohen_macaulay.
     7398SEE ALSO: secondary_charp, secondary_char0, secondary_not_cohen_macaulay
     7399EXAMPLE:  example secondary_charp_molien; shows an example
     7400"
     7401{
     7402 //----------  Internal parameters, whose choice might improve the performance -----
     7403  int pieces = 15;   // For generating reducible secondaries, blocks of #pieces# secondaries
     7404                     // are formed.
     7405                     // If this parameter is small, the memory consumption will decrease.
     7406
     7407  def br=basering;
     7408
     7409 //---------------- checking input and setting verbose mode -------------------
     7410  int n=nvars(br);                     // n is the number of variables, as well
     7411                                       // as the size of the matrices, as well
     7412                                       // as the number of primary invariants,
     7413                                       // we should get
     7414  if (char(br)==0)
     7415  { "ERROR:   secondary_charp_degbound should only be used with rings of characteristic p>0.";
     7416    return();
     7417  }
     7418  int i;
     7419  if (size(#)==0)
     7420  { "ERROR: There are no generators given.";
     7421    return();
     7422  }
     7423  if (typeof(#[size(#)])=="int")
     7424  { int v=#[size(#)];
     7425  }
     7426  else
     7427  { int v=0;
     7428  }
     7429  list GEN;
     7430  for (i=1;i<size(#);i++)
     7431  { if ((typeof(#[i])=="matrix") and
     7432        (ncols(#[i])==n) and (nrows(#[i])==n))
     7433    { GEN[i] = #[i];
     7434    }
     7435    else
     7436    { "ERROR: The generators should be square matrices of appropriate size.";
     7437       return();
     7438    }
     7439  }
     7440  if (typeof(#[size(#)])<>"int")
     7441  { if ((typeof(#[size(#)])=="matrix") and
     7442        (ncols(#[size(#)])==n) and (nrows(#[size(#)])==n))
     7443    { GEN[i] = #[size(#)];
     7444    }
     7445    else
     7446    { "ERROR: The last optional parameter should be an integer.";
     7447       return();
     7448    }
     7449  }
     7450
     7451  if (ncols(P)<>n)
     7452  { "ERROR:   The first parameter ought to be the matrix of the primary";
     7453    "         invariants."
     7454    return();
     7455  }
     7456  if (v && voice==2)
     7457  { "";
     7458  }
     7459  if (v)
     7460  { "  In degree 0 we have: 1";
     7461    "";
     7462  }
     7463 //------------------------ initializing variables ----------------------------
     7464  setring br;
     7465  ideal ProdCand;          // contains products of secondary invariants,
     7466                           // i.e., candidates for reducible sec. inv.
     7467  ideal Mul1,Mul2;
     7468
     7469  int j, counter, irrcounter, d;
     7470  int m = dmax+1;
     7471  int dgb = degBound;
     7472  degBound = 0;
     7473//  degBound = dmax;
     7474  option(redSB);
     7475  ideal sP = groebner(ideal(P));
     7476                           // This is the only explicit Groebner basis computation!
     7477  ideal Reductor,SaveRed;  // sP union Reductor is a Groebner basis up to degree i-1
     7478  int SizeSave;
     7479
     7480  list SSort;         // sec. inv. first sorted by degree and then sorted by the
     7481                      // minimal degree of a non-constant invariant factor.
     7482  list ISSort;        // irr. sec. inv. sorted by degree
     7483
     7484  poly helpP;
     7485  ideal helpI;
     7486  ideal Indicator;        // will tell us which candidates for sec. inv. we can choose
     7487  ideal ReducedCandidates;
     7488  int helpint;
     7489  int k,k2,k3,minD;
     7490  int ii;
     7491  int saveAttr;
     7492  ideal mon,B,IS;              // IS will contain all irr. sec. inv.
     7493
     7494  for (i=1;i<m;i++)
     7495  { SSort[i] = list();
     7496    for (k=1;k<=i;k++)
     7497    { SSort[i][k]=ideal();
     7498      attrib(SSort[i][k],"size",0);
     7499    }
     7500  }
     7501 //------------------- generating secondary invariants ------------------------
     7502  for (i=2;i<=m;i++)                   // going through the invariants of degree i-1 -
     7503    {                                  // starting with reducibles
     7504      if (v)
     7505      { "  Looking for Power Products...";
     7506      }
     7507      counter = 0;                      // counts the number of secondaries
     7508      Reductor = ideal(0);
     7509      helpint = 0;
     7510      SaveRed = Reductor;
     7511      SizeSave = 0;
     7512      attrib(Reductor,"isSB",1);
     7513      attrib(SaveRed,"isSB",1);
     7514
     7515// We start searching for reducible secondary invariants in degree i-1, i.e., those
     7516// that are power products of irreducible secondary invariants.
     7517// It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1)
     7518// with some sec. inv. (Mul2).
     7519// Moreover, we avoid to consider power products twice since we take a product
     7520// into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not
     7521// smaller than the degree of "Mul1".
     7522      for (k=1;k<i-1;k++)
     7523      { if (typeof(ISSort[k])<>"none")
     7524        { Mul1 = ISSort[k];
     7525        }
     7526        else
     7527        { Mul1 = ideal(0);
     7528        }
     7529        if (Mul1[1]<>0)
     7530        { for (minD=k;minD<i-k;minD++)
     7531          { for (k2=1;k2 <= ((attrib(SSort[i-k-1][minD],"size")-1) div pieces)+1; k2++)
     7532            { Mul2=ideal(0);
     7533              if (attrib(SSort[i-k-1][minD],"size")>=k2*pieces)
     7534              { for (k3=1;k3<=pieces;k3++)
     7535                { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3];
     7536                }
     7537              }
     7538              else
     7539              { for (k3=1;k3<=(attrib(SSort[i-k-1][minD],"size") mod pieces);k3++)
     7540                { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3];
     7541                }
     7542              }
     7543//              if (i<10)
     7544                ProdCand = simplify(Mul1*Mul2,4);
     7545//              else { ProdCand = Mul1*Mul2;}
     7546              ReducedCandidates = reduce(ProdCand,sP);
     7547                  // sP union SaveRed union Reductor is a homogeneous Groebner basis
     7548                  // up to degree i-1.
     7549                  // We first reduce by sP (which is fixed, so we can do it once for all),
     7550                  // then by SaveRed resp. by Reductor (which is modified during
     7551                  // the computations).
     7552              Indicator = reduce(ReducedCandidates,SaveRed);
     7553                             // If Indicator[ii]==0 then ReducedCandidates it the reduction
     7554                             // of an invariant that is in the algebra generated by primary
     7555                             // invariants and previously computed secondary invariants.
     7556                             // Otherwise ProdCand[ii] can be taken as secondary invariant.
     7557              if (size(Indicator)<>0)
     7558              { for (ii=1;ii<=ncols(ProdCand);ii++)     // going through all the power products
     7559                { helpP = Indicator[ii];
     7560                  if (helpP <> 0)
     7561                  { counter++;
     7562                    saveAttr = attrib(SSort[i-1][k],"size")+1;
     7563                    SSort[i-1][k][saveAttr] = ProdCand[ii];
     7564                        // By construction, this is a _reducible_ s.i.
     7565                    attrib(SSort[i-1][k],"size",saveAttr);
     7566                    if (v)
     7567                    { "We found",counter, " secondaries in degree",i-1;
     7568                    }
     7569                    Reductor = ideal(helpP);
     7570                        // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a
     7571                        // homogeneous polynomial of degree i-1 then G union NF(p,G) is
     7572                        // a homogeneous Groebner basis up to degree i-1.
     7573                    attrib(Reductor, "isSB",1);
     7574                        // if Reductor becomes too large, we reduce the whole of Indicator by
     7575                        // it, save it in SaveRed, and work with a smaller Reductor. This turns
     7576                        // out to save a little time.
     7577                    Indicator=reduce(Indicator,Reductor);
     7578                    SizeSave++;
     7579                    SaveRed[SizeSave] = helpP;
     7580                    attrib(SaveRed, "isSB",1);
     7581                  }
     7582                }
     7583              }
     7584//              attrib(SaveRed, "isSB",1);
     7585            }
     7586          }
     7587        }
     7588      }
     7589
     7590      // If there are more sec. inv., then these are irreducible!
     7591      if (v)
     7592      { "Searching irreducible secondary invariants in degree ", i-1;
     7593      }
     7594      B=invariant_basis_modS(i-1,SaveRed,GEN); // B contains enough invariant polynomials of degree d
     7595      irrcounter=0;
     7596      j=0;                         // j goes through all of B -
     7597      // Compare the comments on the computation of reducible sec. inv.!
     7598      ReducedCandidates = reduce(B,sP);
     7599      Indicator = reduce(ReducedCandidates,SaveRed);
     7600      while (size(Indicator)>0)
     7601      { j++;
     7602        helpP = Indicator[j];
     7603        if (helpP <>0)                  // B[j] should be added
     7604        { counter++; irrcounter++;
     7605          IS=IS,B[j];
     7606          saveAttr = attrib(SSort[i-1][i-1],"size")+1;
     7607          SSort[i-1][i-1][saveAttr] = B[j];
     7608          attrib(SSort[i-1][i-1],"size",saveAttr);
     7609          if (typeof(ISSort[i-1]) <> "none")
     7610          { ISSort[i-1][irrcounter] = B[j];
     7611          }
     7612          else
     7613          { ISSort[i-1] = ideal(B[j]);
     7614          }
     7615          if (v)
     7616          { "  We found the irreducible sec. inv. "+string(B[j]);
     7617          }
     7618          Reductor = ideal(helpP);
     7619          attrib(Reductor, "isSB",1);
     7620          Indicator=reduce(Indicator,Reductor);
     7621          SizeSave++;
     7622          SaveRed[SizeSave] = helpP;
     7623          attrib(SaveRed, "isSB",1);
     7624        }
     7625        B[j]=0;
     7626        ReducedCandidates[j]=0;
     7627        Indicator[j]=0;
     7628      }
     7629      if (v)
     7630      { "";
     7631      }
     7632    } // for i
     7633  if (v)
     7634  { "  We're done!";
     7635    "";
     7636  }
     7637  degBound = dgb;
     7638
     7639  // Prepare return:
     7640  int TotalNumber;
     7641  for (k=1;k<m;k++)
     7642  { for (k2=1;k2<=k;k2++)
     7643    { if (typeof(attrib(SSort[k][k2],"size"))=="int")
     7644      { TotalNumber = TotalNumber + attrib(SSort[k][k2],"size");
     7645      }
     7646    }
     7647  }
     7648  matrix S[1][TotalNumber+1];
     7649  S[1,1]=1;
     7650  j=1;
     7651  for (k=1;k<m;k++)
     7652  { for (k2=1;k2<=k;k2++)
     7653    { if (typeof(attrib(SSort[k][k2],"size"))=="int")
     7654     {for (i=1;i<=attrib(SSort[k][k2],"size");i++)
     7655      { j++;
     7656        S[1,j] = SSort[k][k2][i];
     7657      }
     7658      SSort[k][k2]=ideal();
     7659     }
     7660    }
     7661  }
     7662  return(matrix(S),matrix(compress(IS)));
     7663}
     7664example
     7665{ "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2;
     7666         ring R=3,(x,y,z),dp;
     7667         matrix A[3][3]=0,1,0,-1,0,0,0,0,-1;
     7668         matrix P=primary_charp_without(A);
     7669         matrix S,IS=secondary_charp_degbound(P,4,A,1);
     7670         print(S);
     7671         print(IS);
     7672}
     7673
Note: See TracChangeset for help on using the changeset viewer.