Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 A B C Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

8 Orbits, stabilisers and actions
 8.1 Orbits
 8.2 Stabilisers
 8.3 Actions and nice monomorphisms revisited

8 Orbits, stabilisers and actions

8.1 Orbits

GAP provides generic functionality to compute orbits. These functions are, generally spoken, applicable to the groups implemented in FinInG, combined with the appropriate action functions. However, the generic functions applied in such situations are rather time consuming. FinInG therefore provides alternative functions to compute orbits.

8.1-1 FiningOrbit
‣ FiningOrbit( g, obj, act )( operation )

Returns: The orbit of the object obj under the action act of the group g.

The argument obj is either a subspace of a projective space, then combined with the action function OnProjSubspaces, or a set of elements of a projective space, then combined with the action function OnSetsProjSubspaces. The group g is a subgroup of a collineation group of a projective space. In both cases the action function computes the action of el under the group element g.

gap> ps := ParabolicQuadric(6,3);
Q(6, 3)
gap> g := CollineationGroup(ps);
PGammaO(7,3)
gap> pg := PG(6,3);
ProjectiveSpace(6, 3)
gap> s := First(Solids(pg),t -> TypeOfSubspace(ps,t) = "elliptic" );
<a solid in ProjectiveSpace(6, 3)>
gap> orbit := FiningOrbit(g,s,OnProjSubspaces);
<closed orbit, 265356 points>
gap> time;
33555
 

The second example shows the possible use of FiningOrbit in combination with the action function OnSetsProjSubspaces. Please note that this variant is probably not the most efficient way to compute all elliptic quadrics contained in the parabolic quadric \(ps\). Experiments show that for \(q=5\) the second variant takes an unreasonable amount of time. Also note that the second argument el must be a set (and therefore it might be necessary to apply Set on a collection of elements).

gap> ps := ParabolicQuadric(4,3);
Q(4, 3)
gap> g := CollineationGroup(ps);
PGammaO(5,3)
gap> pg := PG(4,3);
ProjectiveSpace(4, 3)
gap> s := First(Solids(pg),t -> TypeOfSubspace(ps,t) = "elliptic" );
<a solid in ProjectiveSpace(4, 3)>
gap> orbit1 := FiningOrbit(g,s,OnProjSubspaces);
<closed orbit, 36 points>
gap> time;
9
gap> spts := Filtered(Points(s),s->s in ps);
[ <a point in ProjectiveSpace(4, 3)>, <a point in ProjectiveSpace(4, 3)>, 
  <a point in ProjectiveSpace(4, 3)>, <a point in ProjectiveSpace(4, 3)>, 
  <a point in ProjectiveSpace(4, 3)>, <a point in ProjectiveSpace(4, 3)>, 
  <a point in ProjectiveSpace(4, 3)>, <a point in ProjectiveSpace(4, 3)>, 
  <a point in ProjectiveSpace(4, 3)>, <a point in ProjectiveSpace(4, 3)> ]
gap> orbit2 := FiningOrbit(g,Set(spts),OnSetsProjSubspaces);
<closed orbit, 36 points>
gap> time;
18
 

8.1-2 FiningOrbits
‣ FiningOrbits( g, set, act )( operation )
‣ FiningOrbits( g, coll )( operation )

Returns: The orbits of the group g on set under the action of act.

The set is a set of elements of a projective space, the group g is a subgroup of the collineation group of a projective space, and act is the function OnProjSubspaces. If coll is a collection of elements of a projective space (i.e. not a list or set, but and object representing the collection of elements of a given type, such as Lines(PG(3,4))), then the second versions returns the orbits of g on the elements of coll under the action OnProjSubspaces.

gap> ps := HermitianPolarSpace(3,9);
H(3, 3^2)
gap> g := CollineationGroup(ps);
PGammaU(4,3^2)
gap> FiningOrbits(g,Lines(PG(3,9)));
75%..98%..100%..[ <closed orbit, 5670 points>, <closed orbit, 1680 points>, 
  <closed orbit, 112 points> ]
