diff --git a/doc/ref/rings.xml b/doc/ref/rings.xml index eeb571699a..991cb28e34 100644 --- a/doc/ref/rings.xml +++ b/doc/ref/rings.xml @@ -189,6 +189,8 @@ see . <#Include Label="Subrings"> <#Include Label="Ideals"> <#Include Label="DirectSum"> +<#Include Label="Embedding:rings"> +<#Include Label="Projection:rings"> <#Include Label="RingByStructureConstants"> diff --git a/lib/ringsc.gd b/lib/ringsc.gd index 01d73541c9..0bd93f4ddb 100644 --- a/lib/ringsc.gd +++ b/lib/ringsc.gd @@ -193,8 +193,13 @@ DeclareGlobalFunction("SmallRing"); ## (This somewhat strange syntax allows the method selection to choose ## a reasonable method for special cases.) ## DirectSum(SmallRing(5,1),SmallRing(5,1)); -## +## gap> R7 := SmallRing( 7, 2 );; SetName( R7, "R7" ); +## gap> R8 := SmallRing( 8, 52 );; SetName( R8, "R8" ); +## gap> R78 := DirectSum( R7, R8 ); +## +## gap> R9 := SmallRing( 9, 11 );; SetName( R9, "R9" ); +## gap> R789 := DirectSum( [ R7, R8, R9 ] ); +## ## ]]> ## ## @@ -202,5 +207,54 @@ DeclareGlobalFunction("SmallRing"); ## DeclareGlobalFunction( "DirectSum" ); DeclareOperation( "DirectSumOp", [ IsList, IsRing ] ); -DeclareAttribute( "DirectSumInfo", IsGroup, "mutable" ); +DeclareAttribute( "DirectSumInfo", IsRing, "mutable" ); +############################################################################# +## +#O Embedding( , ) +## +## <#GAPDoc Label="Embedding:rings"> +## +## +## +## +## If ring R is the direct sum of rings [R_1,\ldots,R_k] +## then Embedding(R,i) for 1 \leq i \leq k returns a ring +## homomorphism mapping R_i into R. +##

+## emb1 := Embedding( R78, 1 ); +## [ a ] -> [ Aa ] +## gap> a := GeneratorsOfRing( R7 )[1];; +## gap> ImageElm( emb1, 3*a ); +## 3*Aa +## ]]> +## +## +## <#/GAPDoc> + +############################################################################# +## +#O Projection( , ) +## +## <#GAPDoc Label="Projection:rings"> +## +## +## +## +## If ring R is the direct sum of rings [R_1,\ldots,R_k] +## then Projection(R,i) for 1 \leq i \leq k returns a ring +## homomorphism mapping R onto R_i. +##

