4 Constructing forms and basic functionality

In this chapter, all operations to construct sesquilinear and quadratic forms are listed, along with their basic attributes and properties.

`‣ IsBilinearForm` | ( category ) |

`‣ IsHermitianForm` | ( category ) |

`‣ IsSesquilinearForm` | ( category ) |

`‣ IsQuadraticForm` | ( category ) |

`‣ IsForm` | ( category ) |

`‣ IsForm` | ( category ) |

`‣ IsTrivialForm` | ( category ) |

The categories `IsBilinearForm`

and `IsHermitianForm`

are categories for bilinear and hermitian forms, respectively. They are disjoint and are both contained in the category `IsSesquilinearForm`

.

Quadratic forms are contained in the category `IsQuadraticForm`

. The categories `IsSesquilinearForm`

and `IsQuadraticForm`

are disjoint and are both contained in the category `IsForm`

.

The user is allowed to construct the trivial form (mapping all vectors to the zero element of the field). The trivial form is an object in the category `IsTrivialForm`

. This category is contained in `IsForm`

and disjoint from `IsSesquilinearForm`

and `IsQuadraticForm`

.

`‣ IsFormRep` | ( representation ) |

Every form is represented by a matrix, the base field and a string describing the ``type'' of the form.

`‣ BilinearFormByMatrix` ( matrix, field ) | ( operation ) |

`‣ BilinearFormByMatrix` ( matrix ) | ( operation ) |

Returns: a bilinear form

The argument `matrix` must be a symmetric, or skew-symmetric, square matrix over the finite field `field`. The argument `field` is an optional argument, and if it is not given, then we assume that the *defining field* of the bilinear form is the smallest field containing the entries of matrix. Below we give an example where the defining field can make a difference in some applications. As it is only possible to construct reflexive bilinear forms, it is checked whether the matrix `matrix` is symmetric or skew symmetric. If matrix `matrix` is not symmetric nor skew symmetric, then an error message is returned. The output is a bilinear form (i.e., an object in `IsBilinearForm`

) with Gram matrix `matrix` and defining field `field`. (See 3.1 for more on bilinear forms).

gap> mat := IdentityMat(4, GF(9)); [ [ Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0 ] ] gap> form := BilinearFormByMatrix(mat,GF(9)); < bilinear form > gap> Display(form); Bilinear form Gram Matrix: 1 . . . . 1 . . . . 1 . . . . 1 gap> mat := [[0*Z(2),Z(16)^12,0*Z(2),Z(4)^2,Z(16)^13], > [Z(16)^12,0*Z(2),0*Z(2),Z(16)^11,Z(16)], > [0*Z(2),0*Z(2),0*Z(2),Z(4)^2,Z(16)^3], > [Z(4)^2,Z(16)^11,Z(4)^2,0*Z(2),Z(16)^3], > [Z(16)^13,Z(16),Z(16)^3,Z(16)^3,0*Z(2) ]]; [ [ 0*Z(2), Z(2^4)^12, 0*Z(2), Z(2^2)^2, Z(2^4)^13 ], [ Z(2^4)^12, 0*Z(2), 0*Z(2), Z(2^4)^11, Z(2^4) ], [ 0*Z(2), 0*Z(2), 0*Z(2), Z(2^2)^2, Z(2^4)^3 ], [ Z(2^2)^2, Z(2^4)^11, Z(2^2)^2, 0*Z(2), Z(2^4)^3 ], [ Z(2^4)^13, Z(2^4), Z(2^4)^3, Z(2^4)^3, 0*Z(2) ] ] gap> form := BilinearFormByMatrix(mat,GF(16)); < bilinear form > gap> Display(form); Bilinear form Gram Matrix: z = Z(16) . z^12 . z^10 z^13 z^12 . . z^11 z^1 . . . z^10 z^3 z^10 z^11 z^10 . z^3 z^13 z^1 z^3 z^3 . gap> mat := [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]*Z(7)^0; [ [ Z(7)^0, 0*Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), Z(7)^0, 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7), Z(7)^0 ], [ 0*Z(7), 0*Z(7), Z(7)^0, 0*Z(7) ] ] gap> form := BilinearFormByMatrix(mat); < bilinear form > gap> WittIndex(form); 1 gap> form := BilinearFormByMatrix(mat,GF(49)); < bilinear form > gap> WittIndex(form); 2

`‣ QuadraticFormByMatrix` ( matrix, field ) | ( operation ) |

`‣ QuadraticFormByMatrix` ( matrix ) | ( operation ) |

Returns: a quadratic form

The argument `matrix` must be a square matrix over the finite field `field`. The argument `field` is an optional argument, and if it is not given, then we assume that the *defining field* of the bilinear form is the smallest field containing the entries of matrix. Below we give an example where the defining field can make a difference in some applications. Any square matrix determines a quadratic form, but the Gram matrix is recomputed so that it is an upper triangle matrix. The output is a quadratic form (i.e., an object in `IsQuadraticForm`

) with defining field `field`. (See 3.2 for more on bilinear forms).

