Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  gpolygons.gi   Sprache: unbekannt

 
#############################################################################
##
##  gpolygons.gi              FinInG package
##                                                              John Bamberg
##                                                              Anton Betten
##                                                              Jan De Beule
##                                                             Philippe Cara
##                                                            Michel Lavrauw
##                                                           Max Neunhoeffer
##
##  Copyright 2018 Colorado State University
##                  Sabancı Üniversitesi
##     Università degli Studi di Padova
##     Universiteit Gent
##     University of St. Andrews
##     University of Western Australia
##                  Vrije Universiteit Brussel
##
##
##  Implementation stuff for generalised polygons.
##
#############################################################################

#############################################################################
# Part I: generic part
# This section is generic, i.e. if someone constructs a GP and obeys the representation,
# these methods will work.
#############################################################################
# about IsGeneralisedPolygonRep
# objects belonging to IsGeneralisedPolygonRep should have several fields in their record:
# pointsobj, linesobj, incidence, listelements, shadowofpoint, shadowofline, distance.
#
# pointsobj: a list containing the *underlying objects* for the points of the GP
#
# linesobj: a list containing the *underlying objects* for the lines of the GP
#
# incidence: a function, taking two *elements of the GP* as argument, returning true or false
#    we assume that the elements that are argument of this built in function, belong
#    to the same geometry. See generic method IsIncident.
#
# listelements: a function taking an integer as argument, returning
# a list of all elements of the GP of the given type. This list will be turned into an iterator
# by the method installed for Iterator for elements of GPs.
#
# shadowofpoint: a function, taking a *point of a GP* as argument, returning a list
# of lines incident with the given point.
#
# shadowofline: a function, taking a *line of a GP* as argument, returning a list
# of points incident with the given line.
#  The method for ShadowOfElement should do the necessary checks and pass the appropriate
#  function to the method installed for Iterator for shadow objects.
#
# span: a function taking two *points of a GP* returning fail or the unique line incident with the two points.
#
# meet: a function taking two *lines of a GP* returning fail or the unique point incident with the two lines.
#
# distance: a function taking two *elements of a GP* and returning their distance in the incidence graph.
#
# action: a function describing an action on the *underlying objects*.
#
# gonality: it is not very explicitely documented, but one can actually construct
#   generalised n-gons for n different than 3,4,6,8. To avoid checking the diameter of the underlying
#   graph e.g. for ViewObj, in these case the field gonality is set upon creation. One could say
#   that this field replaces the categories IsProjectivePlaneCategory, IsGeneralisedQuadrangle, IsGeneralisedHexagon
#   and IsGeneralisedOctagon for these arbitrary cases.
#
# Note: - If an object belongs to IsGeneralisedPolygon, then the "generic operations" to explore the GP
#   are *applicable* (does not imply that a specific method is installed or will be working).
#  - If a GP is constructed using a "Generic method", the above fields are created as described, making
#   all the methods for the "generic operations" working.
#  - If a GP is created as an object in IsGeneralisedPolygon and IsGeneralisedPolygonRep, with some of
#   these fields lacking or different, than separate methods need to be installed for certain operations
#   This is not problematic. A typical example are the hexagons: they belong also to IsLieGeometry,
#   so it is easy to get the right methods selected. Furthermore, typical methods for Lie geometries become
#   applicable (but might also need separate methods).
#  - If a GP is constructed using the "generic construction methods", there is always an underlying graph (to
#   check whether the user really constructs a GP. Creating the graph can be time consuming, but there is
#   the possibility to use a group. There is no NC version, either you are a developper, and you want to make
#   a particular GP (e.g. the hexagons) and then you know what you do and there is no need to check whether your
#   developed GP is really a GP, or you are a user and must be protected against yourself.
#   The computed graph is stored as a mutable attribute.
#  - For the particular GPs: of course we know that they are a GP, so on construction, we do not compute
#   the underlying graph.
#  - The classical GQs belong to IsGeneralisedPolygon but *not* to IsGeneralisedPolygonRep. For them there is
#   either an atrtibute set on creation (e.g. Order), or a seperate method for other generic operations.
#
#############################################################################

#############################################################################
#
# Construction of GPs
#
#############################################################################

#############################################################################
#O  GeneralisedPolygonByBlocks( <list> )
# returns a GP, the points are Union(blocks), the lines are the blocks. functions
# for shadows are installed. It is checked whether this is really a GP.
# Note that we allow weak GPs: these are GPs "without order", i.e. bipartite graph,
# grith = 2*diameter, but no constant valency for the vertices in (on of) the components
# of the graph. We can do the necessary checks with LocalParameters.
##
InstallMethod( GeneralisedPolygonByBlocks,
    "for a homogeneous list",
    [ IsHomogeneousList ],
    function( blocks )
        local pts, gp, ty, i, graph, sz, adj, girth, shadpoint, shadline, s, t, dist, vn,
  listels, objs, act, spanoftwopoints, meetoftwolines, bicomp, pointvertices, lp, linevertices;
        pts := Union(blocks);

        i := function( x, y )
        if IsSet( x!.obj ) and not IsSet( y!.obj ) then
            return y!.obj in x!.obj;
        elif IsSet( y!.obj ) and not IsSet( x!.obj ) then
            return x!.obj in y!.obj;
        else
            return x!.obj = y!.obj;
        fi;
        end;

        sz := Size(pts);

  adj := function(x,y)
   if IsSet(x) and not IsSet(y) then
    return y in x;
   elif IsSet(y) and not IsSet(x) then
    return x in y;
   else
    return false;
   fi;
  end;

  act := function(x,g)
   return x;
  end;

        graph := Graph(Group(()), Concatenation(pts,blocks), act, adj );
        girth := Girth(graph);

        if IsBipartite(graph) then
            if not girth = 2*Diameter(graph) then
                Error("<blocks> are not defining a generalised polygon");
            fi;
        else
            Error("<blocks are not defining a generalised polygon");
        fi;

        listels := function( geom, i )
   if i = 1 then
    return List(pts,x->Wrap(geom,i,x));
   else
    return List(blocks,x->Wrap(geom,i,x));
   fi;
  end;

  vn := VertexNames(graph);

        shadpoint := function( pt )
            return List(Filtered(blocks,x->pt!.obj in x),y->Wrap(pt!.geo,2,y));
        end;

        shadline := function( line )
            return List(line!.obj,x->Wrap(line!.geo,1,x));
        end;

  #we have the graph now, the following is easy.
  bicomp := Bicomponents(graph);
  pointvertices := First(bicomp,x->1 in x); #just take all points
  lp := LocalParameters(graph,pointvertices);
  t := lp[1][3]-1; #is the number of lines on a point, is -1 if there is no order, subtract to have t
  linevertices := First(bicomp,x->not 1 in x); #just take all lines
  lp := LocalParameters(graph,linevertices);
  s := lp[1][3]-1; #is the number of points on a line, is -1 if there is no orde, subtract to have s

  dist := function( el1, el2 )
   return Distance(graph,Position(vn,el1!.obj),Position(vn,el2!.obj));
  end;

        spanoftwopoints := function(x,y) #x and y are elements
            local i,j,span,el;
            i := Position(vn,x!.obj);
            j := Position(vn,y!.obj);
            el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
            if not Length(el) = 0 then
                span := vn{el};
                return Wrap(x!.geo,2,span[1]);
            else
                Info(InfoFinInG, 1, "<x> and <y> do not span a line of gp");
                return fail;
            fi;
        end;

        meetoftwolines := function(x,y) #x and y are elements
            local i,j,meet,el;
            i := Position(vn,x!.obj);
            j := Position(vn,y!.obj);
            el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
            if not Length(el) = 0 then
                meet := vn{el};
                return Wrap(x!.geo,1,meet[1]);
            else
                Info(InfoFinInG, 1, "<x> and <y> do meet in a common point of gp");
                return fail;
            fi;
        end;

        gp := rec( pointsobj := pts, linesobj := blocks, incidence := i, listelements := listels,
     shadowofpoint := shadpoint, shadowofline := shadline, distance := dist,
                    span := spanoftwopoints, meet := meetoftwolines );

        if t = -2 or s = -2 then
   ty := NewType( GeometriesFamily, IsWeakGeneralisedPolygon and IsGeneralisedPolygonRep );
            gp!.gonality := girth/2;
  elif girth = 6 then
            ty := NewType( GeometriesFamily, IsProjectivePlaneCategory and IsGeneralisedPolygonRep );
        elif girth = 8 then
            ty := NewType( GeometriesFamily, IsGeneralisedQuadrangle and IsGeneralisedPolygonRep );
        elif girth = 12 then
            ty := NewType( GeometriesFamily, IsGeneralisedHexagon and IsGeneralisedPolygonRep );
        elif girth = 16 then
            ty := NewType( GeometriesFamily, IsGeneralisedOctagon and IsGeneralisedPolygonRep );
        else
            ty := NewType( GeometriesFamily, IsGeneralisedPolygon and IsGeneralisedPolygonRep );
            gp!.gonality := girth/2;
        fi;

        Objectify( ty, gp );
        SetTypesOfElementsOfIncidenceStructure(gp, ["point","line"]);
        if s <> -2 and t <> -2 then
   SetOrder(gp, [s, t]);
  fi;
        SetRankAttr(gp, 2);
        Setter( IncidenceGraphAttr )( gp, graph );
        Setter( HasGraphWithUnderlyingObjectsAsVertices )( gp, true);
        return gp;
  end );