gap> FiningOrbits(g,Planes(PG(3,9)));
65%..100%..[ <closed orbit, 540 points>, <closed orbit, 280 points> ]
gap> ps := ParabolicQuadric(2,5);
Q(2, 5)
gap> g := CollineationGroup(ps);
PGammaO(3,5)
gap> pts := Filtered(Points(PG(2,5)),x->not x in ps);;
gap> Length(pts);
25
gap> FiningOrbits(g,Points(PG(2,5)));
48%..67%..100%..[ <closed orbit, 15 points>, <closed orbit, 6 points>, 
  <closed orbit, 10 points> ]
gap> FiningOrbits(g,pts,OnProjSubspaces);
60%..100%..[ <closed orbit, 15 points>, <closed orbit, 10 points> ]
 

8.1-3 FiningOrbitsDomain
‣ FiningOrbitsDomain( g, coll, act )( operation )

Returns: The orbits of the group g on a collection coll under the action of act.

The argument coll must be an object in the category IsElementsOfIncidenceGeometry, the argument g can be any group, acting on the elements of coll through a suitable action function act. This operation is inspired by the GAP operation OrbitsDomain. It computes the orbits of the group g on the set of elements in coll assuming that the set of elements of coll is closed under that action of g. There is no check whether the assumption is correct, so this operation should typically be used when it is known that the assumption is correct. The operation is generic in the sense that it can be used for different types of incidence geometries as long as the triple arguments consist of a suitable action of g on the elements of coll. In general, if the assumption is correct, this operation will be faster than FiningOrbits.

gap> pg := PG(7,2);
ProjectiveSpace(7, 2)
gap> group:=CollineationGroup(pg);
The FinInG collineation group PGL(8,2)
gap> syl127:=SylowSubgroup(group,127);
<projective collineation group of size 127>
gap> orbits := FiningOrbits(syl127,AsList(Solids(pg)));;
1%..2%..3%..4%..5%..6%..7%..8%..9%..10%..11%..12%..13%..14%..15%..16%..17%..18%..19%..20%..21%..
22%..23%..24%..25%..26%..27%..28%..29%..30%..31%..32%..33%..34%..35%..36%..37%..38%..39%..40%..41%
..42%..43%..44%..45%..46%..47%..48%..49%..50%..51%..52%..53%..54%..55%..56%..57%..58%..59%..60%..
61%..62%..63%..64%..65%..66%..67%..68%..69%..70%..71%..72%..73%..74%..75%..76%..77%..78%..79%..
80%..81%..82%..83%..84%..85%..86%..87%..88%..89%..90%..91%..92%..93%..94%..95%..96%
..97%..98%..99%..100%..
gap> time;
212661
gap> Collected(List(orbits,x->Length(x)));
[ [ 127, 1581 ] ]
gap> orbits := FiningOrbitsDomain(syl127,Solids(pg),OnProjSubspaces);;
gap> time;
26529
gap> Collected(List(orbits,x->Length(x)));
[ [ 127, 1581 ] ]
gap> orbits := OrbitsDomain(syl127,Solids(pg),OnProjSubspaces);;
gap> time;
35506
gap> Collected(List(orbits,x->Length(x)));
[ [ 127, 1581 ] ]
gap> ag := AG(4,5);
AG(4, 5)
gap> h := Random(CollineationGroup(ag));
< a collineation: <cmat 5x5 over GF(5,1)>, F^0>
gap> group := Group(h);
<projective collineation group with 1 generators>
gap> orbits := FiningOrbitsDomain(group,Points(ag),OnAffineSubspaces);
[ <closed orbit, 624 points>, <closed orbit, 1 points> ]
 

8.2 Stabilisers

The GAP function Stabilizer is a generic function to compute stabilisers of one object (or sets or tuples etc. of objects) under a group, using a specified action function. This generic function can be used together with the in FinInG implemented groups and elements of geometries. However, computing time can be very long, already in small geometries.

gap> ps := PG(3,8);
ProjectiveSpace(3, 8)
gap> g := CollineationGroup(ps);
The FinInG collineation group PGammaL(4,8)
gap> p := Random(Points(ps));
<a point in ProjectiveSpace(3, 8)>
gap> Stabilizer(g,p,OnProjSubspaces);
<projective collineation group of size 177223237632 with 2 generators>
gap> time;
10026
gap> line := Random(Lines(ps));
<a line in ProjectiveSpace(3, 8)>
gap> Stabilizer(g,line,OnProjSubspaces);
<projective collineation group of size 21849440256 with 2 generators>
gap> time;
78126
 

