Example #1
0
def test_add_commutes(trials, verbose=False):
    r"""
    This is a simple demonstration of the :func:`random_testing` decorator and
    its recommended usage.

    We test that addition is commutative over rationals.

    EXAMPLES::

        sage: from sage.misc.random_testing import test_add_commutes
        sage: test_add_commutes(2, verbose=True, seed=0)
        a == -4, b == 0 ...
        Passes!
        a == -1/2, b == -1/95 ...
        Passes!
        sage: test_add_commutes(10)
        sage: test_add_commutes(1000) # long time
    """
    from sage.rings.all import QQ
    for _ in xrange(trials):
        a = QQ.random_element()
        b = QQ.random_element()
        if verbose:
            print "a == %s, b == %s ..." % (a, b)
        assert(a+b == b+a)
        if verbose:
            print "Passes!"
Example #2
0
def is_possible_j(j, S=[]):
    r"""
    Tests if the rational `j` is a possible `j`-invariant of an
    elliptic curve with good reduction outside `S`.

    .. note::

        The condition used is necessary but not sufficient unless S
        contains both 2 and 3.

    EXAMPLES::

        sage: from sage.schemes.elliptic_curves.ell_egros import is_possible_j
        sage: is_possible_j(0,[])
        False
        sage: is_possible_j(1728,[])
        True
        sage: is_possible_j(-4096/11,[11])
        True
    """
    j = QQ(j)
    return (j.is_zero() and 3 in S) \
        or (j==1728)                \
        or (j.is_S_integral(S)      \
            and j.prime_to_S_part(S).is_nth_power(3) \
            and (j-1728).prime_to_S_part(S).abs().is_square())
Example #3
0
    def _element_constructor_(self, x):
        r"""
        Create an element in this group from ``x``.

        INPUT:

        - ``x`` -- a rational number

        TESTS::

            sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup
            sage: DiscreteValueSemigroup([])(0)
            0
            sage: DiscreteValueSemigroup([])(1)
            Traceback (most recent call last):
            ...
            ValueError: `1` is not in Trivial Additive Abelian Semigroup.
            sage: DiscreteValueSemigroup([1])(1)
            1
            sage: DiscreteValueSemigroup([1])(-1)
            Traceback (most recent call last):
            ...
            ValueError: `-1` is not in Additive Abelian Semigroup generated by 1.

        """
        x = QQ.coerce(x)
        if x in self._generators or self._solve_linear_program(x) is not None:
            return x 

        raise ValueError("`{0}` is not in {1}.".format(x,self))
Example #4
0
    def __add__(self, other):
        r"""
        Return the subgroup of `\QQ` generated by this group and ``other``.

        INPUT:

        - ``other`` -- a discrete value group or a rational number

        EXAMPLES::

            sage: D = DiscreteValueGroup(1/2)
            sage: D + 1/3
            DiscreteValueGroup(1/6)
            sage: D + D
            DiscreteValueGroup(1/2)
            sage: D + 1
            DiscreteValueGroup(1/2)
            sage: DiscreteValueGroup(2/7) + DiscreteValueGroup(4/9)
            DiscreteValueGroup(2/63)

        """
        if not isinstance(other, DiscreteValueGroup):
            from sage.structure.element import is_Element
            if is_Element(other) and QQ.has_coerce_map_from(other.parent()):
                return self + DiscreteValueGroup(other, category=self.category())
            raise ValueError("`other` must be a DiscreteValueGroup or a rational number")
        if self.category() is not other.category():
            raise ValueError("`other` must be in the same category")
        return DiscreteValueGroup(self._generator.gcd(other._generator), category=self.category())
    def create_key(self, base, s):
        r"""
        Create a key which uniquely identifies a valuation.

        TESTS::

            sage: 3*ZZ.valuation(2) is 2*(3/2*ZZ.valuation(2)) # indirect doctest
            True
            
        """
        from sage.rings.all import infinity, QQ
        if s is infinity or s not in QQ or s <= 0:
            # for these values we can not return a TrivialValuation() in
            # create_object() because that would override that instance's
            # _factory_data and lead to pickling errors
            raise ValueError("s must be a positive rational")
        if base.is_trivial():
            # for the same reason we can not accept trivial valuations here
            raise ValueError("base must not be trivial")
        s = QQ.coerce(s)
        if s == 1:
            # we would override the _factory_data of base if we just returned
            # it in create_object() so we just refuse to do so
            raise ValueError("s must not be 1")

        if isinstance(base, ScaledValuation_generic):
            return self.create_key(base._base_valuation, s*base._scale)

        return base, s
def b(tableau, star=0):
    r"""
    The column projection operator corresponding to the Young tableau
    ``tableau`` (which is supposed to contain every integer from
    `1` to its size precisely once, but may and may not be standard).

    This is the signed sum (in the group algebra of the relevant
    symmetric group over `\QQ`) of all the permutations which
    preserve the column of ``tableau`` (where the signs are the usual
    signs of the permutations). It is called `b_{\text{tableau}}` in
    [EtRT]_, Section 4.2.

    EXAMPLES::

        sage: from sage.combinat.symmetric_group_algebra import b
        sage: b([[1,2]])
        [1, 2]
        sage: b([[1],[2]])
        [1, 2] - [2, 1]
        sage: b([])
        []
        sage: b([[1, 2, 4], [5, 3]])
        [1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]

    With the `l2r` setting for multiplication, the unnormalized
    Young symmetrizer ``e(tableau)`` should be the product
    ``b(tableau) * a(tableau)`` for every ``tableau``. Let us check
    this on the standard tableaux of size 5::

        sage: from sage.combinat.symmetric_group_algebra import a, b, e
        sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) )
        True
    """
    t = Tableau(tableau)
    if star:
        t = t.restrict(t.size()-star)

    cs = t.column_stabilizer().list()
    n = t.size()

    # This all should be over ZZ, not over QQ, but symmetric group
    # algebras don't seem to preserve coercion (the one over ZZ
    # doesn't coerce into the one over QQ even for the same n),
    # and the QQ version of this method is more important, so let
    # me stay with QQ.
    # TODO: Fix this.
    sgalg = SymmetricGroupAlgebra(QQ, n)
    one = QQ.one()
    P = permutation.Permutation

    # Ugly hack for the case of an empty tableau, due to the
    # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
    # being [1] rather than [] (which seems to have its origins in
    # permutation group code).
    # TODO: Fix this.
    if len(tableau) == 0:
        return sgalg.one()

    cd = dict((P(v), v.sign()*one) for v in cs)
    return sgalg._from_dict(cd)
Example #7
0
    def _element_constructor_(self, x):
        r"""
        Create an element from ``x``.

        INPUT:

        - ``x`` -- a rational number or `\infty`

        TESTS::

            sage: from sage.rings.valuation.value_group import DiscreteValuationCodomain
            sage: DiscreteValuationCodomain()(0)
            0
            sage: DiscreteValuationCodomain()(infinity)
            +Infinity
            sage: DiscreteValuationCodomain()(-infinity)
            -Infinity

        """
        if x is infinity:
            return x
        if x is -infinity:
            return x
        if x not in QQ:
            raise ValueError("must be a rational number or infinity")
        return QQ.coerce(x)
Example #8
0
    def _coerce_map_from_(self, S):
        r"""
        Coercion from a parent ``S``.

        There is a coercion from ``S`` if ``S`` has a coerce map to `\Q`
        or if `S = \Q/m\Z` for `m` a multiple of `n`.

        TESTS::

            sage: G2 = QQ/(2*ZZ)
            sage: G3 = QQ/(3*ZZ)
            sage: G4 = QQ/(4*ZZ)
            sage: G2.has_coerce_map_from(QQ)
            True
            sage: G2.has_coerce_map_from(ZZ)
            True
            sage: G2.has_coerce_map_from(ZZ['x'])
            False
            sage: G2.has_coerce_map_from(G3)
            False
            sage: G2.has_coerce_map_from(G4)
            True
            sage: G4.has_coerce_map_from(G2)
            False
        """
        if QQ.has_coerce_map_from(S):
            return True
        if isinstance(S, QmodnZ) and (S.n / self.n in ZZ):
            return True
Example #9
0
    def get_embedding(self,prec):
        r"""
        Returns an embedding of the quaternion algebra
        into the algebra of 2x2 matrices with coefficients in `\QQ_p`.

        INPUT:

        - prec -- Integer. The precision of the splitting.

        """
        if self.F == QQ and self.discriminant == 1:
            R =  Qp(self.p,prec)
            self._F_to_local = QQ.hom([R(1)])
            def iota(q):
                return q.change_ring(R)
            self._prec = prec
        else:
            I,J,K = self.local_splitting(prec)
            mats = [1,I,J,K]
            def iota(q):
                R=I.parent()
                try:
                    q = q.coefficient_tuple()
                except AttributeError:
                    q = q.list()
                return sum(self._F_to_local(a)*b for a,b in zip(q,mats))
        return iota
Example #10
0
    def random_element(self):
        r"""
        Return a random element of `\Q/n\Z`.

        The denominator is selected
        using the ``1/n`` distribution on integers, modified to return
        a positive value.  The numerator is then selected uniformly.

        EXAMPLES::

            sage: G = QQ/(6*ZZ)
            sage: G.random_element()
            47/16
            sage: G.random_element()
            1
            sage: G.random_element()
            3/5
        """
        if self.n == 0:
            return self(QQ.random_element())
        d = ZZ.random_element()
        if d >= 0:
            d = 2 * d + 1
        else:
            d = -2 * d
        n = ZZ.random_element((self.n * d).ceil())
        return self(n / d)
Example #11
0
    def _element_constructor_(self, x):
        r"""
        Create an element in this group from ``x``.

        INPUT:

        - ``x`` -- a rational number

        TESTS::

            sage: from sage.rings.valuation.value_group import DiscreteValueGroup
            sage: DiscreteValueGroup(0)(0)
            0
            sage: DiscreteValueGroup(0)(1)
            Traceback (most recent call last):
            ...
            ValueError: `1` is not in Trivial Additive Abelian Group.
            sage: DiscreteValueGroup(1)(1)
            1
            sage: DiscreteValueGroup(1)(1/2)
            Traceback (most recent call last):
            ...
            ValueError: `1/2` is not in Additive Abelian Group generated by 1.

        """
        x = QQ.coerce(x)
        if x == 0 or (self._generator != 0 and x/self._generator in ZZ):
            return x 

        raise ValueError("`{0}` is not in {1}.".format(x,self))