#############################################################################
#O  GeneralisedPolygonByIncidenceMatrix( <matrix> )
# returns a GP. points are [1..NrRows(matrix)], blocks are sets of entries equal to one.
# Blocks are then used through GeneralisedPolygonByBlocks.
# the commented out check dates from the times that this was only use to construct
# projective planes.
##
InstallMethod( GeneralisedPolygonByIncidenceMatrix,
    "for a matrix",
    [ IsMatrix ],
    function( mat )
    ## Rows represent blocks and columns represent points...
    local v, q, row, blocks, gp;
    v := NrRows(mat);
    #if not ForAll(mat, t->Size(t)=v) then
    #   Error("Matrix is not square");
    #fi;

    blocks := [];
    for row in mat do
        Add(blocks, Positions(row,1));
    od;

    gp := GeneralisedPolygonByBlocks( blocks );
    Setter( IncidenceMatrixOfGeneralisedPolygon )( gp, mat );
    return gp;
  end );

#############################################################################
#O  GeneralisedPolygonByElements( <pts>, <lns>, <inc> )
# <pts>: set of elements of some incidence structure, representing points of GP.
# <lns>: set of elements of some incidence structure, representing points of GP.
# <inc>: incidence function.
# it is checked throug the graph that the incidence structure is a GP.
##
InstallMethod( GeneralisedPolygonByElements,
    "for two sets (points and lines), and an incidence function",
    [ IsSet, IsSet, IsFunction ],
    function( pts, lns, inc )
    local adj, act, graph, ty, girth, shadpoint, shadline, s, t,
 gp, vn, dist, listels, wrapped_incidence, spanoftwopoints, meetoftwolines,
 bicomp, pointvertices, linevertices, lp;

    adj := function(x,y)
    if x in pts and y in pts then
        return false;
    elif x in lns and y in lns then
        return false;
    else
        return inc(x,y);
    fi;
    end;

    # this is the situation where the user gives no group at all. So action function is trivial too.
    act := function(x,g)
        return x;
    end;

    graph := Graph(Group(()), Concatenation(pts,lns), act, adj, true );
    girth := Girth(graph);

    if IsBipartite(graph) then
        if not girth = 2*Diameter(graph) then
            Error("<pts>, <lns>, <inc> are not defining a generalised polygon");
        fi;
    else
        Error("elements are not defining a generalised polygon");
    fi;

 bicomp := Bicomponents(graph);
 pointvertices := First(bicomp,x->1 in x); #just take all points
 lp := LocalParameters(graph,pointvertices);
 t := lp[1][3]-1; #is the number of lines on a point, is -1 if there is no order, subtract to have t
 linevertices := First(bicomp,x->(Size(pts)+1) in x); #just take all lines
 lp := LocalParameters(graph,linevertices);
 s := lp[1][3]-1; #is the number of points on a line, is -1 if there is no order, subtract to have s

 # inc takes in fact underlying objects as arguments. So we must make a new function that takes
 # as arguments elements of this geometry and pipes the underlying objects to inc.

 wrapped_incidence := function(x,y)
  return inc(x!.obj,y!.obj);
 end;

    listels := function( geom, i )
  if i = 1 then
   return List(pts,x->Wrap(geom,i,x));
  else
   return List(lns,x->Wrap(geom,i,x));
  fi;
 end;

    shadpoint := function( pt )
        return List(vn{Adjacency(graph,Position(vn,pt!.obj))},x->Wrap(gp,2,x));
    end;

    shadline := function( line )
        return List(vn{Adjacency(graph,Position(vn,line!.obj))},x->Wrap(gp,1,x));
    end;

    vn := VertexNames(graph);
 dist := function( el1, el2 )
        return Distance(graph,Position(vn,el1!.obj),Position(vn,el2!.obj));
    end;

    spanoftwopoints := function(x,y) #x and y are elements
        local i,j,span,el;
        i := Position(vn,x!.obj);
        j := Position(vn,y!.obj);
        el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
        if not Length(el) = 0 then
            span := vn{el};
            return Wrap(x!.geo,2,span[1]);
        else
            Info(InfoFinInG, 1, "<x> and <y> do not span a line of gp");
            return fail;
        fi;
    end;

    meetoftwolines := function(x,y) #x and y are elements
        local i,j,meet,el;
        i := Position(vn,x!.obj);
        j := Position(vn,y!.obj);
        el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
        if not Length(el) = 0 then
            meet := vn{el};
            return Wrap(x!.geo,1,meet[1]);
        else
            Info(InfoFinInG, 1, "<x> and <y> do meet in a common point of gp");
            return fail;
        fi;
    end;

    gp := rec( pointsobj := pts, linesobj := lns, incidence := wrapped_incidence, listelements := listels,
    shadowofpoint := shadpoint, shadowofline := shadline, distance := dist,
                span := spanoftwopoints, meet := meetoftwolines );

 if t = -2 or s = -2 then
  ty := NewType( GeometriesFamily, IsWeakGeneralisedPolygon and IsGeneralisedPolygonRep );
  gp!.gonality := girth/2;
 elif girth = 6 then
        ty := NewType( GeometriesFamily, IsProjectivePlaneCategory and IsGeneralisedPolygonRep );
    elif girth = 8 then
        ty := NewType( GeometriesFamily, IsGeneralisedQuadrangle and IsGeneralisedPolygonRep );
    elif girth = 12 then
        ty := NewType( GeometriesFamily, IsGeneralisedHexagon and IsGeneralisedPolygonRep );
    elif girth = 16 then
        ty := NewType( GeometriesFamily, IsGeneralisedOctagon and IsGeneralisedPolygonRep );
    else
        ty := NewType( GeometriesFamily, IsGeneralisedPolygon and IsGeneralisedPolygonRep );
        gp!.gonality := girth/2;
    fi;

    Objectify( ty, gp );
 if s <> -2 and t <> -2 then
  SetOrder(gp, [s, t]);
 fi;
    SetTypesOfElementsOfIncidenceStructure(gp, ["point","line"]);
    SetRankAttr(gp, 2);
    Setter( IncidenceGraphAttr )( gp, graph );
    Setter( HasGraphWithUnderlyingObjectsAsVertices )( gp, true);
    return gp;
end );

