From 0ec2f7fdc49ed8a7854de13765e1747f5b0e7354 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Sun, 22 Apr 2018 17:47:02 -0600 Subject: [PATCH] ENHANCE: Reduce impact of immediate methods for groups 1) When creating groups, set filters such as `IsEmpty`, `IsFinite` that always hold, as well as do some very cheap tests for being not trivial to set filters that have trivial immediate methods associated, thereby avoiding a trigger of these methods 2) Comment out a few immediate methods that have doubtful value (the trivial group is perfect, a collection that does not have `IsFinite` has `Size` set to infinity etc.) 3) When creating groups of automorphisms (or similar objects), explicitly set `IsFinite` if we know so. 4) A side-effect of this is that group types cannot be cached anymore, as this type might end up changed in place, inheriting properties it should not. --- lib/coll.gi | 19 +++-- lib/grp.gi | 186 ++++++++++++++++++++++++++++------------------- lib/grpfp.gi | 10 ++- lib/grppc.gi | 189 +++++++++++++++++++++++++++--------------------- lib/grppcaut.gi | 8 ++ lib/grppcext.gi | 2 + lib/grppcfp.gi | 1 + lib/magma.gi | 64 +++++++++++----- 8 files changed, 293 insertions(+), 186 deletions(-) diff --git a/lib/coll.gi b/lib/coll.gi index 46fb6c8656..2054597eb6 100644 --- a/lib/coll.gi +++ b/lib/coll.gi @@ -169,14 +169,17 @@ InstallMethod( IsWholeFamily, ## #M Size( ) . . . . . . . . . . . . . . . . . . . . size of a collection ## -InstallImmediateMethod( Size, - IsCollection and HasIsFinite and IsAttributeStoringRep, 0, - function ( C ) - if IsFinite( C ) then - TryNextMethod(); - fi; - return infinity; - end ); +# This method get called for every group that knows it is finite but does +# not know its size -- e.g. permutation, pc +# the benefit OTOH is minimal beyond showing off a feature. +#InstallImmediateMethod( Size, +# IsCollection and HasIsFinite and IsAttributeStoringRep, 0, +# function ( C ) +# if IsFinite( C ) then +# TryNextMethod(); +# fi; +# return infinity; +# end ); InstallImmediateMethod( Size, IsCollection and HasAsList and IsAttributeStoringRep, 0, diff --git a/lib/grp.gi b/lib/grp.gi index 9c7781c23b..661b84ddc4 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -30,14 +30,15 @@ InstallImmediateMethod( IsFinitelyGeneratedGroup, ## #M IsCyclic( ) . . . . . . . . . . . . . . . . test if a group is cyclic ## -InstallImmediateMethod( IsCyclic, IsGroup and HasGeneratorsOfGroup, 0, - function( G ) - if Length( GeneratorsOfGroup( G ) ) = 1 then - return true; - else - TryNextMethod(); - fi; - end ); +# this is now set when creating the groups +#InstallImmediateMethod( IsCyclic, IsGroup and HasGeneratorsOfGroup, 0, +# function( G ) +# if Length( GeneratorsOfGroup( G ) ) = 1 then +# return true; +# else +# TryNextMethod(); +# fi; +# end ); InstallMethod( IsCyclic, "generic method for groups", @@ -433,10 +434,12 @@ InstallMethod( IsNilpotentGroup, ## #M IsPerfectGroup( ) . . . . . . . . . . . . test if a group is perfect ## -InstallImmediateMethod( IsPerfectGroup, - IsSolvableGroup and HasIsTrivial, - 0, - IsTrivial ); + +# This is now set when the group is created +#InstallImmediateMethod( IsPerfectGroup, +# IsSolvableGroup and HasIsTrivial, +# 0, +# IsTrivial ); InstallImmediateMethod( IsPerfectGroup, IsGroup and HasIsAbelian and IsSimpleGroup, @@ -4291,86 +4294,121 @@ end ); InstallMethod( GroupWithGenerators, "generic method for collection", [ IsCollection ], - function( gens ) - local G,fam,typ; - - fam:=FamilyObj(gens); - if IsFinite(gens) then - if not IsBound(fam!.defaultFinitelyGeneratedGroupType) then - fam!.defaultFinitelyGeneratedGroupType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup); - fi; - typ:=fam!.defaultFinitelyGeneratedGroupType; - else - if not IsBound(fam!.defaultGroupType) then - fam!.defaultGroupType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses); +function( gens ) +local G,fam,typ,id,triv; + + fam:=FamilyObj(gens); + + triv:=fail; # might not find out + + typ:=IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses; + if IsFinite(gens) then + typ:=typ and IsFinitelyGeneratedGroup; + if Length(gens)<=1 then + typ:=typ and HasIsCyclic and IsCyclic + and HasIsCommutative and IsCommutative; + fi; + + if Length(gens)>0 and CanEasilyCompareElements(gens) then + id:=One(gens[1]); + if ForAny(gens,x->x<>id) then + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=false; + else + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=true; + # basic consequence + typ:=typ and HasIsPerfectGroup and IsPerfectGroup; fi; - typ:=fam!.defaultGroupType; fi; - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens)); + fi; + typ:=NewType(fam,typ); - return G; - end ); + G:=rec(); + if triv=fail then + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + IsEmpty,false); + else + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + IsEmpty,false,IsTrivial,triv, + IsNonTrivial,not triv); + fi; + + return G; +end ); InstallMethod( GroupWithGenerators, "generic method for collection and identity element", IsCollsElms, [ IsCollection, IsMultiplicativeElementWithInverse ], - function( gens, id ) - local G,fam,typ; - - fam:=FamilyObj(gens); - if IsFinite(gens) then - if not IsBound(fam!.defaultFinitelyGeneratedGroupWithOneType) then - fam!.defaultFinitelyGeneratedGroupWithOneType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup and HasOne); - fi; - typ:=fam!.defaultFinitelyGeneratedGroupWithOneType; - else - if not IsBound(fam!.defaultGroupWithOneType) then - fam!.defaultGroupWithOneType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses and HasOne); +function( gens, id ) +local G,fam,typ,triv; + + fam:=FamilyObj(gens); + triv:=fail; # might not find out + + typ:=IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses and HasOne; + if IsFinite(gens) then + typ:=typ and IsFinitelyGeneratedGroup; + if Length(gens)<=1 then + typ:=typ and HasIsCyclic and IsCyclic + and HasIsCommutative and IsCommutative; + fi; + + if Length(gens)>0 and CanEasilyCompareElements(gens) then + if ForAny(gens,x->x<>id) then + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=false; + else + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=true; + # basic consequence + typ:=typ and HasIsPerfectGroup and IsPerfectGroup; fi; - typ:=fam!.defaultGroupWithOneType; fi; - G:=rec(); + fi; + typ:=NewType(fam,typ); + + G:=rec(); + if triv=fail then ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - One,id); + IsEmpty,false,One,id); + else + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + IsEmpty,false,One,id, + IsTrivial,triv,IsNonTrivial,not triv); + fi; - return G; + return G; end ); -InstallMethod( GroupWithGenerators, - "method for empty list and element", - [ IsList and IsEmpty, IsMultiplicativeElementWithInverse ], - function( empty, id ) - local G,fam,typ; +InstallMethod( GroupWithGenerators,"method for empty list and element", + [ IsList and IsEmpty, IsMultiplicativeElementWithInverse ], + function( empty, id ) +local G,fam,typ; - fam:= CollectionsFamily( FamilyObj( id ) ); - if not IsBound( fam!.defaultFinitelyGeneratedGroupWithOneType ) then - fam!.defaultFinitelyGeneratedGroupWithOneType:= - NewType( fam, IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup and HasOne ); - fi; - typ:= fam!.defaultFinitelyGeneratedGroupWithOneType; + fam:= CollectionsFamily( FamilyObj( id ) ); - G:= rec(); - ObjectifyWithAttributes( G, typ, - GeneratorsOfMagmaWithInverses, empty, - One, id ); + typ:=IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses and HasOne + and IsFinitelyGeneratedGroup and HasIsTrivial and HasIsNonTrivial + and HasIsFinite and HasIsCyclic + and HasIsPerfectGroup and HasIsEmpty; + typ:=NewType(fam,typ); - return G; - end ); + G:= rec(); + ObjectifyWithAttributes( G, typ, + GeneratorsOfMagmaWithInverses, empty, + One, id,IsEmpty,false, + IsTrivial,true,IsNonTrivial,false, + IsFinite,true,IsCyclic,true, + IsPerfectGroup,true); + + return G; +end ); ############################################################################# diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 0cd53e6ec8..4d786c7077 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -1539,7 +1539,7 @@ end ); #M FactorFreeGroupByRelators(,) . factor of free group by relators ## BindGlobal( "FactorFreeGroupByRelators", function( F, rels ) - local G, fam, gens; + local G, fam, gens,typ; # Create a new family. fam := NewFamily( "FamilyElementsFpGroup", IsElementOfFpGroup ); @@ -1549,12 +1549,14 @@ BindGlobal( "FactorFreeGroupByRelators", function( F, rels ) fam!.freeGroup := F; fam!.relators := Immutable( rels ); + typ:=IsSubgroupFpGroup and IsWholeFamily and IsAttributeStoringRep; + if IsFinitelyGeneratedGroup(F) then + typ:=typ and IsFinitelyGeneratedGroup; + fi; # Create the group. G := Objectify( - NewType( CollectionsFamily( fam ), - IsSubgroupFpGroup and IsWholeFamily and IsAttributeStoringRep ), - rec() ); + NewType( CollectionsFamily( fam ), typ ), rec() ); # Mark to be the 'whole group' of its later subgroups. FamilyObj( G )!.wholeGroup := G; diff --git a/lib/grppc.gi b/lib/grppc.gi index e7e9e1726a..fecd3f9afe 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -272,7 +272,8 @@ InstallMethod( Pcgs, ## #M GeneralizedPcgs( ) ## -InstallImmediateMethod( GeneralizedPcgs, IsGroup and HasPcgs, 0, Pcgs ); +# is now set when creating +#InstallImmediateMethod( GeneralizedPcgs, IsGroup and HasPcgs, 0, Pcgs ); ############################################################################# ## @@ -339,77 +340,97 @@ end); InstallMethod( GroupWithGenerators, "method for pc elements collection", true, [ IsCollection and - IsMultiplicativeElementWithInverseByPolycyclicCollectorCollection] , + IsMultiplicativeElementWithInverseByPolycyclicCollectorCollection and + IsFinite] , # override methods for `IsList' or `IsEmpty'. 10, - function( gens ) - local G,fam,typ,pcgs; - - fam:=FamilyObj(gens); - if IsFinite(gens) then - if not IsBound(fam!.defaultFinitelyGeneratedGroupType) then - fam!.defaultFinitelyGeneratedGroupType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup - and HasFamilyPcgs and HasHomePcgs); - fi; - typ:=fam!.defaultFinitelyGeneratedGroupType; - else - if not IsBound(fam!.defaultGroupType) then - fam!.defaultGroupType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and HasFamilyPcgs and HasHomePcgs); - fi; - typ:=fam!.defaultGroupType; - fi; +function( gens ) +local G,fam,typ,id,triv,pcgs; + + fam:=FamilyObj(gens); + pcgs:=DefiningPcgs(ElementsFamily(fam)); + + # pc groups are always finite and gens is finite. + typ:=IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses + and HasIsFinite and IsFinitelyGeneratedGroup + and HasIsTrivial and HasIsNonTrivial + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs; + + if Length(gens)<=1 then + typ:=typ and HasIsCyclic and IsCyclic + and HasIsCommutative and IsCommutative; + fi; - pcgs:=DefiningPcgs(ElementsFamily(fam)); - - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - FamilyPcgs,pcgs,HomePcgs,pcgs); - SetGroupOfPcgs (pcgs, G); - return G; - end ); + # we can always compare to id cheaply + id:=One(gens[1]); + if ForAny(gens,x->x<>id) then + triv:=false; + else + triv:=true; + # basic consequence to kill an immediate method + typ:=typ and HasIsPerfectGroup and IsPerfectGroup; + fi; + + typ:=NewType(fam,typ); + + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + IsEmpty,false,IsTrivial,triv, + IsNonTrivial,not triv, + IsFinite,true, + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); + SetGroupOfPcgs (pcgs, G); + + return G; +end ); InstallOtherMethod( GroupWithGenerators, "method for pc collection and identity element", IsCollsElms, [ IsCollection and - IsMultiplicativeElementWithInverseByPolycyclicCollectorCollection , + IsMultiplicativeElementWithInverseByPolycyclicCollectorCollection + and IsFinite, IsMultiplicativeElementWithInverseByPolycyclicCollector] , 0, - function( gens, id ) - local G,fam,typ,pcgs; - - fam:=FamilyObj(gens); - if IsFinite(gens) then - if not IsBound(fam!.defaultFinitelyGeneratedGroupWithOneType) then - fam!.defaultFinitelyGeneratedGroupWithOneType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup and HasOne - and HasFamilyPcgs and HasHomePcgs); - fi; - typ:=fam!.defaultFinitelyGeneratedGroupWithOneType; - else - if not IsBound(fam!.defaultGroupWithOneType) then - fam!.defaultGroupWithOneType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses and HasOne - and HasFamilyPcgs and HasHomePcgs); - fi; - typ:=fam!.defaultGroupWithOneType; - fi; +function( gens, id ) +local G,fam,typ,triv,pcgs; - pcgs:=DefiningPcgs(ElementsFamily(fam)); + fam:=FamilyObj(gens); - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - One,id,FamilyPcgs,pcgs,HomePcgs,pcgs); - SetGroupOfPcgs (pcgs, G); - return G; + # pc groups are always finite and gens is finite. + typ:=IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses and HasOne + and HasIsFinite and IsFinitelyGeneratedGroup + and HasIsTrivial and HasIsNonTrivial + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs; + + if Length(gens)<=1 then + typ:=typ and HasIsCyclic and IsCyclic + and HasIsCommutative and IsCommutative; + fi; + + # we can always compare to id cheaply + if ForAny(gens,x->x<>id) then + triv:=false; + else + triv:=true; + # basic consequence to kill an immediate method + typ:=typ and IsPerfectGroup; + fi; + + typ:=NewType(fam,typ); + pcgs:=DefiningPcgs(ElementsFamily(fam)); + + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + IsEmpty,false,One,id, + IsTrivial,triv,IsNonTrivial,not triv, + IsFinite,true, + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); + + SetGroupOfPcgs (pcgs, G); + + return G; end ); InstallOtherMethod( GroupWithGenerators, @@ -418,30 +439,34 @@ InstallOtherMethod( GroupWithGenerators, IsMultiplicativeElementWithInverseByPolycyclicCollector] , # override methods for `IsList' or `IsEmpty'. 10, - function( gens, id ) - local G,fam,typ,pcgs; - - fam:= CollectionsFamily( FamilyObj( id ) ); - if not IsBound(fam!.defaultFinitelyGeneratedGroupWithOneType) then - fam!.defaultFinitelyGeneratedGroupWithOneType:= - NewType(fam,IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses - and IsFinitelyGeneratedGroup and HasOne - and HasFamilyPcgs and HasHomePcgs); - fi; - typ:=fam!.defaultFinitelyGeneratedGroupWithOneType; - - pcgs:=DefiningPcgs(ElementsFamily(fam)); - - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,[], - One,id,FamilyPcgs,pcgs,HomePcgs,pcgs); +function( empty, id ) +local G,fam,typ,pcgs; + + fam:= CollectionsFamily( FamilyObj( id ) ); + + # pc groups are always finite and gens is finite. + typ:=IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses and HasOne + and HasIsFinite and IsFinitelyGeneratedGroup + and HasIsTrivial and HasIsCyclic and HasIsCommutative + and IsPerfectGroup and HasIsEmpty + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs; + typ:=NewType(fam,typ); + pcgs:=DefiningPcgs(ElementsFamily(fam)); + + G:= rec(); + ObjectifyWithAttributes( G, typ, + GeneratorsOfMagmaWithInverses, empty, + One, id,IsEmpty,false, + IsTrivial,true,IsNonTrivial,false, + IsFinite,true, + IsCyclic,true,IsCommutative,true,IsPerfectGroup,true, + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); - SetGroupOfPcgs (pcgs, G); - return G; + SetGroupOfPcgs (pcgs, G); + return G; end ); - ############################################################################# ## #M in diff --git a/lib/grppcaut.gi b/lib/grppcaut.gi index 4ded2f9eaf..fef93ddc52 100644 --- a/lib/grppcaut.gi +++ b/lib/grppcaut.gi @@ -371,6 +371,7 @@ local translate, gens, oper, fac, ind, vec, tmp; permgens:=tmp.gens, pairgens:=tmp.shadows); C:=GroupByGenerators(translate.pairgens,One(C)); + SetIsFinite(C,true); SetSize(C,Size(tmp.stabilizer)); else tmp := OrbitStabilizer( C, v, gens, oper, OnRight ); @@ -493,6 +494,7 @@ InducedActionAutGroup := function( epi, weights, s, n, A ) # add size and check solubility D := GroupByGenerators( comp, DirectProductElement( [ One( A ), Immutable( IdentityMat(Length(pcgsM), field) )])); + SetIsFinite(D,true); SetSize( D, Size( A ) ); if CanEasilyComputePcgs( A ) then TransferPcgsInfo( D, comp, RelativeOrders( gensA ) ); @@ -667,6 +669,7 @@ local spec,s,n,M, TransferPcgsInfo( B, pcgs, rels ); fi; + SetIsFinite(B,true); SetSize( B, Size( L )*(p-1) ); return B; end; @@ -897,6 +900,7 @@ AutomorphismGroupElAbGroup := function( G, B ) od; A := GroupByGenerators( autos, IdentityMapping( G ) ); + SetIsFinite(A,true); SetSize( A, Size( B ) ); if IsPcgs( mats ) then TransferPcgsInfo( A, autos, RelativeOrders( mats ) ); @@ -971,6 +975,7 @@ local f,act,xset,stb,hom,n,m,l,i; Add(stb,m); stb:=List(stb,x->x^act); # base change stb:=Group(stb); + SetIsFinite(stb,true); SetSize(stb,Size(GL(l,f))*Size(GL(n-l,f))*Size(f)^(l*(n-l))); Info(InfoMatOrb,2,"reduced full GL by ",Size(G)/Size(stb)); return stb; @@ -1264,6 +1269,7 @@ if Length(rans[i])=0 then Error("EGAD");fi; gens:=List(gens,x->x^sub); a:=Group(gens,one); + SetIsFinite(a,true); SetSize(a,sz); # are there diagonals we did not deal with, also original spaces? @@ -1804,6 +1810,7 @@ InstallGlobalFunction(AutomorphismGroupSolvableGroup,function( G ) Add( autos, new ); od; B := GroupByGenerators( autos ); + SetIsGroupOfAutomorphismsFiniteGroup(B,true); SetSize( B, Size(A) ); PopOptions(); # undo the added `fail' return B; @@ -1906,6 +1913,7 @@ InstallGlobalFunction(AutomorphismGroupFrattFreeGroup,function( G ) # create automorphism group B := GroupByGenerators( full, IdentityMapping( G ) ); + SetIsGroupOfAutomorphismsFiniteGroup(B,true); SetSize( B, size ); return B; diff --git a/lib/grppcext.gi b/lib/grppcext.gi index 1f12b2fe8b..7ef4ba8b77 100644 --- a/lib/grppcext.gi +++ b/lib/grppcext.gi @@ -526,6 +526,7 @@ local ag, p1iso, agp, p2iso, DP, p1, p2, gens, genimgs, triso,s,i,u,opt, # If this is the first time we use it, # copy group to avoid carrying too much cruft later. ag:=Group(GeneratorsOfGroup(ag),One(ag)); + SetIsGroupOfAutomorphismsFiniteGroup(ag,true); SetSize(ag,s); fi; IsGroupOfAutomorphismsFiniteGroup(ag); @@ -953,6 +954,7 @@ local G, M, Mgrp, oper, A, B, D, translate, gens, genimgs, triso, K, K1, fi; fi; tmp:=SubgroupNC(Range(triso),genimgs); + SetIsGroupOfAutomorphismsFiniteGroup(tmp,true); SetSize(tmp,l); # cache the faithful permutation representation in case we need it # later diff --git a/lib/grppcfp.gi b/lib/grppcfp.gi index 423f293c5d..6332dbd7e0 100644 --- a/lib/grppcfp.gi +++ b/lib/grppcfp.gi @@ -69,6 +69,7 @@ InstallGlobalFunction( IsomorphismFpGroupByPcgs, function( pcgs, str ) od; od; H := F / rels; + SetIsFinite(H,true); SetSize(H,Product(RelativeOrders(pcgs))); phi := GroupHomomorphismByImagesNC( GroupOfPcgs(pcgs), H, AsList( pcgs ), diff --git a/lib/magma.gi b/lib/magma.gi index 47c3598d5a..9ae8155d44 100644 --- a/lib/magma.gi +++ b/lib/magma.gi @@ -184,16 +184,17 @@ InstallImmediateMethod( IsCommutative, fi; end ); -InstallImmediateMethod( IsCommutative, - IsMagmaWithInverses and IsAssociative - and HasGeneratorsOfMagmaWithInverses, 0, - function( M ) - if Length( GeneratorsOfMagmaWithInverses( M ) ) = 1 then - return true; - else - TryNextMethod(); - fi; - end ); +# this is now set when creating groups +#InstallImmediateMethod( IsCommutative, +# IsMagmaWithInverses and IsAssociative +# and HasGeneratorsOfMagmaWithInverses, 0, +# function( M ) +# if Length( GeneratorsOfMagmaWithInverses( M ) ) = 1 then +# return true; +# else +# TryNextMethod(); +# fi; +# end ); InstallMethod( IsCommutative, "for a magma", @@ -652,17 +653,44 @@ InstallOtherMethod( MagmaWithOneByGenerators, #M MagmaWithInversesByGenerators( ) . . . . . . . . for a collection ## MakeMagmaWithInversesByFiniteGenerators:=function(family,gens) -local M; - if not IsBound(family!.defaultMagmaWithInversesByGeneratorsType) then - family!.defaultMagmaWithInversesByGeneratorsType := - NewType( FamilyObj( gens ), - IsMagmaWithInverses and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses); +local M,triv,typ,id; + triv:=fail; # might not find out + + typ:=IsMagmaWithInverses and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses + and HasIsEmpty; + + if IsFinite(gens) then + # typ:=typ and IsFinitelyGeneratedGroup; don't know whether group + if Length(gens)<=1 then + typ:=typ and HasIsCyclic and IsCyclic + and HasIsCommutative and IsCommutative; + fi; + + if Length(gens)>0 and CanEasilyCompareElements(gens) then + id:=One(gens[1]); + if ForAny(gens,x->x<>id) then + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=false; + else + typ:=typ and HasIsTrivial and HasIsNonTrivial; + triv:=true; + fi; + fi; fi; + typ:=NewType( FamilyObj( gens ),typ); M:=rec(); - ObjectifyWithAttributes( M,family!.defaultMagmaWithInversesByGeneratorsType, - GeneratorsOfMagmaWithInverses, AsList( gens ) ); + if triv=fail then + ObjectifyWithAttributes( M,typ, + GeneratorsOfMagmaWithInverses, AsList( gens ), + IsEmpty,false); + else + ObjectifyWithAttributes( M,typ, + GeneratorsOfMagmaWithInverses, AsList( gens ), + IsEmpty,false,IsTrivial,triv, + IsNonTrivial,not triv); + fi; if HasIsAssociative( M ) and IsAssociative( M ) then SetIsFinitelyGeneratedGroup( M, true ); fi;