Example #12
0
    def __add__(self, other):
        r"""
        Return the subsemigroup of `\QQ` generated by this semigroup and ``other``.

        INPUT:

        - ``other`` -- a discrete value (semi-)group or a rational number

        EXAMPLES::

            sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup, DiscreteValueGroup
            sage: D = DiscreteValueSemigroup(1/2)
            sage: D + 1/3
            Additive Abelian Semigroup generated by 1/3, 1/2
            sage: D + D
            Additive Abelian Semigroup generated by 1/2
            sage: D + 1
            Additive Abelian Semigroup generated by 1/2
            sage: DiscreteValueGroup(2/7) + DiscreteValueSemigroup(4/9)
            Additive Abelian Semigroup generated by -2/7, 2/7, 4/9

        """
        if isinstance(other, DiscreteValueSemigroup):
            return DiscreteValueSemigroup(self._generators + other._generators)
        if isinstance(other, DiscreteValueGroup):
            return DiscreteValueSemigroup(self._generators + (other._generator, -other._generator))
        from sage.structure.element import is_Element
        if is_Element(other) and QQ.has_coerce_map_from(other.parent()):
            return self + DiscreteValueSemigroup(other)
        raise ValueError("`other` must be a DiscreteValueGroup, a DiscreteValueSemigroup or a rational number")
def a(tableau, star=0):
    r"""
    The row projection operator corresponding to the Young tableau
    ``tableau`` (which is supposed to contain every integer from
    `1` to its size precisely once, but may and may not be standard).

    This is the sum (in the group algebra of the relevant symmetric
    group over `\QQ`) of all the permutations which preserve
    the rows of ``tableau``. It is called `a_{\text{tableau}}` in
    [EtRT]_, Section 4.2.

    REFERENCES:

    .. [EtRT] Pavel Etingof, Oleg Golberg, Sebastian Hensel, Tiankai
       Liu, Alex Schwendner, Dmitry Vaintrob, Elena Yudovina,
       "Introduction to representation theory",
       :arXiv:`0901.0827v5`.

    EXAMPLES::

        sage: from sage.combinat.symmetric_group_algebra import a
        sage: a([[1,2]])
        [1, 2] + [2, 1]
        sage: a([[1],[2]])
        [1, 2]
        sage: a([])
        []
        sage: a([[1, 5], [2, 3], [4]])
        [1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
    """
    t = Tableau(tableau)
    if star:
        t = t.restrict(t.size()-star)

    rs = t.row_stabilizer().list()
    n = t.size()

    # This all should be over ZZ, not over QQ, but symmetric group
    # algebras don't seem to preserve coercion (the one over ZZ
    # doesn't coerce into the one over QQ even for the same n),
    # and the QQ version of this method is more important, so let
    # me stay with QQ.
    # TODO: Fix this.
    sgalg = SymmetricGroupAlgebra(QQ, n)
    one = QQ.one()
    P = permutation.Permutation

    # Ugly hack for the case of an empty tableau, due to the
    # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
    # being [1] rather than [] (which seems to have its origins in
    # permutation group code).
    # TODO: Fix this.
    if len(tableau) == 0:
        return sgalg.one()

    rd = dict((P(h), one) for h in rs)
    return sgalg._from_dict(rd)
Example #14
0
    def some_elements(self):
        """
        Return some elements, for use in testing.

        TESTS::

            sage: L = (QQ/ZZ).some_elements()
            sage: len(L)
            92
        """
        return list(set(self(x) for x in QQ.some_elements()))
Example #15
0
    def some_elements(self):
        r"""
        Return some typical elements in this group.

        EXAMPLES::

            sage: from sage.rings.valuation.value_group import DiscreteValueGroup
            sage: DiscreteValueGroup(-3/8).some_elements()
            [3/8, -3/8, 0, 42, 3/2, -3/2, 9/8, -9/8]

        """
        return [self._generator, -self._generator] + [x for x in QQ.some_elements() if x in self]
Example #16
0
 def coeff(p, q):
     ret = QQ.one()
     last = 0
     for val in p:
         count = 0
         s = 0
         while s != val:
             s += q[last+count]
             count += 1
         ret /= factorial(count)
         last += count
     return ret
Example #17
0
def rotation_matrix_angle(r, check=False):
    r"""
    Return the angle of the rotation matrix ``r`` divided by ``2 pi``.

    EXAMPLES::

        sage: from flatsurf.geometry.matrix_2x2 import rotation_matrix_angle

        sage: def rot_matrix(p, q):
        ....:     z = QQbar.zeta(q) ** p
        ....:     c = z.real()
        ....:     s = z.imag()
        ....:     return matrix(AA, 2, [c,-s,s,c])
        sage: [rotation_matrix_angle(rot_matrix(i, 5)) for i in range(1,5)]
        [1/5, 2/5, 3/5, 4/5]
        sage: [rotation_matrix_angle(rot_matrix(i,7)) for i in range(1,7)]
        [1/7, 2/7, 3/7, 4/7, 5/7, 6/7]

    Some random tests::

        sage: for _ in range(100):
        ....:     r = QQ.random_element(x=0,y=500)
        ....:     r -= r.floor()
        ....:     m = rot_matrix(r.numerator(), r.denominator())
        ....:     assert rotation_matrix_angle(m) == r

    .. NOTE::

        This is using floating point arithmetic and might be wrong.
    """
    e0,e1 = r.change_ring(CDF).eigenvalues()
    m0 = (e0.log() / 2 / CDF.pi()).imag()
    m1 = (e1.log() / 2 / CDF.pi()).imag()
    r0 = RR(m0).nearby_rational(max_denominator=10000)
    r1 = RR(m1).nearby_rational(max_denominator=10000)
    if r0 != -r1:
        raise RuntimeError
    r0 = r0.abs()
    if r[0][1] > 0:
        return QQ.one() - r0
    else:
        return r0

    if check:
        e = r.change_ring(AA).eigenvalues()[0]
        if e.minpoly() != ZZ['x'].cyclotomic_polynomial()(r.denominator()):
            raise RuntimeError
        z = QQbar.zeta(r.denominator())
        if z**r.numerator() != e:
            raise RuntimeError

    return r
Example #18
0
 def coeff(p, q):
     ret = QQ.one()
     last = 0
     for val in p:
         count = 0
         s = 0
         while s != val:
             s += q[last+count]
             count += 1
         ret /= count
         last += count
     if (len(q) - len(p)) % 2 == 1:
         ret = -ret
     return ret
Example #19
0
    def __classcall__(cls, generator):
        r"""
        Normalizes ``generator`` to a positive rational so that this is a
        unique parent.

        TESTS::

            sage: from sage.rings.valuation.value_group import DiscreteValueGroup
            sage: DiscreteValueGroup(1) is DiscreteValueGroup(-1)
            True

        """
        generator = QQ.coerce(generator)
        generator = generator.abs()
        return super(DiscreteValueGroup, cls).__classcall__(cls, generator)
Example #20
0
def ConstantFormsSpaceFunctor(group):
    r"""
    Construction functor for the space of constant forms.

    When determining a common parent between a ring
    and a forms ring or space this functor is first
    applied to the ring.

    EXAMPLES::

        sage: from sage.modular.modform_hecketriangle.functors import (ConstantFormsSpaceFunctor, FormsSpaceFunctor)
        sage: ConstantFormsSpaceFunctor(4) == FormsSpaceFunctor("holo", 4, 0, 1)
        True
        sage: ConstantFormsSpaceFunctor(4)
        ModularFormsFunctor(n=4, k=0, ep=1)
    """
    return FormsSpaceFunctor("holo", group, QQ.zero(), ZZ.one())
Example #21
0
    def _compute_padic_splitting(self,prec):
        verbose('Entering compute_padic_splitting')
        prime = self.p
        if self.seed is not None:
            self.magma.eval('SetSeed(%s)'%self.seed)
        R = Qp(prime,prec+10) #Zmod(prime**prec) #
        B_magma = self.Gn._B_magma
        a,b = self.Gn.B.invariants()
        if self._matrix_group:
            self._II = matrix(R,2,2,[1,0,0,-1])
            self._JJ = matrix(R,2,2,[0,1,1,0])
            goodroot = self.F.gen().minpoly().change_ring(R).roots()[0][0]
            self._F_to_local = self.F.hom([goodroot])
        else:
            verbose('Calling magma pMatrixRing')
            if self.F == QQ:
                _,f = self.magma.pMatrixRing(self.Gn._O_magma,prime*self.Gn._O_magma.BaseRing(),Precision = 20,nvals = 2)
                self._F_to_local = QQ.hom([R(1)])
            else:
                _,f = self.magma.pMatrixRing(self.Gn._O_magma,sage_F_ideal_to_magma(self.Gn._F_magma,self.ideal_p),Precision = 20,nvals = 2)
                try:
                    self._goodroot = R(f.Image(B_magma(B_magma.BaseRing().gen(1))).Vector()[1]._sage_())
                except SyntaxError:
                    raise SyntaxError("Magma has trouble finding local splitting")
                self._F_to_local = None
                for o,_ in self.F.gen().minpoly().change_ring(R).roots():
                    if (o - self._goodroot).valuation() > 5:
                        self._F_to_local = self.F.hom([o])
                        break
                assert self._F_to_local is not None
            verbose('Initializing II,JJ,KK')
            v = f.Image(B_magma.gen(1)).Vector()
            self._II = matrix(R,2,2,[v[i+1]._sage_() for i in xrange(4)])
            v = f.Image(B_magma.gen(2)).Vector()
            self._JJ = matrix(R,2,2,[v[i+1]._sage_() for i in xrange(4)])
            v = f.Image(B_magma.gen(3)).Vector()
            self._KK = matrix(R,2,2,[v[i+1]._sage_() for i in xrange(4)])
            self._II , self._JJ = lift_padic_splitting(self._F_to_local(a),self._F_to_local(b),self._II,self._JJ,prime,prec)
        self.Gn._F_to_local = self._F_to_local
        if not self.use_shapiro():
            self.Gpn._F_to_local = self._F_to_local

        self._KK = self._II * self._JJ
        self._prec = prec
        return self._II, self._JJ, self._KK
Example #22
0
    def some_elements(self):
        r"""
        Return some typical elements in this semigroup.

        EXAMPLES::

            sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup
            sage: list(DiscreteValueSemigroup([-3/8,1/2]).some_elements())
            [0, -3/8, 1/2, ...]

        """
        yield self(0)
        if self.is_trivial():
            return
        for g in self._generators:
            yield g
        from sage.rings.all import ZZ
        for x in (ZZ**len(self._generators)).some_elements():
            yield QQ.coerce(sum([abs(c)*g for c,g in zip(x,self._generators)]))
