Exemplo n.º 1
0
def szekeres_difference_set_pair(m, check=True):
    r"""
    Construct Szekeres `(2m+1,m,1)`-cyclic difference family

    Let `4m+3` be a prime power. Theorem 3 in [Sz69]_ contains a construction of a pair
    of *complementary difference sets* `A`, `B` in the subgroup `G` of the quadratic
    residues in `F_{4m+3}^*`. Namely `|A|=|B|=m`, `a\in A` whenever `a-1\in G`, `b\in B`
    whenever `b+1 \in G`. See also Theorem 2.6 in [SWW72]_ (there the formula for `B` is
    correct, as opposed to (4.2) in [Sz69]_, where the sign before `1` is wrong.

    In modern terminology, for `m>1` the sets `A` and `B` form a
    :func:`difference family<sage.combinat.designs.difference_family>` with parameters `(2m+1,m,1)`.
    I.e. each non-identity `g \in G` can be expressed uniquely as `xy^{-1}` for `x,y \in A` or `x,y \in B`.
    Other, specific to this construction, properties of `A` and `B` are: for `a` in `A` one has
    `a^{-1}` not in `A`, whereas for `b` in `B` one has `b^{-1}` in `B`.

    INPUT:

    - ``m`` (integer) -- dimension of the matrix

    - ``check`` (default: ``True``) -- whether to check `A` and `B` for correctness

    EXAMPLES::

        sage: from sage.combinat.matrices.hadamard_matrix import szekeres_difference_set_pair
        sage: G,A,B=szekeres_difference_set_pair(6)
        sage: G,A,B=szekeres_difference_set_pair(7)

    REFERENCE:

    .. [Sz69] \G. Szekeres,
      Tournaments and Hadamard matrices,
      Enseignement Math. (2) 15(1969), 269-278
    """
    from sage.rings.finite_rings.finite_field_constructor import GF
    F = GF(4 * m + 3)
    t = F.multiplicative_generator()**2
    G = F.cyclotomic_cosets(t, cosets=[F.one()])[0]
    sG = set(G)
    A = [a for a in G if a - F.one() in sG]
    B = [b for b in G if b + F.one() in sG]
    if check:
        from itertools import product, chain
        assert (len(A) == len(B) == m)
        if m > 1:
            assert (sG == set(
                [xy[0] / xy[1] for xy in chain(product(A, A), product(B, B))]))
        assert (all(F.one() / b + F.one() in sG for b in B))
        assert (not any(F.one() / a - F.one() in sG for a in A))
    return G, A, B
Exemplo n.º 2
0
def find_traces(k, r, l, rl = None):
    '''
    Compute traces such that the charpoly of the Frobenius has a root of order n
    modulo l.

    INPUT:

    - ``k`` -- the base field.

    - ``r`` -- the degree of the extension.

    - ``l`` -- a prime number.

    EXAMPLES::

        sage: from ellrains import find_traces
        sage: r = 281
        sage: l = 3373
        sage: k = GF(1747)
        sage: find_traces(k, r, l)
        [4, 14, 18, 43, 57, 3325, 3337, 3348, 3354, 3357, 3364]
    '''
    L = GF(l)
    q = L(k.order())
    bound = 4*k.characteristic()

    if rl is None:
        rl = ZZ((l-1)/r)

    # Primitive root of unity of order r
    zeta = L.multiplicative_generator()**rl
    # Candidate eigenvalue
    lmbd = L(1)
    # Traces
    T = []
    for i in xrange(1, r):
        lmbd *= zeta
        # Ensure that the order is r
        if r.gcd(i) != 1:
            continue
        if not lmbd.multiplicative_order() == r:
             print l, r, i
        trc = lmbd + q/lmbd
        # Check Hasse bound
        if trc.lift_centered()**2 < bound:
           T.append(trc)

    return T
Exemplo n.º 3
0
    def H_value(self, p, f, t, ring=None):
        """
        Return the trace of the Frobenius, computed in terms of Gauss sums
        using the hypergeometric trace formula.

        INPUT:

        - `p` -- a prime number

        - `f` -- an integer such that `q = p^f`

        - `t` -- a rational parameter

        - ``ring`` -- optional (default ``UniversalCyclotomicfield``)

        The ring could be also ``ComplexField(n)`` or ``QQbar``.

        OUTPUT:

        an integer

        .. WARNING::

            This is apparently working correctly as can be tested
            using ComplexField(70) as value ring.

            Using instead UniversalCyclotomicfield, this is much
            slower than the `p`-adic version :meth:`padic_H_value`.

        EXAMPLES:

        With values in the UniversalCyclotomicField (slow)::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: H = Hyp(alpha_beta=([1/2]*4,[0]*4))
            sage: [H.H_value(3,i,-1) for i in range(1,3)]
            [0, -12]
            sage: [H.H_value(5,i,-1) for i in range(1,3)]
            [-4, 276]
            sage: [H.H_value(7,i,-1) for i in range(1,3)]  # not tested
            [0, -476]
            sage: [H.H_value(11,i,-1) for i in range(1,3)]  # not tested
            [0, -4972]
            sage: [H.H_value(13,i,-1) for i in range(1,3)]  # not tested
            [-84, -1420]

        With values in ComplexField::

            sage: [H.H_value(5,i,-1, ComplexField(60)) for i in range(1,3)]
            [-4, 276]

        Check issue from :trac:`28404`::

            sage: H1 = Hyp(cyclotomic=([1,1,1],[6,2]))
            sage: H2 = Hyp(cyclotomic=([6,2],[1,1,1]))
            sage: [H1.H_value(5,1,i) for i in range(2,5)]
            [1, -4, -4]
            sage: [H2.H_value(5,1,QQ(i)) for i in range(2,5)]
            [-4, 1, -4]

        REFERENCES:

        - [BeCoMe]_ (Theorem 1.3)
        - [Benasque2009]_
        """
        alpha = self._alpha
        beta = self._beta
        t = QQ(t)
        if 0 in alpha:
            return self._swap.H_value(p, f, ~t, ring)
        if ring is None:
            ring = UniversalCyclotomicField()
        gamma = self.gamma_array()
        q = p ** f

        m = {r: beta.count(QQ((r, q - 1))) for r in range(q - 1)}
        D = -min(self.zigzag(x, flip_beta=True) for x in alpha + beta)
        # also: D = (self.weight() + 1 - m[0]) // 2
        M = self.M_value()

        Fq = GF(q)
        gen = Fq.multiplicative_generator()
        zeta_q = ring.zeta(q - 1)

        tM = Fq(M / t)
        for k in range(q - 1):
            if gen ** k == tM:
                teich = zeta_q ** k
                break

        gauss_table = [gauss_sum(zeta_q ** r, Fq) for r in range(q - 1)]

        sigma = sum(q**(D + m[0] - m[r]) *
                    prod(gauss_table[(-v * r) % (q - 1)]**gv
                         for v, gv in gamma.items()) *
                    teich ** r
                    for r in range(q - 1))
        resu = ZZ(-1) ** m[0] / (1 - q) * sigma
        if not ring.is_exact():
            resu = resu.real_part().round()
        return resu