#############################################################################
#O  GeneralisedPolygonByElements( <pts>, <lns>, <inc>, <group>, <act> )
# <pts>: set of elements of some incidence structure, representing points of GP.
# <lns>: set of elements of some incidence structure, representing points of GP.
# <inc>: incidence function.
# <group>: group preserving <pts>, <lns> and <inc>
# <act>: action function for group on <pts> and <lns>.
# it is checked throug the graph that the incidence structure is a GP, by using
# the group, this is much more efficient. The user is responsible the <group>
# really preserves <pts> and <lns>
##
InstallMethod( GeneralisedPolygonByElements,
    "for two sets (points and lines), and an incidence function",
    [ IsSet, IsSet, IsFunction, IsGroup, IsFunction ],
    function( pts, lns, inc, group, act )
    local adj, graph, ty, girth, shadpoint, shadline, s, t, gp, vn,
 dist, listels, wrapped_incidence, spanoftwopoints, meetoftwolines,
 bicomp, pointvertices, linevertices, lp;

    adj := function(x,y)
    if x in pts and y in pts then
        return false;
    elif x in lns and y in lns then
        return false;
    else
        return inc(x,y);
    fi;
    end;

    graph := Graph(group, Concatenation(pts,lns), act, adj, true );
    girth := Girth(graph);

    if IsBipartite(graph) then
        if not girth = 2*Diameter(graph) then
            Error("<blocks> are not defining a generalised polygon");
        fi;
    else
        Error("elements are not defining a generalised polygon");
    fi;

 bicomp := Bicomponents(graph);
 pointvertices := First(bicomp,x->1 in x); #just take all points
 lp := LocalParameters(graph,pointvertices);
 t := lp[1][3]-1; #is the number of lines on a point, is -1 if there is no order, subtract -1 to have t
 linevertices := First(bicomp,x->(Size(pts)+1) in x); #just take all lines
 lp := LocalParameters(graph,linevertices);
 s := lp[1][3]-1; #is the number of points on a line, is -1 if there is no order, subtract -1 to have s

    vn := VertexNames(graph);

 # inc takes in fact underlying objects as arguments. So we must make a new function that takes
 # as arguments elements of this geometry and pipes the underlying objects to inc.

 wrapped_incidence := function(x,y)
  return inc(x!.obj,y!.obj);
 end;

    listels := function( geom, i )
  if i = 1 then
   return List(pts,x->Wrap(geom,i,x));
  else
   return List(lns,x->Wrap(geom,i,x));
  fi;
 end;

    shadpoint := function( pt )
        return List(vn{Adjacency(graph,Position(vn,pt!.obj))},x->Wrap(gp,2,x));
    end;

    shadline := function( line )
        return List(vn{Adjacency(graph,Position(vn,line!.obj))},x->Wrap(gp,1,x));
    end;

    dist := function( el1, el2 )
        return Distance(graph,Position(vn,el1!.obj),Position(vn,el2!.obj));
    end;

    spanoftwopoints := function(x,y) #x and y are elements
        local i,j,span,el;
        i := Position(vn,x!.obj);
        j := Position(vn,y!.obj);
        el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
        if not Length(el) = 0 then
            span := vn{el};
            return Wrap(x!.geo,2,span[1]);
        else
            Info(InfoFinInG, 1, "<x> and <y> do not span a line of gp");
            return fail;
        fi;
    end;

    meetoftwolines := function(x,y) #x and y are elements
        local i,j,meet,el;
        i := Position(vn,x!.obj);
        j := Position(vn,y!.obj);
        el := Intersection(DistanceSet(graph,[1],i), DistanceSet(graph,[1],j));
        if not Length(el) = 0 then
            meet := vn{el};
            return Wrap(x!.geo,1,meet[1]);
        else
            Info(InfoFinInG, 1, "<x> and <y> do meet in a common point of gp");
            return fail;
        fi;
    end;

    gp := rec( pointsobj := pts, linesobj := lns, incidence := wrapped_incidence, listelements := listels,
    shadowofpoint := shadpoint, shadowofline := shadline, distance := dist, span := spanoftwopoints,
                meet := meetoftwolines, action := act );

 if t = -2 or s = -2 then
  ty := NewType( GeometriesFamily, IsWeakGeneralisedPolygon and IsGeneralisedPolygonRep );
  gp!.gonality := girth/2;
 elif girth = 6 then
        ty := NewType( GeometriesFamily, IsProjectivePlaneCategory and IsGeneralisedPolygonRep );
    elif girth = 8 then
        ty := NewType( GeometriesFamily, IsGeneralisedQuadrangle and IsGeneralisedPolygonRep );
    elif girth = 12 then
        ty := NewType( GeometriesFamily, IsGeneralisedHexagon and IsGeneralisedPolygonRep );
    elif girth = 16 then
        ty := NewType( GeometriesFamily, IsGeneralisedOctagon and IsGeneralisedPolygonRep );
    else
        ty := NewType( GeometriesFamily, IsGeneralisedPolygon and IsGeneralisedPolygonRep );
        gp!.gonality := girth/2;
    fi;

    Objectify( ty, gp );
 if s <> -2 and t <> -2 then
  SetOrder(gp, [s, t]);
 fi;
 SetTypesOfElementsOfIncidenceStructure(gp, ["point","line"]);
    SetRankAttr(gp, 2);
    Setter( IncidenceGraphAttr )( gp, graph );
    Setter( HasGraphWithUnderlyingObjectsAsVertices )( gp, true);
    return gp;
end );

#############################################################################
# View methods for GPs.
#############################################################################

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsProjectivePlaneCategory and IsGeneralisedPolygonRep],
 function( p )
        if HasOrder(p) then
            Print("<projective plane order ",Order(p)[1],">");
        else
            Print("<projective plane>");
        fi;
 end );

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsGeneralisedQuadrangle and IsGeneralisedPolygonRep],
 function( p )
        if HasOrder(p) then
            Print("<generalised quadrangle of order ",Order(p),">");
        else
            Print("<generalised quadrangle>");
        fi;
 end );

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsGeneralisedHexagon and IsGeneralisedPolygonRep],
 function( p )
        if HasOrder(p) then
            Print("<generalised hexagon of order ",Order(p),">");
        else
            Print("<generalised hexagon>");
        fi;
 end );

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsGeneralisedOctagon and IsGeneralisedPolygonRep],
 function( p )
        if HasOrder(p) then
            Print("<generalised octagon of order ",Order(p),">");
        else
            Print("<generalised octagon>");
        fi;
 end );

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsGeneralisedPolygon and IsGeneralisedPolygonRep],
 function( gp )
        if HasOrder(gp) then
            Print("<generalised polygon of gonality ",String(gp!.gonality)," and order ",Order(gp),">");
        else
            Print("<generalised polygon of gonality ",String(gp!.gonality),">");
        fi;
 end );

InstallMethod( ViewObj,
 "for a projective plane in GP rep",
 [ IsWeakGeneralisedPolygon and IsGeneralisedPolygonRep],
 function( gp )
  Print("<weak generalised polygon of gonality ",String(gp!.gonality),">");
 end );

#############################################################################
#
# Basic methods for elements (including construction and iterator).
#
#############################################################################

#############################################################################
#O  Order( <x> )
##
InstallMethod( Order,
 "for a weak generalised polygon",
 [ IsWeakGeneralisedPolygon ],
 function( gp )
  Error("<gp> is a weak generalised polygon and has no order");
 end );

#############################################################################
#O  UnderlyingObject( <x> )
##
InstallMethod( UnderlyingObject,
 "for an element of a LieGeometry",
 [ IsElementOfGeneralisedPolygon ],
 function( x )
  return x!.obj;
 end );

#############################################################################
#O  ObjectToElement( <geom>, <type>, <obj> )
# returns the subspace of <geom>, with representative <v> and subspace at infinity
# determined by <m> if and only if <obj> is the list [v,m].
##
InstallMethod( ObjectToElement,
 "for ageneralised polygon, an integer and an object",
 [ IsGeneralisedPolygon and IsGeneralisedPolygonRep, IsPosInt, IsObject],
 function(gp, t, obj)
  if t=1 then
   if obj in gp!.pointsobj then
    return Wrap(gp,t,obj);
   else
    Error("<obj> does not represent a point of <gp>");
   fi;
  elif t=2 then
   if obj in gp!.linesobj then
    return Wrap(gp,t,obj);
   else
    Error("<obj> does not represent a line of <gp>");
   fi;
  else
   Error("<gp> is a point-line geometry not containing elements of type ",t);
  fi;
 end );

#############################################################################
#O  ObjectToElement( <geom>, <obj> )
# returns the subspace of <geom>, with representative <v> and subspace at infinity
# determined by <m> if and only if <obj> is the list [v,m].
##
InstallMethod( ObjectToElement,
 "for ageneralised polygon and an object",
 [ IsGeneralisedPolygon and IsGeneralisedPolygonRep, IsObject],
 function(gp, obj)
  if obj in gp!.pointsobj then
   return Wrap(gp,1,obj);
  elif obj in gp!.linesobj then
   return Wrap(gp,2,obj);
  else
   Error("<obj> does not represent an element of <gp>");
  fi;
 end );

