Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/fining/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 27.6.2023 mit Größe 54 kB image not shown  

Quelle  subgeometries.gi   Sprache: unbekannt

 
##############################################################################
##
##  subgeometries.gi        FinInG package
##                                                              John Bamberg
##                                                              Anton Betten
##                                                              Jan De Beule
##                                                             Philippe Cara
##                                                            Michel Lavrauw
##                                                           Max Neunhoeffer
##
##  Copyright 2020 Colorado State University, Fort Collins
##     Università degli Studi di Padova
##     University of St. Andrews
##     University of Western Australia, Perth
##                  Vrije Universiteit Brussel
##
##
##  Implementation stuff for subgeometries of projective spaces.
##
#############################################################################

#############################################################################
# already some general comments.
# SubgeometryOfProjectiveSpaceByFrame: creates the user defined sub geometry
# starting from a frame. sub!.projectivity: projectivity mapping the canonical
# sub geometry onto the user defined one.
# sub!.sigma: collineation fixing all elements of the sub geometry.
#
#############################################################################

## View methods
#############################################################################
#O  ViewObj( <pg> )
##
InstallMethod( ViewObj,
    "for a subgeometry of a projective space",
    [ IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep ],
    function(pg)
        Print("Subgeometry PG(",pg!.dimension,", ",Size(pg!.subfield),") of ",ViewString(pg!.ambientspace));
end );

#############################################################################
#O  ViewString( <pg> )
##
InstallMethod( ViewString,
    "for a subgeometry of projective space",
    [ IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep ],
    function( pg )
    return Concatenation("Subgeometry PG(",String(pg!.dimension),", ",String(Size(pg!.subfield)),") of ",ViewString(pg!.ambientspace));
end );

## operation to check whether a list of points is a frame of the ambient geometry
# of the points.
#############################################################################
#O  IsFrameOfProjectiveSpace( <list> )
##  change 22/6: IsSomething should return true or false!
InstallMethod( IsFrameOfProjectiveSpace,
    "for a list of points",
    [ IsList ],
    function(list)
    local pg, coll, base, n, i;
    coll:=DuplicateFreeList(List(list,x->AmbientGeometry(x)));
#    coll := Collected(List(list,x->AmbientGeometry(x))); #changed AmbientSpace into AmbientGeometry.
    if Length(coll) > 1 then
        #Error("all elements in <list> lie in the same projective space");
        return false;
    else
#       pg := coll[1][1];
        pg:= coll[1];
    fi;
    coll := Collected(List(list,x->Type(x)));
    if Length(coll) > 1 then
        #Error("all elements in <list> must be points");
        return false;
    elif coll[1][1] <> 1 then
        #Error("all elements in <list> must be points");
        return false;
    fi;
    n := Length(list);
    if n <> ProjectiveDimension(pg) + 2 then
        #Error("<list> does not contain the correct number of points");
        return false;
    fi;
    for i in [1..n] do
        base := list{Difference([1..n],[i])};
        if not Span(base) = pg then
            #Error("<list> is not a frame");
            return false;
        fi;
    od;
    return true;
    end );

#############################################################################
#O  RandomFrameOfProjectiveSpace( <pg> )
#   This method returns a random frame of a projective space
##
InstallMethod( RandomFrameOfProjectiveSpace,
    "for a projective space, and a prime power",
    [ IsProjectiveSpace ],
    function(pg)
    local pts,mat,final,gauge,d,field;
    d := ProjectiveDimension(pg)+1;
    field := BaseField(pg);
    mat := RandomInvertibleMat(d,field);
    pts := List(mat,x->VectorSpaceToElement(pg,x));
    # TODO: start with the standard frame and choose a random projectivity (#ml 18 May 2020)
    gauge := Random(Points(pg));
    while not IsFrameOfProjectiveSpace(Union(pts,[gauge])) do
        gauge := Random(Points(pg));
    od;
    pts := Union(pts,[gauge]);
    return Set(pts);
    end );

## Constructor methods for subgeometries of projective spaces.
# note for the next two methods: it may look strange to put a vectorspace over
# the big field as vectorspace. But this makes sure that incidence can be
# tested between elements of the subgeometry and the ambient geometry.

#############################################################################
#O  CanonicalSubgeometryOfProjectiveSpace( <pg>, <subfield> )
#   This method requires a projective space and a subfield.
# small change on 12/9/16: we added eventually a field .projectivity in the
# returned geometry. From time to time this is useful, e.g. when comparing
# a canonical subgeometry with an arbitrary one, see e.g. code for \=
##
InstallMethod( CanonicalSubgeometryOfProjectiveSpace,
    "for a projective space, and a prime power",
    [ IsProjectiveSpace, IsField and IsFinite],
    function(pg,subfield)
    local geo, subpg, d, frame, ty, em, sigma, h, t, frob, proj;
    if IsSubgeometryOfProjectiveSpace(pg) then
        Error("recursive construction of subgeometries not (yet) possible");
    fi;
    d := ProjectiveDimension(pg);
    h := DegreeOverPrimeField(subfield);
    t := DegreeOverPrimeField(BaseField(pg));
    if not t mod h = 0 then
        Error(" <subfield> is not a subfield of the base field of <pg>");
    elif t = h then #We may consider to return an error here.
        return pg;
    fi;
    subpg := ProjectiveSpace(d,subfield);
    frame := StandardFrame(pg);
    em := NaturalEmbeddingBySubfield(subpg,pg);
    frob := FrobeniusAutomorphism(BaseField(pg))^h;
    sigma := CollineationOfProjectiveSpace(pg,frob);
    proj := CollineationOfProjectiveSpace(IdentityMat(d+1,pg!.basefield),pg!.basefield);
    geo := rec(dimension := d, basefield := pg!.basefield, subfield := subfield, ambientspace := pg, isomorphicsubgeometry := subpg, frame := frame,
        embedding := em, vectorspace := FullRowSpace(pg!.basefield, d+1), sigma := sigma, projectivity := proj );
    ty := NewType( SubgeometriesFamily,
                  IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep );
    Objectify( ty, geo );
    SetIsCanonicalSubgeometryOfProjectiveSpace(geo, true);
    SetAmbientSpace(geo, pg);
    SetDefiningFrameOfSubgeometry(geo,frame);
    #SetRankAttr(geo,d);
    return geo;
    end );

