示例#1
0
def DuadicCodeOddPair(F, S1, S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        ([11, 6] Cyclic Code over GF(3),
         [11, 6] Cyclic Code over GF(3))

    This is consistent with Theorem 6.1.3 in [HP2003]_.
    """
    from sage.misc.stopgap import stopgap
    stopgap(
        "The function DuadicCodeOddPair has several issues which may cause wrong results",
        25896)

    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    j = sum([x**i / n for i in range(n)])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    coeffs1 = [
        _lift2smallest_field(c)[0] for c in (g1 + j).coefficients(sparse=False)
    ]
    coeffs2 = [
        _lift2smallest_field(c)[0] for c in (g2 + j).coefficients(sparse=False)
    ]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    gg1 = gcd(gg1, x**n - 1)
    gg2 = gcd(gg2, x**n - 1)
    C1 = CyclicCode(length=n, generator_pol=gg1)
    C2 = CyclicCode(length=n, generator_pol=gg2)
    return C1, C2
示例#2
0
def DuadicCodeOddPair(F, S1, S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 6 over Finite Field of size 3,
         Linear code of length 11, dimension 6 over Finite Field of size 3)

    This is consistent with Theorem 6.1.3 in [HP]_.
    """
    n = len(S1) + len(S2) + 1
    if not is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    j = sum([x**i / n for i in range(n)])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    coeffs1 = [
        lift2smallest_field(c)[0] for c in (g1 + j).coefficients(sparse=False)
    ]
    coeffs2 = [
        lift2smallest_field(c)[0] for c in (g2 + j).coefficients(sparse=False)
    ]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    C1 = CyclicCodeFromGeneratingPolynomial(n, gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n, gg2)
    return C1, C2
示例#3
0
def DuadicCodeEvenPair(F, S1, S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``_is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        ([11, 5] Cyclic Code over GF(3),
         [11, 5] Cyclic Code over GF(3))
    """
    from sage.misc.stopgap import stopgap
    stopgap(
        "The function DuadicCodeEvenPair has several issues which may cause wrong results",
        25896)

    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    gg1 = P2(
        [_lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2(
        [_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCode(length=n, generator_pol=gg1)
    C2 = CyclicCode(length=n, generator_pol=gg2)
    return C1, C2
示例#4
0
    def mutate_initial(self, k):
        r"""
        Mutate ``self`` in direction `k` at the initial cluster.

        INPUT:
        - ``k`` -- integer in between 0 and ``self.rk``
        """
        n = self.rk

        if k not in xrange(n):
            raise ValueError('Cannot mutate in direction %s, please try a value between 0 and %s.'%(str(k),str(n-1)))

        #modify self._path_dict using Nakanishi-Zelevinsky (4.1) and self._F_poly_dict using CA-IV (6.21)
        new_path_dict = dict()
        new_F_dict = dict()
        new_path_dict[tuple(identity_matrix(n).column(k))] = []
        new_F_dict[tuple(identity_matrix(n).column(k))] = self._U(1)

        poly_ring = PolynomialRing(ZZ,'u')
        h_subs_tuple = tuple([poly_ring.gen(0)**(-1) if j==k else poly_ring.gen(0)**max(-self._B0[k][j],0) for j in xrange(n)])
        F_subs_tuple = tuple([self._U.gen(k)**(-1) if j==k else self._U.gen(j)*self._U.gen(k)**max(-self._B0[k][j],0)*(1+self._U.gen(k))**(self._B0[k][j]) for j in xrange(n)])

        for g_vect in self._path_dict:
            #compute new path
            path = self._path_dict[g_vect]
            if g_vect == tuple(identity_matrix(n).column(k)):
                new_path = [k]
            elif path != []:
                if path[0] != k:
                    new_path = [k] + path
                else:
                    new_path = path[1:]
            else:
                new_path = []

            #compute new g-vector
            new_g_vect = vector(g_vect) - 2*g_vect[k]*identity_matrix(n).column(k)
            for i in xrange(n):
                new_g_vect += max(sign(g_vect[k])*self._B0[i,k],0)*g_vect[k]*identity_matrix(n).column(i)
            new_path_dict[tuple(new_g_vect)] = new_path

            #compute new F-polynomial
            h = 0
            trop = tropical_evaluation(self._F_poly_dict[g_vect](h_subs_tuple))
            if trop != 1:
                h = trop.denominator().exponents()[0]-trop.numerator().exponents()[0]
            new_F_dict[tuple(new_g_vect)] = self._F_poly_dict[g_vect](F_subs_tuple)*self._U.gen(k)**h*(self._U.gen(k)+1)**g_vect[k]

        self._path_dict = new_path_dict
        self._F_poly_dict = new_F_dict

        self._B0.mutate(k)
示例#5
0
def DuadicCodeOddPair(F,S1,S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        ([11, 6] Cyclic Code over GF(3),
         [11, 6] Cyclic Code over GF(3))

    This is consistent with Theorem 6.1.3 in [HP2003]_.
    """
    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1,S2,n):
        raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n))
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    j = sum([x**i/n for i in range(n)])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    coeffs1 = [_lift2smallest_field(c)[0] for c in (g1+j).coefficients(sparse=False)]
    coeffs2 = [_lift2smallest_field(c)[0] for c in (g2+j).coefficients(sparse=False)]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    gg1 = gcd(gg1, x**n - 1)
    gg2 = gcd(gg2, x**n - 1)
    C1 = CyclicCode(length = n, generator_pol = gg1)
    C2 = CyclicCode(length = n, generator_pol = gg2)
    return C1,C2