#############################################################################
#O  ElementsOfIncidenceStructure( <gp>, <j> )
# returns the elements of <gp> of type <j>
##
InstallMethod( ElementsOfIncidenceStructure,
 "for a generalised polygon and a positive integer",
 [IsGeneralisedPolygon and IsGeneralisedPolygonRep, IsPosInt],
 function( gp, j )
  local s, t, sz;
  if j in [1,2] then
   s := Order(gp)[j]; t := Order(gp)[3-j];
  else
   Error("Incorrect type value");
  fi;
  if IsProjectivePlaneCategory(gp) then
   sz := s^2 + s + 1;
  elif IsGeneralisedQuadrangle(gp) then
   sz := (1+s)*(1+s*t);
  elif IsGeneralisedHexagon(gp) then
   sz := (1+s)*(1+s*t+s^2*t^2);
  elif IsGeneralisedOctagon(gp) then
   sz := (1+s)*(1+s*t+s^2*t^2+s^3*t^3);
  else
            if j=1 then
                sz := Length(gp!.pointsobj);
            else
                sz := Length(gp!.linesobj);
            fi;
        fi;
  return Objectify( NewType( ElementsCollFamily, IsElementsOfGeneralisedPolygon and
                                IsElementsOfGeneralisedPolygonRep),
        rec( geometry := gp, type := j, size := sz )
      );
 end );

#############################################################################
#O  ElementsOfIncidenceStructure( <gp>, <j> )
# returns the elements of <gp> of type <j>
##
InstallMethod( ElementsOfIncidenceStructure,
 "for a generalised polygon and a positive integer",
 [IsWeakGeneralisedPolygon and IsGeneralisedPolygonRep, IsPosInt],
 function( gp, j )
  local s, t, sz;
  if not j in [1,2] then
   Error("Incorrect type value");
  fi;
        if j=1 then
   sz := Length(gp!.pointsobj);
  else
   sz := Length(gp!.linesobj);
  fi;
  return Objectify( NewType( ElementsCollFamily, IsElementsOfGeneralisedPolygon and
       IsElementsOfGeneralisedPolygonRep),
      rec( geometry := gp, type := j, size := sz ) );
 end );

#############################################################################
#O  Points( <gp>  )
# returns the points of <gp>.
##
InstallMethod( Points,
 "for a generalised polygon",
 [IsGeneralisedPolygon and IsGeneralisedPolygonRep],
 function( gp )
  return ElementsOfIncidenceStructure(gp, 1);
 end);

#############################################################################
#O  Lines( <gp>  )
# returns the lines of <gp>.
##
InstallMethod( Lines,
 "for a generalised polygon",
 [IsGeneralisedPolygon and IsGeneralisedPolygonRep],
 function( gp )
  return ElementsOfIncidenceStructure(gp, 2);
 end);

#############################################################################
# Display methods: Element collections
#############################################################################

InstallMethod( ViewObj,
 "for elements of a generalised polygon",
 [ IsElementsOfGeneralisedPolygon and IsElementsOfGeneralisedPolygonRep ],
 function( vs )
  local l;
  l := ["points","lines"];
  Print("<", l[vs!.type]," of ");
  ViewObj(vs!.geometry);
  Print(">");
 end );

InstallMethod( PrintObj,
 "for elements of a generalised polygon",
 [ IsElementsOfGeneralisedPolygon and IsElementsOfGeneralisedPolygonRep ],
 function( vs )
  Print("ElementsOfIncidenceStructure( ",vs!.geometry," , ",vs!.type,")");
 end );

#############################################################################
#O  Size( <gp>  )
# returns the size of a collection of elements of a <gp>
##
InstallMethod(Size,
 "for elements of a generalised polygon",
 [IsElementsOfGeneralisedPolygon],
 vs -> vs!.size );

#############################################################################
#O  Iterator( <vs>  )
# returns an iterator for the elements of a gp
##
InstallMethod( Iterator,
 "for elements of a generalised polygon",
 [ IsElementsOfGeneralisedPolygon and IsElementsOfGeneralisedPolygonRep],
 function( vs )
  local gp, j, vars;
  gp := vs!.geometry;
  j := vs!.type;
  if j in [1,2] then
   return IteratorList(gp!.listelements(gp,j)); #looks a bit strange, but correct.
  else
   Error("Element type does not exist");
  fi;
 end );

#############################################################################
#O  Iterator( <shadow>  )
# returns an iterator for a shadow of elements of a gp
##
InstallMethod( Iterator,
 "for shadow elements of a generalised polygon",
 [IsShadowElementsOfGeneralisedPolygon and IsShadowElementsOfGeneralisedPolygonRep ],
 function( vs )
        return IteratorList(vs!.func(vs!.element));
 end);

#############################################################################
#O  Random( <vs>  )
# In general, the list of elements might be stored in the GP itself. Then
# the standard method uses the Iterator. This standard method will be called
# also if our particular GPs do not have a collienation/elation group, the
# iterator will be used, which causes the computation of the collineation
#   group including a nice monomorphism. The next time Random is used, this
# group is used.
##
InstallMethod( Random,
 "for a collection of elements of a generalised polygon",
 [ IsElementsOfGeneralisedPolygon and IsElementsOfGeneralisedPolygonRep ],
 function( vs )
  local geo, type, class, group, rep, act;
  geo := vs!.geometry;
  type := vs!.type;
  if IsClassicalGeneralisedHexagon(geo) and HasCollineationGroup(geo) then
   group := CollineationGroup(geo);
   act := CollineationAction(group);
   rep := RepresentativesOfElements(geo)[type];
   return act(rep,Random(group));
  elif HasElationGroup(geo) then
   group := ElationGroup(geo);
   act := CollineationAction(group);
   rep := RepresentativesOfElements(geo)[type];
   return act(Random(rep),Random(group));
  else
   TryNextMethod();
  fi;
 end );

#############################################################################
#O  IsIncident( <x>, <y>  )
# simply uses the incidence relation that is built in in the gp.
# caveat: check here that elements belong to the same geometry!
##
InstallMethod( IsIncident,
 "for elements of a generalised polygon",
    [IsElementOfGeneralisedPolygon, IsElementOfGeneralisedPolygon],
 function( x, y )
  local inc;
  if not x!.geo = y!.geo then
   Error("The elements <x> and <y> do not belong to the same geometry");
  else
   inc := x!.geo!.incidence;
   return inc(x, y);
  fi;
 end );

#############################################################################
#O  Span( <x>, <y>  )
# return the line spanned by <x> and <y>, if they span a line at all.
##
InstallMethod( Span,
    "for two elements of a generalised polygon",
    [ IsElementOfGeneralisedPolygon, IsElementOfGeneralisedPolygon ],
    function( x, y )
        local graph, vn, el, i, j, span;
        if not x!.type = 1 and y!.type = 1 then
            Error("<x> and <y> must be points of a generalised polygon");
        elif not x!.geo = y!.geo then
            Error("<x> and <y> must belong to the same generalised polygon");
        fi;
        return x!.geo!.span(x,y);
    end );

#############################################################################
#O  Meet( <x>, <y>  )
# return the line spanned by <x> and <y>, if they span a line at all.
##
InstallMethod( Meet,
    "for two elements of a generalised polygon",
    [ IsElementOfGeneralisedPolygon, IsElementOfGeneralisedPolygon ],
    function( x, y )
        local graph, vn, el, i, j, meet;
        if not x!.type = 2 and y!.type = 2 then
            Error("<x> and <y> must be lines of a generalised polygon");
        elif not x!.geo = y!.geo then
            Error("<x> and <y> must belong to the same generalised polygon");
        fi;
        return x!.geo!.meet(x,y);
    end );

#############################################################################
#O  Wrap( <geo>, <type>, <o>  )
# returns the element of <geo> represented by <o>.
# this method is generic, but of course not fool proof.
##
InstallMethod( Wrap,
 "for a generalised polygon and an object",
 [IsGeneralisedPolygon, IsPosInt, IsObject],
 function( geo, type, o )
  local w;
  w := rec( geo := geo, type := type, obj := o );
  Objectify( NewType( ElementsOfIncidenceStructureFamily,
   IsElementOfIncidenceStructureRep and IsElementOfGeneralisedPolygon ), w );
  return w;
  end );