gap> mat := [[1,0,0,0],[0,3,0,0],[0,0,0,6],[0,0,6,0]]*Z(7)^0; [ [ Z(7)^0, 0*Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7), Z(7)^3 ], [ 0*Z(7), 0*Z(7), Z(7)^3, 0*Z(7) ] ] gap> form := QuadraticFormByMatrix(mat,GF(7)); < quadratic form > gap> Display(form); Quadratic form Gram Matrix: 1 . . . . 3 . . . . . 5 . . . . gap> gf := GF(2^2); GF(2^2) gap> mat := InvariantQuadraticForm( SO(-1, 4, 4) )!.matrix; [ [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), Z(2^2)^2, Z(2)^0 ], [ 0*Z(2), 0*Z(2), 0*Z(2), Z(2^2)^2 ] ] gap> form := QuadraticFormByMatrix( mat, gf ); < quadratic form > gap> Display(form); Quadratic form Gram Matrix: z = Z(4) . 1 . . . . . . . . z^2 1 . . . z^2

The following example shows how using the argument `field` has influence on the properties of the constructed form.

gap> mat := > [[Z(2)^0,Z(2)^0,0*Z(2),0*Z(2)],[0*Z(2),Z(2)^0,0*Z(2),0*Z(2)], > [0*Z(2),0*Z(2),0*Z(2),Z(2)^0],[0*Z(2),0*Z(2),0*Z(2),0*Z(2)]]; [ [ Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] ] gap> form := QuadraticFormByMatrix(mat); < quadratic form > gap> WittIndex(form); 1 gap> form := QuadraticFormByMatrix(mat,GF(4)); < quadratic form > gap> WittIndex(form); 2

`‣ HermitianFormByMatrix` ( matrix, field ) | ( operation ) |

Returns: a quadratic form

The argument `matrix` must be a hermitian square matrix over the finite field `field`, and `field` has square order. The field must be specified, since we can only determine the smallest field containing the entries of `matrix`. As it is only possible to construct reflexive sesquilinear forms, it is checked whether the matrix is a hermitian matrix, and if not, an error message is returned. The output is a hermitian sesquilinear form (i.e., an object in `IsHermitianForm`

) with Gram matrix `matrix` and defining field `field`. (See 3.1 for more on hermitian forms).

gap> gf := GF(3^2); GF(3^2) gap> mat := IdentityMat(4, gf); [ [ Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0 ] ] gap> form := HermitianFormByMatrix( mat, gf ); < hermitian form > gap> Display(form); Hermitian form Gram Matrix: 1 . . . . 1 . . . . 1 . . . . 1 gap> mat := [[Z(11)^0,0*Z(11),0*Z(11)],[0*Z(11),0*Z(11),Z(11)], > [0*Z(11),Z(11),0*Z(11)]]; [ [ Z(11)^0, 0*Z(11), 0*Z(11) ], [ 0*Z(11), 0*Z(11), Z(11) ], [ 0*Z(11), Z(11), 0*Z(11) ] ] gap> form := HermitianFormByMatrix(mat,GF(121)); < hermitian form > gap> Display(form); Hermitian form Gram Matrix: 1 . . . . 2 . 2 .

Suppose that \(f\) is a sesquilinear form on an \(n\)-dimensional vectorspace. Consider a vector \(x\) with coordinates x_{1},...,x_{n} with x_{i} indeterminates over the field. Then \(f(x,x)\) is a polynomial in \(n\) indeterminates. When \(f\) is alternating, \(f(x,x)\) is identically zero, but in all other cases, \(f(x,x)\) determines \(f\) completely.

Conversely, suppose that \(Q\) is a quadratic form on an \(n\)-dimensional vectorspace. Consider a vector \(x\) with coordinates x_{1},...,x_{n} with x_{i} indeterminates over the field. Then \(Q(x)\) is a polynomial in \(n\) indeterminates, and \(Q(x)\) determines \(Q\) completely.

**Forms** provides functionality to construct bilinear, hermitian and quadratic forms using an appropriate polynomial.

`‣ BilinearFormByPolynomial` ( poly, r, n ) | ( operation ) |

`‣ BilinearFormByPolynomial` ( poly, r ) | ( operation ) |

Returns: a bilinear form

The argument `poly` must be a polynomial in the polynomial ring `r`. The (optional) last argument is the dimension for the underlying vector space of the resulting form, which by default is the number of indeterminates specified by `poly`. It is checked whether the polynomial is a homogeneous polynomial of degree two over the given field, and if not, an error message is returned. It is not possible to construct a nontrivial bilinear form from a polynomial in even characteristic. The output is a bilinear (orthogonal) form in the category `IsBilinearForm`

. (See 3.1 for more on bilinear forms).

gap> r := PolynomialRing( GF(11), 4); GF(11)[x_1,x_2,x_3,x_4] gap> vars := IndeterminatesOfPolynomialRing( r ); [ x_1, x_2, x_3, x_4 ] gap> pol := vars[1]*vars[2]+vars[3]*vars[4]; x_1*x_2+x_3*x_4 gap> form := BilinearFormByPolynomial(pol, r, 4); < bilinear form > gap> Display(form); Bilinear form Gram Matrix: . 6 . . 6 . . . . . . 6 . . 6 . Polynomial: x_1*x_2+x_3*x_4 gap> r := PolynomialRing(GF(4),2); GF(2^2)[x_1,x_2] gap> pol := r.1*r.2; x_1*x_2 gap> form := BilinearFormByPolynomial(pol,r); Error, No orthogonal form can be associated with a quadratic polynomial in even cha\ ra cteristic called from BilinearFormByPolynomial( pol, pring, n ) at ./pkg/forms/lib/forms.gi:470 called from <function "unknown">( <arguments> ) called from read-eval loop at line 14 of *stdin* you can 'quit;' to quit to outer loop, or you can 'return;' to continue brk> quit;