Example #23
0
    def __classcall__(cls, generators):
        r"""
        Normalize ``generators``.

        TESTS:

        We do not find minimal generators or something like that but just sort the
        generators and drop generators that are trivially contained in the
        semigroup generated by the remaining generators::

            sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup
            sage: DiscreteValueSemigroup([1,2]) is DiscreteValueSemigroup([1])
            True

        In this case, the normalization is not sufficient to determine that
        these are the same semigroup::

            sage: DiscreteValueSemigroup([1,-1,1/3]) is DiscreteValueSemigroup([1/3,-1/3])
            False

        """
        if generators in QQ:
            generators = [generators]
        generators = list(set([QQ.coerce(g) for g in generators if g != 0]))
        generators.sort()
        simplified_generators = generators

        # this is not very efficient but there should never be more than a
        # couple of generators
        for g in generators:
            for h in generators:
                if g == h: continue
                from sage.rings.all import NN
                if h/g in NN:
                    simplified_generators.remove(h)
                    break

        return super(DiscreteValueSemigroup, cls).__classcall__(cls, tuple(simplified_generators))
Example #24
0
    def _mul_(self, other, switch_sides=False):
        r"""
        Return the semigroup generated by ``other`` times the generators of this
        semigroup.

        INPUT:

        - ``other`` -- a rational number

        EXAMPLES::

            sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup
            sage: D = DiscreteValueSemigroup(1/2)
            sage: 1/2 * D
            Additive Abelian Semigroup generated by 1/4
            sage: D * (1/2)
            Additive Abelian Semigroup generated by 1/4
            sage: D * 0
            Trivial Additive Abelian Semigroup

        """
        other = QQ.coerce(other)
        return DiscreteValueSemigroup([g*other for g in self._generators])
Example #25
0
    def __init__(self, a, b=None, parent=None, check=True):
        r"""
        Create the cusp a/b in `\mathbb{P}^1(\QQ)`, where if b=0
        this is the cusp at infinity.

        When present, b must either be Infinity or coercible to an
        Integer.

        EXAMPLES::

            sage: Cusp(2,3)
            2/3
            sage: Cusp(3,6)
            1/2
            sage: Cusp(1,0)
            Infinity
            sage: Cusp(infinity)
            Infinity
            sage: Cusp(5)
            5
            sage: Cusp(1/2)
            1/2
            sage: Cusp(1.5)
            3/2
            sage: Cusp(int(7))
            7
            sage: Cusp(1, 2, check=False)
            1/2
            sage: Cusp('sage', 2.5, check=False)          # don't do this!
            sage/2.50000000000000

        ::

            sage: I**2
            -1
            sage: Cusp(I)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert I to a cusp

        ::

            sage: a = Cusp(2,3)
            sage: loads(a.dumps()) == a
            True

        ::

            sage: Cusp(1/3,0)
            Infinity
            sage: Cusp((1,0))
            Infinity

        TESTS::

            sage: Cusp("1/3", 5)
            1/15
            sage: Cusp(Cusp(3/5), 7)
            3/35
            sage: Cusp(5/3, 0)
            Infinity
            sage: Cusp(3,oo)
            0
            sage: Cusp((7,3), 5)
            7/15
            sage: Cusp(int(5), 7)
            5/7

        ::

            sage: Cusp(0,0)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert (0, 0) to a cusp

        ::

            sage: Cusp(oo,oo)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert (+Infinity, +Infinity) to a cusp

        ::

            sage: Cusp(Cusp(oo),oo)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert (Infinity, +Infinity) to a cusp
        """
        if parent is None:
            parent = Cusps
        Element.__init__(self, parent)

        if not check:
            self.__a = a
            self.__b = b
            return

        if b is None:
            if isinstance(a, Integer):
                self.__a = a
                self.__b = ZZ.one()
            elif isinstance(a, Rational):
                self.__a = a.numer()
                self.__b = a.denom()
            elif is_InfinityElement(a):
                self.__a = ZZ.one()
                self.__b = ZZ.zero()
            elif isinstance(a, Cusp):
                self.__a = a.__a
                self.__b = a.__b
            elif isinstance(a, (int, long)):
                self.__a = ZZ(a)
                self.__b = ZZ.one()
            elif isinstance(a, (tuple, list)):
                if len(a) != 2:
                    raise TypeError("unable to convert %r to a cusp" % a)
                if ZZ(a[1]) == 0:
                    self.__a = ZZ.one()
                    self.__b = ZZ.zero()
                    return
                try:
                    r = QQ((a[0], a[1]))
                    self.__a = r.numer()
                    self.__b = r.denom()
                except (ValueError, TypeError):
                    raise TypeError("unable to convert %r to a cusp" % a)
            else:
                try:
                    r = QQ(a)
                    self.__a = r.numer()
                    self.__b = r.denom()
                except (ValueError, TypeError):
                    raise TypeError("unable to convert %r to a cusp" % a)
            return

        if is_InfinityElement(b):
            if is_InfinityElement(a) or (isinstance(a, Cusp) and a.is_infinity()):
                raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b))
            self.__a = ZZ.zero()
            self.__b = ZZ.one()
            return
        elif not b:
            if not a:
                raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b))
            self.__a = ZZ.one()
            self.__b = ZZ.zero()
            return

        if isinstance(a, Integer) or isinstance(a, Rational):
            r = a / ZZ(b)
        elif is_InfinityElement(a):
            self.__a = ZZ.one()
            self.__b = ZZ.zero()
            return
        elif isinstance(a, Cusp):
            if a.__b:
                r = a.__a / (a.__b * b)
            else:
                self.__a = ZZ.one()
                self.__b = ZZ.zero()
                return
        elif isinstance(a, (int, long)):
            r = ZZ(a) / b
        elif isinstance(a, (tuple, list)):
            if len(a) != 2:
                raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b))
            r = ZZ(a[0]) / (ZZ(a[1]) * b)
        else:
            try:
                r = QQ(a) / b
            except (ValueError, TypeError):
                raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b))

        self.__a = r.numer()
        self.__b = r.denom()
Example #26
0
    def coordinate_vector(self, v):
        r"""
        Return the coordinate vector of ``v`` with respect to
        the basis ``self.gens()``.

        INPUT:

        - ``v`` -- An element of ``self``.

        OUTPUT:

        An element of ``self.module()``, namely the
        corresponding coordinate vector of ``v`` with respect
        to the basis ``self.gens()``.

        The module is the free module over the coefficient
        ring of ``self`` with the dimension of ``self``.

        EXAMPLES::

            sage: from sage.modular.modform_hecketriangle.space import QuasiCuspForms
            sage: MF = QuasiCuspForms(n=6, k=20, ep=1)
            sage: MF.dimension()
            12
            sage: el = MF(MF.E4()^2*MF.Delta() + MF.E4()*MF.E2()^2*MF.Delta())
            sage: el
            2*q + 120*q^2 + 3402*q^3 + 61520*q^4 + O(q^5)
            sage: vec = el.coordinate_vector()    # long time
            sage: vec    # long time
            (1, 13/(18*d), 103/(432*d^2), 0, 0, 1, 1/(2*d), 0, 0, 0, 0, 0)
            sage: vec.parent()    # long time
            Vector space of dimension 12 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
            sage: vec.parent() == MF.module()    # long time
            True
            sage: el == MF(sum([vec[l]*MF.gen(l) for l in range(0,12)]))    # long time
            True
            sage: el == MF.element_from_coordinates(vec)    # long time
            True
            sage: MF.gen(1).coordinate_vector() == vector([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])    # long time
            True

            sage: MF = QuasiCuspForms(n=infinity, k=10, ep=-1)
            sage: el2 = MF(MF.E4()*MF.f_inf()*(MF.f_i() - MF.E2()))
            sage: el2.coordinate_vector()
            (1, -1)
            sage: el2 == MF.element_from_coordinates(el2.coordinate_vector())
            True
        """

        (x,y,z,d) = self.pol_ring().gens()
        k = self._weight
        rmax = QQ(k / ZZ(2)).floor()
        partlist = v.rat().numerator().polynomial(z).list()
        denom = self.coeff_ring()(v.rat().denominator())
        partlist = [part/denom for part in partlist]
        parts = partlist + [0]*(rmax + 1 - len(partlist))
        E2 = self.E2()
        coord_vector = []

        for r in range(ZZ(0), rmax + 1):
            gens = [v/E2**r for v in self.quasi_part_gens(r)]

            if len(gens) > 0:
                ambient_space = self.graded_ring().reduce_type("cusp", degree=(gens[0].weight(), gens[0].ep()))
                subspace = ambient_space.subspace(gens)
                vector_part_in_subspace = subspace(parts[r])
                coord_part = [v for v in vector_part_in_subspace.coordinate_vector() ]
                coord_vector += coord_part

        return self._module(vector(self.coeff_ring(), coord_vector))
Example #27
0
def test_add_is_mul(trials, verbose=False):
    r"""
    This example demonstrates a failing :func:`random_testing` test,
    and shows how to reproduce the error.

    DO NOT USE THIS AS AN EXAMPLE OF HOW TO USE
    :func:`random_testing`!  Instead, look at
    :func:`sage.misc.random_testing.test_add_commutes`.

    We test that ``a+b == a*b``, for *a*, *b* rational.  This is of
    course false, so the test will almost always fail.

    EXAMPLES::

        sage: from sage.misc.random_testing import test_add_is_mul

    We start by testing that we get reproducible results when setting
    *seed* to 0.

    ::

        sage: test_add_is_mul(2, verbose=True, seed=0)
        a == -4, b == 0 ...
        Random testing has revealed a problem in test_add_is_mul
        Please report this bug!  You may be the first
        person in the world to have seen this problem.
        Please include this random seed in your bug report:
        Random seed: 0
        AssertionError()

    Normally in a ``@random_testing`` doctest, we would leave off the
    ``verbose=True`` and the ``# random``.  We put it in here so that we can
    verify that we are seeing the exact same error when we reproduce
    the error below.

    ::

        sage: test_add_is_mul(10, verbose=True) # random
        a == -2/7, b == 1 ...
        Random testing has revealed a problem in test_add_is_mul
        Please report this bug!  You may be the first
        person in the world to have seen this problem.
        Please include this random seed in your bug report:
        Random seed: 216390410596009428782506007128692114173
        AssertionError()

    OK, now assume that some user has reported a
    :func:`test_add_is_mul` failure.  We can specify the same
    *random_seed* that was found in the bug report, and we will get the
    exact same failure so that we can debug the "problem".

    ::

        sage: test_add_is_mul(10, verbose=True, seed=216390410596009428782506007128692114173)
        a == -2/7, b == 1 ...
        Random testing has revealed a problem in test_add_is_mul
        Please report this bug!  You may be the first
        person in the world to have seen this problem.
        Please include this random seed in your bug report:
        Random seed: 216390410596009428782506007128692114173
        AssertionError()
    """
    from sage.rings.all import QQ
    for _ in xrange(trials):
        a = QQ.random_element()
        b = QQ.random_element()
        if verbose:
            print "a == %s, b == %s ..." % (a, b)
        assert(a+b == a*b)
        if verbose:
            print "Passes!"