# CHECKED 11/09/11 jdb
#############################################################################
#A  TypesOfElementsOfIncidenceStructure( <gp> )
# returns the names of the types of the elements of the projective space <ps>
# the is a helper operation.
##
InstallMethod( TypesOfElementsOfIncidenceStructurePlural,
 "for a generalised polygon in the general representation",
    [ IsGeneralisedPolygon and IsGeneralisedPolygonRep ],
  x -> ["points", "lines"] );

#############################################################################
#O ShadowOfElement(<gp>, <el>, <j> )
##
InstallMethod( ShadowOfElement,
 "for a generalised polygon, an element, and an integer",
 [IsGeneralisedPolygon and IsGeneralisedPolygonRep, IsElementOfGeneralisedPolygon, IsPosInt],
 function( gp, el, j )
  local shadow, func;
        if not AmbientGeometry(el) = gp then
            Error("ambient geometry of <el> is not <gp>");
        fi;
        if j = el!.type then
            func := x->[x];
        elif j = 1 then
            func := gp!.shadowofline;
        elif j = 2 then
            func := gp!.shadowofpoint;
        else
            Error("<gp> has no shadow elements of type", j );
        fi;

        shadow := rec( geometry := gp, type := j, element := el, func := func );
  return Objectify( NewType( ElementsCollFamily, IsElementsOfIncidenceStructure and
       IsShadowElementsOfGeneralisedPolygon and
       IsShadowElementsOfGeneralisedPolygonRep),
       shadow
      );
 end);

#############################################################################
# View methods for shadow objects.
#############################################################################

InstallMethod( ViewObj,
 "for shadow elements of a generalised polygon",
 [ IsShadowElementsOfGeneralisedPolygon and IsShadowElementsOfGeneralisedPolygonRep ],
 function( vs )
  Print("<shadow ",TypesOfElementsOfIncidenceStructurePlural(vs!.geometry)[vs!.type]," in ");
  ViewObj(vs!.geometry);
  Print(">");
 end );

#############################################################################
#O  Points( <el> )
# returns the points, i.e. elements of type <1> in <el>, relying on ShadowOfElement
# for particular <el>.
##
InstallMethod( Points,
    "for an element of a generalised polygon",
 [ IsElementOfGeneralisedPolygon ],
 function( var )
  return ShadowOfElement(var!.geo, var, 1);
 end );

#############################################################################
#O  Lines( <el> )
# returns the lines, i.e. elements of type <2> in <el>, relying on ShadowOfElement
# for particular <el>.
##
InstallMethod( Lines,
    "for an element of a generalised polygon",
 [ IsElementOfGeneralisedPolygon ],
 function( var )
  return ShadowOfElement(var!.geo, var, 2);
 end );

#############################################################################
#O  DistanceBetweenElements( <gp>, <el1>, <el2> )
# returns the distance in the incidence graph between two elements
# Important notice: the '5' before the function increases the priority of this
# method for a pair of points satisfying the filters. The only situation where
# this is relevant is to compute the distance between elements of the Classical
# hexagons. Elements of these are also IsSubspaceOfClassicalPolarSpace. For
# elements of classical GQs, the above method for IsSubspaceOfClassicalPolarSpace
# must be applied. For elements of classical GHs, the generic method here must be
# used. But elements of classical GHs satisfy both filters, so the rank of the filters
# is used to select the method. As the rank of IsSubspaceOfClassicalPolarSpace is
# larger than the rank of IsElementOfGeneralisedPolygon, the wrong method gets
# selected for elements of GHs. The difference in rank is currently 2, times 2 makes
# 4, so adding 5 here should do the job, and it does.
##
InstallMethod( DistanceBetweenElements,
    "for a gp in gpRep and two of its elements",
 [ IsElementOfGeneralisedPolygon, IsElementOfGeneralisedPolygon],
    5,
 function( p, q )
  local geo;
        geo := p!.geo;
        if not geo = q!.geo then
            Error("<p> and <q> are not elements of the same generalised polygon");
        fi;
        return geo!.distance(p,q);
 end );

#############################################################################
#O  IncidenceGraph( <gp> )
# We could install a generic method. But currently, our particular GPs (hexagons,
# elation GQs, and classical GQs) have a particular method for good reasons. All other GPs
# currently possible to construct, have their incidence graph computed upon construction.
# So we may restrict here to checking whether this attribute is bounded, and return it,
# or print an error message. Note that we deal here with a mutable attribute.
###
InstallMethod( IncidenceGraph,
    "for a generalised polygon (in all possible representations",
    [ IsGeneralisedPolygon ],
    function( gp )
    local points, lines, graph, sz, adj, elations, gg, coll;
    #if not "grape" in RecNames(GAPInfo.PackagesLoaded) then
    #   Error("You must load the GRAPE package\n");
    #fi;
    if IsBound(gp!.IncidenceGraphAttr) then
       return gp!.IncidenceGraphAttr;
    else
        Error("no method installed currently");
    fi;
    end );

#############################################################################
#O  IncidenceMatrixOfGeneralisedPolygon( <gp> )
#
InstallMethod( IncidenceMatrixOfGeneralisedPolygon,
 "for a generalised polygon",
 [ IsGeneralisedPolygon ],
 function( gp )
  local graph, mat, incmat, szpoints, szlines;
  graph := IncidenceGraph( gp );
  mat := CollapsedAdjacencyMat(Group(()), graph);

    ## The matrix above is the adjacency matrix of the
    ## bipartite incidence graph.

  szpoints := Size(Points(gp));
  szlines := Size(Lines(gp));

  incmat := mat{[1..szpoints]}{[szpoints+1..szpoints+szlines]};
  return incmat;
 end );

#############################################################################
#O  CollineationGroup( <gp> )
# This method is generic. Note that:
# - for classical GQs, we have completely different methods to compute their
# collineation group, of course for good reasons;
# - for classical generalised hexagons, the same remark applies;
# - when a GP is constructed through generic methods, the underlying graph is
# always computed, since this is the only way to check if the input is not rubbish.
# But then the VertexNames of the constructed graph are the underlying objects.
# For particular GQs, the underlying graph is not computed upon construction.
#   But computing a graph afterwards, is very naturally done with the elements themselves
#   as VertexNames. This has some technical consequences to compute the collineation
#   group and to define the CollineationAction of it.
# To distinguish in this method, we introduced the property HasGraphWithUnderlyingObjectsAsVertices.
###
InstallMethod( CollineationGroup,
    "for a generalised polygon",
    [ IsGeneralisedPolygon and IsGeneralisedPolygonRep ],
    function( gp )
        local graph, aut, act, stab, coll, ptsn, points, pointsobj;
        graph := IncidenceGraph( gp );
        aut := AutomorphismGroup( graph );
        points := AsList(Points(gp));
        if HasGraphWithUnderlyingObjectsAsVertices(gp) then
            pointsobj := List(points,x->x!.obj);
            ptsn := Set(pointsobj,x->Position(VertexNames(graph),x));
        else
            ptsn := Set(points,x->Position(VertexNames(graph),x));
        fi;
        coll := Stabilizer(aut, ptsn, OnSets);
        if HasGraphWithUnderlyingObjectsAsVertices(gp) then
            act := function(el,g)
                local src,img;
                if el!.type = 1 then
                    src := Position(VertexNames(graph),el!.obj);
                    img := src^g;
                    return Wrap(gp,1,VertexNames(graph)[img]);
                elif el!.type = 2 then
                    src := Position(VertexNames(graph),el!.obj);
                    img := src^g;
                    return Wrap(gp,2,VertexNames(graph)[img]);
                fi;
            end;
        else
            act := function(el,g)
                local src,img;
    src := Position(VertexNames(graph),el); #change wrt generic function which would be el!.obj
    img := src^g;
    return VertexNames(graph)[img];
            end;
        fi;
        SetCollineationAction( coll, act );
  return coll;
    end );