`‣ QuadraticFormByPolynomial` ( poly, r, n ) | ( operation ) |

`‣ QuadraticFormByPolynomial` ( poly, r ) | ( operation ) |

Returns: a quadratic form

The argument `poly` must be a polynomial in the polynomial ring `r`. The (optional) last argument is the dimension for the underlying vector space of the resulting form, which by default is the number of indeterminates specified by `poly`. It is checked whether the polynomial is a homogeneous polynomial of degree two over the given field, and if not, an error message is returned. The output is a quadratic form in the category `IsQuadraticForm`

. (See 3.2 for more on quadratic forms).

gap> r := PolynomialRing( GF(8), 3); GF(2^3)[x_1,x_2,x_3] gap> poly := r.1^2 + r.2^2 + r.3^2; x_1^2+x_2^2+x_3^2 gap> form := QuadraticFormByPolynomial(poly, r); < quadratic form > gap> RadicalOfForm(form); <vector space over GF(2^3), with 63 generators> gap> r := PolynomialRing(GF(9),4); GF(3^2)[x_1,x_2,x_3,x_4] gap> poly := Z(3)^2*r.1^2+r.2^2+r.3*r.4; x_1^2+x_2^2+x_3*x_4 gap> qform := QuadraticFormByPolynomial(poly,r); < quadratic form > gap> Display(qform); Quadratic form Gram Matrix: 1 . . . . 1 . . . . . 1 . . . . Polynomial: x_1^2+x_2^2+x_3*x_4

`‣ HermitianFormByPolynomial` ( poly, r, n ) | ( operation ) |

`‣ HermitianFormByPolynomial` ( poly, r ) | ( operation ) |

Returns: an hermitian form

The argument `poly` must be a polynomial in the polynomial ring `r` defined over a finite field of square order q^{2} The (optional) last argument is the dimension for the underlying vector space of the resulting form, which by default is the number of indeterminates specified by `poly`. It is checked whether the polynomial is a homogeneous polynomial of degree \(q+1\), and if not, an error message is returned. The output is a hermitian form in the category `IsHermitianForm`

. (See 3.1 for more on hermitian forms).

gap> r := PolynomialRing( GF(9), 4); GF(3^2)[x_1,x_2,x_3,x_4] gap> vars := IndeterminatesOfPolynomialRing( r ); [ x_1, x_2, x_3, x_4 ] gap> poly := vars[1]*vars[2]^3+vars[1]^3*vars[2]+ > vars[3]*vars[4]^3+vars[3]^3*vars[4]; x_1^3*x_2+x_1*x_2^3+x_3^3*x_4+x_3*x_4^3 gap> form := HermitianFormByPolynomial(poly,r); < hermitian form > gap> Display(form); Hermitian form Gram Matrix: . 1 . . 1 . . . . . . 1 . . 1 . Polynomial: x_1^3*x_2+x_1*x_2^3+x_3^3*x_4+x_3*x_4^3

When the characteristic of the field is odd, a homogeneous quadratic polynomial determines a bilinear form, and a quadratic form. In some situations, when a quadratic form \(Q\) is given, it is useful to consider the bilinear form \(f\) such that \(f(v,v)=Q(v)\), i.e., the bilinear form which is determined by exactly the same polynomial determining the quadratic form \(Q\). **Forms** provides functionality to construct a bilinear form \(f\) from a given quadratic form \(Q\) such that \(f(v,v)=Q(v)\). Conversely, we can extract a quadratic form from a given bilinear form.

`‣ QuadraticFormByBilinearForm` ( form ) | ( operation ) |

Returns: a quadratic form

The argument \(form\) is an orthogonal bilinear form (and thus it belongs to `IsBilinearForm`

), otherwise a ``No method found'' error is returned. The output is the quadratic form \(Q\) (an object in `IsQuadraticForm`

), such that \(Q(v) = form(v,v)\) for all vectors \(v\) in a vector space equipped with \(form\). An error is returned when the characteristic of the field is even, or when \(form\) is not orthogonal.

