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 114 kB image not shown  

Quelle  polarspace.gi   Sprache: unbekannt

 
#############################################################################
##
##  polarspace.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 polar spaces
##
#############################################################################

#############################################################################
# Low level help methods:
#############################################################################

FINING.LimitForCanComputeActionOnPoints := 1000000;
FINING.Fast := true;

#############################################################################
# Constructor method (not for users)!:
#############################################################################

# CHECKED 20/09/11 jdb
#############################################################################
#O  Wrap( <geo>, <type>, <o> )
# This is an internal subroutine which is not expected to be used by the user;
# they would be using VectorSpaceToElement. Recall that Wrap is declared in 
# geometry.gd. 
##
InstallMethod( Wrap, 
 "for a polar space and an object",
 [IsClassicalPolarSpace, IsPosInt, IsObject],
 function( geo, type, o )
  local w;
  w := rec( geo := geo, type := type, obj := o );
  Objectify( NewType( SoPSFamily, IsElementOfIncidenceStructure and 
  #Objectify( NewType( SoCPSFamily, IsElementOfIncidenceStructure and #keep this, maybe for future use.
  IsElementOfIncidenceStructureRep and IsSubspaceOfClassicalPolarSpace ), w );
    return w;
 end );

#############################################################################
# Constructor methods for polar spaces.
#############################################################################

# CHECKED 11/10/11 jb + jdb
#############################################################################
#O  PolarSpace( <m>, <f>, <g>, <act> )
# This method returns a polar space with a lot of knowledge. most likely not for user.
# <m> is a sesquilinear form. Furthermore, a field <f>, a group <g> and an action 
# function <act> are given.
##
InstallMethod( PolarSpace, 
 "for a sesquilinear form, a field, a group and an action function",
 [ IsSesquilinearForm, IsField, IsGroup, IsFunction ],
 function( m, f, g, act )
  local geo, ty, gram, eq, r, i1, i2, r2, fam, j, flag;
  if IsDegenerateForm( m ) then 
   Error("Form is degenerate");
  elif IsPseudoForm( m ) then
   Error("No Polar space can be associated with a pseudo form");
  fi;
  gram := m!.matrix;
  geo := rec( basefield := f, dimension := Length(gram)-1,
     vectorspace := FullRowSpace(f,Length(gram)) );
  if IsHermitianForm(m) then
   flag := IsHermitianVariety;
  else
   flag := IsQuadraticVariety;
  fi;
  if not IsAlternatingForm(m) then
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and flag);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep and flag);
   fi;
  else
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep);
   fi;
  fi;
  # at this stage, we are sure that if m is a bilinear form and the characteristic is even, 
  # then m will be symplectic and PolynomialOfForm(m) will produce an error.
  # on the other hand, if m is symplectic and the characteristic is odd, then PolynomialOfForm
  # will produce a 0*Z(q). 
  if IsEvenInt(Size(f)) and IsBilinearForm(m) then  
   eq := Zero(f);
  else
   eq := PolynomialOfForm( m );
  fi;
  if IsZero(eq) then
   i1 := List([1..Length(gram)],i->Concatenation("x",String(i)));
   i2 := List([1..Length(gram)],i->Concatenation("y",String(i)));
   #r := PolynomialRing(f,Concatenation(i1,i2):old);     ## there was an error here for gap4r5
   #i2 := IndeterminatesOfPolynomialRing(r){[Length(gram)+1..2*Length(gram)]};
   #there was a proble with the above lines. If say x_4 existed already, and i1 just ran until 3, than
   # x_4 got changed by y_1, which caused all polynomials in r to change also, which caused funny printing behaviour.
   # the 10000 is completely arbitrary, I guess nobody will use the first 10000 variables in forms, since nobody
   # will work in a 10000-dimensional vector space (I guess...).
   r := PolynomialRing(f,i1:old);     ## there was an error here for gap4r5
   i1 := IndeterminatesOfPolynomialRing(r){[1..Length(gram)]};
   r2 := PolynomialRing(f,[10001..10000+Length(gram)]:old);
   fam := FamilyObj(r2.1);
   for j in [1..Length(gram)] do
    SetIndeterminateName(fam,10000+j,i2[j]);
   od;
   i2 := IndeterminatesOfPolynomialRing(r2);
   eq := i1*gram*i2;
  fi;
  ObjectifyWithAttributes( geo, ty, 
        SesquilinearForm, m,
        CollineationGroup, g,
        CollineationAction, act,
        AmbientSpace, ProjectiveSpace(geo.dimension, f),
        EquationForPolarSpace, eq );
  return geo;
 end );

# CHECKED 11/10/11 jb + jdb
#############################################################################
#O  PolarSpaceStandard( <m>, <bool> )
# Method to crete a polar space using sesquilinear form <m>, where we know
# that this form is the standard one used in Fining. Not intended for users, 
# all checks are removed.
##
InstallMethod( PolarSpaceStandard, 
 "for a sesquilinear form",
 [ IsSesquilinearForm, IsBool ],
 function( m, bool )
  local geo, ty, gram, f, eq, r, i1, i2, r2, fam, j, flag;
  gram := m!.matrix;
  f := m!.basefield;
  geo := rec( basefield := f, dimension := Length(gram)-1,
    vectorspace := FullRowSpace(f,Length(gram)) );
  if IsHermitianForm(m) then
   flag := IsHermitianVariety;
  else
   flag := IsQuadraticVariety;
  fi;
  if not IsAlternatingForm(m) then
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and flag);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep and flag);
   fi;
  else
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep);
   fi;
  fi;
  # at this stage, we are sure that if m is a bilinear form and the characteristic is even, 
  # then m will be symplectic and PolynomialOfForm(m) will produce an error.
  # on the other hand, if m is symplectic and the characteristic is odd, then PolynomialOfForm
  # will produce a 0*Z(q). 
  if IsEvenInt(Size(f)) and IsBilinearForm(m) then  
   eq := Zero(f);
  else
   eq := PolynomialOfForm( m );
  fi;
  if IsZero(eq) then
   #Print("eq is zero\n");
   i1 := List([1..Length(gram)],i->Concatenation("x",String(i)));
   i2 := List([1..Length(gram)],i->Concatenation("y",String(i)));
   #r := PolynomialRing(f,Concatenation(i1,i2):old);     ## there was an error here for gap4r5
   #i2 := IndeterminatesOfPolynomialRing(r){[Length(gram)+1..2*Length(gram)]};
   #there was a proble with the above lines. If say x_4 existed already, and i1 just ran until 3, than
   # x_4 got changed by y_1, which caused all polynomials in r to change also, which caused funny printing behaviour.
   # the 10000 is completely arbitrary, I guess nobody will use the first 10000 variables in forms, since nobody
   # will work in a 10000-dimensional vector space (I guess...).
   r := PolynomialRing(f,i1:old);     ## there was an error here for gap4r5
   i1 := IndeterminatesOfPolynomialRing(r){[1..Length(gram)]};
   r2 := PolynomialRing(f,[10001..10000+Length(gram)]:old);
   fam := FamilyObj(r2.1);
   for j in [1..Length(gram)] do
    SetIndeterminateName(fam,10000+j,i2[j]);
   od;
   i2 := IndeterminatesOfPolynomialRing(r2);
   eq := i1*gram*i2;
  fi;
  ObjectifyWithAttributes( geo, ty, 
                            SesquilinearForm, m,
                            AmbientSpace, ProjectiveSpace(geo.dimension, f),
       EquationForPolarSpace, eq );
  if bool then
   SetIsStandardPolarSpace(geo,true); #if bool is false, we can use this operation to construct almost standard polar spaces :-)
  fi;
  return geo;
 end );

