| 2020 | def AffinePolarGraph(d,q,sign="+"): |
| 2021 | r""" |
| 2022 | Returns the affine polar graph `VO^+(d,q),VO^-(d,q)` or `VO(d,q)`. |
| 2023 | |
| 2024 | Affine Polar graphs are built from a `d`-dimensional vector space over |
| 2025 | `F_q`, and a quadratic form which is hyperbolic, elliptic or parabolic |
| 2026 | according to the value of ``sign``. |
| 2027 | |
| 2028 | Note that `VO^+(d,q),VO^-(d,q)` are strongly regular graphs, while `VO(d,q)` |
| 2029 | is not. |
| 2030 | |
| 2031 | For more information on Affine Polar graphs, see the corresponding `page of |
| 2032 | Andries Brouwer's website <http://www.win.tue.nl/~aeb/graphs/VO.html>`_. |
| 2033 | |
| 2034 | INPUT: |
| 2035 | |
| 2036 | - ``d`` (integer) -- ``d`` must be even if ``sign != None``, and odd |
| 2037 | otherwise. |
| 2038 | |
| 2039 | - ``q`` (integer) -- a power of a prime number, as `F_q` must exist. |
| 2040 | |
| 2041 | - ``sign`` -- must be qual to ``"+"``, ``"-"``, or ``None`` to compute |
| 2042 | (respectively) `VO^+(d,q),VO^-(d,q)` or `VO(d,q)`. By default |
| 2043 | ``sign="+"``. |
| 2044 | |
| 2045 | EXAMPLES: |
| 2046 | |
| 2047 | The :meth:`Brouwer-Haemers graph <BrouwerHaemersGraph>` is isomorphic to |
| 2048 | `VO^-(4,3)`:: |
| 2049 | |
| 2050 | sage: g = graphs.AffinePolarGraph(4,3,"-") |
| 2051 | sage: g.is_isomorphic(graphs.BrouwerHaemersGraph()) |
| 2052 | True |
| 2053 | |
| 2054 | Some examples from `Brouwer's table or strongly regular graphs |
| 2055 | <http://www.win.tue.nl/~aeb/graphs/srg/srgtab.html>`_:: |
| 2056 | |
| 2057 | sage: g = graphs.AffinePolarGraph(6,2,"-"); g |
| 2058 | Affine Polar Graph VO^-(6,2): Graph on 64 vertices |
| 2059 | sage: g.is_strongly_regular(parameters=True) |
| 2060 | (64, 27, 10, 12) |
| 2061 | sage: g = graphs.AffinePolarGraph(6,2,"+"); g |
| 2062 | Affine Polar Graph VO^+(6,2): Graph on 64 vertices |
| 2063 | sage: g.is_strongly_regular(parameters=True) |
| 2064 | (64, 35, 18, 20) |
| 2065 | |
| 2066 | When ``sign is None``:: |
| 2067 | |
| 2068 | sage: g = graphs.AffinePolarGraph(5,2,None); g |
| 2069 | Affine Polar Graph VO^-(5,2): Graph on 32 vertices |
| 2070 | sage: g.is_strongly_regular(parameters=True) |
| 2071 | False |
| 2072 | sage: g.is_regular() |
| 2073 | True |
| 2074 | sage: g.is_vertex_transitive() |
| 2075 | True |
| 2076 | """ |
| 2077 | if sign in ["+","-"]: |
| 2078 | s = 1 if sign == "+" else -1 |
| 2079 | if d%2 == 1: |
| 2080 | raise ValueError("d must be even when sign!=None") |
| 2081 | else: |
| 2082 | if d%2 == 0: |
| 2083 | raise ValueError("d must be odd when sign==None") |
| 2084 | s = 0 |
| 2085 | |
| 2086 | from sage.interfaces.gap import gap |
| 2087 | from sage.rings.finite_rings.constructor import FiniteField |
| 2088 | from sage.modules.free_module import VectorSpace |
| 2089 | from sage.matrix.constructor import Matrix |
| 2090 | from itertools import combinations |
| 2091 | |
| 2092 | m = gap("InvariantQuadraticForm(GO("+str(s)+","+str(d)+","+str(q)+")).matrix") |
| 2093 | F = FiniteField(q,"x") |
| 2094 | V = list(VectorSpace(F,d)) |
| 2095 | M = [[F(y) for y in mm] for mm in m] |
| 2096 | M = Matrix(F,M) |
| 2097 | |
| 2098 | G = Graph() |
| 2099 | G.add_vertices(map(tuple,V)) |
| 2100 | for x,y in combinations(V,2): |
| 2101 | if not (x-y)*(M*(x-y)): |
| 2102 | G.add_edge(tuple(x),tuple(y)) |
| 2103 | |
| 2104 | G.name("Affine Polar Graph VO^"+str('+' if s == 1 else '-')+"("+str(d)+","+str(q)+")") |
| 2105 | G.relabel() |
| 2106 | return G |