gap> mat := [ [ Z(3^2)^7, Z(3)^0, Z(3^2)^2, 0*Z(3), Z(3^2)^5 ], > [ Z(3)^0, Z(3^2)^7, Z(3^2)^6, Z(3^2)^5, Z(3^2)^2 ], > [ Z(3^2)^2, Z(3^2)^6, Z(3^2)^7, Z(3^2)^2, Z(3^2)^2 ], > [ 0*Z(3), Z(3^2)^5, Z(3^2)^2, Z(3^2)^6, Z(3^2)^7 ], > [ Z(3^2)^5, Z(3^2)^2, Z(3^2)^2, Z(3^2)^7, Z(3) ] ]; [ [ Z(3^2)^7, Z(3)^0, Z(3^2)^2, 0*Z(3), Z(3^2)^5 ], [ Z(3)^0, Z(3^2)^7, Z(3^2)^6, Z(3^2)^5, Z(3^2)^2 ], [ Z(3^2)^2, Z(3^2)^6, Z(3^2)^7, Z(3^2)^2, Z(3^2)^2 ], [ 0*Z(3), Z(3^2)^5, Z(3^2)^2, Z(3^2)^6, Z(3^2)^7 ], [ Z(3^2)^5, Z(3^2)^2, Z(3^2)^2, Z(3^2)^7, Z(3) ] ] gap> form := BilinearFormByMatrix(mat,GF(9)); < bilinear form > gap> Q := QuadraticFormByBilinearForm(form); < quadratic form > gap> Display(form); Bilinear form Gram Matrix: z = Z(9) z^7 1 z^2 . z^5 1 z^7 z^6 z^5 z^2 z^2 z^6 z^7 z^2 z^2 . z^5 z^2 z^6 z^7 z^5 z^2 z^2 z^7 2 gap> Display(Q); Quadratic form Gram Matrix: z = Z(9) z^7 2 z^6 . z^1 . z^7 z^2 z^1 z^6 . . z^7 z^6 z^6 . . . z^6 z^3 . . . . 2 gap> Set(List(GF(9)^5),x->[x,x]^form=x^Q); [ true ] gap> PolynomialOfForm(form); Z(3^2)^7*x_1^2-x_1*x_2+Z(3^2)^6*x_1*x_3+Z(3^2)*x_1*x_5+Z(3^2)^7*x_2^2+Z(3^2)^2 *x_2*x_3+Z(3^2)*x_2*x_4+Z(3^2)^6*x_2*x_5+Z(3^2)^7*x_3^2+Z(3^2)^6*x_3*x_4+Z(3^2 )^6*x_3*x_5+Z(3^2)^6*x_4^2+Z(3^2)^3*x_4*x_5-x_5^2 gap> PolynomialOfForm(Q); Z(3^2)^7*x_1^2-x_1*x_2+Z(3^2)^6*x_1*x_3+Z(3^2)*x_1*x_5+Z(3^2)^7*x_2^2+Z(3^2)^2 *x_2*x_3+Z(3^2)*x_2*x_4+Z(3^2)^6*x_2*x_5+Z(3^2)^7*x_3^2+Z(3^2)^6*x_3*x_4+Z(3^2 )^6*x_3*x_5+Z(3^2)^6*x_4^2+Z(3^2)^3*x_4*x_5-x_5^2

Note that the given bilinear form `form` is **not** the associated bilinear form of the constructed quadratic form \(Q\), according to the definition in Section 3.2. We can construct the associated bilinear forms by using `AssociatedBilinearForm`

(4.4-3). (See 3.2 for more on quadratic forms).

`‣ BilinearFormByQuadraticForm` ( Q ) | ( operation ) |

Returns: a bilinear form

The argument \(Q\) must be a quadratic form (and thus it belongs to `IsQuadraticForm`

). The output is the orthogonal bilinear form \(f\) (an object in `IsBilinearForm`

), such that \(f(v,v) = Q(v)\) for all vectors \(v\) in a vector space equipped with \(Q\). An error is returned when the characteristic of the field is even.

gap> r := PolynomialRing(GF(9),4); GF(3^2)[x_1,x_2,x_3,x_4] gap> poly := -r.1*r.2+Z(3^2)*r.3^2+r.4^2; -x_1*x_2+Z(3^2)*x_3^2+x_4^2 gap> qform := QuadraticFormByPolynomial(poly,r); < quadratic form > gap> Display( qform ); Quadratic form Gram Matrix: z = Z(9) . 2 . . . . . . . . z^1 . . . . 1 Polynomial: -x_1*x_2+Z(3^2)*x_3^2+x_4^2 gap> form := BilinearFormByQuadraticForm( qform ); < bilinear form > gap> Display(form); Bilinear form Gram Matrix: z = Z(9) . 1 . . 1 . . . . . z^1 . . . . 1 gap> Set(GF(9)^4, x -> [x,x]^form = x^qform); [ true ]

Note that the constructed bilinear form \(f\) is **not** the associated bilinear form of the given quadratic form \(Q\), according to the definition in Section 3.2. We can construct the associated bilinear forms by using `AssociatedBilinearForm`

(4.4-3). (See 3.2 for more on quadratic forms).

`‣ AssociatedBilinearForm` ( Q ) | ( operation ) |

Returns: a bilinear form

The argument \(Q\) must be a quadratic form (and thus it belongs to `IsQuadraticForm`

). The output is the associated bilinear form \(f\) (an object in `IsBilinearForm`

), as defined in Section 3.2, i.e. the bilinear form \(f\) such that \(f(v,w) = Q(v+w)-Q(v)-Q(w)\) for all vectors \(v,w\) in a vector space equipped with \(Q\). (See 3.2 for more on quadratic forms).

gap> r:= PolynomialRing(GF(121),6); GF(11^2)[x_1,x_2,x_3,x_4,x_5,x_6] gap> poly := r.1*r.5-r.2*r.6+r.3*r.4; x_1*x_5-x_2*x_6+x_3*x_4 gap> form := QuadraticFormByPolynomial(poly,r); < quadratic form > gap> aform := AssociatedBilinearForm(form); < bilinear form > gap> Display(aform); Bilinear form Gram Matrix: . . . . 1 . . . . . . 10 . . . 1 . . . . 1 . . . 1 . . . . . . 10 . . . .