Example #28
0
    def to_sage(self):
        """
        EXAMPLES::

            sage: macaulay2(ZZ).to_sage()      # optional - macaulay2
            Integer Ring
            sage: macaulay2(QQ).to_sage()      # optional - macaulay2
            Rational Field

            sage: macaulay2(2).to_sage()       # optional - macaulay2
            2
            sage: macaulay2(1/2).to_sage()     # optional - macaulay2
            1/2
            sage: macaulay2(2/1).to_sage()     # optional - macaulay2
            2
            sage: _.parent()                   # optional - macaulay2
            Rational Field
            sage: macaulay2([1,2,3]).to_sage() # optional - macaulay2
            [1, 2, 3]

            sage: m = matrix([[1,2],[3,4]])
            sage: macaulay2(m).to_sage()       # optional - macaulay2
            [1 2]
            [3 4]

            sage: macaulay2(QQ['x,y']).to_sage()    # optional - macaulay2
            Multivariate Polynomial Ring in x, y over Rational Field
            sage: macaulay2(QQ['x']).to_sage()      # optional - macaulay2
            Univariate Polynomial Ring in x over Rational Field
            sage: macaulay2(GF(7)['x,y']).to_sage() # optional - macaulay2
            Multivariate Polynomial Ring in x, y over Finite Field of size 7

            sage: macaulay2(GF(7)).to_sage()       # optional - macaulay2
            Finite Field of size 7
            sage: macaulay2(GF(49, 'a')).to_sage() # optional - macaulay2
            Finite Field in a of size 7^2

            sage: R.<x,y> = QQ[]
            sage: macaulay2(x^2+y^2+1).to_sage()   # optional - macaulay2
            x^2 + y^2 + 1

            sage: R = macaulay2("QQ[x,y]")         # optional - macaulay2
            sage: I = macaulay2("ideal (x,y)")     # optional - macaulay2
            sage: I.to_sage()                      # optional - macaulay2
            Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field

            sage: X = R/I       # optional - macaulay2
            sage: X.to_sage()   # optional - macaulay2
            Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x, y)

            sage: R = macaulay2("QQ^2")  # optional - macaulay2
            sage: R.to_sage()            # optional - macaulay2
            Vector space of dimension 2 over Rational Field

            sage: m = macaulay2('"hello"')  # optional - macaulay2
            sage: m.to_sage()               # optional - macaulay2
            'hello'

        """
        repr_str = str(self)
        cls_str = str(self.cls())
        cls_cls_str = str(self.cls().cls())

        if repr_str == "ZZ":
            from sage.rings.all import ZZ
            return ZZ
        elif repr_str == "QQ":
            from sage.rings.all import QQ
            return QQ

        if cls_cls_str == "Type":
            if cls_str == "List":
                return [entry.to_sage() for entry in self]
            elif cls_str == "Matrix":
                from sage.matrix.all import matrix
                base_ring = self.ring().to_sage()
                entries = self.entries().to_sage()
                return matrix(base_ring, entries)
            elif cls_str == "Ideal":
                parent = self.ring().to_sage()
                gens = self.gens().entries().flatten().to_sage()
                return parent.ideal(*gens)
            elif cls_str == "QuotientRing":
                #Handle the ZZ/n case
                if "ZZ" in repr_str and "--" in repr_str:
                    from sage.rings.all import ZZ, GF
                    external_string = self.external_string()
                    zz, n = external_string.split("/")

                    #Note that n must be prime since it is
                    #coming from Macaulay 2
                    return GF(ZZ(n))

                ambient = self.ambient().to_sage()
                ideal = self.ideal().to_sage()
                return ambient.quotient(ideal)
            elif cls_str == "PolynomialRing":
                from sage.rings.all import PolynomialRing
                from sage.rings.polynomial.term_order import inv_macaulay2_name_mapping

                #Get the base ring
                base_ring = self.coefficientRing().to_sage()

                #Get a string list of generators
                gens = str(self.gens())[1:-1]

                # Check that we are dealing with default degrees, i.e. 1's.
                if self.degrees().any("x -> x != {1}").to_sage():
                    raise ValueError("cannot convert Macaulay2 polynomial ring with non-default degrees to Sage")
                #Handle the term order
                external_string = self.external_string()
                order = None
                if "MonomialOrder" not in external_string:
                    order = "degrevlex"
                else:
                    for order_name in inv_macaulay2_name_mapping:
                        if order_name in external_string:
                            order = inv_macaulay2_name_mapping[order_name]
                if len(gens) > 1 and order is None:
                    raise ValueError("cannot convert Macaulay2's term order to a Sage term order")

                return PolynomialRing(base_ring, order=order, names=gens)
            elif cls_str == "GaloisField":
                from sage.rings.all import ZZ, GF
                gf, n = repr_str.split(" ")
                n = ZZ(n)
                if n.is_prime():
                    return GF(n)
                else:
                    gen = str(self.gens())[1:-1]
                    return GF(n, gen)
            elif cls_str == "Boolean":
                if repr_str == "true":
                    return True
                elif repr_str == "false":
                    return False
            elif cls_str == "String":
                return str(repr_str)
            elif cls_str == "Module":
                from sage.modules.all import FreeModule
                if self.isFreeModule().to_sage():
                    ring = self.ring().to_sage()
                    rank = self.rank().to_sage()
                    return FreeModule(ring, rank)
        else:
            #Handle the integers and rationals separately
            if cls_str == "ZZ":
                from sage.rings.all import ZZ
                return ZZ(repr_str)
            elif cls_str == "QQ":
                from sage.rings.all import QQ
                repr_str = self.external_string()
                if "/" not in repr_str:
                    repr_str = repr_str + "/1"
                return QQ(repr_str)

            m2_parent = self.cls()
            parent = m2_parent.to_sage()

            if cls_cls_str == "PolynomialRing":
                from sage.misc.sage_eval import sage_eval
                gens_dict = parent.gens_dict()
                return sage_eval(self.external_string(), gens_dict)

        from sage.misc.sage_eval import sage_eval
        try:
            return sage_eval(repr_str)
        except Exception:
            raise NotImplementedError("cannot convert %s to a Sage object"%repr_str)
Example #29
0
File: cusps.py Project: CETHop/sage
    def __init__(self, a, b=None, parent=None, check=True):
        r"""
        Create the cusp a/b in `\mathbb{P}^1(\QQ)`, where if b=0
        this is the cusp at infinity.

        When present, b must either be Infinity or coercible to an
        Integer.

        EXAMPLES::

            sage: Cusp(2,3)
            2/3
            sage: Cusp(3,6)
            1/2
            sage: Cusp(1,0)
            Infinity
            sage: Cusp(infinity)
            Infinity
            sage: Cusp(5)
            5
            sage: Cusp(1/2)
            1/2
            sage: Cusp(1.5)
            3/2
            sage: Cusp(int(7))
            7
            sage: Cusp(1, 2, check=False)
            1/2
            sage: Cusp('sage', 2.5, check=False)          # don't do this!
            sage/2.50000000000000

        ::

            sage: I**2
            -1
            sage: Cusp(I)
            Traceback (most recent call last):
            ...
            TypeError: Unable to convert I to a Cusp

        ::

            sage: a = Cusp(2,3)
            sage: loads(a.dumps()) == a
            True

        ::

            sage: Cusp(1/3,0)
            Infinity
            sage: Cusp((1,0))
            Infinity

        TESTS::

            sage: Cusp("1/3", 5)
            1/15
            sage: Cusp(Cusp(3/5), 7)
            3/35
            sage: Cusp(5/3, 0)
            Infinity
            sage: Cusp(3,oo)
            0
            sage: Cusp((7,3), 5)
            7/15
            sage: Cusp(int(5), 7)
            5/7

        ::

            sage: Cusp(0,0)
            Traceback (most recent call last):
            ...
            TypeError: Unable to convert (0, 0) to a Cusp

        ::

            sage: Cusp(oo,oo)
            Traceback (most recent call last):
            ...
            TypeError: Unable to convert (+Infinity, +Infinity) to a Cusp

        ::

            sage: Cusp(Cusp(oo),oo)
            Traceback (most recent call last):
            ...
            TypeError: Unable to convert (Infinity, +Infinity) to a Cusp
        """
        if parent is None:
            parent = Cusps
        Element.__init__(self, parent)

        if not check:
            self.__a = a; self.__b = b
            return

        if b is None:
            if isinstance(a, Integer):
                self.__a = a
                self.__b = ZZ(1)
            elif isinstance(a, Rational):
                self.__a = a.numer()
                self.__b = a.denom()
            elif is_InfinityElement(a):
                self.__a = ZZ(1)
                self.__b = ZZ(0)
            elif isinstance(a, Cusp):
                self.__a = a.__a
                self.__b = a.__b
            elif isinstance(a, (int, long)):
                self.__a = ZZ(a)
                self.__b = ZZ(1)
            elif isinstance(a, (tuple, list)):
                if len(a) != 2:
                    raise TypeError, "Unable to convert %s to a Cusp"%a
                if ZZ(a[1]) == 0:
                    self.__a = ZZ(1)
                    self.__b = ZZ(0)
                    return
                try:
                    r = QQ((a[0], a[1]))
                    self.__a = r.numer()
                    self.__b = r.denom()
                except (ValueError, TypeError):
                    raise TypeError, "Unable to convert %s to a Cusp"%a
            else:
                try:
                    r = QQ(a)
                    self.__a = r.numer()
                    self.__b = r.denom()
                except (ValueError, TypeError):
                    raise TypeError, "Unable to convert %s to a Cusp"%a
            return

        if is_InfinityElement(b):
            if is_InfinityElement(a) or (isinstance(a, Cusp) and a.is_infinity()):
                raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b)
            self.__a = ZZ(0)
            self.__b = ZZ(1)
            return
        elif not b:
            if not a:
                raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b)
            self.__a = ZZ(1)
            self.__b = ZZ(0)
            return

        if isinstance(a, Integer) or isinstance(a, Rational):
            r = a / ZZ(b)
        elif is_InfinityElement(a):
            self.__a = ZZ(1)
            self.__b = ZZ(0)
            return
        elif isinstance(a, Cusp):
            if a.__b:
                r = a.__a / (a.__b * b)
            else:
                self.__a = ZZ(1)
                self.__b = ZZ(0)
                return
        elif isinstance(a, (int, long)):
            r = ZZ(a) / b
        elif isinstance(a, (tuple, list)):
            if len(a) != 2:
                raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b)
            r = ZZ(a[0]) / (ZZ(a[1]) * b)
        else:
            try:
                r = QQ(a) / b
            except (ValueError, TypeError):
                raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b)

        self.__a = r.numer()
        self.__b = r.denom()