#############################################################################
#O  PolarSpaceStandard( <m>, <bool> )
# general method to create a polar space using quadratic form. Not intended 
# for the user. no checks.
##
InstallMethod( PolarSpaceStandard, 
 "for a quadratic form",
 [ IsQuadraticForm, IsBool ],
 function( m, bool )
  local geo, ty, gram, polar, f, flavour, eq, flag;
  f := m!.basefield;
  gram := m!.matrix;
  polar := AssociatedBilinearForm( m );
  geo := rec( basefield := f, dimension := Length(gram)-1,
     vectorspace := FullRowSpace(f,Length(gram)) );
  if WittIndex(m) = 2 then
   ty := NewType( GeometriesFamily,
     IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and IsProjectiveVariety);
  else ty := NewType( GeometriesFamily,
     IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsProjectiveVariety);
  fi;
  eq := PolynomialOfForm( m );
  ObjectifyWithAttributes( geo, ty, 
        QuadraticForm, m,
        SesquilinearForm, polar,
        AmbientSpace, ProjectiveSpace(geo.dimension, f),
        EquationForPolarSpace, eq );
  if bool then
   SetIsStandardPolarSpace(geo,true);
  fi;
  return geo;
 end );

# CHECKED 20/09/11 jdb
#############################################################################
#O  PolarSpace( <m> )
# general method to crete a polar space using sesquilinear form <m>. It is checked
# whether the form is not pseudo.##
##
InstallMethod( PolarSpace, 
 "for a sesquilinear form",
 [ IsSesquilinearForm ],
 function( m )
  local geo, ty, gram, f, eq, r, i1, i2, r2, fam, j, flag;  
  if IsDegenerateForm( m ) then 
   Error("Form is degenerate");
  elif IsPseudoForm( m ) then
   Error("No Polar space can be associated with a pseudo form");
  fi;
  gram := m!.matrix;
  f := m!.basefield;
  geo := rec( basefield := f, dimension := Length(gram)-1,
    vectorspace := FullRowSpace(f,Length(gram)) );
  if IsHermitianForm(m) then
   flag := IsHermitianVariety;
  else
   flag := IsQuadraticVariety;
  fi;
  if not IsAlternatingForm(m) then
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and flag);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep and flag);
   fi;
  else
   if WittIndex(m) = 2 then
    ty := NewType( GeometriesFamily,
      IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ);
    else ty := NewType( GeometriesFamily,
       IsClassicalPolarSpace and IsClassicalPolarSpaceRep);
   fi;
  fi;
  # at this stage, we are sure that if m is a bilinear form and the characteristic is even, 
  # then m will be symplectic and PolynomialOfForm(m) will produce an error.
  # on the other hand, if m is symplectic and the characteristic is odd, then PolynomialOfForm
  # will produce a 0*Z(q). 
  if IsEvenInt(Size(f)) and IsBilinearForm(m) then  
   eq := Zero(f);
  else
   eq := PolynomialOfForm( m );
  fi;
  if IsZero(eq) then
   #Print("eq is zero\n");
   i1 := List([1..Length(gram)],i->Concatenation("x",String(i)));
   i2 := List([1..Length(gram)],i->Concatenation("y",String(i)));
   #r := PolynomialRing(f,Concatenation(i1,i2):old);     ## there was an error here for gap4r5
   #i2 := IndeterminatesOfPolynomialRing(r){[Length(gram)+1..2*Length(gram)]};
   #there was a proble with the above lines. If say x_4 existed already, and i1 just ran until 3, than
   # x_4 got changed by y_1, which caused all polynomials in r to change also, which caused funny printing behaviour.
   # the 10000 is completely arbitrary, I guess nobody will use the first 10000 variables in forms, since nobody
   # will work in a 10000-dimensional vector space (I guess...).
   r := PolynomialRing(f,i1:old);     ## there was an error here for gap4r5
   i1 := IndeterminatesOfPolynomialRing(r){[1..Length(gram)]};
   r2 := PolynomialRing(f,[10001..10000+Length(gram)]:old);
   fam := FamilyObj(r2.1);
   for j in [1..Length(gram)] do
    SetIndeterminateName(fam,10000+j,i2[j]);
   od;
   i2 := IndeterminatesOfPolynomialRing(r2);
   eq := i1*gram*i2;
  fi;
  ObjectifyWithAttributes( geo, ty, 
                            SesquilinearForm, m,
                            AmbientSpace, ProjectiveSpace(geo.dimension, f),
       IsStandardPolarSpace, false,
       EquationForPolarSpace, eq );
  return geo;
 end );

# CHECKED 20/09/11 jdb
#############################################################################
#O  PolarSpace( <m> )
#general method to create a polar space using quadratic form. Possible in even
#and odd char.
##
InstallMethod( PolarSpace, 
 "for a quadratic form",
 [ IsQuadraticForm ],
 function( m )
  local geo, ty, gram, polar, f, flavour, eq;
  if IsSingularForm( m ) then 
   Error("Form is singular"); 
  fi;
  f := m!.basefield;
  gram := m!.matrix;
  polar := AssociatedBilinearForm( m );
  geo := rec( basefield := f, dimension := Length(gram)-1,
     vectorspace := FullRowSpace(f,Length(gram)) );
  if WittIndex(m) = 2 then
   ty := NewType( GeometriesFamily,
     IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and IsQuadraticVariety);
  else ty := NewType( GeometriesFamily,
     IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsQuadraticVariety);
  fi;
  eq := PolynomialOfForm(m);
  ObjectifyWithAttributes( geo, ty, 
        QuadraticForm, m,
        SesquilinearForm, polar,
        AmbientSpace, ProjectiveSpace(geo.dimension, f),
        IsStandardPolarSpace, false,
        EquationForPolarSpace, eq );
  return geo;
 end );

# CHECKED 20/09/11 jdb
#############################################################################
#O  PolarSpace( <m> )
# general method to setup a polar space using hermitian form. Is this method
# still necessary? Maybe not necessary, but maybe usefull, since we know slightly
# more properties of the polar space if we start from a hermitian form rather than
# from a sesquilinear form.
##
InstallMethod( PolarSpace, 
 "for a hermitian form",
 [ IsHermitianForm ],
 function( m )
  local geo, ty, gram, f, eq;
  if IsDegenerateForm( m ) then 
   Error("Form is degenerate");
  fi;
  gram := m!.matrix;
  f := m!.basefield;
  geo := rec( basefield := f, dimension := Length(gram)-1,
     vectorspace := FullRowSpace(f,Length(gram)) );
  if WittIndex(m) = 2 then
   ty := NewType( GeometriesFamily,
                  IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsClassicalGQ and IsHermitianVariety);
  else ty := NewType( GeometriesFamily,
                  IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianVariety);
  fi;
  eq := PolynomialOfForm(m);
  ObjectifyWithAttributes( geo, ty, 
                            SesquilinearForm, m,
                            AmbientSpace, ProjectiveSpace(geo.dimension, f),
       IsStandardPolarSpace, false,
       EquationForPolarSpace, eq );
  return geo;
 end );


#############################################################################
## Constructions of Canonical finite classical Polar Spaces
## Important remark. We use "Canonical" in the mathematical sense, i.e, a polar
## space that equals one of the "standard" polar spaces constructed by the methods
## below. So "Standard" refers to a particular form used to construct the polar space. 
## It is well known that two forms that are similar, i.e. differe on a constant factor,
## will yield the same polar space. So a polar space is canonical iff its forms is similar with
## the form of one of the polar spaces constructed with a method below. A polar space is 
## "standard" iff it is constructed with one of the methods below. So if the user
## uses his favorite form, his polar space can become canonical, but it can never become standard.
#############################################################################

#############################################################################
# Part I: A method to setup the representative of the maximal 
# subspaces for polar spaces of each type.
# Recall that the methods for methods for canonical gram matrices and canonical 
# quadratic forms are found in group.gi. All these methods are not intended for the user.
#############################################################################