`‣ EvaluateForm` ( f, u, v ) | ( operation ) |

`‣ EvaluateForm` ( f, u ) | ( operation ) |

Returns: a finite field element

The argument `f` is either a sesquilinear or quadratic form defined over a finite field \(GF(q)\). The other argument is a pair of vectors or matrices, or a single vector or matrix, which represent the bases of given subspaces of GF(q)^{d}. This operation evaluates the form on the given vector or pair of vectors and returns an element in \(GF(q)\). There is also an overloading of the operation `\^` where \((u,v)^f\) represents \(f(u,v)\) in the case that `f` is sesquilinear, and \(u^f\) stands for \(f(u)\) in the quadratic case. So for convenience, the user may use this compressed version of this operation, which we show in the following example:

gap> mat := [[Z(8),0,0,0],[0,0,Z(8)^4,0],[0,0,0,1],[0,0,0,0]]*Z(8)^0;; gap> form := QuadraticFormByMatrix(mat,GF(8)); < quadratic form > gap> u := [ Z(2^3)^4, Z(2^3)^4, Z(2)^0, Z(2^3)^3 ]; [ Z(2^3)^4, Z(2^3)^4, Z(2)^0, Z(2^3)^3 ] gap> EvaluateForm( form, u ); Z(2^3)^6 gap> u^form; Z(2^3)^6 gap> gram := [[0,0,0,0,0,2],[0,0,0,0,2,0],[0,0,0,1,0,0], > [0,0,1,0,0,0],[0,2,0,0,0,0],[2,0,0,0,0,0]]*Z(3)^0;; gap> form := BilinearFormByMatrix(gram,GF(3)); < bilinear form > gap> u := [ [ Z(3)^0, 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ], > [ 0*Z(3), 0*Z(3), Z(3)^0, Z(3)^0, Z(3), 0*Z(3) ] ];; gap> v := [ [ Z(3)^0, 0*Z(3), Z(3)^0, Z(3), 0*Z(3), Z(3) ], > [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3), Z(3), Z(3) ] ];; gap> EvaluateForm( form, u, v); [ [ Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ] gap> [u,v]^form; [ [ Z(3)^0, Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ]

`‣ OrthogonalSubspaceMat` ( form, v ) | ( operation ) |

Returns: a base of the subspace orthogonal to the given vector with relation to the given form

The argument `form` is a sesquilinear or quadratic form. The operation returns a base of the subspace orthogonal to the given vector `v` with relation to the sesquilinear `form` or with relation to the associated bilinear form of the quadratic form `form`

`‣ IsIsotropicVector` ( form, v ) | ( operation ) |

Returns: true or false

The operation return `true` if and only if `v` is isotropic with relation to the sesquilinear or quadratic form `form`.

gap> mat := [[1,0,0,0],[0,-1,0,0],[0,0,0,1],[0,0,1,0]]*Z(41)^0; [ [ Z(41)^0, 0*Z(41), 0*Z(41), 0*Z(41) ], [ 0*Z(41), Z(41)^20, 0*Z(41), 0*Z(41) ], [ 0*Z(41), 0*Z(41), 0*Z(41), Z(41)^0 ], [ 0*Z(41), 0*Z(41), Z(41)^0, 0*Z(41) ] ] gap> form := BilinearFormByMatrix(mat); < bilinear form > gap> v := [1,1,0,0]*Z(41)^0; [ Z(41)^0, Z(41)^0, 0*Z(41), 0*Z(41) ] gap> IsIsotropicVector(form,v); true gap> mat := [[1,0,0,0,0],[0,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0],[0,0,0,0,0]]*Z(8)^0; [ [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] ] gap> form := QuadraticFormByMatrix(mat); < quadratic form > gap> v1 := [1,0,0,0,0]*Z(8)^0; [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] gap> v2 := [0,1,0,0,0]*Z(8)^0; [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ] gap> IsIsotropicVector(form,v1); true gap> IsIsotropicVector(form,v2); true

`‣ IsSingularVector` ( form, v ) | ( operation ) |

Returns: true or false

The operation return `true` if and only if `v` is singular with relation to the quadratic form `form`. Note that only when the characteristic of the field is odd, the singular vectors with relation to a quadratic form are the isotropic vectors with relation to its associated form.

gap> mat := [[1,0,0,0,0],[0,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0],[0,0,0,0,0]]*Z(8)^0; [ [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] ] gap> form := QuadraticFormByMatrix(mat); < quadratic form > gap> v1 := [1,0,0,0,0]*Z(8)^0; [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] gap> v2 := [0,1,0,0,0]*Z(8)^0; [ 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2) ] gap> IsSingularVector(form,v1); false gap> IsSingularVector(form,v2); true gap> IsIsotropicVector(form,v1); true gap> IsIsotropicVector(form,v2); true

`‣ IsTotallyIsotropicSubspace` ( form, sub ) | ( operation ) |

Returns: true or false

The operation return `true` if and only if the subspace spanned by the vectors in the list `sub` is totally isotropic with relation to the sesquilinear or quadratic form `form`. Note that when `form` is a quadratic form, it is checked whether `sub` generates a subspace that is totally isotropic with relation to the associated bilinear form of `form`.

gap> mat := [[1,0,0,0],[0,-1,0,0],[0,0,0,1],[0,0,1,0]]*Z(7)^0; [ [ Z(7)^0, 0*Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), Z(7)^3, 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7), Z(7)^0 ], [ 0*Z(7), 0*Z(7), Z(7)^0, 0*Z(7) ] ] gap> form := BilinearFormByMatrix(mat); < bilinear form > gap> sub:= [[Z(7)^0,0*Z(7),Z(7)^0,Z(7)],[0*Z(7),Z(7)^0,Z(7)^0,Z(7)^4]]; [ [ Z(7)^0, 0*Z(7), Z(7)^0, Z(7) ], [ 0*Z(7), Z(7)^0, Z(7)^0, Z(7)^4 ] ] gap> IsTotallyIsotropicSubspace(form,sub); true gap> mat := IdentityMat(6,GF(2)); [ <a GF2 vector of length 6>, <a GF2 vector of length 6>, <a GF2 vector of length 6>, <a GF2 vector of length 6>, <a GF2 vector of length 6>, <a GF2 vector of length 6> ] gap> form := HermitianFormByMatrix(mat,GF(4)); < hermitian form > gap> sub := [[Z(2)^0,0*Z(2),0*Z(2),Z(2)^0,Z(2)^0,Z(2)^0], > [0*Z(2),Z(2)^0,0*Z(2),Z(2^2)^2,Z(2^2),Z(2)^0], > [0*Z(2),0*Z(2),Z(2)^0,Z(2)^0,Z(2^2),Z(2^2)^2]]; [ [ Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0, 0*Z(2), Z(2^2)^2, Z(2^2), Z(2)^0 ], [ 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0, Z(2^2), Z(2^2)^2 ] ] gap> IsTotallyIsotropicSubspace(form,sub); true