+## pro2 := Projection( R78, 2 ); +## [ Aa, Ba, Bb, Bc ] -> [ 0*a, a, b, c ] +## gap> b := GeneratorsOfRing( R78 )[2];; +## gap> ImageElm( pro2, 5*b ); +## a +## ]]> +## +## +## <#/GAPDoc> diff --git a/lib/ringsc.gi b/lib/ringsc.gi index 6f87c6ac3a..42c82b2f28 100644 --- a/lib/ringsc.gi +++ b/lib/ringsc.gi @@ -1101,7 +1101,7 @@ local ids, tup, first, i, G, gens, g, new, D; ids := List( list, Zero ); tup := []; - first := [1]; + first := [0]; for i in [1..Length( list )] do G := list[i]; gens := GeneratorsOfRing( G ); @@ -1114,7 +1114,7 @@ local ids, tup, first, i, G, gens, g, new, D; new := DirectProductElement( new ); Add( tup, new ); od; - Add( first, Length( tup )+1 ); + Add( first, Length( tup ) ); od; D := RingByGenerators( tup ); @@ -1208,6 +1208,71 @@ local ones,s, moduli, orders, offsets, o, p, newmod, t, nams, gens, e, f, D, i, return D; end ); +############################################################################# +## +#M Embedding( , ) +## +InstallMethod( Embedding, "ring direct sum and integer", + [ IsSubringSCRing and HasDirectSumInfo, IsPosInt ], + function( D, i ) + local info, first, R, gens, imgs, map; + + # check + info := DirectSumInfo( D ); + if IsBound( info.embeddings[i] ) then + return info.embeddings[i]; + fi; + first := info.first; + if not ( i < Length(first) ) then + Error( "value of second parameter is too large" ); + fi; + # compute embedding + R := info.rings[i]; + gens := StandardGeneratorsSubringSCRing( R )[3]; + imgs := GeneratorsOfRing( D ){[first[i]+1 .. first[i+1]]}; + map := RingHomomorphismByImages( R, D, gens, imgs ); + SetIsInjective( map, true ); + + # store information + info.embeddings[i] := map; + return map; +end ); + +############################################################################# +## +#M Projection( , ) +## +InstallMethod( Projection, "ring direct sum and integer", + [ IsSubringSCRing and HasDirectSumInfo, IsPosInt ], + function( D, i ) + local infoD, first, zR, len, R, genR, genD, imgs, j, k, map; + + infoD := DirectSumInfo( D ); + if IsBound( infoD.projections[i] ) then + return infoD.projections[i]; + fi; + first := infoD.first; + len := Length( first ); + if not ( i < len ) then + Error( "value of second parameter is too large" ); + fi; + # compute projection + R := infoD.rings[i]; + zR := Zero( R ); + genR := StandardGeneratorsSubringSCRing( R )[3]; + genD := GeneratorsOfRing( D ); + imgs := ListWithIdenticalEntries( first[len], zR ); + j := first[i]; + for k in [first[i]+1..first[i+1]] do + imgs[k] := genR[k-j]; + od; + map := RingHomomorphismByImages( D, R, genD, imgs ); + + # store information + infoD.projections[i] := map; + return map; +end ); + ############################################################################# ## #M \+( , ) . . . . . . . . . . . . . . . . sum of rings diff --git a/tst/testinstall/ring-dsum.tst b/tst/testinstall/ring-dsum.tst new file mode 100644 index 0000000000..98b71dc43f --- /dev/null +++ b/tst/testinstall/ring-dsum.tst @@ -0,0 +1,86 @@ +gap> START_TEST("ring-dsum.tst"); +gap> # direct sums of small rings +gap> R7 := SmallRing( 7, 2 );; SetName( R7, "R7" ); +gap> R8 := SmallRing( 8, 52 );; SetName( R8, "R8" ); +gap> R9 := SmallRing( 9, 11 );; SetName( R9, "R9" ); +gap> R78 := DirectSum( R7, R8 ); + +gap> info78 := DirectSumInfo( R78 ); +rec( embeddings := [ ], first := [ 0, 1, 4 ], projections := [ ], + rings := [ R7, R8 ] ) +gap> R789 := DirectSum( [ R7, R8, R9 ] ); + +gap> info789 := DirectSumInfo( R789 ); +rec( embeddings := [ ], first := [ 0, 1, 4, 6 ], projections := [ ], + rings := [ R7, R8, R9 ] ) +gap> # +gap> # embeddings and projections of small rings +gap> Embedding( R78, 2 ); +[ a, b, c ] -> [ Ba, Bb, Bc ] +gap> e3 := Embedding( R789, 3 ); +[ a, b ] -> [ Ca, Cb ] +gap> Projection( R78, 1 ); +[ Aa, Ba, Bb, Bc ] -> [ a, 0*a, 0*a, 0*a ] +gap> p3 := Projection( R789, 3 ); +[ Aa, Ba, Bb, Bc, Ca, Cb ] -> [ 0*a, 0*a, 0*a, 0*a, a, b ] +gap> genR9 := GeneratorsOfRing( R9 );; +gap> a := genR9[1];; b := genR9[2];; +gap> [ a*b^2, ImageElm( e3, a*b^2 ) ]; +[ -a, -Ca ] +gap> ForAll( genR9, g -> ( g ^ e3 ) ^ p3 = g ); +true +gap> genR789 := GeneratorsOfRing( R789 );; +gap> x := genR789[3];; y := genR789[6];; +gap> [ x^2, ImageElm( p3, x^2 ) ]; +[ Ba+Bc, 0*a ] +gap> [ y^2, ImageElm( p3, y^2 ) ]; +[ -Ca, -a ] +gap> # +gap> # other direct sums of rings +gap> R4 := ZmodnZ( 4 );; +gap> R5 := ZmodnZ( 5 );; +gap> R6 := ZmodnZ( 6 );; +gap> R45 := DirectSum( R4, R5 ); + +gap> info45 := DirectSumInfo( R45 ); +rec( embeddings := [ ], first := [ 0, 2, 3 ], projections := [ ], + rings := [ (Integers mod 4), GF(5) ] ) +gap> R456 := DirectSum( [ R4, R5, R6 ] ); + +gap> info456 := DirectSumInfo( R456 ); +rec( embeddings := [ ], first := [ 0, 2, 3, 5 ], projections := [ ], + rings := [ (Integers mod 4), GF(5), (Integers mod 6) ] ) +gap> # +gap> # embeddings and projections of these rings: methods for these +gap> # operations are only installed for rings of type IsSubringSCRing +gap> Embedding( R45, 1 ); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `Embedding' on 2 arguments +gap> Projection( R456, 2 ); +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `Projection' on 2 arguments +gap> # +gap> # combine these all together: +gap> D := DirectSum( [R4,R5,R6,R7,R8,R9] ); + +gap> DirectSumInfo( D ); +rec( embeddings := [ ], first := [ 0, 2, 3, 5, 6, 9, 11 ], + projections := [ ], + rings := [ (Integers mod 4), GF(5), (Integers mod 6), R7, R8, R9 ] ) +gap> # +gap> # subrings whose generators are not the standard generators +gap> R3 := SmallRing( 3, 2 );; +gap> T3 := Subring( R3, [ -GeneratorsOfRing( R3 )[1] ] );; +gap> D3 := DirectSum( T3, T3 );; +gap> e := Embedding( D3, 2 );; p := Projection( D3, 2 );; +gap> ForAll( T3, r -> ( r ^ e ) ^ p = r ); +true +gap> ForAll( T3, r -> IsZero( ( r ^ e ) ^ Projection( D3, 1 ) ) ); +true +gap> S4 := SmallRing( 4, 1 );; g := GeneratorsOfRing( S4 )[1];; +gap> T4 := Subring( S4, [ 2*g, g ] );; +gap> D4 := DirectSum( T4, R3 );; +gap> e := Embedding( D4, 1 );; p := Projection( D4, 1 );; +gap> ForAll( T4, r -> ( r ^ e ) ^ p = r ); +true +gap> STOP_TEST("ring-dsum.tst");