示例#6
0
def DuadicCodeOddPair(F,S1,S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = cyclotomic_cosets(q,n); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        (True, 2)
        sage: DuadicCodeOddPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 6 over Finite Field of size 3,
         Linear code of length 11, dimension 6 over Finite Field of size 3)

    This is consistent with Theorem 6.1.3 in [HP]_.
    """
    n = max(S1+S2)+1
    if not(is_a_splitting(S1,S2,n)):
        raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    j = sum([x**i/n for i in range(n)])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    coeffs1 = [lift2smallest_field(c)[0] for c in (g1+j).coeffs()]
    coeffs2 = [lift2smallest_field(c)[0] for c in (g2+j).coeffs()]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
    return C1,C2
示例#7
0
def conv(N):
    file = "data/%s" % N
    if not os.path.exists(file):
        raise RuntimeError, "Data for level %s does not exist." % N

    F = open(file).read()
    i = F.find(":=")
    if i == -1:
        raise RuntimeError, "Syntax error in file for level %s." % N
    F = F[i + 2:]
    TRANS = [("[*", "["), ("*]", "]"), ("<","["), (">","]"), \
             (";",""), ("\n",""), ("^","**")]
    for z, w in TRANS:
        F = F.replace(z, w)
    X = []
    # Define x so the eval below works.
    R = PolynomialRing(RationalField())
    x = R.gen()
    print "starting eval."
    #print "F = ", F
    for f in eval(F):
        print "creating object from f=", f[:4]
        cp = {}
        disc = 0
        for z in f[5]:
            g = R(z[1])
            disc = GCD(disc, g.discriminant())
            cp[z[0]] = g
        X.append(ModularForm(f[0], f[1], f[2], f[3], f[4], cp, disc))
    return X
示例#8
0
    def dependence_polynomial(self, t=None):
        r"""
        Return dependence polynomial.

        The polynomial is defined as follows: `\sum{i}{(-1)^i c_i t^i}`,
        where `c_i` equals to number of full subgraphs
        of size `i` in the independence graph.

        OUTPUT:

        A rational function in ``t`` with coefficients in the integer ring.

        EXAMPLES::

            sage: from sage.monoids.trace_monoid import TraceMonoid
            sage: I = (('a','d'), ('d','a'), ('b','c'), ('c','b'))
            sage: M.<a,b,c,d> = TraceMonoid(I=I)
            sage: M.dependence_polynomial()
            1/(2*t^2 - 4*t + 1)
        """
        if t is None:
            R = PolynomialRing(ZZ, 't')
            t = R.gen()
        clique_seq = self.independence_graph().clique_polynomial(
        ).coefficients()
        return ~sum(
            (-1)**i * coeff * (t**i) for i, coeff in enumerate(clique_seq))
示例#9
0
文件: conv.py 项目: bgxcpku/sagelib
def conv(N):
    file = "data/%s"%N
    if not os.path.exists(file):
        raise RuntimeError, "Data for level %s does not exist."%N

    F = open(file).read()
    i = F.find(":=")
    if i == -1:
        raise RuntimeError, "Syntax error in file for level %s."%N
    F = F[i+2:]
    TRANS = [("[*", "["), ("*]", "]"), ("<","["), (">","]"), \
             (";",""), ("\n",""), ("^","**")]
    for z,w in TRANS:
        F = F.replace(z,w)
    X = []
    # Define x so the eval below works.
    R = PolynomialRing(RationalField())
    x = R.gen()
    print "starting eval."
    #print "F = ", F
    for f in eval(F):
        print "creating object from f=",f[:4]
        cp = {}
        disc = 0        
        for z in f[5]:
            g = R(z[1])
            disc = GCD(disc,g.discriminant())
            cp[z[0]] = g
        X.append(ModularForm(f[0],f[1],f[2],f[3],f[4],cp,disc))
    return X
示例#10
0
class SiegelModularFormG2VVRepresentation(SageObject):
    def __init__(self, K):
        self.__K = K
        self.__R = PolynomialRing(K, ['x', 'y'])
        self.__x = self.__R.gen(0)
        self.__y = self.__R.gen(1)

    def from_module(self, R):
        assert R == PolynomialRing(R.base_ring(), ['x', 'y'])

        return SiegelModularFormG2VVRepresentation(R.base_ring())

    def base_ring(self):
        return self.__K

    def codomain(self):
        return self.__R

    def base_extend(self, L):
        if L.has_coerce_map_from(self.__K):
            return SiegelModularFormG2VVRepresentation(L)

        raise ValueError("Base extension of representation is not defined")

    def extends(self, other):
        if isinstance(other, TrivialRepresentation):
            return self.__K.has_coerce_map_from(other.codomain())
        elif type(self) != type(other):
            return False

        return self.__K.has_coerce_map_from(other.__K)

    def group(self):
        return "GL(2,ZZ)"

    def _apply_function(self):
        return self.apply

    def apply(self, g, a):
        return a(g[0] * self.__x + g[1] * self.__y,
                 g[2] * self.__x + g[3] * self.__y)

    def __cmp__(self, other):
        c = cmp(type(self), type(other))

        if c == 0:
            c = cmp(self.__K, other.__K)

        return c

    def __hash__(self):
        return hash(self.__K)

    def _repr_(self):
        return "Siegel modular form degree 2 vector valued representation on %s" % (
            self.__K)

    def _latex_(self):
        return "Siegel modular form degree 2 vector valued representation on %s" % (
            latex(self.__K))
示例#11
0
    def upper_components(self):
        r"""
        Return the list of all upper components lying above this lower component.

        This lower component corresponds to a discrete valuation `v` on a rational
        function field `L(x)` extending the valuation `v_L`, where `L/K` is some
        finite extension of the base field `K`. The upper components correspond
        to the extensions of v to the function field of `Y_L` (which is a finite
        extension of `L(x)`).

        Since the computation of all extensions of a nonstandard valuation on a
        function field to a finite extension is not yet part of Sage, we have
        to appeal to the MacLane algorithm ourselves.

        EXAMPLES:

        This example shows that extending valuations also works if the equation
        is not integral wrt the valuation v ::

            sage: from mclf import *
            sage: R.<x> = QQ[]
            sage: Y = SuperellipticCurve(5*x^3 + 1, 2)
            sage: Y2 = SemistableModel(Y, QQ.valuation(5))
            sage: Y2.is_semistable()  # indirect doctest
            True

        """
        from sage.geometry.newton_polygon import NewtonPolygon
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        v = self.valuation()
        FY = self.reduction_tree().curve().function_field()
        FYL = base_change_of_function_field(FY, self.base_field())
        FXL = FYL.rational_function_field()
        assert v.domain() == FXL
        G = FYL.polynomial()
        # now FYL = FXL(y| G(y) = 0)

        # we first have to make G integral with respect to v
        np = NewtonPolygon([(i,v(G[i])) for i in range(G.degree() + 1)])
        r = np.slopes()[-1]   # the largest slope
        if r <= 0:      # G is integral w.r.t. v
            upper_valuations = [FYL.valuation(w)
                for w in v.mac_lane_approximants(FYL.polynomial(), require_incomparability=True)]
        else:           # G is not integral
            vK = self.reduction_tree().base_valuation()
            pi = vK.uniformizer()           # we construct a function field FYL1
            k = QQ(r/v(pi)).ceil()          # isomorphic to FYL, but with
            R1 = PolynomialRing(FXL, 'y1')  # integral equation G_1
            y1 = R1.gen()
            G1 = G(pi**(-k)*y1).monic()
            assert all([v(c) >= 0 for c in G1.coefficients()]), "new G is not integral!"
            FYL1 = FXL.extension(G1, 'y1')
            y1 = FYL1.gen()
            V = v.mac_lane_approximants(G1, require_incomparability=True)
            V = [FYL1.valuation(w) for w in V]   # the extensions of v to FYL1
            upper_valuations = [FYL.valuation((w,
                    FYL.hom(y1/pi**k), FYL1.hom(pi**k*FYL.gen()))) for w in V]
                                                 # made into valuations on FYL
        return [UpperComponent(self, w) for w in upper_valuations]
示例#12
0
def DuadicCodeEvenPair(F, S1, S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 5 over Finite Field of size 3,
         Linear code of length 11, dimension 5 over Finite Field of size 3)
    """
    n = len(S1) + len(S2) + 1
    if not is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    gg1 = P2(
        [lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2(
        [lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCodeFromGeneratingPolynomial(n, gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n, gg2)
    return C1, C2
示例#13
0
def comp_prod(P, Q):
    n = Q.degree()
    K = P.base_ring()
    A = PolynomialRing(K, 'X')
    X = A.gen()
    AA = PolynomialRing(K, 'Y,Z')
    Y, Z = AA.gens()
    return P(Y).resultant(AA(Y**n * Q(Z/Y)), Y)(1,X)
示例#14
0
def DuadicCodeEvenPair(F,S1,S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``_is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        ([11, 5] Cyclic Code over GF(3),
         [11, 5] Cyclic Code over GF(3))
    """
    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1,S2,n):
        raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n))
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    gg1 = P2([_lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2([_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCode(length = n, generator_pol = gg1)
    C2 = CyclicCode(length = n, generator_pol = gg2)
    return C1,C2
class SiegelModularFormG2VVRepresentation ( SageObject ) :
    def __init__(self, K) :
        self.__K = K
        self.__R = PolynomialRing(K, ['x', 'y'])
        self.__x = self.__R.gen(0)
        self.__y = self.__R.gen(1)
    
    def from_module(self, R) :
        assert R == PolynomialRing(R.base_ring(), ['x', 'y'])
        
        return SiegelModularFormG2VVRepresentation(R.base_ring())
        
    def base_ring(self) :
        return self.__K
    
    def codomain(self) :
        return self.__R
    
    def base_extend(self, L) :
        if L.has_coerce_map_from(self.__K) :
            return SiegelModularFormG2VVRepresentation( L )
        
        raise ValueError, "Base extension of representation is not defined"
        
    def extends(self, other) :
        if isinstance(other, TrivialRepresentation) :
            return self.__K.has_coerce_map_from(other.codomain())
        elif type(self) != type(other) :
            return False
        
        return self.__K.has_coerce_map_from(other.__K)
        
    def group(self) :
        return "GL(2,ZZ)"
    
    def _apply_function(self) :
        return self.apply
    
    def apply(self, g, a) :
        return a(g[0]*self.__x + g[1]*self.__y, g[2]*self.__x + g[3]*self.__y)
    
    def __cmp__(self, other) :
        c = cmp(type(self), type(other))
        
        if c == 0 :
            c = cmp(self.__K, other.__K)
            
        return c
    
    def __hash__(self) :
        return hash(self.__K)

    def _repr_(self) :
        return "Siegel modular form degree 2 vector valued representation on %s" % (self.__K)
    
    def _latex_(self) :
        return "Siegel modular form degree 2 vector valued representation on %s" % (latex(self.__K))
    def has_rep(self, n, restrict=None, force=False):
        """
        Returns `True` if there exists an `n`-dimensional representation of `self`, and `False`
        otherwise.

        The optional argument `restrict` may be used to restrict the possible images of the
        generators. To do so, `restrict` must be a tuple with entries of `None`, `'diagonal'`,
        `'lower'`, or `'upper'`. Its length must match the number of generators of `self`.

        Use `force=True` if the function does not recognize the base field as computable, but the
        field is computable.
        """
        if (not force and self.base_field() not in NumberFields
                and self.base_field() not in FiniteFields):
            raise TypeError(
                'Base field must be computable. If %s is computable' %
                self.base_field() + ' then use force=True to bypass this.')

        if n not in ZZ or n < 1:
            raise ValueError('Dimension must be a positive integer.')

        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        import math

        B = PolynomialRing(self.base_field(), (self.ngens() * n**2 + 1),
                           'x',
                           order='deglex')
        M = MatrixSpace(B, n, sparse=True)

        gen_matrix = list()
        if not isinstance(restrict, (tuple, list)):
            restrict = [None for i in range(self.ngens())]
        if len(restrict) != self.ngens():
            raise ValueError(
                'Length of restrict does not match number of generators.')
        for i in range(self.ngens()):
            ith_gen_matrix = []
            for j in range(n):
                for k in range(n):
                    if restrict[i] == 'upper' and j > k:
                        ith_gen_matrix.append(B.zero())
                    elif restrict[i] == 'lower' and j < k:
                        ith_gen_matrix.append(B.zero())
                    elif restrict[i] == 'diagonal' and j != k:
                        ith_gen_matrix.append(B.zero())
                    else:
                        ith_gen_matrix.append(B.gen(j + (j + 1) * k +
                                                    i * n**2))
            gen_matrix.append(M(ith_gen_matrix))

        relB_list = list()
        for i in range(self.nrels()):
            relB_list += self._to_matrix(self.rel(i), M, gen_matrix).list()
        relB = B.ideal(relB_list)

        if relB.dimension() == -1: return False
        else: return True
示例#17
0
def DuadicCodeEvenPair(F,S1,S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = cyclotomic_cosets(q,n); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        (True, 2)
        sage: DuadicCodeEvenPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 5 over Finite Field of size 3,
         Linear code of length 11, dimension 5 over Finite Field of size 3)
    """
    n = max(S1+S2)+1
    if not(is_a_splitting(S1,S2,n)):
        raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    gg1 = P2([lift2smallest_field(c)[0] for c in g1.coeffs()])
    gg2 = P2([lift2smallest_field(c)[0] for c in g2.coeffs()])
    C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
    return C1,C2
示例#18
0
    def from_recurrence(cls, coefficients, values):
        """
    Create a C-finite sequence given the coefficients $c$ and starting values $a$
    of a homogenous linear recurrence.

    .. MATH::
    
        a_{n+d} = c_0a_n + c_1a_{n+1} + \cdots + c_{d-1}a_{n+d-1}, \quad d\ge0.

    INPUT:

    - ``coefficients`` -- a list of rationals

    - ``values`` -- start values, a list of rationals

    OUTPUT:

    - A CFiniteSequence object

    EXAMPLES::

        sage: R.<x> = QQ[]
        sage: CFiniteSequence.from_recurrence([1,1],[0,1])   # Fibonacci numbers
        C-finite sequence, generated by x/(-x^2 - x + 1)
        sage: CFiniteSequence.from_recurrence([-1,2],[0,1])    # natural numbers
        C-finite sequence, generated by x/(x^2 - 2*x + 1)
        sage: r = CFiniteSequence.from_recurrence([-1],[1])
        sage: s = CFiniteSequence.from_recurrence([-1],[1,-1])
        sage: r == s
        True
        sage: r = CFiniteSequence(x^3/(1-x-x^2))
        sage: s = CFiniteSequence.from_recurrence([1,1],[0,0,0,1,1])
        sage: r == s
        True
        sage: CFiniteSequence.from_recurrence(1,1)
        Traceback (most recent call last):
        ...
        ValueError: Wrong type for recurrence coefficient list.
        """

        if not isinstance(coefficients, list):
            raise ValueError("Wrong type for recurrence coefficient list.")
        if not isinstance(values, list):
            raise ValueError("Wrong type for recurrence start value list.")
        deg = len(coefficients)

        co = coefficients[::-1]
        co.extend([0] * (len(values) - deg))
        R = PolynomialRing(QQ, 'x')
        x = R.gen()
        den = -1 + sum([x ** (n + 1) * co[n] for n in range(deg)])
        num = -values[0] + sum([x ** n * (-values[n] + sum([values[k] * co[n - 1 - k] for k in range(n)])) for n in range(1, len(values))])
        return cls(num / den)
示例#19
0
def sorted_roots(R, f, p=None):
    H = PolynomialRing(R, names='x')
    x = H.gen()
    if p is None:
        p = R.prime()
    k = f.weight()
    chi = f.character()
    pol = H([R(chi(p) * p**(k - 1)), R(-f.coefficients([p])[0]), R(1)])
    alpha, beta = [o[0] for o in pol.roots()]
    if alpha.valuation() > beta.valuation():
        alpha, beta = beta, alpha
    return alpha, beta
示例#20
0
def _step_upper_bound_low_mem(r, m, q, generating_function):
    r"""
    Low memory implementation of :func:`_step_upper_bound_internal`.

    Significantly slower, but the memory footprint does not significantly
    increase even if the series coefficients need to be computed to very high
    degree terms.
    """
    L = LieAlgebra(ZZ, ['X_%d' % k for k in range(r)]).Lyndon()
    dim_fm = L.graded_dimension(m)

    PR = PolynomialRing(ZZ, 't')
    t = PR.gen()
    a = (1 - dim_fm * (1 - t**q)) * t**m
    b = PR.one()
    for k in range(1, m):
        b *= (1 - t**k)**L.graded_dimension(k)

    # extract initial coefficients from a symbolic series expansion
    bd = b.degree()
    id = max(a.degree() + 1, bd)
    offset = id - bd
    quot = SR(a / b)
    sym_t = SR(t)
    qs = quot.series(sym_t, id)

    # check if partial sum is positive already within series expansion
    # store the last offset...id terms to start the linear recurrence
    coeffs = deque()
    cumul = ZZ.zero()
    for s in range(id):
        c = ZZ(qs.coefficient(sym_t, s))
        cumul += c
        if s >= offset:
            coeffs.append(c)
        if cumul > 0:
            if generating_function:
                return s, quot
            return s

    # the rest of the coefficients are defined by a recurrence relation
    multipliers = [-b.monomial_coefficient(t**(bd - k)) for k in range(bd)]
    while cumul <= 0:
        c_next = sum(c * m for c, m in zip(coeffs, multipliers))
        cumul += c_next
        s += 1
        coeffs.append(c_next)
        coeffs.popleft()

    if generating_function:
        return s, quot
    return s
示例#21
0
def logp(p, p_prec):
    """
    Returns the (integral) power series for log_p(1+z) as a polynomial in y over the rationals of degree < p_prec.
    
    EXAMPLES::
        
        sage: from sage.modular.pollack_stevens.families_util import logp
        sage: logp(11, 5)
        -1/4*y^4 + 1/3*y^3 - 1/2*y^2 + y
    """
    SS = PolynomialRing(QQ, 'y')
    y = SS.gen()
    return sum([((-1)**(m - 1)) * (y**m) / m for m in range(1, p_prec)])
示例#22
0
def logp(p, p_prec):
    """
    Returns the (integral) power series for log_p(1+z) as a polynomial in y over the rationals of degree < p_prec.
    
    EXAMPLES::
        
        sage: from sage.modular.pollack_stevens.families_util import logp
        sage: logp(11, 5)
        -1/4*y^4 + 1/3*y^3 - 1/2*y^2 + y
    """
    SS = PolynomialRing(QQ, 'y')
    y = SS.gen()
    return sum([((-1) ** (m - 1)) * (y ** m) / m for m in range(1, p_prec)])
 def __init__(self,lambda_squared=None, field=None):
     if lambda_squared==None:
         from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
         R=PolynomialRing(ZZ,'x')
         x = R.gen()
         field=NumberField(x**3-ZZ(5)*x**2+ZZ(4)*x-ZZ(1), 'r', embedding=AA(ZZ(4)))
         self._l=field.gen()
     else:
         if field is None:
             self._l=lambda_squared
             field=lambda_squared.parent()
         else:
             self._l=field(lambda_squared)
     Surface.__init__(self,field, ZZ.zero(), finite=False)
示例#24
0
 def F(z,level = 0,method = 'moments'):
     R = PolynomialRing(z.parent(),'x,y').fraction_field()
     Rx = PolynomialRing(z.parent(),'x1').fraction_field()
     x1 = Rx.gen()
     subst = R.hom([x1,z],codomain = Rx)
     x,y = R.gens()
     center = self.parent()._source._BT.find_containing_affinoid(z)
     zbar = z.trace()-z
     f = R(1)/(x-y)
     k = self.parent()._n+2
     V = [f]
     for ii in range(order):
         V = [v.derivative(y) for v in V]+[k/(y-zbar)*v for v in V]
         k += 2
     return sum([self.integrate(subst(v),center,level,method) for v in V])
def bw_shift_rec(dop, shift=ZZ.zero()):
    Pols_n = PolynomialRing(dop.base_ring().base_ring(), 'n')  # XXX: name
    Rops = ore_algebra.OreAlgebra(Pols_n, 'Sn')
    # Using the primitive part here would break the computation of residuals!
    # TODO: add test (arctan); better fix?
    # Other interesting cases: operators of the for P(Θ) (with constant
    # coefficients)
    #rop = dop.to_S(Rops).primitive_part().numerator()
    rop = dop.to_S(Rops)
    ordrec = rop.order()
    coeff = [
        rop[ordrec - k](Pols_n.gen() - ordrec + shift)
        for k in xrange(ordrec + 1)
    ]
    return BwShiftRec(coeff)
示例#26
0
 def F(z):
     R=PolynomialRing(z.parent(),'x,y').fraction_field()
     Rx=PolynomialRing(z.parent(),'x1').fraction_field()
     x1=Rx.gen()
     subst=R.hom([x1,z],codomain=Rx)
     x,y=R.gens()
     center=self._parent._X._BT.find_containing_affinoid(z)
     zbar=z.trace()-z
     f=R(1)/(x-y)
     k=self._parent._k
     V=[f]
     for ii in range(order):
         V=[v.derivative(y) for v in V]+[k/(y-zbar)*v for v in V]
         k+=2
     return sum([self.riemann_sum(subst(v),center,level) for v in V])
 def __init__(self, lambda_squared=None, field=None):
     if lambda_squared == None:
         from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
         R = PolynomialRing(ZZ, 'x')
         x = R.gen()
         field = NumberField(x**3 - ZZ(5) * x**2 + ZZ(4) * x - ZZ(1),
                             'r',
                             embedding=AA(ZZ(4)))
         self._l = field.gen()
     else:
         if field is None:
             self._l = lambda_squared
             field = lambda_squared.parent()
         else:
             self._l = field(lambda_squared)
     Surface.__init__(self, field, ZZ.zero(), finite=False)
示例#28
0
    def test_01(self):
        order = 2**8
        F = FiniteField(order, 'a')
        P = PolynomialRing(F, 'x')
        n = 7
        deg = 2
        poly = F.fetch_int(42)
        for i in range(1, deg+1):
            poly += F.random_element() * P.gen()**i

        # evaluate polynomial at different points (shares)
        print(poly)
        points = [(F.fetch_int(i), poly(F.fetch_int(i))) for i in range(1, n+1)]
        points[0] = (points[0][0], points[0][1] + F.fetch_int(9))
        print(points)
        assert poly == berlekamp_welsh(deg, points)
 def _raise(self, p, level, weight):
     """
     Helper function for :meth:`raise_level` and :meth:`raise_weight`.
     """
     from eigenform_collection import EigenformCollection
     F = self.base_ring()
     R = PolynomialRing(F, 't')
     t = R.gen()
     chi = self.character()
     poly = t**2 - self.coefficient(p) * t + chi(p) * p**(self.weight() - 1)
     roots = poly.roots(multiplicities=False)
     apdict = copy(self._apdict)
     C = EigenformCollection(Gamma1(level), weight, F, chi.extend(level))
     for a in roots:
         apdict[p] = a
         yield C(apdict)
    def test_01(self):
        order = 2**8
        F = FiniteField(order, 'a')
        P = PolynomialRing(F, 'x')
        n = 7
        deg = 2
        poly = F.fetch_int(42)
        for i in range(1, deg + 1):
            poly += F.random_element() * P.gen()**i

        # evaluate polynomial at different points (shares)
        print(poly)
        points = [(F.fetch_int(i), poly(F.fetch_int(i)))
                  for i in range(1, n + 1)]
        points[0] = (points[0][0], points[0][1] + F.fetch_int(9))
        print(points)
        assert poly == berlekamp_welsh(deg, points)
 def __init__(self,lambda_squared=None, field=None):
     TranslationSurface_generic.__init__(self)
     if lambda_squared==None:
         from sage.rings.number_field.number_field import NumberField
         from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
         R=PolynomialRing(ZZ,'x')
         x = R.gen()
         from sage.rings.qqbar import AA
         self._field=NumberField(x**3-ZZ(5)*x**2+ZZ(4)*x-ZZ(1), 'r', embedding=AA(ZZ(4)))
         self._l=self._field.gen()
     else:
         if field is None:
             self._l=lambda_squared
             self._field=lambda_squared.parent()
         else:
             self._field=field
             self._l=field(lambda_squared)
示例#32
0
def component_jumps(xi0, xi1):
    r""" Helper function for ``permanent_completion``.

    """
    from sage.geometry.newton_polygon import NewtonPolygon
    from mclf.berkovich.berkovich_line import valuations_from_inequality
    from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    from mclf.berkovich.berkovich_line import TypeIIPointOnBerkovichLine

    assert xi0.is_leq(xi1), "xi0 has to be an ancestor of xi1"
    X = xi0.berkovich_line()
    vK = X.base_valuation()

    v0 = xi0.pseudovaluation_on_polynomial_ring()
    v1 = xi1.pseudovaluation_on_polynomial_ring()
    y = xi1.parameter()
    if hasattr(v1, "phi"):
        phi = v1.phi()
        # v1 is an inductive valuation
    else:
        phi = v1._G
        # v1 is a limit valuation
    assert v0(phi) < v1(phi), "xi0 is not an ancestor of xi1!"
    R = phi.parent()
    x = R.gen()
    S = PolynomialRing(R, 'T')
    T = S.gen()
    G = phi(x + T)
    NP = NewtonPolygon([(i, v1(G[i])) for i in range(G.degree() + 1)])
    V = []
    vertices = NP.vertices()
    for k in range(len(vertices) - 1):
        i, ai = vertices[k]
        j, aj = vertices[k + 1]
        a0 = aj - j * (ai - aj) / (i - j)
        # print("a0 = ", a0)
        V += valuations_from_inequality(vK, phi, a0, v0)
    ret = [TypeIIPointOnBerkovichLine(X, (v, y)) for v in V]
    """
    if xi1.is_in_unit_disk():
        ret = [X.point_from_polynomial_pseudovaluation(v) for v in V]
    else:
        ret = [X.point_from_polynomial_pseudovaluation(v, in_unit_disk=False) for v in V]
    """
    return [xi for xi in ret if (xi0.is_leq(xi) and xi.is_leq(xi1))]
示例#33
0
    def generating_series(self, var='z'):
        r"""
        Return `1 / (1-z)`.

        EXAMPLES::

            sage: N = SetsWithGrading().example(); N
            Non negative integers
            sage: f = N.generating_series(); f
            1/(-z + 1)
            sage: LaurentSeriesRing(ZZ,'z')(f)
            1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + z^7 + z^8 + z^9 + z^10 + z^11 + z^12 + z^13 + z^14 + z^15 + z^16 + z^17 + z^18 + z^19 + O(z^20)
        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.rings.integer import Integer
        R = PolynomialRing(IntegerRing(), var)
        z = R.gen()
        return Integer(1) / (Integer(1) - z)
示例#34
0
    def Tokuyama_formula(self, name='t'):
        r"""
        Return the Tokuyama formula of ``self``.

        Following the exposition of [BBF]_, Tokuyama's formula asserts

        .. MATH::

            \sum_{G} (t+1)^{s(G)} t^{l(G)}
            z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}
            = s_{\lambda} (z_1, \ldots, z_{n+1}) \prod_{i<j} (z_j+tz_i),

        where the sum is over all strict Gelfand-Tsetlin patterns with fixed
        top row `\lambda+\rho`, with `\lambda` a partition with at most
        `n+1` parts and `\rho = (n,n-1,\dots,1,0)`, and `s_{\lambda}` is a Schur
        function.

        INPUT:

        - ``name`` -- (Default: ``'t'``) An alternative name for the
          variable `t`.

        EXAMPLES::

            sage: GT = GelfandTsetlinPatterns(top_row=[2,1,0],strict=True)
            sage: GT.Tokuyama_formula()
            t^3*x1^2*x2 + t^2*x1*x2^2 + t^2*x1^2*x3 + t^2*x1*x2*x3 + t*x1*x2*x3 + t*x2^2*x3 + t*x1*x3^2 + x2*x3^2
            sage: GT = GelfandTsetlinPatterns(top_row=[3,2,1],strict=True)
            sage: GT.Tokuyama_formula()
            t^3*x1^3*x2^2*x3 + t^2*x1^2*x2^3*x3 + t^2*x1^3*x2*x3^2 + t^2*x1^2*x2^2*x3^2 + t*x1^2*x2^2*x3^2 + t*x1*x2^3*x3^2 + t*x1^2*x2*x3^3 + x1*x2^2*x3^3
            sage: GT = GelfandTsetlinPatterns(top_row=[1,1,1],strict=True)
            sage: GT.Tokuyama_formula()
            0
        """
        n = self._n
        variables = [name] + ["x%d" % i for i in range(1, n + 1)]
        R = PolynomialRing(ZZ, names=variables)
        t = R.gen(0)
        x = R.gens()[1:]
        GT = GelfandTsetlinPatterns(top_row=self._row, strict=True)
        return sum((t + 1)**(gt.number_of_special_entries()) *
                   t**(gt.number_of_boxes()) * prod(x[i]**gt.weight()[i]
                                                    for i in range(n))
                   for gt in GT)
示例#35
0
    def Tokuyama_coefficient(self, name='t'):
        r"""
        Return the Tokuyama coefficient attached to ``self``.

        Following the exposition of [BBF]_, Tokuyama's formula asserts

        .. MATH::

            \sum_{G} (t+1)^{s(G)} t^{l(G)}
            z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}
            =
            s_{\lambda}(z_1,\dots,z_{n+1}) \prod_{i<j} (z_j+tz_i),

        where the sum is over all strict Gelfand-Tsetlin patterns with fixed
        top row `\lambda + \rho`, with `\lambda` a partition with at most
        `n+1` parts and `\rho = (n, n-1, \ldots, 1, 0)`, and `s_\lambda` is a
        Schur function.

        INPUT:

        - ``name`` -- (Default: ``'t'``) An alternative name for the
          variable `t`.

        EXAMPLES::

            sage: P = GelfandTsetlinPattern([[3,2,1],[2,2],[2]])
            sage: P.Tokuyama_coefficient()
            0
            sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[2]])
            sage: G.Tokuyama_coefficient()
            t^2 + t
            sage: G = GelfandTsetlinPattern([[2,1,0],[1,1],[1]])
            sage: G.Tokuyama_coefficient()
            0
            sage: G = GelfandTsetlinPattern([[5,3,2,1,0],[4,3,2,0],[4,2,1],[3,2],[3]])
            sage: G.Tokuyama_coefficient()
            t^8 + 3*t^7 + 3*t^6 + t^5
        """
        R = PolynomialRing(ZZ, name)
        t = R.gen(0)
        if self.is_strict() == False:
            return R(0)
        return (t + 1)**(self.number_of_special_entries()) * t**(
            self.number_of_boxes())
示例#36
0
    def generating_series(self, var='z'):
        r"""
        Returns `1 / (1-z)`.


        EXAMPLES::

            sage: N = SetsWithGrading().example(); N
            Non negative integers
            sage: f = N.generating_series(); f
            1/(-z + 1)
            sage: LaurentSeriesRing(ZZ,'z')(f)
            1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + z^7 + z^8 + z^9 + z^10 + z^11 + z^12 + z^13 + z^14 + z^15 + z^16 + z^17 + z^18 + z^19 + O(z^20)
        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.rings.integer import Integer
        R = PolynomialRing(IntegerRing(), var)
        z = R.gen()
        return Integer(1) / (Integer(1)-z)
示例#37
0
    def Tokuyama_coefficient(self, name='t'):
        r"""
        Return the Tokuyama coefficient attached to ``self``.

        Following the exposition of [BBF]_, Tokuyama's formula asserts

        .. MATH::

            \sum_{G} (t+1)^{s(G)} t^{l(G)}
            z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}
            =
            s_{\lambda}(z_1,\dots,z_{n+1}) \prod_{i<j} (z_j+tz_i),

        where the sum is over all strict Gelfand-Tsetlin patterns with fixed
        top row `\lambda + \rho`, with `\lambda` a partition with at most
        `n+1` parts and `\rho = (n, n-1, \ldots, 1, 0)`, and `s_\lambda` is a
        Schur function.

        INPUT:

        - ``name`` -- (Default: ``'t'``) An alternative name for the
          variable `t`.

        EXAMPLES::

            sage: P = GelfandTsetlinPattern([[3,2,1],[2,2],[2]])
            sage: P.Tokuyama_coefficient()
            0
            sage: G = GelfandTsetlinPattern([[3,2,1],[3,1],[2]])
            sage: G.Tokuyama_coefficient()
            t^2 + t
            sage: G = GelfandTsetlinPattern([[2,1,0],[1,1],[1]])
            sage: G.Tokuyama_coefficient()
            0
            sage: G = GelfandTsetlinPattern([[5,3,2,1,0],[4,3,2,0],[4,2,1],[3,2],[3]])
            sage: G.Tokuyama_coefficient()
            t^8 + 3*t^7 + 3*t^6 + t^5
        """
        R = PolynomialRing(ZZ, name)
        t = R.gen(0)
        if self.is_strict() == False:
            return R(0)
        return (t+1)**(self.number_of_special_entries()) * t**(self.number_of_boxes())
示例#38
0
    def Tokuyama_formula(self, name='t'):
        r"""
        Return the Tokuyama formula of ``self``.

        Following the exposition of [BBF]_, Tokuyama's formula asserts

        .. MATH::

            \sum_{G} (t+1)^{s(G)} t^{l(G)}
            z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2}
            = s_{\lambda} (z_1, \ldots, z_{n+1}) \prod_{i<j} (z_j+tz_i),

        where the sum is over all strict Gelfand-Tsetlin patterns with fixed
        top row `\lambda+\rho`, with `\lambda` a partition with at most
        `n+1` parts and `\rho = (n,n-1,\dots,1,0)`, and `s_{\lambda}` is a Schur
        function.

        INPUT:

        - ``name`` -- (Default: ``'t'``) An alternative name for the
          variable `t`.

        EXAMPLES::

            sage: GT = GelfandTsetlinPatterns(top_row=[2,1,0],strict=True)
            sage: GT.Tokuyama_formula()
            t^3*x1^2*x2 + t^2*x1*x2^2 + t^2*x1^2*x3 + t^2*x1*x2*x3 + t*x1*x2*x3 + t*x2^2*x3 + t*x1*x3^2 + x2*x3^2
            sage: GT = GelfandTsetlinPatterns(top_row=[3,2,1],strict=True)
            sage: GT.Tokuyama_formula()
            t^3*x1^3*x2^2*x3 + t^2*x1^2*x2^3*x3 + t^2*x1^3*x2*x3^2 + t^2*x1^2*x2^2*x3^2 + t*x1^2*x2^2*x3^2 + t*x1*x2^3*x3^2 + t*x1^2*x2*x3^3 + x1*x2^2*x3^3
            sage: GT = GelfandTsetlinPatterns(top_row=[1,1,1],strict=True)
            sage: GT.Tokuyama_formula()
            0
        """
        n = self._n
        variables = [name] + ["x%d"%i for i in range(1,n+1)]
        R = PolynomialRing(ZZ,names=variables)
        t = R.gen(0)
        x = R.gens()[1:]
        GT = GelfandTsetlinPatterns(top_row=self._row, strict=True)
        return sum((t+1)**(gt.number_of_special_entries()) * t**(gt.number_of_boxes()) * prod(x[i]**gt.weight()[i] for i in range(n)) for gt in GT)
示例#39
0
    def _kohnen_rho_polynomial(self, t, p):
        P = PolynomialRing(ZZ, 'x')
        x = P.gen(0)

        #tc = self._minimal_isotropic_subspace_complement_mod_p(t, p)

        if t[0, 0] != 0:
            return (1 - x**2)

        for i in range(t.nrows()):
            if t[i, i] != 0:
                break

        if i % 2 == 0:
            ## Since we have semi definite indices Kohnen's lambda simplifies
            lambda_p = 1 if t == 0 else -1
            ## For we multiply x in the second factor by p**(1/2) to make all coefficients rational.
            return (1 - x**2) * (1 + lambda_p * p**((i + 1) // 2) * x) * \
                   prod(1 - p**(2*j - 1) * x**2 for j in range(1, i // 2))
        else:
            return (1 - x**2) * \
                   prod(1 - p**(2*j - 1) * x**2 for j in range(1, i // 2))
示例#40
0
 def _kohnen_rho_polynomial(self, t, p) :
     P = PolynomialRing(ZZ, 'x')
     x = P.gen(0)
     
     #tc = self._minimal_isotropic_subspace_complement_mod_p(t, p)
     
     if t[0,0] != 0 :
         return (1 - x**2)
     
     for i in xrange(t.nrows()) :
         if t[i,i] != 0 :
             break
     
     if i % 2 == 0 :
         ## Since we have semi definite indices Kohnen's lambda simplifies
         lambda_p = 1 if t == 0 else -1
         ## For we multiply x in the second factor by p**(1/2) to make all coefficients rational.
         return (1 - x**2) * (1 + lambda_p * p**((i + 1) // 2) * x) * \
                prod(1 - p**(2*j - 1) * x**2 for j in xrange(1, i // 2))
     else :
         return (1 - x**2) * \
                prod(1 - p**(2*j - 1) * x**2 for j in xrange(1, i // 2))
示例#41
0
def jorder4(p):
    r"""
    Produce a particularly complicated example of polynomials for
    factorization over Zp(p).

    This method exists to test p-adic polynomial factorization.

    INPUT:

    - ``p`` -- a prime number

    OUTPUT:

    - A p-adic polynomial over Zp(``p``)

    EXAMPLES::

        sage: from sage.rings.polynomial.padics.factor.factoring import jorder4
        sage: jorder4(3)
        (1 + O(3^20))*x^24 + (24 + O(3^20))*x^23 + (276 + O(3^20))*x^22 + (2048 + O(3^20))*x^21 + (11310 + O(3^20))*x^20 + (51180 + O(3^20))*x^19 + (201652 + O(3^20))*x^18 + (709092 + O(3^20))*x^17 + (2228787 + O(3^20))*x^16 + (6232484 + O(3^20))*x^15 + (15469950 + O(3^20))*x^14 + (34143276 + O(3^20))*x^13 + (67323664 + O(3^20))*x^12 + (119268300 + O(3^20))*x^11 + (190652502 + O(3^20))*x^10 + (275456480 + O(3^20))*x^9 + (359189415 + O(3^20))*x^8 + (420635664 + O(3^20))*x^7 + (438402286 + O(3^20))*x^6 + (400618284 + O(3^20))*x^5 + (313569267 + O(3^20))*x^4 + (203945072 + O(3^20))*x^3 + (105227142 + O(3^20))*x^2 + (38341248 + O(3^20))*x + (10912597 + O(3^20))

    Input must be prime::

        sage: jorder4(4)
        Traceback (most recent call last):
        ...
        ValueError: p must be prime

    """
    K = ZpFM(p,20,print_mode='terse')
    Kx = PolynomialRing(K,names='x')
    x = Kx.gen()
    f1 = (x+1)**3+p;
    f2 = f1**2+p**2*(x+1);
    f3 = f2**2+4*p**3*f1*(x+1)**2;
    f4 = f3**2+20*p**2*f3*f2*(x+1)**2+64*p**9*f1;
    return f4;
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension() + 1
        d = self.dimension()
        # create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N * (d + 1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n - N + t) for t in range(N)]
        # map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords, S)
        phi(self.defining_polynomials()[0])
        # create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d + 1):
            t = 0
            for j in range(N):
                t += S.gen(N * i + j) * newcoords[j]
            l.append(t)
        # intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        # saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(u) for u in R.gens()]))[0]
        # eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        # create the plucker coordinates
        D = binomial(N, N - d - 1)  #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)]  #plucker coordinates
        T = PolynomialRing(R.base_ring(),
                           tvars + list(S.variable_names()),
                           order='lex')
        L = []
        coeffs = [
            T.gen(i) for i in range(0 + len(tvars),
                                    N * (d + 1) + len(tvars))
        ]
        M = matrix(T, d + 1, N, coeffs)
        i = 0
        for c in M.minors(d + 1):
            L.append(T.gen(i) - c)
            i += 1
        # create the ideal that we can use for eliminating to get a polynomial
        # in the plucker coordinates (brackets)
        br = T.ideal(L)
        # create a mapping into a polynomial ring over the plucker coordinates
        # and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for _ in range(N)], T)
        E2 = T.ideal([psi(u) for u in E.gens()] + br)
        # eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        # CH should be a principal ideal, but because of the relations among
        # the plucker coordinates, the elimination will probably have several generators

        # get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        # reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        # find the principal generator

        # polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N * (d + 1) + N) * [0], T2)
        # get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        # need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d > 0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind]  #this should be the Chow form of X
        # check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all(f in rel2
                   for f in CH.gens()), "did not find a principal generator"
        return alp(CF)
示例#43
0
def Min(Fun, p, ubRes, conj, all_orbits=False):
    r"""
    Local loop for Affine_minimal, where we check minimality at the prime p.

    First we bound the possible k in our transformations A = zp^k + b.
    See Theorems 3.3.2 and 3.3.3 in [Molnar]_.

    INPUT:

    - ``Fun`` -- a dynamical system on projective space

    - ``p`` - a prime

    - ``ubRes`` -- integer, the upper bound needed for Th. 3.3.3 in [Molnar]_

    - ``conj`` -- a 2x2 matrix keeping track of the conjugation

    - ``all_orbits`` -- boolean; whether or not to use ``==`` in the
      inequalities to find all orbits

    OUTPUT:

    - boolean -- ``True`` if ``Fun`` is minimal at ``p``, ``False`` otherwise

    - a dynamical system on projective space minimal at ``p``

    EXAMPLES::

        sage: P.<x,y> = ProjectiveSpace(QQ, 1)
        sage: f = DynamicalSystem_projective([149*x^2 + 39*x*y + y^2, -8*x^2 + 137*x*y + 33*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import Min
        sage: Min(f, 3, -27000000, matrix(QQ,[[1, 0],[0, 1]]))
        [
        Dynamical System of Projective Space of dimension 1 over Rational Field
          Defn: Defined on coordinates by sending (x : y) to
                (157*x^2 + 72*x*y + 3*y^2 : -24*x^2 + 121*x*y + 54*y^2)        ,
        <BLANKLINE>
        [3 1]
        [0 1]
        ]
    """
    d = Fun.degree()
    AffFun = Fun.dehomogenize(1)
    R = AffFun.coordinate_ring()
    if R.is_field():
        #want the polynomial ring not the fraction field
        R = R.ring()
    F = R(AffFun[0].numerator())
    G = R(AffFun[0].denominator())
    dG = G.degree()
    # all_orbits scales bounds for >= and <= if searching for orbits instead of min model
    if dG > (d + 1) / 2:
        lowerBound = (-2 * (G[dG]).valuation(p) /
                      (2 * dG - d + 1) + 1).floor() - int(all_orbits)
    else:
        lowerBound = (-2 * (F[d]).valuation(p) /
                      (d - 1) + 1).floor() - int(all_orbits)
    upperBound = 2 * (ubRes.valuation(p)) + int(all_orbits)

    if upperBound < lowerBound:
        # There are no possible transformations to reduce the resultant.
        if not all_orbits:
            return [Fun, conj]
        return []
    # Looping over each possible k, we search for transformations to reduce
    # the resultant of F/G
    all_found = []
    k = lowerBound
    Qb = PolynomialRing(QQ, 'b')
    b = Qb.gen(0)
    Q = PolynomialRing(Qb, 'z')
    z = Q.gen(0)
    while k <= upperBound:
        A = (p**k) * z + b
        Ft = Q(F(A) - b * G(A))
        Gt = Q((p**k) * G(A))
        Fcoeffs = Ft.coefficients(sparse=False)
        Gcoeffs = Gt.coefficients(sparse=False)
        coeffs = Fcoeffs + Gcoeffs
        RHS = (d + 1) * k / 2
        # If there is some b such that Res(phi^A) < Res(phi), we must have
        # ord_p(c) > RHS for each c in coeffs.
        # Make sure constant coefficients in coeffs satisfy the inequality.
        if all(
                QQ(c).valuation(p) > RHS - int(all_orbits) for c in coeffs
                if c.degree() == 0):
            # Constant coefficients in coeffs have large enough valuation, so
            # check the rest. We start by checking if simply picking b=0 works.
            if all(c(0).valuation(p) > RHS - int(all_orbits) for c in coeffs):
                # A = z*p^k satisfies the inequalities, and F/G is not minimal
                # "Conjugating by", p,"^", k, "*z +", 0
                newconj = matrix(QQ, 2, 2, [p**k, 0, 0, 1])
                minFun = Fun.conjugate(newconj)
                minFun.normalize_coordinates()
                if not all_orbits:
                    return [minFun, conj * newconj]
                all_found.append([p, k, 0])

            # Otherwise we search if any value of b will work. We start by
            # finding a minimum bound on the valuation of b that is necessary.
            # See Theorem 3.3.5 in [Molnar, M.Sc. thesis].
            bval = max(
                bCheck(coeff, RHS, p, b) for coeff in coeffs
                if coeff.degree() > 0)

            # We scale the coefficients in coeffs, so that we may assume
            # ord_p(b) is at least 0
            scaledCoeffs = [coeff(b * (p**bval)) for coeff in coeffs]

            # We now scale the inequalities, ord_p(coeff) > RHS, so that
            # coeff is in ZZ[b]
            scale = QQ(max(coeff.denominator() for coeff in scaledCoeffs))
            normalizedCoeffs = [coeff * scale for coeff in scaledCoeffs]
            scaleRHS = RHS + scale.valuation(p)

            # We now search for integers that satisfy the inequality
            # ord_p(coeff) > RHS. See Lemma 3.3.6 in [Molnar, M.Sc. thesis].
            bound = (scaleRHS + 1 - int(all_orbits)).floor()
            all_blift = blift(normalizedCoeffs,
                              bound,
                              p,
                              k,
                              all_orbits=all_orbits)

            # If bool is true after lifting, we have a solution b, and F/G
            # is not minimal.
            for boolval, sol in all_blift:
                if boolval:
                    #Rescale, conjugate and return new map
                    bsol = QQ(sol * (p**bval))
                    #only add 'minimal orbit element'
                    while bsol.abs() >= p**k:
                        if bsol < 0:
                            bsol += p**k
                        else:
                            bsol -= p**k
                    #"Conjugating by ", p,"^", k, "*z +", bsol
                    newconj = matrix(QQ, 2, 2, [p**k, bsol, 0, 1])
                    minFun = Fun.conjugate(newconj)

                    minFun.normalize_coordinates()
                    if not all_orbits:
                        return [minFun, conj * newconj]
                    if [p, k, bsol] not in all_found:
                        all_found.append([p, k, bsol])
        k = k + 1
    if not all_orbits:
        return [Fun, conj]
    return all_found
示例#44
0
def BCHCode(n,delta,F,b=0):
    r"""
    A 'Bose-Chaudhuri-Hockenghem code' (or BCH code for short) is the
    largest possible cyclic code of length n over field F=GF(q), whose
    generator polynomial has zeros (which contain the set)
    `Z = \{a^{b},a^{b+1}, ..., a^{b+delta-2}\}`, where a is a
    primitive `n^{th}` root of unity in the splitting field
    `GF(q^m)`, b is an integer `0\leq b\leq n-delta+1`
    and m is the multiplicative order of q modulo n. (The integers
    `b,...,b+delta-2` typically lie in the range
    `1,...,n-1`.) The integer `delta \geq 1` is called
    the "designed distance". The length n of the code and the size q of
    the base field must be relatively prime. The generator polynomial
    is equal to the least common multiple of the minimal polynomials of
    the elements of the set `Z` above.

    Special cases are b=1 (resulting codes are called 'narrow-sense'
    BCH codes), and `n=q^m-1` (known as 'primitive' BCH
    codes).

    It may happen that several values of delta give rise to the same
    BCH code. The largest one is called the Bose distance of the code.
    The true minimum distance, d, of the code is greater than or equal
    to the Bose distance, so `d\geq delta`.

    EXAMPLES::

        sage: FF.<a> = GF(3^2,"a")
        sage: x = PolynomialRing(FF,"x").gen()
        sage: L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L)
        sage: f = x^(8)-1
        sage: g.divides(f)
        True
        sage: C = codes.CyclicCode(8,g); C
        Linear code of length 8, dimension 4 over Finite Field of size 3
        sage: C.minimum_distance()
        4
        sage: C = codes.BCHCode(8,3,GF(3),1); C
        Linear code of length 8, dimension 4 over Finite Field of size 3
        sage: C.minimum_distance()
        4
        sage: C = codes.BCHCode(8,3,GF(3)); C
        Linear code of length 8, dimension 5 over Finite Field of size 3
        sage: C.minimum_distance()
        3
        sage: C = codes.BCHCode(26, 5, GF(5), b=1); C
        Linear code of length 26, dimension 10 over Finite Field of size 5

    """
    from sage.misc.misc import srange
    q = F.order()
    R = IntegerModRing(n)
    m = R(q).multiplicative_order()
    FF = GF(q**m,"z")
    z = FF.gen()
    e = z.multiplicative_order()/n
    a = z**e # order n
    P = PolynomialRing(F,"x")
    x = P.gen()
    cosets = Set([])
    for i in srange(b,b+delta-1):
        cosets = cosets.union(Set(cyclotomic_cosets(q, n, i)))
    L0 = [a**j for j in cosets]
    L1 = [P(ai.minpoly()) for ai in L0]
    g = P(LCM(L1))
    #print cosets, "\n", g, "\n", (x**n-1).factor(), "\n", L1, "\n", g.divides(x**n-1)
    if not(g.divides(x**n-1)):
        raise ValueError, "BCH codes does not exist with the given input."
    return CyclicCodeFromGeneratingPolynomial(n,g)
示例#45
0
def enumerate_totallyreal_fields_rel(F,
                                     m,
                                     B,
                                     a=[],
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.

    .. note::

        This is guaranteed to give all primitive such fields, and
        seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if
      both ``return_seqs`` and ``return_pari_objects`` are ``False`` then
      it returns the elements as Sage objects; otherwise it returns pari
      objects.

    OUTPUT:

    - the list of fields with entries ``[d,fabs,f]``, where ``d`` is the
      discriminant, ``fabs`` is an absolute defining polynomial, and ``f``
      is a defining polynomial relative to ``F``, sorted by discriminant.

    - if ``return_seqs`` is ``True``, then the first field of the list is
      a list containing the count of four items as explained below

      - the first entry gives the number of polynomials tested
      - the second entry gives the number of polynomials with its
        discriminant having a large enough square divisor
      - the third entry is the number of irreducible polynomials
      - the fourth entry is the number of irreducible polynomials with
        discriminant at most ``B``

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 1, 2000)
        [[1, [-2, 0, 1], xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)
        [[9, 6, 5, 0], [[1600, [4, 0, -6, 0, 1], [-1, 1, 1]]]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: type(enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent()
        Integer Ring
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][2].parent()
        Univariate Polynomial Ring in xF over Number Field in t with defining polynomial x^2 - 2
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)[1][0][1][0].parent()
        Rational Field

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError("cannot coerce m (= %s) to an integer" % m)
    if (m < 1):
        raise ValueError("m must be at least 1.")

    n = F.degree() * m

    # Initialize
    S = {}  # dictionary of the form {(d, fabs): f, ...}
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000 * dB_odlyzko**n)
    counts = [0, 0, 0, 0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).polrecip().Vec()
        if return_seqs:
            return [[0, 0, 0, 0], [1, [-1, 1], g]]
        elif return_pari_objects:
            return [[1, g, pari('xF-1')]]
        else:
            Px = PolynomialRing(QQ, 'xF')
            return [[ZZ(1), [QQ(_) for _ in g], Px.gen() - 1]]

    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0] * m + [1]
    T = tr_data_rel(F, m, B, a)
    if verbose == 2:
        T.incr(f_out, verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(
        str(F.defining_polynomial()).replace('x', str(F.primitive_element())))
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print("==>", f_out, end="")

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out) - 1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        #counts[0] += 1
        if d > 0 and nf.polsturm() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B * da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk, d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print("has discriminant", d, end="")

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf, zk]).polredabs()

                        # Check if K is contained in the list.
                        if (d, ng) in S:
                            if verbose:
                                print("but is not new")
                        else:
                            if verbose:
                                print("and is new!")
                            S[(d, ng)] = Fx(f_out)
                    else:
                        if verbose:
                            print("has discriminant", abs(d), "> B")
                else:
                    if verbose:
                        print("is not absolutely irreducible")
            else:
                if verbose:
                    print("has discriminant", abs(d),
                          "with no large enough square divisor")
        else:
            if verbose:
                if d == 0:
                    print("is not squarefree")
                else:
                    print("is not totally real")
        if verbose == 2:
            T.incr(f_out, verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1, 1, 1]).is_irreducible():
            K = F.extension(Fx([-1, 1, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 1, 1])
        elif F.degree() == 2:
            for ff in [[1, -7, 13, -7, 1], [1, -8, 14, -7, 1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    S[(d, ng)] = f
    elif m == 3:
        if Fx([-1, 6, -5, 1]).is_irreducible():
            K = F.extension(Fx([-1, 6, -5, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 6, -5, 1])

    # Convert S to a sorted list of triples [d, fabs, f], taking care
    # not to use the comparison operators on PARI polynomials.
    S = [[s[0], s[1], t] for s, t in S.items()]
    S.sort(key=lambda x: (x[0], [QQ(cf) for cf in x[1].polrecip().Vec()]))

    # Now check for isomorphic fields
    weed_fields(S)

    # Output.
    if verbose:
        print("=" * 80)
        print("Polynomials tested: {}".format(counts[0]))
        print("Polynomials with discriminant with large enough square"
              " divisor: {}".format(counts[1]))
        print("Irreducible polynomials: {}".format(counts[2]))
        print("Polynomials with nfdisc <= B: {}".format(counts[3]))
        for i in range(len(S)):
            print(S[i])
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(x) for x in counts],
                [[
                    s[0], [QQ(x) for x in s[1].polrecip().Vec()],
                    s[2].coefficients(sparse=False)
                ] for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[s[0], Px([QQ(_) for _ in s[1].list()]), s[2]] for s in S]
示例#46
0
class PseudoConwayLattice(WithEqualityById, SageObject):
    r"""
    A pseudo-Conway lattice over a given finite prime field.

    The Conway polynomial `f_n` of degree `n` over `\Bold{F}_p` is
    defined by the following four conditions:

    - `f_n` is irreducible.

    - In the quotient field `\Bold{F}_p[x]/(f_n)`, the element
      `x\bmod f_n` generates the multiplicative group.

    - The minimal polynomial of `(x\bmod f_n)^{\frac{p^n-1}{p^m-1}}`
      equals the Conway polynomial `f_m`, for every divisor `m` of
      `n`.

    - `f_n` is lexicographically least among all such polynomials,
      under a certain ordering.

    The final condition is needed only in order to make the Conway
    polynomial unique.  We define a pseudo-Conway lattice to be any
    family of polynomials, indexed by the positive integers,
    satisfying the first three conditions.

    INPUT:

    - ``p`` -- prime number

    - ``use_database`` -- boolean.  If ``True``, use actual Conway
      polynomials whenever they are available in the database.  If
      ``False``, always compute pseudo-Conway polynomials.

    EXAMPLES::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(2, use_database=False)
        sage: PCL.polynomial(3)
        x^3 + x + 1

    TESTS::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(3)
        sage: hash(PCL)  # random
        8738829832350

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PseudoConwayLattice(3) == PseudoConwayLattice(3)
        False
        sage: PseudoConwayLattice(3) != PseudoConwayLattice(3)
        True
        sage: P = PseudoConwayLattice(5)
        sage: P == P
        True
        sage: P != P
        False
    """
    def __init__(self, p, use_database=True):
        """
        TESTS::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(3)
            sage: PCL.polynomial(3)
            x^3 + 2*x + 1

            sage: PCL = PseudoConwayLattice(5, use_database=False)
            sage: PCL.polynomial(12)
            x^12 + 4*x^11 + 2*x^10 + 4*x^9 + 2*x^8 + 2*x^7 + 4*x^6 + x^5 + 2*x^4 + 2*x^2 + x + 2
            sage: PCL.polynomial(6)
            x^6 + x^5 + 4*x^4 + 3*x^3 + 3*x^2 + 2*x + 2
            sage: PCL.polynomial(11)
            x^11 + x^6 + 3*x^3 + 4*x + 3
        """
        self.p = p
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        self.ring = PolynomialRing(FiniteField(p), 'x')
        if use_database:
            C = sage.databases.conway.ConwayPolynomials()
            self.nodes = {n: self.ring(C.polynomial(p, n))
                          for n in C.degrees(p)}
        else:
            self.nodes = {}

    def polynomial(self, n):
        r"""
        Return the pseudo-Conway polynomial of degree `n` in this
        lattice.

        INPUT:

        - ``n`` -- positive integer

        OUTPUT:

        - a pseudo-Conway polynomial of degree `n` for the prime `p`.

        ALGORITHM:

        Uses an algorithm described in [HL99]_, modified to find
        pseudo-Conway polynomials rather than Conway polynomials.  The
        major difference is that we stop as soon as we find a
        primitive polynomial.

        REFERENCE:

        .. [HL99] \L. Heath and N. Loehr (1999).  New algorithms for
           generating Conway polynomials over finite fields.
           Proceedings of the tenth annual ACM-SIAM symposium on
           discrete algorithms, pp. 429-437.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.polynomial(3)
            x^3 + x + 1
            sage: PCL.polynomial(4)
            x^4 + x^3 + 1
            sage: PCL.polynomial(60)
            x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1
        """
        if n in self.nodes:
            return self.nodes[n]

        p = self.p
        n = Integer(n)

        if n == 1:
            f = self.ring.gen() - FiniteField(p).multiplicative_generator()
            self.nodes[1] = f
            return f

        # Work in an arbitrary field K of order p**n.
        K = FiniteField(p**n, names='a')

        # TODO: something like the following
        # gcds = [n.gcd(d) for d in self.nodes.keys()]
        # xi = { m: (...) for m in gcds }
        xi = {q: self.polynomial(n//q).any_root(K, -n//q, assume_squarefree=True)
              for q in n.prime_divisors()}

        # The following is needed to ensure that in the concrete instantiation
        # of the "new" extension all previous choices are compatible.
        _frobenius_shift(K, xi)

        # Construct a compatible element having order the lcm of orders
        q, x = xi.popitem()
        v = p**(n//q) - 1
        for q, xitem in six.iteritems(xi):
            w = p**(n//q) - 1
            g, alpha, beta = v.xgcd(w)
            x = x**beta * xitem**alpha
            v = v.lcm(w)

        r = p**n - 1
        # Get the missing part of the order to be primitive
        g = r // v
        # Iterate through g-th roots of x until a primitive one is found
        z = x.nth_root(g)
        root = K.multiplicative_generator()**v
        while z.multiplicative_order() != r:
            z *= root
        # The following should work but tries to create a huge list
        # whose length overflows Python's ints for large parameters
        #Z = x.nth_root(g, all=True)
        #for z in Z:
        #    if z.multiplicative_order() == r:
        #         break
        f = z.minimal_polynomial()
        self.nodes[n] = f
        return f

    def check_consistency(self, n):
        """
        Check that the pseudo-Conway polynomials of degree dividing
        `n` in this lattice satisfy the required compatibility
        conditions.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.check_consistency(6)
            sage: PCL.check_consistency(60)  # long time
        """
        p = self.p
        K = FiniteField(p**n, modulus = self.polynomial(n), names='a')
        a = K.gen()
        for m in n.divisors():
            assert (a**((p**n-1)//(p**m-1))).minimal_polynomial() == self.polynomial(m)
示例#47
0
def epsinv(F, target, prec=53, target_tol=0.001, z=None, emb=None):
    """
    Compute a bound on the hyperbolic distance.

    The true minimum will be within the computed bound.
    It is computed as the inverse of epsilon_F from [HS2018]_.
    
    INPUT:

    - ``F`` -- binary form of degree at least 3 with no multiple roots

    - ``target`` --  positive real number. The value we want to attain, i.e.,
      the value we are taking the inverse of

    - ``prec``-- positive integer. precision to use in CC

    - ``target_tol`` -- positive real number. The tolerance with which we
      attain the target value.

    - ``z`` -- complex number. ``z_0`` covariant for F.

    - ``emb`` -- embedding into CC

    OUTPUT: a real number delta satisfying  target + target_tol > eps_F(delta) > target.

    EXAMPLES::

        sage: from sage.rings.polynomial.binary_form_reduce import epsinv
        sage: R.<x,y> = QQ[]
        sage: epsinv(-2*x^3 + 2*x^2*y + 3*x*y^2 + 127*y^3, 31.5022020249597) # tol 1e-12
        4.02520895942207       
    """
    def coshdelta(z):
        #The cosh of the hyperbolic distance from z = t+uj to j
        return (z.norm() + 1) / (2 * z.imag())

    def RQ(delta):
        # this is the quotient R(F_0,z)/R(F_0,z(F)) for a generic z
        # at distance delta from j. See Lemma 4.2 in [HS2018].
        cd = cosh(delta).n(prec=prec)
        sd = sinh(delta).n(prec=prec)
        return prod(
            [cd + (cost * phi[0] + sint * phi[1]) * sd for phi in phis])

    def epsF(delta):
        pol = RQ(delta)  #get R quotient in terms of z
        S = PolynomialRing(C, 'v')
        g = S([(i - d) * pol[i - d]
               for i in range(2 * d + 1)])  # take derivative
        drts = [
            e for e in g.roots(ring=C, multiplicities=False)
            if (e.norm() - 1).abs() < 0.1
        ]
        # find min
        return min([pol(r / r.abs()).real() for r in drts])

    C = ComplexField(prec=prec)
    R = F.parent()
    d = F.degree()
    if z is None:
        z, th = covariant_z0(F, prec=prec, emb=emb)
    else:  #need to do our own input checking
        if R.ngens() != 2 or any(sum(t) != d for t in F.exponents()):
            raise TypeError('must be a binary form')
        if d < 3:
            raise ValueError('must be at least degree 3')

    f = F.subs({R.gen(1): 1}).univariate_polynomial()
    #now we have a single variable polynomial
    if (max([ex for p,ex in f.roots(ring=C)]) >= QQ(d)/2)\
      or (f.degree() < QQ(d)/2):
        raise ValueError('cannot have root with multiplicity >= deg(F)/2')

    R = RealField(prec=prec)
    PR = PolynomialRing(R, 't')
    t = PR.gen(0)
    # compute phi_1, ..., phi_k
    # first find F_0 and its roots
    # this change of variables on f moves z(f) to j, i.e. produces F_0
    rts = f(z.imag() * t + z.real()).roots(ring=C)
    phis = []  # stereographic projection of roots
    for r, e in rts:
        phis.extend(
            [[2 * r.real() / (r.norm() + 1), (r.norm() - 1) / (r.norm() + 1)]])
    if d != f.degree():  # include roots at infinity
        phis.extend([(d - f.degree()) * [0, 1]])

    # for writing RQ in terms of generic z to minimize
    LC = LaurentSeriesRing(C, 'u', default_prec=2 * d + 2)
    u = LC.gen(0)
    cost = (u + u**(-1)) / 2
    sint = (u - u**(-1)) / (2 * C.gen(0))

    # first find an interval containing the desired value
    # then use regula falsi on log eps_F
    # d -> delta value in interval [0,1]
    # v in value in interval [1,epsF(1)]
    dl = R(0.0)
    vl = R(1.0)
    du = R(1.0)
    vu = epsF(du)
    while vu < target:
        # compute the next value of epsF for delta = 2*delta
        dl = du
        vl = vu
        du *= 2
        vu = epsF(du)
    # now dl < delta <= du
    logt = target.log()
    l2 = (vu.log() - logt).n(prec=prec)
    l1 = (vl.log() - logt).n(prec=prec)
    dn = (dl * l2 - du * l1) / (l2 - l1)
    vn = epsF(dn)
    dl = du
    vl = vu
    du = dn
    vu = vn
    while (du - dl).abs() >= target_tol or max(vl, vu) < target:
        l2 = (vu.log() - logt).n(prec=prec)
        l1 = (vl.log() - logt).n(prec=prec)
        dn = (dl * l2 - du * l1) / (l2 - l1)
        vn = epsF(dn)
        dl = du
        vl = vu
        du = dn
        vu = vn
    return max(dl, du)
示例#48
0
def permanental_minor_polynomial(A, permanent_only=False, var='t', prec=None):
    r"""
    Return the polynomial of the sums of permanental minors of ``A``.

    INPUT:

    - `A` -- a matrix

    - `permanent_only` -- if True, return only the permanent of `A`

    - `var` -- name of the polynomial variable

    - `prec` -- if prec is not None, truncate the polynomial at precision `prec`


    The polynomial of the sums of permanental minors is

    .. MATH::

        \sum_{i=0}^{min(nrows, ncols)} p_i(A) x^i

    where `p_i(A)` is the `i`-th permanental minor of `A` (that can also be
    obtained through the method
    :meth:`~sage.matrix.matrix2.Matrix.permanental_minor` via
    ``A.permanental_minor(i)``).

    The algorithm implemented by that function has been developed by P. Butera
    and M. Pernici, see [ButPer]. Its complexity is `O(2^n m^2 n)` where `m` and
    `n` are the number of rows and columns of `A`.  Moreover, if `A` is a banded
    matrix with width `w`, that is `A_{ij}=0` for `|i - j| > w` and `w < n/2`,
    then the complexity of the algorithm is `O(4^w (w+1) n^2)`.

    INPUT:

    - ``A`` -- matrix

    - ``permanent_only`` -- optional boolean. If ``True``, only the permanent
      is computed (might be faster).

    - ``var`` -- a variable name

    EXAMPLES::

        sage: from sage.matrix.matrix_misc import permanental_minor_polynomial
        sage: m = matrix([[1,1],[1,2]])
        sage: permanental_minor_polynomial(m)
        3*t^2 + 5*t + 1
        sage: permanental_minor_polynomial(m, permanent_only=True)
        3
        sage: permanental_minor_polynomial(m, prec=2)
        5*t + 1

    ::

        sage: M = MatrixSpace(ZZ,4,4)
        sage: A = M([1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1])
        sage: permanental_minor_polynomial(A)
        84*t^3 + 114*t^2 + 28*t + 1
        sage: [A.permanental_minor(i) for i in range(5)]
        [1, 28, 114, 84, 0]

    An example over `\QQ`::

        sage: M = MatrixSpace(QQ,2,2)
        sage: A = M([1/5,2/7,3/2,4/5])
        sage: permanental_minor_polynomial(A, True)
        103/175

    An example with polynomial coefficients::

        sage: R.<a> = PolynomialRing(ZZ)
        sage: A = MatrixSpace(R,2)([[a,1], [a,a+1]])
        sage: permanental_minor_polynomial(A, True)
        a^2 + 2*a

    A usage of the ``var`` argument::

        sage: m = matrix(ZZ,4,[0,1,2,3,1,2,3,0,2,3,0,1,3,0,1,2])
        sage: permanental_minor_polynomial(m, var='x')
        164*x^4 + 384*x^3 + 172*x^2 + 24*x + 1

    ALGORITHM:

        The permanent `perm(A)` of a `n \times n` matrix `A` is the coefficient
        of the `x_1 x_2 \ldots x_n` monomial in

        .. MATH::

            \prod_{i=1}^n \left( \sum_{j=1}^n A_{ij} x_j \right)

        Evaluating this product one can neglect `x_i^2`, that is `x_i`
        can be considered to be nilpotent of order `2`.

        To formalize this procedure, consider the algebra
        `R = K[\eta_1, \eta_2, \ldots, \eta_n]` where the `\eta_i` are
        commuting, nilpotent of order `2` (i.e. `\eta_i^2 = 0`).
        Formally it is the quotient ring of the polynomial
        ring in `\eta_1, \eta_2, \ldots, \eta_n` quotiented by the ideal
        generated by the `\eta_i^2`.

        We will mostly consider the ring `R[t]` of polynomials over `R`. We
        denote a generic element of `R[t]` by `p(\eta_1, \ldots, \eta_n)` or
        `p(\eta_{i_1}, \ldots, \eta_{i_k})` if we want to emphasize that some
        monomials in the `\eta_i` are missing.

        Introduce an "integration" operation `\langle p \rangle` over `R` and
        `R[t]` consisting in the sum of the coefficients of the non-vanishing
        monomials in `\eta_i` (i.e. the result of setting all variables `\eta_i`
        to `1`). Let us emphasize that this is *not* a morphism of algebras as
        `\langle \eta_1 \rangle^2 = 1` while `\langle \eta_1^2 \rangle = 0`!

        Let us consider an example of computation.
        Let `p_1 = 1 + t \eta_1 + t \eta_2` and
        `p_2 = 1 + t \eta_1 + t \eta_3`. Then

        .. MATH::

            p_1 p_2 = 1 + 2t \eta_1 +
                    t (\eta_2 + \eta_3) +
                    t^2 (\eta_1 \eta_2 + \eta_1 \eta_3 + \eta_2 \eta_3)

        and

        .. MATH::

            \langle p_1 p_2 \rangle = 1 + 4t + 3t^2

        In this formalism, the permanent is just

        .. MATH::

            perm(A) = \langle \prod_{i=1}^n \sum_{j=1}^n A_{ij} \eta_j \rangle

        A useful property of `\langle . \rangle` which makes this algorithm
        efficient for band matrices is the following: let
        `p_1(\eta_1, \ldots, \eta_n)` and `p_2(\eta_j, \ldots, \eta_n)` be
        polynomials in `R[t]` where `j \ge 1`.  Then one has

        .. MATH::

            \langle p_1(\eta_1, \ldots, \eta_n) p_2 \rangle =
            \langle p_1(1, \ldots, 1, \eta_j, \ldots, \eta_n) p_2 \rangle

        where `\eta_1,..,\eta_{j-1}` are replaced by `1` in `p_1`. Informally,
        we can "integrate" these variables *before* performing the product. More
        generally, if a monomial `\eta_i` is missing in one of the terms of a
        product of two terms, then it can be integrated in the other term.

        Now let us consider an `m \times n` matrix with `m \leq n`. The *sum of
        permanental `k`-minors of `A`* is

        .. MATH::

            perm(A, k) = \sum_{r,c} perm(A_{r,c})

        where the sum is over the `k`-subsets `r` of rows and `k`-subsets `c` of
        columns and `A_{r,c}` is the submatrix obtained from `A` by keeping only
        the rows `r` and columns `c`. Of course
        `perm(A, \min(m,n)) = perm(A)` and note that `perm(A,1)` is just the sum
        of all entries of the matrix.

        The generating function of these sums of permanental minors is

        .. MATH::

            g(t) = \left\langle
            \prod_{i=1}^m \left(1 + t \sum_{j=1}^n A_{ij} \eta_j\right)
            \right\rangle

        In fact the `t^k` coefficient of `g(t)` corresponds to choosing
        `k` rows of `A`;  `\eta_i` is associated to the i-th column;
        nilpotency avoids having twice the same column in a product of `A`'s.

        For more details, see the article [ButPer].

        From a technical point of view, the product in
        `K[\eta_1, \ldots, \eta_n][t]` is implemented as a subroutine in
        :func:`prm_mul`. The indices of the rows and columns actually start at
        `0`, so the variables are  `\eta_0, \ldots, \eta_{n-1}`. Polynomials are
        represented in dictionary form: to a variable `\eta_i` is associated
        the key `2^i` (or in Python ``1 << i``). The keys associated to products
        are obtained by considering the development in base `2`: to the monomial
        `\eta_{i_1} \ldots \eta_{i_k}` is associated the key
        `2^{i_1} + \ldots + 2^{i_k}`. So the product `\eta_1 \eta_2` corresponds
        to the key `6 = (110)_2` while `\eta_0 \eta_3` has key `9 = (1001)_2`.
        In particular all operations on monomials are implemented via bitwise
        operations on the keys.

    REFERENCES:

    .. [ButPer] \P. Butera and M. Pernici "Sums of permanental minors
       using Grassmann algebra", :arxiv:`1406.5337`
    """
    if permanent_only:
        prec = None
    elif prec is not None:
        prec = int(prec)
        if prec == 0:
            raise ValueError('the argument `prec` must be a positive integer')

    K = PolynomialRing(A.base_ring(), var)
    nrows = A.nrows()
    ncols = A.ncols()
    A = A.rows()
    p = {0: K.one()}
    t = K.gen()
    vars_to_do = range(ncols)
    for i in range(nrows):
        # build the polynomial p1 = 1 + t sum A_{ij} eta_j
        if permanent_only:
            p1 = {}
        else:
            p1 = {0: K.one()}
        a = A[i]  # the i-th row of A
        for j in range(len(a)):
            if a[j]:
                p1[1 << j] = a[j] * t

        # make the product with the preceding polynomials, taking care of
        # variables that can be integrated
        mask_free = 0
        j = 0
        while j < len(vars_to_do):
            jj = vars_to_do[j]
            if all(A[k][jj] == 0 for k in range(i + 1, nrows)):
                mask_free += 1 << jj
                vars_to_do.remove(jj)
            else:
                j += 1
        p = prm_mul(p, p1, mask_free, prec)

    if not p:
        return K.zero()

    if len(p) != 1 or 0 not in p:
        raise RuntimeError(
            "Something is wrong! Certainly a problem in the"
            " algorithm... please contact [email protected]")

    p = p[0]
    return p[min(nrows, ncols)] if permanent_only else p
示例#49
0
def BCHCode(n,delta,F,b=0):
    r"""
    A 'Bose-Chaudhuri-Hockenghem code' (or BCH code for short) is the
    largest possible cyclic code of length n over field F=GF(q), whose
    generator polynomial has zeros (which contain the set)
    `Z = \{a^{b},a^{b+1}, ..., a^{b+delta-2}\}`, where a is a
    primitive `n^{th}` root of unity in the splitting field
    `GF(q^m)`, b is an integer `0\leq b\leq n-delta+1`
    and m is the multiplicative order of q modulo n. (The integers
    `b,...,b+delta-2` typically lie in the range
    `1,...,n-1`.) The integer `delta \geq 1` is called
    the "designed distance". The length n of the code and the size q of
    the base field must be relatively prime. The generator polynomial
    is equal to the least common multiple of the minimal polynomials of
    the elements of the set `Z` above.

    Special cases are b=1 (resulting codes are called 'narrow-sense'
    BCH codes), and `n=q^m-1` (known as 'primitive' BCH
    codes).

    It may happen that several values of delta give rise to the same
    BCH code. The largest one is called the Bose distance of the code.
    The true minimum distance, d, of the code is greater than or equal
    to the Bose distance, so `d\geq delta`.

    EXAMPLES::

        sage: FF.<a> = GF(3^2,"a")
        sage: x = PolynomialRing(FF,"x").gen()
        sage: L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L)
        sage: f = x^(8)-1
        sage: g.divides(f)
        True
        sage: C = codes.CyclicCode(8,g); C
        Linear code of length 8, dimension 4 over Finite Field of size 3
        sage: C.minimum_distance()
        4
        sage: C = codes.BCHCode(8,3,GF(3),1); C
        Linear code of length 8, dimension 4 over Finite Field of size 3
        sage: C.minimum_distance()
        4
        sage: C = codes.BCHCode(8,3,GF(3)); C
        Linear code of length 8, dimension 5 over Finite Field of size 3
        sage: C.minimum_distance()
        3
        sage: C = codes.BCHCode(26, 5, GF(5), b=1); C
        Linear code of length 26, dimension 10 over Finite Field of size 5

    """
    q = F.order()
    R = IntegerModRing(n)
    m = R(q).multiplicative_order()
    FF = GF(q**m,"z")
    z = FF.gen()
    e = z.multiplicative_order()/n
    a = z**e # order n
    P = PolynomialRing(F,"x")
    x = P.gen()
    L1 = []
    for coset in R.cyclotomic_cosets(q, range(b,b+delta-1)):
        L1.extend(P((a**j).minpoly()) for j in coset)
    g = P(LCM(L1))
    #print cosets, "\n", g, "\n", (x**n-1).factor(), "\n", L1, "\n", g.divides(x**n-1)
    if not(g.divides(x**n-1)):
        raise ValueError("BCH codes does not exist with the given input.")
    return CyclicCodeFromGeneratingPolynomial(n,g)
示例#50
0
def enumerate_totallyreal_fields_rel(F, m, B, a = [], verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.

    .. note::

        This is guaranteed to give all primitive such fields, and
        seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if
      both ``return_seqs`` and ``return_pari_objects`` are ``False`` then
      it returns the elements as Sage objects; otherwise it returns pari
      objects.

    OUTPUT:

    - the list of fields with entries ``[d,fabs,f]``, where ``d`` is the
      discriminant, ``fabs`` is an absolute defining polynomial, and ``f``
      is a defining polynomial relative to ``F``, sorted by discriminant.

    - if ``return_seqs`` is ``True``, then the first field of the list is
      a list containing the count of four items as explained below

      - the first entry gives the number of polynomials tested
      - the second entry gives the number of polynomials with its
        discriminant having a large enough square divisor
      - the third entry is the number of irreducible polynomials
      - the fourth entry is the number of irreducible polynomials with
        discriminant at most ``B``

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 1, 2000)
        [[1, [-2, 0, 1], xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)
        [[9, 6, 5, 0], [[1600, [4, 0, -6, 0, 1], [-1, 1, 1]]]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1].parent()
        Interface to the PARI C library
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent()
        Integer Ring
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][2].parent()
        Univariate Polynomial Ring in xF over Number Field in t with defining polynomial x^2 - 2
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)[1][0][1][0].parent()
        Rational Field

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError("cannot coerce m (= %s) to an integer" % m)
    if (m < 1):
        raise ValueError("m must be at least 1.")

    n = F.degree()*m

    # Initialize
    S = {}        # dictionary of the form {(d, fabs): f, ...}
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000*dB_odlyzko**n)
    counts = [0,0,0,0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).polrecip().Vec()
        if return_seqs:
            return [[0,0,0,0], [1, [-1, 1], g]]
        elif return_pari_objects:
            return [[1, g, pari('xF-1')]]
        else:
            Px = PolynomialRing(QQ, 'xF')
            return [[ZZ(1), [QQ(_) for _ in g], Px.gen()-1]]

    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0]*m + [1]
    T = tr_data_rel(F,m,B,a)
    if verbose == 2:
        T.incr(f_out,verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(str(F.defining_polynomial()).replace('x', str(F.primitive_element()) ) )
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print "==>", f_out,

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out)-1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        #counts[0] += 1
        if d > 0 and nf.polsturm() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B*da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk,d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print "has discriminant", d,

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf,zk]).polredabs()

                        # Check if K is contained in the list.
                        if (d, ng) in S:
                            if verbose:
                                print "but is not new"
                        else:
                            if verbose:
                                print "and is new!"
                            S[(d, ng)] = Fx(f_out)
                    else:
                        if verbose:
                            print "has discriminant", abs(d), "> B"
                else:
                    if verbose:
                        print "is not absolutely irreducible"
            else:
                if verbose:
                    print "has discriminant", abs(d), "with no large enough square divisor"
        else:
            if verbose:
                if d == 0:
                    print "is not squarefree"
                else:
                    print "is not totally real"
        if verbose == 2:
            T.incr(f_out,verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1,1,1]).is_irreducible():
            K = F.extension(Fx([-1,1,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1,1,1])
        elif F.degree() == 2:
            for ff in [[1,-7,13,-7,1],[1,-8,14,-7,1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    S[(d, ng)] = f
    elif m == 3:
        if Fx([-1,6,-5,1]).is_irreducible():
            K = F.extension(Fx([-1,6,-5,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1,6,-5,1])

    # Convert S to a sorted list of triples [d, fabs, f], taking care
    # to use cmp() and not the comparison operators on PARI polynomials.
    S = [[s[0], s[1], t] for s, t in S.items()]
    S.sort(cmp=lambda x, y: cmp(x[0], y[0]) or cmp(x[1], y[1]))

    # Now check for isomorphic fields
    weed_fields(S)

    # Output.
    if verbose:
        print "="*80
        print "Polynomials tested: {}".format(counts[0])
        print ( "Polynomials with discriminant with large enough square"
                " divisor: {}".format(counts[1]))
        print "Irreducible polynomials: {}".format(counts[2])
        print "Polynomials with nfdisc <= B: {}".format(counts[3])
        for i in range(len(S)):
            print S[i]
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(x) for x in counts],
                [[s[0], [QQ(x) for x in s[1].polrecip().Vec()], s[2].coefficients(sparse=False)]
                 for s in S]
               ]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[s[0], Px([QQ(_) for _ in s[1].list()]), s[2]] for s in S]
示例#51
0
    def coleman(self,t1,t2,poly = None, E = None,method = 'moments',mult = False,level = 0, branch = 0):
        r"""
        If ``self`` is a `p`-adic automorphic form that corresponds to a rigid modular form,
        then this computes the coleman integral of this form between two points on
        the boundary `\PP^1(\QQ_p)` of the `p`-adic upper half plane.

        INPUT:

        - ``t1``, ``t2`` - elements of `\PP^1(\QQ_p)` (the endpoints of integration)

        - ``E`` - (Default: None). If specified, will not compute the covering adapted
           to ``t1`` and ``t2`` and instead use the given one. In that case, ``E``
           should be a list of matrices corresponding to edges describing the open
           balls to be considered.

        - ``method`` - string (Default: 'moments'). Tells which algorithm to use
          (alternative is 'riemann_sum', which is unsuitable for computations
          requiring high precision)

        - ``mult`` - boolean (Default: False). Whether to use the multiplicative version.

        - ``poly`` - polynomial (Default: None)

        - ``level`` - integer (Default: 0)

        OUTPUT:

          The result of the coleman integral

        EXAMPLES::

            sage: p = 7
            sage: lev = 2
            sage: prec = 20
            sage: X = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(X,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = 3*M.decomposition()[0].gen(0) # optional - magma
            sage: MM = pAutomorphicForms(X,k,prec,overconvergent = True) # optional - magma
            sage: D = -11 # optional - magma
            sage: X.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = X.get_CM_points(D,prec = prec) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J0 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve([1,0,1,4,-6]) # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J0,prec) # long time optional -magma
            sage: P = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); P # long time optional - magma
            (7/11 : 58/121*a - 9/11 : 1)

            sage: p = 13 # optional - magma
            sage: lev = 2 # optional - magma
            sage: prec = 20 # optional - magma
            sage: Y = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(Y,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = M.decomposition()[1].gen(0) # optional - magma
            sage: g = M.decomposition()[0].gen(0) # optional - magma
            sage: MM = pAutomorphicForms(Y,k,prec,overconvergent = True) # optional - magma
            sage: D = -11 # optional - magma
            sage: Y.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = Y.get_CM_points(D,prec = prec) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J11 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve('26a2') # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J11,prec) # long time optional - magma
            sage: HP = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); HP # long time optional - magma
            (-137/11 : 2/121*a + 63/11 : 1)

        AUTHORS:

        - Cameron Franc (2012-02-20)
        - Marc Masdeu (2012-02-20)
        """
        p = self.parent().prime()
        K = t1.parent()
        if mult:
            branch = 0

        R = PolynomialRing(K,'x')
        x = R.gen()
        R1 = LaurentSeriesRing(K,'r1')
        r1 = R1.gen()
        if E is None:
            E = self.parent()._source._BT.find_covering(t1,t2,level)
            print 'Got %s open balls.'%len(E)
        value = K(0)
        ii = 0
        value_exp = K(1)
        wt = self.parent()._U.weight()
        dim = self.parent()._U.dimension()
        if(method == 'riemann_sum'):
            R1.set_default_prec(wt+1)
            for e in E:
                ii += 1
                b = e[0,1]
                d = e[1,1]
                y = (b-d*t1)/(b-d*t2)
                pol = R1(y.log(branch = branch))
                c_e = self.evaluate(e)
                new = c_e.evaluate(pol)
                value += new
                if mult:
                    value_exp  *=  K.teichmuller(y)**Integer(c_e[0].rational_reconstruction())

        elif method == 'moments':
            R1.set_default_prec(dim)
            for e in E:
                ii += 1
                f = (x-t1)/(x-t2)
                a,b,c,d = e.list()
                y0 = f((a*r1+b)/(c*r1+d))
                pol = y0(0).log(branch = branch)+((y0.derivative()/y0).integral())
                if poly is not None:
                    pol *= poly(r1) #((r1-t1)**delta*(r1-t2)**(self.parent()._n-delta))
                c_e = self.evaluate(e)
                new = c_e.evaluate(pol)
                value += new
                if mult:
                    base = ((b-d*t1)/(b-d*t2))
                    pwr = ZZ(c_e[0].rational_reconstruction())
                    value_exp  *=  base**pwr
        else:
            print 'The available methods are either "moments" or "riemann_sum". The latter is only provided for consistency check, and should not be used in practice.'
            return False
        if mult:
            a = value_exp.valuation(p)
            print 'a=',a
            return p**a*K.teichmuller(p**(-a)*value_exp) * value.exp(prec = 2*dim) +O(p**(dim+a))
        return value +O(p**(dim+value.valuation(p)))
示例#52
0
    def coleman(self,t1,t2,E=None,method='moments',mult=False,delta=-1,level=0):
        r"""
        If ``self`` is a `p`-adic automorphic form that corresponds to a rigid modular form,
        then this computes the coleman integral of this form between two points on
        the boundary `\PP^1(\QQ_p)` of the `p`-adic upper half plane.

        INPUT:

         - ``t1``, ``t2`` - elements of `\PP^1(\QQ_p)` (the endpoints of integration)

         - ``E`` - (Default: None). If specified, will not compute the covering adapted
            to ``t1`` and ``t2`` and instead use the given one. In that case, ``E``
            should be a list of matrices corresponding to edges describing the open
            balls to be considered.

         - ``method`` - string (Default: 'moments'). Tells which algorithm to use 
           (alternative is 'riemann_sum', which is unsuitable for computations 
           requiring high precision)

         - ``mult`` - boolean (Default: False). Whether to use the multiplicative version.

         - ``delta`` - integer (Default: -1)

         - ``level`` - integer (Default: 0)

        OUTPUT:

          The result of the coleman integral

        EXAMPLES:

        This example illustrates ...

        ::

        TESTS:

        ::
            sage: p = 7
            sage: lev = 2
            sage: prec = 20
            sage: X = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(X,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = 3*B[0] # optional - magma
            sage: MM = pAutomorphicForms(X,k,prec,overconvergent=True) # optional - magma
            sage: D = -11 # optional - magma
            sage: X.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = X.get_CM_points(D,prec=prec) # optional - magma
            sage: Kp = CM[0].parent() # optional - magma
            sage: P=CM[0] # optional - magma
            sage: Q=P.trace()-P # optional - magma
            sage: F=MM.lift(f, verbose = False) # long time optional - magma
            sage: J0=F.coleman(P,Q,mult=True) # long time optional - magma
            sage: E=EllipticCurve([1,0,1,4,-6]) # optional - magma
            sage: T=E.tate_curve(p) # optional - magma
            sage: xx,yy=getcoords(T,J0,prec) # long time optional -magma
            sage: P = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); P # long time optional - magma
            (7/11 : 58/121*a - 9/11 : 1)

            sage: p = 13 # optional - magma
            sage: lev = 2 # optional - magma
            sage: prec = 20 # optional - magma
            sage: Y = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M=HarmonicCocycles(Y,k,prec) # optional - magma
            sage: B=M.basis() # optional - magma

            sage: f = B[1] # optional - magma
            sage: g = -4*B[0]+3*B[1] # optional - magma
            sage: MM = pAutomorphicForms(Y,k,prec,overconvergent=True) # optional - magma
            sage: D = -11 # optional - magma
            sage: Y.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = Y.get_CM_points(D,prec=prec) # optional - magma
            sage: Kp = parent(CM[0]) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J11 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve('26a2') # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J11,prec) # long time optional - magma
            sage: HP = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); HP # long time optional - magma
            (-137/11 : 2/121*a + 63/11 : 1)

        AUTHORS:

        - Cameron Franc (2012-02-20)
        - Marc Masdeu (2012-02-20)
        """
        if(mult and delta>=0):
            raise NotImplementedError, "Need to figure out how to implement the multiplicative part."
        p=self._parent._X._p
        K=t1.parent()
        R=PolynomialRing(K,'x')
        x=R.gen()
        R1=LaurentSeriesRing(K,'r1')
        r1=R1.gen()
        if(E is None):
            E=self._parent._X._BT.find_covering(t1,t2)
            # print 'Got %s open balls.'%len(E)
        value=0
        ii=0
        value_exp=K(1)
        if(method=='riemann_sum'):
            R1.set_default_prec(self._parent._U.weight()+1)
            for e in E:
                ii+=1
                b=e[0,1]
                d=e[1,1]
                y=(b-d*t1)/(b-d*t2)
                poly=R1(y.log()) #R1(our_log(y))
                c_e=self.evaluate(e)
                new=c_e.evaluate(poly)
                value+=new
                if mult:
                    value_exp *= K.teichmuller(y)**Integer(c_e[0].rational_reconstruction())

        elif(method=='moments'):
            R1.set_default_prec(self._parent._U.dimension())
            for e in E:
                ii+=1
                f=(x-t1)/(x-t2)
                a,b,c,d=e.list()
                y0=f(R1([b,a])/R1([d,c])) #f( (ax+b)/(cx+d) )
                y0=p**(-y0(0).valuation())*y0
                mu=K.teichmuller(y0(0))
                y=y0/mu-1
                poly=R1(0)
                ypow=y
                for jj in range(1,R1.default_prec()+10):
                    poly+=(-1)**(jj+1)*ypow/jj
                    ypow*=y
                if(delta>=0):
                    poly*=((r1-t1)**delta*(r1-t2)**(self._parent._n-delta))
                c_e=self.evaluate(e)
                new=c_e.evaluate(poly)
                value+=new
                if mult:
                    value_exp *= K.teichmuller((b-d*t1)/(b-d*t2))**Integer(c_e[0].rational_reconstruction())

        else:
            print 'The available methods are either "moments" or "riemann_sum". The latter is only provided for consistency check, and should not be used in practice.'
            return False
        if mult:
            return value_exp * value.exp()
        return value
示例#53
0
    def segre_embedding(self, PP=None):
        r"""
        Return the Segre embedding of this subscheme into the appropriate projective
        space.

        INPUT:

        - ``PP`` -- (default: ``None``) ambient image projective space;
          this is constructed if it is not given.

        OUTPUT:

        Hom from this subscheme to the appropriate subscheme of projective space

        EXAMPLES::

            sage: X.<x,y,z,w,u,v> = ProductProjectiveSpaces([2,2], QQ)
            sage: P = ProjectiveSpace(QQ,8,'t')
            sage: L = (-w - v)*x + (-w*y - u*z)
            sage: Q = (-u*w - v^2)*x^2 + ((-w^2 - u*w + (-u*v - u^2))*y + (-w^2 - u*v)*z)*x + \
            ((-w^2 - u*w - u^2)*y^2 + (-u*w - v^2)*z*y + (-w^2 + (-v - u)*w)*z^2)
            sage: W = X.subscheme([L,Q])
            sage: phi = W.segre_embedding(P)
            sage: phi.codomain().ambient_space() == P
            True

        ::

            sage: PP.<x,y,u,v,s,t> = ProductProjectiveSpaces([1,1,1], CC)
            sage: PP.subscheme([]).segre_embedding()
            Scheme morphism:
              From: Closed subscheme of Product of projective spaces P^1 x P^1 x P^1
            over Complex Field with 53 bits of precision defined by:
              (no polynomials)
              To:   Closed subscheme of Projective Space of dimension 7 over Complex
            Field with 53 bits of precision defined by:
              -u5*u6 + u4*u7,
              -u3*u6 + u2*u7,
              -u3*u4 + u2*u5,
              -u3*u5 + u1*u7,
              -u3*u4 + u1*u6,
              -u3*u4 + u0*u7,
              -u2*u4 + u0*u6,
              -u1*u4 + u0*u5,
              -u1*u2 + u0*u3
              Defn: Defined by sending (x : y , u : v , s : t) to
                    (x*u*s : x*u*t : x*v*s : x*v*t : y*u*s : y*u*t : y*v*s : y*v*t).

        ::

            sage: PP.<x,y,z,u,v,s,t> = ProductProjectiveSpaces([2,1,1], ZZ)
            sage: PP.subscheme([x^3, u-v, s^2-t^2]).segre_embedding()
            Scheme morphism:
              From: Closed subscheme of Product of projective spaces P^2 x P^1 x P^1
            over Integer Ring defined by:
              x^3,
              u - v,
              s^2 - t^2
              To:   Closed subscheme of Projective Space of dimension 11 over
            Integer Ring defined by:
              u10^2 - u11^2,
              u9 - u11,
              u8 - u10,
              -u7*u10 + u6*u11,
              u6*u10 - u7*u11,
              u6^2 - u7^2,
              u5 - u7,
              u4 - u6,
              u3^3,
              -u3*u10 + u2*u11,
              u2*u10 - u3*u11,
              -u3*u6 + u2*u7,
              u2*u6 - u3*u7,
              u2*u3^2,
              u2^2 - u3^2,
              u1 - u3,
              u0 - u2
              Defn: Defined by sending (x : y : z , u : v , s : t) to
                    (x*u*s : x*u*t : x*v*s : x*v*t : y*u*s : y*u*t : y*v*s : y*v*t :
            z*u*s : z*u*t : z*v*s : z*v*t).
        """
        AS = self.ambient_space()
        CR = AS.coordinate_ring()
        N = AS.dimension_relative_components()
        M = prod([n + 1 for n in N]) - 1

        vars = list(AS.coordinate_ring().variable_names()) + [
            'u' + str(i) for i in range(M + 1)
        ]
        R = PolynomialRing(AS.base_ring(),
                           AS.ngens() + M + 1,
                           vars,
                           order='lex')

        #set-up the elimination for the segre embedding
        mapping = []
        k = AS.ngens()
        index = AS.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                R.gen(k + count) -
                prod([CR(AS[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index) - 1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break  #only increment once

        #change the defining ideal of the subscheme into the variables
        I = R.ideal(list(self.defining_polynomials()) + mapping)
        J = I.groebner_basis()
        s = set(R.gens()[:AS.ngens()])
        n = len(J) - 1
        L = []
        while s.isdisjoint(J[n].variables()):
            L.append(J[n])
            n = n - 1

        #create new subscheme
        if PP is None:
            PS = ProjectiveSpace(self.base_ring(), M, R.gens()[AS.ngens():])
            Y = PS.subscheme(L)
        else:
            if PP.dimension_relative() != M:
                raise ValueError(
                    "projective space %s must be dimension %s") % (PP, M)
            S = PP.coordinate_ring()
            psi = R.hom([0] * k + list(S.gens()), S)
            L = [psi(l) for l in L]
            Y = PP.subscheme(L)

        #create embedding for points
        mapping = []
        index = AS.num_components() * [0]
        for count in range(M + 1):
            mapping.append(
                prod([CR(AS[i].gen(index[i])) for i in range(len(index))]))
            for i in range(len(index) - 1, -1, -1):
                if index[i] == N[i]:
                    index[i] = 0
                else:
                    index[i] += 1
                    break  #only increment once
        phi = self.hom(mapping, Y)

        return phi
示例#54
0
def logpp(p, p_prec):
    """returns the (integral) power series for log_p(1+p*z) -- extra p here!"""
    SS = PolynomialRing(QQ, 'y')
    y = SS.gen()
    return sum([((-1) ** (m - 1)) * ((p * y) ** m) / m for m in range(1, p_prec)])
    def _forward_image(self, f, check=True):
        r"""
        Compute the forward image of this subscheme by the morphism ``f``.

        The forward image is computed through elimination and ``f`` must be
        a morphism for this to be well defined.
        In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal
        $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$.
        Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous
        ideal and $self(X) = V(I_{n+1})$.

        INPUT:

        - ``f`` -- a map whose domain contains ``self``

        - ``check`` -- Boolean, if `False` no input checking is done

        OUTPUT:

         - a subscheme in the codomain of ``f``.

        EXAMPLES::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = End(PS)
            sage: f = H([x^2, y^2-2*z^2, z^2])
            sage: X = PS.subscheme(y-2*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Rational Field
            defined by:
              y - 2*z

        ::

            sage: set_verbose(None)
            sage: PS.<x,y,z,w> = ProjectiveSpace(ZZ, 3)
            sage: H = End(PS)
            sage: f = H([y^2, x^2, w^2, z^2])
            sage: X = PS.subscheme([z^2+y*w, x-w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Integer Ring
            defined by:
              y - z,
              x*z - w^2

        ::

            sage: PS.<x,y,z,w> = ProjectiveSpace(CC, 3)
            sage: H = End(PS)
            sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2])
            sage: X = PS.subscheme([z-2*w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Complex Field
            with 53 bits of precision defined by:
              y + z + (-4.00000000000000)*w

        ::

            sage: R.<t> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2])
            sage: f([t^2*y-z])
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Univariate Polynomial Ring in t over Rational Field defined by:
              y + (-1/t^2)*z

        ::

            sage: set_verbose(-1)
            sage: PS.<x,y,z> = ProjectiveSpace(Qp(3), 2)
            sage: H = End(PS)
            sage: f = H([x^2,2*y^2,z^2])
            sage: X = PS.subscheme([2*x-y,z])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 2 over 3-adic Field
            with capped relative precision 20 defined by:
              z,
              x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 +
            O(3^20))*y

        ::

            sage: R.<y0,y1,y2,y3> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([y0*x^2+y1*z^2, y2*y^2+y3*z^2, z^2])
            sage: X = P.subscheme(x*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Multivariate Polynomial Ring in y0, y1, y2, y3 over Rational Field
            defined by:
              x*z + (-y1)*z^2

            ::

            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P5.<z0,z1,z2,z3,z4,z5> = ProjectiveSpace(QQ, 5)
            sage: H = Hom(P2, P5)
            sage: f = H([x^2,x*y,x*z,y^2,y*z,z^2]) #Veronese map
            sage: X = P2.subscheme([])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 5 over Rational Field
            defined by:
              -z4^2 + z3*z5,
              -z2*z4 + z1*z5,
              -z2*z3 + z1*z4,
              -z2^2 + z0*z5,
              -z1*z2 + z0*z4,
              -z1^2 + z0*z3

            ::

            sage: P2.<x,y,z>=ProjectiveSpace(QQ, 2)
            sage: P3.<u,v,w,t>=ProjectiveSpace(QQ, 3)
            sage: H = Hom(P2, P3)
            sage: X = P2.subscheme([x-y,x-z])
            sage: f = H([x^2,y^2,z^2,x*y])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              w - t,
              v - t,
              u - t

            ::

            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = Hom(P2,P1)
            sage: f = H([x^2,y*z])
            sage: X = P2.subscheme([x-y])
            sage: f(X)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

            ::

            sage: PS.<x,y,z> = ProjectiveSpace(ZZ, 2)
            sage: H = End(PS)
            sage: f = H([x^3, x*y^2, x*z^2])
            sage: X = PS.subscheme([x-y])
            sage: X._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

        ::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: Y = P1.subscheme([u-v])
            sage: H = End(PS)
            sage: f = H([x^2, y^2, z^2])
            sage: Y._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: subscheme must be in ambient space of domain of map
        """
        dom = f.domain()
        codom = f.codomain()
        if check:
            if not f.is_morphism():
                raise TypeError("map must be a morphism")
            if self.ambient_space() != dom:
                raise TypeError(
                    "subscheme must be in ambient space of domain of map")
        CR_dom = dom.coordinate_ring()
        CR_codom = codom.coordinate_ring()
        n = CR_dom.ngens()
        m = CR_codom.ngens()
        #can't call eliminate if the base ring is polynomial so we do it ourselves
        #with a lex ordering
        R = PolynomialRing(f.base_ring(), n + m, 'tempvar', order='lex')
        Rvars = R.gens()[0:n]
        phi = CR_dom.hom(Rvars, R)
        zero = n * [0]
        psi = R.hom(zero + list(CR_codom.gens()), CR_codom)
        #set up ideal
        L = R.ideal([phi(t) for t in self.defining_polynomials()] +
                    [R.gen(n + i) - phi(f[i]) for i in range(m)])
        G = L.groebner_basis()  #eliminate
        newL = []
        #get only the elimination ideal portion
        for i in range(len(G) - 1, 0, -1):
            v = G[i].variables()
            if all(Rvars[j] not in v for j in range(n)):
                newL.append(psi(G[i]))
        return (codom.subscheme(newL))
示例#56
0
    def dynatomic_polynomial(self,period):
        r"""
        For a map `f:\mathbb{A}^1 \to \mathbb{A}^1` this function computes the (affine) dynatomic polynomial.
        The dynatomic polynomial is the analog of the cyclotomic polynomial and its roots are the points
        of formal period `n`.

        ALGORITHM:

        Homogenize to a map `f:\mathbb{P}^1 \to \mathbb{P}^1` and compute the dynatomic polynomial there.
        Then, dehomogenize.

        INPUT:

        - ``period`` -- a positive integer or a list/tuple `[m,n]` where `m` is the preperiod and `n` is the period

        OUTPUT:

        - If possible, a single variable polynomial in the coordinate ring of ``self``.
          Otherwise a fraction field element of the coordinate ring of ``self``

        EXAMPLES::

            sage: A.<x,y>=AffineSpace(QQ,2)
            sage: H=Hom(A,A)
            sage: f=H([x^2+y^2,y^2])
            sage: f.dynatomic_polynomial(2)
            Traceback (most recent call last):
            ...
            TypeError: Does not make sense in dimension >1

            ::

            sage: A.<x>=AffineSpace(ZZ,1)
            sage: H=Hom(A,A)
            sage: f=H([(x^2+1)/x])
            sage: f.dynatomic_polynomial(4)
            2*x^12 + 18*x^10 + 57*x^8 + 79*x^6 + 48*x^4 + 12*x^2 + 1

            ::

            sage: A.<x>=AffineSpace(CC,1)
            sage: H=Hom(A,A)
            sage: f=H([(x^2+1)/(3*x)])
            sage: f.dynatomic_polynomial(3)
            13.0000000000000*x^6 + 117.000000000000*x^4 + 78.0000000000000*x^2 +
            1.00000000000000

            ::

            sage: A.<x>=AffineSpace(QQ,1)
            sage: H=Hom(A,A)
            sage: f=H([x^2-10/9])
            sage: f.dynatomic_polynomial([2,1])
            531441*x^4 - 649539*x^2 - 524880
        """
        if self.domain() != self.codomain():
            raise TypeError("Must have same domain and codomain to iterate")
        from sage.schemes.affine.affine_space import is_AffineSpace
        if is_AffineSpace(self.domain())==False:
            raise NotImplementedError("Not implemented for subschemes")
        if self.domain().dimension_relative()>1:
            raise TypeError("Does not make sense in dimension >1")
        F=self.homogenize(1).dynatomic_polynomial(period)
        if F.denominator()==1:
            R=F.parent()
            Vars=list(R.variable_names())
            Vars.pop()
            S=PolynomialRing(R.base_ring(),Vars)
            phi=R.hom([S.gen(0),1],S)
            return(phi(F))
        else:
            R=F.numerator().parent()
            Vars=list(R.variable_names())
            Vars.pop()
            S=PolynomialRing(R.base_ring(),Vars)
            phi=R.hom([S.gen(0),1],S)
            return(phi(F.numerator())/phi(F.denominator()))
示例#57
0
    def markov_chain_transition_matrix(self, action = 'promotion', labeling = 'identity'):
        r"""
        Returns the transition matrix of the Markov chain for the action of generalized promotion or tau on ``self``

        INPUT:

        - ``action`` -- 'promotion' or 'tau' (default: 'promotion')
        - ``labeling`` -- 'identity' or 'source' (default: 'identity')

        This method yields the transition matrix of the Markov chain defined by the action of the generalized
        promotion operator `\partial_i` (resp. `\tau_i`) on the set of linear extensions of a finite poset. 
        Here the transition from the linear extension `\pi` to `\pi'`, where `\pi' = \pi \partial_i` 
        (resp. `\pi'= \pi \tau_i`) is counted with weight `x_i` (resp. `x_{\pi_i}` if ``labeling`` is set to ``source``).

        EXAMPLES::

            sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension = True)
            sage: L = P.linear_extensions()
            sage: L.markov_chain_transition_matrix()
            [-x0 - x1 - x2            x2       x0 + x1             0             0]
            [      x1 + x2 -x0 - x1 - x2             0            x0             0]
            [            0            x1      -x0 - x1             0            x0]
            [            0            x0             0 -x0 - x1 - x2       x1 + x2]
            [           x0             0             0       x1 + x2 -x0 - x1 - x2]

            sage: L.markov_chain_transition_matrix(labeling = 'source')
            [-x0 - x1 - x2            x3       x0 + x3             0             0]
            [      x1 + x2 -x0 - x1 - x3             0            x1             0]
            [            0            x1      -x0 - x3             0            x1]
            [            0            x0             0 -x0 - x1 - x2       x0 + x3]
            [           x0             0             0       x0 + x2 -x0 - x1 - x3]

            sage: L.markov_chain_transition_matrix(action = 'tau')
            [     -x0 - x2            x2             0            x0             0]
            [           x2 -x0 - x1 - x2            x1             0            x0]
            [            0            x1           -x1             0             0]
            [           x0             0             0      -x0 - x2            x2]
            [            0            x0             0            x2      -x0 - x2]

            sage: L.markov_chain_transition_matrix(action = 'tau', labeling = 'source')
            [     -x0 - x2            x3             0            x1             0]
            [           x2 -x0 - x1 - x3            x3             0            x1]
            [            0            x1           -x3             0             0]
            [           x0             0             0      -x1 - x2            x3]
            [            0            x0             0            x2      -x1 - x3]

        .. seealso:: :meth:`markov_chain_digraph`, :meth:`promotion`, :meth:`tau`

        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.matrix.constructor import matrix
        L = self.list()
        n = self.poset().cardinality()
        R = PolynomialRing(QQ, 'x', n)
        x = [R.gen(i) for i in range(n)]
        l = self.cardinality()
        M = dict([(i,j),0] for i in range(l) for j in range(l))
        if labeling == 'source':
            for i in range(l):
                perm = [ self.poset().unwrap(k) for k in L[i] ]
                for j in range(n-1):
                    p = getattr(L[i], action)(j+1)
                    M[(L.index(p),i)] += x[perm[j]-1]
        else:
            for i in range(l):
                for j in range(n-1):
                    p = getattr(L[i], action)(j+1)
                    M[(L.index(p),i)] += x[j]
        for i in range(l):
            M[(i,i)] += -sum(M[(j,i)] for j in range(l))
        return matrix(l,l,lambda x,y : M[(x,y)])
示例#58
0
    def molien_series(self, chi=None, return_series=True, prec=20, variable='t'):
        r"""
        Compute the Molien series of this finite group with respect to the
        character ``chi``. It can be returned either as a rational function
        in one variable or a power series in one variable. The base field
        must be a finite field, the rationals, or a cyclotomic field.

        Note that the base field characteristic cannot divide the group
        order (i.e., the non-modular case).

        ALGORITHM:

        For a finite group `G` in characteristic zero we construct the Molien series as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\text{det}(I-tg)},

        where `I` is the identity matrix and `t` an indeterminate.

        For characteristic `p` not dividing the order of `G`, let `k` be the base field
        and `N` the order of `G`. Define `\lambda` as a primitive `N`-th root of unity over `k`
        and `\omega` as a primitive `N`-th root of unity over `\QQ`. For each `g \in G`
        define `k_i(g)` to be the positive integer such that
        `e_i = \lambda^{k_i(g)}` for each eigenvalue `e_i` of `g`. Then the Molien series
        is computed as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\prod_{i=1}^n(1 - t\omega^{k_i(g)})},

        where `t` is an indeterminant. [Dec1998]_

        INPUT:

        - ``chi`` -- (default: trivial character) a linear group character of this group

        - ``return_series`` -- boolean (default: ``True``) if ``True``, then returns
          the Molien series as a power series, ``False`` as a rational function

        - ``prec`` -- integer (default: 20); power series default precision

        - ``variable`` -- string (default: ``'t'``); Variable name for the Molien series

        OUTPUT: single variable rational function or power series with integer coefficients

        EXAMPLES::

            sage: MatrixGroup(matrix(QQ,2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for finite groups
            sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: characteristic cannot divide group order

        Tetrahedral Group::

            sage: K.<i> = CyclotomicField(4)
            sage: Tetra =  MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
            sage: Tetra.molien_series(prec=30)
            1 + t^8 + 2*t^12 + t^16 + 2*t^20 + 3*t^24 + 2*t^28 + O(t^30)
            sage: mol = Tetra.molien_series(return_series=False); mol
            (t^8 - t^4 + 1)/(t^16 - t^12 - t^4 + 1)
            sage: mol.parent()
            Fraction Field of Univariate Polynomial Ring in t over Integer Ring
            sage: chi = Tetra.character(Tetra.character_table()[1])
            sage: Tetra.molien_series(chi, prec=30, variable='u')
            u^6 + u^14 + 2*u^18 + u^22 + 2*u^26 + 3*u^30 + 2*u^34 + O(u^36)
            sage: chi = Tetra.character(Tetra.character_table()[2])
            sage: Tetra.molien_series(chi)
            t^10 + t^14 + t^18 + 2*t^22 + 2*t^26 + O(t^30)

        ::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: mol = S3.molien_series(prec=10); mol
            1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^10)
            sage: mol.parent()
            Power Series Ring in t over Integer Ring

        Octahedral Group::

            sage: K.<v> = CyclotomicField(8)
            sage: a = v-v^3 #sqrt(2)
            sage: i = v^2
            sage: Octa = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [(1+i)/a,0, 0,(1-i)/a])
            sage: Octa.molien_series(prec=30)
            1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30)

        Icosahedral Group::

            sage: K.<v> = CyclotomicField(10)
            sage: z5 = v^2
            sage: i = z5^5
            sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5)
            sage: Ico = MatrixGroup([[z5^3,0, 0,z5^2], [0,1, -1,0], [(z5^4-z5)/a, (z5^2-z5^3)/a, (z5^2-z5^3)/a, -(z5^4-z5)/a]])
            sage: Ico.molien_series(prec=40)
            1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40)

        ::

            sage: G = MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: G.molien_series(chi, prec=10)
            t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 9*t^6 + 12*t^7 + 15*t^8 + 18*t^9 + 22*t^10 + O(t^11)

        ::

            sage: K = GF(5)
            sage: S = MatrixGroup(SymmetricGroup(4))
            sage: G = MatrixGroup([matrix(K,4,4,[K(y) for u in m.list() for y in u])for m in S.gens()])
            sage: G.molien_series(return_series=False)
            1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1)

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: chi = G.character(G.character_table()[4])
            sage: G.molien_series(chi)
            3*t^5 + 6*t^11 + 9*t^17 + 12*t^23 + O(t^25)
        """
        if not self.is_finite():
            raise NotImplementedError("only implemented for finite groups")
        if chi is None:
            chi = self.trivial_character()
        M = self.matrix_space()
        R = FractionField(self.base_ring())
        N = self.order()
        if R.characteristic() == 0:
            P = PolynomialRing(R, variable)
            t = P.gen()
            #it is possible the character is over a larger cyclotomic field
            K = chi.values()[0].parent()
            if K.degree() != 1:
                if R.degree() != 1:
                    L = K.composite_fields(R)[0]
                else:
                    L = K
            else:
                L = R
            mol = P(0)
            for g in self:
                mol += L(chi(g)) / (M.identity_matrix()-t*g.matrix()).det().change_ring(L)
        elif R.characteristic().divides(N):
            raise NotImplementedError("characteristic cannot divide group order")
        else: #char p>0
            #find primitive Nth roots of unity over base ring and QQ
            F = cyclotomic_polynomial(N).change_ring(R)
            w = F.roots(ring=R.algebraic_closure(), multiplicities=False)[0]
            #don't need to extend further in this case since the order of
            #the roots of unity in the character divide the order of the group
            L = CyclotomicField(N, 'v')
            v = L.gen()
            #construct Molien series
            P = PolynomialRing(L, variable)
            t = P.gen()
            mol = P(0)
            for g in self:
                #construct Phi
                phi = L(chi(g))
                for e in g.matrix().eigenvalues():
                    #find power such that w**n  = e
                    n = 1
                    while w**n != e and n < N+1:
                        n += 1
                    #raise v to that power
                    phi *= (1-t*v**n)
                mol += P(1)/phi
        #We know the coefficients will be integers
        mol = mol.numerator().change_ring(ZZ) / mol.denominator().change_ring(ZZ)
        #divide by group order
        mol /= N
        if return_series:
            PS = PowerSeriesRing(ZZ, variable, default_prec=prec)
            return PS(mol)
        return mol
示例#59
0
class PseudoConwayLattice(WithEqualityById, SageObject):
    r"""
    A pseudo-Conway lattice over a given finite prime field.

    The Conway polynomial `f_n` of degree `n` over `\Bold{F}_p` is
    defined by the following four conditions:

    - `f_n` is irreducible.

    - In the quotient field `\Bold{F}_p[x]/(f_n)`, the element
      `x\bmod f_n` generates the multiplicative group.

    - The minimal polynomial of `(x\bmod f_n)^{\frac{p^n-1}{p^m-1}}`
      equals the Conway polynomial `f_m`, for every divisor `m` of
      `n`.

    - `f_n` is lexicographically least among all such polynomials,
      under a certain ordering.

    The final condition is needed only in order to make the Conway
    polynomial unique.  We define a pseudo-Conway lattice to be any
    family of polynomials, indexed by the positive integers,
    satisfying the first three conditions.

    INPUT:

    - ``p`` -- prime number

    - ``use_database`` -- boolean.  If ``True``, use actual Conway
      polynomials whenever they are available in the database.  If
      ``False``, always compute pseudo-Conway polynomials.

    EXAMPLES::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(2, use_database=False)
        sage: PCL.polynomial(3)
        x^3 + x + 1

    TESTS::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(3)
        sage: hash(PCL)  # random
        8738829832350

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PseudoConwayLattice(3) == PseudoConwayLattice(3)
        False
        sage: PseudoConwayLattice(3) != PseudoConwayLattice(3)
        True
        sage: P = PseudoConwayLattice(5)
        sage: P == P
        True
        sage: P != P
        False
    """
    def __init__(self, p, use_database=True):
        """
        TESTS::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(3)
            sage: PCL.polynomial(3)
            x^3 + 2*x + 1

            sage: PCL = PseudoConwayLattice(5, use_database=False)
            sage: PCL.polynomial(12)
            x^12 + 4*x^11 + 2*x^10 + 4*x^9 + 2*x^8 + 2*x^7 + 4*x^6 + x^5 + 2*x^4 + 2*x^2 + x + 2
            sage: PCL.polynomial(6)
            x^6 + x^5 + 4*x^4 + 3*x^3 + 3*x^2 + 2*x + 2
            sage: PCL.polynomial(11)
            x^11 + x^6 + 3*x^3 + 4*x + 3
        """
        self.p = p
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        self.ring = PolynomialRing(FiniteField(p), 'x')
        if use_database:
            C = sage.databases.conway.ConwayPolynomials()
            self.nodes = {
                n: self.ring(C.polynomial(p, n))
                for n in C.degrees(p)
            }
        else:
            self.nodes = {}

    def polynomial(self, n):
        r"""
        Return the pseudo-Conway polynomial of degree `n` in this
        lattice.

        INPUT:

        - ``n`` -- positive integer

        OUTPUT:

        - a pseudo-Conway polynomial of degree `n` for the prime `p`.

        ALGORITHM:

        Uses an algorithm described in [HL1999]_, modified to find
        pseudo-Conway polynomials rather than Conway polynomials.  The
        major difference is that we stop as soon as we find a
        primitive polynomial.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.polynomial(3)
            x^3 + x + 1
            sage: PCL.polynomial(4)
            x^4 + x^3 + 1
            sage: PCL.polynomial(60)
            x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1
        """
        if n in self.nodes:
            return self.nodes[n]

        p = self.p
        n = Integer(n)

        if n == 1:
            f = self.ring.gen() - FiniteField(p).multiplicative_generator()
            self.nodes[1] = f
            return f

        # Work in an arbitrary field K of order p**n.
        K = FiniteField(p**n, names='a')

        # TODO: something like the following
        # gcds = [n.gcd(d) for d in self.nodes.keys()]
        # xi = { m: (...) for m in gcds }
        xi = {
            q: self.polynomial(n // q).any_root(K,
                                                -n // q,
                                                assume_squarefree=True)
            for q in n.prime_divisors()
        }

        # The following is needed to ensure that in the concrete instantiation
        # of the "new" extension all previous choices are compatible.
        _frobenius_shift(K, xi)

        # Construct a compatible element having order the lcm of orders
        q, x = xi.popitem()
        v = p**(n // q) - 1
        for q, xitem in xi.items():
            w = p**(n // q) - 1
            g, alpha, beta = v.xgcd(w)
            x = x**beta * xitem**alpha
            v = v.lcm(w)

        r = p**n - 1
        # Get the missing part of the order to be primitive
        g = r // v
        # Iterate through g-th roots of x until a primitive one is found
        z = x.nth_root(g)
        root = K.multiplicative_generator()**v
        while z.multiplicative_order() != r:
            z *= root
        # The following should work but tries to create a huge list
        # whose length overflows Python's ints for large parameters
        #Z = x.nth_root(g, all=True)
        #for z in Z:
        #    if z.multiplicative_order() == r:
        #         break
        f = z.minimal_polynomial()
        self.nodes[n] = f
        return f

    def check_consistency(self, n):
        """
        Check that the pseudo-Conway polynomials of degree dividing
        `n` in this lattice satisfy the required compatibility
        conditions.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.check_consistency(6)
            sage: PCL.check_consistency(60)  # long time
        """
        p = self.p
        K = FiniteField(p**n, modulus=self.polynomial(n), names='a')
        a = K.gen()
        for m in n.divisors():
            assert (a**((p**n - 1) //
                        (p**m - 1))).minimal_polynomial() == self.polynomial(m)
示例#60
0
def Min(Fun, p, ubRes, conj, all_orbits=False):
    r"""
    Local loop for Affine_minimal, where we check minimality at the prime p.

    First we bound the possible k in our transformations A = zp^k + b.
    See Theorems 3.3.2 and 3.3.3 in [Molnar]_.

    INPUT:

    - ``Fun`` -- a dynamical system on projective space

    - ``p`` - a prime

    - ``ubRes`` -- integer, the upper bound needed for Th. 3.3.3 in [Molnar]_

    - ``conj`` -- a 2x2 matrix keeping track of the conjugation

    - ``all_orbits`` -- boolean; whether or not to use ``==`` in the
      inequalities to find all orbits

    OUTPUT:

    - boolean -- ``True`` if ``Fun`` is minimal at ``p``, ``False`` otherwise

    - a dynamical system on projective space minimal at ``p``

    EXAMPLES::

        sage: P.<x,y> = ProjectiveSpace(QQ, 1)
        sage: f = DynamicalSystem_projective([149*x^2 + 39*x*y + y^2, -8*x^2 + 137*x*y + 33*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import Min
        sage: Min(f, 3, -27000000, matrix(QQ,[[1, 0],[0, 1]]))
        [
        Dynamical System of Projective Space of dimension 1 over Rational Field
          Defn: Defined on coordinates by sending (x : y) to
                (157*x^2 + 72*x*y + 3*y^2 : -24*x^2 + 121*x*y + 54*y^2)        ,
        <BLANKLINE>
        [3 1]
        [0 1]
        ]
    """
    d = Fun.degree()
    AffFun = Fun.dehomogenize(1)
    R = AffFun.coordinate_ring()
    if R.is_field():
        #want the polynomial ring not the fraction field
        R = R.ring()
    F = R(AffFun[0].numerator())
    G = R(AffFun[0].denominator())
    dG = G.degree()
    # all_orbits scales bounds for >= and <= if searching for orbits instead of min model
    if dG > (d+1)/2:
        lowerBound = (-2*(G[dG]).valuation(p)/(2*dG - d + 1) + 1).floor() - int(all_orbits)
    else:
        lowerBound = (-2*(F[d]).valuation(p)/(d-1) + 1).floor() - int(all_orbits)
    upperBound = 2*(ubRes.valuation(p)) + int(all_orbits)

    if upperBound < lowerBound:
        # There are no possible transformations to reduce the resultant.
        if not all_orbits:
            return [Fun, conj]
        return []
    # Looping over each possible k, we search for transformations to reduce
    # the resultant of F/G
    all_found = []
    k = lowerBound
    Qb = PolynomialRing(QQ,'b')
    b = Qb.gen(0)
    Q = PolynomialRing(Qb,'z')
    z = Q.gen(0)
    while k <= upperBound:
        A = (p**k)*z + b
        Ft = Q(F(A) - b*G(A))
        Gt = Q((p**k)*G(A))
        Fcoeffs = Ft.coefficients(sparse=False)
        Gcoeffs = Gt.coefficients(sparse=False)
        coeffs = Fcoeffs + Gcoeffs
        RHS = (d + 1) * k / 2
        # If there is some b such that Res(phi^A) < Res(phi), we must have
        # ord_p(c) > RHS for each c in coeffs.
        # Make sure constant coefficients in coeffs satisfy the inequality.
        if all(QQ(c).valuation(p) > RHS - int(all_orbits)
               for c in coeffs if c.degree() == 0):
            # Constant coefficients in coeffs have large enough valuation, so
            # check the rest. We start by checking if simply picking b=0 works.
            if all(c(0).valuation(p) > RHS - int(all_orbits) for c in coeffs):
                # A = z*p^k satisfies the inequalities, and F/G is not minimal
                # "Conjugating by", p,"^", k, "*z +", 0
                newconj = matrix(QQ, 2, 2, [p**k, 0, 0, 1])
                minFun = Fun.conjugate(newconj)
                minFun.normalize_coordinates()
                if not all_orbits:
                    return [minFun, conj*newconj]
                all_found.append([p, k, 0])

            # Otherwise we search if any value of b will work. We start by
            # finding a minimum bound on the valuation of b that is necessary.
            # See Theorem 3.3.5 in [Molnar, M.Sc. thesis].
            bval = max(bCheck(coeff, RHS, p, b) for coeff in coeffs if coeff.degree() > 0)

            # We scale the coefficients in coeffs, so that we may assume
            # ord_p(b) is at least 0
            scaledCoeffs = [coeff(b*(p**bval)) for coeff in coeffs]

            # We now scale the inequalities, ord_p(coeff) > RHS, so that
            # coeff is in ZZ[b]
            scale = QQ(max(coeff.denominator() for coeff in scaledCoeffs))
            normalizedCoeffs = [coeff * scale for coeff in scaledCoeffs]
            scaleRHS = RHS + scale.valuation(p)

            # We now search for integers that satisfy the inequality
            # ord_p(coeff) > RHS. See Lemma 3.3.6 in [Molnar, M.Sc. thesis].
            bound = (scaleRHS + 1 - int(all_orbits)).floor()
            all_blift = blift(normalizedCoeffs, bound, p, k, all_orbits=all_orbits)

            # If bool is true after lifting, we have a solution b, and F/G
            # is not minimal.
            for boolval, sol in all_blift:
                if boolval:
                    #Rescale, conjugate and return new map
                    bsol = QQ(sol * (p**bval))
                    #only add 'minimal orbit element'
                    while bsol.abs() >= p**k:
                        if bsol < 0:
                            bsol += p**k
                        else:
                            bsol -= p**k
                    #"Conjugating by ", p,"^", k, "*z +", bsol
                    newconj = matrix(QQ, 2, 2, [p**k, bsol, 0, 1])
                    minFun = Fun.conjugate(newconj)

                    minFun.normalize_coordinates()
                    if not all_orbits:
                        return [minFun, conj*newconj]
                    if [p,k,bsol] not in all_found:
                        all_found.append([p, k, bsol])
        k = k + 1
    if not all_orbits:
        return [Fun, conj]
    return all_found