`‣ IsTotallySingularSubspace` ( form, sub ) | ( operation ) |

Returns: true or false

The operation return `true` if and only if the subspace spanned by the vectors in the list `sub` is totally singular with relation to quadratic form `form`. Note that only when the characteristic of the field is odd, the totally singular subspaces of given dimension \(n\) with relation to a quadratic form are exactly the totally isotropic subspaces of dimension \(n\) with relation to its associated form.

gap> mat := [[1,0,0,0,0],[0,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0],[0,0,0,0,0]]*Z(8)^0; [ [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] ] gap> form := QuadraticFormByMatrix(mat); < quadratic form > gap> sub := [[Z(2)^0,0*Z(2),Z(2^3)^6,Z(2^3),Z(2^3)^3], > [0*Z(2),Z(2)^0,Z(2^3)^6,Z(2^3)^2,Z(2^3)]]; [ [ Z(2)^0, 0*Z(2), Z(2^3)^6, Z(2^3), Z(2^3)^3 ], [ 0*Z(2), Z(2)^0, Z(2^3)^6, Z(2^3)^2, Z(2^3) ] ] gap> IsTotallySingularSubspace(form,sub); true

`‣ IsReflexiveForm` ( f ) | ( property ) |

Returns: true or false.

A sesquilinear form \(f\) on a vector space \(V\) is *reflexive* if \(f(v,w)=0 \Rightarrow f(w,v)=0\) for all \(v,w \in V\). The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). A sesquilinear form \(f\) is *reflexive* if whenever we have \(f(u,v)=0\), for two vectors \(u,v\) in the associated vector space, then we also have \(f(v,u)=0\). This attribute simply returns `true` or `false` according to whether `f` is reflexive or not, and is stored as a property of `f`. It is not possible in this version of **Forms** to construct non-reflexive forms. (See 3.1 for more on reflexive sesquilinear forms).

`‣ IsAlternatingForm` ( f ) | ( property ) |

Returns: true or false.

A sesquilinear form \(f\) on a vector space \(V\) is *alternating* if \(f(v,v)=0\) for all \(v \in V\). The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). A bilinear form \(f\) is *alternating* if \(f(v,v)=0\) for all \(v\). This method simply returns `true` or `false` according to whether `f` is alternating or not, and is stored as a property of `f`. (See 3.1 for more on alternating sesquilinear forms).

`‣ IsSymmetricForm` ( f ) | ( property ) |

Returns: true or false.

A sesquilinear form \(f\) on a vector space \(V\) is *symmetric* if \(f(v,w)=f(w,v)\) for all \(v,w \in V\). The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). A bilinear form \(f\) is *symmetric* if \(f(u,v)=f(v,u)\) for all pairs of vectors \(u\) and \(v\). This attribute simply returns `true` or `false` according to whether `f` is symmetric or not, and is stored as a property of `f`. (See 3.1 for more on symmetric sesquilinear forms).

`‣ IsOrthogonalForm` ( f ) | ( property ) |

Returns: true or false.

The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). A bilinear form \(f\) is called *orthogonal* if the characteristic of the underlying field is odd, and \(f\) is a symmetric form. (See 3.1 for more on bilinear forms). This operation simply returns `true` or `false` according to whether `f` is an orthogonal bilinear form or not, and is stored as a property of `f`.

`‣ IsPseudoForm` ( f ) | ( property ) |

Returns: true or false.

When the characteristic of the field is odd, we call a form \(f\) *orthogonal* if and only \(f\) is symmetric, and when the characteristic of the field is even, we call a form \(f\) *pseudo* if and only if \(f\) is symmetric but not alternating. The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). (See 3.1 for more on pseudo forms). This method simply returns `true` or `false` according to whether `f` is a pseudo form or not, and is stored as a property of `f`.