#############################################################################
#O  SubgeometryOfProjectiveSpaceByFrame( <pg>, <frame>, <subfield> )
#   It is checked whether <frame> is a frame. This operation requires
#   a projective space, a frame of this space, and a subfield.
##
InstallMethod( SubgeometryOfProjectiveSpaceByFrame,
    "for a projective space, and a prime power",
    [ IsProjectiveSpace, IsList, IsField and IsFinite],
    function(pg,frame,subfield)
    local geo, subpg, d, ty, matrix, proj, n, i, vecs, basis, coefs, em, sigma, h, t, frob, can;
    if not IsFrameOfProjectiveSpace(frame) then
        Error(" <frame> must be a frame of <pg>");
    fi;
     if IsSubgeometryOfProjectiveSpace(pg) then
        Error("recursive construction of subgeometries not (yet) possible");
    fi;
    d := ProjectiveDimension(pg);
    h := DegreeOverPrimeField(subfield);
    t := DegreeOverPrimeField(BaseField(pg));
    if not t mod h = 0 then
        Error(" <subfield> is not a subfield of the base field of <pg>");
    elif t = h then #We may consider to return an error here.
        return pg;
    fi;
    subpg := ProjectiveSpace(d,subfield);
    frob := FrobeniusAutomorphism(BaseField(pg))^h;
    if ForAll(frame,y->ForAll(Flat(y!.obj),x->x in subfield)=true) then
        can := true;
        proj := CollineationOfProjectiveSpace(IdentityMat(d+1 ,pg!.basefield),pg!.basefield);
        sigma := CollineationOfProjectiveSpace(pg,frob);
    else
        can := false;
        n:=Size(frame)-1;
        vecs:=List(frame,x->Coordinates(x));
        basis:=Basis(UnderlyingVectorSpace(Span(frame)),vecs{[1..n]});
        coefs:=Coefficients(basis,vecs[n+1]);
        matrix := List([1..n],i->coefs[i]*vecs[i]);
        proj := CollineationOfProjectiveSpace(matrix,BaseField(pg));
        sigma := proj^(-1)*CollineationOfProjectiveSpace(pg,frob)*proj;
    fi;
    em := NaturalEmbeddingBySubfield(subpg,pg);
    geo := rec(dimension := d, basefield := pg!.basefield, subfield := subfield, ambientspace := pg, isomorphicsubgeometry := subpg,
        frame := ShallowCopy(frame), embedding := em, vectorspace := FullRowSpace(pg!.basefield, d+1), sigma := sigma,
        projectivity := proj );
    ty := NewType( SubgeometriesFamily,
                  IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep );
    Objectify( ty, geo );
    SetAmbientSpace(geo, pg);
    SetIsCanonicalSubgeometryOfProjectiveSpace(geo, can);
    SetDefiningFrameOfSubgeometry(geo,frame);
    #SetRankAttr(geo,d);
    return geo;
    end );

#############################################################################
#O  CanonicalSubgeometryOfProjectiveSpace( <pg>, <q> )
#   shortcut to CanonicalSubgeometryOfProjectiveSpace( <pg>, <GF(<q>))
##
InstallMethod( CanonicalSubgeometryOfProjectiveSpace,
    "for a projective space, and a prime power",
    [ IsProjectiveSpace, IsPosInt],
    function(pg,q)
        return CanonicalSubgeometryOfProjectiveSpace(pg,GF(q));
    end );

#############################################################################
#O  SubgeometryOfProjectiveSpaceByFrame( <pg>, <frame>, <q> )
#   shortcut to SubgeometryOfProjectiveSpaceByFrame( <pg>, <frame>, <GF(<q>))
##
InstallMethod( SubgeometryOfProjectiveSpaceByFrame,
    "for a projective space, and a prime power",
    [ IsProjectiveSpace, IsList, IsPosInt],
    function(pg,frame,q)
        return SubgeometryOfProjectiveSpaceByFrame(pg,frame,GF(q));
    end );

# Basic methods for subgeometries.
#############################################################################

#############################################################################
#O  \=( <sub1>, <sub2> )
# test equality of subgeometries.
# To test equality of two subgeometries, we check whether
# (0) if there ambient space equals, if not, return false
# (1) if (0)=true, then, test equality of their subfields, if not, return false
# (2) if (1)=true, test if one of them is not canonical, if so, check whether they
#      are equal if p*q^1, p, s their respective projectivities,
#      is a collineation over the subfield,
#      note 12/9/16: checking whether all elements of mat belong to the subfield, is
#      too restrictive: we must now first divded mat by the first non-zero element!
# (3) if (2)=false, then both are canonical, and return true.
##
InstallMethod( \=,
    "for two subgeometries of a projective space",
 [ IsSubgeometryOfProjectiveSpace, IsSubgeometryOfProjectiveSpaceRep ],
    function(sub1,sub2)
    local proj1, proj2, res, mat, nz;
    if not AmbientSpace(sub1) = AmbientSpace(sub2) then
        return false;
    elif not sub1!.subfield = sub2!.subfield then
        return false;
    elif IsCanonicalSubgeometryOfProjectiveSpace(sub1) = false or IsCanonicalSubgeometryOfProjectiveSpace(sub2) = false then
        proj1 := sub1!.projectivity;
        proj2 := sub2!.projectivity;
        res := proj1 * proj2^(-1);
        mat := MatrixOfCollineation(res);
        #return ForAll(Flat(mat), x->x in sub1!.subfield); # too restrictive!
        nz := First(Flat(mat),x->x <> Zero(sub1!.basefield));
        return ForAll(Flat(mat), x->x/nz in sub1!.subfield);
    else
        return true;
    fi;
    end );

# The next two methods are necessary, since a subgeometry of a projective space
# is also a projective space. Not installing these methods, would invoke the
# method for \= for two projective spaces if one of the arguments is a subgeometry
# and the other one a projective space not a subgeometry, with an incorrect answer.
#############################################################################
#O  \=( <pg1>, <pg2> )
##
InstallMethod( \=,
 "for two projective spaces",
 [IsSubgeometryOfProjectiveSpace, IsProjectiveSpace],
 function(pg1,pg2);
  return false;
 end );

#############################################################################
#O  \=( <pg1>, <pg2> )
##
InstallMethod( \=,
 "for two projective spaces",
 [IsProjectiveSpace, IsSubgeometryOfProjectiveSpace],
 function(pg1,pg2);
  return false;
 end );

#############################################################################
#O  Rank( <ps> )
# Rank of a subgeometry
##
InstallMethod( Rank,
 "for a projective space",
 [ IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep ],
 ps -> ps!.dimension
 );