Example #30
0
    def normal_cone(self):
        r"""
        Return the (closure of the) normal cone of the triangulation.

        Recall that a regular triangulation is one that equals the
        "crease lines" of a convex piecewise-linear function. This
        support function is not unique, for example, you can scale it
        by a positive constant. The set of all piecewise-linear
        functions with fixed creases forms an open cone. This cone can
        be interpreted as the cone of normal vectors at a point of the
        secondary polytope, which is why we call it normal cone. See
        [GKZ1994]_ Section 7.1 for details.

        OUTPUT:

        The closure of the normal cone. The `i`-th entry equals the
        value of the piecewise-linear function at the `i`-th point of
        the configuration.

        For an irregular triangulation, the normal cone is empty. In
        this case, a single point (the origin) is returned.

        EXAMPLES::

            sage: triangulation = polytopes.hypercube(2).triangulate(engine='internal')
            sage: triangulation
            (<0,1,3>, <1,2,3>)
            sage: N = triangulation.normal_cone();  N
            4-d cone in 4-d lattice
            sage: N.rays()
            ( 0,  0,  0, -1),
            ( 0,  0,  1,  1),
            ( 0,  0, -1, -1),
            ( 1,  0,  0,  1),
            (-1,  0,  0, -1),
            ( 0,  1,  0, -1),
            ( 0, -1,  0,  1)
            in Ambient free module of rank 4
            over the principal ideal domain Integer Ring
            sage: N.dual().rays()
            (1, -1, 1, -1)
            in Ambient free module of rank 4
            over the principal ideal domain Integer Ring

        TESTS::

            sage: polytopes.simplex(2).triangulate().normal_cone()
            3-d cone in 3-d lattice
            sage: _.dual().is_trivial()
            True
        """
        if not self.point_configuration().base_ring().is_subring(QQ):
            raise NotImplementedError(
                'Only base rings ZZ and QQ are supported')
        from ppl import Constraint_System, Linear_Expression, C_Polyhedron
        from sage.matrix.constructor import matrix
        from sage.arith.all import lcm
        pc = self.point_configuration()
        cs = Constraint_System()
        for facet in self.interior_facets():
            s0, s1 = self._boundary_simplex_dictionary()[facet]
            p = set(s0).difference(facet).pop()
            q = set(s1).difference(facet).pop()
            origin = pc.point(p).reduced_affine_vector()
            base_indices = [i for i in s0 if i != p]
            base = matrix([
                pc.point(i).reduced_affine_vector() - origin
                for i in base_indices
            ])
            sol = base.solve_left(pc.point(q).reduced_affine_vector() - origin)
            relation = [0] * pc.n_points()
            relation[p] = sum(sol) - 1
            relation[q] = 1
            for i, base_i in enumerate(base_indices):
                relation[base_i] = -sol[i]
            rel_denom = lcm([QQ(r).denominator() for r in relation])
            relation = [ZZ(r * rel_denom) for r in relation]
            ex = Linear_Expression(relation, 0)
            cs.insert(ex >= 0)
        from sage.modules.free_module import FreeModule
        ambient = FreeModule(ZZ, self.point_configuration().n_points())
        if cs.empty():
            cone = C_Polyhedron(ambient.dimension(), 'universe')
        else:
            cone = C_Polyhedron(cs)
        from sage.geometry.cone import _Cone_from_PPL
        return _Cone_from_PPL(cone, lattice=ambient)
Example #31
0
def lift_map(target):
    """
    Create a lift map, to be used for lifting the cross ratios of a matroid
    representation.

    .. SEEALSO::

        :meth:`lift_cross_ratios() <sage.matroids.utilities.lift_cross_ratios>`

    INPUT:

    - ``target`` -- a string describing the target (partial) field.

    OUTPUT:

    - a dictionary

    Depending on the value of ``target``, the following lift maps will be created:

    - "reg": a lift map from `\GF3` to the regular partial field `(\ZZ, <-1>)`.

    - "sru": a lift map from `\GF7` to the
      sixth-root-of-unity partial field `(\QQ(z), <z>)`, where `z` is a sixth root
      of unity. The map sends 3 to `z`.

    - "dyadic": a lift map from `\GF{11}` to the dyadic partial field `(\QQ, <-1, 2>)`.

    - "gm": a lift map from `\GF{19}` to the golden mean partial field
      `(\QQ(t), <-1,t>)`, where `t` is a root of `t^2-t-1`. The map sends `5` to `t`.

    The example below shows that the latter map satisfies three necessary conditions stated in
    :meth:`lift_cross_ratios() <sage.matroids.utilities.lift_cross_ratios>`

    EXAMPLES::

        sage: from sage.matroids.utilities import lift_map
        sage: lm = lift_map('gm')
        sage: for x in lm:
        ....:     if (x == 1) is not (lm[x] == 1):
        ....:         print 'not a proper lift map'
        ....:     for y in lm:
        ....:         if (x+y == 0) and not (lm[x]+lm[y] == 0):
        ....:             print 'not a proper lift map'
        ....:         if (x+y == 1) and not (lm[x]+lm[y] == 1):
        ....:             print 'not a proper lift map'
        ....:         for z in lm:
        ....:             if (x*y==z) and not (lm[x]*lm[y]==lm[z]):
        ....:                 print 'not a proper lift map'

    """
    if target == "reg":
        R = GF(3)
        return {R(1): ZZ(1)}

    if target == "sru":
        R = GF(7)
        z = ZZ['z'].gen()
        S = NumberField(z * z - z + 1, 'z')
        return {R(1): S(1), R(3): S(z), R(3)**(-1): S(z)**5}

    if target == "dyadic":
        R = GF(11)
        return {R(1): QQ(1), R(-1): QQ(-1), R(2): QQ(2), R(6): QQ(1 / 2)}

    if target == "gm":
        R = GF(19)
        t = QQ['t'].gen()
        G = NumberField(t * t - t - 1, 't')
        return {
            R(1): G(1),
            R(5): G(t),
            R(1) / R(5): G(1) / G(t),
            R(-5): G(-t),
            R(-5)**(-1): G(-t)**(-1),
            R(5)**2: G(t)**2,
            R(5)**(-2): G(t)**(-2)
        }

    raise NotImplementedError(target)