The packages GenSS and orb required by FinInG provide efficient operations to compute stabilisers, and FinInG provides functionality to use these operations for the particular groups and (elements) of geometries.

8.2-1 FiningStabiliser
‣ FiningStabiliser( g, el )( operation )

Returns: The subgroup of g stabilising the element el

The argument g is a group of collineations acting on the element el, being a subspace of a projective space (and hence, all elements of a Lie geometry are allowed as second argument). This operation relies on the GenSS operation Stab.

gap> ps := PG(5,4);
ProjectiveSpace(5, 4)
gap> g := SpecialHomographyGroup(ps);
The FinInG PSL group PSL(6,4)
gap> p := Random(Points(ps));
<a point in ProjectiveSpace(5, 4)>
gap> FiningStabiliser(g,p);
<projective collineation group of size 264696069567283200 with 2 generators>
gap> line := Random(Lines(ps));
<a line in ProjectiveSpace(5, 4)>
gap> FiningStabiliser(g,line);
<projective collineation group of size 3881174040576000 with 3 generators>
gap> plane := Random(Planes(ps));
<a plane in ProjectiveSpace(5, 4)>
gap> FiningStabiliser(g,plane);
#I  Have 106048 points.
#I  Have 158748 points.
<projective collineation group of size 958878292377600 with 2 generators>
gap> ps := HyperbolicQuadric(5,5);
Q+(5, 5)
gap> g := IsometryGroup(ps);
PGO(1,6,5)
gap> p := Random(Points(ps));
<a point in Q+(5, 5)>
gap> FiningStabiliser(g,p);
<projective collineation group of size 36000000 with 3 generators>
gap> line := Random(Lines(ps));
<a line in Q+(5, 5)>
gap> FiningStabiliser(g,line);
<projective collineation group of size 6000000 with 3 generators>
gap> plane := Random(Planes(ps));
<a plane in Q+(5, 5)>
gap> FiningStabiliser(g,plane);
<projective collineation group of size 93000000 with 2 generators>
gap> h := SplitCayleyHexagon(3);
H(3)
gap> g := CollineationGroup(h);
#I  for Split Cayley Hexagon
#I  Computing nice monomorphism...
#I  Found permutation domain...
G_2(3)
gap> p := Random(Points(h));
<a point in H(3)>
gap> FiningStabiliser(g,p);
<projective collineation group of size 11664 with 2 generators>
gap> line := Random(Lines(h));
<a line in H(3)>
gap> FiningStabiliser(g,line);
<projective collineation group of size 11664 with 2 generators>
 

8.2-2 FiningStabiliserOrb
‣ FiningStabiliserOrb( g, el )( operation )

Returns: The subgroup of g stabilising the element el

The argument g is a group of collineations acting on the element el, being a subspace of a projective space (and hence, all elements of a Lie geometry are allowed as second argument). This operation relies on some particular orb functionality.

gap> ps := PG(5,4);
ProjectiveSpace(5, 4)
gap> g := SpecialHomographyGroup(ps);
The FinInG PSL group PSL(6,4)
gap> p := Random(Points(ps));
<a point in ProjectiveSpace(5, 4)>
gap> FiningStabiliserOrb(g,p);
<projective collineation group with 15 generators>
gap> line := Random(Lines(ps));
<a line in ProjectiveSpace(5, 4)>
gap> FiningStabiliserOrb(g,line);
<projective collineation group with 15 generators>
gap> plane := Random(Planes(ps));
<a plane in ProjectiveSpace(5, 4)>
gap> FiningStabiliserOrb(g,plane);
<projective collineation group with 15 generators>
gap> ps := HyperbolicQuadric(5,5);
Q+(5, 5)
gap> g := IsometryGroup(ps);
PGO(1,6,5)
gap> p := Random(Points(ps));
<a point in Q+(5, 5)>
gap> FiningStabiliserOrb(g,p);
<projective collineation group with 15 generators>
gap> line := Random(Lines(ps));
<a line in Q+(5, 5)>
gap> FiningStabiliserOrb(g,line);
<projective collineation group with 15 generators>
gap> plane := Random(Planes(ps));
<a plane in Q+(5, 5)>
gap> FiningStabiliserOrb(g,plane);
<projective collineation group with 15 generators>
gap> h := SplitCayleyHexagon(3);
H(3)
gap> g := CollineationGroup(h);
#I  for Split Cayley Hexagon
#I  Computing nice monomorphism...
#I  Found permutation domain...
G_2(3)
gap> p := Random(Points(h));
<a point in H(3)>
gap> FiningStabiliserOrb(g,p);
<projective collineation group with 15 generators>
gap> line := Random(Lines(h));
<a line in H(3)>
gap> FiningStabiliserOrb(g,line);
<projective collineation group with 15 generators>
 