# CHECKED 21/09/11 jdb
#############################################################################
#O  CanonicalOrbitRepresentativeForSubspaces( <type>, <d>, <f> )
## This function returns representatives for the
## maximal totally isotropic (singular) subspaces
## of the given canonical polar space
##
InstallMethod( CanonicalOrbitRepresentativeForSubspaces, 
 "for a string, an integer and a field",
 [IsString, IsPosInt, IsField],  
 function( type, d, f )
  local b, i, id, one, w, q, sqrtq;
  q := Size(f);
  id := IdentityMat(d, f);
  if type = "symplectic" then    
   b := List([1..d/2], i-> id[2*i-1] + id[2*i]);
  elif type = "hermitian" then     
   one := One(f);
   sqrtq := Sqrt(q);
      ## find element with norm -1
   w := First(AsList(f), t -> IsZero( t^(sqrtq+1) + one ) );
   if IsEvenInt(d) then   
    b := List([1..d/2], i-> w * id[2*i] + id[2*i-1]);
   else 
    b := List([1..(d-1)/2], i-> w * id[2*i] + id[2*i-1]);
   fi;
  elif type = "parabolic" then 
   b := id{List([1..(d-1)/2], i -> 2*i)};
  elif type = "hyperbolic" then 
   b := id{List([1..d/2], i -> 2*i-1)};
  elif type = "elliptic" then 
   b := id{List([1..(d/2-1)],i -> 2*i+1)};
  else Error( "type is unknown or not implemented");
  fi;
  return [b];
 end );

#############################################################################
# Part II: constructor methods, for the user of course.
#############################################################################