# Note that UnderlyingVectorSpace and BaseField are installed for projective
# spaces and hence, are applicable to subgeometries. See introductory comments
# at top of file, for the "definition" of underlying vectorspace and base field.
#############################################################################
#O  SubfieldOfSubgeometry( <sub> )
# Subfield of subgeometry.
##
InstallMethod( SubfieldOfSubgeometry,
 "for a subgeometry of a projective space",
 [ IsSubgeometryOfProjectiveSpace ],
 sub -> sub!.subfield );

# NEW 31/5/2020 jdb
#############################################################################
#A  StandardFrame( <sub> )
# if the dimension of subgeometry <sub> is n and <sub> is the canonical subgeometry,
# then StandardFrame returns a list of points of <sub> with coordinates
# (1,0,...0), (0,1,0,...,0), ..., (0,...,0,1) and (1,1,...,1). In case <sub> is not the
# canonical subgeometry, the image of these points under sub!.projectivity is returned.
# note that, due to the way we construct subgeometries of projective space,
# this is nothing else than the meet of the points of the defining frame with sub
##
InstallMethod( StandardFrame, 
 "for a subgeometry of a projective space",
 [ IsSubgeometryOfProjectiveSpace ],
 function( sub )
        return List(sub!.frame,x->Meet(sub,x));
 end );

#############################################################################
#A CollineationFixingSubgeometry
# For a subgeometry PG(n,q) in PG(n,q^2), we would call this the Baer involution.
# This is the collineation of PGammaL(n+1,q^t) fixing the subgeometry point wise.
# Its order is t.
##
InstallMethod( CollineationFixingSubgeometry,
 "for a subgeometry of a projective space",
 [ IsSubgeometryOfProjectiveSpace ],
    function(pg)
        return pg!.sigma;
    end );

# Constructor operations for elements and basic operations for elements.
#############################################################################

#############################################################################
#O  Wrap( <geo>, <type>, <o> )
# An almost classical method for Wrap, with <geo> a subgeometry. Note that
# Wrap is not a user operation.
##
InstallMethod( Wrap,
 "for a projective space and an object",
 [ IsSubgeometryOfProjectiveSpace, IsPosInt, IsObject],
 function( geo, type, o )
  local w;
  w := rec( geo := geo, type := type, obj := o );
  Objectify( NewType( SoSoPSFamily, IsElementOfIncidenceStructure and
   IsElementOfIncidenceStructureRep and IsSubspaceOfSubgeometryOfProjectiveSpace ), w );
  return w;
 end );

#############################################################################
#O  VectorSpaceToElementForSubgeometries( <sub>, <obj> )
# Note that a VectorSpaceToElement method must be created for every Lie geometry
# This is a helper operation to simplify the different VectorSpaceToElement
# methods for particular objects.
# It is checked whether the projectivity maps the element of the ambient projective
# space based on <obj> back to and element of the canonical subgeometry. If so,
# the element of the subgeometry based on <obj> is returned.
##
InstallMethod( VectorSpaceToElementForSubgeometries,
 "for a sub geometry of a projective space and an object",
 [ IsSubgeometryOfProjectiveSpace, IsObject],
 function( sub, obj )
        local ambient, element, newelement, proj, subfield, newobj, elements;
     if IsZero(obj) then
        return EmptySubspace(sub);
      fi;
      ambient := sub!.ambientspace;
      element := VectorSpaceToElement(ambient,obj);
      if element = ambient then
          # newobj := Filtered(obj,x->not IsZero(x));
          # elements := List(newobj,x->VectorSpaceToElement(sub,x));
          return sub;
      # else
      #     elements := [element];
      fi;
      if not IsCanonicalSubgeometryOfProjectiveSpace(sub) then
          proj := sub!.projectivity;
          newelement := element^(proj^(-1));
      else
          newelement := element;
      fi;
      subfield := sub!.subfield;
      if not ForAll(Flat(newelement!.obj),a->a in subfield) then
      #if not ForAll( Flat( List(newelements,x->x!.obj ) ), i -> i in subfield) then
          Error( "<obj> does not determine an element in <sub>");
      # elif element = ambient then
      #     return sub;
      else
          return Wrap(sub,element!.type,UnderlyingObject(element));
      fi;
    end);

# Now follow the different methods for VectorSpaceToElement for objects
# of particular type.
#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a matrix as plist",
 [IsSubgeometryOfProjectiveSpace, IsPlistRep and IsMatrix],
 function( geom, v )
    return VectorSpaceToElementForSubgeometries(geom,v);
    end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a CMatRep",
 [ IsSubgeometryOfProjectiveSpace, IsCMatRep],
 function( geom, v )
 return VectorSpaceToElementForSubgeometries(geom, Unpack(v));
 end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a compressed GF(2)-matrix",
 [IsSubgeometryOfProjectiveSpace, IsGF2MatrixRep],
 function( geom, v )
 return VectorSpaceToElementForSubgeometries(geom, Unpack(v));
 end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a compressed basis of a vector subspace",
 [IsSubgeometryOfProjectiveSpace, Is8BitMatrixRep],
 function( geom, v )
   return VectorSpaceToElementForSubgeometries(geom, Unpack(v));
    end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a row vector as cvec",
 [IsSubgeometryOfProjectiveSpace, IsCVecRep],
 function( geom, v )
   return VectorSpaceToElementForSubgeometries(geom, Unpack(v));
    end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and a row vector",
 [IsSubgeometryOfProjectiveSpace, IsRowVector],
 function( geom, v )
   return VectorSpaceToElementForSubgeometries(geom, v);
    end );

#############################################################################
#O  VectorSpaceToElement( <sub>, <v> )
##
InstallMethod( VectorSpaceToElement,
 "for a subgeometry of a projective space and an 8-bit vector",
 [IsSubgeometryOfProjectiveSpace, Is8BitVectorRep],
 function( geom, v )
   return VectorSpaceToElementForSubgeometries(geom, Unpack(v));
    end );