`‣ IsSymplecticForm` ( f ) | ( property ) |

Returns: true or false.

We call a bilinear form \(f\) *symplectic* if and only if \(f\) is alternating. The argument \(f\) must be a sesquilinear form (and thus it belongs to `IsSesquilinearForm`

). (See 3.1 for more on symplectic forms). This method simply returns `true` or `false` according to whether `f` is symplectic or not, and is stored as a property of `f`.

`‣ IsDegenerateForm` ( f ) | ( property ) |

Returns: true or false.

The argument \(f\) must be a form (and thus it belongs to `IsForm`

). A sesquilinear form \(f\) is *degenerate* if its radical is non-trivial. A quadratic form is degenerate if and only if the radical of the associated bilinear form is non-trivial. Note that degeneracy for quadratic forms is too restrictive if the characteristic is even. See also `IsSingularForm`

(4.7-8). This attribute simply returns `true` or `false` according to whether `f` is degenerate or not, and is stored as a property of `f`.

`‣ IsSingularForm` ( f ) | ( property ) |

Returns: true or false.

The argument \(f\) must be a quadratic form (and thus it belongs to `IsQuadraticForm`

). A quadratic form \(f\) is *singular* if its radical is non-trivial. When the characteristic of the field is odd, a quadratic form is singular if and only if it is degenerate. This is not the case when the characteristic of the field is even. This method simply returns `true` or `false` according to whether `f` is singular or not, and is stored as a property of `f`.

`‣ BaseField` ( f ) | ( attribute ) |

Returns: the underlying field of `f`.

The argument \(f\) must be a form (and thus it belongs to `IsForm`

). The method returns the field which is stored as the *defining field* of \(f\). We sometimes stipulate in **Forms** that a form have a defining field, for mathematical reasons. Clearly, to define a hermitian form one needs to specify the field of scalars for the vector space that you wish your hermitian form to act on. The default, if the user has not specified a field on creation of a form, is the smallest field containing the entries or coefficients of the input (a matrix or polynomial). Having a particular defining field for a form can be very useful, for example, when one wants to find a change of basis from one form to another (isometric) form. In this case, one needs to know in which \(GL(d,q)\) the base-transition matrix should be taken.

`‣ GramMatrix` ( f ) | ( attribute ) |

Returns: the Gram matrix of `f`.

The argument \(f\) must be a form (and thus it belongs to `IsForm`

). This method returns the Gram matrix of \(f\) (see 3.1 and 3.2).

`‣ RadicalOfForm` ( f ) | ( attribute ) |

Returns: The radical of the form `f`

The argument \(f\) must be a form (and thus it belongs to `IsForm`

) on some vector space \(V\). The radical of a form \(f\) is the subspace consisting of vectors which are orthogonal to every vector, i.e.,

\[Rad(f) = {v ∈ V | f(v,w) = 0 for all w ∈ V}.\]

gap> r := PolynomialRing( GF(8), 3 ); GF(2^3)[x_1,x_2,x_3] gap> poly := r.1^2 + r.2 * r.3; x_1^2+x_2*x_3 gap> form := QuadraticFormByPolynomial( poly, r ); < quadratic form > gap> r := RadicalOfForm( form ); <vector space over GF(2^3), with 0 generators> gap> Dimension(r); 0

`‣ PolynomialOfForm` ( f ) | ( attribute ) |

Returns: the polynomial associated with `f`.

The argument `f` must be a form (and thus it belongs to `IsForm`

). All forms, except for bilinear forms in even characteristic, have an associated polynomial defining a quadratic or hermitian form (see 3.1 and 3.2). This method returns the polynomial associated with `f`, and if not already bound, stores it as a property of `f`.

gap> mat := [ [ Z(8) , 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], > [ 0*Z(2), Z(2)^0, Z(2^3)^5, 0*Z(2), 0*Z(2) ], > [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ], > [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ], > [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] ];; gap> form := QuadraticFormByMatrix(mat,GF(8)); < quadratic form > gap> PolynomialOfForm(form); Z(2^3)*x_1^2+x_2^2+Z(2^3)^5*x_2*x_3+x_4*x_5

`‣ DiscriminantOfForm` ( f ) | ( attribute ) |

Returns: a string

The argument \(f\) must be a form (and thus it belongs to `IsForm`

). Given a quadratic or bilinear form `f` of even dimension, this operation returns a string: ``square'' or ``nonsquare''. More specifically, let \(f\) be a from over \(GF(q)\), and let \(M\) be the Gram matrix of \(f\). Define the *discriminant* of \(Q\) (n.b., *quasideterminant* in [CCNPW85]) as `square' if \(det(M)\) is a square of \(GF(q)\), and `non-square' otherwise. The discriminant is an invariant of nondegenerate orthogonal spaces over finite fields of odd order, up to isometry. Thus, discriminants can be used to delineate the isometry type of an orthogonal form in even (algebraic) dimension. The discriminant of a hermitian form is not defined, and applying this operation on a hermitian form, will result in an error message.

gap> gram := InvariantQuadraticForm(GO(-1,4,5))!.matrix;; gap> qform := QuadraticFormByMatrix(gram, GF(5)); < quadratic form > gap> DiscriminantOfForm( qform ); "nonsquare"