Example #32
0
def Polyhedron(vertices=None, rays=None, lines=None,
               ieqs=None, eqns=None,
               ambient_dim=None, base_ring=None, minimize=True, verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements. If ``rays`` or
      ``lines`` are specified but no ``vertices``, the origin is
      taken to be the single vertex.

    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.

    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as any
      iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`.

    - ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which
      the polyhedron will be defined. For ``QQ``, exact arithmetic
      will be used. For ``RDF``, floating point numbers will be
      used. Floating point arithmetic is faster but might give the
      wrong result for degenerate input.

    - ``ambient_dim`` -- integer. The ambient space dimension. Usually
      can be figured out automatically from the H/Vrepresentation
      dimensions.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cdd'``: use cdd
        (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
        `\RDF` coefficients depending on ``base_ring``.


      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
        `\QQ` coefficients depending on ``base_ring``.

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`

    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::

      * Once constructed, a ``Polyhedron`` object is immutable.
      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _make_listlist(vertices)
    rays     = _make_listlist(rays)
    lines    = _make_listlist(lines)
    ieqs     = _make_listlist(ieqs)
    eqns     = _make_listlist(eqns)

    got_Vrep = (len(vertices+rays+lines) > 0)
    got_Hrep = (len(ieqs+eqns) > 0)

    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
    elif got_Hrep:
        deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1
    else:
        if ambient_dim is None:
            deduced_ambient_dim = 0
        else:
            deduced_ambient_dim = ambient_dim
        if base_ring is None:
            base_ring = ZZ

    # set ambient_dim
    if ambient_dim is not None and deduced_ambient_dim!=ambient_dim:
        raise ValueError('Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.')
    ambient_dim = deduced_ambient_dim

    # figure out base_ring
    from sage.misc.flatten import flatten
    values = flatten(vertices+rays+lines+ieqs+eqns)
    if base_ring is not None:
        try:
            convert = not all(x.parent() is base_ring for x in values)
        except AttributeError:   # No x.parent() method?
            convert = True
    else:
        from sage.rings.integer import is_Integer
        from sage.rings.rational import is_Rational
        from sage.rings.real_double import is_RealDoubleElement
        if all(is_Integer(x) for x in values):
            if got_Vrep:
                base_ring = ZZ
            else:   # integral inequalities usually do not determine a latice polytope!
                base_ring = QQ
            convert=False
        elif all(is_Rational(x) for x in values):
            base_ring = QQ
            convert=False
        elif all(is_RealDoubleElement(x) for x in values):
            base_ring = RDF
            convert=False
        else:
            try:
                map(ZZ, values)
                if got_Vrep:
                    base_ring = ZZ
                else:
                    base_ring = QQ
                convert = True
            except TypeError:
                from sage.structure.sequence import Sequence
                values = Sequence(values)
                if QQ.has_coerce_map_from(values.universe()):
                    base_ring = QQ
                    convert = True
                else:
                    base_ring = RDF
                    convert = True

    # Add the origin if necesarry
    if got_Vrep and len(vertices)==0:
        vertices = [ [0]*ambient_dim ]

    # Specific backends can override the base_ring
    from sage.geometry.polyhedron.parent import Polyhedra
    parent = Polyhedra(base_ring, ambient_dim, backend=backend)
    base_ring = parent.base_ring()

    # Convert into base_ring if necessary
    def convert_base_ring(lstlst):
        return [ [base_ring(x) for x in lst] for lst in lstlst]
    Hrep = Vrep = None
    if got_Hrep:
        Hrep = [ieqs, eqns]
    if got_Vrep:
        Vrep = [vertices, rays, lines]

    # finally, construct the Polyhedron
    return parent(Vrep, Hrep, convert=convert)
Example #33
0
 def _rad(self, center):
     return RBF.one() << QQ(center).valuation(2)
Example #34
0
def enumerate_totallyreal_fields_all(n,
                                     B,
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    Enumerates *all* totally real fields of degree ``n`` with discriminant
    at most ``B``, primitive or otherwise.

    INPUT:

    - ``n`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``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.

    EXAMPLES::

        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1],
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1],
        [1600, x^4 - 6*x^2 + 4],
        [1957, x^4 - 4*x^2 - x + 1],
        [2000, x^4 - 5*x^2 + 5]]
        sage: enumerate_totallyreal_fields_all(1, 10)
        [[1, x - 1]]

    TESTS:

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

        sage: enumerate_totallyreal_fields_all(2, 10)
        [[5, x^2 - x - 1], [8, x^2 - 2]]
        sage: type(enumerate_totallyreal_fields_all(2, 10)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field

    In practice most of these will be found by
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`,
    which is guaranteed to return all primitive fields but often returns
    many non-primitive ones as well. For instance, only one of the five
    fields in the example above is primitive, but
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`
    finds four out of the five (the exception being `x^4 - 6x^2 + 4`).

    The following was fixed in :trac:`13101`::

        sage: enumerate_totallyreal_fields_all(8, 10^6)  # long time (about 2 s)
        []
    """
    S = []
    counts = [0, 0, 0, 0]
    if len(divisors(n)) > 4:
        raise ValueError("Only implemented for n = p*q with p,q prime")
    for d in divisors(n):
        if 1 < d < n:
            Sds = enumerate_totallyreal_fields_prim(
                d, int(math.floor((1. * B)**(1. * d / n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print("=" * 80)
                    print("Taking F =", Sds[i][1])
                F = NumberField(ZZx(Sds[i][1]), 't')
                T = enumerate_totallyreal_fields_rel(F,
                                                     n / d,
                                                     B,
                                                     verbose=verbose,
                                                     return_seqs=return_seqs)
                if return_seqs:
                    for i in range(4):
                        counts[i] += T[0][i]
                    S += [[t[0], pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0], t[1]] for t in T]
                for E in enumerate_totallyreal_fields_prim(
                        n / d,
                        int(
                            math.floor((1. * B)**(1. / d) /
                                       (1. * Sds[i][0])**(n * 1. / d**2)))):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), 'u')):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append(
                                [EF.disc(),
                                 pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort(key=lambda x: (x[0], [QQ(cf) for cf in x[1].polrecip().Vec()]))
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
        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(_) for _ in counts],
                [[ZZ(s[0]), [QQ(_) for _ in s[1].polrecip().Vec()]]
                 for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[ZZ(s[0]), Px([QQ(_) for _ in s[1].list()])] for s in S]
Example #35
0
def Polyhedron(vertices=None,
               rays=None,
               lines=None,
               ieqs=None,
               eqns=None,
               ambient_dim=None,
               base_ring=None,
               minimize=True,
               verbose=False,
               backend=None):
    """
    Construct a polyhedron object.

    You may either define it with vertex/ray/line or
    inequalities/equations data, but not both. Redundant data will
    automatically be removed (unless ``minimize=False``), and the
    complementary representation will be computed.

    INPUT:

    - ``vertices`` -- list of point. Each point can be specified as
      any iterable container of ``base_ring`` elements. If ``rays`` or
      ``lines`` are specified but no ``vertices``, the origin is
      taken to be the single vertex.

    - ``rays`` -- list of rays. Each ray can be specified as any
      iterable container of ``base_ring`` elements.

    - ``lines`` -- list of lines. Each line can be specified as any
      iterable container of ``base_ring`` elements.

    - ``ieqs`` -- list of inequalities. Each line can be specified as any
      iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`.

    - ``eqns`` -- list of equalities. Each line can be specified as
      any iterable container of ``base_ring`` elements. An entry equal to
      ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`.

    - ``base_ring`` -- a sub-field of the reals implemented in
      Sage. The field over which the polyhedron will be defined. For
      ``QQ`` and algebraic extensions, exact arithmetic will be
      used. For ``RDF``, floating point numbers will be used. Floating
      point arithmetic is faster but might give the wrong result for
      degenerate input.

    - ``ambient_dim`` -- integer. The ambient space dimension. Usually
      can be figured out automatically from the H/Vrepresentation
      dimensions.

    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are

      * ``'cdd'``: use cdd
        (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
        `\RDF` coefficients depending on ``base_ring``.

      * ``'ppl'``: use ppl
        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
        `\QQ` coefficients depending on ``base_ring``.

      * ``'field'``: use python implementation
        (:mod:`~sage.geometry.polyhedron.backend_field`) for any field

    Some backends support further optional arguments:

    - ``minimize`` -- boolean (default: ``True``). Whether to
      immediately remove redundant H/V-representation data. Currently
      not used.

    - ``verbose`` -- boolean (default: ``False``). Whether to print
      verbose output for debugging purposes. Only supported by the cdd
      backends.

    OUTPUT:

    The polyhedron defined by the input data.

    EXAMPLES:

    Construct some polyhedra::

        sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]])
        sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]])
        sage: list(square_from_ieqs.vertex_generator())
        [A vertex at (1, -1),
         A vertex at (1, 1),
         A vertex at (-1, 1),
         A vertex at (-1, -1)]
        sage: list(square_from_vertices.inequality_generator())
        [An inequality (1, 0) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0]
        sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF)
        sage: p.n_inequalities()
        2

    The same polyhedron given in two ways::

        sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]])
        sage: p.Vrepresentation()
        (A line in the direction (0, 0, 1),
         A ray in the direction (1, 0, 0),
         A ray in the direction (0, 1, 0),
         A vertex at (0, 0, 0))
        sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]])
        sage: q.Hrepresentation()
        (An inequality (1, 0, 0) x + 0 >= 0,
         An inequality (0, 1, 0) x + 0 >= 0)

    Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with
    coordinates `a, b, \dots, f` and

      * The inequality `e+b \geq c+d`
      * The inequality `e+c \geq b+d`
      * The equation `a+b+c+d+e+f = 31`

    ::

        sage: positive_coords = Polyhedron(ieqs=[
        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
        sage: P
        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
        sage: P.dim()
        5
        sage: P.Vrepresentation()
        (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31),
         A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0),
         A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0),
         A vertex at (0, 0, 0, 31/2, 31/2, 0))

    .. NOTE::

      * Once constructed, a ``Polyhedron`` object is immutable.

      * Although the option ``field=RDF`` allows numerical data to
        be used, it might not give the right answer for degenerate
        input data - the results can depend upon the tolerance
        setting of cdd.
    """
    # Clean up the arguments
    vertices = _make_listlist(vertices)
    rays = _make_listlist(rays)
    lines = _make_listlist(lines)
    ieqs = _make_listlist(ieqs)
    eqns = _make_listlist(eqns)

    got_Vrep = (len(vertices + rays + lines) > 0)
    got_Hrep = (len(ieqs + eqns) > 0)

    if got_Vrep and got_Hrep:
        raise ValueError('You cannot specify both H- and V-representation.')
    elif got_Vrep:
        deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
    elif got_Hrep:
        deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1
    else:
        if ambient_dim is None:
            deduced_ambient_dim = 0
        else:
            deduced_ambient_dim = ambient_dim
        if base_ring is None:
            base_ring = ZZ

    # set ambient_dim
    if ambient_dim is not None and deduced_ambient_dim != ambient_dim:
        raise ValueError(
            'Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.'
        )
    ambient_dim = deduced_ambient_dim

    # figure out base_ring
    from sage.misc.flatten import flatten
    values = flatten(vertices + rays + lines + ieqs + eqns)
    if base_ring is not None:
        try:
            convert = not all(x.parent() is base_ring for x in values)
        except AttributeError:  # No x.parent() method?
            convert = True
    else:
        from sage.rings.integer import is_Integer
        from sage.rings.rational import is_Rational
        from sage.rings.real_double import is_RealDoubleElement
        if all(is_Integer(x) for x in values):
            if got_Vrep:
                base_ring = ZZ
            else:  # integral inequalities usually do not determine a latice polytope!
                base_ring = QQ
            convert = False
        elif all(is_Rational(x) for x in values):
            base_ring = QQ
            convert = False
        elif all(is_RealDoubleElement(x) for x in values):
            base_ring = RDF
            convert = False
        else:
            try:
                map(ZZ, values)
                if got_Vrep:
                    base_ring = ZZ
                else:
                    base_ring = QQ
                convert = True
            except (TypeError, ValueError):
                from sage.structure.sequence import Sequence
                values = Sequence(values)
                common_ring = values.universe()
                if QQ.has_coerce_map_from(common_ring):
                    base_ring = QQ
                    convert = True
                elif common_ring is RR:  # DWIM: replace with RDF
                    base_ring = RDF
                    convert = True
                else:
                    base_ring = common_ring
                    convert = True

    # Add the origin if necesarry
    if got_Vrep and len(vertices) == 0:
        vertices = [[0] * ambient_dim]

    # Specific backends can override the base_ring
    from sage.geometry.polyhedron.parent import Polyhedra
    parent = Polyhedra(base_ring, ambient_dim, backend=backend)
    base_ring = parent.base_ring()

    # finally, construct the Polyhedron
    Hrep = Vrep = None
    if got_Hrep:
        Hrep = [ieqs, eqns]
    if got_Vrep:
        Vrep = [vertices, rays, lines]
    return parent(Vrep, Hrep, convert=convert, verbose=verbose)
def e(tableau, star=0):
    """
    The unnormalized Young projection operator corresponding to
    the Young tableau ``tableau`` (which is supposed to contain
    every integer from `1` to its size precisely once, but may
    and may not be standard).

    EXAMPLES::

        sage: from sage.combinat.symmetric_group_algebra import e
        sage: e([[1,2]])
        [1, 2] + [2, 1]
        sage: e([[1],[2]])
        [1, 2] - [2, 1]
        sage: e([])
        []

    There are differing conventions for the order of the symmetrizers
    and antisymmetrizers.  This example illustrates our conventions::

        sage: e([[1,2],[3]])
        [1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1]
    """
    t = Tableau(tableau)
    if star:
        t = t.restrict(t.size()-star)

    mult = permutation_options['mult']
    permutation_options['mult'] = 'l2r'

    if t in e_cache:
        res = e_cache[t]
    else:
        rs = t.row_stabilizer().list()
        cs = t.column_stabilizer().list()
        n = t.size()

        QSn = SymmetricGroupAlgebra(QQ, n)
        one = QQ.one()
        P = permutation.Permutation

        rd = dict((P(h), one) for h in rs)
        sym = QSn._from_dict(rd)

        cd = dict((P(v), v.sign()*one) for v in cs)
        antisym = QSn._from_dict(cd)

        res = antisym*sym

        # Ugly hack for the case of an empty tableau, due to the
        # annoyance of Permutation(Tableau([]).row_stabilizer()[0])
        # being [1] rather than [] (which seems to have its origins in
        # permutation group code).
        # TODO: Fix this.
        if len(tableau) == 0:
            res = QSn.one()

        e_cache[t] = res

    permutation_options['mult'] = mult

    return res
Example #37
0
    def __call__(self, Q, P):
        """
        Compute and return the :class:`ReductionData` corresponding to
        the genus 2 curve `y^2 + Q(x) y = P(x)`.

        EXAMPLES::

            sage: x = polygen(QQ)
            sage: genus2reduction(x^3 - 2*x^2 - 2*x + 1, -5*x^5)
            Reduction data about this proper smooth genus 2 curve:
                    y^2 + (x^3 - 2*x^2 - 2*x + 1)*y = -5*x^5
            A Minimal Equation (away from 2):
                    y^2 = x^6 - 240*x^4 - 2550*x^3 - 11400*x^2 - 24100*x - 19855
            Minimal Discriminant (away from 2):  56675000
            Conductor (away from 2): 1416875
            Local Data:
                    p=2
                    (potential) stable reduction:  (II), j=1
                    p=5
                    (potential) stable reduction:  (I)
                    reduction at p: [V] page 156, (3), f=4
                    p=2267
                    (potential) stable reduction:  (II), j=432
                    reduction at p: [I{1-0-0}] page 170, (1), f=1

        ::

            sage: genus2reduction(x^2 + 1, -5*x^5)
            Reduction data about this proper smooth genus 2 curve:
                    y^2 + (x^2 + 1)*y = -5*x^5
            A Minimal Equation (away from 2):
                    y^2 = -20*x^5 + x^4 + 2*x^2 + 1
            Minimal Discriminant (away from 2):  48838125
            Conductor: 32025
            Local Data:
                    p=3
                    (potential) stable reduction:  (II), j=1
                    reduction at p: [I{1-0-0}] page 170, (1), f=1
                    p=5
                    (potential) stable reduction:  (IV)
                    reduction at p: [I{1-1-2}] page 182, (5), f=2
                    p=7
                    (potential) stable reduction:  (II), j=4
                    reduction at p: [I{1-0-0}] page 170, (1), f=1
                    p=61
                    (potential) stable reduction:  (II), j=57
                    reduction at p: [I{2-0-0}] page 170, (2), f=1

        Verify that we fix :trac:`5573`::

            sage: genus2reduction(x^3 + x^2 + x,-2*x^5 + 3*x^4 - x^3 - x^2 - 6*x - 2)
            Reduction data about this proper smooth genus 2 curve:
                    y^2 + (x^3 + x^2 + x)*y = -2*x^5 + 3*x^4 - x^3 - x^2 - 6*x - 2
            A Minimal Equation (away from 2):
                    y^2 = x^6 + 18*x^3 + 36*x^2 - 27
            Minimal Discriminant (away from 2):  1520984142
            Conductor: 954
            Local Data:
                    p=2
                    (potential) stable reduction:  (II), j=1
                    reduction at p: [I{1-0-0}] page 170, (1), f=1
                    p=3
                    (potential) stable reduction:  (I)
                    reduction at p: [II] page 155, (1), f=2
                    p=53
                    (potential) stable reduction:  (II), j=12
                    reduction at p: [I{1-0-0}] page 170, (1), f=1
        """
        R = PolynomialRing(QQ, 'x')
        P = R(P)
        Q = R(Q)
        if P.degree() > 6:
            raise ValueError("P (=%s) must have degree at most 6"%P)
        if Q.degree() >=4:
            raise ValueError("Q (=%s) must have degree at most 3"%Q)

        res = pari.genus2red([P,Q])

        conductor = ZZ(res[0])
        minimal_equation = R(res[2])

        minimal_disc = QQ(res[2].poldisc()).abs()
        if minimal_equation.degree() == 5:
            minimal_disc *= minimal_equation[5]**2
        # Multiply with suitable power of 2 of the form 2^(2*(d-1) - 12)
        b = 2 * (minimal_equation.degree() - 1)
        k = QQ((12 - minimal_disc.valuation(2), b)).ceil()
        minimal_disc >>= 12 - b*k
        minimal_disc = ZZ(minimal_disc)

        local_data = {}
        for red in res[3]:
            p = ZZ(red[0])

            t = red[1]
            data = "(potential) stable reduction:  (%s)" % roman_numeral[int(t[0])]
            t = t[1]
            if len(t) == 1:
                data += ", j=%s" % t[0].lift()
            elif len(t) == 2:
                data += ", j1+j2=%s, j1*j2=%s" % (t[0].lift(), t[1].lift())

            t = red[2]
            if t:
                data += "\nreduction at p: %s, " % str(t[0]).replace('"', '').replace("(tame) ", "")
                data += divisors_to_string(t[1]) + ", f=" + str(res[0].valuation(red[0]))

            local_data[p] = data

        prime_to_2_conductor_only = (-1 in res[1].component(2))
        return ReductionData(res, P, Q, minimal_equation, minimal_disc, local_data,
                             conductor, prime_to_2_conductor_only)
Example #38
0
    def descend_to(self, K, f=None):
        r"""
        Given a subfield `K` and an elliptic curve self defined over a field `L`,
        this function determines whether there exists an elliptic curve over `K`
        which is isomorphic over `L` to self. If one exists, it finds it.

        INPUT:

        - `K` -- a subfield of the base field of self.
        - `f` -- an embedding of `K` into the base field of self.

        OUTPUT:

        Either an elliptic curve defined over `K` which is isomorphic to self
        or None if no such curve exists.

        .. NOTE::

            This only works over number fields and QQ.

        EXAMPLES::

            sage: E = EllipticCurve([1,2,3,4,5])
            sage: E.descend_to(ZZ)
            Traceback (most recent call last):
            ...
            TypeError: Input must be a field.

        ::

            sage: F.<b> = QuadraticField(23)
            sage: G.<a> = F.extension(x^3+5)
            sage: E = EllipticCurve(j=1728*b).change_ring(G)
            sage: E.descend_to(F)
            Elliptic Curve defined by y^2 = x^3 + (8957952*b-206032896)*x + (-247669456896*b+474699792384) over Number Field in b with defining polynomial x^2 - 23

        ::

            sage: L.<a> = NumberField(x^4 - 7)
            sage: K.<b> = NumberField(x^2 - 7)
            sage: E = EllipticCurve([a^6,0])
            sage: E.descend_to(K)
            Elliptic Curve defined by y^2 = x^3 + 1296/49*b*x over Number Field in b with defining polynomial x^2 - 7

        ::

            sage: K.<a> = QuadraticField(17)
            sage: E = EllipticCurve(j = 2*a)
            sage: print E.descend_to(QQ)
            None
        """
        if not K.is_field():
            raise TypeError, "Input must be a field."
        if self.base_field()==K:
            return self
        j = self.j_invariant()
        from sage.rings.all import QQ
        if K == QQ:
            f = QQ.embeddings(self.base_field())[0]
            if j in QQ:
                jbase = QQ(j)
            else:
                return None
        elif f == None:
            embeddings = K.embeddings(self.base_field())
            if len(embeddings) == 0:
                raise TypeError, "Input must be a subfield of the base field of the curve."
            for g in embeddings:
                try:
                    jbase = g.preimage(j)
                    f = g
                    break
                except StandardError:
                    pass
            if f == None:
                return None
        else:
            try:
                jbase = f.preimage(j)
            except StandardError:
                return None
        E = EllipticCurve(j=jbase)
        E2 = EllipticCurve(self.base_field(), [f(a) for a in E.a_invariants()])
        if jbase==0:
            d = self.is_sextic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.sextic_twist(d)
        elif jbase==1728:
            d = self.is_quartic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quartic_twist(d)
        else:
            d = self.is_quadratic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quadratic_twist(d)
        if Etwist.is_isomorphic(self):
            try:
                Eout = EllipticCurve(K, [f.preimage(a) for a in Etwist.a_invariants()])
            except StandardError:
                return None
            else:
                return Eout
Example #39
0
def kneading_sequence(theta):
    r"""
    Determines the kneading sequence for an angle theta in RR/ZZ which
    is periodic under doubling. We use the definition for the kneading
    sequence given in Definition 3.2 of [LS1994]_.

    INPUT:

    - ``theta`` -- a rational number with odd denominator

    OUTPUT:

    a string representing the kneading sequence of theta in RR/ZZ

    REFERENCES:

    [LS1994]_

    EXAMPLES::

        sage: kneading_sequence(0)
        '*'

    ::

        sage: kneading_sequence(1/3)
        '1*'

    Since 1/3 and 7/3 are the same in RR/ZZ, they have the same kneading sequence::

        sage: kneading_sequence(7/3)
        '1*'

    We can also use (finite) decimal inputs, as long as the denominator in reduced form is odd::

        sage: kneading_sequence(1.2)
        '110*'

    Since rationals with even denominator are not periodic under doubling, we have not implemented kneading sequences for such rationals::

        sage: kneading_sequence(1/4)
        Traceback (most recent call last):
        ...
        ValueError: input must be a rational number with odd denominator
    """

    if theta not in QQ:
        raise TypeError('input must be a rational number with odd denominator')
    elif QQ(theta).valuation(2) < 0:
        raise ValueError(
            'input must be a rational number with odd denominator')
    else:
        theta = QQ(theta)
        theta = theta - floor(theta)
        KS = []
        not_done = True
        left = theta / 2
        right = (theta + 1) / 2
        y = theta
        while not_done:
            if ((y < left) or (y > right)):
                KS.append('0')
            elif ((y > left) and (y < right)):
                KS.append('1')
            else:
                not_done = False
            y = 2 * y - floor(2 * y)
        KS_str = ''.join(KS) + '*'
    return KS_str
Example #40
0
def enum_affine_rational_field(X, B):
    """
    Enumerates affine rational points on scheme ``X`` up to bound ``B``.

    INPUT:

    - ``X`` -  a scheme or set of abstract rational points of a scheme.
    - ``B`` -  a positive integer bound.

    OUTPUT:

    - a list containing the affine points of ``X`` of height up to ``B``,
      sorted.

    EXAMPLES::

        sage: A.<x,y,z> = AffineSpace(3, QQ)
        sage: from sage.schemes.affine.affine_rational_point import enum_affine_rational_field
        sage: enum_affine_rational_field(A(QQ), 1)
        [(-1, -1, -1), (-1, -1, 0), (-1, -1, 1), (-1, 0, -1), (-1, 0, 0), (-1, 0, 1),
        (-1, 1, -1), (-1, 1, 0), (-1, 1, 1), (0, -1, -1), (0, -1, 0), (0, -1, 1),
        (0, 0, -1), (0, 0, 0), (0, 0, 1), (0, 1, -1), (0, 1, 0), (0, 1, 1), (1, -1, -1),
        (1, -1, 0), (1, -1, 1), (1, 0, -1), (1, 0, 0), (1, 0, 1), (1, 1, -1), (1, 1, 0),
        (1, 1, 1)]

    ::

        sage: A.<w,x,y,z> = AffineSpace(4, QQ)
        sage: S = A.subscheme([x^2-y*z+1, w^3+z+y^2])
        sage: enum_affine_rational_field(S(QQ), 1)
        [(0, 0, -1, -1)]
        sage: enum_affine_rational_field(S(QQ), 2)
        [(0, 0, -1, -1), (1, -1, -1, -2), (1, 1, -1, -2)]

    ::

        sage: A.<x,y> = AffineSpace(2, QQ)
        sage: C = Curve(x^2+y-x)
        sage: enum_affine_rational_field(C, 10) # long time (3 s)
        [(-2, -6), (-1, -2), (-2/3, -10/9), (-1/2, -3/4), (-1/3, -4/9),
        (0, 0), (1/3, 2/9), (1/2, 1/4), (2/3, 2/9), (1, 0),
        (4/3, -4/9), (3/2, -3/4), (5/3, -10/9), (2, -2), (3, -6)]

    AUTHORS:

    - David R. Kohel <*****@*****.**>: original version.

    - Charlie Turner (06-2010): small adjustments.

    - Raman Raghukul 2018: updated.
    """
    from sage.schemes.affine.affine_space import is_AffineSpace
    if (is_Scheme(X)):
        if (not is_AffineSpace(X.ambient_space())):
            raise TypeError(
                "ambient space must be affine space over the rational field")
        X = X(X.base_ring())
    else:
        if (not is_AffineSpace(X.codomain().ambient_space())):
            raise TypeError(
                "codomain must be affine space over the rational field")

    n = X.codomain().ambient_space().ngens()
    VR = X.value_ring()
    if VR is ZZ:
        R = [0] + [s * k for k in range(1, B + 1) for s in [1, -1]]
        iters = [iter(R) for _ in range(n)]
    else:  # rational field
        iters = [QQ.range_by_height(B + 1) for _ in range(n)]
    pts = []
    P = [0] * n
    try:
        pts.append(X(P))
    except TypeError:
        pass

    for it in iters:
        next(it)
    i = 0
    while i < n:
        try:
            a = VR(next(iters[i]))
        except StopIteration:
            if VR is ZZ:
                iters[i] = iter(R)
            else:  # rational field
                iters[i] = QQ.range_by_height(B + 1)
            P[i] = next(iters[i])  # reset P[i] to 0 and increment
            i += 1
            continue
        P[i] = a
        try:
            pts.append(X(P))
        except TypeError:
            pass
        i = 0
    pts.sort()
    return pts
Example #41
0
    def descend_to(self, K, f=None):
        r"""
        Given an elliptic curve self defined over a field `L` and a
        subfield `K` of `L`, return all elliptic curves over `K` which
        are isomorphic over `L` to self.

        INPUT:

        - `K` -- a field which embeds into the base field `L` of self.

        - `f` (optional) -- an embedding of `K` into `L`.  Ignored if
          `K` is `\QQ`.

        OUTPUT:

        A list (possibly empty) of elliptic curves defined over `K`
        which are isomorphic to self over `L`, up to isomorphism over
        `K`.

        .. NOTE::

           Currently only implemented over number fields.  To extend
           to other fields of characteristic not 2 or 3, what is
           needed is a method giving the preimages in `K^*/(K^*)^m` of
           an element of the base field, for `m=2,4,6`.

        EXAMPLES::

            sage: E = EllipticCurve([1,2,3,4,5])
            sage: E.descend_to(ZZ)
            Traceback (most recent call last):
            ...
            TypeError: Input must be a field.

        ::

            sage: F.<b> = QuadraticField(23)
            sage: G.<a> = F.extension(x^3+5)
            sage: E = EllipticCurve(j=1728*b).change_ring(G)
            sage: EF = E.descend_to(F); EF
            [Elliptic Curve defined by y^2 = x^3 + (27*b-621)*x + (-1296*b+2484) over Number Field in b with defining polynomial x^2 - 23]
            sage: all([Ei.change_ring(G).is_isomorphic(E) for Ei in EF])
            True

        ::

            sage: L.<a> = NumberField(x^4 - 7)
            sage: K.<b> = NumberField(x^2 - 7, embedding=a^2)
            sage: E = EllipticCurve([a^6,0])
            sage: EK = E.descend_to(K); EK
            [Elliptic Curve defined by y^2 = x^3 + b*x over Number Field in b with defining polynomial x^2 - 7,
            Elliptic Curve defined by y^2 = x^3 + 7*b*x over Number Field in b with defining polynomial x^2 - 7]
            sage: all([Ei.change_ring(L).is_isomorphic(E) for Ei in EK])
            True

        ::

            sage: K.<a> = QuadraticField(17)
            sage: E = EllipticCurve(j = 2*a)
            sage: E.descend_to(QQ)
            []

        TESTS:

        Check that :trac:`16456` is fixed::

            sage: K.<a> = NumberField(x^3-2)
            sage: E = EllipticCurve('11a1').quadratic_twist(2)
            sage: EK = E.change_ring(K)
            sage: EK2 = EK.change_weierstrass_model((a,a,a,a+1))
            sage: EK2.descend_to(QQ)
            [Elliptic Curve defined by y^2 = x^3 + x^2 - 41*x - 199 over Rational Field]

            sage: k.<i> = QuadraticField(-1)
            sage: E = EllipticCurve(k,[0,0,0,1,0])
            sage: E.descend_to(QQ)
            [Elliptic Curve defined by y^2 = x^3 + x over Rational Field,
            Elliptic Curve defined by y^2 = x^3 - 4*x over Rational Field]

        """
        if not K.is_field():
            raise TypeError("Input must be a field.")
        L = self.base_field()
        if L is K:
            return self
        elif L == K:  # number fields can be equal but not identical
            return self.base_extend(K)

        # Construct an embedding f of K in L, and check that the
        # j-invariant is in the image, otherwise return an empty list:

        j = self.j_invariant()
        from sage.rings.all import QQ
        if K == QQ:
            try:
                jK = QQ(j)
            except (ValueError, TypeError):
                return []
        elif f is None:
            embeddings = K.embeddings(L)
            if len(embeddings) == 0:
                raise TypeError("Input must be a subfield of the base field of the curve.")
            for g in embeddings:
                try:
                    jK = g.preimage(j)
                    f = g
                    break
                except Exception:
                    pass
            if f is None:
                return []
        else:
            try:
                if f.domain() != K:
                    raise ValueError("embedding has wrong domain")
                if f.codomain() != L:
                    raise ValueError("embedding has wrong codomain")
            except AttributeError:
                raise ValueError("invalid embedding: %s" % s)
            try:
                jK = f.preimage(j)
            except Exception:
                return []

        # Now we have the j-invariant in K and must find all twists
        # which work, separating the cases of j=0 and j=1728.

        if L.characteristic():
            raise NotImplementedError("Not implemented in positive characteristic")

        if jK == 0:
            t = -54*self.c6()
            try:
                dlist = t.descend_mod_power(K,6)
                # list of d in K such that t/d is in L*^6
            except AttributeError:
                raise NotImplementedError("Not implemented over %s" % L)
            Elist = [EllipticCurve([0,0,0,0,d]) for d in dlist]
        elif jK == 1728:
            t = -27*self.c4()
            try:
                dlist = t.descend_mod_power(K,4)
                # list of d in K such that t/d is in L*^4
            except AttributeError:
                raise NotImplementedError("Not implemented over %s" % L)
            Elist = [EllipticCurve([0,0,0,d,0]) for d in dlist]
        else:
            c4, c6 = self.c_invariants()
            t = c6/c4
            try:
                dlist = t.descend_mod_power(K,2)
                # list of d in K such that t/d is in L*^2
            except AttributeError:
                raise NotImplementedError("Not implemented over %s" % L)
            c = -27*jK/(jK-1728) # =-27c4^3/c6^2
            a4list = [c*d**2 for d in dlist]
            a6list = [2*a4*d for a4,d in zip(a4list,dlist)]
            Elist = [EllipticCurve([0,0,0,a4,a6]) for a4,a6 in zip(a4list,a6list)]

        if K is QQ:
            Elist = [E.minimal_model() for E in Elist]
        return Elist
Example #42
0
    def descend_to(self, K, f=None):
        r"""
        Given a subfield `K` and an elliptic curve self defined over a field `L`,
        this function determines whether there exists an elliptic curve over `K`
        which is isomorphic over `L` to self. If one exists, it finds it.

        INPUT:

        - `K` -- a subfield of the base field of self.
        - `f` -- an embedding of `K` into the base field of self.

        OUTPUT:

        Either an elliptic curve defined over `K` which is isomorphic to self
        or None if no such curve exists.

        .. NOTE::

            This only works over number fields and QQ.

        EXAMPLES::

            sage: E = EllipticCurve([1,2,3,4,5])
            sage: E.descend_to(ZZ)
            Traceback (most recent call last):
            ...
            TypeError: Input must be a field.

        ::

            sage: F.<b> = QuadraticField(23)
            sage: G.<a> = F.extension(x^3+5)
            sage: E = EllipticCurve(j=1728*b).change_ring(G)
            sage: E.descend_to(F)
            Elliptic Curve defined by y^2 = x^3 + (8957952*b-206032896)*x + (-247669456896*b+474699792384) over Number Field in b with defining polynomial x^2 - 23

        ::

            sage: L.<a> = NumberField(x^4 - 7)
            sage: K.<b> = NumberField(x^2 - 7)
            sage: E = EllipticCurve([a^6,0])
            sage: E.descend_to(K)
            Elliptic Curve defined by y^2 = x^3 + 1296/49*b*x over Number Field in b with defining polynomial x^2 - 7

        ::

            sage: K.<a> = QuadraticField(17)
            sage: E = EllipticCurve(j = 2*a)
            sage: print E.descend_to(QQ)
            None
        """
        if not K.is_field():
            raise TypeError, "Input must be a field."
        if self.base_field() == K:
            return self
        j = self.j_invariant()
        from sage.rings.all import QQ
        if K == QQ:
            f = QQ.embeddings(self.base_field())[0]
            if j in QQ:
                jbase = QQ(j)
            else:
                return None
        elif f == None:
            embeddings = K.embeddings(self.base_field())
            if len(embeddings) == 0:
                raise TypeError, "Input must be a subfield of the base field of the curve."
            for g in embeddings:
                try:
                    jbase = g.preimage(j)
                    f = g
                    break
                except StandardError:
                    pass
            if f == None:
                return None
        else:
            try:
                jbase = f.preimage(j)
            except StandardError:
                return None
        E = EllipticCurve(j=jbase)
        E2 = EllipticCurve(self.base_field(), [f(a) for a in E.a_invariants()])
        if jbase == 0:
            d = self.is_sextic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.sextic_twist(d)
        elif jbase == 1728:
            d = self.is_quartic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quartic_twist(d)
        else:
            d = self.is_quadratic_twist(E2)
            if d == 1:
                return E
            if d == 0:
                return None
            Etwist = E2.quadratic_twist(d)
        if Etwist.is_isomorphic(self):
            try:
                Eout = EllipticCurve(
                    K, [f.preimage(a) for a in Etwist.a_invariants()])
            except StandardError:
                return None
            else:
                return Eout