# CHECKED 21/09/11 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  EllipticQuadric( <d>, <f> )
# returns the standard elliptic quadrac. See CanonicalQuadraticForm and CanonicalGramMatrix
# for details on the standard.
##
InstallMethod( EllipticQuadric, 
 "for an integer and a field",
 [ IsPosInt, IsField ],
 function( d, f )
  local eq,m,types,max,reps,q,form,creps;
  q := Size(f);
  if IsEvenInt(d) then
   Error("dimension must be odd");
   return;
  fi;
  if IsEvenInt(q) then
   m := CanonicalQuadraticForm("elliptic", d+1, f);
   form := QuadraticFormByMatrix(m, f);
  else 
   m := CanonicalGramMatrix("elliptic", d+1, f);  
   form := BilinearFormByMatrix(m, f);  
  fi; 
        eq := PolarSpaceStandard( form, true );
  SetRankAttr( eq, (d-1)/2 );
  types := TypesOfElementsOfIncidenceStructure( AmbientSpace(eq) );
  SetTypesOfElementsOfIncidenceStructure(eq, types{[1..(d-1)/2]});
  SetIsEllipticQuadric(eq, true);
  SetIsCanonicalPolarSpace(eq, true);
  SetPolarSpaceType(eq, "elliptic");
  if RankAttr(eq) = 2 then
   SetOrder( eq, [q, q^2]);
  fi;
  max := CanonicalOrbitRepresentativeForSubspaces("elliptic", d+1, f)[1];

 ## Here we take the maximal totally isotropic subspace rep
 ## max and make representatives for lower dimensional subspaces
 ## it could be that max is empty, not Max of course, but the variable max. 

  if not IsEmpty(max) then
   reps := [ [max[1]] ]; #small change
   Append(reps, List([2..(d-1)/2], j -> max{[1..j]})); 
 ## We would like the representative to be stored as
 ## compressed matrices. Then they will be more efficient
 ## to work with.
   
   creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
   creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.
   
   #for m in reps do
   # if IsMatrix(m) then
   #  ConvertToMatrixRep(m,f);
   # else 
   #  ConvertToVectorRep(m,f);
   # fi;
   #od;   

    ## Wrap 'em up #can be done without using VectorSpaceToElement (and hence withou computations) now :-)
   reps := List([1..(d-1)/2], j -> Wrap(eq, j, creps[j]) ); #one more small change :-)
   SetRepresentativesOfElements(eq, reps);
  else;
   SetRepresentativesOfElements(eq, []);
  fi;
  SetClassicalGroupInfo( eq, rec( degree := (q^((d+1)/2)+1)*(q^((d+1)/2-1)-1)/(q-1) ) );  
  return eq;
 end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  EllipticQuadric( <d>, <q> )
# returns the standard elliptic quadric. See EllipticQuadric method above.
##
InstallMethod( EllipticQuadric,
 "for two positive inteters <d> and <q>", 
 [ IsPosInt, IsPosInt ],
 function( d, q )  
  return EllipticQuadric(d,GF(q));
 end );

# CHECKED 21/09/11 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  SymplecticSpace( <d>, <f> )
# returns the standard symplectic space. See CanonicalGramMatrix
# for details on the standard.
##
InstallMethod( SymplecticSpace,
 "for an integer and a field",
 [ IsPosInt, IsField ],
 function( d, f )
  local w,frob,m,types,max,reps,q,form,creps;
  if IsEvenInt(d) then
   Error("dimension must be odd");
   return;
  fi;

 ## put compressed matrices here also
  q := Size(f);
  m := CanonicalGramMatrix("symplectic", d+1, f);     
  w := PolarSpaceStandard( BilinearFormByMatrix(m, f), true );
  SetRankAttr( w, (d+1)/2 );
  types := TypesOfElementsOfIncidenceStructure(AmbientSpace(w));
  if RankAttr(w) = 2 then
   SetOrder( w, [q, q]);
  fi;
  SetTypesOfElementsOfIncidenceStructure(w,types{[1..(d+1)/2]});
  SetIsSymplecticSpace(w,true);
  SetIsCanonicalPolarSpace(w, true);
  SetPolarSpaceType(w, "symplectic");
  max := CanonicalOrbitRepresentativeForSubspaces("symplectic", d+1, w!.basefield)[1];    

    ## Here we take the maximal totally isotropic subspace rep
    ## max and make representatives for lower dimensional subspaces
  reps := [ [ max[1] ] ]; #small change
  Append(reps, List([2..(d+1)/2], j -> max{[1..j]}));  

    ## We would like the representative to be stored as
    ## compressed matrices. Then they will be more efficient
    ## to work with.

  creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
  creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.

  #for m in reps do
  # if IsMatrix(m) then
  #  ConvertToMatrixRep(m,f);
  # else 
  #  ConvertToVectorRep(m,f);
  # fi;
  #od;   

    ## Wrap 'em up
  reps := List([1..(d+1)/2], j -> Wrap(w, j, creps[j]) ); #one more small change :-)
  SetRepresentativesOfElements(w, reps);
        SetClassicalGroupInfo( w, rec(  degree := (q^(d+1)-1)/(q-1) ) );    
  return w;
 end );


# CHECKED 21/09/11 jdb
#############################################################################
#O  SymplecticSpace( <d>, <q> )
# returns the standard symplectic space. See SymplecticSpace method above.
##
InstallMethod(SymplecticSpace, 
 "for an integer and an integer",
 [ IsPosInt, IsPosInt ],
 function( d, q ) 
  return SymplecticSpace(d, GF(q));
 end );

# CHECKED 21/09/11 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  ParabolicQuadric( <d>, <f> )
# returns the standard parabolic quadric. See CanonicalQuadraticForm and CanonicalGramMatrix
# for details on the standard.
##
InstallMethod( ParabolicQuadric, 
 "for an integer and a field", 
 [ IsPosInt, IsField ],
 function( d, f )
  local pq,m,types,max,reps,q,form,creps;
  if IsOddInt(d) then
   Error("dimension must be even");
   return;
  fi;
  q := Size(f);
  if IsEvenInt(q) then
   m := CanonicalQuadraticForm("parabolic", d+1, f);
   form := QuadraticFormByMatrix(m, f);
  else 
   m := CanonicalGramMatrix("parabolic", d+1, f); 
   form := BilinearFormByMatrix(m, f);   
  fi; 
        pq := PolarSpaceStandard( form, true );
  SetRankAttr( pq, d/2 );
  types := TypesOfElementsOfIncidenceStructure( AmbientSpace(pq) );
  SetTypesOfElementsOfIncidenceStructure(pq, types{[1..d/2]});
  SetIsParabolicQuadric(pq, true);
  SetIsCanonicalPolarSpace(pq, true);
  SetPolarSpaceType(pq, "parabolic");
  if RankAttr(pq) = 2 then
   SetOrder( pq, [q, q]);
  fi;
  max := CanonicalOrbitRepresentativeForSubspaces("parabolic", d+1, f)[1];

    ## Here we take the maximal totally isotropic subspace rep
    ## max and make representatives for lower dimensional subspaces

  reps := [ [ max[1] ] ]; #small change
  Append(reps, List([2..d/2], j -> max{[1..j]}));  

    ## We would like the representative to be stored as
    ## compressed matrices. Then they will be more efficient
    ## to work with.
  creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
  creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.
  
  #for m in reps do
  # if IsMatrix(m) then
  #  ConvertToMatrixRep(m,f);
  # else 
  #  ConvertToVectorRep(m,f);
  # fi;
  #od;   

    ## Wrap 'em up
  reps := List([1..d/2], j -> Wrap(pq, j, creps[j]) ); #one more small change :-)
  SetRepresentativesOfElements(pq, reps);
        SetClassicalGroupInfo( pq, rec( degree := (q^(d/2)-1)/(q-1)*(q^((d+2)/2-1)+1) ) );   
  return pq;
 end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  ParabolicQuadric( <d>, <q> )
# returns the standard parabolic quadric. See ParabolicQuadric method above.
##
InstallMethod( ParabolicQuadric,
 "for two integers",
 [ IsPosInt, IsPosInt ],
 function( d, q ) 
  return ParabolicQuadric(d, GF(q));
 end );

# CHECKED 21/09/11 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  HyperbolicQuadric( <d>, <f> )
# returns the standard hyperbolic quadric. See CanonicalQuadraticForm and CanonicalGramMatrix
# for details on the standard.
##
InstallMethod( HyperbolicQuadric, 
 "for an integer and a field", 
 [ IsPosInt, IsField ],
 function( d, f )
  local hq,m,types,max,reps,q,form,creps;
  q := Size(f);
  if IsEvenInt(d) then
   Error("dimension must be odd");
   return;
  fi;
  if IsEvenInt(q) then
   m := CanonicalQuadraticForm("hyperbolic", d+1, f);
   form := QuadraticFormByMatrix(m, f);
  else 
   m := CanonicalGramMatrix("hyperbolic", d+1, f);    
   form := BilinearFormByMatrix(m, f);
  fi; 
  hq := PolarSpaceStandard( form, true );
  SetRankAttr( hq, (d+1)/2 );
  types := TypesOfElementsOfIncidenceStructure( AmbientSpace(hq) );
  SetTypesOfElementsOfIncidenceStructure(hq, types{[1..(d+1)/2]});
  SetIsCanonicalPolarSpace(hq, true);
  SetIsHyperbolicQuadric(hq, true);
  SetPolarSpaceType(hq, "hyperbolic");
  if RankAttr(hq) = 2 then
   SetOrder( hq, [q, 1]);
  fi;
  max := CanonicalOrbitRepresentativeForSubspaces("hyperbolic", d+1, f)[1];
  
    ## Here we take the maximal totally isotropic subspace rep
    ## max and make representatives for lower dimensional subspaces

  reps := [ [ max[1] ] ]; #small change
  Append(reps, List([2..(d+1)/2], j -> max{[1..j]}));  

    ## We would like the representative to be stored as
    ## compressed matrices. Then they will be more efficient
    ## to work with.

  creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
  creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.
  
  #for m in reps do
  # if IsMatrix(m) then
  #  ConvertToMatrixRep(m,f);
  # else 
  #  ConvertToVectorRep(m,f);
  # fi;
  #od;   

    ## Wrap 'em up
  reps := List([1..(d+1)/2], j -> Wrap(hq, j, creps[j]) ); #one more small change :-)
  SetRepresentativesOfElements(hq, reps);
        SetClassicalGroupInfo( hq, rec( degree := (q^((d+1)/2)-1)/(q-1)*(q^((d+1)/2-1)+1)) );
  return hq;
 end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  HyperbolicQuadric( <d>, <q> )
# returns the standard hyperbolic quadric. See HyperbolicQuadric method above.
##
InstallMethod(HyperbolicQuadric, 
 "for a two integers",
 [ IsPosInt, IsPosInt ],
 function( d, q ) 
  return HyperbolicQuadric(d, GF(q));
 end );

# CHECKED 21/09/11 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  HermitianPolarSpace( <d>, <f> )
# returns the standard hermitian variety. See CanonicalGramMatrix
# for details on the standard.
##
InstallMethod( HermitianPolarSpace, 
 "for an integer and a field", 
 [ IsPosInt, IsField ],
 function( d, f )
  local h,m,types,max,reps,q,creps,degree;
  if IsOddInt(DegreeOverPrimeField(f)) then
   Error("field order must be a square");
   return;
  fi;
  q := Sqrt(Size(f));
  m := CanonicalGramMatrix("hermitian", d+1, f);   
  h := PolarSpaceStandard( HermitianFormByMatrix(m, f), true );
  if d mod 2 = 0 then  
   SetRankAttr( h, d/2 );
  else
   SetRankAttr( h, (d+1)/2 );    
  fi;    
  types := TypesOfElementsOfIncidenceStructure( AmbientSpace(h) );
  SetTypesOfElementsOfIncidenceStructure(h, types{[1..RankAttr(h)]});
  SetIsHermitianPolarSpace(h, true);
  SetIsCanonicalPolarSpace(h, true);
  SetPolarSpaceType(h, "hermitian");
  if RankAttr(h) = 2 then
   if d = 3 then SetOrder( h, [q^2, q]); fi;
   if d = 4 then SetOrder( h, [q^2, q^3]); fi;
  fi;
  max := CanonicalOrbitRepresentativeForSubspaces("hermitian", d+1, f)[1];

    ## Here we take the maximal totally isotropic subspace rep
    ## max and make representatives for lower dimensional subspaces
  reps := [ [ max[1] ] ]; #small change
  Append(reps, List([2..RankAttr(h)], j -> max{[1..j]}));  

    ## We would like the representative to be stored as
    ## compressed matrices. Then they will be more efficient
    ## to work with.

  creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
  creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.

  #for m in reps do
  # if IsMatrix(m) then
  #  ConvertToMatrixRep(m,f);
  # else
  #  ConvertToVectorRep(m,f);  
  # fi;
  #od;   

    ## Wrap 'em up
  reps := List([1..RankAttr(h)], j -> Wrap(h, j, creps[j]) ); #one more small change :-)
  SetRepresentativesOfElements(h, reps);
  if d = 3 then
            degree := (q^3+1)*(q+1);
        else
            degree := (q^d-(-1)^d)*(q^(d+1)-(-1)^(d+1))/(q^2-1);
        fi;
        #SetClassicalGroupInfo( h, rec(  degree := (q^d-(-1)^d)*(q^(d+1)-(-1)^(d+1))/(q^2-1)) );
        SetClassicalGroupInfo( h, rec(  degree := degree ));
  return h;
 end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  HermitianPolarSpace( <d>, <q> )
# returns the standard hermitian polar space. See HermitianPolarSpace method above.
##
InstallMethod(HermitianPolarSpace,
 "for an two integers",
 [ IsPosInt, IsPosInt ],
 function( d, q ) 
  return HermitianPolarSpace(d, GF(q));
 end );

# ADDED 7/11/12 jdb
#############################################################################
#O  StandardPolarSpace( <ps> )
# returns the standard polar space isomorphic with <ps>.
##
InstallMethod( StandardPolarSpace, 
 "for a polar space",
 [ IsClassicalPolarSpace ],
 function( ps )
  local type, standard,d,f;
  d := ps!.dimension;
  f := ps!.basefield;
  type := PolarSpaceType( ps );
  if type = "hermitian" then
   standard := HermitianPolarSpace(d, f);               
   SetIsHermitianPolarSpace(ps, true);            
  elif type = "symplectic" then
   standard := SymplecticSpace(d, f);         
   SetIsSymplecticSpace(ps, true);
  elif type = "elliptic" then 
   standard := EllipticQuadric(d, f);         
   SetIsEllipticQuadric(ps, true);
  elif type = "parabolic" then
   standard := ParabolicQuadric(d, f);         
   SetIsParabolicQuadric(ps, true);
  elif type = "hyperbolic" then
   standard := HyperbolicQuadric(d, f);         
   SetIsHyperbolicQuadric(ps, true);
  fi;
  return standard;
 end );

# ADDED 30/3/14 jdb
#############################################################################
#O  IsCanonicalPolarSpace( <ps> )
# returns true if <ps> is canonical. Remind that canonical means similar to
# standard: in geometrical terms: the same geometry as a standard polar space
# with an underlying form that differs a factor with a standard form.
# Calling this operation also makes sure the ClassicalGroupInfo is set and
# the correct property. This mechanism makes sure that when a user constructs
# his favorite-non-standard-but-canonical polar space, it is recognised by
# FinInG, and only once a base change computation by forms will be done.
##
InstallMethod( IsCanonicalPolarSpace,
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
 local type, form, d, bf, st, gram, c1, c2, order, q, result;
 type := PolarSpaceType(ps); #a base change is computed in forms.
 d := ps!.dimension;
 bf := ps!.basefield;
 if HasQuadraticForm(ps) then
  form := QuadraticForm(ps);
  gram := GramMatrix(form);
  st := CanonicalQuadraticForm(type, d+1, bf); #returns a matrix.
 else
  form := SesquilinearForm(ps);
  gram := GramMatrix(form);
  st := CanonicalGramMatrix(type, d+1, bf);
 fi;
 q := Size(bf);
 if type = "elliptic" then
  SetIsEllipticQuadric(ps,true);
  order := (q^((d+1)/2)+1)*(q^((d+1)/2-1)-1)/(q-1);
 elif type = "parabolic" then
  SetIsParabolicQuadric(ps,true);
  order := (q^(d/2)-1)/(q-1)*(q^((d+2)/2-1)+1);
 elif type = "hyperbolic" then
  SetIsHyperbolicQuadric(ps,true);
  order := (q^((d+1)/2)-1)/(q-1)*(q^((d+1)/2-1)+1);
 elif type = "symplectic" then
  SetIsSymplecticSpace(ps,true);
  order := (q^(d+1)-1)/(q-1);
 elif type = "hermitian" then
  SetIsHermitianPolarSpace(ps,true);
  q := Sqrt(q);
        if d=3 then
            order := (q^3+1)*(q+1);
        else
            order := (q^d-(-1)^d)*(q^(d+1)-(-1)^(d+1))/(q^2-1);
        fi;
 fi;
 c1 := First(gram[1],x->not IsZero(x));
 if c1 = fail then
  return false;
 fi;
 c2 := First(st[1],x->not IsZero(x));
 result :=  c1*st = c2*gram;
 if result then
  SetClassicalGroupInfo( ps, rec(  degree := order ) );
 fi;
 return result;
end );

# ADDED 7/11/12 jdb
# Cmat adapted 20/3/14
#############################################################################
#O  CanonicalPolarSpace( <ps> )
# assume that f is the form determining <ps>, then this operation returns a 
# polar space <geo> determined by a form isometric with f, so <geo> is canonical 
# but not necessarily standard.
##
InstallMethod( CanonicalPolarSpace, 
 "for a polar space",
 [ IsClassicalPolarSpace ],
 function( ps )
  local type, canonicalps,d,f,form1,form2,isometric,b,mat1,mat2,canonicalmatrix,canonicalform, pq,types,max,reps,m,q,gram,creps;
  d := ps!.dimension;
  f := ps!.basefield;
  q := Size(f);
  type := PolarSpaceType( ps );
  if type = "hermitian" then
   canonicalps := HermitianPolarSpace(d, f);               
   SetIsHermitianPolarSpace(ps, true);            
  elif type = "symplectic" then
   canonicalps := SymplecticSpace(d, f);         
   SetIsSymplecticSpace(ps, true);
  elif type = "elliptic" then 
   canonicalps := EllipticQuadric(d, f);         
   SetIsEllipticQuadric(ps, true);
  elif type = "parabolic" then
   canonicalps := ParabolicQuadric(d, f);         
   SetIsParabolicQuadric(ps, true);
  elif type = "hyperbolic" then
   canonicalps := HyperbolicQuadric(d, f);         
   SetIsHyperbolicQuadric(ps, true);
  fi;
  if IsOddInt(Size(f)) and type in ["parabolic"] then
   form1 := QuadraticForm( ps );
   isometric := IsometricCanonicalForm(form1); #be careful with the notion Canonical in Forms package, its meaning is different than canonical in FinInG :-)
   gram := GramMatrix(isometric);
   canonicalmatrix := gram[1,1]*CanonicalGramMatrix("parabolic", d+1, f); 
   canonicalform := BilinearFormByMatrix(canonicalmatrix, f);
   canonicalps := PolarSpaceStandard( canonicalform, false );
   SetRankAttr( canonicalps, d/2 );
   types := TypesOfElementsOfIncidenceStructure( AmbientSpace(canonicalps) );
   SetTypesOfElementsOfIncidenceStructure(canonicalps, types{[1..d/2]});
   SetIsParabolicQuadric(canonicalps, true);
   SetIsCanonicalPolarSpace(canonicalps, true);
   SetIsStandardPolarSpace(canonicalps, false);
   SetPolarSpaceType(canonicalps, "parabolic");
   if RankAttr(canonicalps) = 2 then
    SetOrder( canonicalps, [q, q]);
   fi;
   max := CanonicalOrbitRepresentativeForSubspaces("parabolic", d+1, f)[1];

    ## Here we take the maximal totally isotropic subspace rep
    ## max and make representatives for lower dimensional subspaces

   reps := [ [ max[1] ] ]; #small change
   Append(reps, List([2..d/2], j -> max{[1..j]}));  

    ## We would like the representative to be stored as
    ## compressed matrices. Then they will be more efficient
    ## to work with.
  
   creps := List(reps,x->NewMatrix(IsCMatRep, f, d+1, x));
   creps[1] := creps[1][1]; #max is not empty, first element should always be a 1xn matrix->cvec.

   #for m in reps do
   # if IsMatrix(m) then
   #  ConvertToMatrixRep(m,f);
   # else 
   #  ConvertToVectorRep(m,f);
   # fi;
   #od;   

    ## Wrap 'em up
   reps := List([1..d/2], j -> Wrap(canonicalps, j, creps[j]) ); #one more small change :-)
   SetRepresentativesOfElements(canonicalps, reps);
   SetClassicalGroupInfo( canonicalps, rec( degree := (q^(d/2)-1)/(q-1)*(q^((d+2)/2-1)+1) ) );
  fi;
  return canonicalps;
end );   


#############################################################################
# methods for some attributes.
#############################################################################
 
# CHECKED 25/09/11 jdb
#############################################################################
#A  QuadraticForm( <ps> )
# returns the quadratic form of which the polar space <ps> is the geometry.
# this is usefull since there are generic methods (q odd and even) thinkable 
# for orthogonal polar spaces. In such a case, we must use the quadratic form
# in the even case, and we can use it in the odd case. A typical example are 
# the enumerators. 
# IMPORTANT: this method will only be used when q is odd (and <ps> is orthogonal
# of course). In the q even case, the attribute will be set upon creation of the 
# polar space.
##
InstallMethod( QuadraticForm, 
 "for a polar space",
 [ IsClassicalPolarSpace ],
 function(ps)
  local form;
  form := SesquilinearForm(ps);
  if form!.type <> "orthogonal" then
   Error( "No quadratic form can be associated to this polar space" );
  fi;
  return QuadraticFormByBilinearForm(SesquilinearForm(ps));
 end );


# CHECKED 20/09/11 jdb
#############################################################################
#A  PolarSpaceType( <ps> )
# type of a polar space: see manual and conventions for orthogonal polar spaces.
##
InstallMethod( PolarSpaceType, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local ty, form, sesq;
  if HasQuadraticForm( ps ) then 
   form := QuadraticForm( ps );
  else 
   form := SesquilinearForm( ps );
  fi;
  ty := form!.type;
  if ty = "orthogonal" or ty = "quadratic" then
   if IsParabolicForm( form ) then
    ty := "parabolic";
   elif IsEllipticForm( form ) then
    ty := "elliptic";
   else
    ty := "hyperbolic";
   fi;
  fi;
  return ty;
 end );

# CHECKED 20/09/11 jdb
#############################################################################
#A  CompanionAutomorphism( <ps> )
# companion automorphism of polar space, i.e. the companion automorphism of 
# the sesquilinear form determining the polar space. If the form is quadratic, 
# or not hermitian, then the trivial automorphism is returned.
##
InstallMethod( CompanionAutomorphism, 
 "for a polar space",
 [ IsClassicalPolarSpace ],
 function( ps )
  local aut, type;
  type := PolarSpaceType( ps );
  aut := FrobeniusAutomorphism(ps!.basefield);
  if type = "hermitian" then
   aut := aut ^ (Order(aut)/2);
  else
   aut := aut ^ 0;
  fi;
  return aut;
 end );

#############################################################################
# jdb and ml will change ViewObj/PrintObj/Display methods now.`
# The ViewString is used e.g. in the ViewObj for flags.
#############################################################################

InstallMethod( ViewObj, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( p )
  Print("<polar space in ",AmbientSpace(p),": ",EquationForPolarSpace(p),"=0 >");
 end );

InstallMethod( ViewString, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( p )
  return Concatenation("<polar space in ",ViewString(AmbientSpace(p)),": ",String(EquationForPolarSpace(p)),"=0 >");
 end );

InstallMethod( ViewObj,
 "for an elliptic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric],
 function( p )
  Print("Q-(",p!.dimension,", ",Size(p!.basefield),"): ",EquationForPolarSpace(p),"=0");
 end );

InstallMethod( ViewObj,
 "for a standard elliptic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric and IsStandardPolarSpace],
 function( p )
  Print("Q-(",p!.dimension,", ",Size(p!.basefield),")");
 end );
 
InstallMethod( ViewString, 
 "for a standard elliptic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric and IsStandardPolarSpace],
 function( p )
  return Concatenation("Q-(",String(p!.dimension),", ",String(Size(p!.basefield)),")");
 end );

InstallMethod( ViewString, 
 "for an elliptic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric],
 function( p )
  return Concatenation("Q-(",String(p!.dimension),", ",
    String(Size(p!.basefield)),"): ",String(EquationForPolarSpace(p)),"=0");
 end );

InstallMethod( ViewObj,
 "for a symplectic space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace],
    function( p )
  Print("W(",p!.dimension,", ",Size(p!.basefield),"): ",EquationForPolarSpace(p),"=0");
 end );

InstallMethod( ViewObj,
 "for a standard symplectic space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace and IsStandardPolarSpace],
    function( p )
  Print("W(",p!.dimension,", ",Size(p!.basefield),")");
 end );

InstallMethod( ViewString, 
 "for a standard symplectic space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace and IsStandardPolarSpace],
 function( p )
  return Concatenation("W(",String(p!.dimension),", ",String(Size(p!.basefield)),")");
 end );

InstallMethod( ViewString, 
 "for a symplectic space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace],
 function( p )
  return Concatenation("W(",String(p!.dimension),", ",String(Size(p!.basefield)),"): ",
    EquationForPolarSpace(p),"=0");
 end );

InstallMethod( ViewObj,
 "for a parabolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric ],
    function( p )
  Print("Q(",p!.dimension,", ",Size(p!.basefield),"): ",EquationForPolarSpace(p),"=0");
 end);

InstallMethod( ViewObj,
 "for a standard parabolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric and IsStandardPolarSpace ],
    function( p )
  Print("Q(",p!.dimension,", ",Size(p!.basefield),")");
 end);

InstallMethod( ViewString, 
 "for a standard parabolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric and IsStandardPolarSpace ],
 function( p )
  return Concatenation("Q(",String(p!.dimension),", ",String(Size(p!.basefield)),")");
 end );

InstallMethod( ViewString, 
 "for a standard parabolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric ],
 function( p )
  return Concatenation("Q(",String(p!.dimension),", ",String(Size(p!.basefield)),"): ",
   String(EquationForPolarSpace(p)),"=0");
 end );

InstallMethod( ViewObj,
 "for a parabolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric ],
    function( p )
  Print("Q(",p!.dimension,", ",Size(p!.basefield),"): ",EquationForPolarSpace(p),"=0");
 end);

InstallMethod( ViewObj,
 "for a hyperbolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric ],
    function( p )
  Print("Q+(",p!.dimension,", ",Size(p!.basefield),"): ",EquationForPolarSpace(p),"=0");
 end);

InstallMethod( ViewObj,
 "for a standard hyperbolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric and IsStandardPolarSpace],
    function( p )
  Print("Q+(",p!.dimension,", ",Size(p!.basefield),")");
 end);

InstallMethod( ViewString, 
 "for a standard hyperbolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric and IsStandardPolarSpace],
 function( p )
  return Concatenation("Q+(",String(p!.dimension),", ",String(Size(p!.basefield)),")");
 end );

InstallMethod( ViewString, 
 "for a hyperbolic quadric",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric],
 function( p )
  return Concatenation("Q+(",String(p!.dimension),", ",
    String(Size(p!.basefield)),"): ",String(EquationForPolarSpace(p)),"=0");
 end );

InstallMethod( ViewObj,
 "for a hermitian variety",
 [IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace ],
    function( p )
  Print("H(",p!.dimension,", ",Sqrt(Size(p!.basefield)),"^2): ",EquationForPolarSpace(p),"=0");
 end);

InstallMethod( ViewObj,
 "for a standard hermitian variety",
 [IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace and IsStandardPolarSpace],
    function( p )
  Print("H(",p!.dimension,", ",Sqrt(Size(p!.basefield)),"^2)");
    end);

InstallMethod( ViewString, 
 "for a standard hermitian quadric",
 [IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace and IsStandardPolarSpace],
 function( p )
  return Concatenation("H(",String(p!.dimension),", ",String(Sqrt(Size(p!.basefield))),"^2)");
 end );

InstallMethod( ViewString, 
 "for a hermitian quadric",
 [IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace],
 function( p )
  return Concatenation("H(",String(p!.dimension),", ",String(Sqrt(Size(p!.basefield))),"^2): ",
   EquationForPolarSpace(p),"=0");
 end );

InstallMethod( PrintObj, [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
  function( p )
    Print("PolarSpace(\n");
    if HasQuadraticForm(p) then
       Print(QuadraticForm(p));
    else
       Print(SesquilinearForm(p));
    fi;
    Print(", ", p!.basefield, " )");
  end );

InstallMethod( Display, [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
# fixed the output for rank (11/11/14 ml)
  function( p )
    Print("<polar space of rank ",RankAttr(p)," in PG(", p!.dimension, ", ", Size(p!.basefield), ")",">\n");
    if HasQuadraticForm(p) then
       Display(QuadraticForm(p));
    fi;
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

InstallMethod( PrintObj,
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric ],
        function( p )
          Print("EllipticQuadric(",p!.dimension,",",p!.basefield,"): ",EquationForPolarSpace(p),"=0");
        end );

InstallMethod( Display, 
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsEllipticQuadric ],
  function( p )
    Print("Q-(",p!.dimension,", ",Size(p!.basefield),")\n");
    if HasQuadraticForm(p) then
       Display(QuadraticForm(p));
    fi;
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

InstallMethod( PrintObj,
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace ],
        function( p )
          Print("SymplecticSpace(",p!.dimension,",",p!.basefield,"): ",EquationForPolarSpace(p),"=0");
  end);

InstallMethod( Display, 
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsSymplecticSpace ],
  function( p )
    Print("W(",p!.dimension,", ",Size(p!.basefield),")\n");
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

InstallMethod( PrintObj,
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric ],
        function( p )
          Print("ParabolicQuadric(",p!.dimension,",",p!.basefield,"): ",EquationForPolarSpace(p),"=0");
  end);

InstallMethod( Display, 
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsParabolicQuadric ],
  function( p )
    Print("Q(",p!.dimension,", ",Size(p!.basefield),")\n");
    if HasQuadraticForm(p) then
       Display(QuadraticForm(p));
    fi;
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

InstallMethod( PrintObj,
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric ],
        function( p )
          Print("HyperbolicQuadric(",p!.dimension,",",p!.basefield,"): ",EquationForPolarSpace(p),"=0");
        end);

InstallMethod( Display, 
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHyperbolicQuadric ],
  function( p )
    Print("Q+(",p!.dimension,", ",Size(p!.basefield),")\n");
    if HasQuadraticForm(p) then
       Display(QuadraticForm(p));
    fi;
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

InstallMethod( PrintObj,
  [IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace ],
        function( p )
          Print("HermitianPolarSpace(",p!.dimension,",",p!.basefield,"): ",EquationForPolarSpace(p),"=0");
        end);

InstallMethod( Display, 
  [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep and IsHermitianPolarSpace ],
  function( p )
    Print("H(",p!.dimension,", ",Size(p!.basefield),")\n");
    Display(SesquilinearForm(p));
    #if HasDiagramOfGeometry( p ) then
    #   Display( DiagramOfGeometry( p ) );
    #fi;
  end );

#############################################################################
## The following methods are needed for "naked" polar spaces; those
## that on conception are devoid of many of the attributes that
## the "canonical" polar spaces exhibit (see the code for the
## "SymplecticSpace" as an example).
#############################################################################

# CHECKED 21/09/11 jdb
#############################################################################
#O  IsomorphismCanonicalPolarSpace( <ps> )
# This method returns a geometry morphism that is in fact the coordinate transformation
# going FROM the standard polar space TO the given polar space <ps>
##
InstallMethod( IsomorphismCanonicalPolarSpace, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local d, f, type, canonical, iso, info;
  d := ps!.dimension;
  f := ps!.basefield;
  type := PolarSpaceType( ps );
  if type = "hermitian" then
   canonical := HermitianPolarSpace(d, f);               
   SetIsHermitianPolarSpace(ps, true);            
  elif type = "symplectic" then
   canonical := SymplecticSpace(d, f);         
   SetIsSymplecticSpace(ps, true);
  elif type = "elliptic" then 
   canonical := EllipticQuadric(d, f);         
   SetIsEllipticQuadric(ps, true);
  elif type = "parabolic" then
   canonical := ParabolicQuadric(d, f);         
   SetIsParabolicQuadric(ps, true);
  elif type = "hyperbolic" then
   canonical := HyperbolicQuadric(d, f);         
   SetIsHyperbolicQuadric(ps, true);
  fi;
  iso := IsomorphismPolarSpacesNC(canonical, ps, false);      ## jb: no longer computes nice monomorphism here
  info := ClassicalGroupInfo( canonical );
  SetClassicalGroupInfo( ps, rec( degree := info!.degree ) );
  return iso;
 end );

#############################################################################
#O  IsomorphismCanonicalPolarSpaceWithIntertwiner( <ps> )
# This method returns a geometry morphism that is in fact the coordinate transformation
# going FROM the standard polar space TO the given polar space <ps>, with intertwiner
##
InstallMethod( IsomorphismCanonicalPolarSpaceWithIntertwiner, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local d, f, type, canonical, iso, info;
  d := ps!.dimension;
  f := ps!.basefield;
  type := PolarSpaceType( ps );
  if type = "hermitian" then
   canonical := HermitianPolarSpace(d, f);               
   SetIsHermitianPolarSpace(ps, true);            
  elif type = "symplectic" then
   canonical := SymplecticSpace(d, f);         
   SetIsSymplecticSpace(ps, true);
  elif type = "elliptic" then 
   canonical := EllipticQuadric(d, f);         
   SetIsEllipticQuadric(ps, true);
  elif type = "parabolic" then
   canonical := ParabolicQuadric(d, f);         
   SetIsParabolicQuadric(ps, true);
  elif type = "hyperbolic" then
   canonical := HyperbolicQuadric(d, f);         
   SetIsHyperbolicQuadric(ps, true);
  fi;
  iso := IsomorphismPolarSpacesNC(canonical, ps, true); 
  info := ClassicalGroupInfo( canonical );
  SetClassicalGroupInfo( ps, rec( degree := info!.degree ) );
  return iso;
 end );

#############################################################################
#More attributes...
#############################################################################

# CHECKED 21/09/11 jdb
#############################################################################
#O  RankAttr( <ps> )
# returns the rank of the polar space <ps>, which is the Witt index of the
# defining form.
##
InstallMethod( RankAttr,
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local iso;
  iso := IsomorphismCanonicalPolarSpace( ps );
  return RankAttr(Source(iso)!.geometry);
  end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  TypesOfElementsOfIncidenceStructure( <ps> )
# Well known method that returns a list with the names of the elements of 
# the polar space <ps>
##
InstallMethod( TypesOfElementsOfIncidenceStructure, 
 "for a polar space ",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local iso;
  iso := IsomorphismCanonicalPolarSpace( ps );
  return TypesOfElementsOfIncidenceStructure(Source(iso)!.geometry);
 end );

#The next two methods are wrong. THe TypesOfElementsOfIncidenceStructure are determined by the
#rank of the polar space, not the projective dimenion.
#InstallMethod( TypesOfElementsOfIncidenceStructure, "for a polar space", 
#  [IsClassicalPolarSpace],
#  function( ps )
#    local d,i,types;
#    types := ["point"];
#    d := ProjectiveDimension(ps);
#    if d >= 2 then Add(types,"line"); fi;
#    if d >= 3 then Add(types,"plane"); fi;
#    if d >= 4 then Add(types,"solid"); fi;
#    for i in [5..d] do
#        Add(types,Concatenation("proj. subspace of dim. ",String(i-1)));
#    od;
#    return types;
#  end );

#InstallMethod( TypesOfElementsOfIncidenceStructurePlural, "for a polar space",
#  [IsClassicalPolarSpace],
#  function( ps )
#    local d,i,types;
#    types := ["points"];
#    d := ProjectiveDimension(ps);
#    if d >= 2 then Add(types,"lines"); fi;
#    if d >= 3 then Add(types,"planes"); fi;
#    if d >= 4 then Add(types,"solids"); fi;
#    for i in [5..d] do
#        Add(types,Concatenation("proj. subspaces of dim. ",String(i-1)));
#    od;
#    return types;
#  end );

# CHECKED 22/09/11 jdb
#############################################################################
#O  TypesOfElementsOfIncidenceStructurePlural( <ps> )
# Well known method that returns a list with the names of the elements of 
# the polar space <ps>
##
InstallMethod( TypesOfElementsOfIncidenceStructurePlural, 
 "for a polar space",  
 [IsClassicalPolarSpace],
 function( ps )
  local d,i,types;
  types := ["points"];
  d := Rank(ps);
  if d >= 2 then Add(types,"lines"); fi;
  if d >= 3 then Add(types,"planes"); fi;
  if d >= 4 then Add(types,"solids"); fi;
  for i in [5..d] do
   Add(types,Concatenation("proj. subspaces of dim. ",String(i-1)));
  od;
  return types;
 end );

# CHECKED 21/09/11 jdb
#############################################################################
#O  Order( <ps> )
# If <ps> has rank two, then it is a GQ, and we can ask its order.
##
InstallOtherMethod( Order, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  if RankAttr(ps) = 2 then
   return Order(Source(IsomorphismCanonicalPolarSpace(ps) )!.geometry );
  else
   Error("Rank is not 2");
  fi;
 end );
  
# CHECKED 21/09/11 jdb
#############################################################################
#O  RepresentativesOfElements( <ps> )
# returns an element of each type of the polar space <ps>
##
InstallMethod( RepresentativesOfElements, 
 "for a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep ],
 function( ps )
  local iso, reps;
  iso := IsomorphismCanonicalPolarSpace( ps );
  reps := RepresentativesOfElements( Source( iso )!.geometry );
  return ImagesSet(iso, reps);
 end );

#############################################################################
# one more operation...
#############################################################################

# CHECKED 21/09/11 jdb
#############################################################################
#O  \/( <ps>, <v> )
# returns the quotien space of the element <v>, which must be an element of the
# polar space <ps>
##
InstallOtherMethod(\/,
 "for a polar space and an element of a polar space",
 [ IsClassicalPolarSpace and IsClassicalPolarSpaceRep, IsSubspaceOfClassicalPolarSpace],
 function( ps, v )
  if not v in ps then 
   Error( "Subspace does not belong to the polar space" );
  fi;
  return Range( NaturalProjectionBySubspace( ps, v ) )!.geometry;
 end );

#############################################################################
# Counting the number of elements of the polar spaces
#############################################################################

# CHECKED 21/09/11 jdb
# question: can we not use the NumberOfTotallySingularSubspaces for this?
#############################################################################
#O  Size( <vs> )
# returns the number of elements on <vs>, a collection of elements of a polar
# space of a given type.
##
InstallMethod( Size, 
 "for a collection of elements of a polar space",
 [IsSubspacesOfClassicalPolarSpace],
 function( vs )
  local geom, q, d, m, ovnum, ordominus, numti, gauss, flavour;
  geom := vs!.geometry; 
  q := Size(vs!.geometry!.basefield);
  d := vs!.geometry!.dimension + 1;
  m := vs!.type;
  flavour := PolarSpaceType(geom);
        if flavour = "symplectic" then
   return Product(List([0..(m-1)],i->(q^(d-2*i)-1)/(q^(i+1)-1)));
  fi;
  if flavour = "elliptic" then
   gauss:=Product(List([0..(m-1)],i->(q^(d/2-1)-q^i)/(q^m-q^i)));
   numti:=gauss * Product(List([0..(m-1)],j->q^(d/2-j)+1));
   return numti;
  fi;
  if flavour = "hyperbolic" then
   gauss:=Product(List([0..(m-1)],i->(q^(d/2)-q^i)/(q^m-q^i)));
   numti:=gauss * Product(List([0..(m-1)],j->q^(d/2-1-j)+1));
   return numti;
  fi;
  if flavour = "parabolic" then
   gauss:=Product(List([0..(m-1)],i->(q^((d-1)/2)-q^i)/(q^m-q^i)));
   numti:=gauss * Product(List([0..(m-1)],j->q^( (d+1)/2-1-j)+1));
   return numti;
  fi;
  if flavour = "hermitian" then
   return Product(List([(d+1-2*m)..d],i->(Sqrt(q)^i-(-1)^i)))/
   Product(List([1..m],j->q^j-1 ));
  fi;
  Error("Unknown polar space type!");
 end );

#############################################################################
# Elements -- Subspaces
#############################################################################

## The following needs more work: I think it's ok now. jdb
## jb 19/02/2009: Just changed the compressed matrix methods
##               so that length 1 matrices are allowed.

###cmat methods need to be added here. VectorSpaceToElement checks wheter 
# a vectorspace really makes an element of a polar space by checking 
# whether it is totally isotropic. Therefore we need some forms functionality.
# Since forms is not working with cmat/cvecs, and this will not change, we have
# to unpack a cmat before piping it to forms. Hence it makes sens to create VectorSpaceToElement
# methods the lazy way: just unpack and pipe to an existing VectorSpaceToElement method.
###

# Added 20/3/14 jdb
#############################################################################
#O  VectorSpaceToElement( <geom>, <v> ) returns the elements in <geom> determined
# by the vectorspace <v>. 
##
InstallMethod( VectorSpaceToElement, 
 "for a polar space and a CMat",
 [IsClassicalPolarSpace, IsCMatRep],
 function( geom, v )
  return VectorSpaceToElement(geom,Unpack(v));
 end );
 
# Added 20/3/14 jdb
#############################################################################
#O  VectorSpaceToElement( <geom>, <v> ) returns the elements in <geom> determined
# by the vectorspace <v>. 
##
InstallMethod( VectorSpaceToElement, 
 "for a polar space and a cvec",
 [IsClassicalPolarSpace, IsCVecRep],
 function( geom, v )
  return VectorSpaceToElement(geom,Unpack(v));
 end );

# CHECKED 21/09/11 jdb
# cmat change 20/3/14.
# changed 19/01/16 (jdb): by a change of IsPlistRep, this method gets also
# called when using a row vector, causing a problem with TriangulizeMat.
# a solution was to add IsMatrix.
#############################################################################
#O  VectorSpaceToElement( <geom>, <v> ) returns the elements in <geom> determined
# by the vectorspace <v>. Several checks are built in. 
##
# JB: Fixed a strange error in here
# I had Q+(11,3) (with a different form than usual) and tried to wrap
# [ [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ] ]
# It kept on returning 0*Z(3).
# JDB: I kept John's historical note, but the code where the bug was, has disappeared with the cmat adaptation :-)
# Information on NewMatrix us here can be found in projectivespaces.gi, method for VectorSpaceToElement.
#
InstallMethod( VectorSpaceToElement, 
 "for a polar space and a Plist",
 [IsClassicalPolarSpace, IsPlistRep and IsMatrix],
 function( geom, v )
  local  x, n, i, y;
  ## when v is empty... 
  if IsEmpty(v) then
   Error("<v> does not represent any element");
  fi;
        if not IsMatrix(v) then #next 3 lines: patch of Max Horn (16/2/16)
            TryNextMethod();
        fi;

  x := MutableCopyMat(v);
  TriangulizeMat(x);
  ## dimension should be correct
  if Length(v[1]) <> geom!.dimension + 1 then
   Error("Dimensions are incompatible");
  fi;
  ## Remove zero rows. It is possible the the user
  ## has inputted a matrix which does not have full rank
        n := Length(x);
  i := 0;
  while i < n and ForAll(x[n-i], IsZero) do
   i := i+1; 
  od;
  if i = n then
   return EmptySubspace(geom);
  fi;
  x := x{[1..n-i]};
  #if we check later on the the subspace is an element of the polar space, then
  #the user cannot create the whole polar space like this, so I commented out the
  # next three lines.
  #if Length(x)=ProjectiveDimension(geom)+1 then
  # return geom;
  #fi;
        ## check here that it is in the polar space. 
  if HasQuadraticForm(geom) then
   if not IsTotallySingularSubspace(QuadraticForm(geom),x) then
    Error("<x> does not generate an element of <geom>");
   fi;
  else
   if not IsTotallyIsotropicSubspace(SesquilinearForm(geom),x) then
    Error("<x> does not generate an element of <geom>");
   fi;
  fi;
  y := NewMatrix(IsCMatRep,geom!.basefield,Length(x[1]),x);
  if Length(y) = 1 then
   return Wrap(geom, 1, y[1]);
  else
   return Wrap(geom, Length(y), y);
  fi;
 end );

# CHECKED 21/09/11
# cmat changed 20/3/14.
#############################################################################
#O  VectorSpaceToElement( <geom>, <v> ) returns the elements in <geom> determined
# by the vectorspace <v>. Several checks are built in. 
##
InstallMethod( VectorSpaceToElement, 
 "for a compressed GF(2)-matrix",
 [IsClassicalPolarSpace, IsGF2MatrixRep],
 function( geom, v )
  local  x, n, i, y;
  if IsEmpty(v) then
   Error("<v> does not represent any element");
  fi;
  x := MutableCopyMat(v);
  TriangulizeMat(x);
  ## remove zero rows
  n := Length(x);
  i := 0;
  while i < n and ForAll(x[n-i], IsZero) do
   i := i+1; 
  od;
  if i = n then
   return EmptySubspace(geom);
  fi;
  x := x{[1..n-i]};
  #x := x{[1..n-i]};
  #if we check later on the the subspace is an element of the polar space, then
  #the user cannot create the whole polar space like this, so I commented out the
  # next three lines.
  #if Length(x)=ProjectiveDimension(geom)+1 then
  # return geom;
  #fi;
        ## check here that it is in the polar space. 
  if HasQuadraticForm(geom) then
   if not IsTotallySingularSubspace(QuadraticForm(geom),x) then
    Error("<x> does not generate an element of <geom>");
   fi;
--> --------------------

--> maximum size reached

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

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