In this section, we describe a function that was initially developed by Frank Celler (and which has now been adapted to **Forms**) for the recognition of sesquilinear forms left invariant by a matrix group. More importantly, we should stress that this routine differs to that already offered by the **MeatAxe** in that it finds sesquilinear forms preserved up to **scalars**. Eventually, the procedure used for finding preserved sesquilinear forms does use the **MeatAxe** but in some cases it can rule out the existence of preserved forms without calling the **MeatAxe**. For more information on the algorithm, please see [CLNNPP08].

`‣ PreservedSesquilinearForms` ( group ) | ( operation ) |

Returns: a list of forms

The argument `group` is a matrix group. The function uses random methods to find all of the bilinear or unitary forms preserved by `group` (the trivial form is also a possibility) up to a scalar. Since the procedure relies on a pseudo-random generator, the user may need to execute the operation more than once to find all invariant sesquilinear forms.

gap> g := SU(4,3); SU(4,3) gap> forms := PreservedSesquilinearForms(g); [ < hermitian form > ] gap> Display( forms[1] ); Hermitian form Gram Matrix: . . . 2 . . 2 . . 2 . . 2 . . .

Here is another example which shows that this procedure is suitable in some cases where using the **MeatAxe** is not applicable. Here, our matrix group is the group of similarities preserving a (hyperbolic) bilinear form on \(GF(3)^6\).

gap> a := [ [ -1, 0, 0, -1, 0, 1 ], [ 0, -1, -1, 0, 0, 1 ], > [ -1, 0, 0, 1, 0, 0 ], [ 0, -1, 1, 0, 0, -1 ], > [ 0, 0, 0, 0, 0, -1 ], [ 0, -1, -1, 1, 1, 1 ] ] * One(GF(3));; gap> b := [ [ 1, -1, 1, -1, 1, -1 ], [ 1, 1, -1, 1, 1, 0 ], > [ -1, 0, 1, 0, 0, 0 ], [ 0, -1, 0, 0, 0, 1 ], > [ 1, 1, 1, 1, 1, 1 ], [ -1, 1, 1, 1, -1, 0 ] ] * One(GF(3));; gap> g := Group( a, b ); <matrix group with 2 generators> gap> forms := PreservedSesquilinearForms( g ); [ < bilinear form > ] gap> Display( forms[1] ); Bilinear form Gram Matrix: . 1 . . . . 1 . . . . . . . . 1 . . . . 1 . . . . . . . . 1 . . . . 1 . gap> m := GModuleByMats( [a,b], GF(3) );; gap> usemeataxe := MTX.InvariantBilinearForm(m); fail

It can be useful to work with trivial a quadratic or sesquilinear form, i.e. a form mapping all vectors, couples of vectors respectively, to the zero element of their basefield. As mentioned in Section 4.1, **Forms** allows the construction of an object in the Category `IsTrivialForm`

.

gap> mat := [[0,0,0],[0,0,0],[0,0,0]]*Z(7)^0; [ [ 0*Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7) ] ] gap> form1 := BilinearFormByMatrix(mat,GF(7)); < trivial form > gap> form2 := QuadraticFormByMatrix(mat,GF(7)); < trivial form > gap> form1 = form2; true gap> IsQuadraticForm(form1); false gap> IsSesquilinearForm(form1); false gap> mat := [[0,0],[0,0]]*Z(4)^0; [ [ 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2) ] ] gap> form3 := BilinearFormByMatrix(mat,GF(4)); < trivial form > gap> form3 = form1; false

As we have seen by the above example, there is only one trivial form for a given vector space over a finite field, and such a trivial form can result from the construction of a quadratic form or a sesquilinear form, but the trivial form itself is none of these, although it can behave as a sesquilinear or a quadratic form, depending on its arguments.

gap> mat := [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]*Z(3)^0; [ [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ] ] gap> form := BilinearFormByMatrix(mat,GF(3)); < trivial form > gap> v := Random(GF(3)^4); [ Z(3), Z(3), 0*Z(3), Z(3) ] gap> [v,v]^form; 0*Z(3) gap> v^form; 0*Z(3)

The attributes and properties described in Section 4.7 are all applicable to trivial forms.

gap> mat := [[0,0,0],[0,0,0],[0,0,0]]*Z(11)^0; [ [ 0*Z(11), 0*Z(11), 0*Z(11) ], [ 0*Z(11), 0*Z(11), 0*Z(11) ], [ 0*Z(11), 0*Z(11), 0*Z(11) ] ] gap> form := QuadraticFormByMatrix(mat,GF(121)); < trivial form > gap> IsReflexiveForm(form); true gap> IsAlternatingForm(form); true gap> IsSymmetricForm(form); true gap> IsOrthogonalForm(form); false gap> IsPseudoForm(form); false gap> IsSymplecticForm(form); true gap> IsDegenerateForm(form); true gap> IsSingularForm(form); true gap> BaseField(form); GF(11^2) gap> GramMatrix(form); [ [ 0*Z(11), 0*Z(11), 0*Z(11) ], [ 0*Z(11), 0*Z(11), 0*Z(11) ], [ 0*Z(11), 0*Z(11), 0*Z(11) ] ] gap> RadicalOfForm(form); <vector space over GF(11^2), with 3 generators>

generated by GAPDoc2HTML