Changeset e52b9f in git
- Timestamp:
- Jan 22, 2007, 2:08:25 PM (17 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- 8223cd635042d178325b09664e9e3c94114b9a5c
- Parents:
- 05a31dd1bac7c8886acb526ecf5503742a948378
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/LIB/finvar.lib
r05a31d re52b9f 1 1 /////////////////////////////////////////////////////////////////////////////// 2 version="$Id: finvar.lib,v 1.5 1 2006-08-02 15:40:47Singular Exp $"2 version="$Id: finvar.lib,v 1.52 2007-01-22 13:08:25 Singular Exp $" 3 3 category="Invariant theory"; 4 4 info=" … … 40 40 irred_secondary_char0() irreducible secondary invariants in char 0 41 41 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 42 45 secondary_no_molien() secondary invariants, without Molien series 46 but with Reynolds operator 43 47 secondary_and_irreducibles_no_molien() s.i. & irreducible s.i., without M.s. 44 48 secondary_not_cohen_macaulay() s.i. when invariant ring not Cohen-Macaulay … … 54 58 // sort_of_invariant_basis() lin. ind. invariants of a degree mod p.i. 55 59 // next_vector lists all of Z^n with first nonzero entry 1 56 // int_number_map integers 1..q are map ed to q field elements60 // int_number_map integers 1..q are mapped to q field elements 57 61 // search searches a number of p.i., char 0 58 62 // p_search searches a number of p.i., char p … … 90 94 " 91 95 { if (i<=0) 92 { "ERROR: the input should be > 0."; 93 return(); 96 { ERROR("ERROR: the input should be > 0."); 94 97 } 95 98 poly v1=var(1); … … 138 141 RETURN: a <list>, the first list element will be a gxn <matrix> representing 139 142 the Reynolds operator if we are in the non-modular case; if the 140 characteristic is >0, minpoly==0 and the finite group isnon-cyclic the143 characteristic is >0, minpoly==0 and the finite group non-cyclic the 141 144 second list element is an <int> giving the lowest common multiple of 142 145 the matrix group elements' order (used in molien); in general all … … 148 151 (or the generators themselves during the first run). All the ones that 149 152 have been generated before are thrown out and the program terminates 150 when no new elements arefound in one run. Additionally each time a new153 when no new elements found in one run. Additionally each time a new 151 154 group element is found the corresponding ring mapping of which the 152 155 Reynolds operator is made up is generated. They are stored in the rows … … 161 164 if (typeof(#[size(#)])=="int") 162 165 { 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"); 165 167 } 166 168 int v=#[size(#)]; … … 172 174 } 173 175 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>"); 176 177 } 177 178 int n=nrows(#[1]); 178 179 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"); 182 182 } 183 183 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"); 186 185 } 187 186 matrix vars=matrix(maxideal(1)); // creating an nx1-matrix containing the … … 209 208 // procedure 210 209 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>"); 213 211 } 214 212 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"); 217 214 } 218 215 if (unique(G(1..i),#[j])) … … 358 355 elements generated by group_reynolds(), lcm is the second return value 359 356 of group_reynolds() 360 RETURN: in case of characteristic 0 a 1x2 <matrix> giving numerator and357 RETURN: in case of characteristic 0 a 1x2 <matrix> giving enumerator and 361 358 denominator of Molien series; in case of prime characteristic a ring 362 359 with the name `ringname` of characteristic 0 is created where the same … … 379 376 { int mol_flag=#[size(#)][1]; 380 377 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"); 383 379 } 384 380 int interval=#[size(#)][2]; … … 386 382 } 387 383 else 388 { "ERROR: <intvec> should have three components"; 389 return(); 384 { ERROR("ERROR: <intvec> should have three components"); 390 385 } 391 386 if (ch<>0) … … 393 388 { int r=#[size(#)-1]; 394 389 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"); 398 392 } 399 393 else 400 394 { if (#[size(#)-2]=="") 401 { "ERROR: <string> may not be empty"; 402 return(); 395 { ERROR("ERROR: <string> may not be empty"); 403 396 } 404 397 string newring=#[size(#)-2]; … … 408 401 else 409 402 { 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"); 412 405 return(); 413 406 } 414 407 else 415 408 { if (#[size(#)-1]=="") 416 { "ERROR: <string> may not be empty"; 417 return(); 409 { ERROR("ERROR: <string> may not be empty"); 418 410 } 419 411 string newring=#[size(#)-1]; … … 435 427 { int r=#[size(#)]; 436 428 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"); 440 431 } 441 432 else 442 433 { if (#[size(#)-1]=="") 443 { "ERROR: <string> may not be empty"; 444 return(); 434 { ERROR("ERROR: <string> may not be empty"); 445 435 } 446 436 string newring=#[size(#)-1]; … … 450 440 else 451 441 { 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"); 455 444 } 456 445 else 457 446 { if (#[size(#)]=="") 458 { "ERROR: <string> may not be empty"; 459 return(); 447 { ERROR("ERROR: <string> may not be empty"); 460 448 } 461 449 string newring=#[size(#)]; … … 471 459 if (ch<>0) 472 460 { if ((g/r)*r<>g) 473 { "ERROR: <int> should divide the group order." 474 return(); 461 { ERROR("ERROR: <int> should divide the group order."); 475 462 } 476 463 } … … 507 494 //---------------------------------------------------------------------------- 508 495 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>"); 511 497 } 512 498 int n=nrows(#[1]); 513 499 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"); 517 502 } 518 503 if (v && voice<>2) … … 540 525 for (int j=1;j<=g;j++) 541 526 { 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>"); 544 528 } 545 529 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"); 548 531 } 549 532 p=det(I-v1*#[j]); // denominator of new term - … … 637 620 { setring br; 638 621 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>"); 641 623 } 642 624 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"); 645 626 } 646 627 setring bre; … … 798 779 { setring br; 799 780 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>"); 802 782 } 803 783 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"); 806 785 } 807 786 string stM(i)=string(#[i]); … … 908 887 new group element is found the corresponding ring mapping of which the 909 888 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) 911 890 is computed whenever a new element E is found. In prime characteristic 912 891 a Brauer lift is involved and the terms are only computed after the 913 892 entire matrix group is generated (to avoid the modular case). The 914 returned matrix gives numerator and denominator of the expanded893 returned matrix gives enumerator and denominator of the expanded 915 894 version where common factors have been canceled. 916 895 EXAMPLE: example reynolds_molien; shows an example … … 925 904 { int mol_flag=#[size(#)][1]; 926 905 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"); 929 907 } 930 908 int interval=#[size(#)][2]; … … 932 910 } 933 911 else 934 { "ERROR: <intvec> should have three components"; 935 return(); 912 { ERROR("ERROR: <intvec> should have three components"); 936 913 } 937 914 if (ch<>0) 938 915 { 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"); 940 917 " of a new ring where the Molien series can be stored"; 941 918 return(); … … 943 920 else 944 921 { if (#[size(#)-1]=="") 945 { "ERROR: <string> may not be empty";922 { ERROR("ERROR: <string> may not be empty"); 946 923 return(); 947 924 } … … 960 937 if (ch<>0) 961 938 { 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"); 965 941 } 966 942 else 967 943 { if (#[size(#)]=="") 968 { "ERROR: <string> may not be empty"; 969 return(); 944 { ERROR("ERROR: <string> may not be empty"); 970 945 } 971 946 string newring=#[size(#)]; … … 1018 993 if (ch==0) 1019 994 { 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>"); 1022 996 } 1023 997 int n=nrows(#[1]); 1024 998 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"); 1028 1001 } 1029 1002 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"); 1032 1004 } 1033 1005 matrix vars=matrix(maxideal(1)); // creating an nx1-matrix containing the … … 1055 1027 // procedure 1056 1028 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>"); 1059 1030 } 1060 1031 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"); 1063 1033 } 1064 1034 if (unique(G(1..i),#[j])) … … 1651 1621 print(invariant_basis(2,A)); 1652 1622 } 1623 /////////////////////////////////////////////////////////////////////////////// 1624 1625 stat 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 1631 RETURNS: invariants of degree g 1632 THEORY: 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 1653 1709 /////////////////////////////////////////////////////////////////////////////// 1654 1710 … … 2064 2120 ASSUME: REY is the first return value of group_reynolds or reynolds_molien and 2065 2121 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 not2122 DISPLAY: information about the various stages of the programme if v does not 2067 2123 equal 0 2068 2124 RETURN: primary invariants (type <matrix>) of the invariant ring … … 2163 2219 if (cd<>dif) 2164 2220 { 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 B2166 else 2221 } 2222 else // i.e. we can take all of B 2167 2223 { for(j=i+1;j<=i+dif;j++) 2168 2224 { CI=CI+ideal(var(j)^d); … … 2207 2263 ringname gives the name of a ring of characteristic 0 that has been 2208 2264 created by molien or reynolds_molien 2209 DISPLAY: information about the various stages of the program if v does not2265 DISPLAY: information about the various stages of the programme if v does not 2210 2266 equal 0 2211 2267 RETURN: primary invariants (type <matrix>) of the invariant ring … … 2249 2305 } 2250 2306 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."; 2253 2309 return(); 2254 2310 } … … 2360 2416 <int> 2361 2417 ASSUME: 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 not2418 DISPLAY: information about the various stages of the programme if v does not 2363 2419 equal 0 2364 2420 RETURN: primary invariants (type <matrix>) of the invariant ring and an … … 2503 2559 <int> 2504 2560 ASSUME: 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 not2561 DISPLAY: information about the various stages of the programme if v does not 2506 2562 equal 0 2507 2563 RETURN: primary invariants (type <matrix>) of the invariant ring and an … … 2644 2700 G1,G2,...: <matrices> generating a finite matrix group, v: an optional 2645 2701 <int> 2646 DISPLAY: information about the various stages of the program if v does not2702 DISPLAY: information about the various stages of the programme if v does not 2647 2703 equal 0 2648 2704 RETURN: primary invariants (type <matrix>) of the invariant ring … … 2658 2714 //--------------------- checking input and setting verbose mode -------------- 2659 2715 if (char(basering)==0) 2660 { "ERROR: primary_charp_without should onlybe used with rings of";2716 { "ERROR: primary_charp_without should not be used with rings of"; 2661 2717 " characteristic 0."; 2662 2718 return(); … … 2704 2760 // space of invariants of degree d, 2705 2761 // newdim: dimension the ideal generated 2706 // the primary invariants plus basis2762 // by the primary invariants plus basis 2707 2763 // elements, dif=n-i-newdim, i.e. the 2708 2764 // number of new primary invairants that … … 2784 2840 G1,G2,...: <matrices> generating a finite matrix group, flags: an 2785 2841 optional <intvec> with three entries, if the first one equals 0 (also 2786 the default), the program attempts to compute the Molien series and2787 Reynolds operator, if it equals 1, the program is told that the2842 the default), the programme attempts to compute the Molien series and 2843 Reynolds operator, if it equals 1, the programme is told that the 2788 2844 Molien series should not be computed, if it equals -1 characteristic 0 2789 2845 is simulated, i.e. the Molien series is computed as if the base field 2790 2846 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, it2847 characteristic, e.g. 32003) and if the first one is anything else, it 2792 2848 means that the characteristic of the base field divides the group 2793 2849 order, the second component should give the size of intervals between … … 2797 2853 common factors should always be canceled when the expansion is simple 2798 2854 (the root of the extension field occurs not among the coefficients) 2799 DISPLAY: information about the various stages of the program if the third2855 DISPLAY: information about the various stages of the programme if the third 2800 2856 flag does not equal 0 2801 2857 RETURN: primary invariants (type <matrix>) of the invariant ring and if … … 2892 2948 else 2893 2949 { 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"; 2895 2951 " invariant rings over extension fields of prime characteristic, we have to"; 2896 2952 " continue without it."; … … 3199 3255 ASSUME: REY is the first return value of group_reynolds or reynolds_molien and 3200 3256 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 not3257 DISPLAY: information about the various stages of the programme if v does not 3202 3258 equal 0 3203 3259 RETURN: primary invariants (type <matrix>) of the invariant ring … … 3346 3402 ringname gives the name of a ring of characteristic 0 that has been 3347 3403 created by molien or reynolds_molien 3348 DISPLAY: information about the various stages of the program if v does not3404 DISPLAY: information about the various stages of the programme if v does not 3349 3405 equal 0 3350 3406 RETURN: primary invariants (type <matrix>) of the invariant ring … … 3499 3555 bases elements, v: an optional <int> 3500 3556 ASSUME: 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 not3557 DISPLAY: information about the various stages of the programme if v does not 3502 3558 equal 0 3503 3559 RETURN: primary invariants (type <matrix>) of the invariant ring and an … … 3646 3702 bases elements, v: an optional <int> 3647 3703 ASSUME: 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 not3704 DISPLAY: information about the various stages of the programme if v does not 3649 3705 equal 0 3650 3706 RETURN: primary invariants (type <matrix>) of the invariant ring and an … … 3792 3848 where -|r| to |r| is the range of coefficients of the random 3793 3849 combinations of bases elements, v: an optional <int> 3794 DISPLAY: information about the various stages of the program if v does not3850 DISPLAY: information about the various stages of the programme if v does not 3795 3851 equal 0 3796 3852 RETURN: primary invariants (type <matrix>) of the invariant ring … … 3943 3999 where -|r| to |r| is the range of coefficients of the random 3944 4000 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 3946 4002 attempts to compute the Molien series and Reynolds operator, if it 3947 equals 1, the program is told that the Molien series should not be4003 equals 1, the programme is told that the Molien series should not be 3948 4004 computed, if it equals -1 characteristic 0 is simulated, i.e. the 3949 4005 Molien series is computed as if the base field were characteristic 0 3950 4006 (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 the4007 32003) and if the first one is anything else, it means that the 3952 4008 characteristic of the base field divides the group order, the second 3953 4009 component should give the size of intervals between canceling common … … 3957 4013 always be canceled when the expansion is simple (the root of the 3958 4014 extension field does not occur among the coefficients) 3959 DISPLAY: information about the various stages of the program if the third4015 DISPLAY: information about the various stages of the programme if the third 3960 4016 flag does not equal 0 3961 4017 RETURN: primary invariants (type <matrix>) of the invariant ring and if … … 4060 4116 else 4061 4117 { 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"; 4063 4119 " invariant rings over extension fields of prime characteristic, we have to"; 4064 4120 " continue without it."; … … 4424 4480 proc secondary_char0 (matrix P, matrix REY, matrix M, list #) 4425 4481 " 4426 USAGE: secondary_char0(P,REY,M[,v][,\" AH\"]);4482 USAGE: secondary_char0(P,REY,M[,v][,\"old\"]); 4427 4483 @* P: a 1xn <matrix> with homogeneous primary invariants, where 4428 4484 n is the number of variables of the basering; … … 4432 4488 series; 4433 4489 @* v: an optional <int>; 4434 @* \" AH\": if this string occurs as (optional) parameter, then an4490 @* \"old\": if this string occurs as (optional) parameter, then an 4435 4491 old version of secondary_char0 is used (for downward 4436 4492 compatibility) 4437 ASSUME: REY is the 1st return value of group_reynolds(), reynolds_molien() or 4493 ASSUME: The characteristic of basering is zero; 4494 REY is the 1st return value of group_reynolds(), reynolds_molien() or 4438 4495 the second one of primary_invariants(); 4439 4496 @* M is the return value of molien() … … 4450 4507 independent modulo the primary invariants (see paper \"Some 4451 4508 Algorithms in Invariant Theory of Finite Groups\" by Kemper and 4452 Steel (1997)) . The size of this set can be read off from the4453 Molien series.4509 Steel (1997)) using Groebner basis techniques. The size of this set 4510 can be read off from the Molien series. 4454 4511 NOTE: Secondary invariants are not uniquely determined by the given data. 4455 Specifically, the output of secondary_char0(P,REY,M, "AH") will4512 Specifically, the output of secondary_char0(P,REY,M,\"old\") will 4456 4513 differ from the output of secondary_char0(P,REY,M). However, the 4457 4514 ideal generated by the irreducible homogeneous 4458 4515 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). 4462 4520 SEE ALSO: irred_secondary_char0; 4463 4521 EXAMPLE: example secondary_char0; shows an example 4464 4522 " 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; 4466 4537 4467 4538 //----------------- checking input and setting verbose mode ------------------ 4468 4539 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(); 4471 4543 } 4472 4544 int i; … … 4484 4556 if (size(#)>0) 4485 4557 { if (typeof(#[size(#)])=="string") 4486 { if (#[size(#)]==" AH")4558 { if (#[size(#)]=="old") 4487 4559 { if (typeof(#[1])=="int") 4488 4560 { matrix S,IS = old_secondary_char0(P,REY,M,#[1]); … … 4495 4567 } 4496 4568 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\"."; 4498 4570 return(matrix(ideal()),matrix(ideal())); 4499 4571 } … … 4561 4633 option(redSB); 4562 4634 ideal sP = groebner(ideal(P)); 4635 // This is the only explicit Groebner basis computation! 4563 4636 ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 4564 4637 int SizeSave; … … 4576 4649 int ii; 4577 4650 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. 4582 4652 4583 4653 for (i=1;i<m;i++) … … 4587 4657 attrib(SSort[i][k],"size",0); 4588 4658 } 4589 4659 } 4590 4660 //--------------------- generating secondary invariants ---------------------- 4591 4661 for (i=2;i<=m;i++) // going through dimmat - … … 4642 4712 } 4643 4713 } 4644 ProdCand = Mul1*Mul2; 4714 // if (i<10) 4715 ProdCand = simplify(Mul1*Mul2,4); 4716 // else { ProdCand = Mul1*Mul2;} 4645 4717 ReducedCandidates = reduce(ProdCand,sP); 4646 4718 // sP union SaveRed union Reductor is a homogeneous Groebner basis … … 4654 4726 // invariants and previously computed secondary invariants. 4655 4727 // Otherwise ProdCand[ii] can be taken as secondary invariant. 4656 if (size(Indicator)<>0)4728 if (size(Indicator)<>0) 4657 4729 { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products 4658 { helpP = reduce(Indicator[ii],Reductor);4730 { helpP = Indicator[ii]; 4659 4731 if (helpP <> 0) 4660 4732 { counter++; … … 4667 4739 } 4668 4740 if (int(dimmat[i,1])<>counter) 4669 { helpint++; 4670 Reductor[helpint] = helpP; 4741 { Reductor = ideal(helpP); 4671 4742 // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a 4672 4743 // homogeneous polynomial of degree i-1 then G union NF(p,G) is … … 4676 4747 // it, save it in SaveRed, and work with a smaller Reductor. This turns 4677 4748 // 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); 4689 4753 } 4690 4754 else … … 4694 4758 } 4695 4759 } 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); 4704 4761 } 4705 4762 } … … 4712 4769 { "There are irreducible secondary invariants in degree ", i-1," !!"; 4713 4770 } 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); 4715 4837 // B contains 4716 4838 // images of kbase(sP,i-1) under the 4717 4839 // 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);} 4727 4853 } 4728 4854 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); 4750 4884 } 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; 4771 4888 } 4772 4889 } 4773 } 4774 } 4890 } // i<=IrrSwitch 4891 } // Computation of irreducible secondaries 4775 4892 if (v) 4776 4893 { ""; 4777 4894 } 4778 } 4779 } 4895 } // if (int(dimmat[i,1])<>0) 4896 } // for i 4780 4897 if (v) 4781 4898 { " We're done!"; … … 4784 4901 degBound = dgb; 4785 4902 4786 // Prepare return:4903 // Prepare return: 4787 4904 int TotalNumber; 4788 4905 for (k=1;k<=m;k++) … … 4806 4923 } 4807 4924 4808 4809 4925 example 4810 4926 { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; … … 4816 4932 print(IS); 4817 4933 } 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 4828 4936 /////////////////////////////////////////////////////////////////////////////// 4829 4830 4937 4831 4938 proc irred_secondary_char0 (matrix P, matrix REY, matrix M, list #) … … 4841 4948 RETURN: Irreducible homogeneous secondary invariants of the invariant ring 4842 4949 (type <matrix>) 4843 ASSUME: REY is the 1st return value of group_reynolds(), reynolds_molien() or 4950 ASSUME: 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 4844 4953 the second one of primary_invariants(); 4845 4954 M is the return value of molien() or the second one of … … 4852 4961 independent modulo the primary invariants (see paper \"Some 4853 4962 Algorithms in Invariant Theory of Finite Groups\" by Kemper and 4854 Steel (1997)) . The size of this set can be read off from the4855 Molien series. Here, only irreducible secondary4963 Steel (1997)) using Groebner basis techniques. The size of this set 4964 can be read off from the Molien series. Here, only irreducible secondary 4856 4965 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). 4860 4970 SEE ALSO: secondary_char0 4861 4971 KEYWORDS: irreducible secondary invariant 4862 4972 EXAMPLE: example irred_secondary_char0; shows an example 4863 4973 " 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; 4866 4987 //----------------- checking input and setting verbose mode ------------------ 4867 4988 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(); 4870 4992 } 4871 4993 int i; … … 4958 5080 int ii; 4959 5081 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. 4964 5083 4965 5084 for (i=1;i<m;i++) … … 5027 5146 } 5028 5147 } 5029 ProdCand = Mul1*Mul2; 5148 // if (i<10) 5149 ProdCand = simplify(Mul1*Mul2,4); 5150 // else { ProdCand = Mul1*Mul2;} 5030 5151 ReducedCandidates = reduce(ProdCand,sP); 5031 5152 // sP union SaveRed union Reductor is a homogeneous Groebner basis … … 5042 5163 if (size(Indicator)<>0) 5043 5164 { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products 5044 { helpP = reduce(Indicator[ii],Reductor);5165 { helpP = Indicator[ii]; 5045 5166 if (helpP <> 0) 5046 5167 { counter++; … … 5054 5175 } 5055 5176 if (int(dimmat[i,1])<>counter) 5056 { helpint++; 5057 Reductor[helpint] = helpP; 5177 { Reductor = ideal(helpP); 5058 5178 // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a 5059 5179 // homogeneous polynomial of degree i-1 then G union NF(p,G) is … … 5063 5183 // it, save it in SaveRed, and work with a smaller Reductor. This turns 5064 5184 // 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); 5076 5190 } 5077 5191 else … … 5081 5195 } 5082 5196 } 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;5089 5197 attrib(SaveRed, "isSB",1); 5090 5198 attrib(Reductor, "isSB",1); … … 5099 5207 { "There are irreducible secondary invariants in degree ", i-1," !!"; 5100 5208 } 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); 5102 5277 // B is a set of 5103 5278 // images of kbase(sP,i-1) under the … … 5105 5280 // independent and that do not reduce to 5106 5281 // 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);} 5114 5294 } 5115 5295 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]; 5152 5313 } 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; 5156 5325 attrib(SaveRed, "isSB",1); 5157 5326 attrib(Reductor, "isSB",1); 5158 5327 } 5328 B[j]=0; 5329 ReducedCandidates[j]=0; 5330 Indicator[j]=0; 5159 5331 } 5160 5332 } 5161 } 5162 } 5333 } // i<=IrrSwitch 5334 } // Computation of irreducible secondaries 5163 5335 if (v) 5164 5336 { ""; … … 5189 5361 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; 5190 5362 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; 5191 list L = primary_invariants(A1,A2); // sorry, this takes a while...5363 list L = primary_invariants(A1,A2); 5192 5364 matrix IS = irred_secondary_char0(L[1],L[2],L[3],0); 5193 5365 IS; … … 5197 5369 /////////////////////////////////////////////////////////////////////////////// 5198 5370 5199 5200 proc secondary_charp (matrix P, matrix REY, string ring_name, list #) 5371 proc old_secondary_charp (matrix P, matrix REY, string ring_name, list #) 5201 5372 "USAGE: secondary_charp(P,REY,ringname[,v]); 5202 5373 P: a 1xn <matrix> with primary invariants, REY: a gxn <matrix> … … 5421 5592 /////////////////////////////////////////////////////////////////////////////// 5422 5593 5594 5595 proc 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) 5608 ASSUME: 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() 5613 RETURN: secondary invariants of the invariant ring (type <matrix>) and 5614 irreducible secondary invariants (type <matrix>) 5615 DISPLAY: information if v does not equal 0 5616 THEORY: 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. 5624 EXAMPLE: 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 } 6041 example 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 5423 6052 proc secondary_no_molien (matrix P, matrix REY, list #) 5424 6053 "USAGE: secondary_no_molien(P,REY[,deg_vec,v]); … … 5437 6066 monomials) of the basering modulo primary invariants, mapping those to 5438 6067 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. 5440 6072 EXAMPLE: example secondary_no_molien; shows an example 5441 6073 " … … 5879 6511 M(1)[i,1..k]=B[1..k]; // we will look for the syzygies of M(1) 5880 6512 } 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); 5885 6517 module M(2)=nres(M(1),2)[2]; 5886 6518 int m=ncols(M(2)); // number of generators of the module … … 5933 6565 " group order."; 5934 6566 } 5935 return( S);6567 return(matrix(S)); 5936 6568 } 5937 6569 example … … 5954 6586 Molien series is computed as if the base field were characteristic 0 5955 6587 (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 the6588 32003) and if the first one is anything else, it means that the 5957 6589 characteristic of the base field divides the group order (i.e. it will 5958 6590 not even be attempted to compute the Reynolds operator or Molien … … 6051 6683 else 6052 6684 { if (v) 6053 { " Since it is impossible for this program to calculate the Molien6685 { " Since it is impossible for this programme to calculate the Molien 6054 6686 series for"; 6055 6687 " invariant rings over extension fields of prime characteristic, we … … 6171 6803 i.e. the Molien series is computed as if the base field were 6172 6804 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, 6174 6806 then the characteristic of the base field divides the group order 6175 6807 (i.e. we will not even attempt to compute the Reynolds operator or … … 6286 6918 else 6287 6919 { if (v) 6288 { " Since it is impossible for this program to calculate the Molien6920 { " Since it is impossible for this programme to calculate the Molien 6289 6921 series for"; 6290 6922 " invariant rings over extension fields of prime characteristic, we … … 6403 7035 THEORY: The ideal of algebraic relations of the invariant ring generators is 6404 7036 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 6406 7038 EXAMPLE: example orbit_variety; shows an example 6407 7039 " … … 6620 7252 @* s: a <string> giving a name for a new ring 6621 7253 RETURN: 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. 6624 7257 THEORY: A Groebner basis of the ideal of algebraic relations of the invariant 6625 7258 ring generators is calculated, then one of the basis elements plus the … … 6706 7339 @* F: a 1xm <matrix> defining an invariant ring of some matrix group 6707 7340 RETURN: The <ideal> defining the image under that group of the variety defined 6708 by I .7341 by I 6709 7342 THEORY: rel_orbit_variety(I,F) is called and the newly introduced 6710 7343 @* variables in the output are replaced by the generators of the 6711 7344 @* 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 6713 7346 EXAMPLE: example image_of_variety; shows an example 6714 7347 " … … 6743 7376 6744 7377 6745 6746 7378 proc 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>; 7385 ASSUME: The characteristic of basering is not zero 7386 RETURN: secondary invariants of the invariant ring (type <matrix>) and 7387 irreducible secondary invariants (type <matrix>) of degree at most dmax. 7388 DISPLAY: information if v does not equal 0 7389 THEORY: 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. 7398 SEE ALSO: secondary_charp, secondary_char0, secondary_not_cohen_macaulay 7399 EXAMPLE: 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 } 7664 example 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.