Exemplo n.º 4
0
K1MASK = 2**m1 - 1
K1HIGHBIT = 2**(m1-1)
K0MASK = 2**m0 - 1
K0HIGHBIT = 2**(m0-1)
NECKLACES = 1/m1*sum(euler_phi(d)*2**(ZZ(m1/d)) for d in m1.divisors())
# 9*2*2*2 > 64
if m2 > 8:
    USE_DWORD = 1
else:
    USE_DWORD = 0

GF2 = GF(2)
x = polygen(GF2)
K2 = GF(2**m2, name='g2', modulus=modulus)
g2 = K2.gen()
z2 = K2.multiplicative_generator()
K1 = GF(2**m1, name='g1', modulus=modulus)
g1 = K1.gen()
z1 = K1.multiplicative_generator()
Z1 = z1.polynomial().change_ring(ZZ)(2)
K0 = GF(2**m0, name='g0', modulus=modulus)
g0 = K0.gen()
z0 = K0.multiplicative_generator()
L = [K0, K1, K2]
moduli = [k.modulus() for k in L]
F = [f.change_ring(ZZ)(2) for f in moduli]
weights = [f.hamming_weight()-2 for f in moduli]
degrees = [(f-x**f.degree()-1).exponents() for f in moduli]
FWEIGHTS = weights
F0D = degrees[0]
if F0D == [1]:
    def H_value(self, p, f, t, ring=None):
        """
        Return the trace of the Frobenius, computed in terms of Gauss sums
        using the hypergeometric trace formula.

        INPUT:

        - `p` -- a prime number

        - `f` -- an integer such that `q = p^f`

        - `t` -- a rational parameter

        - ``ring`` -- optional (default ``UniversalCyclotomicfield``)

        The ring could be also ``ComplexField(n)`` or ``QQbar``.

        OUTPUT:

        an integer

        .. WARNING::

            This is apparently working correctly as can be tested
            using ComplexField(70) as value ring.

            Using instead UniversalCyclotomicfield, this is much
            slower than the `p`-adic version :meth:`padic_H_value`.

        EXAMPLES:

        With values in the UniversalCyclotomicField (slow)::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: H = Hyp(alpha_beta=([1/2]*4,[0]*4))
            sage: [H.H_value(3,i,-1) for i in range(1,3)]
            [0, -12]
            sage: [H.H_value(5,i,-1) for i in range(1,3)]
            [-4, 276]
            sage: [H.H_value(7,i,-1) for i in range(1,3)]  # not tested
            [0, -476]
            sage: [H.H_value(11,i,-1) for i in range(1,3)]  # not tested
            [0, -4972]
            sage: [H.H_value(13,i,-1) for i in range(1,3)]  # not tested
            [-84, -1420]

        With values in ComplexField::

            sage: [H.H_value(5,i,-1, ComplexField(60)) for i in range(1,3)]
            [-4, 276]

        REFERENCES:

        - [BeCoMe]_ (Theorem 1.3)
        - [Benasque2009]_
        """
        alpha = self._alpha
        beta = self._beta
        if 0 in alpha:
            H = self.swap_alpha_beta()
            return(H.H_value(p, f, ~t, ring))
        if ring is None:
            ring = UniversalCyclotomicField()
        t = QQ(t)
        gamma = self.gamma_array()
        q = p ** f

        m = {r: beta.count(QQ((r, q - 1))) for r in range(q - 1)}
        D = -min(self.zigzag(x, flip_beta=True) for x in alpha + beta)
        # also: D = (self.weight() + 1 - m[0]) // 2
        M = self.M_value()

        Fq = GF(q)
        gen = Fq.multiplicative_generator()
        zeta_q = ring.zeta(q - 1)

        tM = Fq(M / t)
        for k in range(q - 1):
            if gen ** k == tM:
                teich = zeta_q ** k
                break

        gauss_table = [gauss_sum(zeta_q ** r, Fq) for r in range(q - 1)]

        sigma = sum(q**(D + m[0] - m[r]) *
                    prod(gauss_table[(-v * r) % (q - 1)] ** gv
                         for v, gv in gamma.items()) *
                    teich ** r
                    for r in range(q - 1))
        resu = ZZ(-1) ** m[0] / (1 - q) * sigma
        if not ring.is_exact():
            resu = resu.real_part().round()
        return resu