A small example shows the difference in computing time. Clearly the FiningStabiliserOrb is the fastest way to compute stabilizers of one element.

gap> ps := PG(3,8);
ProjectiveSpace(3, 8)
gap> g := CollineationGroup(ps);
The FinInG collineation group PGammaL(4,8)
gap> p := Random(Points(ps));
<a point in ProjectiveSpace(3, 8)>
gap> g1 := Stabilizer(g,p);
<projective collineation group of size 177223237632 with 2 generators>
gap> time;
9576
gap> g2 := FiningStabiliser(g,p);
<projective collineation group of size 177223237632 with 2 generators>
gap> time;
244
gap> g3 := FiningStabiliserOrb(g,p);
<projective collineation group with 15 generators>
gap> time;
46
gap> g1=g2;
true
gap> g2=g3;
true
 

8.2-3 FiningSetwiseStabiliser
‣ FiningSetwiseStabiliser( g, els )( operation )

Returns: The subgroup of g stabilising the set els

The argument g is a group of collineations acting on the element el, being a subspace of a projective space (and hence, all elements of a Lie geometry are allowed as second argument). The argument els is a set of elements of the same type of the same Lie geometry, the elements are all in the category IsSubspaceOfProjectiveSpace. The underlying action function is assumed to be OnProjSubspaces

gap> ps := HyperbolicQuadric(5,5);                   
Q+(5, 5)
gap> g := IsometryGroup(ps);
PGO(1,6,5)
gap> plane1 := Random(Planes(ps));
<a plane in Q+(5, 5)>
gap> plane2 := Random(Planes(ps));
<a plane in Q+(5, 5)>
gap> FiningSetwiseStabiliser(g,Set([plane1,plane2]));
#I  Computing adjusted stabilizer chain...
<projective collineation group with 4 generators>
 

Computing the setwise stabiliser under a group is also possible using Stabilizer. But, not surprisingly, the computing time can be very long.

gap> ps := PG(3,4);
ProjectiveSpace(3, 4)
gap> p := Random(Points(ps));
<a point in ProjectiveSpace(3, 4)>
gap> q := Random(Points(ps));
<a point in ProjectiveSpace(3, 4)>
gap> g := CollineationGroup(ps);
The FinInG collineation group PGammaL(4,4)
gap> Stabilizer(g,Set([p,q]),OnSets);
<projective collineation group of size 552960 with 5 generators>
gap> time;
10440
 

The package GenSS provides an efficient operations to compute setwise stabilisers. This is why FinInG provides functionality, such as FiningSetwiseStabiliser, to use these GenSS operations for the particular groups and (elements) of geometries. A small example shows the difference in computing time.

gap> ps := ParabolicQuadric(4,4);
Q(4, 4)
gap> g := CollineationGroup(ps);
PGammaO(5,4)
gap> l1 := Random(Lines(ps));
<a line in Q(4, 4)>
gap> l2 := Random(Lines(ps));
<a line in Q(4, 4)>
gap> g1 := Stabilizer(g,Set([l1,l2]),OnSets);
<projective collineation group of size 2304 with 6 generators>
gap> time;
2633
gap> g2 := FiningSetwiseStabiliser(g,Set([l1,l2]));
#I  Computing adjusted stabilizer chain...
<projective collineation group with 5 generators>
gap> time;
70
gap> g1=g2;
true
 

For subspaces of projective spaces we can be even more efficient by writing down generators of the stabiliser and then return the generated subgroup.

8.2-4 StabiliserGroupOfSubspace
‣ StabiliserGroupOfSubspace( sub )( operation )

Returns: The subgroup of the collineation group of AmbientSpace(sub) stabilising the subspace sub

The argument sub is a subspace of a projective space.