#############################################################################
#O  BlockDesignOfGeneralisedPolygon( <gp> )
# Note about BlockDesign: this is a global (so read-only) function in the
# "design" package. We have created in FinInG a function BlockDesign (not
# through DeclareGlobalFunction, so it can be overwritten at user level and
# through loading other packages), so that the method for BlockDesignOfGeneralisedPolygon
# can be loaded without the "design" package loaded. We make sure that this method checks
# whether design is loaded, and produces an error when this is not the case.
#
InstallMethod( BlockDesignOfGeneralisedPolygon,
    "for a generalised polygon",
    [ IsGeneralisedPolygon and IsGeneralisedPolygonRep ],
    function( gp )
        local points, lines, des, blocks, l, b, elations, gg, orbs;
        if not IsPackageLoaded("design") then #this is a gap4r10 function.
        #if not "design" in RecNames(GAPInfo.PackagesLoaded) then
            Error("You must load the DESIGN package\n");
        fi;
        if IsBound(gp!.BlockDesignOfGeneralisedPolygonAttr) then
            return gp!.BlockDesignOfGeneralisedPolygonAttr;
        fi;
        points := AsList(Points(gp));;
        lines := AsList(Lines(gp));;
        if IsElationGQ(gp) and HasElationGroup( gp ) then
            elations := ElationGroup(gp);
            Info(InfoFinInG, 1, "Computing orbits on lines of gen. polygon...");
            orbs := List( Orbits(elations, lines, CollineationAction(elations)), Representative);
            orbs := List(orbs, l -> Filtered([1..Size(points)], i -> points[i] * l));
            gg := Action(elations, points, CollineationAction( elations ) );
            Info(InfoFinInG, 1, "Computing block design of generalised polygon...");
            des := BlockDesign(Size(points), orbs, gg );
        elif HasCollineationGroup(gp) then
            gg := CollineationGroup(gp);
            orbs := List( Orbits(gg, lines, CollineationAction(gg)), Representative);
            orbs := List(orbs, l -> Filtered([1..Size(points)], i -> points[i] * l));
            gg := Action(gg, points, CollineationAction( gg ) );
            des := BlockDesign(Size(points), orbs, gg );
        else
            blocks := [];
            for l in lines do
                b := Filtered([1..Size(points)], i -> points[i] * l);
                Add(blocks, b);
            od;
            des := BlockDesign(Size(points), Set(blocks));
        fi;
        Setter( BlockDesignOfGeneralisedPolygonAttr )( gp, des );
        return des;
  end );

#############################################################################
#
# Part II: particular models of GPs.
#
#############################################################################

#############################################################################
#
# Desarguesian projective planes. Methods needed:
# - DistanceBetweenElements
# - IncidenceGraph
#
#############################################################################

#############################################################################
#O  DistanceBetweenElements( <v>, <w> )
# It is possible to create points and lines of PG(2,q) in the category
# IsElementsOfGeneralisedPolygon (or even more specified). But this would increase
# the dependency of projectivespace.gi on gpolygons.gd, which we want to avoid.
###
InstallMethod( DistanceBetweenElements,
    "for subspaces of a projective space",
    [ IsSubspaceOfProjectiveSpace, IsSubspaceOfProjectiveSpace ],
    function( v, w )
        if not IsDesarguesianPlane(v!.geo) then
            Error( "Elements must have a generalised polygon as ambient geometry" );
        fi;
        if not v!.geo = w!.geo then
            Error( "Elements must belong to the same generalised polygon ");
        fi;
        if v = w then
            return 0;
        elif v!.type <> w!.type then
   if IsIncident(v,w) then
    return 1;
   else
    return 3;
   fi;
  else
   return 2;
  fi;
 end );

#############################################################################
#O  IncidenceGraph( <gp> )
# Note that computing the collineation group of a projective space is zero
# computation time. So useless to print the warning here if the group is not
# yet computed.
##
# Note that there is actually a method for IsProjectiveSpace, and IsDesarguesianPlane
# is a subcategory of IsProjectiveSpace. But the property HasGraphWithUnderlyingObjectsAsVertices
# is important for IsGeneralisedPolygon. We could check in the method for projective
# spaces whether the spaces is a plane, and set the property there, but we want
# to keep projectivespace.gi independent from gpolygons.gd.
###
InstallMethod( IncidenceGraph,
    "for a Desarguesian plane",
    [ IsDesarguesianPlane ],
    function( gp )
        local points, lines, graph, adj, group, coll, sz;
        #if not "grape" in RecNames(GAPInfo.PackagesLoaded) then
        #    Error("You must load the GRAPE package\n");
        #fi;
        if IsBound(gp!.IncidenceGraphAttr) then
            return gp!.IncidenceGraphAttr;
        fi;
        points := AsList(Points(gp));
        lines := AsList(Lines(gp));
        Setter( HasGraphWithUnderlyingObjectsAsVertices )( gp, false );
        Info(InfoFinInG, 1, "Computing incidence graph of generalised polygon...");
        adj := function(x,y)
            if x!.type <> y!.type then
                return IsIncident(x,y);
            else
                return false;
            fi;
        end;
        group := CollineationGroup(gp);
        graph := Graph(group,Concatenation(points,lines),OnProjSubspaces,adj,true);
        Setter( IncidenceGraphAttr )( gp, graph );
        return graph;
    end );

#############################################################################
#
# Classical GQs. Methods needed:
# - DistanceBetweenElements
# - IncidenceGraph
#
#############################################################################

#############################################################################
#O  DistanceBetweenElements( <v>, <w> )
# It is possible to create points and lines of PG(2,q) in the category
# IsElementsOfGeneralisedPolygon (or even more specified). But this would increase
# the dependency of projectivespace.gi on gpolygons.gd, which we want to avoid.
###
InstallMethod( DistanceBetweenElements,
    "for subspaces of a projective space",
    [ IsSubspaceOfClassicalPolarSpace, IsSubspaceOfClassicalPolarSpace ],
    function( v, w )
        if not IsClassicalGQ(v!.geo) then
            Error( "Elements must have a generalised polygon as ambient geometry" );
        fi;
        if not v!.geo = w!.geo then
            Error( "Elements must belong to the same generalised polygon ");
        fi;
        if v = w then
            return 0;
        elif v!.type <> w!.type then
   if IsIncident(v,w) then
    return 1;
   else
    return 3;
   fi;
  else
   if v!.type = 1 then
    if Span(v,w) in v!.geo then
     return 2;
    else
     return 4;
    fi;
   else
    if ProjectiveDimension(Meet(v,w)) = 0 then
     return 2;
    else
     return 4;
    fi;
   fi;
  fi;
 end );

#############################################################################
#O  IncidenceGraph( <gp> )
##
# Note that there is actually a method for IsProjectiveSpace, and IsDesarguesianPlane
# is a subcategory of IsProjectiveSpace. But the property HasGraphWithUnderlyingObjectsAsVertices
# is important for IsGeneralisedPolygon. We could check in the method for projective
# spaces whether the spaces is a plane, and set the property there, but we want
# to keep polarspace.gi independent from gpolygons.gd.
###
InstallMethod( IncidenceGraph,
    "for a generalised polygon (in all possible representations",
    [ IsClassicalGQ ],
    function( gp )
        local points, lines, graph, adj, group, coll, sz;
        #if not "grape" in RecNames(GAPInfo.PackagesLoaded) then
        #    Error("You must load the GRAPE package\n");
        #fi;
        if IsBound(gp!.IncidenceGraphAttr) then
            return gp!.IncidenceGraphAttr;
        fi;
        if not HasCollineationGroup(gp) then
            Error("No collineation group computed. Please compute collineation group before computing incidence graph\,n");
        else
            points := AsList(Points(gp));
            lines := AsList(Lines(gp));
            Setter( HasGraphWithUnderlyingObjectsAsVertices )( gp, false );
            Info(InfoFinInG, 1, "Computing incidence graph of generalised polygon...");
            adj := function(x,y)
                if x!.type <> y!.type then
                    return IsIncident(x,y);
                else
                    return false;
                fi;
            end;
            group := CollineationGroup(gp);
            graph := Graph(group,Concatenation(points,lines),OnProjSubspaces,adj,true);
            Setter( IncidenceGraphAttr )( gp, graph );
            return graph;
        fi;
  end );

