Exemplo n.º 1
0
    def xseries(self, all_conjugates=True):
        r"""Returns the corresponding x-series.

        Parameters
        ----------
        all_conjugates : bool
            (default: True) If ``True``, returns all conjugates
            x-representations of this Puiseux t-series. If ``False``,
            only returns one representative.

        Returns
        -------
        list
            List of PuiseuxXSeries representations of this PuiseuxTSeries.

        """
        # obtain relevant rings:
        #   o R = parent ring of curve
        #   o L = parent ring of T-series
        #   o S = temporary polynomial ring over base ring of T-series
        #   o P = Puiseux series ring
        L = self.ypart.parent()
        t = L.gen()
        S = L.base_ring()['z']
        z = S.gen()

        R = self.f.parent()
        x,y = R.gens()
        P = PuiseuxSeriesRing(L.base_ring(), str(x))
        x = P.gen()

        # given x = alpha + lambda*t^e solve for t. this involves finding an
        # e-th root of either (1/lambda) or of lambda, depending on e's sign
        ## (A sign on a ramification index ? hm)
        e = self.ramification_index
        abse = abs(e)
        lamb = S(self.xcoefficient)
        order = self.order
        if e > 0:
            phi = lamb*z**e - 1
        else:
            phi = z**abse - lamb
        mu = phi.roots(QQbar, multiplicities=False)[0]

        if all_conjugates:
            zeta_e=QQbar.zeta(abse)
            conjugates = [mu*zeta_e**k for k in range(abse)]
        else:
            conjugates = [mu]
        map(lambda x: x.exactify(), conjugates)

        # determine the resulting x-series
        xseries = []
        for c in conjugates:
            t = self.ypart.parent().gen()
            fconj = self.ypart(c*t)
            p = P(fconj(x**(QQ(1)/e)))
            p = p.add_bigoh(QQ(order+1)/abse)
            xseries.append(p)
        return xseries
Exemplo n.º 2
0
def braid_in_segment(f, x0, x1):
    """
    Return the braid formed by the `y` roots of ``f`` when `x` moves
    from ``x0`` to ``x1``.

    INPUT:

    - ``f`` -- a polynomial in two variables
    - ``x0`` -- a complex number
    - ``x1`` -- a complex number

    OUTPUT:

    A braid.

    EXAMPLES::

        sage: from sage.schemes.curves.zariski_vankampen import braid_in_segment # optional - sirocco
        sage: R.<x,y> = QQ[]
        sage: f = x^2 + y^3
        sage: x0 = CC(1,0)
        sage: x1 = CC(1, 0.5)
        sage: braid_in_segment(f, x0, x1) # optional - sirocco
        s1
    """
    CC = ComplexField(64)
    (x, y) = f.variables()
    I = QQbar.gen()
    X0 = QQ(x0.real()) + I*QQ(x0.imag())
    X1 = QQ(x1.real()) + I*QQ(x1.imag())
    F0 = QQbar[y](f(X0, y))
    y0s = F0.roots(multiplicities=False)
    strands = [followstrand(f, x0, x1, CC(a)) for a in y0s]
    complexstrands = [[(a[0], CC(a[1], a[2])) for a in b] for b in strands]
    centralbraid = braid_from_piecewise(complexstrands)
    initialstrands = []
    y0aps = [c[0][1] for c in complexstrands]
    used = []
    for y0ap in y0aps:
        distances = [((y0ap - y0).norm(), y0) for y0 in y0s]
        y0 = sorted(distances)[0][1]
        if y0 in used:
            raise ValueError("different roots are too close")
        used.append(y0)
        initialstrands.append([(0, CC(y0)), (1, y0ap)])
    initialbraid = braid_from_piecewise(initialstrands)
    F1 = QQbar[y](f(X1,y))
    y1s = F1.roots(multiplicities=False)
    finalstrands = []
    y1aps = [c[-1][1] for c in complexstrands]
    used = []
    for y1ap in y1aps:
        distances = [((y1ap - y1).norm(), y1) for y1 in y1s]
        y1 = sorted(distances)[0][1]
        if y1 in used:
            raise ValueError("different roots are too close")
        used.append(y1)
        finalstrands.append([(0, y1ap), (1, CC(y1))])
    finallbraid = braid_from_piecewise(finalstrands)
    return initialbraid * centralbraid * finallbraid
Exemplo n.º 3
0
    def __init__(self, parent, x, prec=None, dx=[], dx_mode='linear_combination', valuation=None, check=True, reduce=True):
        r"""
        TESTS::

            sage: R = ZpLC(2)
            sage: x = R(1, 10)  # indirect doctest
            sage: x
            1 + O(2^10)
        """
        self._parent = parent
        p = parent.prime()
        pAdicGenericElement.__init__(self, parent)
        self._precision = parent.precision()
        if check:
            if isinstance(x, pAdicGenericElement):
                if parent.prime() != x.parent().prime():
                    raise TypeError("conversion between different p-adic rings/fields not supported")
                if prec is None:
                    prec = x.precision_absolute()
                else:
                    prec = min(prec, x.precision_absolute())
            x = QQ(x)
        if isinstance(x, pRational):
            self._value = x
        else:
            self._value = pRational(p, QQ(x))
        trunc = self._declare_new_element(dx, prec, dx_mode)
        if reduce:
            self._value = self._value.reduce(trunc)
Exemplo n.º 4
0
    def _richcmp_(self, other, op):
        r"""
        Compare this element with ``other``.

        TESTS::

            sage: R = ZpLC(2)
            sage: x = R(1, 5)
            sage: y = R(128, 10)
            sage: z = x + y

            sage: x
            1 + O(2^5)
            sage: z
            1 + O(2^5)

            sage: x == z   # Indirect doctest
            False
            sage: z - x
            2^7 + O(2^10)
        """
        if (self - other).is_zero():
            return rich_to_bool(op, 0)
        else:
            return richcmp(QQ(self.lift()), QQ(other.lift()), op)
Exemplo n.º 5
0
    def orbital_angular_velocity(self, r, retrograde=False):
        r"""
        Return the angular velocity on a circular orbit.

        The angular velocity `\Omega` on a circular orbit of Boyer-Lindquist
        radial coordinate `r` around a Kerr black hole of parameters `(m, a)`
        is given by the formula

        .. MATH::
           :label: Omega

            \Omega := \frac{\mathrm{d}\phi}{\mathrm{d}t}
                    = \pm \frac{m^{1/2}}{r^{3/2} \pm a m^{1/2}}

        where `(t,\phi)` are the Boyer-Lindquist time and azimuthal coordinates
        and `\pm` is `+` (resp. `-`) for a prograde (resp. retrograde) orbit.

        INPUT:

        - ``r`` -- Boyer-Lindquist radial coordinate `r` of the circular orbit
        - ``retrograde`` -- (default: ``False``) boolean determining whether
          the orbit is retrograde or prograde

        OUTPUT:

        - Angular velocity `\Omega` computed according to Eq. :eq:`Omega`

        EXAMPLES::

            sage: from kerrgeodesic_gw import KerrBH
            sage: a, m, r = var('a m r')
            sage: BH = KerrBH(a, m)
            sage: BH.orbital_angular_velocity(r)
            sqrt(m)/(a*sqrt(m) + r^(3/2))
            sage: BH.orbital_angular_velocity(r, retrograde=True)
            sqrt(m)/(a*sqrt(m) - r^(3/2))
            sage: KerrBH(0.9).orbital_angular_velocity(4.)  # tol 1.0e-13
            0.112359550561798

        Orbital angular velocity around a Schwarzschild black hole::

            sage: KerrBH(0, m).orbital_angular_velocity(r)
            sqrt(m)/r^(3/2)

        Orbital angular velocity on the prograde ISCO of an extreme Kerr
        black hole (`a=m`)::

            sage: EKBH = KerrBH(m, m)
            sage: EKBH.orbital_angular_velocity(EKBH.isco_radius())
            1/2/m

        """
        m = self._m
        a = self._a
        # Eq. (2.16) in Bardeen, Press & Teukolsky, ApJ 178, 347 (1972)
        three_halves = QQ(3) / QQ(2)
        sm = sqrt(m)
        if retrograde:
            return -sm / (r**three_halves - a * sm)
        return sm / (r**three_halves + a * sm)
Exemplo n.º 6
0
def demo3():
    s = SimilaritySurfaceGenerators.right_angle_triangle(QQ(3), QQ(4))
    sm, sb = s.get_bundle()
    sm.set_surface(sb)
    globals()['s'] = s
    globals()['sb'] = sb
    globals()['sm'] = sm
Exemplo n.º 7
0
    def __init__(self, R):
        """
        Initialize self.

        TESTS::

            sage: V = lie_conformal_algebras.N2(QQ)
            sage: TestSuite(V).run()
        """
        n2dict =\
        {('L','L'):{0:{('L',1):1}, 1:{('L',0): 2},
        3:{('C', 0):R(2).inverse_of_unit()}},
        ('L','G1'):{0:{('G1',1):1}, 1:{('G1',0):3*R(2).\
        inverse_of_unit()}},
        ('L','G2'):{0:{('G2',1):1}, 1:{('G2',0):3*R(2).\
        inverse_of_unit()}},
        ('G1','G2'): {0:{('L',0):1,('J',1):R(2).inverse_of_unit()},
                   1:{('J',0):1}, 2:{('C',0):R(3).inverse_of_unit()}},
        ('L','J'): {0:{('J',1):1},1:{('J',0):1}},
        ('J','J'): {1:{('C',0):R(3).inverse_of_unit()}},
        ('J','G1'): {0:{('G1',0):1}},
        ('J','G2'): {0:{('G2',0):-1}}}
        from sage.rings.rational_field import QQ
        weights = (2, 1, QQ(3 / 2), QQ(3 / 2))
        parity = (0, 0, 1, 1)
        GradedLieConformalAlgebra.__init__(self,
                                           R,
                                           n2dict,
                                           names=('L', 'J', 'G1', 'G2'),
                                           central_elements=('C', ),
                                           weights=weights,
                                           parity=parity)
Exemplo n.º 8
0
def is_hyperbolic(self, p):
    """
    Checks if the quadratic form is a sum of hyperbolic planes over
    the p-adic numbers Q_p.

    REFERENCES:

        This criteria follows from Cassels's "Rational Quadratic Forms":
            - local invariants for hyperbolic plane (Lemma 2.4, p58)
            - direct sum formulas (Lemma 2.3 on p58)

    INPUT:

        `p` -- a prime number > 0

    OUTPUT:

        boolean

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
        sage: Q.is_hyperbolic("infinity")
        False
        sage: Q.is_hyperbolic(2)
        False
        sage: Q.is_hyperbolic(3)
        False
        sage: Q.is_hyperbolic(5)     ## Here -1 is a square, so it's true.
        True
        sage: Q.is_hyperbolic(7)
        False
        sage: Q.is_hyperbolic(13)    ## Here -1 is a square, so it's true.
        True

    """
    ## False for odd-dim'l forms
    if self.dim() % 2 != 0:
        return False

    ## True for the zero form
    if self.dim == 0:
        return True

    ## Compare local invariants
    ## (Note: since the dimension is even, the extra powers of 2 in
    ##        self.det() := Det(2*Q) don't affect the answer!)
    m = ZZ(self.dim() // 2)
    if p == "infinity":
        return (self.signature() == 0)

    elif p == 2:
        return QQ(self.det() * (-1)**m).is_padic_square(p) and (
            self.hasse_invariant(p) == (-1)**m
        )  ## Actually, this -1 is the Hilbert symbol (-1,-1)_p

    else:
        return QQ(self.det() *
                  (-1)**m).is_padic_square(p) and (self.hasse_invariant(p)
                                                   == 1)
Exemplo n.º 9
0
    def zoom_screen_box(self, x1, y1, x2, y2):
        r"""
        Scale picture by a factor fixing the point (xc,yc) in screen coordinates
        - ``factor`` -- rational scaling factor

        - ``xc`` -- rational or integer point in screen coordinates
        - ``yc`` -- rational or integer point in screen coordinates
        """
        width = x2 - x1
        height = y2 - y1
        screen_width = self._editor.get_width()
        screen_height = self._editor.get_height()
        width_change = QQ(screen_width) / width
        height_change = QQ(screen_height) / height
        # Commenting this line out seems to have solved the label loss issue:
        #self.before_zoom_change()

        # proposed scale change:
        scale_change = min(width_change, height_change)
        new_scale = self._s * scale_change

        screen_center = self._editor.get_center()
        vertex1 = self.screen_to_math_coordinates(x1, y1)
        vertex2 = self.screen_to_math_coordinates(x2, y2)
        math_center_x = (vertex1[0] + vertex2[0]) / 2
        math_center_y = (vertex1[1] + vertex2[1]) / 2
        tx = screen_center[0] - (new_scale * math_center_x)
        ty = screen_center[1] + (new_scale * math_center_y)
        self.set_transform(new_scale, tx, ty)
Exemplo n.º 10
0
def test_add_commutes(trials, verbose=False):
    r"""
    This is a simple demonstration of the :func:`random_testing` decorator and
    its recommended usage.

    We test that addition is commutative over rationals.

    EXAMPLES::

        sage: from sage.misc.random_testing import test_add_commutes
        sage: test_add_commutes(2, verbose=True, seed=0)
        a == -4, b == 0 ...
        Passes!
        a == -1/2, b == -1/95 ...
        Passes!
        sage: test_add_commutes(10)
        sage: test_add_commutes(1000) # long time
    """
    from sage.rings.rational_field import QQ
    for _ in range(trials):
        a = QQ.random_element()
        b = QQ.random_element()
        if verbose:
            print("a == {}, b == {} ...".format(a, b))
        assert (a + b == b + a)
        if verbose:
            print("Passes!")
Exemplo n.º 11
0
 def set_transform(self, s, tx, ty):
     r"""
     Set the parts of the transformation which convert to screen coordinates.
     """
     s = QQ(s)
     tx = QQ(tx)
     ty = QQ(ty)
     ratio = self._s / s
     if (ratio > QQ(999) / 1000) and (ratio < QQ(1001) / 1000):
         # ignore negligible change in scale!
         self._editor.get_canvas().move(ALL, RDF(tx - self._tx),
                                        RDF(ty - self._ty))
         self._tx = self._field(tx)
         self._ty = self._field(ty)
     else:
         self.before_zoom_change()
         scale = 1 / ratio
         offset_x = ((self._s * tx) - (self._tx * s)) / (self._s - s)
         offset_y = ((self._s * ty) - (self._ty * s)) / (self._s - s)
         self._editor.get_canvas().scale(ALL, RDF(offset_x), RDF(offset_y),
                                         RDF(scale), RDF(scale))
         self._s = self._field(s)
         self._tx = self._field(tx)
         self._ty = self._field(ty)
         self.after_zoom_change()
Exemplo n.º 12
0
def strict_inequality_symmetric_choice(k, left, right):
    r"""
    TESTS::

        sage: from partitioner import strict_inequality_symmetric_choice
        sage: S = Set(srange(5))
        sage: for s in S.subsets():
        ....:     L = tuple(s)
        ....:     R = tuple(S.difference(s))
        ....:     a = strict_inequality_symmetric_choice(5, L, R)
        ....:     b = strict_inequality_symmetric_choice(5, R, L)
        ....:     assert a != b

        sage: strict_inequality_symmetric_choice(1, [], [0])
        True
    """
    from sage.rings.rational_field import QQ

    assert not set(left) & set(right)
    center = QQ(k - 1) / QQ(2)
    def weight(t):
        return -(center + 1 - (t-center).abs())
    def total(T):
        return sum(weight(t) for t in T)
    def rule(T):
        return total(T), sorted((weight(t), t) for t in T)
    return rule(left) > rule(right)
Exemplo n.º 13
0
def cyclotomic_to_alpha(cyclo):
    """
    Convert a list of indices of cyclotomic polynomials
    to a list of rational numbers.

    The input represents a product of cyclotomic polynomials.

    The output is the list of arguments of the roots of the
    given product of cyclotomic polynomials.

    This is the inverse of :func:`alpha_to_cyclotomic`.

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import cyclotomic_to_alpha
        sage: cyclotomic_to_alpha([1])
        [0]
        sage: cyclotomic_to_alpha([2])
        [1/2]
        sage: cyclotomic_to_alpha([5])
        [1/5, 2/5, 3/5, 4/5]
        sage: cyclotomic_to_alpha([1,2,3,6])
        [0, 1/6, 1/3, 1/2, 2/3, 5/6]
        sage: cyclotomic_to_alpha([2,3])
        [1/3, 1/2, 2/3]
    """
    alpha = []
    for d in cyclo:
        if d == 1:
            alpha.append(QQ.zero())
        else:
            for k in ZZ(d).coprime_integers(d):
                alpha.append(QQ((k, d)))
    return sorted(alpha)
Exemplo n.º 14
0
    def _cmp_(self, other):
        r"""
        Compare this element with ``other``.

        TESTS::

            sage: R = ZpLC(2)
            sage: x = R(1, 5)
            sage: y = R(128, 10)
            sage: z = x + y

            sage: x
            1 + O(2^5)
            sage: z
            1 + O(2^5)

            sage: x == z   # Indirect doctest
            False
            sage: z - x
            2^7 + O(2^10)
        """
        if (self - other).is_zero():
            return 0
        else:
            return QQ(self.lift())._cmp_(QQ(other.lift()))
def is_hyperbolic(self, p):
    r"""
    Check if the quadratic form is a sum of hyperbolic planes over
    the `p`-adic numbers `\QQ_p` or over the real numbers `\RR`.

    REFERENCES:

    This criteria follows from Cassels's "Rational Quadratic Forms":

    - local invariants for hyperbolic plane (Lemma 2.4, p58)
    - direct sum formulas (Lemma 2.3, p58)

    INPUT:

    - `p` -- a prime number > 0 or `-1` for the infinite place

    OUTPUT:

    boolean

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1])
        sage: Q.is_hyperbolic(-1)
        False
        sage: Q.is_hyperbolic(2)
        False
        sage: Q.is_hyperbolic(3)
        False
        sage: Q.is_hyperbolic(5)     ## Here -1 is a square, so it's true.
        True
        sage: Q.is_hyperbolic(7)
        False
        sage: Q.is_hyperbolic(13)    ## Here -1 is a square, so it's true.
        True
    """
    ## False for odd-dim'l forms
    if self.dim() % 2:
        return False

    ## True for the zero form
    if not self.dim():
        return True

    ## Compare local invariants
    ## Note: since the dimension is even, the extra powers of 2 in
    ##        self.det() := Det(2*Q) don't affect the answer!
    m = ZZ(self.dim() // 2)
    if p == -1:
        return self.signature() == 0

    if p == 2:
        return (QQ(self.det() * (-1)**m).is_padic_square(p)
                and self.hasse_invariant(p) == (-1)**m.binomial(2)
                )  # here -1 is hilbert_symbol(-1,-1,2)

    return (QQ(self.det() * (-1)**m).is_padic_square(p)
            and self.hasse_invariant(p) == 1)
Exemplo n.º 16
0
    def __init__(self, f, x0, singular_data, order=None):
        r"""Initialize a PuiseuxTSeries using a set of :math:`\pi = \{\tau\}`
        data.

        Parameters
        ----------
        f, x, y : polynomial
            A plane algebraic curve.
        x0 : complex
            The x-center of the Puiseux series expansion.
        singular_data : list
            The output of :func:`singular`.
        t : variable
            The variable in which the Puiseux t series is represented.

        """
        R = f.parent()
        x, y = R.gens()
        extension_polynomial, xpart, ypart = singular_data
        L = LaurentSeriesRing(ypart.base_ring(), 't')
        t = L.gen()

        self.f = f
        self.t = t
        self._xpart = xpart
        self._ypart = ypart

        # store x-part attributes. handle the centered at infinity case
        self.x0 = x0
        if x0 == infinity:
            x0 = QQ(0)
        self.center = x0

        # extract and store information about the x-part of the puiseux series
        xpart = xpart(t, 0)
        xpartshift = xpart - x0
        ramification_index, xcoefficient = xpartshift.laurent_polynomial(
        ).dict().popitem()
        self.xcoefficient = xcoefficient
        self.ramification_index = QQ(ramification_index).numerator()
        self.xpart = xpart

        # extract and store information about the y-part of the puiseux series
        self.ypart = L(ypart(t, 0))
        self._initialize_extension(extension_polynomial)

        # determine the initial order. See the order property
        val = L(ypart(t, O(t))).prec()
        self._singular_order = 0 if val == infinity else val
        self._regular_order = self._p.degree(x)

        # extend to have at least two elements
        self.extend(nterms=1)

        # the curve, x-part, and terms output by puiseux make the puiseux
        # series unique. any mutability only adds terms
        self.__parent = self.ypart.parent()
        self._hash = hash((self.f, self.xpart, self.ypart))
def local_density(self, p, m):
    """
    Gives the local density -- should be called by the user. =)

    NOTE: This screens for imprimitive forms, and puts the quadratic
    form in local normal form, which is a *requirement* of the
    routines performing the computations!

    INPUT:

        `p` -- a prime number > 0
        `m` -- an integer

    OUTPUT:

        a rational number

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])   ## NOTE: This is already in local normal form for *all* primes p!
        sage: Q.local_density(p=2, m=1)
        1
        sage: Q.local_density(p=3, m=1)
        8/9
        sage: Q.local_density(p=5, m=1)
        24/25
        sage: Q.local_density(p=7, m=1)
        48/49
        sage: Q.local_density(p=11, m=1)
        120/121

    """
    n = self.dim()
    if (n == 0):
        raise TypeError("Oops!  We currently don't handle 0-dim'l forms. =(")

    ## Find the local normal form and p-scale of Q     --  Note: This uses the valuation ordering of local_normal_form.
    ##                                                     TO DO:  Write a separate p-scale and p-norm routines!
    Q_local = self.local_normal_form(p)
    if n == 1:
        p_valuation = valuation(Q_local[0, 0], p)
    else:
        p_valuation = min(valuation(Q_local[0, 0], p),
                          valuation(Q_local[0, 1], p))

    ## If m is less p-divisible than the matrix, return zero
    if (
        (m != 0) and (valuation(m, p) < p_valuation)
    ):  ## Note: The (m != 0) condition protects taking the valuation of zero.
        return QQ(0)

    ## If the form is imprimitive, rescale it and call the local density routine
    p_adjustment = QQ(1) / p**p_valuation
    m_prim = QQ(m) / p**p_valuation
    Q_prim = Q_local.scale_by_factor(p_adjustment)

    ## Return the densities for the reduced problem
    return Q_prim.local_density_congruence(p, m_prim)
Exemplo n.º 18
0
 def single_right_click(self, event):
     from sage.rings.rational_field import QQ
     x = self._editor.get_canvas().canvasx(event.x)
     y = self._editor.get_canvas().canvasy(event.y)
     bundle=self._editor.get_surface_bundle()
     if bundle is None:
         pass
     else:
         bundle.zoom(QQ(7)/QQ(8),x,y)
Exemplo n.º 19
0
def gamma__exact(n):
    """
    Evaluates the exact value of the gamma function at an integer or
    half-integer argument.

    EXAMPLES::

        sage: gamma__exact(4)
        6
        sage: gamma__exact(3)
        2
        sage: gamma__exact(2)
        1
        sage: gamma__exact(1)
        1

        sage: gamma__exact(1/2)
        sqrt(pi)
        sage: gamma__exact(3/2)
        1/2*sqrt(pi)
        sage: gamma__exact(5/2)
        3/4*sqrt(pi)
        sage: gamma__exact(7/2)
        15/8*sqrt(pi)

        sage: gamma__exact(-1/2)
        -2*sqrt(pi)
        sage: gamma__exact(-3/2)
        4/3*sqrt(pi)
        sage: gamma__exact(-5/2)
        -8/15*sqrt(pi)
        sage: gamma__exact(-7/2)
        16/105*sqrt(pi)

    """
    from sage.all import sqrt
    ## SANITY CHECK
    if (not n in QQ) or (denominator(n) > 2):
        raise TypeError, "Oops!  You much give an integer or half-integer argument."

    if (denominator(n) == 1):
        if n <= 0:
            return infinity
        if n > 0:
            return factorial(n - 1)
    else:
        ans = QQ(1)
        while (n != QQ(1) / 2):
            if (n < 0):
                ans *= QQ(1) / n
                n = n + 1
            elif (n > 0):
                n = n - 1
                ans *= n

        ans *= sqrt(pi)
        return ans
Exemplo n.º 20
0
    def test_cuberoot(self):
        # recenter cuberoot(x) at x+1
        G = (y + 1)**3 - (x + 1)
        S = newton_iteration(G, 9).truncate(x, 10) + 1

        z = var('z')
        series = taylor(z**(QQ(1) / QQ(3)), z, 1, 9)
        series = R(series.subs({z: x + 1}))
        self.assertEqual(S, series)
Exemplo n.º 21
0
def corrected_voronoi_diagram(points):
    r"""
    Compute a Voronoi diagram of a set of points with rational coordinates, such
    that the given points are granted to lie one in each bounded region.

    INPUT:

    - ``points`` -- a list of complex numbers

    OUTPUT:

    A VoronoiDiagram constructed from rational approximations of the points,
    with the guarantee that each bounded region contains exactly one of the
    input points.

    EXAMPLES::

        sage: from sage.schemes.curves.zariski_vankampen import corrected_voronoi_diagram
        sage: points = (2, I, 0.000001, 0, 0.000001*I)
        sage: V = corrected_voronoi_diagram(points)
        sage: V
        The Voronoi diagram of 9 points of dimension 2 in the Rational Field
        sage: V.regions()
        {P(-7, 0): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices and 2 rays,
        P(0, -7): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices and 2 rays,
        P(0, 0): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices,
        P(0, 1): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 5 vertices,
        P(0, 1/1000000): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices,
        P(0, 7): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 2 rays,
        P(1/1000000, 0): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 5 vertices,
        P(2, 0): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 5 vertices,
        P(7, 0): A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays}

    """
    prec = 53
    point_coordinates = [(p.real(), p.imag()) for p in points]
    while True:
        RF = RealField(prec)
        apprpoints = {(QQ(RF(p[0])), QQ(RF(p[1]))): p
                      for p in point_coordinates}
        added_points = 3 * max(map(abs, flatten(apprpoints))) + 1
        configuration = list(apprpoints.keys()) + [(added_points, 0),
                                                   (-added_points, 0),
                                                   (0, added_points),
                                                   (0, -added_points)]
        V = VoronoiDiagram(configuration)
        valid = True
        for r in V.regions().items():
            if not r[1].rays() and not r[1].interior_contains(
                    apprpoints[r[0].affine()]):
                prec += 53
                valid = False
                break
        if valid:
            break
    return V
Exemplo n.º 22
0
def newton_data(H, exceptional=False):
    r"""Determines the "newton data" associated with each side of the polygon.

    For each side :math:`\Delta` of the Newton polygon of `H` we
    associate the data :math:`(q,m,l,`phi)` where

    .. math::

        \Delta: qj + mi = l \\
        \phi_{\Delta}(t) = \sum_{(i,j) \in \Delta} a_{ij} t^{(i-i_0)/q}

    Here, :math:`a_ij x^j y_i` is a term in the polynomial :math:`H` and
    :math:`i_0` is the smallest value of :math:`i` belonging to the
    polygon side :math:`\Delta`.

    Parameters
    ----------
    H : sympy.Poly
        Polynomial in `x` and `y`.

    Returns
    -------
    list
        A list of the tuples :math:`(q,m,l,\phi)`.
    """
    R = H.parent()
    x, y = R.gens()

    if exceptional:
        newton = newton_polygon_exceptional(H)
    else:
        newton = newton_polygon(H)

    # special case when the newton polygon is a single point
    if len(newton[0]) == 1:
        return []

    # for each side dtermine the corresponding newton data: side slope
    # information and corresponding side characteristic polynomial, phi
    result = []
    for side in newton:
        i0, j0 = side[0]
        i1, j1 = side[1]
        slope = QQ(j1 - j0) / QQ(i1 - i0)
        q = slope.denom()
        m = -slope.numer()
        l = min(q * j0 + m * i0, q * j1 + m * i1)
        phi = sum(
            H.coefficient({
                y: i,
                x: j
            }) * x**((i - i0) / q) for i, j in side)
        phi = phi.univariate_polynomial()
        result.append((q, m, l, phi))
    return result
Exemplo n.º 23
0
    def construct_from_file(cls, polyfile):
        """
        Construct an RNAPolytope from a file in polyfile format.

        Keyword arguments:
        polyfile -- A file representing the polytope structure
        """

        filebase = os.path.splitext(polyfile)[0]

        # Construct the polytope
        try:
            # If the polytope is available in a pickle, we should use that
            thepoly = load(
                filebase)  # Attempt to load the polytope from a pickle file

            # If the pickled polytope is obsolete, however, we need to rebuild it
            if cls.poly_is_obsolete(thepoly):
                raise UnpicklingError

        except (IOError, UnpicklingError, AssertionError):
            # In any of these exception cases, the load failed, so we generate the polytope from the points

            # Read the point data from the specified file
            points = []
            with open(polyfile) as f:
                for line in f:
                    newline = line.split('#')[
                        0]  # Only use content before the comment symbol
                    if newline.strip() != '':
                        elts = newline.split()
                        structure = elts[1]
                        multiloops = QQ(elts[2])
                        unpaired = QQ(elts[3])
                        branches = QQ(elts[4])
                        w = QQ(elts[5])
                        energy = QQ(elts[6])
                        coords = (multiloops, unpaired, branches, w)

                        newpoint = namedtuple(
                            'RNApoint', ['structure', 'vector', 'energy'])
                        newpoint.vector = coords
                        newpoint.structure = structure
                        newpoint.energy = energy

                        points.append(newpoint)

            thepoly = RNAPolytope(points)
            thepoly._pickle_version = pickle_version
            thepoly._build_normal_fan()
            thepoly._build_d1_slices()
            thepoly.dump(filebase, -1)

        return thepoly
Exemplo n.º 24
0
 def extract(cls, obj):
     """
     Takes an object extracted by the json parser and decodes the
     special-formating dictionaries used to store special types.
     """
     if isinstance(obj, dict) and 'data' in obj:
         if len(obj) == 2 and '__ComplexList__' in obj:
             return [complex(*v) for v in obj['data']]
         elif len(obj) == 2 and '__QQList__' in obj:
             return [QQ(tuple(v)) for v in obj['data']]
         elif len(obj) == 3 and '__NFList__' in obj and 'base' in obj:
             base = cls.extract(obj['base'])
             return [cls._extract(base, c) for c in obj['data']]
         elif len(obj) == 2 and '__IntDict__' in obj:
             return {Integer(k): cls.extract(v) for k,v in obj['data']}
         elif len(obj) == 3 and '__Vector__' in obj and 'base' in obj:
             base = cls.extract(obj['base'])
             return vector([cls._extract(base, v) for v in obj['data']])
         elif len(obj) == 2 and '__Rational__' in obj:
             return Rational(*obj['data'])
         elif len(obj) == 3 and '__RealLiteral__' in obj and 'prec' in obj:
             return LmfdbRealLiteral(RealField(obj['prec']), obj['data'])
         elif len(obj) == 2 and '__complex__' in obj:
             return complex(*obj['data'])
         elif len(obj) == 3 and '__Complex__' in obj and 'prec' in obj:
             return ComplexNumber(ComplexField(obj['prec']), *obj['data'])
         elif len(obj) == 3 and '__NFElt__' in obj and 'parent' in obj:
             return cls._extract(cls.extract(obj['parent']), obj['data'])
         elif len(obj) == 3 and ('__NFRelative__' in obj or '__NFAbsolute__' in obj) and 'vname' in obj:
             poly = cls.extract(obj['data'])
             return NumberField(poly, name=obj['vname'])
         elif len(obj) == 2 and '__NFCyclotomic__' in obj:
             return CyclotomicField(obj['data'])
         elif len(obj) == 2 and '__IntegerRing__' in obj:
             return ZZ
         elif len(obj) == 2 and '__RationalField__' in obj:
             return QQ
         elif len(obj) == 3 and '__RationalPoly__' in obj and 'vname' in obj:
             return QQ[obj['vname']]([QQ(tuple(v)) for v in obj['data']])
         elif len(obj) == 4 and '__Poly__' in obj and 'vname' in obj and 'base' in obj:
             base = cls.extract(obj['base'])
             return base[obj['vname']]([cls._extract(base, c) for c in obj['data']])
         elif len(obj) == 5 and '__PowerSeries__' in obj and 'vname' in obj and 'base' in obj and 'prec' in obj:
             base = cls.extract(obj['base'])
             prec = infinity if obj['prec'] == 'inf' else int(obj['prec'])
             return base[[obj['vname']]]([cls._extract(base, c) for c in obj['data']], prec=prec)
         elif len(obj) == 2 and '__date__' in obj:
             return datetime.datetime.strptime(obj['data'], "%Y-%m-%d").date()
         elif len(obj) == 2 and '__time__' in obj:
             return datetime.datetime.strptime(obj['data'], "%H:%M:%S.%f").time()
         elif len(obj) == 2 and '__datetime__' in obj:
             return datetime.datetime.strptime(obj['data'], "%Y-%m-%d %H:%M:%S.%f")
     return obj
Exemplo n.º 25
0
def num_and_weighted_num(it):
    from sage.rings.integer_ring import ZZ
    from sage.rings.rational_field import QQ
    s = QQ.zero()
    n = ZZ.zero()
    for _, aut in it:
        n += ZZ.one()
        if aut is None:
            s += QQ.one()
        else:
            s += QQ((1, aut.group_cardinality()))
    return n, s
Exemplo n.º 26
0
def newton_data(H, exceptional=False):
    r"""Determines the "newton data" associated with each side of the polygon.

    For each side :math:`\Delta` of the Newton polygon of `H` we
    associate the data :math:`(q,m,l,`phi)` where

    .. math::

        \Delta: qj + mi = l \\
        \phi_{\Delta}(t) = \sum_{(i,j) \in \Delta} a_{ij} t^{(i-i_0)/q}

    Here, :math:`a_ij x^j y_i` is a term in the polynomial :math:`H` and
    :math:`i_0` is the smallest value of :math:`i` belonging to the
    polygon side :math:`\Delta`.

    Parameters
    ----------
    H : sympy.Poly
        Polynomial in `x` and `y`.

    Returns
    -------
    list
        A list of the tuples :math:`(q,m,l,\phi)`.
    """
    R = H.parent()
    x,y = R.gens()

    if exceptional:
        newton = newton_polygon_exceptional(H)
    else:
        newton = newton_polygon(H)

    # special case when the newton polygon is a single point
    if len(newton[0]) == 1:
        return []

    # for each side dtermine the corresponding newton data: side slope
    # information and corresponding side characteristic polynomial, phi
    result = []
    for side in newton:
        i0,j0 = side[0]
        i1,j1 = side[1]
        slope = QQ(j1-j0)/QQ(i1-i0)
        q = slope.denom()
        m = -slope.numer()
        l = min(q*j0 + m*i0, q*j1 + m*i1)
        phi = sum(H.coefficient({y:i,x:j})*x**((i-i0)/q) for i,j in side)
        phi = phi.univariate_polynomial()
        result.append((q,m,l,phi))
    return result
Exemplo n.º 27
0
    def test_bigoh(self):
        R = PuiseuxSeriesRing(QQ, 'x')
        x = R.gen()
        half = QQ(1) / QQ(2)

        p = x**(3 * half)
        q = p.add_bigoh(half)
        self.assertEqual(q.prec(), half)
        self.assertEqual(q.laurent_part.prec(), 1)

        p = x**(3 * half)
        q = p.add_bigoh(4)
        self.assertEqual(q.prec(), 4)
        self.assertEqual(q.laurent_part.prec(), 8)
Exemplo n.º 28
0
    def test_sub(self):
        R = PuiseuxSeriesRing(QQ, 't')
        t = R.gen()
        half = QQ(1) / QQ(2)

        p = 1 + t
        q = 1 + t + t**2
        r = t**2
        self.assertEqual(q - p, r)

        p = 1 + t**half
        q = 1 + t**half + t
        r = t
        self.assertEqual(q - p, r)
Exemplo n.º 29
0
def family_two(n, backend=None):
    r"""
    Return the vector configuration of the simplicial arrangement
    `A(n,1)` from the family `\mathcal R(1)` in Grunbaum's list [Gru]_.

    The arrangement will have an ``n`` hyperplanes, with ``n`` even, consisting
    of the edges of the regular `n/2`-gon and the `n/2` lines of 
    mirror symmetry.

    INPUT:

    - ``n`` -- integer. ``n`` `\geq 6`. The number of lines in the arrangement.
    
    - ``backend`` -- string (default = ``None``). The backend to use.

    OUTPUT:

    A vector configuration.

    EXAMPLES::

        sage: from cn_hyperarr.infinite_families import *
        sage: pf = family_two(8,'normaliz'); pf   # optional - pynormaliz
        Vector configuration of 8 vectors in dimension 3

    The number of lines must be even::

        sage: pf3 = family_two(3,'normaliz');     # optional - pynormaliz
        Traceback (most recent call last):
        ...
        AssertionError: n must be even

    The number of lines must be at least 6::

        sage: pf4 = family_two(4,'normaliz')      # optional - pynormaliz
        Traceback (most recent call last):
        ...
        ValueError: n (=2) must be an integer greater than 2
    """
    assert n % 2 == 0, "n must be even"
    reg_poly = polytopes.regular_polygon(n / QQ(2), backend='normaliz')
    reg_cone = Polyhedron(
        rays=[list(v.vector()) + [1] for v in reg_poly.vertices()],
        backend=backend)
    vecs = [h.A() for h in reg_cone.Hrepresentation()]

    z = QQbar.zeta(n)
    vecs += [[(z**k).real(), (z**k).imag(), 0] for k in range(n / QQ(2))]
    return VectorConfiguration(vecs, backend=backend)
Exemplo n.º 30
0
    def _test__jacobi_torsion_point(phi, weight, torsion_point):
        r"""
        Given a list of power series, which are the corrected Taylor coefficients
        of a Jacobi form, return the specialization to ``torsion_point``.
        
        INPUT:
        
        - ``phi`` -- A Fourier expansion of a Jacobi form.
        
        - ``weight`` -- An integer.
        
        - ``torsion_point`` -- A rational.
        
        OUPUT:
        
        - A power series.
        
        TESTS:
                
        See jacobi_form_by_taylor_expansion.
        
            sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import *
            sage: from psage.modform.jacobiforms.jacobiformd1nn_types import *
            sage: precision = 50
            sage: weight = 10; index = 7
            sage: phis = [jacobi_form_by_taylor_expansion(i, JacobiFormD1NNFilter(precision, index), weight) for i in range(JacobiFormD1NN_Gamma(weight, index)._rank(QQ))]
            sage: fs = [JacobiFormD1NNFactory_class._test__jacobi_torsion_point(phi, weight, 2/3) for phi in phis]
            sage: fs_vec = [vector(f.padded_list(precision)) for f in fs]
            sage: mf_span = span([vector(b.qexp(precision).padded_list(precision)) for b in ModularForms(GammaH(9, [4]), weight).basis()])
            sage: all(f_vec in mf_span for f_vec in fs_vec)
            True
        
        FIXME: The case of torsion points of order 5, which should lead to forms for Gamma1(25) fails even in the simplest case.
        """
        from sage.rings.all import CyclotomicField

        K = CyclotomicField(QQ(torsion_point).denominator())
        zeta = K.gen()
        R = PowerSeriesRing(K, 'q')
        q = R.gen(0)

        ch = JacobiFormD1WeightCharacter(weight)

        coeffs = dict((n, QQ(0)) for n in range(phi.precision().index()))
        for (n, r) in phi.precision().monoid_filter():
            coeffs[n] += zeta**r * phi[(ch, (n, r))]

        return PowerSeriesRing(K, 'q')(coeffs)
Exemplo n.º 31
0
    def _element_constructor_(self, data, *extra_args):
        r"""
        Build an element of that field.

        TESTS::

            sage: CFF(1/3)
            [0; 3]
            sage: CFF([1,3,2])
            [1; 3, 2]
            sage: CFF(CFF(1/3))
            [0; 3]
        """
        if isinstance(data, FieldElement) and data.parent() is self:
            data = list(data)
        if extra_args:
            print "data",data,type(data)
            print "extra_args",extra_args, type(extra_args[0])
            data = list(extra_args[0])
        if not isinstance(data, (tuple,list)):
            from sage.rings.rational_field import QQ
            data = QQ(data).continued_fraction_list()
        else:
            from continued_fraction import check_and_reduce_pair
            data,_ = check_and_reduce_pair(data, [])
        return self.element_class(data)
Exemplo n.º 32
0
def cyclotomic_to_alpha(cyclo):
    """
    Convert a list of indices of cyclotomic polynomials
    to a list of rational numbers.

    The input represents a product of cyclotomic polynomials.

    The output is the list of arguments of the roots of the
    given product of cyclotomic polynomials.

    This is the inverse of :func:`alpha_to_cyclotomic`.

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import cyclotomic_to_alpha
        sage: cyclotomic_to_alpha([1])
        [0]
        sage: cyclotomic_to_alpha([2])
        [1/2]
        sage: cyclotomic_to_alpha([5])
        [1/5, 2/5, 3/5, 4/5]
        sage: cyclotomic_to_alpha([1,2,3,6])
        [0, 1/6, 1/3, 1/2, 2/3, 5/6]
        sage: cyclotomic_to_alpha([2,3])
        [1/3, 1/2, 2/3]
    """
    alpha = []
    for d in cyclo:
        if d == 1:
            alpha.append(QQ.zero())
        else:
            for k in ZZ(d).coprime_integers(d):
                alpha.append(QQ((k, d)))
    return sorted(alpha)
Exemplo n.º 33
0
def quadratic_L_function__exact(n, d):
    r"""
    Returns the exact value of a quadratic twist of the Riemann Zeta function
    by `\chi_d(x) = \left(\frac{d}{x}\right)`.

    The input `n` must be a critical value.

    EXAMPLES::

        sage: quadratic_L_function__exact(1, -4)
        1/4*pi
        sage: quadratic_L_function__exact(-4, -4)
        5/2
        sage: quadratic_L_function__exact(2, 1)
        1/6*pi^2

    TESTS::

        sage: quadratic_L_function__exact(2, -4)
        Traceback (most recent call last):
        ...
        TypeError: n must be a critical value (i.e. odd > 0 or even <= 0)

    REFERENCES:

    - [Iwa1972]_, pp 16-17, Special values of `L(1-n, \chi)` and `L(n, \chi)`
    - [IR1990]_
    - [Was1997]_
    """
    from sage.all import SR, sqrt
    if n <= 0:
        return QuadraticBernoulliNumber(1-n,d)/(n-1)
    elif n >= 1:
        # Compute the kind of critical values (p10)
        if kronecker_symbol(fundamental_discriminant(d), -1) == 1:
            delta = 0
        else:
            delta = 1

        # Compute the positive special values (p17)
        if ((n - delta) % 2 == 0):
            f = abs(fundamental_discriminant(d))
            if delta == 0:
                GS = sqrt(f)
            else:
                GS = I * sqrt(f)
            ans = SR(ZZ(-1)**(1+(n-delta)/2))
            ans *= (2*pi/f)**n
            ans *= GS     # Evaluate the Gauss sum here! =0
            ans *= QQ.one()/(2 * I**delta)
            ans *= QuadraticBernoulliNumber(n,d)/factorial(n)
            return ans
        else:
            if delta == 0:
                raise TypeError("n must be a critical value (i.e. even > 0 or odd < 0)")
            if delta == 1:
                raise TypeError("n must be a critical value (i.e. odd > 0 or even <= 0)")
Exemplo n.º 34
0
def relation_space(v):
    r"""
    Relation space of the given vector ``v``

    This is the sub vector space of `\QQ^d` given as the kernel of the map
    `n \mapsto n \cdot \lambda`. The dimension is `d - rank`.

    EXAMPLES::

        sage: from surface_dynamics.misc.linalg import relation_space
        sage: K.<sqrt2> = QuadraticField(2)
        sage: v3 = vector([sqrt2, 1, 1+sqrt2])
        sage: relation_space(v3)
        Vector space of degree 3 and dimension 1 over Rational Field
        Basis matrix:
        [ 1  1 -1]
        sage: v4 = vector([sqrt2, 1, 1+sqrt2, 1-sqrt2])
        sage: relation_space(v4)
        Vector space of degree 4 and dimension 2 over Rational Field
        Basis matrix:
        [   1    0 -1/2  1/2]
        [   0    1 -1/2 -1/2]

        sage: v = vector([1,2,5,3])
        sage: relation_space(v)
        Vector space of degree 4 and dimension 3 over Rational Field
        Basis matrix:
        [   1    0    0 -1/3]
        [   0    1    0 -2/3]
        [   0    0    1 -5/3]

    The relation space has some covariance relation with respect to matrix
    actions::

        sage: m3 = matrix(3, [1,-1,0,2,-3,4,5,-2,2])
        sage: relation_space(v3 * m3) == relation_space(v3) * ~m3.transpose()
        True
        sage: relation_space(m3 * v3) == relation_space(v3) * ~m3
        True

        sage: m4 = matrix(4, [1,-1,0,1,2,-3,0,4,5,3,-2,2,1,1,1,1])
        sage: relation_space(v4 * m4) == relation_space(v4) * ~m4.transpose()
        True
        sage: relation_space(m4 * v4) == relation_space(v4) * ~m4
        True
    """
    from sage.matrix.constructor import matrix
    try:
        m_lengths = matrix([u.vector() for u in v])
    except AttributeError:
        from sage.rings.rational_field import QQ
        v = [QQ.coerce(i) for i in v]
        m_lengths = matrix([[i] for i in v])
    return m_lengths.left_kernel()
Exemplo n.º 35
0
def deformation_space(lengths):
    r"""
    Deformation space of the given ``lengths``

    This is the smallest vector space defined over `\QQ` that contains
    the vector ``lengths``. Its dimension is `rank`.

    EXAMPLES::

        sage: from surface_dynamics.misc.linalg import deformation_space
        sage: K.<sqrt2> = QuadraticField(2)
        sage: v3 = vector([sqrt2, 1, 1+sqrt2])
        sage: deformation_space(v3)
        Vector space of degree 3 and dimension 2 over Rational Field
        Basis matrix:
        [1 0 1]
        [0 1 1]
        sage: v4 = vector([sqrt2, 1, 1+sqrt2, 1-sqrt2])
        sage: deformation_space(v4)
        Vector space of degree 4 and dimension 2 over Rational Field
        Basis matrix:
        [ 1  0  1 -1]
        [ 0  1  1  1]

        sage: v = vector([1, 5, 2, 9])
        sage: deformation_space(v)
        Vector space of degree 4 and dimension 1 over Rational Field
        Basis matrix:
        [1 5 2 9]

    The deformation space has some covariance relation with respect to matrix
    actions::

        sage: m3 = matrix(3, [1,-1,0,2,-3,4,5,-2,2])
        sage: deformation_space(v3 * m3) == deformation_space(v3) * m3
        True
        sage: deformation_space(m3 * v3) == deformation_space(v3) * m3.transpose()
        True

        sage: m4 = matrix(4, [1,-1,0,1,2,-3,0,4,5,3,-2,2,1,1,1,1])
        sage: deformation_space(v4 * m4) == deformation_space(v4) * m4
        True
        sage: deformation_space(m4 * v4) == deformation_space(v4) * m4.transpose()
        True
    """
    from sage.matrix.constructor import matrix
    try:
        m_lengths = matrix([u.vector() for u in lengths])
    except AttributeError:
        from sage.rings.rational_field import QQ
        lengths = [QQ.coerce(i) for i in lengths]
        m_lengths = matrix([[i] for i in lengths])

    return m_lengths.column_space()
Exemplo n.º 36
0
 def charpoly_reverse(self, g, var='x'):
     r"""
     Determines the characteristic polynomial `\det(I-gT)`
     
     sage: from sage.rings.number_field.galois_group import GaloisGroup_v3
     sage: from sage.rings.number_field.artin_representation import ArtinRepresentation
     sage: K = NumberField(x^3 - 2, 'a')
     sage: G = GaloisGroup_v3(K, names='b2')
     sage: chi = ArtinRepresentation(G, [2, 0, -1])
     sage: L = G.splitting_field()
     sage: for p in prime_range(5, 50):
     ...    print p, chi.charpoly_reverse(G.artin_symbol(L.primes_above(p)[0]))
     5 -x^2 + 1
     7 x^2 + x + 1
     11 -x^2 + 1
     13 x^2 + x + 1
     17 -x^2 + 1
     19 x^2 + x + 1
     23 -x^2 + 1
     29 -x^2 + 1
     31 x^2 - 2*x + 1
     37 x^2 + x + 1
     41 -x^2 + 1
     43 x^2 - 2*x + 1
     47 -x^2 + 1
     """
     if self.degree() == 0:
         return QQ.one()
     from sage.combinat.sf.sf import SymmetricFunctions
     S = SymmetricFunctions(QQ)
     p = S.powersum()
     e = S.elementary()
     deg = self.degree()
     traces = [self(g ** n) for n in range(1, deg+1)]
     x = PolynomialRing(QQ, var).gen()
     cp = QQ.one()
     for n in range(deg):
         mc = p(e[n+1]).monomial_coefficients()
         cp += (-1) ** (n+1) * x ** (n+1) * sum(mc[k] * prod(traces[j-1] for j in k) for k in mc.keys())
     return cp
Exemplo n.º 37
0
def alpha_to_cyclotomic(alpha):
    """
    Convert from a list of rationals arguments to a list of integers.

    The input represents arguments of some roots of unity.

    The output represent a product of cyclotomic polynomials with exactly
    the given roots. Note that the multiplicity of `r/s` in the list
    must be independent of `r`; otherwise, a ``ValueError`` will be raised.

    This is the inverse of :func:`cyclotomic_to_alpha`.

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import alpha_to_cyclotomic
        sage: alpha_to_cyclotomic([0])
        [1]
        sage: alpha_to_cyclotomic([1/2])
        [2]
        sage: alpha_to_cyclotomic([1/5,2/5,3/5,4/5])
        [5]
        sage: alpha_to_cyclotomic([1/6, 1/3, 1/2, 2/3, 5/6, 1])
        [1, 2, 3, 6]
        sage: alpha_to_cyclotomic([1/3,2/3,1/2])
        [2, 3]
    """
    cyclo = []
    Alpha = list(alpha)
    while Alpha:
        q = QQ(Alpha.pop())
        n = q.numerator()
        d = q.denominator()
        for k in d.coprime_integers(d):
            if k != n:
                try:
                    Alpha.remove(QQ((k, d)))
                except ValueError:
                    raise ValueError("multiplicities not balanced")
        cyclo.append(d)
    return sorted(cyclo)
    def residue(self):
        r"""
        denominator: each (1 - mon)^k in denom is replaced with -> mon^k
        numerator: evaluate at (1,1,...,1)

        OUTPUT: a pair '(degree, value)`

        EXAMPLES::

            sage: from surface_dynamics.misc.multivariate_generating_series import MultivariateGeneratingSeriesRing

            sage: M = MultivariateGeneratingSeriesRing(2, 'x')
            sage: R = M.laurent_polynomial_ring()
            sage: x0,x1 = R.gens()
            sage: f = M.term(x0, [((1,1),2)])
            sage: f.residue()
            (2, [(1, {(1, 1): 2})])
            sage: f = M.term(x0, [((1,1),2)]) + M.term(1, [((1,0),1),((0,1),1),((1,1),1)])
            sage: f.residue()
            (3, [(1, {(0, 1): 1, (1, 0): 1, (1, 1): 1})])
            sage: f = M.term(x0, [((1,1),2)]) + M.term(1, [((1,0),1),((1,1),1)])
            sage: f.residue()
            (2, [(1, {(1, 0): 1, (1, 1): 1}), (1, {(1, 1): 2})])
        """
        R = self.parent().laurent_polynomial_ring()
        one = QQ.one()
        values = {g: one for g in R.gens()}
        ans = []
        d = -1
        for den, num in self._data.items():
            if den.degree() >= d:
                if den.degree() > d:
                    ans = []
                    d = den.degree()
                num = QQ(num.subs(values))
                if num.is_zero():
                    raise NotImplementedError('zero numerator')
                ans.append((num, den))
        return d, ans
Exemplo n.º 39
0
def _delta_invariant(P):
    r"""Computes the delta invariant of the singularity at :math:`u_0,v_0`.

    Parameters
    ----------
    P : list
        A list of PuiseuxTSeries of `g = g(u,v)` centered at some `(u_0,v_0)`
        where `g` is a complex affine algebraic curve.

    Returns
    -------
    int
        The delta invariant of the singularity :math:`(u_0, v_0)`.

    """
    # compute the puiseux series at (u0,v0). get the parametric forms as well
    # as an x-representative of each parametric form
    Px = [p.xseries(all_conjugates=False)[0] for p in P]
    Px_all = [p.xseries(all_conjugates=True) for p in P]
    Px_all = [item for sublist in Px_all for item in sublist]

    # for each place compute its contribution to the delta invariant
    delta = QQ(0)
    for i in range(len(Px)):
        # compute Int of each x-representation. note that it's sufficient to
        # only look at the Puiseux series with the given v0 since, for all
        # other puiseux series, the contribution to Int() will be zero.
        Pxi = Px[i]
        j = Px_all.index(Pxi)
        IntPxi = Int(j, Px_all)

        # obtain the ramification index by retreiving the corresponding
        # parametric form. By definition, this parametric series satisfies
        # Y(t=0) = v0
        ri = Pxi.ramification_index
        delta += QQ(ri * IntPxi - ri + 1) / 2
    return delta.numerator()
Exemplo n.º 40
0
    def M_value(self):
        """
        Return the `M` coefficient that appears in the trace formula.

        OUTPUT:

        a rational

        .. SEEALSO:: :meth:`canonical_scheme`

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: H = Hyp(alpha_beta=([1/6,1/3,2/3,5/6],[1/8,3/8,5/8,7/8]))
            sage: H.M_value()
            729/4096
            sage: Hyp(alpha_beta=(([1/2,1/2,1/2,1/2],[0,0,0,0]))).M_value()
            256
            sage: Hyp(cyclotomic=([5],[1,1,1,1])).M_value()
            3125
        """
        up = QQ.prod(capital_M(d) for d in self._cyclo_up)
        down = QQ.prod(capital_M(d) for d in self._cyclo_down)
        return up / down
    def one(self):
        r"""
        EXAMPLES::

            sage: from surface_dynamics.misc.multivariate_generating_series import MultivariateGeneratingSeriesRing

            sage: M = MultivariateGeneratingSeriesRing('x', 2)
            sage: M.zero()
            0
            sage: M.zero().parent() is M
            True
            sage: M.one().is_one()
            True
        """
        return self._element_constructor_(QQ.one())
Exemplo n.º 42
0
    def random_element(self, *args, **kwds):
        """
        Return a somewhat random continued fraction (the result is either
        finite or ultimately periodic).

        INPUT:

        - ``args``, ``kwds`` - arguments passed to ``QQ.random_element``

        EXAMPLES::

            sage: CFF.random_element() # random
            [0; 4, 7]
        """
        from sage.rings.rational_field import QQ
        return self(QQ.random_element())
Exemplo n.º 43
0
 def charpoly(self, g, var='x'):
     r"""
     Determines the characteristic polynomial `\det(I-gT)`
     """
     if self.degree() == 0:
         return QQ.one()
     from sage.combinat.sf.sf import SymmetricFunctions
     S = SymmetricFunctions(QQ)
     p = S.powersum()
     e = S.elementary()
     deg = self.degree()
     traces = [self(g ** n) for n in range(1, deg+1)]
     x = PolynomialRing(QQ, var).gen()
     cp = x ** deg
     for n in range(deg):
         mc = p(e[n+1]).monomial_coefficients()
         cp += (-1) ** (n+1) * x ** (deg-1-n) * sum(mc[k] * prod(traces[j-1] for j in k) for k in mc.keys())
     return cp
Exemplo n.º 44
0
def capital_M(n):
    """
    Auxiliary function, used to describe the canonical scheme.

    INPUT:

    - ``n`` -- an integer

    OUTPUT:

    a rational

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import capital_M
        sage: [capital_M(i) for i in range(1,8)]
        [1, 4, 27, 64, 3125, 432, 823543]
    """
    n = ZZ(n)
    return QQ.prod(d ** (d * moebius(n / d)) for d in divisors(n))
Exemplo n.º 45
0
def construct_from_maass_products(ring, weight, products, is_basis = True,
                                  provides_maass_spezialschar = False,
                                  is_integral = False,
                                  lazy_rank_check = True) :
    r"""
    Pass the return value of spanning_maass_products of a space of Siegel modular
    forms of same type. This will return a space using these forms.
    Whenever ``is_basis`` is False the the products are first filtered to yield a
    basis.
    """
    assert QQ.has_coerce_map_from(ring.base_ring()) or ring.base_ring() is ZZ, \
           "%s doesn't have rational base field" % ring
           
    dim = ring.graded_submodule(weight).dimension()

    ## if the products don't provide a basis, we have to choose one
    if not is_basis :
        ## we prefer to use Maass lifts, since they are very cheap
        maass_forms = []; non_maass_forms = []
        for p in products :
            if len(p[0]) == 1 :
                maass_forms.append(p)
            else :
                non_maass_forms.append(p)
        
        
        monomials = set()
        lift_polys = []
        products = []
        for lifts, lift_poly in maass_forms + non_maass_forms :
            red_poly = ring(ring.relations().ring()(lift_poly))._reduce_polynomial()
            monomials = monomials.union(set(red_poly.monomials()))
                
            M = matrix( QQ, len(lift_polys) + 1,
                        [ poly.monomial_coefficient(m)
                          for poly in lift_polys + [lift_poly]
                          for m in monomials] )                
                                    
            # TODO : Use linbox
            try :
                if magma(M).Rank() > len(lift_polys) :
                    break
            except TypeError :
                for i in xrange(10) :
                    Mp = matrix(Qp(random_prime(10**10), 10), M)
                    if Mp.rank() > len(lift_polys) : break
                else :
                    if lazy_rank_check :
                        continue
                    elif M.rank() <= len(lift_polys) :
                        continue
                    
            lift_polys.append(red_poly)
            products.append((lifts, red_poly))

            if len(products) == dim :
                break
        else :
            raise ValueError, "products don't provide a basis"
    
    basis = []
     
    if provides_maass_spezialschar :
        maass_form_indices = []
    for i, (lifts, lift_poly) in enumerate(products) :
        e = ring(ring.relations().ring()(lift_poly))

        if len(lifts) == 1 :
            l = lifts[0]
            e._set_fourier_expansion(
                SiegelModularFormG2MaassLift(l[0], l[1], ring.fourier_expansion_precision(),
                                             is_integral = is_integral) )
        elif len(lifts) == 2 :
            (l0, l1) = tuple(lifts)
            e._set_fourier_expansion(
                EquivariantMonoidPowerSeries_LazyMultiplication(
                    SiegelModularFormG2MaassLift(l0[0], l0[1], ring.fourier_expansion_precision(),
                                                 is_integral = is_integral),
                    SiegelModularFormG2MaassLift(l1[0], l1[1], ring.fourier_expansion_precision(),
                                                 is_integral = is_integral) ) ) 

        else :
            e._set_fourier_expansion( 
                prod( SiegelModularFormG2MaassLift(l[0], l[1], ring.precision(),
                                                   is_integral = is_integral)
                      for l in lifts) )            
        basis.append(e)
        
        if provides_maass_spezialschar and len(lifts) == 1 :
            maass_form_indices.append(i)
    
    ss = ring._submodule(basis, grading_indices = (weight,), is_heckeinvariant = True)
    if provides_maass_spezialschar : 
        maass_coords = [ ss([0]*i + [1] + [0]*(dim-i-1))
                         for i in maass_form_indices ]
        ss.maass_space.set_cache( 
          SiegelModularFormG2Submodule_maassspace(ss, map(ss, maass_coords)) )
                                 
    return ss
Exemplo n.º 46
0
def gamma__exact(n):
    """
    Evaluates the exact value of the `\Gamma` function at an integer or
    half-integer argument.

    EXAMPLES::

        sage: gamma__exact(4)
        6
        sage: gamma__exact(3)
        2
        sage: gamma__exact(2)
        1
        sage: gamma__exact(1)
        1

        sage: gamma__exact(1/2)
        sqrt(pi)
        sage: gamma__exact(3/2)
        1/2*sqrt(pi)
        sage: gamma__exact(5/2)
        3/4*sqrt(pi)
        sage: gamma__exact(7/2)
        15/8*sqrt(pi)

        sage: gamma__exact(-1/2)
        -2*sqrt(pi)
        sage: gamma__exact(-3/2)
        4/3*sqrt(pi)
        sage: gamma__exact(-5/2)
        -8/15*sqrt(pi)
        sage: gamma__exact(-7/2)
        16/105*sqrt(pi)

    TESTS::

        sage: gamma__exact(1/3)
        Traceback (most recent call last):
        ...
        TypeError: you must give an integer or half-integer argument
    """
    from sage.all import sqrt
    n = QQ(n)

    if denominator(n) == 1:
        if n <= 0:
            return infinity
        if n > 0:
            return factorial(n-1)
    elif denominator(n) == 2:
        ans = QQ.one()
        while n != QQ((1, 2)):
            if n < 0:
                ans /= n
                n += 1
            elif n > 0:
                n += -1
                ans *= n

        ans *= sqrt(pi)
        return ans
    else:
        raise TypeError("you must give an integer or half-integer argument")
def Kitaoka_mass_at_2(self):
    """
    Returns the local mass of the quadratic form when `p=2`, according
    to Theorem 5.6.3 on pp108--9 of Kitaoka's Book "The Arithmetic of
    Quadratic Forms".

    INPUT:

        none

    OUTPUT:

        a rational number > 0

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
        sage: Q.Kitaoka_mass_at_2()   ## WARNING:  WE NEED TO CHECK THIS CAREFULLY!
        1/2

    """
    ## Make a 0-dim'l quadratic form (for initialization purposes)
    Null_Form = copy.deepcopy(self)
    Null_Form.__init__(ZZ, 0)

    ## Step 0: Compute Jordan blocks and bounds of the scales to keep track of
    Jordan_Blocks = self.jordan_blocks_by_scale_and_unimodular(2)
    scale_list = [B[0]  for B in Jordan_Blocks]
    s_min = min(scale_list)
    s_max = max(scale_list)

    ## Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale
    diag_dict = dict((i, Null_Form)  for i in range(s_min-2, s_max + 4))     ## Initialize with the zero form
    dim2_dict = dict((i, Null_Form)  for i in range(s_min, s_max + 4))       ## Initialize with the zero form
    for (s,L) in Jordan_Blocks:
        i = 0
        while (i < L.dim()-1) and (L[i,i+1] == 0):      ## Find where the 2x2 blocks start
            i = i + 1
        if i < (L.dim() - 1):
            diag_dict[s] = L.extract_variables(range(i))                ## Diagonal Form
            dim2_dict[s+1] = L.extract_variables(range(i, L.dim()))     ## Non-diagonal Form
        else:
            diag_dict[s] = L

    #print "diag_dict = ", diag_dict
    #print "dim2_dict = ", dim2_dict
    #print "Jordan_Blocks = ", Jordan_Blocks


    ##################  START EDITING HERE  ##################

    ## Compute q := sum of the q_j
    q = 0
    for j in range(s_min, s_max + 1):
        if diag_dict[j].dim() > 0:               ## Check that N_j is odd (i.e. rep'ns an odd #)
            if diag_dict[j+1].dim() == 0:
                q += Jordan_Blocks[j][1].dim()        ## When N_{j+1} is "even", add n_j
            else:
                q += Jordan_Blocks[j][1].dim() + 1    ## When N_{j+1} is "odd", add n_j + 1

    ## Compute P = product of the P_j
    P = QQ.one()
    for j in range(s_min, s_max + 1):
        tmp_m = dim2_dict[j].dim() // 2
        P *= prod(QQ.one() - QQ(4**(-k)) for k in range(1, tmp_m + 1))

    ## Compute the product E := prod_j (1 / E_j)
    E = QQ.one()
    for j in range(s_min - 1, s_max + 2):
        if (diag_dict[j-1].dim() == 0) and (diag_dict[j+1].dim() == 0) and \
           ((diag_dict[j].dim() != 2) or (((diag_dict[j][0,0] - diag_dict[j][1,1]) % 4) != 0)):

            ## Deal with the complicated case:
            tmp_m = dim2_dict[j].dim() // 2
            if dim2_dict[j].is_hyperbolic(2):
                E *= QQ(2) / (1 + 2**(-tmp_m))
            else:
                E *= QQ(2) / (1 - 2**(-tmp_m))

        else:
            E *= 2

    ## DIAGNOSTIC
    #print "\nFinal Summary:"
    #print "nu =", nu
    #print "q = ", q
    #print "P = ", P
    #print "E = ", E

    ## Compute the exponent w
    w = QQ.zero()
    for j in range(s_min, s_max+1):
        n_j = Jordan_Blocks[j][1].dim()
        for k in range(j+1, s_max+1):
            n_k = Jordan_Blocks[k][1].dim()
            w += j * n_j * (n_k + QQ(n_j + 1) / 2)


    ## Step 5: Compute the local mass for the prime 2.
    mass_at_2 = (QQ(2)**(w - q)) * P * E
    return mass_at_2
Exemplo n.º 48
0
class QQpApprox_element(RingElement,Approximation):  # maybe should create a ApproximatedRingElement
    def __init__(self,parent,x,val=0,normalized=False):
        RingElement.__init__(self,parent)
        Approximation.__init__(self,parent)
        self._x = QQ(x)
        self._val = val
        self._normalized = normalized

    def _normalize(self):
        if not self._normalized:
            if self._x == 0:
                self._val = 0
            else:
                powers = self.parent().uniformizer
                v = self._x.valuation(powers())
                self._val += v
                if v > 0:
                    self._x /= powers(v)
                elif v < 0:
                    self._x *= powers(-v)
            self._normalized = True

    def parenthesis_level(self):
        if self._x.denominator() == 1:
            return 3
        else:
            return 1

    def _getitem_by_num(self,i):
        return self

    def is_zero(self):
        return self._x == 0

    def _add_(self,other,**kwargs):
        parent = self.parent()
        selfval = self._val
        otherval = other._val
        if selfval == otherval:
            return QQpApprox_element(parent, self._x + other._x, selfval)
        if selfval > otherval:
            return QQpApprox_element(parent, self._x * parent.uniformizer(selfval-otherval) + other._x, otherval)
        else:
            return QQpApprox_element(self.parent(), self._x + other._x * parent.uniformizer(otherval-selfval), selfval)

    def __neg__(self,**kwargs):
        return QQpApprox_element(self.parent(), -self._x, self._val)

    def _sub_(self,other,**kwargs):
        parent = self.parent()
        selfval = self._val
        otherval = other._val
        if selfval == otherval:
            return QQpApprox_element(parent, self._x - other._x, selfval)
        if selfval > otherval:
            return QQpApprox_element(parent, self._x * parent.uniformizer(selfval-otherval) - other._x, otherval)
        else:
            return QQpApprox_element(self.parent(), self._x - other._x * parent.uniformizer(otherval-selfval), selfval)

    def _mul_(self,other,**kwargs):
        return QQpApprox_element(self.parent(), self._x * other._x, self._val + other._val, self._normalized and other._normalized)

    def _rmul_(self,other,**kwargs):
        return self._mul_(other,**kwargs)

    def _lmul_(self,other,**kwargs):
        return self._mul_(other,**kwargs)

    def __invert__(self,**kwargs):
        return QQpApprox_element(self.parent(), ~self._x, -self._val, self._normalized)

    def _div_(self,other,**kwargs):
        return QQpApprox_element(self.parent(), self._x / other._x, self._val - other._val, self._normalized and other._normalized)

    def valuation(self,lazylimit=Infinity):
        self._normalize()
        if self._x == 0:
            return Infinity
        else:
            return self._val

    def _repr_(self):
        self._normalize()
        if self._x == 0:
            return "0"
        elif self._val == 0:
            return "%s" % self._x
        else:
            return "%s*%s^%s" % (self._x, self.parent()._p, self._val)

    def __pow__(self,exp,**kwargs):
        return QQpApprox_element(self.parent(), self._x ** exp, self._val * exp, self._normalized)

    def __cmp__(self,other):
        v = self._val - other._val
        return cmp(self._x, other._x * self.parent().uniformizer(v))

    def truncate(self,workprec):
        if workprec == Infinity:
            return self
        parent = self.parent()
        self._normalize()
        pow = workprec - self._val
        if pow <= 0:
            return QQpApprox_element(parent, 0, 0, True)
        modulo = parent.uniformizer(pow)
        num = self._x.numerator() % modulo
        denom = self._x.denominator() % modulo
        if denom != 1:
            _,inv,_ = denom.xgcd(modulo)
            num = (num * inv) % modulo
        return QQpApprox_element(parent, num, self._val, True)

    def log(self,workprec=Infinity):
        from sage.functions.log import log
        from sage.functions.other import floor
        if workprec is Infinity:
            raise ApproximationError("unable to compute log to infinite precision")
        parent = self.parent()
        pow = parent(-1)
        res = parent(0)
        t = parent(1) - self
        iter = workprec + floor(log(workprec)/log(parent._p)) + 1
        for i in range(1,iter):
            pow *= t
            res += pow / parent(i)
            res = res.truncate(workprec)
        return res

    def exp(self,workprec=Infinity):
        from sage.functions.other import ceil
        if workprec is Infinity:
            raise ApproximationError("unable to compute exp to infinite precision")
        parent = self.parent()
        pow = parent(1)
        res = parent(1)
        val = self.valuation()
        iter = ceil(workprec / (val - 1/(parent._p-1))) + 1
        for i in range(1,iter):
            pow *= self / parent(i)
            res += pow
            res = res.truncate(workprec)
        return res

    def teichmuller(self,workprec=Infinity):
        if workprec is Infinity:
            raise ApproximationError("unable compute Teichmuller lift to infinite precision")
        res = self.truncate(1)
        p = self.parent()._p
        for i in range(2,workprec+1):
            res = res ** p
            res = res.truncate(i)
        return res
Exemplo n.º 49
0
def Min(Fun, p, ubRes, conj):
    r"""
    Local loop for Affine_minimal, where we check minimality at the prime p.

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

    INPUT:

    - ``Fun`` -- a projective space morphisms.

    - ``p`` - a prime.

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

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

    OUTPUT:

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

    - a projective morphism minimal at ``p``.

    EXAMPLES::

        sage: P.<x,y> = ProjectiveSpace(QQ, 1)
        sage: H = End(P)
        sage: f = H([149*x^2 + 39*x*y + y^2, -8*x^2 + 137*x*y + 33*y^2])
        sage: from sage.schemes.projective.endPN_minimal_model import Min
        sage: Min(f, 3, -27000000, matrix(QQ,[[1, 0],[0, 1]]))
        (
        Scheme endomorphism of Projective Space of dimension 1 over Rational
        Field
          Defn: Defined on coordinates by sending (x : y) to
                (181*x^2 + 313*x*y + 81*y^2 : -24*x^2 + 73*x*y + 151*y^2)
        ,
        [3 4]
        [0 1]
        )
    """
    d = Fun.degree()
    AffFun = Fun.dehomogenize(1)
    R = AffFun.coordinate_ring()
    if R.is_field():
        #want the polynomial ring not the fraction field
        R = R.ring()
    F = R(AffFun[0].numerator())
    G = R(AffFun[0].denominator())
    dG = G.degree()
    if dG > (d+1)/2:
        lowerBound = (-2*(G[dG]).valuation(p)/(2*dG - d + 1) + 1).floor()
    else:
        lowerBound = (-2*(F[d]).valuation(p)/(d-1) + 1).floor()
    upperBound = 2*(ubRes.valuation(p))

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

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

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

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

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

                #If bool is true after lifting, we have a solution b, and F/G is not
                #minimal.
                if bool:
                    #Rescale, conjugate and return new map
                    bsol = QQ(sol*(p**bval))
                    #"Conjugating by ", p,"^", k, "*z +", bsol
                    newconj = matrix(QQ,2,2,[p**k,bsol,0,1])
                    minFun = Fun.conjugate(newconj)
                    conj = conj*newconj

                    minFun.normalize_coordinates()
                    return minFun, conj
            k = k + 1
        return Fun, conj
Exemplo n.º 50
0
def test_comparison(ring):
    """
    Check comparison with infinity

    INPUT:

    - ``ring`` -- a sub-ring of the real numbers

    OUTPUT:

    Various attempts are made to generate elements of ``ring``. An
    assertion is triggered if one of these elements does not compare
    correctly with plus/minus infinity.

    EXAMPLES::

        sage: from sage.rings.infinity import test_comparison
        sage: rings = [ZZ, QQ, RR, RealField(200), RDF, RLF, AA, RIF]
        sage: for R in rings:
        ....:     print('testing {}'.format(R))
        ....:     test_comparison(R)
        testing Integer Ring
        testing Rational Field
        testing Real Field with 53 bits of precision
        testing Real Field with 200 bits of precision
        testing Real Double Field
        testing Real Lazy Field
        testing Algebraic Real Field
        testing Real Interval Field with 53 bits of precision

    Comparison with number fields does not work::

        sage: K.<sqrt3> = NumberField(x^2-3)
        sage: (-oo < 1+sqrt3) and (1+sqrt3 < oo)     # known bug
        False

    The symbolic ring handles its own infinities, but answers
    ``False`` (meaning: cannot decide) already for some very
    elementary comparisons::

        sage: test_comparison(SR)      # known bug
        Traceback (most recent call last):
        ...
        AssertionError: testing -1000.0 in Symbolic Ring: id = ...
    """
    from sage.symbolic.ring import SR
    from sage.rings.rational_field import QQ
    elements = [-1e3, 99.9999, -SR(2).sqrt(), 0, 1,
                3 ** (-QQ.one()/3), SR.pi(), 100000]
    elements.append(ring.an_element())
    elements.extend(ring.some_elements())
    for z in elements:
        try:
            z = ring(z)
        except (ValueError, TypeError):
            continue    # ignore if z is not in ring
        msg = 'testing {} in {}: id = {}, {}, {}'.format(z, ring, id(z), id(infinity), id(minus_infinity))
        assert minus_infinity < z, msg
        assert z > minus_infinity, msg
        assert z < infinity, msg
        assert infinity > z, msg
        assert minus_infinity <= z, msg
        assert z >= minus_infinity, msg
        assert z <= infinity, msg
        assert infinity >= z, msg
Exemplo n.º 51
0
def Min(Fun, p, ubRes, conj, all_orbits=False):
    r"""
    Local loop for Affine_minimal, where we check minimality at the prime p.

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

    INPUT:

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

    - ``p`` - a prime

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

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

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

    OUTPUT:

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

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

    EXAMPLES::

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

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

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

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

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

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

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

                    minFun.normalize_coordinates()
                    if not all_orbits:
                        return [minFun, conj*newconj]
                    if [p,k,bsol] not in all_found:
                        all_found.append([p, k, bsol])
        k = k + 1
    if not all_orbits:
        return [Fun, conj]
    return all_found
Exemplo n.º 52
0
 def __init__(self,parent,x,val=0,normalized=False):
     RingElement.__init__(self,parent)
     Approximation.__init__(self,parent)
     self._x = QQ(x)
     self._val = val
     self._normalized = normalized