8.2-5 ProjectiveStabiliserGroupOfSubspace
‣ ProjectiveStabiliserGroupOfSubspace( sub )( operation )

Returns: The subgroup of the projectivity group of AmbientSpace(sub) stabilising the subspace sub

The argument sub is a subspace of a projective space.

8.2-6 SpecialProjectiveStabiliserGroupOfSubspace
‣ SpecialProjectiveStabiliserGroupOfSubspace( sub )( operation )

Returns: The subgroup of the special projectivity group of AmbientSpace(sub) stabilising the subspace sub

The argument sub is a subspace of a projective space.

gap> pg:=ProjectiveSpace(5,9);            
ProjectiveSpace(5, 9)
gap> sub:=RandomSubspace(pg,2);     
<a plane in ProjectiveSpace(5, 9)>
gap> coll:=StabiliserGroupOfSubspace(sub); time;                                
<projective collineation group of size 11173786189009966655078400 with 
6 generators>
10
gap> computed:=FiningStabiliserOrb(CollineationGroup(pg),sub); 
<projective collineation group with 15 generators>
gap> time;
34923
gap> coll = computed;
true
gap> proj:=ProjectiveStabiliserGroupOfSubspace(sub); 
<projective collineation group of size 5586893094504983327539200 with 
5 generators>
gap> time;
2
gap> FiningStabiliserOrb(ProjectivityGroup(pg),sub)=proj; 
true
gap> time;      
116113
gap> specproj:=SpecialProjectiveStabiliserGroupOfSubspace(sub); 
<projective collineation group of size 2793446547252491663769600 with 
5 generators>
gap> time;
2
gap> specproj = FiningStabiliserOrb(SpecialProjectivityGroup(pg),sub); 
true
gap> time;
65564
 

8.3 Actions and nice monomorphisms revisited

GAP provides generic functions to compute action homomorphisms and their images for arbitrary groups. These functions are applicable on the projective groups implemented in FinInG.

8.3-1 Action functions
‣ OnProjSubspaces( el, g )( function )
‣ OnProjSubspacesExtended( el, g )( function )
‣ OnSetsProjSubspaces( set, g )( function )

Returns: a element of a Lie geometry

Let el be an element of any Lie geometry, and g an element of a projective group acting on the elements of the ambient Lie geometry of el. Then then OnProjSubspaces will return simply the image of el under g. When g is an element of the correlation/collineation group of a projective space, OnProjSubspacesExtended returns the image of el under g. Finally, when set is a set of elements of a Lie geometry, OnSetsProjSubspaces returns the set of images under g. OnProjSubspaces is also explained in 5.8-1, OnProjSubspacesExtended is also explained in 5.8-3.

8.3-2 Generic GAP functions
‣ ActionHomomorphism( g, S, act )( operation )
‣ Action( g, S, act )( operation )

g is a projective group, S is a set or a collection of elements, act is an action function. Action simply returns Image(hom), if hom is the result of ActionHomomorphism. The examples are self-explanatory.

gap> pg := PG(2,3);
ProjectiveSpace(2, 3)
gap> conic := Set(Points(ParabolicQuadric(2,3)));;
gap> coll := CollineationGroup(pg);
The FinInG collineation group PGL(3,3)
gap> orb := Orbit(coll,conic,OnSetsProjSubspaces);;
gap> Length(orb);
234
gap> hom := ActionHomomorphism(coll,orb,OnSetsProjSubspaces);
<action homomorphism>
gap> perm := Image(hom);
<permutation group with 2 generators>
gap> Order(perm);
5616
gap> NrMovedPoints(perm);
234
gap> ps := SymplecticSpace(5,2);
W(5, 2)
gap> coll := CollineationGroup(ps);
PGammaSp(6,2)
gap> perm := Action(coll,Lines(ps),OnProjSubspaces);
<permutation group with 4 generators>
gap> NrMovedPoints(perm);
315

A nice monomorphism of a group \(G\) is roughly just a permutation representation of \(G\) on a suitable action domain. An easy example is the permutation action of the full collineation group of a projective space on its points.

8.3-3 NiceMonomorphism
‣ NiceMonomorphism( group )( attribute )

Returns: A group homomorphism

This is a generic GAP function, and returns a homomorphism to a "better" representation.

8.3-4 NiceObject
‣ NiceObject( group )( attribute )