#############################################################################
#
#  Classical Generalised Hexagons
#  This section implements H(q) and T(q,q^3). In FinInG, these geometries
#  are nicely constructed inside polar spaces, but are also constructed
#  formally as generalised polygons, which make typical operations available
#  Both are also Lie geometries, and are hard wired embedded inside the corresponding
#  polar space. See chapter 4 of the documentation.
#
#  For both models we (have to) install methods for Wrap etc. This makes other
#  operations, like OnProjSubspaces (action function) generic. As such, we can fully
#  exploit the fact that these geometries are also Lie geometries.
#
#############################################################################

#############################################################################
#O  Wrap( <geo>, <type>, <o>  )
# returns the element of <geo> represented by <o>
##
InstallMethod( Wrap,
 "for a generalised polygon and an object",
 [IsClassicalGeneralisedHexagon, IsPosInt, IsObject],
 function( geo, type, o )
  local w;
  w := rec( geo := geo, type := type, obj := o );
  Objectify( NewType( SoPSFamily, IsElementOfIncidenceStructureRep and IsElementOfGeneralisedPolygon
   and IsSubspaceOfClassicalPolarSpace ), w );
  return w;
  end );

#############################################################################
# The fixed, hard-coded triality :-)
#############################################################################

#############################################################################
#F  SplitCayleyPointToPlane5( <el> )
# returns a list of vectors spanning the plane of W(5,q): ---, which is the
# image of the point represented by <w> under the fixed triality
###
InstallGlobalFunction( SplitCayleyPointToPlane5,
    function(w, f)
        local z, hyps, q, y, spacevec, hyp, vec, int, n;
        q := Size(f);
        #w := Unpack(elvec);
  y := w{[1..3]};
        y{[5..7]} := w{[4..6]};
        y[4] := (y[1]*y[5]+y[2]*y[6]+y[3]*y[7])^(q/2);
        y[8] := -y[4];
        z := [];
  n := Zero(f);
        z[1] := [n,y[3],-y[2],y[5],y[8],n,n,n];
        z[2] := [-y[3],n,y[1],y[6],n,y[8],n,n];
        z[3] := [y[2],-y[1],n,y[7],n,n,y[8],n];
        z[4] := [n,n,n,-y[4],y[1],y[2],y[3],n];
        z[5] := [y[4],n,n,n,n,y[7],-y[6],y[1]];
        z[6] := [n,y[4],n,n,-y[7],n,y[5],y[2]];
        z[7] := [n,n,y[4],n,y[6],-y[5],n,y[3]];
        z[8] := [y[5],y[6],y[7],n,n,n,n,-y[8]];
        z := Filtered(z,x->not IsZero(x));
        hyp := [0,0,0,1,0,0,0,1]*Z(q)^0;
        Add(z,[0,0,0,1,0,0,0,1]*Z(q)^0);
        spacevec := NullspaceMat(TransposedMat(z));
  int := IdentityMat(8,f){[1..7]};
  int[4][8] := -One(f); #could have been One(f) too, since this is only used in even char...
  vec := SumIntersectionMat(spacevec, int)[2];
        return vec{[1..3]}{[1,2,3,5,6,7]};
    end );

#############################################################################
#F  SplitCayleyPointToPlane( <elvec>, <f> )
# returns a list of vectors spanning the plane of Q(6,q): ---, which is the
# image of the point represented by <elvec> under the fixed triality
##
InstallGlobalFunction( SplitCayleyPointToPlane,
 function(elvec, f)
  local z, hyps, y, spacevec, hyp, vec, int, n;
  y := ShallowCopy(elvec);
  y[8] := -y[4];
  z := [];
  n := Zero(f);
  z[1] := [n,y[3],-y[2],y[5],y[8],n,n,n];
  z[2] := [-y[3],n,y[1],y[6],n,y[8],n,n];
  z[3] := [y[2],-y[1],n,y[7],n,n,y[8],n];
  z[4] := [n,n,n,-y[4],y[1],y[2],y[3],n];
  z[5] := [y[4],n,n,n,n,y[7],-y[6],y[1]];
  z[6] := [n,y[4],n,n,-y[7],n,y[5],y[2]];
  z[7] := [n,n,y[4],n,y[6],-y[5],n,y[3]];
  z[8] := [y[5],y[6],y[7],n,n,n,n,-y[8]];
  z := Filtered(z,x->not IsZero(x));
  hyp := [0,0,0,1,0,0,0,1]*One(f);
  Add(z,[0,0,0,1,0,0,0,1]*One(f));
  spacevec := NullspaceMat(TransposedMat(z));
  int := IdentityMat(8,f){[1..7]};
  int[4,8] := -One(f);
  vec := SumIntersectionMat(spacevec, int)[2];
  return vec{[1..3]}{[1..7]};
 end );

#############################################################################
#F  ZeroPointToOnePointsSpaceByTriality( <elvec>, <frob>, <f> )
# returns a list of vectors spanning the solid of Q+(7,q): ---, which is the
# image of the point represented by <elvec> under the fixed triality
##
InstallGlobalFunction( ZeroPointToOnePointsSpaceByTriality,
 function(elvec,frob,f)
 # elvec represents a point of T(q,q^3)
  local z, hyps, y, spacevec, n;
  n := Zero(f);
  y := elvec^frob;
  z := [];
  z[1] := [n,y[3],-y[2],y[5],y[8],n,n,n];
  z[2] := [-y[3],n,y[1],y[6],n,y[8],n,n];
  z[3] := [y[2],-y[1],n,y[7],n,n,y[8],n];
  z[4] := [n,n,n,-y[4],y[1],y[2],y[3],n];
  z[5] := [y[4],n,n,n,n,y[7],-y[6],y[1]];
  z[6] := [n,y[4],n,n,-y[7],n,y[5],y[2]];
  z[7] := [n,n,y[4],n,y[6],-y[5],n,y[3]];
  z[8] := [y[5],y[6],y[7],n,n,n,n,-y[8]];
  z := Filtered(z,x->not IsZero(x));
  spacevec := NullspaceMat(TransposedMat(z));
  return spacevec;
 end );

#############################################################################
#F  TwistedTrialityHexagonPointToPlaneByTwoTimesTriality( <elvec>, <frob>, <f> )
# elvec represents a point of T(q^3,q). elvec^frob is a one point, elvec^frob^2
# is a two point. This function computes a basis for the intersection of the
# one and two point (which are actually generators of Q+(7,q)). There intersection
# will be a plane containing the q+1 lines through elvec.
##
InstallGlobalFunction( TwistedTrialityHexagonPointToPlaneByTwoTimesTriality,
 function(elvec,frob,f)
  local z, hyps, y, pg, spacevec1, spacevec2, n;
  n := Zero(f);
  #y := Unpack(elvec)^frob;
  y := elvec^frob;
  z := [];
  z[1] := [n,y[3],-y[2],y[5],y[8],n,n,n];
  z[2] := [-y[3],n,y[1],y[6],n,y[8],n,n];
  z[3] := [y[2],-y[1],n,y[7],n,n,y[8],n];
  z[4] := [n,n,n,-y[4],y[1],y[2],y[3],n];
  z[5] := [y[4],n,n,n,n,y[7],-y[6],y[1]];
  z[6] := [n,y[4],n,n,-y[7],n,y[5],y[2]];
  z[7] := [n,n,y[4],n,y[6],-y[5],n,y[3]];
  z[8] := [y[5],y[6],y[7],n,n,n,n,-y[8]];
  z := Filtered(z,x->not IsZero(x));
  spacevec1 := NullspaceMat(TransposedMat(z));
  z := y^frob;
  y := [];
  y[1] := [n,-z[3],z[2],n,z[4],n,n,z[5]];
  y[2] := [z[3],n,-z[1],n,n,z[4],n,z[6]];
  y[3] := [-z[2],z[1],n,n,n,n,z[4],z[7]];
  y[4] := [z[5],z[6],z[7],-z[4],n,n,n,n];
  y[5] := [z[8],n,n,z[1],n,-z[7],z[6],n];
  y[6] := [n,z[8],n,z[2],z[7],n,-z[5],n];
  y[7] := [n,n,z[8],z[3],-z[6],z[5],n,n];
  y[8] := [n,n,n,n,z[1],z[2],z[3],-z[8]];
  y := Filtered(y,x->not IsZero(x));
  spacevec2 := NullspaceMat(TransposedMat(y));
  return SumIntersectionMat(spacevec1, spacevec2)[2];
 end );

