From 4981e00ddafbd1d1eade341fa82186d6b5123c52 Mon Sep 17 00:00:00 2001 From: Alexander Hulpke Date: Sun, 22 Apr 2018 17:47:02 -0600 Subject: [PATCH 1/3] ENHANCE: Reduce impact of immediate methods for groups etc. This commit changes routines that create groups, certain Submagmas and vector spaces so that flags that set basic properties (being trivial, being empty, being cyclic) are set at the same time as the object was created. This functionality used to be provided through immediate methods, however this meant that the type of a just-created object was changed immediately multiple times (with some changes precipitating other changes), causing a notable performance hit. Notably, the following changes have been done: 1) In a number of methods used to create groups (or submagmas, when called from `Subgroup` or cosets) from generating sets, a number of cheaply deduced properties (such as being cyclic) are set while creating the object. Thus the immediate methods do not apply for these objects any longer. 2) Type caching in these methods is not worth the effort and has been removed. 3) A new setter method for `Size` deals similarly with deductions done before by immediate methods for a known size. Caveat: The manual specifies (ill-advised one might say) that setting a different size if a size already is given will be ignored. This is tested in manual examples and test files. The new setter method therefore cannot be used to check for this property as an error -- it will do so only if assertion level is set >=3. 4a) Immediate methods that have been made obsolete by the changes in 1) and 3) have been changed to ordinary methods. 4b) A number of immediate methods (e.g. a trivial group is solvable) have been replaced by `TrueMethods` that have the same effect but are chapter to run. 4c) Also a number of immediate methods that need to run often, but apply only rarely (i.e. setting `IsFinite` to false if a size is set to `infinity`) have been removed. 5) These changes have minor impact on test files and manual tests: A few objects will have slightly different knowledge about their properties and thus print differently; respectively test code exists that checks explicitly for such properties having been set by immediate methods. These tests and examples have been changed. A few, very unstable tests (e.g. checking explicitly for the values of random elements) have been commented out. 6) Some tests explicitly relied on immediate methods enabling derived series calculations in special cases of finitely presented groups. These tests never would have worked if immediate methods were turned off, the respective finitely presented groups method has been changed accordingly to test explicitly for the particular situation, thus enabling the same examples to work. --- lib/coll.gd | 4 + lib/coll.gi | 46 +++++++++-- lib/csetgrp.gi | 35 ++++---- lib/ctbl.gd | 2 + lib/grp.gd | 10 +++ lib/grp.gi | 153 ++++++++++++++++++----------------- lib/grpfp.gi | 15 +++- lib/grpmat.gi | 98 ++++++++++++---------- lib/grppc.gi | 149 ++++++++++++++++------------------ lib/grppcaut.gi | 3 +- lib/grppcext.gi | 2 + lib/magma.gi | 32 ++++---- lib/modulrow.gi | 34 +++++--- lib/object.gd | 42 +++++----- lib/read1.g | 2 +- lib/vspcrow.gi | 72 +++++++++++------ tst/testbugfix/00005.tst | 2 +- tst/testinstall/algmat.tst | 3 +- tst/testinstall/coll.tst | 17 ++-- tst/testinstall/semigrp.tst | 11 ++- tst/testinstall/semitran.tst | 2 +- 21 files changed, 418 insertions(+), 316 deletions(-) diff --git a/lib/coll.gd b/lib/coll.gd index 0f02c4662d..085d105daa 100644 --- a/lib/coll.gd +++ b/lib/coll.gd @@ -1415,6 +1415,10 @@ InstallFactorMaintenance( IsTrivial, ## DeclareProperty( "IsNonTrivial", IsCollection ); +# true methods to avoid immediate methods +InstallTrueMethod(HasIsTrivial,IsNonTrivial); +InstallTrueMethod(HasIsNonTrivial,IsTrivial); + ############################################################################# ## diff --git a/lib/coll.gi b/lib/coll.gi index d3f81b2362..f788cf5b26 100644 --- a/lib/coll.gi +++ b/lib/coll.gi @@ -120,8 +120,8 @@ InstallMethod( IsTrivial, [ IsCollection ], C -> Size( C ) = 1 ); -InstallImmediateMethod( IsTrivial, - IsCollection and HasIsNonTrivial, 0, +InstallMethod( IsTrivial, + [IsCollection and HasIsNonTrivial], 0, C -> not IsNonTrivial( C ) ); @@ -129,8 +129,8 @@ InstallImmediateMethod( IsTrivial, ## #M IsNonTrivial( ) . . . . . . . . . test if a collection is nontrivial ## -InstallImmediateMethod( IsNonTrivial, - IsCollection and HasIsTrivial, 0, +InstallMethod( IsNonTrivial, + [IsCollection and HasIsTrivial], 0, C -> not IsTrivial( C ) ); InstallMethod( IsNonTrivial, @@ -169,8 +169,12 @@ InstallMethod( IsWholeFamily, ## #M Size( ) . . . . . . . . . . . . . . . . . . . . size of a collection ## -InstallImmediateMethod( Size, - IsCollection and HasIsFinite and IsAttributeStoringRep, 0, +# This used to be an immediate method. It was replaced by an ordinary +# method, as the immediate method would get called for every group that +# knows it is finite but does not know its size -- e.g. permutation, pc. +# The benefit of this is minimal beyond showing off a feature. +InstallMethod( Size,true, [IsCollection and HasIsFinite], + 100, # rank above object-specific methods function ( C ) if IsFinite( C ) then TryNextMethod(); @@ -3055,6 +3059,36 @@ end); InstallMethod( CanComputeIsSubset,"default: no, unless identical", [IsObject,IsObject],IsIdenticalObj); +# This setter method is installed to implement filter settings in response +# to an objects size as part of setting the size. This used to be handled +# instead by immediate methods, but in a situation as here it would trigger +# multiple immediate methods, several of which could apply and each changing +# the type of the object. Doing so can be costly and thus should be +# avoided. +InstallOtherMethod(SetSize,true,[IsObject and IsAttributeStoringRep,IsObject], + 100, # override system setter +function(obj,sz) +local filt; + if HasSize(obj) and Size(obj)<>sz then + if AssertionLevel()>2 then + # Make this an ordinary error (not ErrorNoReturn as suggested) to + # preserve all debugging options -- even use `return` to investigate + # what would have happened before this methods was introduced. + Error("size of ",obj," already set to ",Size(obj), + ", cannot be changed to ",sz); + fi; + return; + fi; + if sz=0 then filt:=IsEmpty and IsNonTrivial; # IsNonTrivial hold + elif sz=1 then filt:=IsTrivial; + elif sz=infinity then filt:=IsNonTrivial and HasIsFinite; + else filt:=IsNonTrivial and IsFinite; + fi; + filt:=filt and HasSize; + obj!.Size:=sz; + SetFilterObj(obj,filt); +end); + ############################################################################# ## #E diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index b00f607fcc..44c5c84478 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -411,18 +411,17 @@ end); InstallOtherMethod(DoubleCoset,"with size",true, [IsGroup,IsObject,IsGroup,IsPosInt],0, function(U,g,V,sz) -local d,fam; +local d,fam,typ; fam:=FamilyObj(U); - if not IsBound(fam!.doubleCosetsDefaultSizeType) then - fam!.doubleCosetsDefaultSizeType:=NewType(fam,IsDoubleCosetDefaultRep - and HasSize and HasIsFinite and IsFinite + typ:=NewType(fam,IsDoubleCosetDefaultRep + and HasIsFinite and IsFinite and HasLeftActingGroup and HasRightActingGroup and HasRepresentative); - fi; d:=rec(); - ObjectifyWithAttributes(d,fam!.doubleCosetsDefaultSizeType, - LeftActingGroup,U,RightActingGroup,V,Representative,g, - Size,sz); + ObjectifyWithAttributes(d,typ, + LeftActingGroup,U,RightActingGroup,V,Representative,g); + SetSize(d,sz); # Size has private setter which will cause problems with + # HasSize triggering an immediate method. return d; end); @@ -574,21 +573,25 @@ end); InstallMethod(RightCoset,"use subgroup size",IsCollsElms, [IsGroup and HasSize,IsObject],0, function(U,g) -local d,fam; +local d,fam,typ; # noch tests... fam:=FamilyObj(U); - if not IsBound(fam!.rightCosetsDefaultSizeType) then - fam!.rightCosetsDefaultSizeType:=NewType(fam,IsRightCosetDefaultRep and - HasActingDomain and HasFunctionAction and HasRepresentative and - HasSize and HasCanonicalRepresentativeDeterminatorOfExternalSet); - fi; + typ:=NewType(fam,IsRightCosetDefaultRep and + HasActingDomain and HasFunctionAction and HasRepresentative + and HasCanonicalRepresentativeDeterminatorOfExternalSet); d:=rec(); - ObjectifyWithAttributes(d,fam!.rightCosetsDefaultSizeType, + ObjectifyWithAttributes(d,typ, ActingDomain,U,FunctionAction,OnLeftInverse,Representative,g, - Size,Size(U),CanonicalRepresentativeDeterminatorOfExternalSet, + CanonicalRepresentativeDeterminatorOfExternalSet, RightCosetCanonicalRepresentativeDeterminator); + # We cannot set the size in the previous ObjectifyWithAttributes as there is + # a custom setter method (the one added in this commit). In such a case + # ObjectifyWith Attributes just does `Objectify` and calls all setters + # separately which is what we want to avoid here. + SetSize(d,Size(U)); + return d; end); diff --git a/lib/ctbl.gd b/lib/ctbl.gd index dc26480cf4..0b114f57f1 100644 --- a/lib/ctbl.gd +++ b/lib/ctbl.gd @@ -3584,6 +3584,8 @@ DeclareGlobalVariable( "CharacterTableDisplayDefaults" ); ## tbl:=rec(); ## tbl.Irr:= ## [ [ 1, 1 ], [ 1, -1 ] ]; +## tbl.IsFinite:= +## true; ## tbl.NrConjugacyClasses:= ## 2; ## tbl.Size:= diff --git a/lib/grp.gd b/lib/grp.gd index ca7c815533..7569375911 100644 --- a/lib/grp.gd +++ b/lib/grp.gd @@ -603,6 +603,8 @@ InstallTrueMethod( IsGroup, IsPerfectGroup ); InstallFactorMaintenance( IsPerfectGroup, IsGroup and IsPerfectGroup, IsObject, IsGroup ); +InstallTrueMethod( IsPerfectGroup, IsGroup and IsTrivial ); + ############################################################################# ## #P IsSporadicSimpleGroup( ) @@ -797,6 +799,8 @@ InstallFactorMaintenance( IsSolvableGroup, InstallTrueMethod( IsSolvableGroup, IsMonomialGroup ); InstallTrueMethod( IsSolvableGroup, IsSupersolvableGroup ); +InstallTrueMethod( HasIsPerfectGroup, IsGroup and IsSolvableGroup and IsNonTrivial ); + ############################################################################# ## @@ -3582,6 +3586,12 @@ DeclareOperation( "GroupWithGenerators", [ IsListOrCollection, IsMultiplicativeElementWithInverse ] ); +#F MakeGroupyType( , , , ) +# type creator function to incorporate basic deductions so immediate methods +# are not needed +DeclareGlobalFunction("MakeGroupyType"); + + ############################################################################# ## #F Group( , ... ) diff --git a/lib/grp.gi b/lib/grp.gi index af95120410..96f5b9bd18 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -30,7 +30,9 @@ InstallImmediateMethod( IsFinitelyGeneratedGroup, ## #M IsCyclic( ) . . . . . . . . . . . . . . . . test if a group is cyclic ## -InstallImmediateMethod( IsCyclic, IsGroup and HasGeneratorsOfGroup, 0, +# This used to be an immediate method. It was replaced by an ordinary +# method since the flag is typically set when creating the group. +InstallMethod( IsCyclic, true, [IsGroup and HasGeneratorsOfGroup], 0, function( G ) if Length( GeneratorsOfGroup( G ) ) = 1 then return true; @@ -43,10 +45,14 @@ InstallMethod( IsCyclic, "generic method for groups", [ IsGroup ], function ( G ) + local a; # if has a generator list of length 1 then is cyclic if HasGeneratorsOfGroup( G ) and Length( GeneratorsOfGroup(G) ) = 1 then - SetMinimalGeneratingSet(G,GeneratorsOfGroup(G)); + a:=GeneratorsOfGroup(G)[1]; + if CanEasilyCompareElements(a) and not IsOne(a) then + SetMinimalGeneratingSet(G,GeneratorsOfGroup(G)); + fi; return true; # if is not commutative it is certainly not cyclic @@ -433,11 +439,6 @@ InstallMethod( IsNilpotentGroup, ## #M IsPerfectGroup( ) . . . . . . . . . . . . test if a group is perfect ## -InstallImmediateMethod( IsPerfectGroup, - IsSolvableGroup and HasIsTrivial, - 0, - IsTrivial ); - InstallImmediateMethod( IsPerfectGroup, IsGroup and HasIsAbelian and IsSimpleGroup, 0, @@ -4297,6 +4298,39 @@ local s,b; return s; end ); +#F MakeGroupyType( , , , , ) +# type creator function to incorporate basic deductions so immediate methods +# are not needed. Parameters are family, filter to start with, generator +# list, is it indeed a group (or only magma)? +InstallGlobalFunction(MakeGroupyType, +function(fam,filt,gens,id,isgroup) + + if IsFinite(gens) then + if isgroup then + filt:=filt and IsFinitelyGeneratedGroup; + fi; + + if Length(gens)>0 and CanEasilyCompareElements(gens) then + if id=false then + id:=One(gens[1]); + fi; + if id<>fail then # cannot do identity in magma + if ForAny(gens,x->x<>id) then + filt:=filt and HasIsTrivial and IsNonTrivial; + if isgroup and Length(gens)<=1 then # cyclic not for magmas + filt:=filt and IsCyclic; + fi; + else + filt:=filt and IsTrivial and HasIsNonTrivial; + fi; + fi; + elif isgroup and Length(gens)<=1 then # cyclic not for magmas + filt:=filt and IsCyclic; + fi; + fi; + return NewType(fam,filt); +end); + ############################################################################# ## #M GroupWithGenerators( ) . . . . . . . . group with given generators @@ -4305,86 +4339,57 @@ 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); - fi; - typ:=fam!.defaultGroupType; - fi; +function( gens ) +local G,typ; - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens)); + typ:=MakeGroupyType(FamilyObj(gens), + IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses, + gens,false,true); - return G; - end ); + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens)); + + 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); - fi; - typ:=fam!.defaultGroupWithOneType; - fi; +function( gens, id ) +local G,typ; - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - One,id); + typ:=MakeGroupyType(FamilyObj(gens), + IsGroup and IsAttributeStoringRep + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses and HasOne, + gens,id,true); - return G; + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + One,id); + + 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 IsTrivial and + HasIsEmpty and HasIsNonTrivial; + typ:=NewType(fam,typ); - return G; - end ); + G:= rec(); + ObjectifyWithAttributes( G, typ, + GeneratorsOfMagmaWithInverses, empty, + One, id ); + + return G; +end ); ############################################################################# diff --git a/lib/grpfp.gi b/lib/grpfp.gi index 0cd53e6ec8..9ee39263d2 100644 --- a/lib/grpfp.gi +++ b/lib/grpfp.gi @@ -955,6 +955,11 @@ local iso,hom,u; if HasIsAbelian(G) and IsAbelian(G) then return TrivialSubgroup(G); elif Size(Image(hom))=infinity then + # test a special case -- one generator + if Length(GeneratorsOfGroup(G))=1 then + SetIsAbelian(G,true); + return TrivialSubgroup(G); + fi; Error("Derived subgroup has infinite index, cannot represent"); elif Size(Range(hom))=1 then return G; # this is needed because the trivial quotient is represented @@ -1539,7 +1544,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 +1554,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/grpmat.gi b/lib/grpmat.gi index cea6b7f092..9caaeecb7d 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -814,61 +814,75 @@ InstallMethod( GroupWithGenerators, "list of matrices", [ IsFFECollCollColl ], #T ??? - function( gens ) - local G,fam,typ,f; - - 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 - TryNextMethod(); - fi; - f:=DefaultScalarDomainOfMatrixList(gens); - gens:=List(Immutable(gens),i->ImmutableMatrix(f,i)); +function( gens ) +local G,typ,f; - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens)); + if not IsFinite(gens) then TryNextMethod(); fi; + typ:=MakeGroupyType(FamilyObj(gens), + IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses + and IsFinitelyGeneratedGroup and HasIsEmpty and IsFinite, + gens,false,true); - if IsField(f) then SetDefaultFieldOfMatrixGroup(G,f);fi; + f:=DefaultScalarDomainOfMatrixList(gens); + gens:=List(Immutable(gens),i->ImmutableMatrix(f,i)); - return G; - end ); + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens)); + + if IsField(f) then SetDefaultFieldOfMatrixGroup(G,f);fi; + + return G; +end ); InstallMethod( GroupWithGenerators, "list of matrices with identity", IsCollsElms, [ IsFFECollCollColl,IsMultiplicativeElementWithInverse and IsFFECollColl], function( gens, id ) +local G,typ,f; + + if not IsFinite(gens) then TryNextMethod(); fi; + typ:=MakeGroupyType(FamilyObj(gens), IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses and IsFinitelyGeneratedGroup + and HasIsEmpty and IsFinite and HasOne, + gens,id,true); + + f:=DefaultScalarDomainOfMatrixList(gens); + gens:=List(Immutable(gens),i->ImmutableMatrix(f,i)); + id:=ImmutableMatrix(f,id); + + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + One,id); + + if IsField(f) then SetDefaultFieldOfMatrixGroup(G,f);fi; + + return G; +end ); + +InstallMethod( GroupWithGenerators, + "empty list of matrices with identity", true, + [ IsList and IsEmpty,IsMultiplicativeElementWithInverse and IsFFECollColl], +function( gens, id ) local G,fam,typ,f; - 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 - TryNextMethod(); - fi; - f:=DefaultScalarDomainOfMatrixList(gens); - gens:=List(Immutable(gens),i->ImmutableMatrix(f,i)); - id:=ImmutableMatrix(f,id); + if not IsFinite(gens) then TryNextMethod(); fi; + typ:=MakeGroupyType(FamilyObj([id]), IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses and IsFinitelyGeneratedGroup + and HasIsEmpty and IsFinite and HasOne + and IsTrivial and HasIsNonTrivial, + gens,id,true); + + f:=DefaultScalarDomainOfMatrixList([id]); + id:=ImmutableMatrix(f,id); - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - One,id); + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + One,id); - if IsField(f) then SetDefaultFieldOfMatrixGroup(G,f);fi; + if IsField(f) then SetDefaultFieldOfMatrixGroup(G,f);fi; - return G; + return G; end ); diff --git a/lib/grppc.gi b/lib/grppc.gi index 71a1b95322..ad1a10f292 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -272,7 +272,10 @@ InstallMethod( Pcgs, ## #M GeneralizedPcgs( ) ## -InstallImmediateMethod( GeneralizedPcgs, IsGroup and HasPcgs, 0, Pcgs ); +# This used to be an immediate method. It was replaced by an ordinary +# method as the attribute is set when creating pc groups. +InstallMethod( GeneralizedPcgs,true,[ IsGroup and HasPcgs], 0, Pcgs ); + ############################################################################# ## @@ -339,77 +342,61 @@ 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,pcgs; - pcgs:=DefiningPcgs(ElementsFamily(fam)); - - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), - FamilyPcgs,pcgs,HomePcgs,pcgs); - SetGroupOfPcgs (pcgs, G); - return G; - end ); + fam:=FamilyObj(gens); + pcgs:=DefiningPcgs(ElementsFamily(fam)); + + # pc groups are always finite and gens is finite. + typ:=MakeGroupyType(fam, + IsGroup and IsAttributeStoringRep and IsSolvableGroup + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses + and IsFinite and IsFinitelyGeneratedGroup + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs, + gens,One(gens[1]),true); + + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); + #SetGroupOfPcgs (pcgs, G); That cannot be true, as pcgs is the family pcgs + + 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,pcgs; - pcgs:=DefiningPcgs(ElementsFamily(fam)); + fam:=FamilyObj(gens); + pcgs:=DefiningPcgs(ElementsFamily(fam)); - 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:=MakeGroupyType(fam, + IsGroup and IsAttributeStoringRep and IsSolvableGroup + and HasIsEmpty and HasGeneratorsOfMagmaWithInverses and HasOne + and IsFinite and IsFinitelyGeneratedGroup + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs, + gens,id,true); + + G:=rec(); + ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,AsList(gens), + One,id, + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); + + #SetGroupOfPcgs (pcgs, G); + + return G; end ); InstallOtherMethod( GroupWithGenerators, @@ -418,29 +405,31 @@ 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; +function( empty, id ) +local G,fam,typ,pcgs; - pcgs:=DefiningPcgs(ElementsFamily(fam)); + fam:= CollectionsFamily( FamilyObj( id ) ); - G:=rec(); - ObjectifyWithAttributes(G,typ,GeneratorsOfMagmaWithInverses,[], - One,id,FamilyPcgs,pcgs,HomePcgs,pcgs); + # pc groups are always finite and gens is finite. + typ:=IsGroup and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses and HasOne + and IsFinite and IsFinitelyGeneratedGroup + and IsTrivial and HasIsNonTrivial + and HasIsEmpty and IsSolvableGroup + and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs; + typ:=NewType(fam,typ); - SetGroupOfPcgs (pcgs, G); - return G; -end ); + pcgs:=DefiningPcgs(ElementsFamily(fam)); + G:= rec(); + ObjectifyWithAttributes( G, typ, + GeneratorsOfMagmaWithInverses, empty, + One, id, + FamilyPcgs,pcgs,HomePcgs,pcgs,GeneralizedPcgs,pcgs); + + #SetGroupOfPcgs (pcgs, G); + return G; +end ); ############################################################################# ## diff --git a/lib/grppcaut.gi b/lib/grppcaut.gi index 4ded2f9eaf..dd683e75cd 100644 --- a/lib/grppcaut.gi +++ b/lib/grppcaut.gi @@ -1804,6 +1804,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 +1907,7 @@ InstallGlobalFunction(AutomorphismGroupFrattFreeGroup,function( G ) # create automorphism group B := GroupByGenerators( full, IdentityMapping( G ) ); + SetIsGroupOfAutomorphismsFiniteGroup(B,true); SetSize( B, size ); return B; @@ -1960,7 +1962,6 @@ InstallGlobalFunction(AutomorphismGroupNilpotentGroup,function(G) autG := Group( gensAutG, IdentityMapping(G) ); SetIsAutomorphismGroup(autG, true); SetIsGroupOfAutomorphismsFiniteGroup(autG, true); - SetIsFinite(autG,true); return autG; end ); 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/magma.gi b/lib/magma.gi index 47c3598d5a..6c1eac9b3a 100644 --- a/lib/magma.gi +++ b/lib/magma.gi @@ -119,8 +119,8 @@ InstallImmediateMethod( IsTrivial, fi; end ); -InstallImmediateMethod( IsTrivial, - IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses, 0, +InstallMethod( IsTrivial, + [IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses], 0, function( M ) if IsEmpty( GeneratorsOfMagmaWithInverses( M ) ) then return true; @@ -184,9 +184,11 @@ InstallImmediateMethod( IsCommutative, fi; end ); -InstallImmediateMethod( IsCommutative, - IsMagmaWithInverses and IsAssociative - and HasGeneratorsOfMagmaWithInverses, 0, +# This used to be an immediate method. It was replaced by an ordinary +# method, as the filter is now set when creating groups. +InstallMethod( IsCommutative,true, + [IsMagmaWithInverses and IsAssociative + and HasGeneratorsOfMagmaWithInverses], 0, function( M ) if Length( GeneratorsOfMagmaWithInverses( M ) ) = 1 then return true; @@ -652,17 +654,19 @@ 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); - fi; +local M,typ,id,fam; + + typ:=MakeGroupyType(FamilyObj(gens), + IsMagmaWithInverses and IsAttributeStoringRep + and HasGeneratorsOfMagmaWithInverses + and HasIsEmpty, + gens,fail,false); M:=rec(); - ObjectifyWithAttributes( M,family!.defaultMagmaWithInversesByGeneratorsType, - GeneratorsOfMagmaWithInverses, AsList( gens ) ); + + ObjectifyWithAttributes( M,typ, + GeneratorsOfMagmaWithInverses, AsList( gens )); + if HasIsAssociative( M ) and IsAssociative( M ) then SetIsFinitelyGeneratedGroup( M, true ); fi; diff --git a/lib/modulrow.gi b/lib/modulrow.gi index 645823dce4..efc9d07a15 100644 --- a/lib/modulrow.gi +++ b/lib/modulrow.gi @@ -21,26 +21,36 @@ #F FullRowModule( , ) ## InstallGlobalFunction( FullRowModule, function( R, n ) - local M; # the free module record, result +local M,typ; # the free module record, result if not ( IsRing( R ) and IsInt( n ) and 0 <= n ) then Error( "usage: FullRowModule( , ) for ring " ); fi; + typ:=IsFreeLeftModule and IsFullRowModule and IsAttributeStoringRep + and HasIsEmpty; + if IsDivisionRing( R ) then - M:= Objectify( NewType( CollectionsFamily( FamilyObj( R ) ), - IsFreeLeftModule - and IsGaussianSpace - and IsFullRowModule - and IsAttributeStoringRep ), - rec() ); + typ:=typ and IsGaussianSpace; + fi; + + if n=0 then + typ:=typ and IsTrivial and HasIsNonTrivial and IsFinite; else - M:= Objectify( NewType( CollectionsFamily( FamilyObj( R ) ), - IsFreeLeftModule - and IsFullRowModule - and IsAttributeStoringRep ), - rec() ); + typ:=typ and HasIsTrivial and IsNonTrivial; + fi; + + if n<>infinity and HasIsFinite(R) and IsFinite(R) then + typ:=typ and IsFinite; + elif n<>0 and HasIsFinite(R) and not IsFinite(R) then + typ:=typ and HasIsFinite; fi; + + + M:= Objectify( NewType( CollectionsFamily( FamilyObj( R ) ), + typ ), + rec() ); + SetLeftActingDomain( M, R ); SetDimensionOfVectors( M, n ); diff --git a/lib/object.gd b/lib/object.gd index 15b19558e4..122e3b2c24 100644 --- a/lib/object.gd +++ b/lib/object.gd @@ -693,8 +693,7 @@ DeclareOperation( "ObjByExtRep", [ IsFamily, IsObject ] ); ## gap> KnownAttributesOfObject(g); ## [ "Size", "OneImmutable", "NrMovedPoints", "MovedPoints", ## "GeneratorsOfMagmaWithInverses", "MultiplicativeNeutralElement", -## "HomePcgs", "Pcgs", "GeneralizedPcgs", "StabChainMutable", -## "StabChainOptions" ] +## "HomePcgs", "Pcgs", "StabChainMutable", "StabChainOptions" ] ## ]]> ## ## @@ -735,28 +734,29 @@ DeclareOperation( "KnownPropertiesOfObject", [ IsObject ] ); ## g:=Group((1,2),(1,2,3));; ## gap> KnownPropertiesOfObject(g); -## [ "IsFinite", "CanEasilyCompareElements", "CanEasilySortElements", -## "IsDuplicateFree", "IsGeneratorsOfMagmaWithInverses", -## "IsAssociative", "IsGeneratorsOfSemigroup", "IsSimpleSemigroup", -## "IsRegularSemigroup", "IsInverseSemigroup", -## "IsCompletelyRegularSemigroup", "IsCompletelySimpleSemigroup", -## "IsGroupAsSemigroup", "IsMonoidAsSemigroup", "IsOrthodoxSemigroup", -## "IsFinitelyGeneratedGroup", "IsSubsetLocallyFiniteGroup", -## "KnowsHowToDecompose", "IsInfiniteAbelianizationGroup", -## "IsNilpotentByFinite" ] +## [ "IsEmpty", "IsTrivial", "IsNonTrivial", "IsFinite", +## "CanEasilyCompareElements", "CanEasilySortElements", +## "IsDuplicateFree", "IsGeneratorsOfMagmaWithInverses", +## "IsAssociative", "IsGeneratorsOfSemigroup", "IsSimpleSemigroup", +## "IsRegularSemigroup", "IsInverseSemigroup", +## "IsCompletelyRegularSemigroup", "IsCompletelySimpleSemigroup", +## "IsGroupAsSemigroup", "IsMonoidAsSemigroup", "IsOrthodoxSemigroup", +## "IsFinitelyGeneratedGroup", "IsSubsetLocallyFiniteGroup", +## "KnowsHowToDecompose", "IsInfiniteAbelianizationGroup", +## "IsNilpotentByFinite", "IsTorsionFree", "IsFreeAbelian" ] ## gap> Size(g); ## 6 ## gap> KnownPropertiesOfObject(g); -## [ "IsEmpty", "IsTrivial", "IsNonTrivial", "IsFinite", -## "CanEasilyCompareElements", "CanEasilySortElements", -## "IsDuplicateFree", "IsGeneratorsOfMagmaWithInverses", -## "IsAssociative", "IsGeneratorsOfSemigroup", "IsSimpleSemigroup", -## "IsRegularSemigroup", "IsInverseSemigroup", -## "IsCompletelyRegularSemigroup", "IsCompletelySimpleSemigroup", -## "IsGroupAsSemigroup", "IsMonoidAsSemigroup", "IsOrthodoxSemigroup", -## "IsFinitelyGeneratedGroup", "IsSubsetLocallyFiniteGroup", -## "KnowsHowToDecompose", "IsPerfectGroup", "IsSolvableGroup", -## "IsPolycyclicGroup", "IsInfiniteAbelianizationGroup", +## [ "IsEmpty", "IsTrivial", "IsNonTrivial", "IsFinite", +## "CanEasilyCompareElements", "CanEasilySortElements", +## "IsDuplicateFree", "IsGeneratorsOfMagmaWithInverses", +## "IsAssociative", "IsGeneratorsOfSemigroup", "IsSimpleSemigroup", +## "IsRegularSemigroup", "IsInverseSemigroup", +## "IsCompletelyRegularSemigroup", "IsCompletelySimpleSemigroup", +## "IsGroupAsSemigroup", "IsMonoidAsSemigroup", "IsOrthodoxSemigroup", +## "IsFinitelyGeneratedGroup", "IsSubsetLocallyFiniteGroup", +## "KnowsHowToDecompose", "IsPerfectGroup", "IsSolvableGroup", +## "IsPolycyclicGroup", "IsInfiniteAbelianizationGroup", ## "IsNilpotentByFinite", "IsTorsionFree", "IsFreeAbelian" ] ## gap> KnownTruePropertiesOfObject(g); ## [ "IsNonTrivial", "IsFinite", "CanEasilyCompareElements", diff --git a/lib/read1.g b/lib/read1.g index 831ca8981b..50c115a998 100644 --- a/lib/read1.g +++ b/lib/read1.g @@ -38,6 +38,7 @@ ReadLib( "record.gd" ); ReadLib( "random.gd" ); ReadLib( "cache.gi" ); +ReadLib( "assert.gd" ); ReadLib( "coll.gi" ); ReadLib( "flag.g" ); @@ -54,7 +55,6 @@ ReadLib( "filter.gi" ); ReadLib( "object.gi" ); ReadLib( "listcoef.gd" ); ReadLib( "info.gd" ); -ReadLib( "assert.gd" ); ReadLib( "files.gd" ); ReadLib( "streams.gd" ); diff --git a/lib/vspcrow.gi b/lib/vspcrow.gi index a5f67a94f4..80f5f9b78a 100644 --- a/lib/vspcrow.gi +++ b/lib/vspcrow.gi @@ -54,22 +54,31 @@ InstallMethod( LeftModuleByGenerators, IsElmsColls, [ IsDivisionRing, IsMatrix ], function( F, mat ) - local V; + local V,typ; + typ:=IsAttributeStoringRep and HasIsEmpty and IsFiniteDimensional; if ForAll( mat, row -> IsSubset( F, row ) ) then - V:= Objectify( NewType( FamilyObj( mat ), - IsGaussianRowSpace - and IsAttributeStoringRep ), - rec() ); + typ:=typ and IsGaussianRowSpace; else - V:= Objectify( NewType( FamilyObj( mat ), - IsVectorSpace - and IsNonGaussianRowSpace - and IsRowModule - and IsAttributeStoringRep ), - rec() ); + typ:=typ and IsVectorSpace and IsRowModule and IsNonGaussianRowSpace; + fi; + + if Length(mat)>0 and ForAny(mat,x->not IsZero(x)) then + typ:=typ and HasIsTrivial and IsNonTrivial; + else + typ:=typ and IsTrivial and HasIsNonTrivial; + fi; + + if HasIsFinite(F) then + if IsFinite(F) then + typ:=typ and IsFinite; + else + typ:=typ and HasIsFinite; # i.e. not finite + fi; fi; + V:= Objectify( NewType( FamilyObj( mat ), typ), rec() ); + SetLeftActingDomain( V, F ); SetGeneratorsOfLeftModule( V, AsList( mat ) ); SetDimensionOfVectors( V, Length( mat[1] ) ); @@ -81,7 +90,7 @@ InstallMethod( LeftModuleByGenerators, "for division ring, empty list, and row vector", [ IsDivisionRing, IsList and IsEmpty, IsRowVector ], function( F, empty, zero ) - local V; + local V,typ; # Check whether this method is the right one. if not IsIdenticalObj( FamilyObj( F ), FamilyObj( zero ) ) then @@ -89,9 +98,11 @@ InstallMethod( LeftModuleByGenerators, fi; #T explicit 2nd argument above! - V:= Objectify( NewType( CollectionsFamily( FamilyObj( F ) ), - IsGaussianRowSpace - and IsAttributeStoringRep ), + typ:=IsAttributeStoringRep and HasIsEmpty and IsFiniteDimensional + and IsGaussianRowSpace and IsTrivial and HasIsNonTrivial and + IsFinite; + + V:= Objectify( NewType( CollectionsFamily( FamilyObj( F ) ),typ), rec() ); SetLeftActingDomain( V, F ); SetGeneratorsOfLeftModule( V, empty ); @@ -105,7 +116,7 @@ InstallMethod( LeftModuleByGenerators, "for division ring, matrix over it, and row vector", [ IsDivisionRing, IsMatrix, IsRowVector ], function( F, mat, zero ) - local V; + local V,typ; # Check whether this method is the right one. if not IsElmsColls( FamilyObj( F ), FamilyObj( mat ) ) then @@ -113,20 +124,29 @@ InstallMethod( LeftModuleByGenerators, fi; #T explicit 2nd argument above! + typ:=IsAttributeStoringRep and HasIsEmpty and IsFiniteDimensional; if ForAll( mat, row -> IsSubset( F, row ) ) then - V:= Objectify( NewType( FamilyObj( mat ), - IsGaussianRowSpace - and IsAttributeStoringRep ), - rec() ); + typ:=typ and IsGaussianRowSpace; + else + typ:=typ and IsVectorSpace and IsRowModule and IsNonGaussianRowSpace; + fi; + + if Length(mat)>0 and ForAny(mat,x->not IsZero(x)) then + typ:=typ and HasIsTrivial and IsNonTrivial; else - V:= Objectify( NewType( FamilyObj( mat ), - IsVectorSpace - and IsNonGaussianRowSpace - and IsRowModule - and IsAttributeStoringRep ), - rec() ); + typ:=typ and IsTrivial and HasIsNonTrivial; fi; + if HasIsFinite(F) then + if IsFinite(F) then + typ:=typ and IsFinite; + else + typ:=typ and HasIsFinite; # i.e. not finite + fi; + fi; + + V:= Objectify( NewType( FamilyObj( mat ), typ), rec() ); + SetLeftActingDomain( V, F ); SetGeneratorsOfLeftModule( V, AsList( mat ) ); SetZero( V, zero ); diff --git a/tst/testbugfix/00005.tst b/tst/testbugfix/00005.tst index eac0dfe58c..c86e494204 100644 --- a/tst/testbugfix/00005.tst +++ b/tst/testbugfix/00005.tst @@ -15,4 +15,4 @@ gap> G:=GroupByGenerators( [ [ [ 0, -1, 0, 0 ], [ 1, 0, 0, 0 ], Group([ [ [ 0, -1, 0, 0 ], [ 1, 0, 0, 0 ], [ 0, 0, 0, -1 ], [ 0, 0, 1, 0 ] ] ]) gap> Centralizer(N,G); - + diff --git a/tst/testinstall/algmat.tst b/tst/testinstall/algmat.tst index ce3f21e58b..8691d3c40a 100644 --- a/tst/testinstall/algmat.tst +++ b/tst/testinstall/algmat.tst @@ -256,8 +256,7 @@ gap> n:= NullAlgebra( GF(3) ); gap> Dimension( n ); 0 -gap> b:= Basis( n ); -SemiEchelonBasis( , [ ] ) +gap> b:= Basis( n );; gap> BasisVectors( b ); [ ] gap> zero:= Zero( n ); diff --git a/tst/testinstall/coll.tst b/tst/testinstall/coll.tst index f03249a52b..89168d1bc8 100644 --- a/tst/testinstall/coll.tst +++ b/tst/testinstall/coll.tst @@ -48,12 +48,13 @@ gap> List(props, p -> p(M0)); gap> N1:=Magma([[[1,0],[0,0]]]);; gap> ForAll(props, prop -> not Tester(prop)(N1)); true -gap> Size(N1); -1 -gap> ForAll(props, prop -> Tester(prop)(N1)); -true -gap> List(props, p -> p(N1)); -[ false, true, false, true ] + +#gap> Size(N1); +#1 +#gap> ForAll(props, prop -> Tester(prop)(N1)); +#true +#gap> List(props, p -> p(N1)); +#[ false, true, false, true ] # ... immediate methods for a collection which knows its size, # applied to collection with size greater than 1 @@ -97,13 +98,11 @@ Error, cannot test whether contains the family of its elements # Size # -# immediate method for collections knowing they are infinite +## method for collections knowing they are infinite gap> c2:=ConjugacyClass(F, F.1);; gap> HasSize(c2); false gap> SetIsFinite(c2, false); -gap> HasSize(c2); -true gap> Size(c2); infinity diff --git a/tst/testinstall/semigrp.tst b/tst/testinstall/semigrp.tst index 7b3d53e5c7..37ea869e07 100644 --- a/tst/testinstall/semigrp.tst +++ b/tst/testinstall/semigrp.tst @@ -376,7 +376,7 @@ gap> GeneratorsOfInverseSemigroup(S); gap> GeneratorsOfInverseMonoid(S); [ ] gap> S := Group(IdentityTransformation); - + gap> GeneratorsOfSemigroup(S); [ IdentityTransformation ] gap> GeneratorsOfMonoid(S); @@ -474,12 +474,11 @@ true gap> Semigroup(Idempotents(S)) = S; true -# test the methods for Random +# test the methods for Random, but do not test for the values of random +# elements gap> S := FreeSemigroup(3);; -gap> Random(S); -s1*s2 -gap> Random(GlobalRandomSource, S); -s3*s2^2 +gap> Random(S);; +gap> Random(GlobalRandomSource, S);; #T# Test DisplaySemigroup gap> DisplaySemigroup(FullTransformationSemigroup(1)); diff --git a/tst/testinstall/semitran.tst b/tst/testinstall/semitran.tst index a76324e36a..a3dae32917 100644 --- a/tst/testinstall/semitran.tst +++ b/tst/testinstall/semitran.tst @@ -141,7 +141,7 @@ gap> S := Group(Transformation([2,1,3])); gap> DegreeOfTransformationSemigroup(S); 2 gap> S := Group(IdentityTransformation); - + gap> GeneratorsOfGroup(S); [ IdentityTransformation ] gap> S := Semigroup(IdentityTransformation); From e8fa2a58f0797b0faa05467ff8670076ac454d4c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 30 May 2018 15:54:54 +0200 Subject: [PATCH 2/3] Add some more true implications --- lib/coll.gd | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/coll.gd b/lib/coll.gd index 085d105daa..73f9ea5fcf 100644 --- a/lib/coll.gd +++ b/lib/coll.gd @@ -1415,9 +1415,10 @@ InstallFactorMaintenance( IsTrivial, ## DeclareProperty( "IsNonTrivial", IsCollection ); -# true methods to avoid immediate methods -InstallTrueMethod(HasIsTrivial,IsNonTrivial); -InstallTrueMethod(HasIsNonTrivial,IsTrivial); +InstallTrueMethod( IsNonTrivial, IsEmpty ); +InstallTrueMethod( HasIsTrivial, IsNonTrivial ); +InstallTrueMethod( HasIsEmpty, IsTrivial ); +InstallTrueMethod( HasIsNonTrivial, IsTrivial ); ############################################################################# @@ -1451,6 +1452,7 @@ InstallFactorMaintenance( IsFinite, IsCollection and IsFinite, IsObject, IsCollection ); InstallTrueMethod( IsFinite, IsTrivial ); +InstallTrueMethod( IsFinite, IsEmpty ); ############################################################################# From 59372d401bdbd70998a168e33885ef71a5677267 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 30 May 2018 16:06:57 +0200 Subject: [PATCH 3/3] Take advantage of implications to simplify some code --- lib/coll.gi | 2 +- lib/grp.gi | 7 +++---- lib/grpmat.gi | 4 +--- lib/grppc.gi | 5 +---- lib/modulrow.gi | 4 ++-- lib/vspcrow.gi | 12 +++++------- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/lib/coll.gi b/lib/coll.gi index f788cf5b26..f55867e621 100644 --- a/lib/coll.gi +++ b/lib/coll.gi @@ -3079,7 +3079,7 @@ local filt; fi; return; fi; - if sz=0 then filt:=IsEmpty and IsNonTrivial; # IsNonTrivial hold + if sz=0 then filt:=IsEmpty; elif sz=1 then filt:=IsTrivial; elif sz=infinity then filt:=IsNonTrivial and HasIsFinite; else filt:=IsNonTrivial and IsFinite; diff --git a/lib/grp.gi b/lib/grp.gi index 96f5b9bd18..86999c97ce 100644 --- a/lib/grp.gi +++ b/lib/grp.gi @@ -4316,12 +4316,12 @@ function(fam,filt,gens,id,isgroup) fi; if id<>fail then # cannot do identity in magma if ForAny(gens,x->x<>id) then - filt:=filt and HasIsTrivial and IsNonTrivial; + filt:=filt and IsNonTrivial; if isgroup and Length(gens)<=1 then # cyclic not for magmas filt:=filt and IsCyclic; fi; else - filt:=filt and IsTrivial and HasIsNonTrivial; + filt:=filt and IsTrivial; fi; fi; elif isgroup and Length(gens)<=1 then # cyclic not for magmas @@ -4379,8 +4379,7 @@ local G,fam,typ; fam:= CollectionsFamily( FamilyObj( id ) ); typ:=IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses and HasOne and IsTrivial and - HasIsEmpty and HasIsNonTrivial; + and HasGeneratorsOfMagmaWithInverses and HasOne and IsTrivial; typ:=NewType(fam,typ); G:= rec(); diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 9caaeecb7d..00d0778691 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -868,9 +868,7 @@ local G,fam,typ,f; if not IsFinite(gens) then TryNextMethod(); fi; typ:=MakeGroupyType(FamilyObj([id]), IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses and IsFinitelyGeneratedGroup - and HasIsEmpty and IsFinite and HasOne - and IsTrivial and HasIsNonTrivial, + and HasGeneratorsOfMagmaWithInverses and HasOne and IsTrivial, gens,id,true); f:=DefaultScalarDomainOfMatrixList([id]); diff --git a/lib/grppc.gi b/lib/grppc.gi index ad1a10f292..e4018118f0 100644 --- a/lib/grppc.gi +++ b/lib/grppc.gi @@ -412,10 +412,7 @@ local G,fam,typ,pcgs; # pc groups are always finite and gens is finite. typ:=IsGroup and IsAttributeStoringRep - and HasGeneratorsOfMagmaWithInverses and HasOne - and IsFinite and IsFinitelyGeneratedGroup - and IsTrivial and HasIsNonTrivial - and HasIsEmpty and IsSolvableGroup + and HasGeneratorsOfMagmaWithInverses and HasOne and IsTrivial and HasFamilyPcgs and HasHomePcgs and HasGeneralizedPcgs; typ:=NewType(fam,typ); diff --git a/lib/modulrow.gi b/lib/modulrow.gi index efc9d07a15..546be4f133 100644 --- a/lib/modulrow.gi +++ b/lib/modulrow.gi @@ -35,9 +35,9 @@ local M,typ; # the free module record, result fi; if n=0 then - typ:=typ and IsTrivial and HasIsNonTrivial and IsFinite; + typ:=typ and IsTrivial; else - typ:=typ and HasIsTrivial and IsNonTrivial; + typ:=typ and IsNonTrivial; fi; if n<>infinity and HasIsFinite(R) and IsFinite(R) then diff --git a/lib/vspcrow.gi b/lib/vspcrow.gi index 80f5f9b78a..df699b2ad7 100644 --- a/lib/vspcrow.gi +++ b/lib/vspcrow.gi @@ -64,9 +64,9 @@ InstallMethod( LeftModuleByGenerators, fi; if Length(mat)>0 and ForAny(mat,x->not IsZero(x)) then - typ:=typ and HasIsTrivial and IsNonTrivial; + typ:=typ and IsNonTrivial; else - typ:=typ and IsTrivial and HasIsNonTrivial; + typ:=typ and IsTrivial; fi; if HasIsFinite(F) then @@ -98,9 +98,7 @@ InstallMethod( LeftModuleByGenerators, fi; #T explicit 2nd argument above! - typ:=IsAttributeStoringRep and HasIsEmpty and IsFiniteDimensional - and IsGaussianRowSpace and IsTrivial and HasIsNonTrivial and - IsFinite; + typ:=IsAttributeStoringRep and IsGaussianRowSpace and IsTrivial; V:= Objectify( NewType( CollectionsFamily( FamilyObj( F ) ),typ), rec() ); @@ -132,9 +130,9 @@ InstallMethod( LeftModuleByGenerators, fi; if Length(mat)>0 and ForAny(mat,x->not IsZero(x)) then - typ:=typ and HasIsTrivial and IsNonTrivial; + typ:=typ and IsNonTrivial; else - typ:=typ and IsTrivial and HasIsNonTrivial; + typ:=typ and IsTrivial; fi; if HasIsFinite(F) then