############################################################################# #### ## #W Manipulations.gi RADIROOT package Andreas Distler ## ## Installation file for the functions that do various manipulations ## to special elements of a splitting field and to the permutations ## in its Galois group ## #Y 2006 ##
############################################################################# ## #M GaloisGroupOnRoots( <f> ) #M GaloisType( <f> ) ## ## Computes the Galois group of the rational polynomial <f> with respect to ## its roots, created as matrices ##
InstallMethod( GaloisGroupOnRoots, "for rational polynomial",
[ IsUnivariateRationalFunction and IsPolynomial ], function( f )
local erw, galgrp;
if not ForAll( CoefficientsOfUnivariatePolynomial( f ), IsRat ) then
TryNextMethod( ); fi;
if not IsSeparablePolynomial( f ) then
Error("f must be separable"); fi;
# neccessary to use RR_Produkt in the computation of the Galois group
erw.unity := 1;
galgrp := RR_ConstructGaloisGroup( erw );
return galgrp; end );
InstallMethod(GaloisType,"for polynomials",true,[IsUnivariateRationalFunction
and IsPolynomial and HasGaloisGroupOnRoots],0, function( f )
if not(IsIrreducibleRingElement(f)) then
Error("f must be irreducible"); fi;
return TransitiveIdentification( GaloisGroupOnRoots( f )); end );
############################################################################# ## #F RR_DegreeConclusion( <B>, <roots> ) ##
InstallGlobalFunction( RR_DegreeConclusion, function( B, roots )
local i, degs;
degs := [ ];
roots := Filtered( roots, root -> root in B ); for i in [ 1..Length( roots )-1 ] do
degs[i] := (Position( B, roots[i+1] ) - 1) / Product(degs);
od;
degs[ Length( roots ) ] := Length( B ) / Product(degs);
return degs; end );
############################################################################# ## #F RR_PrimElImg( <erw>, <perm> ) ## ## Calculates the result for apllying the permutation <perm> to the ## primitive element of the field in the record <erw> ##
InstallGlobalFunction( RR_PrimElImg, function( erw, perm )
# basefield = rationals if Length(erw.degs) = Length(erw.coeffs) then
return Sum( [ 1..Length(erw.coeffs) ],
i -> erw.coeffs[i] * erw.roots[i^perm] );; # basefield = cyclotomic field else
return Sum( [ 2..Length(erw.coeffs) ],
i -> erw.coeffs[i] * erw.roots[(i-1)^perm] ) +
erw.coeffs[1] * erw.unity;; fi; end );
############################################################################# ## #F RR_Produkt( <erw>, <elm>, <perm> ) ## ## Calculates the result for apllying the permutation <perm> to the ## field element <elm> ##
InstallGlobalFunction( RR_Produkt, function( erw, elm, perm )
local i, k, mat, coeff, degprod, prod;
mat := 0*One(erw.K);
coeff := Coefficients( Basis(erw.K), elm );
# computation with respect to the known order of the basis for i in [ 1..Length(coeff) ] do if coeff[i] <> 0then # Einheitswurzel bleibt erhalten # Size(elm)/Product(erw.degs) ist 1, wenn keine # Einheitswurzel adjungiert wurde
degprod := Length( coeff ) / Product( erw.degs );
prod := erw.unity^RemInt( i-1, degprod ); # One( erw.K ); # the roots that built the basis are permuted for k in [ 1..Length(erw.degs) ] do
prod := prod * erw.roots[ k^perm ]^QuoInt(
RemInt( i-1, degprod * erw.degs[k] ), degprod );
degprod := degprod * erw.degs[k];
od;
mat := mat + coeff[i] * prod; fi;
od;
return mat; end );
############################################################################# ## #F RR_CompositionSeries( <G>, <N> ) ## ## Computes a composition series of <G> through its normal subgroup <N> ##
InstallGlobalFunction( RR_CompositionSeries, function( G, N )
local hom, genN, grps, gens;
if G = N then
return CompositionSeries( G ); elif Order( G ) / Order( N ) in Primes then
return Concatenation([ G ], CompositionSeries( N )); else
Info( InfoRadiroot, 3, " computation of compositon series" );
hom := NaturalHomomorphismByNormalSubgroupNC( G, N ); # Generators of Composition Series G/N as free group
gens := List( CompositionSeries(Range(hom)), GeneratorsOfGroup );
Unbind( gens[ Length( gens ) ] ); # Preimages of the Generators in G
gens := List(gens, ll->List(ll, x->PreImagesRepresentative(hom, x)));
genN := GeneratorsOfGroup( N );
grps := List( gens, x -> Group( Concatenation( genN, x ))); fi;
return Concatenation( grps, CompositionSeries( N ) ); end );
############################################################################# ## #F RR_Potfree( <rats>, <exp> ) ## ## Computes <num>/<den> where <num> and <den> are the largest integers such ## that <num>^<exp> resp. <den>)^<exp> occur as factor the nominator resp. ## denominator of every rational number in the list <rats> ##
InstallGlobalFunction( RR_Potfree, function( rats, exp )
local num, den;
num := Gcd(List(rats, NumeratorRat));
den := Gcd(List(Filtered(rats, x-> x<>0), DenominatorRat));
num := Product( Collected( Factors( num )),
pe -> pe[1]^( exp * (QuoInt( pe[2], exp ) ) ) );
den := Product( Collected( Factors( den )),
pe -> pe[1]^( exp * (QuoInt( pe[2], exp ) ) ) );
return Root( num, exp ) / Root( den, exp ); end );
############################################################################# ## #F RR_Resolvent( <G>, <N>, <elm>, <erw> ) ## ## Computes the Lagrange resolvent for the element <elm> and a ## generator of the factor group of <G> and <N> ##
InstallGlobalFunction( RR_Resolvent, function( G, N, elm, erw )
local unity, gen, p;
p := Order( G ) / Order( N ); # determine gen with G/N = <genN>
gen := First( Elements( G ), x -> not x in N ); # p-th root of unity if IsInt( Order( erw.unity ) / p ) then
unity := erw.unity^( Order( erw.unity ) / p ); else# if RR_SplittField has been used this distinction is necessary
unity := E( p ) * One( erw.K ); fi;
return Sum([ 0..p-1 ], k -> unity^k * RR_Produkt( erw, elm, gen^k ) )/p; end );
############################################################################# ## #F RR_CyclicElements( <erw>, <compser> ) ## ## It is <compser> a composition series for the Galois group of the ## field in the record <erw>. The function returns a list of elements ## that generate the corresponding tower of fields. Each element is ## cyclic in the direct subfield. ##
InstallGlobalFunction( RR_CyclicElements, function( erw, compser )
local i, k, elements, elm, primEllist, L, n, potelm, primEl;
if erw.H = Rationals then return [ ]; fi;
elements := [ ]; if Length(erw.degs) = Length(erw.coeffs) then
L := FieldByMatricesNC( [ One( erw.K ) ] ); else
L := FieldByMatricesNC( [ erw.unity ] ); fi; for i in [ 2..Length(compser)-1 ] do
primEllist := List( AsList( compser[i] ),
perm -> RR_PrimElImg( erw, perm ));; for k in Flat(List([ 1..Length(primEllist) ],
i -> [i, Length(primEllist) + 1 - i ])) do
elm := Sum( Combinations( [ 1..Length(primEllist) ], k),
subset -> Product( subset, x -> primEllist[x]));; if not (elm in L) then
Info( InfoRadiroot, 3, " found element of field with degree ",
DegreeOverPrimeField( erw.K ) / Order( compser[i] ) );
break; fi;
od;
n := Order( compser[i-1] ) / Order( compser[i] ); for k in [ 1..n ] do
elements[i-1]:=RR_Resolvent(compser[i-1],compser[i],elm^k,erw); if elements[i-1] <> 0 * One( erw.K ) then break; fi;
od;
potelm := elements[i-1]^n;; if IsDiagonalMat( potelm ) and IsRat( potelm[1][1] ) then
elements[i-1] := elements[i-1] / RR_Potfree( [ potelm[1][1] ], n ); fi;
elements[i-1] := [elements[i-1], n]; if i <> Length(compser)-1then
L := FieldByMatricesNC( Concatenation( GeneratorsOfField(L),
[ elements[i-1][1] ])); fi;
od;
i := Length( compser );
n := Order( compser[i-1] ) / Order( compser[i] ); for k in [ 1..n ] do
elements[i-1]:=RR_Resolvent(compser[i-1],compser[i],
PrimitiveElement(erw.K)^k,erw); if elements[i-1] <> 0 * One( erw.K ) then break; fi;
od; if i = 2then
potelm := elements[i-1]^n; if IsDiagonalMat( potelm ) and IsRat( potelm[1][1] ) then
elements[i-1] := elements[i-1] / RR_Potfree( [ potelm[1][1] ], n ); fi; fi;
elements[i-1] := [elements[i-1], n];
return elements; end );
############################################################################# ## #F RR_IsInGalGrp( <erw>, <perm> ) ## ## Tests if the permutation <perm> is in the Galois group that ## belongs to the roots in the record <erw> ##
InstallGlobalFunction( RR_IsInGalGrp, function( erw, perm )
local i;
for i in [ 1..Length(erw.roots) ] do if RR_Produkt( erw, erw.roots[i], perm ) <> erw.roots[ i^perm ] then
return false; fi;
od;
return true; end );
############################################################################# ## #F RR_ConstructGaloisGroup( <erw> ) ## ## Constructs the Galois group for the roots in the record <erw> with ## respect to their order ##
InstallGlobalFunction( RR_ConstructGaloisGroup, function( erw )
local Sn, rt, ggelm, p, B, imgs, oldgroup;
Info( InfoRadiroot, 2, " Construction of the Galoisgroup" );
ggelm := [ () ];
oldgroup := [ ]; if erw.H = Rationals then return Group( ggelm ); fi;
Sn := SymmetricGroup( Length( erw.roots ) );
rt := RightTransversal( Sn, Stabilizer( Sn, [ 1..Length(erw.degs) ],
OnTuples ) );
imgs := List( rt, perm -> RR_PrimElImg( erw, perm ));; if IsDuplicateFreeList( imgs ) then
Info( InfoRadiroot, 3, " using fast Galoisgroup computation" );
repeat # sort out already known permutations
rt := Difference(rt,
List(Difference(AsList(Group(ggelm)),oldgroup),
p -> First(rt,
prm->ForAll([1..Length(erw.degs)],
i->i^prm = i^p))));;
oldgroup := AsList(Group(ggelm));
p := Permutation( Remove(rt,1),
erw.roots, function(x, g)
return RR_Produkt(erw, x, g); end ); if p <> fail and Value( DefiningPolynomial(erw.K),
RR_PrimElImg( erw, p )) = 0 * One(erw.K) then
Add( ggelm, p ); fi;
until Order(Group(ggelm)) = Product(erw.degs); else
Info( InfoRadiroot, 3, " using slow Galoisgroup computation" );
imgs := DuplicateFreeList(imgs);
repeat
imgs := Difference(imgs,
List(Difference(AsList(Group(ggelm)),oldgroup),
p->RR_PrimElImg( erw, p )));;
oldgroup := AsList(Group(ggelm)); if Value(DefiningPolynomial(erw.K), imgs[1]) = 0 * One(erw.K) then
B := Basis(erw.K,ListElmPower([0..Size(imgs[1])-1],imgs[1]));;
p := Permutation( (), erw.roots, function( x, g )
return LinearCombination( B,
Coefficients( EquationOrderBasis( erw.K, PrimitiveElement(erw.K) ), x )); end );
Add( ggelm, p ); else
imgs := imgs{[ 2..Length(imgs) ]}; fi;
until Order(Group(ggelm)) = DegreeOverPrimeField(erw.K); fi;
return Group( Difference( ggelm, [ () ] )); end );
############################################################################# ## #F RR_FindGaloisGroup( <erw>, <poly>, <galgrp> ) ## ## This function searchs the Galois group of the rational polynomial ## <poly> that is compatible to the numbering of the roots of <poly> ## in <erw>; it is recommended to use RR_ConstructGaloisGroup if there ## exist many groups conjugated to <galgrp> ##
InstallGlobalFunction( RR_FindGaloisGroup, function( erw, poly, galgrp )
local G, H, perm, k, gens, newgens, Sn;
k := 1;
gens := [ ];
Sn := SymmetricGroup( Degree(poly) ); for G in ConjugacyClassSubgroups( Sn, galgrp ) do
newgens := Filtered( GeneratorsOfGroup( G ),
gen -> RR_IsInGalGrp( erw, gen ) );
gens := DuplicateFreeList( Concatenation( gens, newgens ) );
H := Subgroup( Sn, gens ); if Order(galgrp) = Order( H ) then
return H; fi;
od; end );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.