#############################################################################
# Constructor operations for the Classical Generalised Hexagons.
#############################################################################

#############################################################################
#O  SplitCayleyHexagon( <f> )
# returns the split cayley hexagon over <f>
##
InstallMethod( SplitCayleyHexagon,
 "for a finite field",
 [ IsField and IsFinite ],
 function( f )
    local geo, ty, repline, reppointvect, reppoint, replinevect, dist,
     hvm, ps, hvmform, form, nonzerof, x, w, listels, shadpoint, shadline;
    if IsOddInt(Size(f)) then
       ## the corresponding sesquilinear form here for
       ## q odd is the matrix
       ## [[0,0,0,0,1,0,0],[0,0,0,0,0,1,0],
       ## [0,0,0,0,0,0,1],[0,0,0,-2,0,0,0],
       ## [1,0,0,0,0,0,0],[0,1,0,0,0,0,0],[0,0,1,0,0,0,0]];

    ## this is Hendrik's form
  hvm := List([1..7], i -> [0,0,0,0,0,0,0]*One(f));
  hvm{[1..3]}{[5..7]} := IdentityMat(3, f);
  hvm{[5..7]}{[1..3]} := IdentityMat(3, f);
  hvm[4][4] := -2*One(f);
  hvmform := BilinearFormByMatrix(hvm, f);
  ps := PolarSpace(hvmform);
  # UnderlyingObject will return a cvec.
  reppointvect := UnderlyingObject(RepresentativesOfElements(ps)[1]);

       ## Hendrik's canonical line is <(1,0,0,0,0,0,0), (0,0,0,0,0,0,1)>
  replinevect := [[1,0,0,0,0,0,0], [0,0,0,0,0,0,1]] * One(f);
  TriangulizeMat(replinevect);
  #ConvertToMatrixRep(replinevect, f); #is useless now.
        shadpoint := function( pt )
            local planevec, flag, plane, f;
            f := BaseField( pt );
            planevec := SplitCayleyPointToPlane( Unpack(pt!.obj), f );
            plane := VectorSpaceToElement(PG(6,f),planevec);
            flag := FlagOfIncidenceStructure(PG(6,f),[pt,plane]);
            return List(ShadowOfFlag(PG(6,f),flag,2),x->Wrap(pt!.geo,2,Unwrap(x)));
        end;

        dist := function(el1,el2)
            local x,y;
            if el1=el2 then
                return 0;
            elif el1!.type = 1 and el2!.type = 1 then
                y := VectorSpaceToElement(PG(6,f), SplitCayleyPointToPlane(Unpack(el2!.obj),f)); #PG(5,f): avoids some unnecessary checks
                if el1 in y then
                    return 2;
                else
                    x := VectorSpaceToElement(PG(6,f), SplitCayleyPointToPlane(Unpack(el1!.obj),f));
                    if ProjectiveDimension(Meet(x,y)) = 0 then
                        return 4;
                    else
                        return 6;
                    fi;
                fi;
            elif el1!.type = 2 and el2!.type = 2 then
                if ProjectiveDimension(Meet(el1,el2)) = 0 then
                    return 2;
                fi;
                x := TangentSpace(ps,el1);
                if ProjectiveDimension(Meet(x,el2)) = 0 then
                    return 4;
                else
                    return 6;
                fi;
            elif el1!.type = 1 and el2!.type = 2 then
                if el1 in el2 then
                    return 1;
                fi;
                x := VectorSpaceToElement(PG(6,f), SplitCayleyPointToPlane(Unpack(el1!.obj),f));
                if ProjectiveDimension(Meet(x,el2)) = 0 then
                    return 3;
                else
                    return 5;
                fi;
            else
                return dist(el2,el1);
            fi;
        end;

    else
       ## Here we embed the hexagon in W(5,q)
       ## Hendrik's form
  hvm := List([1..6], i -> [0,0,0,0,0,0]*One(f));
  hvm{[1..3]}{[4..6]} := IdentityMat(3, f);
  hvm{[4..6]}{[1..3]} := IdentityMat(3, f);
  hvmform := BilinearFormByMatrix(hvm, f);
  ps := PolarSpace(hvmform);
  # UnderlyingObject will return a cvec.
  reppointvect := UnderlyingObject(RepresentativesOfElements(ps)[1]);

  ## Hendrik's canonical line is <(1,0,0,0,0,0), (0,0,0,0,0,1)>
  replinevect := [[1,0,0,0,0,0], [0,0,0,0,0,1]] * One(f);
  TriangulizeMat(replinevect);
  #ConvertToMatrixRep(replinevect, f); #is useless now.
        shadpoint := function( pt )
            local planevec, flag, plane, f;
            f := BaseField( pt );
            planevec := SplitCayleyPointToPlane5( Unpack(pt!.obj), f );
            plane := VectorSpaceToElement(PG(5,f),planevec);
            flag := FlagOfIncidenceStructure(PG(5,f),[pt,plane]);
            return List(ShadowOfFlag(PG(5,f),flag,2),x->Wrap(pt!.geo,2,Unwrap(x)));
        end;

        dist := function(el1,el2)
            local x,y;
            if el1=el2 then
                return 0;
            elif el1!.type = 1 and el2!.type = 1 then
                y := VectorSpaceToElement(PG(5,f), SplitCayleyPointToPlane5(Unpack(el2!.obj),f)); #PG(5,f): avoids some unnecessary checks
                if el1 in y then
                    return 2;
                else
                    x := VectorSpaceToElement(PG(5,f), SplitCayleyPointToPlane5(Unpack(el1!.obj),f));
                    if ProjectiveDimension(Meet(x,y)) = 0 then
                        return 4;
                    else
                        return 6;
                    fi;
                fi;
            elif el1!.type = 2 and el2!.type = 2 then
                if ProjectiveDimension(Meet(el1,el2)) = 0 then
                    return 2;
                fi;
                x := TangentSpace(ps,el1);
                if ProjectiveDimension(Meet(x,el2)) = 0 then
                    return 4;
                else
                    return 6;
                fi;
            elif el1!.type = 1 and el2!.type = 2 then
                if el1 in el2 then
                    return 1;
                fi;
                x := VectorSpaceToElement(PG(5,f), SplitCayleyPointToPlane5(Unpack(el1!.obj),f));
                if ProjectiveDimension(Meet(x,el2)) = 0 then
                    return 3;
                else
                    return 5;
                fi;
            else
                return dist(el2,el1);
            fi;
        end;

    fi;
 #now comes the cmatrixification of the replinevect
 replinevect := NewMatrix(IsCMatRep,f,Length(reppointvect),replinevect);

 listels := function(gp,j)
  local coll,reps;
  coll := CollineationGroup(gp);
  reps := RepresentativesOfElements( gp );
  return Enumerate(Orb(coll, reps[j], OnProjSubspaces));
 end;

 shadline := function( l )
  return List(Points(ElementToElement(AmbientSpace(l),l)),x->Wrap(l!.geo,1,x!.obj));
 end;

 #in the next line, we set the data fields for the geometry. We have to take into account that H(q) will also be
 #a Lie geometry, so it needs more data fields than a GP. But we can derive this information from ps.
 geo := rec( pointsobj := [], linesobj := [], incidence:= \*, listelements := listels, basefield := BaseField(ps),
  dimension := Dimension(ps), vectorspace := UnderlyingVectorSpace(ps), polarspace := ps,
  shadowofpoint := shadpoint, shadowofline := shadline, distance := dist);
    ty := NewType( GeometriesFamily, IsClassicalGeneralisedHexagon and IsGeneralisedPolygonRep );
    Objectify( ty, geo );
    SetAmbientSpace(geo, AmbientSpace(ps));
    SetAmbientPolarSpace(geo,ps);
    SetOrder(geo, [Size(f), Size(f)]);
    SetTypesOfElementsOfIncidenceStructure(geo, ["point","line"]);
    SetRankAttr(geo, 2);

    #now we are ready to pack the representatives of the elements, which are also elements of a polar space.
    #recall that reppointvect and replinevect are triangulized.
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.54 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge