Exemple #1
0
    def _element_constructor_(self, vectors):
        """
        Construct an element of ``self`` from ``vectors``.

        TESTS::

            sage: E.<x,y> = ExteriorAlgebra(QQ)
            sage: H = E.hochschild_complex(E)
            sage: H(0)
            Trivial chain
            sage: H(2)
            Chain(0: 2)
            sage: H(x+2*y)
            Chain(0: x + 2*y)
            sage: H({0: H.module(0).an_element()})
            Chain(0: 2 + 2*x + 3*y)
            sage: H({2: H.module(2).an_element()})
            Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y)
            sage: H({0:x-y, 2: H.module(2).an_element()})
            Chain with 2 nonzero terms over Rational Field
            sage: H([2])
            Traceback (most recent call last):
            ...
            ValueError: cannot construct an element from [2]
        """
        if not vectors:  # special case: the zero chain
            return self.element_class(self, {})
        # special case: an element of the defining module
        if self._M.has_coerce_map_from(parent(vectors)):
            vectors = self._M(vectors)
        if parent(vectors) is self._M:
            mc = vectors.monomial_coefficients(copy=False)
            vec = self.module(0)._from_dict({(k,): mc[k] for k in mc})
            return self.element_class(self, {0: vec})
        if isinstance(vectors, (Chain_class, self.element_class)):
            vectors = vectors._vec
        data = dict()
        if not isinstance(vectors, dict):
            raise ValueError("cannot construct an element from {}".format(vectors))
        # Special handling for the 0 free module
        # FIXME: Allow coercions between the 0 free module and the defining module
        if 0 in vectors:
            vec = vectors.pop(0)
            if parent(vec) is self._M:
                mc = vec.monomial_coefficients(copy=False)
                data[0] = self.module(0)._from_dict({(k,): mc[k] for k in mc})
            else:
                data[0] = self.module(0)(vec)
        for degree in vectors:
            vec = self.module(degree)(vectors[degree])
            if not vec:
                continue
            data[degree] = vec
        return self.element_class(self, data)
Exemple #2
0
        def __ge__(self, other):
            """
            TESTS::

                sage: A = crystals.KirillovReshetikhin(['C',2,1], 1,2).affinization()
                sage: S = A.subcrystal(max_depth=2)
                sage: ([(i,j) for i in range(len(S)) for j in range(len(S)) if S[i]>=S[j]]
                ....: == [(i,j) for i in range(len(S)) for j in range(len(S)) if 
                ....: S[i].value>=S[j].value])
                True
            """
            return parent(self) is parent(other) and self.value >= other.value
Exemple #3
0
        def __cmp__(self, other):
            """
            TESTS::

                sage: A = crystals.KirillovReshetikhin(['C',2,1], 1,2).affinization()
                sage: S = A.subcrystal(max_depth=2)
                sage: ([(i,j,cmp(S[i],S[j])) for i in range(len(S)) for j in range(len(S))]
                ....: == [(i,j,cmp(S[i].value,S[j].value)) for i in range(len(S)) for j in range(len(S))])
                True
            """
            if parent(self) is parent(other):
                return cmp(self.value, other.value)
            else:
                return cmp(parent(self), parent(other))
Exemple #4
0
    def __ge__(self, other):
        """"
        EXAMPLES::

            sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1)
            sage: b = K(rows=[[1]])
            sage: c = K(rows=[[2]])
            sage: c>=b
            True
            sage: b>=b
            True
            sage: b>=c
            False
        """
        return parent(self) is parent(other) and self.value >= other.value
Exemple #5
0
    def __lt__(self, other):
        """"
        EXAMPLES::

            sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1)
            sage: b = K(rows=[[1]])
            sage: c = K(rows=[[2]])
            sage: c<b
            False
            sage: b<b
            False
            sage: b<c
            True
        """
        return parent(self) is parent(other) and self.value < other.value
Exemple #6
0
    def __contains__(self, x):
        r"""
        Test if x is an element of this group. This checks that x defines (is?) a 2x2 integer matrix of determinant 1, and
        then hands over to the routine _contains_sl2, which derived classes should implement.

        EXAMPLES::

            sage: [1,2] in SL2Z # indirect doctest
            False
            sage: [1,2,0,1] in SL2Z # indirect doctest
            True
            sage: SL2Z([1,2,0,1]) in Gamma(3) # indirect doctest
            False
            sage: -1 in SL2Z
            True
            sage: 2 in SL2Z
            False
        """
        # Do not override this function! Derived classes should override
        # _contains_sl2.
        if isinstance(x, list) and len(x) == 4:
            if not (x[0] in ZZ and x[1] in ZZ and x[2] in ZZ and x[3] in ZZ):
                return False
            a,b,c,d = map(ZZ, x)
            if a*d - b*c != 1: return False
            return self._contains_sl2(a,b,c,d)
        else:
            if parent(x) is not SL2Z:
                try:
                    y = SL2Z(x)
                except TypeError:
                    return False
                x = y
            return self._contains_sl2(x.a(),x.b(),x.c(),x.d())
Exemple #7
0
    def __pow__(self, n):
        """
        EXAMPLES::

            sage: a = maxima('2')
            sage: a^(3/4)
            2^(3/4)

        ::

            sage: f = maxima.function('x','sin(x)')
            sage: g = maxima('-cos(x)')
            sage: f^g
            1/sin(x)^cos(x)

        ::

            sage: f = maxima.function('x','sin(x)')
            sage: g = maxima('-cos(x)') # not a function
            sage: g^f
            (-cos(x))^sin(x)
        """
        P = self._check_valid()
        if parent(n) is not P:
            n = P(n)
        return self._operation("^", n)
Exemple #8
0
    def _evalf_(self, n, x, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: bessel_J(0.0, 1.0)
            0.765197686557967
            sage: bessel_J(0, 1).n(digits=20)
            0.76519768655796655145
            sage: bessel_J(0.5, 1.5)
            0.649838074753747

        Check for correct rounding (:trac:`17122`)::

            sage: R = RealField(113)
            sage: a = R("8.935761195587725798762818805462843676e-01")
            sage: aa = RealField(200)(a)
            sage: for n in [-10..10]:
            ....:     b = bessel_J(R(n), a)
            ....:     bb = R(bessel_J(n, aa))
            ....:     if b != bb:
            ....:         print n, b-bb
        """
        if parent is not None:
            x = parent(x)

        try:
            return x.jn(Integer(n))
        except Exception:
            pass

        n, x = get_coercion_model().canonical_coercion(n, x)
        import mpmath
        return mpmath_utils.call(mpmath.besselj, n, x, parent=parent)
Exemple #9
0
    def index_of_object(self, i):
        """
        Try to return the node of the Dynkin diagram indexing the object `i`.

        OUTPUT: a node of the Dynkin diagram or ``None``

        EXAMPLES::

            sage: L = RootSystem(["A",3]).root_lattice()
            sage: alpha = L.simple_roots()
            sage: omega = RootSystem(["A",3]).weight_lattice().fundamental_weights()
            sage: options = L.plot_parse_options(labels=False)
            sage: options.index_of_object(3)
            3
            sage: options.index_of_object(alpha[1])
            1
            sage: options.index_of_object(omega[2])
            2
            sage: options.index_of_object(omega[2]+omega[3])
            sage: options.index_of_object(30)
            sage: options.index_of_object("bla")
        """
        if parent(i) in RootLatticeRealizations and len(i) == 1 and i.leading_coefficient().is_one():
            i = i.leading_support()
        if i in self.space.cartan_type().index_set():
            return i
        return None
Exemple #10
0
    def _evalf_(self, n, x, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: bessel_Y(0.5, 1.5)
            -0.0460831658930974
            sage: bessel_Y(1.0+2*I, 3.0+4*I)
            0.699410324467538 + 0.228917940896421*I
            sage: bessel_Y(0, 1).n(256)
            0.08825696421567695798292676602351516282781752309067554671104384761199978932351

        Check for correct rounding (:trac:`17122`)::

            sage: R = RealField(113)
            sage: a = R("8.935761195587725798762818805462843676e-01")
            sage: aa = RealField(200)(a)
            sage: for n in [-10..10]:
            ....:     b = bessel_Y(R(n), a)
            ....:     bb = R(bessel_Y(n, aa))
            ....:     if b != bb:
            ....:         print n, b-bb
        """
        if parent is not None:
            x = parent(x)

        try:
            return x.yn(Integer(n))
        except Exception:
            pass

        n, x = get_coercion_model().canonical_coercion(n, x)
        import mpmath
        return mpmath_utils.call(mpmath.bessely, n, x, parent=parent)
Exemple #11
0
        def is_parent_of(self, element):
            """
            Returns whether ``self`` is the parent of ``element``

            INPUT:
             - ``element`` -- any object

            EXAMPLES::

                sage: S = ZZ
                sage: S.is_parent_of(1)
                True
                sage: S.is_parent_of(2/1)
                False

            This method differs from :meth:`__contains__` because it
            does not attempt any coercion::

                sage: 2/1 in S, S.is_parent_of(2/1)
                (True, False)
                sage: int(1) in S, S.is_parent_of(int(1))
                (True, False)
            """
            from sage.structure.element import parent
            return parent(element) == self
    def strongly_finer(self):
        """
        Return the set of ordered set partitions which are strongly
        finer than ``self``.

        See :meth:`is_strongly_finer` for the definition of "strongly
        finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
            sage: C.cardinality()
            2
            sage: C.list()
            [[{1}, {3}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).strongly_finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.strongly_finer().list()
            [[{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            buo = OrderedSetPartition.bottom_up_osp
            return FiniteEnumeratedSet([par(sum((list(P) for P in C), []))
                    for C in cartesian_product([[buo(X, comp) for comp in Compositions(len(X))] for X in self])])
Exemple #13
0
    def _cmp_(self, other):
        """
        EXAMPLES::

            sage: one = lisp(1); two = lisp(2)
            sage: one == one
            True
            sage: one != two
            True
            sage: one < two
            True
            sage: two > one
            True
            sage: one < 1
            False
            sage: two == 2
            True

        """
        P = self._check_valid()
        if parent(other) is not P:
            other = P(other)

        if P.eval('(= %s %s)'%(self.name(), other.name())) == P._true_symbol():
            return 0
        elif P.eval('(< %s %s)'%(self.name(), other.name())) == P._true_symbol():
            return -1
        else:
            return 1
Exemple #14
0
        def _element_constructor_(self, element):
            """
            Coerce ``element`` into ``self``

            INPUT:

            - ``element`` -- any object

            This default implementation returns ``element`` if
            ``self`` is a facade for ``parent(element)`. Otherwise it
            attempts in turn to coerce ``element`` into each parent
            ``self`` is a facade for.

            This implementation is only valid for a facade parent
            which models the full union of the parents it is a facade
            for. Other facade parents should redefine
            :meth:`element_constructor` appropriately.

            EXAMPLES::

                sage: S = Sets().Facades().example("union"); S
                An example of a facade set: the integers completed by +-infinity
                sage: S(1)
                1
                sage: S(1/2)
                Traceback (most recent call last):
                ...
                ValueError: Can't coerce `1/2` in any parent `An example of a facade set: the integers completed by +-infinity` is a facade for
                sage: S(2/1)
                2
                sage: S(2/1).parent()
                Integer Ring
                sage: S(int(1))
                1
                sage: S(int(1)).parent()
                Integer Ring

            Facade parents that model strict subsets should redefine
            :meth:`element_constructor`::

                sage: S = Sets().Facades().example(); S
                An example of facade set: the monoid of positive integers
                sage: S(-1)
                Traceback (most recent call last):
                ...
                ValueError: %s should be positive
            """
            if self.is_parent_of(element):
                return element
            else:
                parents = self.facade_for()
                if parents is True:
                    return NotImplementedError
                for parent in self.facade_for():
                    try:
                        return parent(element)
                    except Exception:
                        pass
            raise ValueError, "Can't coerce `%s` in any parent `%s` is a facade for"%(element, self)
    def __ne__(self, other):
        r"""
        TESTS::

            sage: from flatsurf import *
            sage: t = translation_surfaces.square_torus()
            sage: F = t.fundamental_group()
            sage: a,b = F.gens()
            sage: a != b
            True
            sage: a*b != b*a
            True
            sage: a*b != a*b
            False
        """
        return parent(self) is not parent(other) or \
               self._polys != other._polys or \
               self._edges != other._edges
Exemple #16
0
    def __cmp__(self, other):
        """"
        EXAMPLES::

            sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1)
            sage: b = K(rows=[[1]])
            sage: c = K(rows=[[2]])
            sage: cmp(b,c)
            -1
            sage: cmp(b,b)
            0

        If the parent are different, it uses comparison of the parents::

            sage: cmp(b,1) == cmp(b.parent(), ZZ)
            True
        """
        return cmp(parent(self), parent(other)) or cmp(self.value, other.value)
    def __eq__(self, other):
        r"""
        TESTS::

            sage: from flatsurf import *
            sage: t = translation_surfaces.square_torus()
            sage: F = t.fundamental_group()
            sage: a,b = F.gens()
            sage: a == b
            False
            sage: a*b == b*a
            False
            sage: a*b == a*b
            True
        """
        return parent(self) is parent(other) and \
               self._polys == other._polys and  \
               self._edges == other._edges 
    def __eq__(self, other):
        r"""
        Equality test.

        EXAMPLES::

            sage: UCF = UniversalCyclotomicField()
            sage: UCF.one() == 1
            True
            sage: 1 == UCF.one()
            True

            sage: UCF(2/3) == 2/3
            True
            sage: 2/3 == UCF(2/3)
            True

            sage: UCF.gen(3) == UCF.gen(5)
            False
            sage: UCF.gen(5) + UCF.gen(3) == UCF.gen(3) + UCF.gen(5)
            True

            sage: UCF.zero() == None
            False

            sage: QQbar.zeta(5) == UCF.gen(5)
            True
            sage: UCF.gen(5) == QQbar.zeta(5)
            True
            sage: QQbar.zeta(5) == UCF.gen(5,2)
            False
            sage: UCF.gen(5,2) == QQbar.zeta(5)
            False
        """
        if parent(self) is not parent(other):
            from sage.structure.element import get_coercion_model

            cm = get_coercion_model()
            try:
                self, other = cm.canonical_coercion(self, other)
            except TypeError:
                return False
            return self == other
        return self._obj == other._obj
        def _test_codegrees(self, **options):
            """
            Test the method :meth:`degrees`.

            INPUT:

            - ``options`` -- any keyword arguments accepted by :meth:`_tester`

            EXAMPLES::

                sage: from sage.categories.complex_reflection_groups import ComplexReflectionGroups
                sage: W = ComplexReflectionGroups().Finite().example(); W   # optional - gap3
                Reducible real reflection group of rank 4 and type A2 x B2
                sage: W._test_codegrees()                  # optional - gap3

                sage: W = SymmetricGroup(5)
                sage: W._test_codegrees()

            We now break the implementation of W.degrees and check that this is caught::

                sage: W.codegrees = lambda: (1/1,5)
                sage: W._test_codegrees()
                Traceback (most recent call last):
                ...
                AssertionError: the codegrees should be integers

                sage: W.codegrees = lambda: (2,1,-1)
                sage: W._test_codegrees()
                Traceback (most recent call last):
                ...
                AssertionError: the codegrees should be nonnegative

            We restore W to its normal state::

                sage: del W.codegrees
                sage: W._test_codegrees()

            See the documentation for :class:`TestSuite` for more information.
            """
            from sage.structure.element import parent
            from sage.rings.integer_ring import ZZ

            tester = self._tester(**options)
            codegrees = self.codegrees()
            tester.assertIsInstance(codegrees, tuple,
                                    "the codegrees method should return a tuple")
            tester.assertTrue(all(parent(d) is ZZ for d in codegrees),
                              "the codegrees should be integers")
            tester.assertTrue(all(d >= 0 for d in codegrees),
                              "the codegrees should be nonnegative")
            tester.assertEqual(len(codegrees), self.rank(),
                               "the number of codegrees should coincide with the rank")
            tester.assertEqual(sum(d + 1 for d in codegrees),
                               self.number_of_reflection_hyperplanes(),
                               "the sum of the codegrees should be consistent with the number of reflection hyperplanes")
Exemple #20
0
        def __cmp__(self, other):
            """
            Comparison.

            TESTS::

                sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization()
                sage: mg = A.module_generators[0]
                sage: mg == mg
                True
                sage: mg == mg.f(2).e(2)
                True
                sage: KT = crystals.TensorProductOfKirillovReshetikhinTableaux(['C',2,1], [[1,2],[2,1]])
                sage: A = crystals.AffinizationOf(KT)
                sage: A(KT.module_generators[3], 1).f(0) == A.module_generators[0]
                True

                sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization()
                sage: mg = A.module_generators[0]
                sage: mg != mg.f(2)
                True
                sage: mg != mg.f(2).e(2)
                False


                sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization()
                sage: S = A.subcrystal(max_depth=2)
                sage: sorted(S)
                [[[1, 1], [2, 2]](0),
                 [[1, 1], [2, 3]](0),
                 [[1, 2], [2, 3]](0),
                 [[1, 1], [3, 3]](0),
                 [[1, 1], [2, 3]](1),
                 [[1, 2], [2, 3]](1),
                 [[1, 2], [3, 3]](1),
                 [[2, 2], [3, 3]](2)]

            """
            if parent(self) is parent(other):
                return cmp(self._m, other._m) or cmp(self._b, other._b)
            else:
                return cmp(parent(self), parent(other))
Exemple #21
0
    def __eq__(self, other):
        """
        Non elements of the crystal are incomparable with elements of the
        crystal (or should it return ``NotImplemented``?). Elements of this
        crystal are compared using the comparison in the underlying
        classical crystal.

        EXAMPLES::

            sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1)
            sage: b = K(rows=[[1]])
            sage: c = K(rows=[[2]])
            sage: b==c
            False
            sage: b==b
            True
            sage: b==1
            False
        """
        return parent(self) is parent(other) and self.value == other.value
Exemple #22
0
    def _evalf_(self, u, m, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: elliptic_eu(1,1).n()
            0.761594155955765
            sage: elliptic_eu(1,1).n(200)
            0.7615941559557648881194582...
        """
        R = parent or parent(z)
        return mpmath_utils.call(elliptic_eu_f, u, m, parent=R)
Exemple #23
0
    def __lt__(self, other):
        """
        Non elements of the crystal are incomparable with elements of the crystal
        (or should it return NotImplemented?)

        Comparison of two elements of this crystal:
         - different length: incomparable
         - otherwise lexicographicaly, considering self[i] and other[i]
           as incomparable if self[i] < other[i] returns NotImplemented
        """
        if parent(self) is not parent(other):
            return False
        if len(self) != len(other):
            return False
        for i in range(len(self)):
            if (self[i] < other[i]) == True:
                return True
            if (other[i] < self[i]) == True:
                return False
        return False
Exemple #24
0
    def __pow__(self, n):
        """
        EXAMPLES::

            sage: a = maxima('2')
            sage: a^(3/4)
            2^(3/4)
        """
        P = self._check_valid()
        if parent(n) is not P:
            n = P(n)
        return self._operation("^", n)
Exemple #25
0
 def __init__(self, p, a, b, s, t, sign):
     r"""
     Construct the similarity (x,y) mapsto (ax-by+s,bx+ay+t) if sign=1,
     and (ax+by+s,bx-ay+t) if sign=-1
     """
     if p is None:
         raise ValueError("The parent must be provided")
     field = p._field
     if parent(a) is not field or \
        parent(b) is not field or \
        parent(s) is not field or \
        parent(t) is not field:
            raise ValueError("wrong parent for a,b,s or t")
     self._a = a
     self._b = b
     self._s = s
     self._t = t
     if parent(sign) is not ZZ or not sign.is_unit():
         raise ValueError("sign must be either 1 or -1.")
     self._sign = sign
     MultiplicativeGroupElement.__init__(self, p)
Exemple #26
0
 def _element_constructor_(self, *args, **kwds):
     if len(args)!=1:
         return self.element_class(self, *args, **kwds)
     x = args[0]
     p=parent(x)
     if self._f.has_coerce_map_from(p):
         return self.element_class( self,self._f(x), self._f.zero(), self._f.zero(), self._f.zero())
     if isinstance(p, SimilarityGroup):
         return self.element_class(self, x.a(), x.b(), x.s(), x.t())
     if isinstance(p, TranslationGroup):
         return self.element_class( self,self._f.one(), self._f.zero(), x.s(), x.t() )
     return self.element_class(self, x, **kwds)
    def __contains__(self, elt):
        """
        EXAMPLES::

            sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])])
            sage: J = A.ideal(A([0,1]))
            sage: A([0,1]) in J
            True
            sage: A([1,0]) in J
            False
        """
        if self.ring() is not parent(elt):
            return False
        return elt.vector() in self.vector_space()
Exemple #28
0
    def _evalf_(self, z, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: elliptic_kc(1/2).n()
            1.85407467730137
            sage: elliptic_kc(1/2).n(200)
            1.85407467730137191843385034...
            sage: elliptic_kc(I).n()
            1.42127228104504 + 0.295380284214777*I
        """
        R = parent or parent(z)
        from mpmath import ellipk
        return mpmath_utils.call(ellipk, z, parent=R)
Exemple #29
0
    def _evalf_(self, z, m, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: elliptic_f(1,1).n()
            1.22619117088352
            sage: elliptic_f(1,1).n(200)
            1.22619117088351707081306096...
            sage: elliptic_f(I,I).n()
            0.149965060031782 + 0.925097284105771*I
        """
        R = parent or parent(z)
        from mpmath import ellipf
        return mpmath_utils.call(ellipf, z, m, parent=R)
Exemple #30
0
    def _evalf_(self, x, parent=None, algorithm=None):
        """
        EXAMPLES::

            sage: elliptic_ec(sqrt(2)/2).n()
            1.23742252487318
            sage: elliptic_ec(sqrt(2)/2).n(200)
            1.237422524873181672854746084083...
            sage: elliptic_ec(I).n()
            1.63241178144043 - 0.369219492375499*I
        """
        R = parent or parent(z)
        from mpmath import ellipe
        return mpmath_utils.call(ellipe, x, parent=R)
    def _element_constructor_(self, x, check=False):
        r"""
        Create an element from x. This may be either an element of self, an element of the
        ambient group, or an iterable (in which case the result is the corresponding
        product of the generators of self).

        EXAMPLES::

            sage: V = Zmod(8)**2; G = AdditiveAbelianGroupWrapper(V, [[2,2],[4,0]], [4, 2])
            sage: G(V([6,2]))
            (6, 2)
            sage: G([1,1])
            doctest:...: DeprecationWarning: The default behaviour changed!
             If you *really* want a linear combination of smith generators,
             use .linear_combination_of_smith_form_gens.
            See http://trac.sagemath.org/16261 for details.
            (6, 2)
            sage: G(G([1,1]))
            (6, 2)
        """
        if parent(x) is self.universe():
            return self.element_class(self, self._discrete_log(x), element=x)
        return addgp.AdditiveAbelianGroup_fixed_gens._element_constructor_(
            self, x, check)
Exemple #32
0
    def finer(self):
        """
        Return the set of ordered set partitions which are finer
        than ``self``.

        See :meth:`is_finer` for the definition of "finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).finer()
            sage: C.cardinality()
            3
            sage: C.list()
            [[{1}, {3}, {2}], [{3}, {1}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.finer().list()
            [[{9}, {4}, {2}, {-1}],
             [{9}, {4}, {-1}, {2}],
             [{9}, {4}, {-1, 2}],
             [{4}, {9}, {2}, {-1}],
             [{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {2}, {-1}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            return FiniteEnumeratedSet([par(sum((list(i) for i in C), []))
                    for C in cartesian_product([OrderedSetPartitions(X) for X in self])])
Exemple #33
0
    def strongly_finer(self):
        """
        Return the set of ordered set partitions which are strongly
        finer than ``self``.

        See :meth:`is_strongly_finer` for the definition of "strongly
        finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
            sage: C.cardinality()
            2
            sage: C.list()
            [[{1}, {3}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).strongly_finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.strongly_finer().list()
            [[{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            buo = OrderedSetPartition.bottom_up_osp
            return FiniteEnumeratedSet([
                par(sum((list(P) for P in C), [])) for C in cartesian_product(
                    [[buo(X, comp) for comp in Compositions(len(X))]
                     for X in self])
            ])
Exemple #34
0
 def __gt__(self, other):
     if parent(self) is not parent(other):
         return NotImplemented
     return other.__lt__(self)
Exemple #35
0
    def _element_constructor_(self, elt):
        r"""
        TESTS::

            sage: UCF = UniversalCyclotomicField()
            sage: UCF(3)
            3
            sage: UCF(3/2)
            3/2

            sage: C = CyclotomicField(13)
            sage: UCF(C.gen())
            E(13)
            sage: UCF(C.gen() - 3*C.gen()**2 + 5*C.gen()**5)
            E(13) - 3*E(13)^2 + 5*E(13)^5

            sage: C = CyclotomicField(12)
            sage: zeta12 = C.gen()
            sage: a = UCF(zeta12 - 3* zeta12**2)
            sage: a
            -E(12)^7 + 3*E(12)^8
            sage: C(_) == a
            True

            sage: UCF('[[0, 1], [0, 2]]')
            Traceback (most recent call last):
            ...
            TypeError: [ [ 0, 1 ], [ 0, 2 ] ]
            of type <type 'sage.libs.gap.element.GapElement_List'> not valid
            to initialize an element of the universal cyclotomic field

        Some conversions from symbolic functions are possible::

            sage: UCF = UniversalCyclotomicField()
            sage: [UCF(sin(pi/k, hold=True)) for k in range(1,10)]
            [0,
             1,
             -1/2*E(12)^7 + 1/2*E(12)^11,
             1/2*E(8) - 1/2*E(8)^3,
             -1/2*E(20)^13 + 1/2*E(20)^17,
             1/2,
             -1/2*E(28)^19 + 1/2*E(28)^23,
             1/2*E(16)^3 - 1/2*E(16)^5,
             -1/2*E(36)^25 + 1/2*E(36)^29]
            sage: [UCF(cos(pi/k, hold=True)) for k in range(1,10)]
            [-1,
             0,
             1/2,
             1/2*E(8) - 1/2*E(8)^3,
             -1/2*E(5)^2 - 1/2*E(5)^3,
             -1/2*E(12)^7 + 1/2*E(12)^11,
             -1/2*E(7)^3 - 1/2*E(7)^4,
             1/2*E(16) - 1/2*E(16)^7,
             -1/2*E(9)^4 - 1/2*E(9)^5]

        .. TODO::

            Implement conversion from QQbar (and as a consequence from the
            symbolic ring)
        """
        elt = py_scalar_to_element(elt)

        if isinstance(elt, (Integer, Rational)):
            return self.element_class(self, libgap(elt))
        elif isinstance(
                elt,
            (GapElement_Integer, GapElement_Rational, GapElement_Cyclotomic)):
            return self.element_class(self, elt)
        elif not elt:
            return self.zero()

        obj = None
        if isinstance(elt, gap.GapElement):
            obj = libgap(elt)
        elif isinstance(elt, gap3.GAP3Element):
            obj = libgap.eval(str(elt))
        elif isinstance(elt, str):
            obj = libgap.eval(elt)
        if obj is not None:
            if not isinstance(obj, (GapElement_Integer, GapElement_Rational,
                                    GapElement_Cyclotomic)):
                raise TypeError(
                    "{} of type {} not valid to initialize an element of the universal cyclotomic field"
                    .format(obj, type(obj)))
            return self.element_class(self, obj)

        # late import to avoid slowing down the above conversions
        from sage.rings.number_field.number_field_element import NumberFieldElement
        from sage.rings.number_field.number_field import NumberField_cyclotomic, CyclotomicField
        P = parent(elt)
        if isinstance(elt, NumberFieldElement) and isinstance(
                P, NumberField_cyclotomic):
            n = P.gen().multiplicative_order()
            elt = CyclotomicField(n)(elt)
            return sum(c * self.gen(n, i)
                       for i, c in enumerate(elt._coefficients()))

        if hasattr(elt, '_algebraic_'):
            return elt._algebraic_(self)

        raise TypeError(
            "{} of type {} not valid to initialize an element of the universal cyclotomic field"
            .format(elt, type(elt)))
Exemple #36
0
    def __call__(self, x=None, order=unk):
        """
        EXAMPLES::

            sage: from sage.combinat.species.stream import Stream
            sage: L = LazyPowerSeriesRing(QQ)
            sage: L()
            Uninitialized lazy power series
            sage: L(1)
            1
            sage: L(ZZ).coefficients(10)
            [0, 1, -1, 2, -2, 3, -3, 4, -4, 5]
            sage: L(iter(ZZ)).coefficients(10)
            [0, 1, -1, 2, -2, 3, -3, 4, -4, 5]
            sage: L(Stream(ZZ)).coefficients(10)
            [0, 1, -1, 2, -2, 3, -3, 4, -4, 5]

        ::

            sage: a = L([1,2,3])
            sage: a.coefficients(3)
            [1, 2, 3]
            sage: L(a) is a
            True
            sage: L_RR = LazyPowerSeriesRing(RR)
            sage: b = L_RR(a)
            sage: b.coefficients(3)
            [1.00000000000000, 2.00000000000000, 3.00000000000000]
            sage: L(b)
            Traceback (most recent call last):
            ...
            TypeError: do not know how to coerce ... into self

        TESTS::

            sage: L(pi)
            Traceback (most recent call last):
            ...
            TypeError: do not know how to coerce pi into self
        """
        cls = self._element_class
        BR = self.base_ring()

        if x is None:
            res = cls(self, stream=None, order=unk, aorder=unk,
                      aorder_changed=True, is_initialized=False)
            res.compute_aorder = uninitialized
            return res

        if isinstance(x, LazyPowerSeries):
            x_parent = x.parent()
            if x_parent.__class__ != self.__class__:
                raise ValueError

            if x_parent.base_ring() == self.base_ring():
                return x
            else:
                if self.base_ring().has_coerce_map_from(x_parent.base_ring()):
                    return x._new(partial(x._change_ring_gen, self.base_ring()), lambda ao: ao, x, parent=self)


        if BR.has_coerce_map_from(parent(x)):
            x = BR(x)
            return self.term(x, 0)

        if hasattr(x, "__iter__") and not isinstance(x, Stream_class):
            x = iter(x)

        if is_iterator(x):
            x = Stream(x)

        if isinstance(x, Stream_class):
            aorder = order if order != unk else 0
            return cls(self, stream=x, order=order, aorder=aorder,
                       aorder_changed=False, is_initialized=True)
        elif not isinstance(x, Element):
            x = BR(x)
            return self.term(x, 0)

        raise TypeError("do not know how to coerce %s into self" % x)
Exemple #37
0
def balance_sample(s, q=None):
    r"""
    Given ``(a,c) = s`` return a tuple ``(a',c')`` where ``a'`` is an integer
    vector with entries between -q//2 and q//2 and ``c`` is also within these
    bounds.

    If ``q`` is given ``(a,c) = s`` may live in the integers. If ``q`` is not
    given, then ``(a,c)`` are assumed to live in `\Zmod{q}`.

    INPUT:

    - ``s`` - sample of the form (a,c) where a is a vector and c is a scalar
    - ``q`` - modulus (default: ``None``)

    EXAMPLE::

        sage: from sage.crypto.lwe import balance_sample, samples, Regev
        sage: map(balance_sample, samples(10, 5, Regev))
        [((-9, -4, -4, 4, -4), 6), ((-3, -10, 8, -3, -1), -10), ((-6, -12, -3, -2, -6), -6),
        ...
        ((-1, -8, -11, 13, 4), -6), ((10, 11, -3, -13, 0), 6), ((6, -1, 2, -11, 14), 2)]


        sage: from sage.crypto.lwe import balance_sample, DiscreteGaussianPolynomialSampler, RingLWE, samples
        sage: D = DiscreteGaussianPolynomialSampler(8, 5)
        sage: rlwe = RingLWE(20, 257, D)
        sage: map(balance_sample, samples(10, 8, rlwe))
        [((5, -55, -31, -90, 6, 100, -46, -107), (6, -64, -40, 117, 27, 54, -98, -56)),
         ((109, -106, 28, 77, -14, -109, 115, 34), (82, 17, -89, 62, 1, -77, 128, 64)),
         ...
         ((-32, 51, -110, -106, 35, -82, 14, -113), (126, -120, 126, 119, 101, 3, -122, -75))]

    .. note::

        This function is useful to convert between Sage's standard
        representation of elements in `\Zmod{q}` as integers between 0 and q-1
        and the usual representation of such elements in lattice cryptography as
        integers between -q//2 and q//2.
    """
    a, c = s

    try:
        c[0]
        scalar = False
    except TypeError:
        c = vector(c.parent(), [c])
        scalar = True

    if q is None:
        q = parent(c[0]).order()
        a = a.change_ring(ZZ)
        c = c.change_ring(ZZ)
    else:
        K = IntegerModRing(q)
        a = a.change_ring(K).change_ring(ZZ)
        c = c.change_ring(K).change_ring(ZZ)

    q2 = q // 2

    if scalar:
        return vector(ZZ, len(a),
                      [e if e <= q2 else e - q
                       for e in a]), c[0] if c[0] <= q2 else c[0] - q
    else:
        return vector(ZZ, len(a),
                      [e if e <= q2 else e - q for e in a]), vector(
                          ZZ, len(c), [e if e <= q2 else e - q for e in c])
    def _element_constructor_(self, x, n=0):
        r"""
        Construct a Laurent series from `x`.

        INPUT:

        - ``x`` -- object that can be converted into a Laurent series

        - ``n`` -- (default: 0) multiply the result by `t^n`

        EXAMPLES::

            sage: R.<u> = LaurentSeriesRing(Qp(5, 10))
            sage: S.<t> = LaurentSeriesRing(RationalField())
            sage: print R(t + t^2 + O(t^3))
            (1 + O(5^10))*u + (1 + O(5^10))*u^2 + O(u^3)

        Note that coercing an element into its own parent just produces
        that element again (since Laurent series are immutable)::

            sage: u is R(u)
            True

        Rational functions are accepted::

            sage: I = sqrt(-1)
            sage: K.<I> = QQ[I]
            sage: P.<t> = PolynomialRing(K)
            sage: L.<u> = LaurentSeriesRing(QQ[I])
            sage: L((t*I)/(t^3+I*2*t))
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        ::

            sage: L(t*I) / L(t^3+I*2*t)
            1/2 + 1/4*I*u^2 - 1/8*u^4 - 1/16*I*u^6 + 1/32*u^8 +
            1/64*I*u^10 - 1/128*u^12 - 1/256*I*u^14 + 1/512*u^16 +
            1/1024*I*u^18 + O(u^20)

        TESTS:

        When converting from `R((z))` to `R((z))((w))`, the variable
        `z` is sent to `z` rather than to `w` (see :trac:`7085`)::

            sage: A.<z> = LaurentSeriesRing(QQ)
            sage: B.<w> = LaurentSeriesRing(A)
            sage: B(z)
            z
            sage: z/w
            z*w^-1

        Various conversions from PARI (see also :trac:`2508`)::

            sage: L.<q> = LaurentSeriesRing(QQ)
            sage: L.set_default_prec(10)
            sage: L(pari('1/x'))
            q^-1
            sage: L(pari('poltchebi(5)'))
            5*q - 20*q^3 + 16*q^5
            sage: L(pari('poltchebi(5) - 1/x^4'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5
            sage: L(pari('1/poltchebi(5)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + O(q^9)
            sage: L(pari('poltchebi(5) + O(x^40)'))
            5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('poltchebi(5) - 1/x^4 + O(x^40)'))
            -q^-4 + 5*q - 20*q^3 + 16*q^5 + O(q^40)
            sage: L(pari('1/poltchebi(5) + O(x^10)'))
            1/5*q^-1 + 4/5*q + 64/25*q^3 + 192/25*q^5 + 2816/125*q^7 + 8192/125*q^9 + O(q^10)
            sage: L(pari('1/poltchebi(5) + O(x^10)'), -10)  # Multiply by q^-10
            1/5*q^-11 + 4/5*q^-9 + 64/25*q^-7 + 192/25*q^-5 + 2816/125*q^-3 + 8192/125*q^-1 + O(1)
            sage: L(pari('O(x^-10)'))
            O(q^-10)
        """
        from sage.rings.fraction_field_element import is_FractionFieldElement
        from sage.rings.polynomial.polynomial_element import is_Polynomial
        from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial
        from sage.structure.element import parent

        P = parent(x)
        if isinstance(x, self.element_class) and n == 0 and P is self:
            return x  # ok, since Laurent series are immutable (no need to make a copy)
        elif P is self.base_ring():
            # Convert x into a power series; if P is itself a Laurent
            # series ring A((t)), this prevents the implementation of
            # LaurentSeries.__init__() from effectively applying the
            # ring homomorphism A((t)) -> A((t))((u)) sending t to u
            # instead of the one sending t to t.  We cannot easily
            # tell LaurentSeries.__init__() to be more strict, because
            # A((t)) -> B((u)) is expected to send t to u if A admits
            # a coercion to B but A((t)) does not, and this condition
            # would be inefficient to check there.
            x = self.power_series_ring()(x)
        elif isinstance(x, pari_gen):
            t = x.type()
            if t == "t_RFRAC":  # Rational function
                x = self(self.polynomial_ring()(x.numerator())) / \
                    self(self.polynomial_ring()(x.denominator()))
                return (x << n)
            elif t == "t_SER":  # Laurent series
                n += x._valp()
                bigoh = n + x.length()
                x = self(self.polynomial_ring()(x.Vec()))
                return (x << n).add_bigoh(bigoh)
            else:  # General case, pretend to be a polynomial
                return self(self.polynomial_ring()(x)) << n
        elif is_FractionFieldElement(x) and \
             (x.base_ring() is self.base_ring() or x.base_ring() == self.base_ring()) and \
             (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
            x = self(x.numerator()) / self(x.denominator())
            return (x << n)
        return self.element_class(self, x, n)
Exemple #39
0
def reduce_load(parent, x):
    return parent(x)
    def _element_constructor_(self, elt):
        r"""
        TESTS::

            sage: UCF = UniversalCyclotomicField()
            sage: UCF(3)
            3
            sage: UCF(3/2)
            3/2

            sage: C = CyclotomicField(13)
            sage: UCF(C.gen())
            E(13)
            sage: UCF(C.gen() - 3*C.gen()**2 + 5*C.gen()**5)
            E(13) - 3*E(13)^2 + 5*E(13)^5

            sage: C = CyclotomicField(12)
            sage: zeta12 = C.gen()
            sage: a = UCF(zeta12 - 3* zeta12**2)
            sage: a
            -E(12)^7 + 3*E(12)^8
            sage: C(_) == a
            True

            sage: UCF('[[0, 1], [0, 2]]')
            Traceback (most recent call last):
            ...
            TypeError: [ [ 0, 1 ], [ 0, 2 ] ] of type <type
            'sage.libs.gap.element.GapElement_List'> not valid to initialize an
            element of the universal cyclotomic field

        .. TODO::

            Implement conversion from QQbar (and as a consequence from the
            symbolic ring)
        """
        elt = py_scalar_to_element(elt)

        if isinstance(elt, (Integer, Rational)):
            return self.element_class(self, libgap(elt))
        elif isinstance(elt, (GapElement_Integer, GapElement_Rational, GapElement_Cyclotomic)):
            return self.element_class(self, elt)
        elif not elt:
            return self.zero()

        obj = None
        if isinstance(elt, gap.GapElement):
            obj = libgap(elt)
        elif isinstance(elt, gap3.GAP3Element):
            obj = libgap.eval(str(elt))
        elif isinstance(elt, str):
            obj = libgap.eval(elt)
        if obj is not None:
            if not isinstance(obj, (GapElement_Integer, GapElement_Rational, GapElement_Cyclotomic)):
                raise TypeError("{} of type {} not valid to initialize an element of the universal cyclotomic field".format(obj, type(obj)))
            return self.element_class(self, obj)

        # late import to avoid slowing down the above conversions
        from sage.rings.number_field.number_field_element import NumberFieldElement
        from sage.rings.number_field.number_field import NumberField_cyclotomic, CyclotomicField
        P = parent(elt)
        if isinstance(elt, NumberFieldElement) and isinstance(P, NumberField_cyclotomic):
            n = P.gen().multiplicative_order()
            elt = CyclotomicField(n)(elt)
            return sum(c * self.gen(n, i)
                       for i, c in enumerate(elt._coefficients()))
        else:
            raise TypeError("{} of type {} not valid to initialize an element of the universal cyclotomic field".format(elt, type(elt)))
Exemple #41
0
    def _element_constructor_(self, x, e=1, prec=infinity):
        r"""
        Construct a Puiseux series from ``x``.

        INPUT:

        - ``x`` -- an object that can be converted into a Puiseux series
        - ``e`` -- (default: ``1``) the ramification index of the series
        - ``prec`` -- (default: ``infinity``) the precision of the series
          as a rational number

        EXAMPLES::

            sage: P = PuiseuxSeriesRing(QQ, 'y')
            sage: y = P.gen()
            sage: P([1,3,5,7])
            1 + 3*y + 5*y^2 + 7*y^3
            sage: P(33/14)
            33/14

            sage: Q = PowerSeriesRing(QQ, 'y')
            sage: z = Q([1,2,4,5]).O(6); z
            1 + 2*y + 4*y^2 + 5*y^3 + O(y^6)
            sage: P(z) + y**(1/2)
            1 + y^(1/2) + 2*y + 4*y^2 + 5*y^3 + O(y^6)

            sage: Q = LaurentSeriesRing(QQ, 'y')
            sage: z = Q([3,2,1,2]).add_bigoh(5); z
            3 + 2*y + y^2 + 2*y^3 + O(y^5)
            sage: P(z) + y**(1/2)
            3 + y^(1/2) + 2*y + y^2 + 2*y^3 + O(y^5)

            sage: from sage.modular.etaproducts import qexp_eta
            sage: y^(1/24)*qexp_eta(P, prec=30)
            y^(1/24) - y^(25/24) - y^(49/24) + y^(121/24) + y^(169/24) - y^(289/24) - y^(361/24) + y^(529/24) + y^(625/24) + O(y^(721/24))
        """
        P = parent(x)

        # 1. x is a Puiseux series belonging to this ring.
        #    This is short-circuited by the coercion framework.
        #if isinstance(x, self.element_class) and P is self:
        #    return x
        # 2. x is a Puiseux series but not an element of this ring. the laurent
        #    part should be coercible to the laurent series ring of self
        if isinstance(x, self.element_class):
            l = self._laurent_series_ring(x.laurent_part())
            e = x.ramification_index()
        # 3. x is a member of the base ring then convert x to a laurent series
        #    and set the ramification index of the Puiseux series to 1.
        elif P is self.base_ring():
            l = self._laurent_series_ring(x)
            e = 1
        # 4. x is a Laurent or power series with the same base ring
        elif (isinstance(x, (LaurentSeries, PowerSeries))
              and P is self.base_ring()):
            l = self._laurent_series_ring(x)
        # 5. everything else: try to coerce to laurent series ring
        else:
            l = self._laurent_series_ring(x)

        # finally, construct an instance of the element class and adding
        # the precision afterwards (see also :trac:`28993`).
        return self.element_class(self, l, e=e).add_bigoh(prec)
Exemple #42
0
    def __call__(self, *values):
        """
        Replace the generators of the free group by corresponding
        elements of the iterable ``values`` in the group element
        ``self``.

        INPUT:

        - ``*values`` -- a sequence of values, or a
          list/tuple/iterable of the same length as the number of
          generators of the free group.

        OUTPUT:

        The product of ``values`` in the order and with exponents
        specified by ``self``.

        EXAMPLES::

            sage: G.<a,b> = FreeGroup()
            sage: w = a^2 * b^-1 * a^3
            sage: w(1, 2)
            1/2
            sage: w(2, 1)
            32
            sage: w.subs(b=1, a=2)   # indirect doctest
            32

        TESTS::

            sage: w([1, 2])
            1/2
            sage: w((1, 2))
            1/2
            sage: w(i+1 for i in range(2))
            1/2

        Check that :trac:`25017` is fixed::

            sage: F = FreeGroup(2)
            sage: x0, x1 = F.gens()
            sage: u = F(1)
            sage: parent(u.subs({x1:x0})) is F
            True

            sage: F = FreeGroup(2)
            sage: x0, x1 = F.gens()
            sage: u = x0*x1
            sage: u.subs({x0:3, x1:2})
            6
            sage: u.subs({x0:1r, x1:2r})
            2
            sage: M0 = matrix(ZZ,2,[1,1,0,1])
            sage: M1 = matrix(ZZ,2,[1,0,1,1])
            sage: u.subs({x0: M0, x1: M1})
            [2 1]
            [1 1]

        TESTS::

            sage: F.<x,y> = FreeGroup()
            sage: F.one().subs(x=x, y=1)
            Traceback (most recent call last):
            ...
            TypeError: no common canonical parent for objects with parents: 'Free Group on generators {x, y}' and 'Integer Ring'
        """
        if len(values) == 1:
            try:
                values = list(values[0])
            except TypeError:
                pass
        G = self.parent()
        if len(values) != G.ngens():
            raise ValueError(
                'number of values has to match the number of generators')
        replace = dict(zip(G.gens(), values))
        new_parent = coercion_model.common_parent(*[parent(v) for v in values])
        try:
            return new_parent.prod(replace[gen]**power
                                   for gen, power in self.syllables())
        except AttributeError:
            return prod(
                new_parent(replace[gen])**power
                for gen, power in self.syllables())
Exemple #43
0
def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=None, use_sage_types=False):
    """
    A mutable list of elements with a common guaranteed universe,
    which can be set immutable.

    A universe is either an object that supports coercion (e.g., a
    parent), or a category.

    INPUT:

    - ``x`` - a list or tuple instance

    - ``universe`` - (default: None) the universe of elements; if None
      determined using canonical coercions and the entire list of
      elements.  If list is empty, is category Objects() of all
      objects.

    - ``check`` -- (default: True) whether to coerce the elements of x
      into the universe

    - ``immutable`` - (default: True) whether or not this sequence is
      immutable

    - ``cr`` - (default: False) if True, then print a carriage return
      after each comma when printing this sequence.

    - ``cr_str`` - (default: False) if True, then print a carriage return
      after each comma when calling ``str()`` on this sequence.

    - ``use_sage_types`` -- (default: False) if True, coerce the
       built-in Python numerical types int, long, float, complex to the
       corresponding Sage types (this makes functions like vector()
       more flexible)
    
    OUTPUT:

    - a sequence

    EXAMPLES::
    
        sage: v = Sequence(range(10))
        sage: v.universe()
        <type 'int'>
        sage: v
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    We can request that the built-in Python numerical types be coerced
    to Sage objects::
    
        sage: v = Sequence(range(10), use_sage_types=True)
        sage: v.universe()
        Integer Ring
        sage: v
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    You can also use seq for "Sequence", which is identical to using
    Sequence::
    
        sage: v = seq([1,2,1/1]); v
        [1, 2, 1]
        sage: v.universe()
        Rational Field
        sage: v.parent()
        Category of sequences in Rational Field
        sage: v.parent()([3,4/3])
        [3, 4/3]
        

    Note that assignment coerces if possible,::
    
        sage: v = Sequence(range(10), ZZ)
        sage: a = QQ(5)
        sage: v[3] = a
        sage: parent(v[3])
        Integer Ring
        sage: parent(a)
        Rational Field
        sage: v[3] = 2/3
        Traceback (most recent call last):
        ...
        TypeError: no conversion of this rational to integer

    Sequences can be used absolutely anywhere lists or tuples can be used::
    
        sage: isinstance(v, list)
        True

    Sequence can be immutable, so entries can't be changed::
    
        sage: v = Sequence([1,2,3], immutable=True)
        sage: v.is_immutable()
        True
        sage: v[0] = 5
        Traceback (most recent call last):
        ...
        ValueError: object is immutable; please change a copy instead.

    Only immutable sequences are hashable (unlike Python lists),
    though the hashing is potentially slow, since it first involves
    conversion of the sequence to a tuple, and returning the hash of
    that.::

        sage: v = Sequence(range(10), ZZ, immutable=True)
        sage: hash(v)
        1591723448             # 32-bit
        -4181190870548101704   # 64-bit


    If you really know what you are doing, you can circumvent the type
    checking (for an efficiency gain)::
    
        sage: list.__setitem__(v, int(1), 2/3)        # bad circumvention
        sage: v
        [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9]
        sage: list.__setitem__(v, int(1), int(2))     # not so bad circumvention

    You can make a sequence with a new universe from an old sequence.::
    
        sage: w = Sequence(v, QQ)
        sage: w
        [0, 2, 2, 3, 4, 5, 6, 7, 8, 9]
        sage: w.universe()
        Rational Field
        sage: w[1] = 2/3
        sage: w
        [0, 2/3, 2, 3, 4, 5, 6, 7, 8, 9]

    Sequences themselves live in a category, the category of all sequences
    in the given universe.::
    
        sage: w.category()
        Category of sequences in Rational Field
        
    This is also the parent of any sequence::
    
        sage: w.parent()
        Category of sequences in Rational Field

    The default universe for any sequence, if no compatible parent structure
    can be found, is the universe of all Sage objects.

    This example illustrates how every element of a list is taken into account
    when constructing a sequence.::
    
        sage: v = Sequence([1,7,6,GF(5)(3)]); v
        [1, 2, 1, 3]
        sage: v.universe()
        Finite Field of size 5
        sage: v.parent()
        Category of sequences in Finite Field of size 5
        sage: v.parent()([7,8,9])
        [2, 3, 4]
    """
    from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal


    if isinstance(x, Sequence_generic) and universe is None:
        universe = x.universe()
        x = list(x)

    if isinstance(x, MPolynomialIdeal) and universe is None:
        universe = x.ring()
        x = x.gens()

    if universe is None:
        if not isinstance(x, (list, tuple)):
            x = list(x)
            #raise TypeError("x must be a list or tuple")

        if len(x) == 0:
            import sage.categories.all
            universe = sage.categories.all.Objects()
        else:
            import sage.structure.element as coerce
            y = x
            x = list(x)   # make a copy, or we'd change the type of the elements of x, which would be bad.
            if use_sage_types:
                # convert any Python built-in numerical types to Sage objects
                from sage.rings.integer_ring import ZZ
                from sage.rings.real_double import RDF
                from sage.rings.complex_double import CDF
                for i in range(len(x)):
                    if isinstance(x[i], int) or isinstance(x[i], long):
                        x[i] = ZZ(x[i])
                    elif isinstance(x[i], float):
                        x[i] = RDF(x[i])
                    elif isinstance(x[i], complex):
                        x[i] = CDF(x[i])
            # start the pairwise coercion
            for i in range(len(x)-1):
                try:
                    x[i], x[i+1] = coerce.canonical_coercion(x[i],x[i+1])
                except TypeError:
                    import sage.categories.all
                    universe = sage.categories.all.Objects()
                    x = list(y)
                    check = False  # no point
                    break
            if universe is None:   # no type errors raised.
                universe = coerce.parent(x[len(x)-1])

    from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing
    from sage.rings.quotient_ring import is_QuotientRing
    from sage.rings.polynomial.pbori import BooleanMonomialMonoid

    if is_MPolynomialRing(universe) or \
            (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())) or \
            isinstance(universe, BooleanMonomialMonoid):
        from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
        try:
            return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str)
        except (TypeError,AttributeError):
            return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types)
    else:
        return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types)
Exemple #44
0
def q_binomial(n, k, q=None, algorithm='auto'):
    r"""
    Return the `q`-binomial coefficient.

    This is also known as the Gaussian binomial coefficient, and is defined by

    .. MATH::

        \binom{n}{k}_q = \frac{(1-q^n)(1-q^{n-1}) \cdots (1-q^{n-k+1})}
        {(1-q)(1-q^2)\cdots (1-q^k)}.

    See :wikipedia:`Gaussian_binomial_coefficient`.

    If `q` is unspecified, then the variable is the generator `q` for
    a univariate polynomial ring over the integers.

    INPUT:

    - ``n, k`` -- the values `n` and `k` defined above

    - ``q`` -- (default: ``None``) the variable `q`; if ``None``, then use a
      default variable in `\ZZ[q]`

    - ``algorithm`` -- (default: ``'auto'``) the algorithm to use and can be
      one of the following:

      - ``'auto'`` -- automatically choose the algorithm; see the algorithm
        section below
      - ``'naive'`` -- use the naive algorithm
      - ``'cyclotomic'`` -- use cyclotomic algorithm

    ALGORITHM:

    The naive algorithm uses the product formula. The cyclotomic
    algorithm uses a product of cyclotomic polynomials
    (cf. [CH2006]_).

    When the algorithm is set to ``'auto'``, we choose according to
    the following rules:

    - If ``q`` is a polynomial:

      When ``n`` is small or ``k`` is small with respect to ``n``, one
      uses the naive algorithm. When both ``n`` and ``k`` are big, one
      uses the cyclotomic algorithm.

    - If ``q`` is in the symbolic ring, one uses the cyclotomic algorithm.

    - Otherwise one uses the naive algorithm, unless ``q`` is a root of
      unity, then one uses the cyclotomic algorithm.

    EXAMPLES:

    By default, the variable is the generator of `\ZZ[q]`::

        sage: from sage.combinat.q_analogues import q_binomial
        sage: g = q_binomial(5,1) ; g
        q^4 + q^3 + q^2 + q + 1
        sage: g.parent()
        Univariate Polynomial Ring in q over Integer Ring

    The `q`-binomial coefficient vanishes unless `0 \leq k \leq n`::

        sage: q_binomial(4,5)
        0
        sage: q_binomial(5,-1)
        0

    Other variables can be used, given as third parameter::

        sage: p = ZZ['p'].gen()
        sage: q_binomial(4,2,p)
        p^4 + p^3 + 2*p^2 + p + 1

    The third parameter can also be arbitrary values::

        sage: q_binomial(5,1,2) == g.subs(q=2)
        True
        sage: q_binomial(5,1,1)
        5
        sage: q_binomial(4,2,-1)
        2
        sage: q_binomial(4,2,3.14)
        152.030056160000
        sage: R = GF(25, 't')
        sage: t = R.gen(0)
        sage: q_binomial(6, 3, t)
        2*t + 3

    We can also do this for more complicated objects such as matrices or
    symmetric functions::

        sage: q_binomial(4,2,matrix([[2,1],[-1,3]]))
        [ -6  84]
        [-84  78]
        sage: Sym = SymmetricFunctions(QQ)
        sage: s = Sym.schur()
        sage: q_binomial(4,1, s[2]+s[1])
        s[] + s[1] + s[1, 1] + s[1, 1, 1] + 2*s[2] + 4*s[2, 1] + 3*s[2, 1, 1]
         + 4*s[2, 2] + 3*s[2, 2, 1] + s[2, 2, 2] + 3*s[3] + 7*s[3, 1] + 3*s[3, 1, 1]
         + 6*s[3, 2] + 2*s[3, 2, 1] + s[3, 3] + 4*s[4] + 6*s[4, 1] + s[4, 1, 1]
         + 3*s[4, 2] + 3*s[5] + 2*s[5, 1] + s[6]

    TESTS:

    One checks that the first two arguments are integers::

        sage: q_binomial(1/2,1)
        Traceback (most recent call last):
        ...
        TypeError: no conversion of this rational to integer

    One checks that `n` is nonnegative::

        sage: q_binomial(-4,1)
        Traceback (most recent call last):
        ...
        ValueError: n must be nonnegative

    This also works for variables in the symbolic ring::

        sage: z = var('z')
        sage: factor(q_binomial(4,2,z))
        (z^2 + z + 1)*(z^2 + 1)

    This also works for complex roots of unity::

        sage: q_binomial(6, 1, QQbar(I))
        I + 1

    Note that the symbolic computation works (see :trac:`14982`)::

        sage: q_binomial(6, 1, I)
        I + 1

    Check that the algorithm does not matter::

        sage: q_binomial(6,3, algorithm='naive') == q_binomial(6,3, algorithm='cyclotomic')
        True

    One more test::

        sage: q_binomial(4, 2, Zmod(6)(2), algorithm='naive')
        5

    Check that it works with Python integer for ``q``::

        sage: q_binomial(3r, 2r, 1r)
        3

    REFERENCES:

    .. [CH2006] William Y.C. Chen and Qing-Hu Hou, *Factors of the Gaussian
       coefficients*, Discrete Mathematics 306 (2006), 1446-1449.
       :doi:`10.1016/j.disc.2006.03.031`

    AUTHORS:

    - Frederic Chapoton, David Joyner and William Stein
    """
    # sanity checks
    n = ZZ(n)
    k = ZZ(k)
    if n < 0:
        raise ValueError('n must be nonnegative')

    # polynomiality test
    if q is None:
        from sage.rings.polynomial.polynomial_ring import polygen
        q = polygen(ZZ, name='q')
        is_polynomial = True
    else:
        from sage.rings.polynomial.polynomial_element import Polynomial
        is_polynomial = isinstance(q, Polynomial)

    R = parent(q)
    try:
        zero = R.zero()
    except AttributeError:
        zero = R('0')
    try:
        one = R.one()
    except AttributeError:
        one = R('1')

    if not(0 <= k and k <= n):
        return zero

    k = min(n-k,k) # Pick the smallest k

    # heuristic choice of the fastest algorithm
    if algorithm == 'auto':
        from sage.symbolic.ring import SR
        if is_polynomial:
            if n <= 70 or k <= n // 4:
                algorithm = 'naive'
            else:
                algorithm = 'cyclo_polynomial'
        elif q in SR:
            algorithm = 'cyclo_generic'
        else:
            algorithm = 'naive'
    elif algorithm == 'cyclotomic':
        if is_polynomial:
            algorithm = 'cyclo_polynomial'
        else:
            algorithm = 'cyclo_generic'
    elif algorithm != 'naive':
        raise ValueError("invalid algorithm choice")

    # the algorithms
    if algorithm == 'naive':
        denom = prod(one - q**i for i in range(1, k+1))
        if not denom: # q is a root of unity, use the cyclotomic algorithm
            from sage.rings.polynomial.cyclotomic import cyclotomic_value
            return cyclotomic_value(n, k, q, algorithm='cyclotomic')
        else:
            num = prod(one - q**i for i in range(n-k+1, n+1))
            try:
                try:
                    return num // denom
                except TypeError:
                    return num / denom
            except (TypeError, ZeroDivisionError):
                # use substitution instead
                return q_binomial(n,k)(q)
    elif algorithm == 'cyclo_generic':
        from sage.rings.polynomial.cyclotomic import cyclotomic_value
        return prod(cyclotomic_value(d,q)
                    for d in range(2,n+1)
                    if (n//d) != (k//d) + ((n-k)//d))
    elif algorithm == 'cyclo_polynomial':
        return prod(R.cyclotomic_polynomial(d)
                    for d in range(2,n+1)
                    if (n//d) != (k//d) + ((n-k)//d))
Exemple #45
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``.

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

      * ``'polymake'``: use polymake
        (:mod:`~sage.geometry.polyhedron.backend_polymake`) with `\QQ`, `\RDF` or
        ``QuadraticField`` 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))

    When the input contains elements of a Number Field, they require an
    embedding::

        sage: K = NumberField(x^2-2,'s')
        sage: s = K.0
        sage: L = NumberField(x^3-2,'t')
        sage: t = L.0
        sage: P = Polyhedron(vertices = [[0,s],[t,0]])
        Traceback (most recent call last):
        ...
        ValueError: invalid base ring

    .. NOTE::

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

      * Although the option ``base_ring=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.


    TESTS:

    Check that giving ``float`` input gets converted to ``RDF`` (see :trac:`22605`)::

        sage: f = float(1.1)
        sage: Polyhedron(vertices=[[f]])
        A 0-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex

    Check that giving ``int`` input gets converted to ``ZZ`` (see :trac:`22605`)::

        sage: Polyhedron(vertices=[[int(42)]])
        A 0-dimensional polyhedron in ZZ^1 defined as the convex hull of 1 vertex

    Check that giving ``Fraction`` input gets converted to ``QQ`` (see :trac:`22605`)::

        sage: from fractions import Fraction
        sage: f = Fraction(int(6), int(8))
        sage: Polyhedron(vertices=[[f]])
        A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex

    Check that input with too many bits of precision returns an error (see
    :trac:`22552`)::

        sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), (6.4876921900819049, 4.8435898415984129)])
        Traceback (most recent call last):
        ...
        ValueError: for polyhedra with floating point numbers, the only allowed ring is RDF with backend 'cdd'
    
    Check that setting ``base_ring`` to a ``RealField`` returns an error (see :trac:`22552`)::
    
        sage: Polyhedron(vertices =[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40))
        Traceback (most recent call last):
        ...
        ValueError: no appropriate backend for computations with Real Field with 40 bits of precision
        sage: Polyhedron(vertices =[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53))
        Traceback (most recent call last):
        ...
        ValueError: no appropriate backend for computations with Real Field with 53 bits of precision
    """
    # 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('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
    from sage.structure.element import parent
    from sage.categories.all import Rings, Fields

    values = flatten(vertices + rays + lines + ieqs + eqns)
    if base_ring is not None:
        convert = any(parent(x) is not base_ring for x in values)
    elif not values:
        base_ring = ZZ
        convert = False
    else:
        P = parent(values[0])
        if any(parent(x) is not P for x in values):
            from sage.structure.sequence import Sequence
            P = Sequence(values).universe()
            convert = True
        else:
            convert = False

        from sage.structure.coerce import py_scalar_parent
        if isinstance(P, type):
            base_ring = py_scalar_parent(P)
            convert = convert or P is not base_ring
        else:
            base_ring = P

        if not got_Vrep and base_ring not in Fields():
            base_ring = base_ring.fraction_field()
            convert = True

        if base_ring not in Rings():
            raise ValueError('invalid base ring')

        if not base_ring.is_exact():
            # TODO: remove this hack?
            if base_ring is RR:
                base_ring = RDF
                convert = True
            elif base_ring is not RDF:
                raise ValueError(
                    "for polyhedra with floating point numbers, the only allowed ring is RDF with backend 'cdd'"
                )

    # Add the origin if necessary
    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)
Exemple #46
0
def q_jordan(t, q=None):
    r"""
    Return the `q`-Jordan number of `t`.

    If `q` is the power of a prime number, the output is the number of
    complete flags in `\GF{q}^N` (where `N` is the size of `t`) stable
    under a linear nilpotent endomorphism `f_t` whose Jordan type is
    given by `t`, i.e. such that for all `i`:

    .. MATH::

        \dim (\ker f_t^i) = t[0] + \cdots + t[i-1]

    If `q` is unspecified, then it defaults to using the generator `q` for
    a univariate polynomial ring over the integers.

    The result is cached.

    INPUT:

    -  ``t`` -- an integer partition, or an argument accepted by
       :class:`Partition`

    - ``q`` -- (default: ``None``) the variable `q`; if ``None``, then use a
      default variable in `\ZZ[q]`

    EXAMPLES::

        sage: from sage.combinat.q_analogues import q_jordan
        sage: [q_jordan(mu, 2) for mu in Partitions(5)]
        [9765, 1029, 213, 93, 29, 9, 1]
        sage: [q_jordan(mu, 2) for mu in Partitions(6)]
        [615195, 40635, 5643, 2331, 1491, 515, 147, 87, 47, 11, 1]
        sage: q_jordan([3,2,1])
        16*q^4 + 24*q^3 + 14*q^2 + 5*q + 1
        sage: q_jordan([2,1], x)
        2*x + 1

    If the partition is trivial (i.e. has only one part), we get
    the `q`-factorial (in this case, the nilpotent endomorphism is
    necessarily `0`)::

        sage: from sage.combinat.q_analogues import q_factorial
        sage: q_jordan([5]) == q_factorial(5)
        True
        sage: q_jordan([11], 5) == q_factorial(11, 5)
        True

    TESTS::

        sage: all(multinomial(mu.conjugate()) == q_jordan(mu, 1) for mu in Partitions(6))
        True

    AUTHOR:

    - Xavier Caruso (2012-06-29)
    """
    if q is None:
        q = ZZ['q'].gen()

    if all(part == 0 for part in t):
        return parent(q)(1)
    tj = 0
    res = parent(q)(0)
    for i in range(len(t) - 1, -1, -1):
        ti = t[i]
        if ti > tj:
            tp = list(t)
            tp[i] -= 1
            res += q_jordan(tp, q) * q**tj * q_int(ti - tj, q)
            tj = ti
    return res
Exemple #47
0
    def _element_constructor_(self, *args, **kwds):
        r"""
        TESTS::

            sage: from flatsurf.geometry.similarity import SimilarityGroup
            sage: S = SimilarityGroup(QQ)
            sage: S((1,1))  # translation
            (x, y) |-> (x + 1, y + 1)

            sage: V = QQ^2
            sage: S(V((1,-1)))
            (x, y) |-> (x + 1, y - 1)

            sage: S(vector((1,1)))
            (x, y) |-> (x + 1, y + 1)
        """
        if len(args) == 1:
            x = args[0]
        else:
            x = args

        a = self._ring.one()
        b = s = t = self._ring.zero()
        sign = ZZ_1

        # TODO: 2x2 and 3x3 matrix input

        if isinstance(x, (tuple, list)):
            if len(x) == 2:
                s, t = map(self._ring, x)
            elif len(x) == 4:
                a, b, s, t = map(self._ring, x)
            elif len(x) == 5:
                a, b, s, t = map(self._ring, x[:4])
                sign = ZZ(x[4])
            else:
                raise ValueError(
                    "can not construct a similarity from a list of length {}".
                    format(len(x)))
        elif is_Matrix(x):
            #   a -sb
            #   b sa
            if x.nrows() == x.ncols() == 2:
                a, c, b, d = x.list()
                if a == d and b == -c:
                    sign = ZZ_1
                elif a == -d and b == c:
                    sign = ZZ_m1
                else:
                    raise ValueError("not a similarity matrix")
            elif x.nrows() == x.ncols() == 3:
                raise NotImplementedError
            else:
                raise ValueError("invalid dimension for matrix input")
        elif isinstance(x, FreeModuleElement):
            if len(x) == 2:
                if x.base_ring() is self._ring:
                    s, t = x
                else:
                    s, t = map(self._ring, x)
            else:
                raise ValueError("invalid dimension for vector input")
        else:
            p = parent(x)
            if self._ring.has_coerce_map_from(p):
                a = self._ring(x)
            else:
                raise ValueError(
                    "element in %s cannot be used to create element in %s" %
                    (p, self))

        if (a * a + b * b).is_zero():
            raise ValueError("not invertible")

        return self.element_class(self, a, b, s, t, sign)
Exemple #48
0
 def n(x):
     if parent(x) is SR:
         return x.numerical_approx()
     else:
         return x
Exemple #49
0
    def __classcall_private__(cls, ogf):
        r"""
        Ensures that elements created by :class:`CFiniteSequence` have the same
        parent than the ones created by the parent itself and follow the category
        framework (they should be instance of :class:`CFiniteSequences` automatic
        element class).

        This method is called before the ``__init__`` method, it checks the
        o.g.f to create the appropriate parent.

        INPUT:

        - ``ogf`` -- a rational function

        TESTS::

            sage: f1 = CFiniteSequence((2-x)/(1-x-x^2))
            sage: f1
            C-finite sequence, generated by (x - 2)/(x^2 + x - 1)
            sage: C.<x> = CFiniteSequences(QQ)
            sage: f2 = CFiniteSequence((2-x)/(1-x-x^2))
            sage: f2
            C-finite sequence, generated by (x - 2)/(x^2 + x - 1)
            sage: f3 = C((2-x)/(1-x-x^2))
            sage: f3
            C-finite sequence, generated by (x - 2)/(x^2 + x - 1)
            sage: f1 == f2 and f2 == f3
            True
            sage: f1.parent() == f2.parent() and f2.parent() == f3.parent()
            True
            sage: type(f1)
            <class 'sage.rings.cfinite_sequence.CFiniteSequences_generic_with_category.element_class'>
            sage: type(f1) == type(f2) and type(f2) == type(f3)
            True
            sage: CFiniteSequence(log(x))
            Traceback (most recent call last):
            ...
            TypeError: unable to convert log(x) to a rational
            sage: CFiniteSequence(pi)
            Traceback (most recent call last):
            ...
            TypeError: unable to convert pi to a rational
            sage: var('y')
            y
            sage: f4 = CFiniteSequence((2-y)/(1-y-y^2))
            sage: f4
            C-finite sequence, generated by (y - 2)/(y^2 + y - 1)
            sage: f4 == f1
            False
            sage: f4.parent() == f1.parent()
            False
            sage: f4.parent()
            The ring of C-Finite sequences in y over Rational Field
        """

        br = ogf.base_ring()
        if not (br in (QQ, ZZ)):
            br = QQ  # if the base ring of the o.g.f is not QQ, we force it to QQ and see if the o.g.f converts nicely

        # trying to figure out the ogf variables
        variables = []
        if ogf not in br:
            if hasattr(ogf, 'variables'):
                variables = ogf.variables()
            elif hasattr(ogf.parent(), 'gens'):
                variables = ogf.parent().gens()
                # for some reason, fraction field elements don't have the variables
                # method, but symbolic elements don't have the gens method so we check both

        if not variables:
            parent = CFiniteSequences(
                QQ
            )  # if we cannot find variables, we create the default parent (with x)
        else:
            parent = CFiniteSequences(QQ, variables)
        return parent(
            ogf
        )  # if ogf cannot be converted to a fraction field, this will break and raise the proper error
Exemple #50
0
def q_pochhammer(n, a, q=None):
    r"""
    Return the `q`-Pochhammer `(a; q)_n`.

    The `q`-Pochhammer symbol is defined by

    .. MATH::

        (a; q)_n = \prod_{k=0}^{n-1} (1 - aq^k)

    with `(a; q)_0 = 1` for all `a, q` and `n \in \NN`.
    By using the identity

    .. MATH::

        (a; q)_n = \frac{(a; q)_{\infty}}{(aq^n; q)_{\infty}},

    we can extend the definition to `n < 0` by

    .. MATH::

        (a; q)_n = \frac{1}{(aq^n; q)_{-n}}
        = \prod_{k=1}^{-n} \frac{1}{1 - a/q^k}.

    EXAMPLES::

        sage: from sage.combinat.q_analogues import q_pochhammer
        sage: q_pochhammer(3, 1/7)
        6/343*q^3 - 6/49*q^2 - 6/49*q + 6/7
        sage: q_pochhammer(3, 3)
        -18*q^3 + 6*q^2 + 6*q - 2
        sage: q_pochhammer(3, 1)
        0

        sage: R.<q> = ZZ[]
        sage: q_pochhammer(4, q)
        q^10 - q^9 - q^8 + 2*q^5 - q^2 - q + 1
        sage: q_pochhammer(4, q^2)
        q^14 - q^12 - q^11 - q^10 + q^8 + 2*q^7 + q^6 - q^4 - q^3 - q^2 + 1
        sage: q_pochhammer(-3, q)
        1/(-q^9 + q^7 + q^6 + q^5 - q^4 - q^3 - q^2 + 1)

    TESTS::

        sage: q_pochhammer(0, 2)
        1
        sage: q_pochhammer(0, 1)
        1
        sage: q_pochhammer(0, var('a'))
        1

    We check that :trac:`25715` is fixed::

        sage: q_pochhammer(0, 3r)
        1

    REFERENCES:

    - :wikipedia:`Q-Pochhammer_symbol`
    """
    if q is None:
        q = ZZ['q'].gen()
    if n not in ZZ:
        raise ValueError("{} must be an integer".format(n))
    R = parent(q)
    one = R(1)
    if n < 0:
        return R.prod(one / (one - a / q**-k) for k in range(1, -n + 1))
    return R.prod((one - a * q**k) for k in range(n))
Exemple #51
0
def q_stirling_number1(n, k, q=None):
    r"""
    Return the (unsigned) `q`-Stirling number of the first kind.

    This is a `q`-analogue of :func:`sage.combinat.combinat.stirling_number1` .

    INPUT:

    - ``n``, ``k`` -- integers with ``1 <= k <= n``

    - ``q`` -- optional variable (default `q`)

    OUTPUT: a polynomial in the variable `q`

    These polynomials satisfy the recurrence

    .. MATH::

         s_{n,k} = s_{n-1,k-1} + [n-1]_q s_{n-1, k}.

    EXAMPLES::

        sage: from sage.combinat.q_analogues import q_stirling_number1
        sage: q_stirling_number1(4,2)
        q^3 + 3*q^2 + 4*q + 3

        sage: all(stirling_number1(6,k) == q_stirling_number1(6,k)(1)
        ....:     for k in range(1,7))
        True

        sage: x = polygen(QQ['q'],'x')
        sage: S = sum(q_stirling_number1(5,k)*x**k for k in range(1, 6))
        sage: factor(S)
        x * (x + 1) * (x + q + 1) * (x + q^2 + q + 1) * (x + q^3 + q^2 + q + 1)

    TESTS::

        sage: q_stirling_number1(-1,2)
        Traceback (most recent call last):
        ...
        ValueError: q-Stirling numbers are not defined for n < 0

    We check that :trac:`25715` is fixed::

        sage: q_stirling_number1(2,1,1r)
        1

    REFERENCES:

    - [Ca1948]_

    - [Ca1954]_
    """
    if q is None:
        q = ZZ['q'].gen()
    if n < 0:
        raise ValueError('q-Stirling numbers are not defined for n < 0')
    if n == 0 == k:
        return parent(q)(1)
    if k > n or k < 1:
        return parent(q)(0)
    return (q_stirling_number1(n - 1, k - 1, q=q) +
            q_int(n - 1, q=q) * q_stirling_number1(n - 1, k, q=q))
Exemple #52
0
def safe_ne(a, b):
    if parent(a) is not parent(b):
        logger.debug("comparing elements of %s and %s", parent(a), parent(b))
        return True
    else:
        return a != b
Exemple #53
0
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True):
    r"""
    Construct an elliptic curve.

    In Sage, an elliptic curve is always specified by its a-invariants

    .. math::

       y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.

    INPUT:

    There are several ways to construct an elliptic curve:

    - ``EllipticCurve([a1,a2,a3,a4,a6])``: Elliptic curve with given
      a-invariants. The invariants are coerced into the parent of the
      first element. If all are integers, they are coerced into the
      rational numbers.

    - ``EllipticCurve([a4,a6])``: Same as above, but `a_1=a_2=a_3=0`.

    - ``EllipticCurve(label)``: Returns the elliptic curve over Q from
      the Cremona database with the given label. The label is a
      string, such as ``"11a"`` or ``"37b2"``. The letters in the
      label *must* be lower case (Cremona's new labeling).

    - ``EllipticCurve(R, [a1,a2,a3,a4,a6])``: Create the elliptic
      curve over ``R`` with given a-invariants. Here ``R`` can be an
      arbitrary ring. Note that addition need not be defined.

    - ``EllipticCurve(j=j0)`` or ``EllipticCurve_from_j(j0)``: Return
      an elliptic curve with j-invariant ``j0``.

    - ``EllipticCurve(polynomial)``: Read off the a-invariants from
      the polynomial coefficients, see
      :func:`EllipticCurve_from_Weierstrass_polynomial`.

    In each case above where the input is a list of length 2 or 5, one
    can instead give a 2 or 5-tuple instead.

    EXAMPLES:

    We illustrate creating elliptic curves::

        sage: EllipticCurve([0,0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

    We create a curve from a Cremona label::

        sage: EllipticCurve('37b2')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
        sage: EllipticCurve('5077a')
        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
        sage: EllipticCurve('389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    Old Cremona labels are allowed::

        sage: EllipticCurve('2400FF')
        Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field

    Unicode labels are allowed::

        sage: EllipticCurve(u'389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    We create curves over a finite field as follows::

        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
        sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    "elliptic curve over a finite field"::

        sage: F = Zmod(101)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 101

    In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
    are of type "generic elliptic curve"::

        sage: F = Zmod(95)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 95

    The following is a curve over the complex numbers::

        sage: E = EllipticCurve(CC, [0,0,1,-1,0])
        sage: E
        Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
        sage: E.j_invariant()
        2988.97297297297

    We can also create elliptic curves by giving the Weierstrass equation::

        sage: x, y = var('x,y')
        sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field

        sage: R.<x,y> = GF(5)[]
        sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5

    We can explicitly specify the `j`-invariant::

        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
        1728
        '32a2'

        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
        2

    See :trac:`6657` ::

        sage: EllipticCurve(GF(144169),j=1728)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169

    By default, when a rational value of `j` is given, the constructed
    curve is a minimal twist (minimal conductor for curves with that
    `j`-invariant).  This can be changed by setting the optional
    parameter ``minimal_twist``, which is True by default, to False::


        sage: EllipticCurve(j=100)
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E =EllipticCurve(j=100); E
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E.conductor()
        33129800
        sage: E.j_invariant()
        100
        sage: E =EllipticCurve(j=100, minimal_twist=False); E
        Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
        sage: E.conductor()
        298168200
        sage: E.j_invariant()
        100

    Without this option, constructing the curve could take a long time
    since both `j` and `j-1728` have to be factored to compute the
    minimal twist (see :trac:`13100`)::

       sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False)
       sage: E.j_invariant() == 2^256+1
       True

    TESTS::

        sage: R = ZZ['u', 'v']
        sage: EllipticCurve(R, [1,1])
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
        over Integer Ring

    We create a curve and a point over QQbar (see #6879)::

        sage: E = EllipticCurve(QQbar,[0,1])
        sage: E(0)
        (0 : 1 : 0)
        sage: E.base_field()
        Algebraic Field

        sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: EllipticCurve(CC,[3,4]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
        Algebraic Field

    See :trac:`6657` ::

        sage: EllipticCurve(3,j=1728)
        Traceback (most recent call last):
        ...
        ValueError: First parameter (if present) must be a ring when j is specified

        sage: EllipticCurve(GF(5),j=3/5)
        Traceback (most recent call last):
        ...
        ValueError: First parameter must be a ring containing 3/5

    If the universe of the coefficients is a general field, the object
    constructed has type EllipticCurve_field.  Otherwise it is
    EllipticCurve_generic.  See :trac:`9816` ::

        sage: E = EllipticCurve([QQbar(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([RR(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([i,i]); E
        Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Symbolic Ring
        sage: SR in Fields()
        True

        sage: F = FractionField(PolynomialRing(QQ,'t'))
        sage: t = F.gen()
        sage: E = EllipticCurve([t,0]); E
        Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field

    See :trac:`12517`::

        sage: E = EllipticCurve([1..5])
        sage: EllipticCurve(E.a_invariants())
        Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field

    See :trac:`11773`::

        sage: E = EllipticCurve()
        Traceback (most recent call last):
        ...
        TypeError: invalid input to EllipticCurve constructor

    """
    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes

    if j is not None:
        if not x is None:
            if is_Ring(x):
                try:
                    j = x(j)
                except (ZeroDivisionError, ValueError, TypeError):
                    raise ValueError, "First parameter must be a ring containing %s" % j
            else:
                raise ValueError, "First parameter (if present) must be a ring when j is specified"
        return EllipticCurve_from_j(j, minimal_twist)

    if x is None:
        raise TypeError, "invalid input to EllipticCurve constructor"

    if is_SymbolicEquation(x):
        x = x.lhs() - x.rhs()

    if parent(x) is SR:
        x = x._polynomial_(rings.QQ['x', 'y'])

    if is_MPolynomial(x):
        if y is None:
            return EllipticCurve_from_Weierstrass_polynomial(x)
        else:
            return EllipticCurve_from_cubic(x, y, morphism=False)

    if is_Ring(x):
        if is_RationalField(x):
            return ell_rational_field.EllipticCurve_rational_field(x, y)
        elif is_FiniteField(x) or (is_IntegerModRing(x)
                                   and x.characteristic().is_prime()):
            return ell_finite_field.EllipticCurve_finite_field(x, y)
        elif rings.is_pAdicField(x):
            return ell_padic_field.EllipticCurve_padic_field(x, y)
        elif is_NumberField(x):
            return ell_number_field.EllipticCurve_number_field(x, y)
        elif x in _Fields:
            return ell_field.EllipticCurve_field(x, y)
        return ell_generic.EllipticCurve_generic(x, y)

    if isinstance(x, unicode):
        x = str(x)

    if isinstance(x, basestring):
        return ell_rational_field.EllipticCurve_rational_field(x)

    if is_RingElement(x) and y is None:
        raise TypeError, "invalid input to EllipticCurve constructor"

    if not isinstance(x, (list, tuple)):
        raise TypeError, "invalid input to EllipticCurve constructor"

    x = Sequence(x)
    if not (len(x) in [2, 5]):
        raise ValueError, "sequence of coefficients must have length 2 or 5"
    R = x.universe()

    if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):
        return ell_rational_field.EllipticCurve_rational_field(x, y)

    elif is_NumberField(R):
        return ell_number_field.EllipticCurve_number_field(x, y)

    elif rings.is_pAdicField(R):
        return ell_padic_field.EllipticCurve_padic_field(x, y)

    elif is_FiniteField(R) or (is_IntegerModRing(R)
                               and R.characteristic().is_prime()):
        return ell_finite_field.EllipticCurve_finite_field(x, y)

    elif R in _Fields:
        return ell_field.EllipticCurve_field(x, y)

    return ell_generic.EllipticCurve_generic(x, y)
Exemple #54
0
def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'):
    r"""
    Return the `q`-number of subgroups of type ``mu`` in a finite abelian
    group of type ``la``.

    INPUT:

    - ``la`` -- type of the ambient group as a :class:`Partition`
    - ``mu`` -- type of the subgroup as a :class:`Partition`
    - ``q`` -- (default: ``None``) an indeterminate or a prime number; if
      ``None``, this defaults to `q \in \ZZ[q]`
    - ``algorithm`` -- (default: ``'birkhoff'``) the algorithm to use can be
      one of the following:

      - ``'birkhoff`` -- use the Birkhoff formula from [Bu87]_
      - ``'delsarte'`` -- use the formula from [Delsarte48]_

    OUTPUT:

    The number of subgroups of type ``mu`` in a group of type ``la`` as a
    polynomial in ``q``.

    ALGORITHM:

    Let `q` be a prime number and `\lambda = (\lambda_1, \ldots, \lambda_l)`
    be a partition. A finite abelian `q`-group is of type `\lambda` if it
    is isomorphic to

    .. MATH::

        \ZZ / q^{\lambda_1} \ZZ \times \cdots \times \ZZ / q^{\lambda_l} \ZZ.

    The formula from [Bu87]_ works as follows:
    Let `\lambda` and `\mu` be partitions. Let `\lambda^{\prime}` and
    `\mu^{\prime}` denote the conjugate partitions to `\lambda` and `\mu`,
    respectively. The number of subgroups of type `\mu` in a group of type
    `\lambda` is given by

    .. MATH::

        \prod_{i=1}^{\mu_1} q^{\mu^{\prime}_{i+1}
        (\lambda^{\prime}_i - \mu^{\prime}_i)}
        \binom{\lambda^{\prime}_i - \mu^{\prime}_{i+1}}
        {\mu^{\prime}_i - \mu^{\prime}_{i+1}}_q

    The formula from [Delsarte48]_ works as follows:
    Let `\lambda` and `\mu` be partitions. Let `(s_1, s_2, \ldots, s_l)`
    and `(r_1, r_2, \ldots, r_k)` denote the parts of the partitions
    conjugate to `\lambda` and `\mu` respectively. Let


    .. MATH::

        \mathfrak{F}(\xi_1, \ldots, \xi_k) = \xi_1^{r_2} \xi_2^{r_3} \cdots
        \xi_{k-1}^{r_k} \prod_{i_1=r_2}^{r_1-1} (\xi_1-q^{i_1})
        \prod_{i_2=r_3}^{r_2-1} (\xi_2-q^{i_2}) \cdots
        \prod_{i_k=0}^{r_k-1} (\xi_k-q^{-i_k}).

    Then the number of subgroups of type `\mu` in a group of type `\lambda`
    is given by

    .. MATH::

        \frac{\mathfrak{F}(q^{s_1}, q^{s_2}, \ldots, q^{s_k})}{\mathfrak{F}
        (q^{r_1}, q^{r_2}, \ldots, q^{r_k})}.

    EXAMPLES::

        sage: from sage.combinat.q_analogues import q_subgroups_of_abelian_group
        sage: q_subgroups_of_abelian_group([1,1], [1])
        q + 1
        sage: q_subgroups_of_abelian_group([3,3,2,1], [2,1])
        q^6 + 2*q^5 + 3*q^4 + 2*q^3 + q^2
        sage: R.<t> = QQ[]
        sage: q_subgroups_of_abelian_group([5,3,1], [3,1], t)
        t^4 + 2*t^3 + t^2
        sage: q_subgroups_of_abelian_group([5,3,1], [3,1], 3)
        144
        sage: q_subgroups_of_abelian_group([1,1,1], [1]) == q_subgroups_of_abelian_group([1,1,1], [1,1])
        True
        sage: q_subgroups_of_abelian_group([5], [3])
        1
        sage: q_subgroups_of_abelian_group([1], [2])
        0
        sage: q_subgroups_of_abelian_group([2], [1,1])
        0

    TESTS:

    Check the same examples with ``algorithm='delsarte'``::

        sage: q_subgroups_of_abelian_group([1,1], [1], algorithm='delsarte')
        q + 1
        sage: q_subgroups_of_abelian_group([3,3,2,1], [2,1], algorithm='delsarte')
        q^6 + 2*q^5 + 3*q^4 + 2*q^3 + q^2
        sage: q_subgroups_of_abelian_group([5,3,1], [3,1], t, algorithm='delsarte')
        t^4 + 2*t^3 + t^2
        sage: q_subgroups_of_abelian_group([5,3,1], [3,1], 3, algorithm='delsarte')
        144
        sage: q_subgroups_of_abelian_group([1,1,1], [1], algorithm='delsarte') == q_subgroups_of_abelian_group([1,1,1], [1,1])
        True
        sage: q_subgroups_of_abelian_group([5], [3], algorithm='delsarte')
        1
        sage: q_subgroups_of_abelian_group([1], [2], algorithm='delsarte')
        0
        sage: q_subgroups_of_abelian_group([2], [1,1], algorithm='delsarte')
        0

    Check that :trac:`25715` is fixed::

        sage: parent(q_subgroups_of_abelian_group([2], [1], algorithm='delsarte'))
        Univariate Polynomial Ring in q over Integer Ring
        sage: q_subgroups_of_abelian_group([7,7,1], [])
        1
        sage: q_subgroups_of_abelian_group([7,7,1], [0,0])
        1

    REFERENCES:

    .. [Bu87] Butler, Lynne M. *A unimodality result in the enumeration
       of subgroups of a finite abelian group.* Proceedings of the American
       Mathematical Society 101, no. 4 (1987): 771-775.
       :doi:`10.1090/S0002-9939-1987-0911049-8`

    .. [Delsarte48] \S. Delsarte, *Fonctions de Möbius Sur Les Groupes Abeliens
       Finis*, Annals of Mathematics, second series, Vol. 45, No. 3, (Jul 1948),
       pp. 600-609. http://www.jstor.org/stable/1969047

    AUTHORS:

    - Amritanshu Prasad (2013-06-07): Implemented the Delsarte algorithm
    - Tomer Bauer (2013, 2018): Implemented the Birkhoff algorithm and refactoring
    """
    if q is None:
        q = ZZ['q'].gen()
    la_c = _Partitions(la).conjugate()
    mu_c = _Partitions(mu).conjugate()
    k = mu_c.length()
    if not mu_c:
        # There is only one trivial subgroup
        return parent(q)(1)
    if not la_c.contains(mu_c):
        return parent(q)(0)

    if algorithm == 'delsarte':

        def F(args):
            prd = lambda j: prod(args[j] - q**i
                                 for i in range(mu_c[j + 1], mu_c[j]))
            F1 = prod(args[i]**mu_c[i + 1] * prd(i) for i in range(k - 1))
            return F1 * prod(args[k - 1] - q**i for i in range(mu_c[k - 1]))

        return F([q**ss for ss in la_c[:k]]) // F([q**rr for rr in mu_c])

    if algorithm == 'birkhoff':
        fac1 = q**(sum(mu_c[i + 1] * (la_c[i] - mu_c[i])
                       for i in range(k - 1)))
        fac2 = prod(
            q_binomial(la_c[i] - mu_c[i + 1], mu_c[i] - mu_c[i + 1], q=q)
            for i in range(k - 1))
        fac3 = q_binomial(la_c[k - 1], mu_c[k - 1], q=q)

        return prod([fac1, fac2, fac3])

    raise ValueError("invalid algorithm choice")
Exemple #55
0
        def _element_constructor_(self, element):
            """
            Coerce ``element`` into ``self``

            INPUT:

            - ``element`` -- any object

            This default implementation returns ``element`` if
            ``self`` is a facade for ``parent(element)`. Otherwise it
            attempts in turn to coerce ``element`` into each parent
            ``self`` is a facade for.

            This implementation is only valid for a facade parent
            which models the full union of the parents it is a facade
            for. Other facade parents should redefine
            :meth:`element_constructor` appropriately.

            EXAMPLES::

                sage: S = Sets().Facade().example("union"); S
                An example of a facade set: the integers completed by +-infinity
                sage: S(1)
                1
                sage: S(1/2)
                Traceback (most recent call last):
                ...
                ValueError: Can't coerce `1/2` in any parent `An example of a facade set: the integers completed by +-infinity` is a facade for
                sage: S(2/1)
                2
                sage: S(2/1).parent()
                Integer Ring
                sage: S(int(1))
                1
                sage: S(int(1)).parent()
                Integer Ring

            Facade parents that model strict subsets should redefine
            :meth:`element_constructor`::

                sage: S = Sets().Facade().example(); S
                An example of facade set: the monoid of positive integers
                sage: S(-1)
                Traceback (most recent call last):
                ...
                ValueError: %s should be positive
            """
            if self.is_parent_of(element):
                return element
            else:
                parents = self.facade_for()
                if parents is True:
                    raise NotImplementedError
                for parent in self.facade_for():
                    try:
                        return parent(element)
                    except Exception:
                        pass
            raise ValueError(
                "Can't coerce `%s` in any parent `%s` is a facade for" %
                (element, self))
Exemple #56
0
    def _element_constructor_(self, x=None, valuation=None, degree=None, constant=None, coefficients=None):
        r"""
        Construct a lazy series from ``x``.

        INPUT:

        - ``x`` -- data used to the define a series
        - ``valuation`` -- integer (optional); integer; a lower bound for
          the valuation of the series
        - ``degree`` -- (optional) the degree when the series is ``constant``
        - ``constant`` -- (optional) the eventual constant of the series
        - ``coefficients`` -- (optional) a callable that defines the
          coefficients of the series; must be ``None`` if ``x`` is provided;
          see note below

        If ``valuation`` is specified and ``x`` is convertible into
        an element of the underlying ring corresponding to series
        with finite support or ``x`` is a lazy series of the same
        parent, then the data is shifted so that the result has the
        specified valuation.

        .. WARNING::

            If ``valuation`` is specified and ``x`` is a lazy series, then
            the valuation will be computed. If the series ``x`` is not
            known to be zero, then this will run forever.

        .. NOTE::

            When working over a base ring that takes callables as valid
            input, then passing a function as ``x`` might be converted to
            the base ring. If instead the input is to be treated as the
            function giving the coefficients of the lazy series being
            constructed, then use the ``coefficients`` argument in this
            case and do not provide ``x``.

        .. WARNING::

            Polynomials, but also :class:`LazyLaurentSeries` and
            :class:`LazyDirichletSeries` are callable.  Therefore, an
            argument ``x`` which is not convertible into an element
            of the underlying ring corresponding to series with
            finite support is interpreted as a function providing the
            coefficients when evaluated at integers.  Examples are
            provided below.

        EXAMPLES::

            sage: L = LazyLaurentSeriesRing(GF(2), 'z')
            sage: L(2)
            0
            sage: L(3)
            1

            sage: L.<z> = LazyLaurentSeriesRing(ZZ)

            sage: L(lambda i: i, valuation=5, constant=1, degree=10)
            5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
            sage: L(lambda i: i, valuation=5, constant=(1, 10))
            5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)

            sage: X = L(constant=5, degree=2); X
            5*z^2 + 5*z^3 + 5*z^4 + O(z^5)
            sage: X.valuation()
            2

            sage: def g(i):
            ....:     if i < 0:
            ....:         return 1
            ....:     else:
            ....:         return 1 + sum(k for k in range(i+1))
            sage: e = L(g, valuation=-5); e
            z^-5 + z^-4 + z^-3 + z^-2 + z^-1 + 1 + 2*z + O(z^2)
            sage: f = e^-1; f
            z^5 - z^6 - z^11 + O(z^12)
            sage: f.coefficient(10)
            0
            sage: f[20]
            9
            sage: f[30]
            -219

            sage: L(valuation=2, constant=1)
            z^2 + z^3 + z^4 + O(z^5)
            sage: L(constant=1)
            Traceback (most recent call last):
            ...
            ValueError: you must specify the degree for the polynomial 0

        Alternatively, ``x`` can be a list of elements of the base ring.
        Then these elements are read as coefficients of the terms of
        degrees starting from the ``valuation``. In this case, ``constant``
        may be just an element of the base ring instead of a tuple or can be
        simply omitted if it is zero::

            sage: f = L([1,2,3,4], valuation=-5)
            sage: f
            z^-5 + 2*z^-4 + 3*z^-3 + 4*z^-2
            sage: g = L([1,3,5,7,9], valuation=5, constant=-1)
            sage: g
            z^5 + 3*z^6 + 5*z^7 + 7*z^8 + 9*z^9 - z^10 - z^11 - z^12 + O(z^13)

        Finally, ``x`` can be a Laurent polynomial::

            sage: P.<x> = LaurentPolynomialRing(QQ)
            sage: p = x^-2 + 3*x^3
            sage: L.<x> = LazyLaurentSeriesRing(ZZ)
            sage: L(p)
            x^-2 + 3*x^3

            sage: L(p, valuation=0)
            1 + 3*x^5

            sage: L(p, valuation=1)
            x + 3*x^6

        We construct a lazy Laurent series over another lazy Laurent series::

            sage: R.<s> = LazyLaurentSeriesRing(QQ)
            sage: L.<z> = LazyLaurentSeriesRing(R)
            sage: e = L(lambda n: 1/factorial(n), 0); e
            1 + z + 1/2*z^2 + 1/6*z^3 + 1/24*z^4 + 1/120*z^5 + 1/720*z^6 + O(z^7)
            sage: L(lambda n: 1/(1 + s^n), 0)
            1/2 + (1 - s + s^2 - s^3 + s^4 - s^5 + s^6 + O(s^7))*z
             + (1 - s^2 + s^4 - s^6 + O(s^7))*z^2
             + (1 - s^3 + s^6 + O(s^7))*z^3 + (1 - s^4 + O(s^7))*z^4
             + (1 - s^5 + O(s^7))*z^5 + (1 - s^6 + O(s^7))*z^6 + O(z^7)

        We note that ``e`` builds correctly because ``R`` additionally
        requires the valuation to be specified.

        In the next example the argument is interpreted as a constant
        polynomial, which happens to be a Dirichlet series::

            sage: D = LazyDirichletSeriesRing(QQ, "s")
            sage: L.<z> = LazyLaurentSeriesRing(D)
            sage: L(lambda n: 1/factorial(n), valuation=0)
            (1 + 1/2/2^s + 1/6/3^s + 1/24/4^s + 1/120/5^s + 1/720/6^s + 1/5040/7^s + O(1/(8^s)))

        We can also specify that the given function should be
        interpreted as the coefficients of the Laurent series::

            sage: L(coefficients=lambda n: 1/factorial(n), valuation=0)
            1 + z + 1/2*z^2 + 1/6*z^3 + 1/24*z^4 + 1/120*z^5 + 1/720*z^6 + O(z^7)

        When the argument ``x`` is callable and not convertible into
        an element of the underlying ring of series of finite
        support, it is evaluated at integers to compute the
        coefficients::

            sage: R.<q> = QQ[]
            sage: D = LazyDirichletSeriesRing(ZZ, 't')
            sage: D(1+2*q)
            3 + 5/2^t + 7/3^t + 9/4^t + 11/5^t + 13/6^t + 15/7^t + O(1/(8^t))

        In this example, the Dirichlet series ``m`` is considered as an
        element in the base ring::

            sage: m = D(moebius)
            sage: s = L(m, valuation=0)
            sage: s[0]
            1 - 1/(2^s) - 1/(3^s) - 1/(5^s) + 1/(6^s) - 1/(7^s) + O(1/(8^s))
            sage: s[1]
            0

        TESTS:

        Checking the valuation is consistent::

            sage: L.<z> = LazyLaurentSeriesRing(ZZ)
            sage: L([0,0,2,3], valuation=-4)
            2*z^-4 + 3*z^-3
            sage: L(range(5), valuation=-4)
            z^-4 + 2*z^-3 + 3*z^-2 + 4*z^-1
            sage: P.<x> = ZZ[]
            sage: L(x^2 + x^5, valuation=-4)
            z^-4 + z^-1
            sage: L(1, valuation=-4)
            z^-4
            sage: L(L(1), valuation=-4)
            z^-4
            sage: L(1/(1-z), valuation=-4)
            z^-4 + z^-3 + z^-2 + z^-1 + 1 + z + z^2 + O(z^3)
            sage: L(z^-3/(1-z), valuation=-4)
            z^-4 + z^-3 + z^-2 + z^-1 + 1 + z + z^2 + O(z^3)
            sage: L(z^3/(1-z), valuation=-4)
            z^-4 + z^-3 + z^-2 + z^-1 + 1 + z + z^2 + O(z^3)

            sage: L(z^3/(1-z), valuation=0)
            1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + O(z^7)

            sage: L = LazyLaurentSeriesRing(ZZ, 'z')
            sage: L(lambda n: 1/(n+1), degree=3)
            Traceback (most recent call last):
            ...
            ValueError: the valuation must be specified

            sage: L(5, valuation=3.1)
            Traceback (most recent call last):
            ...
            ValueError: the valuation must be an integer

            sage: L(5, valuation=6/2)
            5*z^3

        Checking that series are not interpreted as coefficients when
        they can be interpreted as series::

            sage: P.<s> = ZZ[]
            sage: L.<z> = LazyLaurentSeriesRing(ZZ)
            sage: M.<w> = LazyLaurentSeriesRing(QQ)
            sage: L(M(s^2 + s^5), valuation=-4)
            z^-4 + z^-1

            sage: D = LazyDirichletSeriesRing(ZZ, "s")
            sage: E = LazyDirichletSeriesRing(QQ, "t")
            sage: D(E([1,2,3]))
            1 + 2/2^s + 3/3^s

        This gives zero::

            sage: L = LazyLaurentSeriesRing(ZZ, 'z')
            sage: L(lambda n: 0, degree=3, valuation=0)
            0
            sage: L(L.zero(), degree=3)
            0
            sage: L(L.zero(), degree=3, valuation=2)
            0
            sage: L(L.zero(), degree=3, constant=0)
            0
            sage: L(L.zero(), degree=3, valuation=2, constant=0)
            0

        This does not::

            sage: L(lambda n: 0, degree=3, constant=1, valuation=0)
            z^3 + z^4 + z^5 + O(z^6)
            sage: L(L.zero(), degree=-3, constant=1)
            z^-3 + z^-2 + z^-1 + O(1)
            sage: L(L.zero(), valuation=2, constant=1)
            z^2 + z^3 + z^4 + O(z^5)

        This raises an error::

            sage: L(lambda n: 0, valuation=3, constant=1)
            Traceback (most recent call last):
            ...
            ValueError: constant may only be specified if the degree is specified

        We support the old input format for ``constant``::

            sage: f = L(lambda i: i, valuation=-3, constant=-1, degree=3)
            sage: g = L(lambda i: i, valuation=-3, constant=(-1,3))
            sage: f == g
            True
            sage: g = L(lambda i: i, -3, (-1,3))
            sage: f == g
            True

        .. TODO::

            Add a method to change the sparse/dense implementation.

        """
        if valuation is not None and valuation not in ZZ:
            raise ValueError("the valuation must be an integer")

        if x is None and coefficients is None:
            if valuation is None:
                raise ValueError("the valuation must be specified")
            return self.element_class(self, Stream_uninitialized(self._sparse, valuation))

        if coefficients is not None and (x is not None and (not isinstance(x, int) or x)):
            raise ValueError("coefficients must be None if x is provided")

        BR = self.base_ring()
        if isinstance(constant, (tuple, list)):
            constant, degree = constant
        if isinstance(degree, (tuple, list)):
            constant, degree = degree
        if constant is not None:
            constant = BR(constant)

        if coefficients is None:
            # Try to build stuff using the internal polynomial ring constructor
            R = self._internal_poly_ring
            try:
                x = R(x)
            except (TypeError, ValueError):
                pass

            # If x has been converted to the internal polynomial ring
            if parent(x) is R:
                if not x and not constant:
                    return self.zero()
                if x and valuation is not None:
                    x = x.shift(valuation - x.valuation())
                if degree is None and not x:
                    if valuation is None:
                        raise ValueError("you must specify the degree for the polynomial 0")
                    degree = valuation
                if x == R.zero():
                    coeff_stream = Stream_exact([], self._sparse, order=degree, constant=constant)
                    return self.element_class(self, coeff_stream)
                initial_coefficients = [x[i] for i in range(x.valuation(), x.degree() + 1)]
                coeff_stream = Stream_exact(initial_coefficients, self._sparse,
                                            order=x.valuation(), constant=constant, degree=degree)
                return self.element_class(self, coeff_stream)

            # Handle when it is a lazy series
            if isinstance(x, self.Element):
                if x._coeff_stream._is_sparse is not self._sparse:
                    # TODO: Implement a way to make a self._sparse copy
                    raise NotImplementedError("cannot convert between sparse and dense")

                # If x is known to be 0
                if isinstance(x._coeff_stream, Stream_zero):
                    if not constant:
                        if self is parent(x):
                            return x
                        return self.element_class(self, x._coeff_stream)
                    if degree is None:
                        if valuation is None:
                            raise ValueError("you must specify the degree for the polynomial 0")
                        degree = valuation
                    coeff_stream = Stream_exact([], self._sparse, order=degree,
                                                constant=constant)
                    return self.element_class(self, coeff_stream)

                # Make the result exact
                if degree is not None:
                    # truncate the series and then possibly make constant
                    x_val = x._coeff_stream.order()
                    if not valuation:
                        valuation = x_val
                    initial_coefficients = [x[x_val+i] for i in range(degree-valuation)]
                    if not any(initial_coefficients):
                        if not constant:
                            return self.zero()
                        # We learned some stuff about x; pass it along
                        x._coeff_stream._approximate_order += len(initial_coefficients)
                        initial_coefficients = []
                    coeff_stream = Stream_exact(initial_coefficients, self._sparse,
                                                order=valuation, constant=constant, degree=degree)
                    return self.element_class(self, coeff_stream)

                # We are just possibly shifting the result
                ret = self.element_class(self, x._coeff_stream)
                if valuation is None:
                    return ret
                return ret.shift(valuation - x._coeff_stream.order())

        else:
            x = coefficients

        if callable(x):
            if valuation is None:
                raise ValueError("the valuation must be specified")
            if degree is None:
                if constant is not None:
                    raise ValueError("constant may only be specified if the degree is specified")
                coeff_stream = Stream_function(x, self.base_ring(), self._sparse, valuation)
                return self.element_class(self, coeff_stream)

            # degree is not None
            if constant is None:
                constant = BR.zero()
            p = [BR(x(i)) for i in range(valuation, degree)]
            if not any(p) and not constant:
                return self.zero()
            coeff_stream = Stream_exact(p, self._sparse, order=valuation,
                                        constant=constant, degree=degree)
            return self.element_class(self, coeff_stream)

        raise ValueError(f"unable to convert {x} into {self}")
Exemple #57
0
    def create_key_and_extra_args(self,
                                  x=None,
                                  y=None,
                                  j=None,
                                  minimal_twist=True,
                                  **kwds):
        """
        Return a ``UniqueFactory`` key and possibly extra parameters.

        INPUT:

        See the documentation for :class:`EllipticCurveFactory`.

        OUTPUT:

        A pair ``(key, extra_args)``:

        - ``key`` has the form `(R, (a_1, a_2, a_3, a_4, a_6))`,
          representing a ring and the Weierstrass coefficients of an
          elliptic curve over that ring;

        - ``extra_args`` is a dictionary containing additional data to
          be inserted into the elliptic curve structure.

        EXAMPLES::

            sage: EllipticCurve.create_key_and_extra_args(j=8000)
            ((Rational Field, (0, -1, 0, -3, -1)), {})

        When constructing a curve over `\\QQ` from a Cremona or LMFDB
        label, the invariants from the database are returned as
        ``extra_args``::

            sage: key, data = EllipticCurve.create_key_and_extra_args('389.a1')
            sage: key
            (Rational Field, (0, 1, 1, -2, 0))
            sage: data['conductor']
            389
            sage: data['cremona_label']
            '389a1'
            sage: data['lmfdb_label']
            '389.a1'
            sage: data['rank']
            2
            sage: data['torsion_order']
            1

        User-specified keywords are also included in ``extra_args``::

            sage: key, data = EllipticCurve.create_key_and_extra_args((0, 0, 1, -23737, 960366), rank=4)
            sage: data['rank']
            4

        Furthermore, keywords takes precedence over data from the
        database, which can be used to specify an alternative set of
        generators for the Mordell-Weil group::

            sage: key, data = EllipticCurve.create_key_and_extra_args('5077a1', gens=[[1, -1], [-2, 3], [4, -7]])
            sage: data['gens']
            [[1, -1], [-2, 3], [4, -7]]
            sage: E = EllipticCurve.create_object(0, key, **data)
            sage: E.gens()
            [(-2 : 3 : 1), (1 : -1 : 1), (4 : -7 : 1)]

        Note that elliptic curves are equal if and only they have the
        same base ring and Weierstrass equation; the data in
        ``extra_args`` do not influence comparison of elliptic curves.
        A consequence of this is that passing keyword arguments only
        works when constructing an elliptic curve the first time::

            sage: E = EllipticCurve('433a1', gens=[[-1, 1], [3, 4]])
            sage: E.gens()
            [(-1 : 1 : 1), (3 : 4 : 1)]
            sage: E = EllipticCurve('433a1', gens=[[-1, 0], [0, 1]])
            sage: E.gens()
            [(-1 : 1 : 1), (3 : 4 : 1)]

        .. WARNING::

            Manually specifying extra data is almost never necessary
            and is not guaranteed to have any effect, as the above
            example shows.  Almost no checking is done, so specifying
            incorrect data may lead to wrong results of computations
            instead of errors or warnings.

        """
        R = None
        if is_Ring(x):
            (R, x) = (x, y)

        if j is not None:
            if R is not None:
                try:
                    j = R(j)
                except (ZeroDivisionError, ValueError, TypeError):
                    raise ValueError(
                        "First parameter must be a ring containing %s" % j)
            elif x is not None:
                raise ValueError(
                    "First parameter (if present) must be a ring when j is specified"
                )
            x = coefficients_from_j(j, minimal_twist)

        if is_SymbolicEquation(x):
            x = x.lhs() - x.rhs()

        if parent(x) is SR:
            x = x._polynomial_(rings.QQ['x', 'y'])

        if is_MPolynomial(x):
            if y is None:
                x = coefficients_from_Weierstrass_polynomial(x)
            else:
                x = coefficients_from_cubic(x, y, morphism=False)

        if isinstance(x, string_types):
            # Interpret x as a Cremona or LMFDB label.
            from sage.databases.cremona import CremonaDatabase
            x, data = CremonaDatabase().coefficients_and_data(x)
            # User-provided keywords may override database entries.
            data.update(kwds)
            kwds = data

        if not isinstance(x, (list, tuple)):
            raise TypeError("invalid input to EllipticCurve constructor")

        if len(x) == 2:
            x = (0, 0, 0, x[0], x[1])
        elif len(x) != 5:
            raise ValueError(
                "sequence of coefficients must have length 2 or 5")

        if R is None:
            R = Sequence(x).universe()
            if R in (rings.ZZ, ) + integer_types:
                R = rings.QQ

        return (R, tuple(R(a) for a in x)), kwds
Exemple #58
0
def _check_parents(a, b):
    # comparison between different parent may be okay if the elements are
    # instances of the same class (e.g., balls with different precisions)
    if parent(a) is not parent(b) and type(a) is not type(b):
        raise TypeError("unsafe comparison", parent(a), parent(b))
Exemple #59
0
    def _element_constructor_(self, x, mon=None):
        """
        EXAMPLES::

            sage: L = LaurentPolynomialRing(QQ,2,'x')
            sage: L(1/2)
            1/2

            sage: M = LaurentPolynomialRing(QQ, 'x, y')
            sage: var('x, y')
            (x, y)
            sage: M(x/y + 3/x)
            x*y^-1 + 3*x^-1

        ::

            sage: M(exp(x))
            Traceback (most recent call last):
            ...
            TypeError: unable to convert e^x to a rational

        ::

            sage: L.<a, b, c, d> = LaurentPolynomialRing(QQ)
            sage: M = LaurentPolynomialRing(QQ, 'c, d')
            sage: Mc, Md = M.gens()
            sage: N = LaurentPolynomialRing(M, 'a, b')
            sage: Na, Nb = N.gens()
            sage: M(c/d)
            c*d^-1
            sage: N(a*b/c/d)
            (c^-1*d^-1)*a*b
            sage: N(c/d)
            c*d^-1
            sage: L(Mc)
            c
            sage: L(Nb)
            b

            sage: M(L(0))
            0
            sage: N(L(0))
            0
            sage: L(M(0))
            0
            sage: L(N(0))
            0

            sage: U = LaurentPolynomialRing(QQ, 'a')
            sage: Ua = U.gen()
            sage: V = LaurentPolynomialRing(QQ, 'c')
            sage: Vc = V.gen()
            sage: L(Ua)
            a
            sage: L(Vc)
            c
            sage: N(Ua)
            a
            sage: M(Vc)
            c

            sage: P = LaurentPolynomialRing(QQ, 'a, b')
            sage: Q = LaurentPolynomialRing(P, 'c, d')
            sage: Q(P.0)
            a

        ::

            sage: A.<a> = LaurentPolynomialRing(QQ)
            sage: B.<b> = LaurentPolynomialRing(A)
            sage: C = LaurentPolynomialRing(QQ, 'a, b')
            sage: C(B({1: a}))
            a*b
            sage: D.<d, e> = LaurentPolynomialRing(B)
            sage: F.<f, g> = LaurentPolynomialRing(D)
            sage: D(F(d*e))
            d*e

        ::

            sage: from sage.rings.polynomial.polydict import ETuple
            sage: R.<x,y,z> = LaurentPolynomialRing(QQ)
            sage: mon = ETuple({}, int(3))
            sage: P = R.polynomial_ring()
            sage: R(sum(P.gens()), mon)
            x + y + z
            sage: R(sum(P.gens()), (-1,-1,-1))
            y^-1*z^-1 + x^-1*z^-1 + x^-1*y^-1
        """
        from sage.symbolic.expression import Expression
        element_class = LaurentPolynomial_mpair

        if mon is not None:
            return element_class(self, x, mon)

        P = parent(x)
        if P is self.polynomial_ring():
            from sage.rings.polynomial.polydict import ETuple
            return element_class(self, x, mon=ETuple({}, int(self.ngens())))

        elif isinstance(x, Expression):
            return x.laurent_polynomial(ring=self)

        elif isinstance(
                x, (LaurentPolynomial_univariate, LaurentPolynomial_mpair)):
            if self.variable_names() == P.variable_names():
                # No special processing needed here;
                #   handled by LaurentPolynomial_mpair.__init__
                pass
            elif set(self.variable_names()) & set(P.variable_names()):
                if isinstance(x, LaurentPolynomial_univariate):
                    d = {(k, ): v for k, v in iteritems(x.dict())}
                else:
                    d = x.dict()
                x = _split_laurent_polynomial_dict_(self, P, d)
            elif self.base_ring().has_coerce_map_from(P):
                from sage.rings.polynomial.polydict import ETuple
                mz = ETuple({}, int(self.ngens()))
                return element_class(self, {mz: self.base_ring()(x)}, mz)
            elif x.is_constant() and self.has_coerce_map_from(P.base_ring()):
                return self(x.constant_coefficient())
            elif len(self.variable_names()) == len(P.variable_names()):
                x = x.dict()

        return element_class(self, x)
Exemple #60
0
def safe_eq(a, b):
    if parent(a) is not parent(b):
        logger.debug("comparing elements of %s and %s", parent(a), parent(b))
        return False
    else:
        return a == b