Ejemplo n.º 1
0
def UnitaryDualPolarGraph(m, q):
    r"""
    Returns the Dual Unitary Polar Graph `U(m,q)`.

    For more information on Unitary Dual Polar graphs, see [BCN89]_ and
    Sect. 2.3.1 of [Co81]_.

    INPUT:

    - ``m,q`` (integers) -- `q` must be a prime power.

    EXAMPLES:

    The point graph of a generalized quadrangle of order (8,4)::

        sage: G = graphs.UnitaryDualPolarGraph(5,2); G   # long time
        Unitary Dual Polar Graph DU(5, 2); GQ(8, 4): Graph on 297 vertices
        sage: G.is_strongly_regular(parameters=True)     # long time
        (297, 40, 7, 5)

    Another way to get the  generalized quadrangle of order (2,4)::

        sage: G = graphs.UnitaryDualPolarGraph(4,2); G
        Unitary Dual Polar Graph DU(4, 2); GQ(2, 4): Graph on 27 vertices
        sage: G.is_isomorphic(graphs.OrthogonalPolarGraph(6,2,'-'))
        True

    A bigger graph::

        sage: G = graphs.UnitaryDualPolarGraph(6,2); G   # not tested (long time)
        Unitary Dual Polar Graph DU(6, 2): Graph on 891 vertices
        sage: G.is_distance_regular(parameters=True)     # not tested (long time)
        ([42, 40, 32, None], [None, 1, 5, 21])

    TESTS::

        sage: graphs.UnitaryDualPolarGraph(6,6)
        Traceback (most recent call last):
        ...
        ValueError: libGAP: Error, <subfield> must be a prime or a finite field
    """
    from sage.libs.gap.libgap import libgap
    G = _polar_graph(m,
                     q**2,
                     libgap.GeneralUnitaryGroup(m, q),
                     intersection_size=(q**(2 * (m // 2 - 1)) - 1) /
                     (q**2 - 1))
    G.relabel()
    G.name("Unitary Dual Polar Graph DU" + str((m, q)))
    if m == 4:
        G.name(G.name() + '; GQ' + str((q, q**2)))
    if m == 5:
        G.name(G.name() + '; GQ' + str((q**3, q**2)))
    return G
Ejemplo n.º 2
0
def NonisotropicUnitaryPolarGraph(m, q):
    r"""
    Returns the Graph `NU(m,q)`.

    Returns the graph on nonisotropic, with respect to a nondegenerate
    Hermitean form, points of the `(m-1)`-dimensional projective space over `F_q`,
    with points adjacent whenever they lie on a tangent (to the set of isotropic points)
    line.
    For more information, see Sect. 9.9 of [BH12]_ and series C14 in [Hu75]_.

    INPUT:

    - ``m,q`` (integers) -- `q` must be a prime power.

    EXAMPLES::

        sage: g=graphs.NonisotropicUnitaryPolarGraph(5,2); g
        NU(5, 2): Graph on 176 vertices
        sage: g.is_strongly_regular(parameters=True)
        (176, 135, 102, 108)

    TESTS::

        sage: graphs.NonisotropicUnitaryPolarGraph(4,2).is_strongly_regular(parameters=True)
        (40, 27, 18, 18)
        sage: graphs.NonisotropicUnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # long time
        (540, 224, 88, 96)
        sage: graphs.NonisotropicUnitaryPolarGraph(6,6)
        Traceback (most recent call last):
        ...
        ValueError: q must be a prime power

    REFERENCE:

    .. [Hu75] X. L. Hubaut.
      Strongly regular graphs.
      Disc. Math. 13(1975), pp 357--381.
      http://dx.doi.org/10.1016/0012-365X(75)90057-6
    """
    from sage.rings.arith import is_prime_power
    p, k = is_prime_power(q, get_data=True)
    if k == 0:
        raise ValueError('q must be a prime power')
    from sage.libs.gap.libgap import libgap
    from itertools import combinations
    F = libgap.GF(q**2)  # F_{q^2}
    W = libgap.FullRowSpace(F, m)  # F_{q^2}^m
    B = libgap.Elements(libgap.Basis(W))  # the standard basis of W
    if m % 2 != 0:
        point = B[(m - 1) / 2]
    else:
        if p == 2:
            point = B[m / 2] + F.PrimitiveRoot() * B[(m - 2) / 2]
        else:
            point = B[(m - 2) / 2] + B[m / 2]
    g = libgap.GeneralUnitaryGroup(m, q)
    V = libgap.Orbit(g, point, libgap.OnLines)  # orbit on nonisotropic points
    gp = libgap.Action(g, V, libgap.OnLines)  # make a permutation group

    s = libgap.Subspace(W, [point, point + B[0]])  # a tangent line on point

    # and the points there
    sp = [
        libgap.Elements(libgap.Basis(x))[0]
        for x in libgap.Elements(s.Subspaces(1))
    ]
    h = libgap.Set(
        map(lambda x: libgap.Position(V, x),
            libgap.Intersection(V, sp)))  # indices
    L = libgap.Orbit(gp, h, libgap.OnSets)  # orbit on the tangent lines
    G = Graph()
    for x in L:  # every pair of points in the subspace is adjacent to each other in G
        G.add_edges(combinations(x, 2))
    G.relabel()
    G.name("NU" + str((m, q)))
    return G
Ejemplo n.º 3
0
def UnitaryPolarGraph(m, q, algorithm="gap"):
    r"""
    Returns the Unitary Polar Graph `U(m,q)`.

    For more information on Unitary Polar graphs, see the `page of
    Andries Brouwer's website <http://www.win.tue.nl/~aeb/graphs/srghub.html>`_.

    INPUT:

    - ``m,q`` (integers) -- `q` must be a prime power.

    - ``algorithm`` -- if set to 'gap' then the computation is carried via GAP
      library interface, computing totally singular subspaces, which is faster for
      large examples (especially with `q>2`). Otherwise it is done directly.

    EXAMPLES::

        sage: G = graphs.UnitaryPolarGraph(4,2); G
        Unitary Polar Graph U(4, 2); GQ(4, 2): Graph on 45 vertices
        sage: G.is_strongly_regular(parameters=True)
        (45, 12, 3, 3)
        sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True)
        (165, 36, 3, 9)
        sage: graphs.UnitaryPolarGraph(6,2)    # not tested (long time)
        Unitary Polar Graph U(6, 2): Graph on 693 vertices

    TESTS::

        sage: graphs.UnitaryPolarGraph(4,3, algorithm="gap").is_strongly_regular(parameters=True)
        (280, 36, 8, 4)
        sage: graphs.UnitaryPolarGraph(4,3).is_strongly_regular(parameters=True)
        (280, 36, 8, 4)
        sage: graphs.UnitaryPolarGraph(4,3, algorithm="foo")
        Traceback (most recent call last):
        ...
        ValueError: unknown algorithm!
    """
    if algorithm == "gap":
        from sage.libs.gap.libgap import libgap
        G = _polar_graph(m, q**2, libgap.GeneralUnitaryGroup(m, q))

    elif algorithm == None:  # slow on large examples
        from sage.schemes.projective.projective_space import ProjectiveSpace
        from sage.rings.finite_rings.constructor import FiniteField
        from sage.modules.free_module_element import free_module_element as vector
        from __builtin__ import sum as psum
        Fq = FiniteField(q**2, 'a')
        PG = map(vector, ProjectiveSpace(m - 1, Fq))
        map(lambda x: x.set_immutable(), PG)

        def P(x, y):
            return psum(map(lambda j: x[j] * y[m - 1 - j]**q, xrange(m))) == 0

        V = filter(lambda x: P(x, x), PG)
        G = Graph(
            [
                V,
                lambda x, y:  # bottleneck is here, of course:
                P(x, y)
            ],
            loops=False)
    else:
        raise ValueError("unknown algorithm!")

    G.relabel()
    G.name("Unitary Polar Graph U" + str((m, q)))
    if m == 4:
        G.name(G.name() + '; GQ' + str((q**2, q)))
    if m == 5:
        G.name(G.name() + '; GQ' + str((q**2, q**3)))
    return G