Returns: A permutation group

group is a projective group. The object this operation returns is actually equivalent with Image(NiceMonomorphism(group)).

8.3-5 Different behaviour for different collineation groups

For the different Lie geometries implemented in FinInG, nicemonomorphisms are (necessarily) treated in a different way. As the aim of a nicemonomorphism of group \(G\) is to provide a permutation representation, such that efficient algorithms for permutation groups become available for certain operations applicable on \(G\), clearly the efficiency will be increased if the degree of the permutation representation is as small as possible.

For the collineation group, projectivity group and special projectivity group of a projective space, it is clear that the smallest degree permutation representation is the action of the group on the projective points. In principle, one could also consider the action on the hyperplanes. For the collineation group, similarity group and isometry group of a classical polar space, in most cases, the smallest degree permutation representation is the action on the points. A notorious exception to this is the hermitian polar space in three dimensions, of which the number of lines is smaller than the number of points, and hence of which the smallest degree permutation representation is the action of the group on the lines. When constructing a collineation group (or (special) projectivity group) of a projective space, the nicemonomorphism is not computed. It is only computed when needed. The reason is that from the underlying field and dimension, the underlying projective space can be determined at any time, and hence the smallest degree representation can be computed. For the collineation groups (and similarity and isometry groups) of classical polar spaces, this behaviour is different. Indeed, given a group of collineations, from the underlying field and dimension, the original polar space can not be determined. Of course one could consider the action on the points of the underlying projective space, but typically the number of points of a classical polar space is much smaller than the number points of the underlying projective space. This explains why, currently, a nice monomorphism is computed at the moment a collineation group of a classical polar space is computed. As a consequence, just asking the collineation group of a polar space can be time consuming.

gap> g := CollineationGroup(PG(5,9));
The FinInG collineation group PGammaL(6,9)
gap> time;
28
gap> HasNiceMonomorphism(g);
false
gap> h := CollineationGroup(EllipticQuadric(5,9));
PGammaO-(6,9)
gap> time;
1584
gap> HasNiceMonomorphism(h);
true

8.3-6 SetParent
‣ SetParent( group )( operation )

Assume that \(G\) is a group of collineations. As mentioned already, from the underlying field and dimension, only the underlying projective space can be determined. An operation like Order requires a nice monomorphism, so for an arbitrary group \(G\), the action on the points of the underlying projective space will be computed, which can be time consuming for large projective spaces. However, if it is known that \(G\) is a subgroup of another collineation group \(H\), this group \(H\) can be set as a parent group for \(G\). If a nice monomorphism is available for \(H\), it will become available for \(G\). In the example we construct the collineation group of the hermitian polar space \(H(3,81)\). As explained, a nice monomorphism is computed upon construction. Then construct a group generated by two random elements of this collineation group of \(H(3,81)\), and compute its order. Without further information, it will be assumed by the system that this new group is a subgroup of the collineation group of \(PG(3,81)\), and a nice monomorphism will be computed through this group. In the second part we set the parent group as the collineation group of \(H(3,81)\), and compute the order again. Compare the different timings.

gap> ps := HermitianPolarSpace(3,81);
H(3, 9^2)
gap> group := CollineationGroup(ps);
PGammaU(4,9^2)
gap> time;
2219
gap> g := Random(group);
< a collineation: <cmat 4x4 over GF(3,4)>, F^27>
gap> h := Random(group);
< a collineation: <cmat 4x4 over GF(3,4)>, F^3>
gap> group2 := Group([g,h]);
<projective collineation group with 2 generators>
gap> HasNiceMonomorphism(group2);
false
gap> Order(group2);
407194345728000
gap> time;
371559
gap> HasNiceMonomorphism(group2);
true
gap> NrMovedPoints(NiceObject(group2));
538084
gap> Size(Points(PG(3,81)));
538084
gap> group2 := Group([g,h]);
<projective collineation group with 2 generators>
gap> SetParent(group2,group);
gap> HasNiceMonomorphism(group2);
true
gap> HasNiceObject(group2);
false
gap> Order(group2);
407194345728000
gap> time;
888
gap> HasNiceObject(group2);
true
gap> NrMovedPoints(NiceObject(group2));
7300
gap> Size(Lines(ps));
7300

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 A B C Bib Ind

generated by GAPDoc2HTML