#############################################################################
#O \=
# Equality of two subspaces of a subgeometry
# Note that this is a test of mathematical equality: the ambient geometry
# must be equal (so not IsIdenticalObj), and
# the underlying object must be equal. Recall that due to norming the underlying
# object, this is garantueed for two equal subspaces.
##
InstallMethod( \=,
 "for two subspace of subgeometry a projective space",
 [IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
 function(p1,p2);
  return (p1!.obj = p2!.obj) and (p1!.geo = p2!.geo);
 end );

#############################################################################
#O \=
# Equality of a subspace of a subgeometry and a subspace of a projective space
# returns always false.
##
InstallMethod( \=,
 "for a subspace of subgeometry a projective space and a subspace of a projective space",
 [IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfProjectiveSpace],
 function(p1,p2);
  return false;
 end );

#############################################################################
#O \=
# Equality of a subspace of a subgeometry and a subspace of a projective space
# returns always false.
##
InstallMethod( \=,
 "for a subspace of subgeometry a projective space and a subspace of a projective space",
 [IsSubspaceOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
 function(p1,p2);
  return false;
 end );

#############################################################################
#O UnderlyingVectorSpace
# This operation is defined for subspaces of a projective space. However,
# for subspaces of a subgeometry, which are also subspaces of projective
# spaces, this is mathematically senseless. We have to think about this,
# but currently, we return an error.
##
InstallMethod( UnderlyingVectorSpace,
 "for a subspace of subgeometry of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace ],
    function(el)
        Error(" <el> is a subspace of a subgeometry of a projective space");
    end );

#InstallMethod( BaseField,
# "for an element of a projective space",
# [IsSubspaceOfProjectiveSpace],
# sub -> sub!.basefield );

#############################################################################
#O ElementsOfIncidenceStructure
# Classical operation for Lie geometries, here for subgeometries of projective
# spaces. Note that for this method, we rely on the isomorphic subgeometry.
##
InstallMethod( ElementsOfIncidenceStructure,
 "for a projective space and an integer",
 [IsSubgeometryOfProjectiveSpace, IsPosInt],
 function( ps, j )
  local r;
  r := Rank(ps);
  if j > r then
   Error("<ps> has no elements of type <j>");
  else
   return Objectify(
   NewType( ElementsCollFamily, IsSubspacesOfSubgeometryOfProjectiveSpace and IsSubspacesOfSubgeometryOfProjectiveSpaceRep ),
    rec( geometry := ps,
     type := j,
     size := Size(Subspaces(ps!.isomorphicsubgeometry!.vectorspace, j))
     )
     );
  fi;
 end);

#############################################################################
#O ExtendElementOfSubgeometry
# Particular method for subspaces of subgeometries: extend a subspace of a
# subgeometry to a subspace of the ambient projective space.
##
InstallMethod( ExtendElementOfSubgeometry,
 "for an element of a subgeometry of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace ],
 element -> VectorSpaceToElement(AmbientSpace(element),Unpack(UnderlyingObject(element))));


# For elements of Lie geometries, incidence is based on set theoretic containment.
# therefore, a method of \in must be present. Note that we define several
# methods that return Errors if the (sub)geometries are different.
# For Lie geometries, \in is also applicable on subspaces of subgeometries
# and projective spaces.
#############################################################################
#O \in We use ExtendElementOfSubgeometry. Clearly, if the extension of an element
# is contained in the extension of another element, the first element is contained
# in the second in the subgeometry.
##
InstallMethod( \in,
 "for two subspaces of a subgeometry",
 [IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
    if x!.geo = y!.geo then
        return ExtendElementOfSubgeometry(x) in ExtendElementOfSubgeometry(y);
    else
        Error("<x> and <y> do not belong to the same geometry");
    fi;
    end );

#############################################################################
#O \in for a subspace of a subgeometry and a subspace of a projective space.
##
InstallMethod( \in,
 "for a subspace of a subgeometry and a subspace of a projective space",
 [IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

#############################################################################
#O \in for a subspace of a projective space and a subspace of a subgeometry.
##
InstallMethod( \in,
 "for a subspace of a projective space and a subspace of a subgeometry",
 [IsSubspaceOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

#############################################################################
#O \in for a subspace of a subgeometry of a projective space and a projective
# space. This is somehow tricky: subgeometries also belong to IsProjectiveSpace
# so the element!.geo = can really occur. The consequence is also that
# an element of a subgeometry is not in the ambient projective space. This
# complies with the basic philosophy of subgeometries.
##
InstallMethod( \in,
 "for an element of a subgeometry of a projective space and a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace, IsProjectiveSpace],
 function( element, ps )
        if element!.geo = ps then
            return true;
        else
            Error(" <element> is not an element of <ps>");
        fi;
    end );

#############################################################################
#O \in( <element>, <ps> )
# for a subspace of a projective space and a subgeometry.
# This is tricky as well: subspaces of subgeometries also belong to
# IsSubspaceOfProjectiveSpace so the element!.geo = ps can occur if the
# element is really a subspace of a subgeometry.
##
InstallMethod( \in,
 "for an element of a subgeometry of a projective space and a projective space",
 [ IsSubspaceOfProjectiveSpace, IsSubgeometryOfProjectiveSpace],
 function( element, ps )
       return element!.geo = ps;
    end );

#############################################################################
#O  Random( <subs> )
# returns a random subspace out of the collection of subspaces of given dimension
# of a subgeometry of a projective space. Note that Random has its own method
# for a collection of subspaces of a given dimension of a projective space.
# We use the isomorphic subgeometry for the method here.
##
InstallMethod( Random,
 "for a collection of subspaces of a subgeometry of a projective space",
 [ IsSubspacesOfSubgeometryOfProjectiveSpace ],
    # chooses a random element out of the collection of subspaces of given
    # dimension of a subgeometry of a projective space
 function( subs )
  local d, pg, w, isom, em, el;
  ## the underlying projective space
  pg := subs!.geometry;
        isom := pg!.isomorphicsubgeometry;
        em := pg!.embedding;
  if not IsInt(subs!.type) then
   Error("The subspaces of the collection need to have the same dimension");
        fi;
  ## the common type of elements of subs
  d := subs!.type;
        el := Random(ElementsOfIncidenceStructure(isom,d))^em;
        if not IsCanonicalSubgeometryOfProjectiveSpace(pg) then
            el := el^pg!.projectivity;
        fi;
        return Wrap(pg,d,UnderlyingObject(el));
        end );

# Span/Meet operations. Note the basic philosophy. We allow a span of two
# subspaces of a subgeometry only if their ambient geometry is the same. So
# having the same ambient space is not sufficient. This is slightly different
# than for e.g. polar spaces.

#############################################################################
#O Span( <x>, <y> )
# for two elements of a subgeometry. We use Embed, then compute the
# span in the ambient space, and then rewrap the result as a subspace of
# the subgeometry. We are sure that if the ambient geometries of
# both subspaces are the same, the result is correct. It is checked whether
# this is true for the input.
##
InstallMethod( Span,
 "for two elements of a subgeometry of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace,  IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
    local z,w,pg,span;
    if x!.geo = y!.geo then
        pg := AmbientSpace(x);
        z := Embed(pg,x);
        w := Embed(pg,y);
        span := Span(z,w);
        if (ProjectiveDimension(span) = ProjectiveDimension(x!.geo)) then
            return x!.geo;
        else
            return Wrap(x!.geo,span!.type,UnderlyingObject(span));
        fi;
    else
        Error( "<x> and <y> do not belong to the same geometry" );
    fi;
    end );

#############################################################################
#O Span( <l> )
# for a homogeneous lis of subspaces of a subgeometry. Note that the necessary
# checks are built in. We rely again on the Span in the ambient space.
# Compare this method with the method for Span for a homogeneous list of
# subspaces of a projective space.
##
InstallMethod( Span,
    "for a homogeneous list of subspaces of a subgeometry of a projective space",
 [ IsHomogeneousList and IsSubspaceOfSubgeometryOfProjectiveSpaceCollection ],
 function( l )
  local list, span, pg, same;
  # first we check that all items in the list belong to the same ambient geometry
  if Length(l)=0 then
   return [];
  elif not Size(AsDuplicateFreeList(List(l,x->AmbientGeometry(x))))=1 then
   Error("The elements in the list do not belong to the same ambient geometry");
  else
            pg := AmbientSpace(l[1]);
            list := List(l,x->Embed(pg,x));
            span := Span(list);
            same := Size(AsDuplicateFreeList(List(l,x->AmbientGeometry(x))))=1;
            if (ProjectiveDimension(span) = ProjectiveDimension(l[1]!.geo)) then
                return l[1]!.geo;
            else
                return Wrap(l[1]!.geo,span!.type,UnderlyingObject(span));
            fi;
        fi;
    end );

#############################################################################
#O Span( <x>, <y> )
# for a subspace of subgeometry and a subspace of a projective space. Simply
# produces an error. But we need to install this method, if not, the method
# for Span for two subspaces of a projective space would return a result which
# makes, in our philosophy of subgeometries, no sense.
##
InstallMethod( Span,
 "for a subspace of a projective space and a subspace of a subgeometry",
 [IsSubspaceOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

#############################################################################
#O Span( <x>, <y> )
# see comment on previous Span method
##
InstallMethod( Span,
 "for a subspace of a subgeometry and a subspace of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

#############################################################################
#O Span( <element>, <ps> )
# returns <ps> if it is the ambient geometry of element.
##
InstallMethod( Span,
 "for an element of a subgeometry of a projective space and a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace, IsProjectiveSpace],
 function( element, ps )
        if element!.geo = ps then
            return ps;
        else
            Error( "<element> does not belong to <ps>");
        fi;
    end );

#############################################################################
#O Span( <ps>, <element> )
# returns <ps> if it is the ambient geometry of element.
##
InstallMethod( Span,
 "for a projective space and an element of a subgeometry of a projective space",
 [ IsProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
 function( ps, element )
        if element!.geo = ps then
            return ps;
        else
            Error( "<element> does not belong to <ps>");
        fi;
    end );

#############################################################################
#O Meet( <x>, <y> )
# for two elements of a subgeometry. We use Embed, then compute the
# meet in the ambient space, and then rewrap the result as a subspace of
# the subgeometry. We are sure that if the ambient geometries of
# both subspaces are the same, the result is correct. It is checked whether
# this is true for the input.
##
InstallMethod( Meet,
 "for two elements of a subgeometry of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace,  IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
    local z,w,pg,meet;
    if x!.geo = y!.geo then
        pg := AmbientSpace(x);
        z := Embed(pg,x);
        w := Embed(pg,y);
        meet := Meet(z,w);
        if IsEmptySubspace(meet) then
            return EmptySubspace(x!.geo);
        else
            return Wrap(x!.geo,meet!.type,UnderlyingObject(meet));
        fi;
    else
        Error( "<x> and <y> do not belong to the same geometry" );
    fi;
    end );

#############################################################################
#O Meet( <l> )
# for a homogeneous lis of subspaces of a subgeometry. Note that the necessary
# checks are built in. We rely again on the Meet in the ambient space.
# Compare this method with the method for Meet for a homogeneous list of
# subspaces of a projective space.
##
InstallMethod( Meet,
    "for a homogeneous list of subspaces of a subgeometry of a projective space",
 [ IsHomogeneousList and IsSubspaceOfSubgeometryOfProjectiveSpaceCollection ],
 function( l )
  local list, meet, pg, same;
  # first we check that all items in the list belong to the same ambient geometry
  if Length(l)=0 then
   return [];
  elif not Size(AsDuplicateFreeList(List(l,x->AmbientGeometry(x))))=1 then
   Error("The elements in the list do not belong to the same ambient geometry");
  else
            pg := AmbientSpace(l[1]);
            list := List(l,x->Embed(pg,x));
            meet := Meet(list);
            # same := Size(AsDuplicateFreeList(List(l,x->AmbientGeometry(x))))=1;
            if IsEmptySubspace(meet) then
                return EmptySubspace(l[1]!.geo);
            else
                return Wrap(l[1]!.geo,meet!.type,UnderlyingObject(meet));
            fi;
        fi;
    end );

# we might consider to allow slightly more here: e.g. meet of a subspace of
# of subgeometry with a subspace of the ambient space.
#############################################################################
#O Meet( <x>, <y> )
# for a subspace of subgeometry and a subspace of a projective space. Simply
# produces an error. But we need to install this method, if not, the method
# for Meet for two subspaces of a projective space would return a result which
# makes, in our philosophy of subgeometries, no sense.
##
InstallMethod( Meet,
 "for a subspace of a projective space and a subspace of a subgeometry",
 [IsSubspaceOfProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

InstallMethod( Meet,
 "for a subspace of a subgeometry and a subspace of a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace, IsSubspaceOfProjectiveSpace],
    function(x,y)
        Error("<x> and <y> do not belong to the same geometry");
    end );

#############################################################################
#O Meet( <element>, <ps> )
# returns <element> if <ps> is the ambient geometry of element.
##
InstallMethod( Meet,
 "for an element of a subgeometry of a projective space and a projective space",
 [ IsSubspaceOfSubgeometryOfProjectiveSpace, IsProjectiveSpace],
 function( element, ps )
        if element!.geo = ps then
            return element;
        else
            Error( "<element> does not belong to <ps>");
        fi;
    end );

#############################################################################
#O Meet( <ps>, <element> )
# returns <element> if <ps> is the ambient geometry of element.
##
InstallMethod( Meet,
 "for a projective space and an element of a subgeometry of a projective space",
 [ IsProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace],
 function( ps, element )
        if element!.geo = ps then
            return element;
        else
            Error( "<element> does not belong to <ps>");
        fi;
    end );

#############################################################################
#O Meet( <sub>, <el> )
# for a subgeometry and a subspace of a projective space.
##
#use sigma to compute the intersection of an element of the ambient space
InstallMethod( Meet,
    "for a subgeometry of a projectice space and a subspace of the ambient space",
    [ IsSubgeometryOfProjectiveSpace, IsSubspaceOfProjectiveSpace],
    function( sub, el)
        local sigma,meet;
        if not AmbientSpace(sub) = AmbientGeometry(el) then
            Error( "the ambient space of <sub> is not the ambient geometry of <el>");
        else
            sigma := sub!.sigma;
            meet := Meet(el,el^sigma);
            if not IsEmptySubspace(meet) then
                return Wrap(sub,meet!.type,meet!.obj);
            else
                return EmptySubspace(sub);
            fi;
        fi;
    end );

#############################################################################
#O Meet( <sub>, <el> )
# for a subspace of a projective space and a subgeometry
##
InstallMethod( Meet,
 "for a projective space and an element of a subgeometry of a projective space",
 [ IsSubspaceOfProjectiveSpace, IsSubgeometryOfProjectiveSpace],
 function( el, sub )
        return Meet(sub,el);
    end );

#  flags and shadows

#############################################################################
#O FlagOfIncidenceStructure( <ps>, <els> )
# returns the flag of the subgeometry <ps> with elements in <els>.
# It is checked first whether the elements in <els> belong to the
# same ambient geometry. The method checks whether the input really determines a flag.
# Note that the filter for the first argument is IsProjectiveSpace. So this method
# is applicable for a projective space that is not a subgeometry and a list
# of elements of a subgeometry, but will give an appropriate error.
# Using IsSubgeometryOfProjectiveSpace would force us to install another method
# just producing an error saying that the elements do not belong to <ps>
# if called with the first argument a projective space that is not a subgeometry.
# Installing no such method in that case would result in a no method found error.
##
InstallMethod( FlagOfIncidenceStructure,
 "for a projective space and list of subspaces of the projective space",
 [ IsProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpaceCollection ],
 function(ps,els)
  local list,i,test,type,flag;
  list := Set(ShallowCopy(els));
  if Length(list) > Rank(ps) then
    Error("A flag can contain at most Rank(<ps>) elements");
  fi;
        test := List(list,x->AmbientGeometry(x));
        if not ForAll(test,x->x=ps) then
            Error("not all elements have <ps> as ambient geometry");
        fi;
        test := Set(List([1..Length(list)-1],i -> IsIncident(list[i],list[i+1])));
  if (test <> [ true ] and test <> []) then
    Error("<els> do not determine a flag");
  fi;
  flag := rec(geo := ps, types := List(list,x->x!.type), els := list, vectorspace := ps!.vectorspace );
  ObjectifyWithAttributes(flag, IsFlagsOfSgOPSType, IsEmptyFlag, false, RankAttr, Size(list) );
  return flag;
 end);

#############################################################################
#O ShadowOfElement( <ps>, <v>, <j> )
# returns the shadow of an element v as a record containing the subgeometry <ps>,
# the type j of the elements (type), the element v (parentflag), and
# some extra information useful to compute with the shadows, e.g. iterator
# This method relies on the isomorphic subgeometry of <ps>
# Note: we use IsProjectiveSpace, see also note at FlagOfIncidenceStructure
##
InstallMethod( ShadowOfElement,
 "for a projective space, an element of a subgeometry, and an integer",
 [IsProjectiveSpace, IsSubspaceOfSubgeometryOfProjectiveSpace, IsPosInt],
 # returns the shadow of an element v as a record containing the projective space (geometry),
 # the type j of the elements (type), the element v (parentflag), and some extra information
 # useful to compute with the shadows, e.g. iterator
 function( ps, v, j )
  local localinner, localouter, localfactorspace, tocanonical, vs, vcanonical;
        if not AmbientGeometry(v) = ps then
            Error("<ps> is not the ambient geometry of <v>");
        fi;
        if j > ps!.dimension then
            Error("<ps> has no elements of type <j>");
        fi;
        if not IsCanonicalSubgeometryOfProjectiveSpace(ps) then
            tocanonical := (ps!.projectivity)^(-1);
            vcanonical := v^tocanonical;
        else
            vcanonical := v;
        fi;
        vs := ps!.isomorphicsubgeometry!.vectorspace;
        if j < v!.type then
   localinner := [];
   localouter := Unpack(vcanonical!.obj);
  elif j = v!.type then
            tocanonical := (ps!.proj)^(-1);
   localinner := Unpack(vcanonical!.obj);
   localouter := localinner;
  else
   localinner := Unpack(vcanonical!.obj);
   localouter := BasisVectors(Basis(vs));
  fi;
     if IsVector(localinner) and not IsMatrix(localinner) then
   localinner := [localinner];
  fi;
  if IsVector(localouter) and not IsMatrix(localouter) then
   localouter := [localouter];
  fi;
  localfactorspace := Subspace(vs,
  BaseSteinitzVectors(localouter, localinner).factorspace);
  return Objectify( NewType( ElementsCollFamily, IsElementsOfIncidenceStructure and
       IsShadowSubspacesOfSubgeometryOfProjectiveSpace and
       IsShadowSubspacesOfSubgeometryOfProjectiveSpaceRep),
       rec( geometry := ps,
         type := j,
         inner := localinner,
         outer := localouter,
         factorspace := localfactorspace,
         parentflag := FlagOfIncidenceStructure(ps,[v]),
         size := Size(Subspaces(localfactorspace))
        )
      );
 end);

#############################################################################
#O  ShadowOfFlag( <ps>, <flag>, <j> )
# returns the shadow elements of <flag>, i.e. the elements of <ps> of type <j>
# incident with all elements of <flag>.
# returns the shadow of a flag as a record containing the geometry,
# the type j of the elements (type), the flag (parentflag), and some extra information
# useful to compute with the shadows, e.g. iterator
# This method relies on the isomorphic subgeometry of <ps>
# Note: we use IsProjectiveSpace, see also note at FlagOfIncidenceStructure
##
InstallMethod( ShadowOfFlag,
 "for a a projective space, a flag of a subgeometry of a projective space, and an integer",
 [IsProjectiveSpace, IsFlagOfSubgeometryOfProjectiveSpace, IsPosInt],
 function( ps, flag, j )
    local localinner, localouter, localfactorspace, v, smallertypes, biggertypes, ceiling, floor, canels, vs;
    if not flag!.geo = ps then
        Error("<flag> is not a flag of <ps>");
    fi;
    if j > ps!.dimension then
        Error("<ps> has no elements of type <j>");
    fi;
    #empty flag - return all subspaces of the right type
    if IsEmptyFlag(flag) then
      return ElementsOfIncidenceStructure(ps, j);
    fi;

    # find the element in the flag of highest type less than j, and the subspace
    # in the flag of lowest type more than j.

 #listoftypes:=List(flag,x->x!.type);
 smallertypes:=Filtered(flag!.types,t->t <= j);
 biggertypes:=Filtered(flag!.types,t->t >= j);
    vs := ps!.isomorphicsubgeometry!.vectorspace;
    if not IsCanonicalSubgeometryOfProjectiveSpace(ps) then
           canels := List(flag!.els,x->x^(ps!.projectivity^(-1)));
        else
           canels := List(flag!.els);
    fi;

 if smallertypes=[] then
  localinner := [];
  ceiling:=Minimum(biggertypes);
  localouter:= canels[Position(flag!.types,ceiling)];
 elif biggertypes=[] then
  localouter:=BasisVectors(Basis(vs));
  floor:=Maximum(smallertypes);
  localinner:= canels[Position(flag!.types,floor)];
 else
  floor:=Maximum(smallertypes);
  ceiling:=Minimum(biggertypes);
  localinner:= canels[Position(flag!.types,floor)];
  localouter:= canels[Position(flag!.types,ceiling)];
 fi;
 if not smallertypes = [] then
  if localinner!.type = 1 then
   localinner:=[Unpack(localinner!.obj)]; #here is the cmat change
  else
   localinner:=Unpack(localinner!.obj);
  fi;
 fi;
    if not biggertypes = [] then
  if localouter!.type = 1 then
   localouter := [Unpack(localouter!.obj)];
        else
   localouter := Unpack(localouter!.obj);
        fi;
 fi;
    localfactorspace := Subspace(vs,
  BaseSteinitzVectors(localouter, localinner).factorspace);
    return Objectify(
  NewType( ElementsCollFamily, IsElementsOfIncidenceStructure and
       IsShadowSubspacesOfSubgeometryOfProjectiveSpace and
       IsShadowSubspacesOfSubgeometryOfProjectiveSpaceRep),
        rec(
          geometry := ps,
          type := j,
          inner := localinner,
          outer := localouter,
          factorspace := localfactorspace,
    parentflag := flag,
          size := Size(Subspaces(localfactorspace)) #this causes a problem when localfactorspace consists of cvec/cmat.
        )
      );
 end);

#############################################################################
#O Iterator: the classical iterator, relying completely on the isomorphic
# subgeometry and using the projectivity.
##
InstallMethod(Iterator,
 "for subspaces of a projective space",
 [ IsSubspacesOfSubgeometryOfProjectiveSpace ],
 function( vs )
  local sub, isomorphicsubgeometry, canonicalelements, j, em, proj, map;
  sub := vs!.geometry;
        j := vs!.type;
        isomorphicsubgeometry := sub!.isomorphicsubgeometry;
        canonicalelements := ElementsOfIncidenceStructure(isomorphicsubgeometry,j);
        em := sub!.embedding;
        if IsCanonicalSubgeometryOfProjectiveSpace(sub) then
            map := x->Wrap(sub,j,UnderlyingObject(x^em));
        else
            proj := sub!.projectivity;
            map := x->Wrap(sub,j,UnderlyingObject((x^em)^proj));
        fi;
        return IteratorByFunctions(
            rec(
   NextIterator := function(iter)
                local element;
                element := NextIterator(iter!.S);
                return map(element);
                end,

            IsDoneIterator := function(iter)
              return IsDoneIterator(iter!.S);
            end,

            ShallowCopy := function(iter)
              return rec(
                S := ShallowCopy(iter!.S)
                );
            end,
            S := Iterator(canonicalelements)
          ));
 end);


#############################################################################
#O Iterator: the classical iterator for shadows, relying completely on
# the isomorphic subgeometry and using the projectivity.
##
InstallMethod( Iterator,
 "for shadow subspaces of a projective space",
 [IsShadowSubspacesOfSubgeometryOfProjectiveSpace and IsShadowSubspacesOfSubgeometryOfProjectiveSpaceRep ],
    function( vs )
        local j, d, F, act, sub, proj;
        sub := vs!.geometry;
        j := vs!.type;
        d := sub!.dimension;
        F := sub!.basefield;
        if IsCanonicalSubgeometryOfProjectiveSpace(sub) then
            act := x->x;
        else
            proj := sub!.projectivity;
        #this should be just the action of the projectivity on x, see OnProjSubspacesNoFrob, we will take over
        #the code from there, OnProjSubspacesNoFrob expect that both arguments are cvec/cmat. Also note that
        #x is always a matrix.
            act := function(x)
                local mat;
                    mat := OnSubspacesByCanonicalBasis(x,Unpack(proj!.mat));
                        TriangulizeMat(mat);
                        return mat;
            end;
        fi;
        return IteratorByFunctions( rec(
        NextIterator := function(iter)
            local mat;
            mat := NextIterator(iter!.S);
            mat := MutableCopyMat(Concatenation(
                BasisVectors(Basis(mat)),
                    iter!.innermat
                ));
            return VectorSpaceToElement(sub,act(mat));
            end,
            IsDoneIterator := function(iter)
            return IsDoneIterator(iter!.S);
            end,
            ShallowCopy := function(iter)
            return rec(
                innermat := iter!.innermat,
                S := ShallowCopy(iter!.S)
            );
            end,
            innermat := vs!.inner,
            S := Iterator(Subspaces(vs!.factorspace,j-Size(vs!.inner)))
        ));
    end);

## groups and actions.

InstallMethod( CollineationGroup,
 "for a subgeometry of a projective space",
 [ IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep ],
 function( sub )
  local coll,d,f,frob,g,newgens,q,s,pow,h,baer;
  f := sub!.subfield;
  q := Size(f);
  d := ProjectiveDimension(sub);
  if d <= -1 then
   Error("The dimension of the projective spaces needs to be at least 0");
  fi;
  g := GL(d+1,f);
  frob := FrobeniusAutomorphism(sub!.basefield); #frobenius automorphism of big field
        h := DegreeOverPrimeField(BaseField(sub));
        newgens := List(GeneratorsOfGroup(g),x->[x,frob^0]);
        #baer := frob^Length(FactorsInt(q)); #this is precisely the Baer collineation for the canonical subgeometry.
        #Add(newgens,[One(g),baer]);
        # new paradigm: CollineationGroup(sub) will not consider the embedding,
        # if q is not prime, the frobenius automorphism of GF(q) is also a collineation.
        # note that we add the frobenius automorphism of the basefield (not the subfield).
  #if not IsPrime(q) then #if q is not prime, there is a frobenius automorphism.
  # Add(newgens,[One(g),frob]);
        #    s := q^(d*(d+1)/2)*Product(List([2..d+1], i->q^i-1)) * Order(frob);
  #else
        #    Add(newgens,[One(g),baer]);
        #    s := q^(d*(d+1)/2)*Product(List([2..d+1], i->q^i-1)) * Order(baer);
        #fi;
        Add(newgens,[One(g),frob]);
  s := Size(CollineationGroup(PG(d,q)))*h;
        newgens := ProjElsWithFrob(newgens,sub!.basefield); #using sub!.basefield as second argument makes sure that
        # ProjElsWithFrob returns elements in the collineation group of the ambient projective space.
        if not IsCanonicalSubgeometryOfProjectiveSpace(sub) then
            newgens := List(newgens,x->sub!.projectivity^(-1)*x*sub!.projectivity);
        fi;
  coll := GroupWithGenerators(newgens);
  #pow := LogInt(q, Characteristic(f)); #order of frobenius of subfield!
  #s := pow * q^(d*(d+1)/2)*Product(List([2..d+1], i->q^i-1))*Order(baer); #hard coded order!
  if not IsPrime(q) then
   SetName( coll, Concatenation("The FinInG collineation group PGammaL(",String(d+1),",",String(q),") of ",ViewString(sub)) );
  else
   SetName( coll, Concatenation("The FinInG collineation group PGL(",String(d+1),",",String(q),") of ",ViewString(sub)) );
   # Remark that in the prime case, PGL is returned as a FinInG collineation group with associated automorphism F^0.
  fi;
  SetSize( coll, s );
        # only for making generalised polygons section more generic:
        if d = 2 then
            SetCollineationAction(coll,OnProjSubspacesOfSubgeometryNC);
        fi;
        SetDefaultGeometry(coll,sub);
        SetParent(coll,CollineationGroup(AmbientSpace(sub)));
  return coll;
 end );


##
InstallMethod( ProjectivityGroup,
 "for a subgeometry of a projective space",
 [ IsSubgeometryOfProjectiveSpace and IsSubgeometryOfProjectiveSpaceRep ],
 function( sub )
  local d,f,frob,g,newgens,q,s,baer,coll;
  f := sub!.subfield;
  q := Size(f);
  d := ProjectiveDimension(sub);
  if d <= -1 then
   Error("The dimension of the projective spaces needs to be at least 0");
  fi;
  g := GL(d+1,f);
  frob := FrobeniusAutomorphism(sub!.basefield); #frobenius automorphism of big field
  newgens := List(GeneratorsOfGroup(g),x->[x,frob^0]);
        #baer := frob^Length(FactorsInt(q)); #this is precisely the Baer collineation for the canonical subgeometry.
        #Add(newgens,[One(g),baer]);
  newgens := ProjElsWithFrob(newgens,sub!.basefield); #using sub!.basefield as second argument makes sure that
        # ProjElsWithFrob returns elements in the collineation group of the ambient projective space.
        if not IsCanonicalSubgeometryOfProjectiveSpace(sub) then
            newgens := List(newgens,x->sub!.projectivity^(-1)*x*sub!.projectivity);
        fi;
  coll := GroupWithGenerators(newgens);
        SetName( coll, Concatenation("The FinInG projectivity group PGL(",String(d+1),",",String(q),") of ",ViewString(sub)) );
        #s := q^(d*(d+1)/2)*Product(List([2..d+1], i->q^i-1)) * Order(baer);
  s := Size(ProjectivityGroup(PG(d,f)));
        SetSize( coll, s );
        # only for making generalised polygons section more generic:
        if d = 2 then
            SetCollineationAction(coll,OnProjSubspacesOfSubgeometryNC);
        fi;
        SetDefaultGeometry(coll,sub);
  return coll;
 end );


InstallMethod( NiceMonomorphism,
 "for a projective group of a subgeometry",
 [IsProjectiveGroupWithFrob and HasDefaultGeometry],
 50,
 function( pg )
 local hom, dom,bf, geom;
 Info(InfoFinInG,4,"Using NiceMonomorphism for proj. group (feasible)");
    geom := DefaultGeometry(pg);
 bf := SubfieldOfSubgeometry(geom);
    #dom := List(MakeAllProjectivePoints( bf, Dimension(pg) - 1),x->OnProjPointsWithFrob(x,geom!.projectivity));
    dom := AsList(Points(geom));
    #The use of FINING.Fast seems deprecated 25/5/2020.
    #if FINING.Fast then
    hom := NiceMonomorphismByDomain( pg, dom, OnProjSubspacesOfSubgeometryNC );
    #else
    #   hom := ActionHomomorphism(pg, dom, OnProjSubspacesOfSubgeometriesNC, "surjective");
    #   SetIsBijective(hom, true);
    #fi;
    return hom;
 end );


InstallGlobalFunction( OnProjSubspacesOfSubgeometryNC,
  function( var, el )
    local amb,geo,newvar;
    geo := var!.geo;
    if var!.type = 1 then
        newvar := OnProjPointsWithFrob(var!.obj,el);
    else
        newvar := OnProjSubspacesWithFrob(var!.obj,el);
    fi;
    return Wrap(geo,var!.type,newvar);
  end );

InstallGlobalFunction( OnProjSubspacesOfSubgeometry,
  function( var, el )
    local amb,geo,newvar,newel,baer;
    geo := var!.geo;
    if var!.type = 1 then
        newvar := OnProjPointsWithFrob(var!.obj,el);
    else
        newvar := OnProjSubspacesWithFrob(var!.obj,el);
    fi;
    newel := Wrap(AmbientSpace(geo),var!.type,newvar);
    baer := geo!.sigma;
    if newel^baer = newel then
        return Wrap(geo,var!.type,newvar);
    else
        return newel;
    fi;
  end );

InstallOtherMethod( \^,
 "for an element of an incidence structure and a projective semilinear element",
 [IsSubspaceOfSubgeometryOfProjectiveSpace, IsProjGrpElWithFrob],
 function(x, em)
  return OnProjSubspacesOfSubgeometry(x,em);
 end );

InstallGlobalFunction( OnSubgeometryOfProjectiveSpace,
  function( sub, el )
    local frame;
    frame := List(sub!.frame,x->x^el);
    return SubgeometryOfProjectiveSpaceByFrame(AmbientSpace(sub),frame,SubfieldOfSubgeometry(sub));
end );

[ zur Elbe Produktseite wechseln0.58Quellennavigators  Analyse erneut starten  ]