示例#1
0
    def global_height(self, prec=None):
        r"""
        Returns the logarithmic height of the point.

        INPUT:

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number

        EXAMPLES::

            sage: P.<x,y>=AffineSpace(QQ,2)
            sage: Q=P(41,1/12)
            sage: Q.global_height()
            3.71357206670431

        ::

            sage: P=AffineSpace(ZZ,4,'x')
            sage: Q=P(3,17,-51,5)
            sage: Q.global_height()
            3.93182563272433

        ::

            sage: R.<x>=PolynomialRing(QQ)
            sage: k.<w>=NumberField(x^2+5)
            sage: A=AffineSpace(k,2,'z')
            sage: A([3,5*w+1]).global_height(prec=100)
            2.4181409534757389986565376694

        .. TODO::

            p-adic heights

            add heights to integer.pyx and remove special case
        """
        if self.domain().base_ring() == ZZ:
            if prec is None:
                R = RealField()
            else:
                R = RealField(prec)
            H = max([
                self[i].abs() for i in range(
                    self.codomain().ambient_space().dimension_relative())
            ])
            return (R(max(H, 1)).log())
        if self.domain().base_ring() in _NumberFields or is_NumberFieldOrder(
                self.domain().base_ring()):
            return (max([
                self[i].global_height(prec) for i in range(
                    self.codomain().ambient_space().dimension_relative())
            ]))
        else:
            raise NotImplementedError(
                "Must be over a Numberfield or a Numberfield Order")
示例#2
0
    def _compute_power_series(self, n, abs_prec, cache_ring=None):
        """
        Compute the power series giving Dickman's function on [n, n+1], by
        recursion in n. For internal use; self.power_series() is a wrapper
        around this intended for the user.

        INPUT:

        -  ``n`` - the lower endpoint of the interval for which
           this power series holds

        -  ``abs_prec`` - the absolute precision of the
           resulting power series

        -  ``cache_ring`` - for internal use, caches the power
           series at this precision.

        EXAMPLES::

            sage: f = dickman_rho.power_series(2, 20); f
            -9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032
        """
        if n <= 1:
            if n <= -1:
                return PolynomialRealDense(RealField(abs_prec)['x'])
            if n == 0:
                return PolynomialRealDense(RealField(abs_prec)['x'], [1])
            elif n == 1:
                nterms = (RDF(abs_prec) * RDF(2).log() / RDF(3).log()).ceil()
                R = RealField(abs_prec)
                neg_three = ZZ(-3)
                coeffs = [1 - R(1.5).log()
                          ] + [neg_three**-k / k for k in range(1, nterms)]
                f = PolynomialRealDense(R['x'], coeffs)
                if cache_ring is not None:
                    self._f[n] = f.truncate_abs(f[0] >> (
                        cache_ring.prec() + 1)).change_ring(cache_ring)
                return f
        else:
            f = self._compute_power_series(n - 1, abs_prec, cache_ring)
            # integrand = f / (2n+1 + x)
            # We calculate this way because the most significant term is the constant term,
            # and so we want to push the error accumulation and remainder out to the least
            # significant terms.
            integrand = f.reverse().quo_rem(
                PolynomialRealDense(f.parent(), [1, 2 * n + 1]))[0].reverse()
            integrand = integrand.truncate_abs(RR(2)**-abs_prec)
            iintegrand = integrand.integral()
            ff = PolynomialRealDense(f.parent(),
                                     [f(1) + iintegrand(-1)]) - iintegrand
            i = 0
            while abs(f[i]) < abs(f[i + 1]):
                i += 1
            rel_prec = int(abs_prec + abs(RR(f[i])).log2())
            if cache_ring is not None:
                self._f[n] = ff.truncate_abs(
                    ff[0] >> (cache_ring.prec() + 1)).change_ring(cache_ring)
            return ff.change_ring(RealField(rel_prec))
示例#3
0
    def global_height(self, prec=None):
        r"""
        Returns the maximum of the heights of the coefficients in any of the coordinate functions of ``self``.

        INPUT:

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number

        EXAMPLES::

            sage: A.<x>=AffineSpace(QQ,1)
            sage: H=Hom(A,A)
            sage: f=H([1/1331*x^2+4000]);
            sage: f.global_height()
            8.29404964010203

        ::

            sage: R.<x>=PolynomialRing(QQ)
            sage: k.<w>=NumberField(x^2+5)
            sage: A.<x,y>=AffineSpace(k,2)
            sage: H=Hom(A,A)
            sage: f=H([13*w*x^2+4*y, 1/w*y^2]);
            sage: f.global_height(prec=100)
            3.3696683136785869233538671082

        .. TODO::

            add heights to integer.pyx and remove special case
        """
        if self.domain().base_ring() == ZZ:
            if prec is None:
                R = RealField()
            else:
                R = RealField(prec)
            H = R(0)
            for i in range(self.domain().ambient_space().dimension_relative()):
                C = self[i].coefficients()
                h = max([c.abs() for c in C])
                H = max(H, R(h).log())
            return (H)
        H = 0
        for i in range(self.domain().ambient_space().dimension_relative()):
            C = self[i].coefficients()
            if C == []:  #to deal with the case self[i]=0
                h = 0
            else:
                h = max([c.global_height(prec) for c in C])
            H = max(H, h)
        return (H)
示例#4
0
    def global_height(self, prec=None):
        r"""
        Returns the logarithmic height of the points. Must be over `\ZZ` or `\QQ`.

        INPUT:

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number

        EXAMPLES::

            sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
            sage: Q=P.point([4,4,1/30])
            sage: Q.global_height()
            4.78749174278205

        ::

            sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
            sage: Q=P([4,1,30])
            sage: Q.global_height()
            3.40119738166216

        ::

            sage: R.<x>=PolynomialRing(QQ)
            sage: k.<w>=NumberField(x^2+5)
            sage: A=ProjectiveSpace(k,2,'z')
            sage: A([3,5*w+1,1]).global_height(prec=100)
            2.4181409534757389986565376694

        .. TODO::

            p-adic heights

            add heights to integer.pyx and remove special case
        """
        if self.domain().base_ring() == ZZ:
            if prec is None:
                R = RealField()
            else:
                R = RealField(prec)
            H=R(0)
            return(R(max([self[i].abs() for i in range(self.codomain().ambient_space().dimension_relative()+1)])).log())
        if self.domain().base_ring() in _NumberFields or is_NumberFieldOrder(self.domain().base_ring()):
            return(max([self[i].global_height(prec) for i in range(self.codomain().ambient_space().dimension_relative()+1)]))
        else:
            raise NotImplementedError("Must be over a Numberfield or a Numberfield Order")
示例#5
0
文件: encoding.py 项目: kwang23/lmfdb
def numeric_converter(value, cur=None):
    """
    Used for converting numeric values from Postgres to Python.

    INPUT:

    - ``value`` -- a string representing a decimal number.
    - ``cur`` -- a cursor, unused

    OUTPUT:

    - either a sage integer (if there is no decimal point) or a real number whose precision depends on the number of digits in value.
    """
    if value is None:
        return None
    if "." in value:
        if SAGE_MODE:
            # The following is a good guess for the bit-precision,
            # but we use LmfdbRealLiterals to ensure that our number
            # prints the same as we got it.
            prec = ceil(len(value) * 3.322)
            return LmfdbRealLiteral(RealField(prec), value)
        else:
            # Sage isn't installed, so we fall back on Python floats
            return float(value)
    else:
        return Integer(value)
示例#6
0
def _test_fun_approx(pol, ref, disk_rad=None, interval_rad=None,
        prec=53, test_count=100):
    r"""
    EXAMPLES::

        sage: from ore_algebra.analytic.polynomial_approximation import _test_fun_approx
        sage: _test_fun_approx(lambda x: x.exp(), lambda x: x.exp() + x/1000,
        ....:                  interval_rad=1)
        Traceback (most recent call last):
        ...
        AssertionError: z = ..., ref(z) = ... not in pol(z) = ...
    """
    from sage.rings.real_mpfr import RealField
    from sage.rings.real_arb import RealBallField
    from sage.rings.complex_arb import ComplexBallField
    my_RR = RealField(prec)
    my_RBF = RealBallField(prec)
    my_CBF = ComplexBallField(prec)
    if bool(disk_rad) == bool(interval_rad):
        raise ValueError
    rad = disk_rad or interval_rad
    for _ in range(test_count):
        rho = my_RBF(my_RR.random_element(-rad, rad))
        if disk_rad:
            exp_i_theta = my_CBF(my_RR.random_element(0, 1)).exppii()
            z = rho*exp_i_theta
        elif interval_rad:
            z = rho
        ref_z = ref(z)
        pol_z = pol(z)
        if not ref_z.overlaps(pol_z):
            fmt = "z = {}, ref(z) = {} not in pol(z) = {}"
            raise AssertionError(fmt.format(z, ref_z, pol_z))
示例#7
0
    def __init__(self, v, omega, mu=0, prec=None):
        r"""
        EXAMPLES::

            sage: from slabbe import DiscreteHyperplane
            sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=0)
            sage: p
            Set of points x in ZZ^3 satisfying: 0 <= (1, pi, 7) . x + 0 < pi + 8

        ::

            sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=20)
            sage: vector((0,0,0)) in p
            False
            sage: p = DiscreteHyperplane([1,pi,7], 1+pi+7, mu=0)
            sage: vector((0,0,0)) in p
            True
        """
        if prec is None:
            self._v = vector(v)
            self._omega = omega
            self._mu = mu
        else:
            RF = RealField(prec=prec)
            self._v = vector(RF, v)
            self._omega = RF(omega)
            self._mu = RF(mu)

        def contain(p):
            #print "est-ce proche : ", self._v.dot_product(p) + self._mu
            return 0 <= self._v.dot_product(p) + self._mu < self._omega

        DiscreteSubset.__init__(self,
                                dimension=len(self._v),
                                predicate=contain)
示例#8
0
def column_Log(SUK, iota, U, prec=106):
    r"""
    Return the log vector of ``iota``; i.e., the logs of all the valuations

    INPUT:

    - ``SUK`` -- a group of `S`-units
    - ``iota`` -- an element of ``K``
    - ``U`` -- a list of places (finite or infinite) of ``K``
    - ``prec`` -- (default: 106) the precision of the real field

    OUTPUT:

    The log vector as a list of real numbers

    EXAMPLES::

        sage: from sage.rings.number_field.S_unit_solver import column_Log
        sage: K.<xi> = NumberField(x^3-3)
        sage: S = tuple(K.primes_above(3))
        sage: SUK = UnitGroup(K, S=S)
        sage: phi_complex = K.places()[1]
        sage: v_fin = S[0]
        sage: U = [phi_complex, v_fin]
        sage: column_Log(SUK, xi^2, U) # abs tol 1e-29
        [1.464816384890812968648768625966, -2.197224577336219382790490473845]

    REFERENCES:

    - [Sma1995]_ p. 823
    """
    R = RealField(prec)

    return [ R(SUK.number_field().abs_val(v, iota, prec)).log() for v in U]
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
示例#10
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
示例#11
0
    def __init__(self, X, P, codomain=None, check=False):
        r"""
        Create the discrete probability space with probabilities on the
        space X given by the dictionary P with values in the field
        real_field.

        EXAMPLES::

            sage: S = [ i for i in range(16) ]
            sage: P = {}
                   sage: for i in range(15): P[i] = 2^(-i-1)
            sage: P[15] = 2^-16
            sage: X = DiscreteProbabilitySpace(S,P)
            sage: X.domain()
            (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
            sage: X.set()
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
            sage: X.entropy().n()
            1.99972534179688

        A probability space can be defined on any list of elements::

            sage: AZ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            sage: S = [ AZ[i] for i in range(26) ]
            sage: P = { 'A':1/2, 'B':1/4, 'C':1/4 }
            sage: X = DiscreteProbabilitySpace(S,P)
            sage: X
            Discrete probability space defined by {'A': 1/2, 'C': 1/4, 'B': 1/4}
            sage: X.entropy().n()
            1.50000000000000
        """
        if codomain is None:
            codomain = RealField()
        if not is_RealField(codomain) and not is_RationalField(codomain):
            raise TypeError(
                "Argument codomain (= %s) must be the reals or rationals" %
                codomain)
        if check:
            one = sum([P[x] for x in P.keys()])
            if is_RationalField(codomain):
                if not one == 1:
                    raise TypeError(
                        "Argument P (= %s) does not define a probability function"
                    )
            else:
                if not Abs(one - 1) < 2 ^ (-codomain.precision() + 1):
                    raise TypeError(
                        "Argument P (= %s) does not define a probability function"
                    )
        ProbabilitySpace_generic.__init__(self, X, codomain)
        DiscreteRandomVariable.__init__(self, self, P, codomain, check)
示例#12
0
def hypergeometric_U(alpha, beta, x, algorithm="pari", prec=53):
    r"""
    Default is a wrap of PARI's hyperu(alpha,beta,x) function.
    Optionally, algorithm = "scipy" can be used.

    The confluent hypergeometric function `y = U(a,b,x)` is
    defined to be the solution to Kummer's differential equation

    .. math::

             xy'' + (b-x)y' - ay = 0.

    This satisfies `U(a,b,x) \sim x^{-a}`, as
    `x\rightarrow \infty`, and is sometimes denoted
    ``x^{-a}2_F_0(a,1+a-b,-1/x)``. This is not the same as Kummer's
    `M`-hypergeometric function, denoted sometimes as
    ``_1F_1(alpha,beta,x)``, though it satisfies the same DE that
    `U` does.

    .. warning::

       In the literature, both are called "Kummer confluent
       hypergeometric" functions.

    EXAMPLES::

        sage: hypergeometric_U(1,1,1,"scipy")
        0.596347362323...
        sage: hypergeometric_U(1,1,1)
        0.59634736232319...
        sage: hypergeometric_U(1,1,1,"pari",70)
        0.59634736232319407434...
    """
    if algorithm == "scipy":
        if prec != 53:
            raise ValueError(
                "for the scipy algorithm the precision must be 53")
        import scipy.special
        ans = str(scipy.special.hyperu(float(alpha), float(beta), float(x)))
        ans = ans.replace("(", "")
        ans = ans.replace(")", "")
        ans = ans.replace("j", "*I")
        return sage_eval(ans)
    elif algorithm == 'pari':
        from sage.libs.pari.all import pari
        R = RealField(prec)
        return R(pari(R(alpha)).hyperu(R(beta), R(x), precision=prec))
    else:
        raise ValueError("unknown algorithm '%s'" % algorithm)
示例#13
0
def c3_func(SUK, prec=106):
    r"""
    Return the constant `c_3` from Smart's 1995 TCDF paper, [Sma1995]_

    INPUT:

    - ``SUK`` -- a group of `S`-units
    - ``prec`` -- (default: 106) the precision of the real field

    OUTPUT:

    The constant ``c3``, as a real number

    EXAMPLES::

        sage: from sage.rings.number_field.S_unit_solver import c3_func
        sage: K.<xi> = NumberField(x^3-3)
        sage: SUK = UnitGroup(K, S=tuple(K.primes_above(3)))

        sage: c3_func(SUK) # abs tol 1e-29
        0.4257859134798034746197327286726

    .. NOTE::

        The numerator should be as close to 1 as possible, especially as the rank of the `S`-units grows large

    REFERENCES:

    - [Sma1995]_ p. 823

    """

    R = RealField(prec)

    all_places = list(SUK.primes()) + SUK.number_field().places(prec)
    Possible_U = Combinations(all_places, SUK.rank())
    c1 = R(0)
    for U in Possible_U:
        # first, build the matrix C_{i,U}
        columns_of_C = []
        for unit in SUK.fundamental_units():
            columns_of_C.append(column_Log(SUK, unit, U, prec))
        C = Matrix(SUK.rank(), SUK.rank(), columns_of_C)
        # Is it invertible?
        if abs(C.determinant()) > 10**(-10):
            poss_c1 = C.inverse().apply_map(abs).norm(Infinity)
            c1 = R(max(poss_c1, c1))
    return R(0.9999999) / (c1*SUK.rank())
示例#14
0
def quadratic_L_function__numerical(n, d, num_terms=1000):
    """
    Evaluate the Dirichlet L-function (for quadratic character) numerically
    (in a very naive way).

    EXAMPLES:

    First, let us test several values for a given character::

        sage: RR = RealField(100)
        sage: for i in range(5):
        ....:     print("L({}, (-4/.)): {}".format(1+2*i, RR(quadratic_L_function__exact(1+2*i, -4)) - quadratic_L_function__numerical(RR(1+2*i),-4, 10000)))
        L(1, (-4/.)): 0.000049999999500000024999996962707
        L(3, (-4/.)): 4.99999970000003...e-13
        L(5, (-4/.)): 4.99999922759382...e-21
        L(7, (-4/.)): ...e-29
        L(9, (-4/.)): ...e-29

    This procedure fails for negative special values, as the Dirichlet
    series does not converge here::

        sage: quadratic_L_function__numerical(-3,-4, 10000)
        Traceback (most recent call last):
        ...
        ValueError: the Dirichlet series does not converge here

    Test for several characters that the result agrees with the exact
    value, to a given accuracy ::

        sage: for d in range(-20,0):  # long time (2s on sage.math 2014)
        ....:     if abs(RR(quadratic_L_function__numerical(1, d, 10000) - quadratic_L_function__exact(1, d))) > 0.001:
        ....:         print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d))))
    """
    # Set the correct precision if it is given (for n).
    if isinstance(n.parent(), sage.rings.abc.RealField):
        R = n.parent()
    else:
        from sage.rings.real_mpfr import RealField
        R = RealField()

    if n < 0:
        raise ValueError('the Dirichlet series does not converge here')

    d1 = fundamental_discriminant(d)
    ans = R.zero()
    for i in range(1,num_terms):
        ans += R(kronecker_symbol(d1,i) / R(i)**n)
    return ans
示例#15
0
def K0_func(SUK, A, prec=106):
    r"""
    Return the constant `K_0` from Smart's TCDF paper, [Sma1995]_

    INPUT:

    - ``SUK`` -- a group of `S`-units
    - ``A`` -- the set of the products of the coefficients of the `S`-unit equation with each root of unity of ``K``
    - ``prec`` -- (default: 106) the precision of the real field

    OUTPUT:

    The constant ``K0``, a real number

    EXAMPLES::

        sage: from sage.rings.number_field.S_unit_solver import K0_func
        sage: K.<xi> = NumberField(x^3-3)
        sage: SUK = UnitGroup(K, S=tuple(K.primes_above(3)))
        sage: A = K.roots_of_unity()

        sage: K0_func(SUK, A) # abs tol 1e-29
        9.475576673109275443280257946929e17

    REFERENCES:

    - [Sma1995]_ p. 824
    """
    R = RealField(prec)

    def c5_func(SUK, v, R):
        return c3_func(SUK, R.precision()) / (v.residue_class_degree()*R(v.smallest_integer()).log()*v.ramification_index())

    def c6_func(SUK, v, A, R):
        return c4_func(SUK, v, A, R.precision()).log() / (v.residue_class_degree()*R(v.smallest_integer()).log()*v.ramification_index())

    def c7_func(SUK, v, A, R):
        return (c4_func(SUK, v, A, R.precision())).log() / c3_func(SUK, R.precision())

    def c10_func(SUK, v, A, R):
        # [Sma1995]_ p. 824
        e_h = v.ramification_index()
        c_8, c_9 = c8_c9_func(SUK, v, A, R.precision())
        return (2/(e_h*c5_func(SUK, v, R))) * (e_h*c6_func(SUK, v, A, R)+c_9+c_8*(c_8/(e_h*c5_func(SUK, v, R))).log())

    return R(max([c10_func(SUK,v, A, R) for v in SUK.primes()] + [c7_func(SUK,v,A,R) for v in SUK.primes()]))
示例#16
0
    def __init__(self, X, f, codomain = None, check = False):
        r"""
        Create free binary string monoid on `n` generators.

        INPUT: x: A probability space f: A dictionary such that X[x] =
        value for x in X is the discrete function on X
        """
        if not is_DiscreteProbabilitySpace(X):
            raise TypeError("Argument X (= %s) must be a discrete probability space" % X)
        if check:
            raise NotImplementedError("Not implemented")
        if codomain is None:
            RR = RealField()
        else:
            RR = codomain
        RandomVariable_generic.__init__(self, X, RR)
        self._function = f
示例#17
0
def c11_func(SUK, v, A, prec=106):
    r"""
    Return the constant `c_{11}` from Smart's TCDF paper, [Sma1995]_

    INPUT:

    - ``SUK`` -- a group of `S`-units
    - ``v`` -- a place of ``K``, finite (a fractional ideal) or infinite (element of ``SUK.number_field().places(prec)``)
    - ``A`` -- the set of the product of the coefficients of the `S`-unit equation with each root of unity of ``K``
    - ``prec`` -- (default: 106) the precision of the real field

    OUTPUT:

    The constant ``c11``, a real number

    EXAMPLES::

        sage: from sage.rings.number_field.S_unit_solver import c11_func
        sage: K.<xi> = NumberField(x^3-3)
        sage: SUK = UnitGroup(K, S=tuple(K.primes_above(3)))
        sage: phi_real = K.places()[0]
        sage: phi_complex = K.places()[1]
        sage: A = K.roots_of_unity()

        sage: c11_func(SUK, phi_real, A) # abs tol 1e-29
        3.255848343572896153455615423662

        sage: c11_func(SUK, phi_complex, A) # abs tol 1e-29
        6.511696687145792306911230847323

    REFERENCES:

    - [Sma1995]_ p. 825
    """
    R = RealField(prec)
    if is_real_place(v):
        return R(4*c4_func(SUK, v, A, prec)).log() / c3_func(SUK, prec)
    else:
        return 2*R(4*(c4_func(SUK, v, A, prec)).sqrt()).log() / c3_func(SUK, prec)
示例#18
0
def removeConstants(list1, list2, pars):
    '''
	Remove constant expresions from list1 and list2.
	If the constant expresion does not contain any parameter, it is just removed
	otherwise it is moved into constList1 and constList2
	'''
    i = 0
    RR = RealField()  # define Real field
    constList1 = []
    constList2 = []
    while i < len(list1):
        if (list1[i] in RR
            ):  # checks if it is a Real Number of SAGE (no parameters at all)
            list1.pop(i)
            list2.pop(i)
        elif expresionIsConstant(list1[i],
                                 pars):  # checks if there are only parameters
            constList1.append(list1.pop(i))
            constList2.append(list2.pop(i))
        else:
            i += 1
    return constList1, constList2
示例#19
0
文件: tides.py 项目: wdv4758h/sage
def remove_constants(l1,l2):
    """
    Given two lists, remove the entries in the first that are real constants,
    and also the corresponding elements in the second one.

        sage: from sage.interfaces.tides import subexpressions_list, remove_constants
        sage: f(a)=[1+cos(7)*a]
        sage: l1, l2 = subexpressions_list(f)
        sage: l1, l2
        ([sin(7), cos(7), a*cos(7), a*cos(7) + 1],
        [('sin', 7), ('cos', 7), ('mul', cos(7), a), ('add', 1, a*cos(7))])
        sage: remove_constants(l1,l2)
        sage: l1, l2
        ([a*cos(7), a*cos(7) + 1], [('mul', cos(7), a), ('add', 1, a*cos(7))])

    """
    i=0
    while i < len(l1):
        if l1[i] in RealField():
            l1.pop(i)
            l2.pop(i)
        else:
            i+=1
示例#20
0
文件: infinity.py 项目: yarv/sage
    def _coerce_map_from_(self, R):
        r"""
        There is a coercion from anything that has a coercion into the reals.

        The way Sage works is that everything that should be
        comparable with infinity can be coerced into the infinity
        ring, so if you ever compare with infinity the comparison is
        done there. If you don't have a coercion then you will get
        undesirable answers from the fallback comparison (likely
        memory location).

        EXAMPLES::

            sage: InfinityRing.has_coerce_map_from(int) # indirect doctest
            True
            sage: InfinityRing.has_coerce_map_from(AA)
            True
            sage: InfinityRing.has_coerce_map_from(RDF)
            True
            sage: InfinityRing.has_coerce_map_from(RIF)
            True

        As explained above, comparison works by coercing to the
        infinity ring::

            sage: cm = get_coercion_model()
            sage: cm.explain(AA(3), oo, operator.lt)
            Coercion on left operand via
                Coercion map:
                  From: Algebraic Real Field
                  To:   The Infinity Ring
            Arithmetic performed after coercions.
            Result lives in The Infinity Ring
            The Infinity Ring

        The symbolic ring does not coerce to the infinity ring, so
        symbolic comparisons with infinities all happen in the
        symbolic ring::

            sage: SR.has_coerce_map_from(InfinityRing)
            True
            sage: InfinityRing.has_coerce_map_from(SR)
            False

        Complex numbers do not coerce into the infinity ring (what
        would `i \infty` coerce to?). This is fine since they can not
        be compared, so we do not have to enforce consistency when
        comparing with infinity either::

            sage: InfinityRing.has_coerce_map_from(CDF)
            False
            sage: InfinityRing.has_coerce_map_from(CC)
            False
            sage: CC(0, oo) < CC(1)   # does not coerce to infinity ring
            True
        """
        from sage.rings.real_mpfr import mpfr_prec_min, RealField
        if RealField(mpfr_prec_min()).has_coerce_map_from(R):
            return True
        from sage.rings.real_mpfi import RealIntervalField_class
        if isinstance(R, RealIntervalField_class):
            return True
        try:
            from sage.rings.real_arb import RealBallField
            if isinstance(R, RealBallField):
                return True
        except ImportError:
            pass
        return False
示例#21
0
def epsinv(F, target, prec=53, target_tol=0.001, z=None, emb=None):
    """
    Compute a bound on the hyperbolic distance.

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

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

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

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

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

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

    - ``emb`` -- embedding into CC

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

    EXAMPLES::

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

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

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

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

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

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

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

    # first find an interval containing the desired value
    # then use regula falsi on log eps_F
    # d -> delta value in interval [0,1]
    # v in value in interval [1,epsF(1)]
    dl = R(0.0)
    vl = R(1.0)
    du = R(1.0)
    vu = epsF(du)
    while vu < target:
        # compute the next value of epsF for delta = 2*delta
        dl = du
        vl = vu
        du *= 2
        vu = epsF(du)
    # now dl < delta <= du
    logt = target.log()
    l2 = (vu.log() - logt).n(prec=prec)
    l1 = (vl.log() - logt).n(prec=prec)
    dn = (dl * l2 - du * l1) / (l2 - l1)
    vn = epsF(dn)
    dl = du
    vl = vu
    du = dn
    vu = vn
    while (du - dl).abs() >= target_tol or max(vl, vu) < target:
        l2 = (vu.log() - logt).n(prec=prec)
        l1 = (vl.log() - logt).n(prec=prec)
        dn = (dl * l2 - du * l1) / (l2 - l1)
        vn = epsF(dn)
        dl = du
        vl = vu
        du = dn
        vu = vn
    return max(dl, du)
示例#22
0
文件: tides.py 项目: wdv4758h/sage
def genfiles_mpfr(integrator, driver, f, ics, initial, final, delta,
                  parameters = None , parameter_values = None, dig = 20, tolrel=1e-16,
                  tolabs=1e-16, output = ''):
    r"""
        Generate the needed files for the mpfr module of the tides library.

    INPUT:

    - ``integrator`` -- the name of the integrator file.

    - ``driver`` -- the name of the driver file.

    - ``f`` -- the function that determines the differential equation.

    - ``ics`` -- a list or tuple with the initial conditions.

    - ``initial`` -- the initial time for the integration.

    - ``final`` -- the final time for the integration.

    - ``delta`` -- the step of the output.

    - ``parameters`` -- the variables inside the function that should be treated
       as parameters.

    - ``parameter_values`` -- the values of the parameters for the particular
       initial value problem.

    - ``dig`` -- the number of digits of precission that will be used in the integration

    - ``tolrel`` -- the relative tolerance.

    - ``tolabs`` -- the absolute tolerance.

    -  ``output`` -- the name of the file that the compiled integrator will write to

    This function creates two files, integrator and driver, that can be used
    later with the tides library ([TI]_).


    TESTS::

        sage: from tempfile import mkdtemp
        sage: from sage.interfaces.tides import genfiles_mpfr
        sage: import os
        sage: import shutil
        sage: from sage.misc.temporary_file import tmp_dir
        sage: tempdir = tmp_dir()
        sage: intfile = os.path.join(tempdir, 'integrator.c')
        sage: drfile = os.path.join(tempdir ,'driver.c')
        sage: var('t,x,y,X,Y')
        (t, x, y, X, Y)
        sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)]
        sage: genfiles_mpfr(intfile, drfile, f, [1,0, 0, 0.2], 0, 10, 0.1, output = 'out', dig = 50)
        sage: fileint = open(intfile)
        sage: l = fileint.readlines()
        sage: fileint.close()
        sage: l[5]
        '    #include "mp_tides.h"\n'
        sage: l[15]
        '\tstatic int PARAMETERS = 0;\n'
        sage: l[25]
        '\t\tmpfrts_var_t(itd, link[5], var[3], i);\n'
        sage: l[30]
        '\t\tmpfrts_pow_t_c(itd, link[2], "-1.500000000000000000000000000000000000000000000000000", link[3], i);\n'
        sage: l[35]
        '\n'
        sage: l[36]
        '    }\n'
        sage: l[37]
        '    write_mp_solution();\n'
        sage: filedr = open(drfile)
        sage: l = filedr.readlines()
        sage: filedr.close()
        sage: l[6]
        '    #include "mpfr.h"\n'
        sage: l[16]
        '    int nfun = 0;\n'
        sage: l[26]
        '\tmpfr_set_str(v[2], "0.0000000000000000000000000000000000000000000000000000", 10, TIDES_RND);\n'
        sage: l[30]
        '\tmpfr_init2(tolabs, TIDES_PREC); \n'
        sage: l[34]
        '\tmpfr_init2(tini, TIDES_PREC); \n'
        sage: l[40]
        '\tmp_tides_delta(function_iteration, NULL, nvar, npar, nfun, v, p, tini, dt, nipt, tolrel, tolabs, NULL, fd);\n'
        sage: shutil.rmtree(tempdir)

    Check that ticket :trac:`17179` is fixed (handle expressions like `\\pi`)::

        sage: from sage.interfaces.tides import genfiles_mpfr
        sage: import os
        sage: import shutil
        sage: from sage.misc.temporary_file import tmp_dir
        sage: tempdir = tmp_dir()
        sage: intfile = os.path.join(tempdir, 'integrator.c')
        sage: drfile = os.path.join(tempdir ,'driver.c')
        sage: var('t,x,y,X,Y')
        (t, x, y, X, Y)
        sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)]
        sage: genfiles_mpfr(intfile, drfile, f, [pi, 0, 0, 0.2], 0, 10, 0.1, output = 'out', dig = 50)
        sage: fileint = open(intfile)
        sage: l = fileint.readlines()
        sage: fileint.close()
        sage: l[30]
        '\t\tmpfrts_pow_t_c(itd, link[2], "-1.500000000000000000000000000000000000000000000000000", link[3], i);\n'
        sage: filedr = open(drfile)
        sage: l = filedr.readlines()
        sage: filedr.close()
        sage: l[24]
        '\tmpfr_set_str(v[0], "3.141592653589793238462643383279502884197169399375101", 10, TIDES_RND);\n'
        sage: shutil.rmtree(tempdir)

    """
    if parameters == None:
        parameters = []
    if parameter_values == None:
        parameter_values = []
    RR = RealField(ceil(dig * 3.3219))
    l1, l2 = subexpressions_list(f, parameters)
    remove_repeated(l1, l2)
    remove_constants(l1, l2)
    l3=[]
    var = f[0].arguments()
    l0 = map(str, l1)
    lv = map(str, var)
    lp = map(str, parameters)
    for i in l2:
        oper = i[0]
        if oper in ["log", "exp", "sin", "cos", "atan", "asin", "acos"]:
            a = i[1]
            if str(a) in lv:
                l3.append((oper, 'var[{}]'.format(lv.index(str(a)))))
            elif str(a) in lp:
                l3.append((oper, 'par[{}]'.format(lp.index(str(a)))))
            else:
                l3.append((oper, 'link[{}]'.format(l0.index(str(a)))))

        else:
            a=i[1]
            b=i[2]
            sa = str(a)
            sb = str(b)
            consta=False
            constb=False

            if sa in lv:
                aa = 'var[{}]'.format(lv.index(sa))
            elif sa in l0:
                aa = 'link[{}]'.format(l0.index(sa))
            elif sa in lp:
                aa = 'par[{}]'.format(lp.index(sa))
            else:
                consta=True
                aa = RR(a).str(truncate=False)
            if sb in lv:
                bb = 'var[{}]'.format(lv.index(sb))
            elif sb in l0:
                bb = 'link[{}]'.format(l0.index(sb))
            elif sb in lp:
                bb = 'par[{}]'.format(lp.index(sb))
            else:
                constb=True
                bb = RR(b).str(truncate=False)
            if consta:
                oper += '_c'
                if not oper=='div':
                    bb, aa = aa,bb
            elif constb:
                oper += '_c'
            l3.append((oper, aa, bb))


    n = len(var)
    code = []


    l0 = lv + l0
    indices = [l0.index(str(i(*var)))+n for i in f]
    for i in range (1, n):
        aux = indices[i-1]-n
        if aux < n:
            code.append('mpfrts_var_t(itd, var[{}], var[{}], i);'.format(aux, i))
        else:
            code.append('mpfrts_var_t(itd, link[{}], var[{}], i);'.format(aux-n, i))

    for i in range(len(l3)):
        el = l3[i]
        string = "mpfrts_"
        if el[0] == 'add':
            string += 'add_t(itd, ' + el[1] + ', ' + el[2] + ', link[{}], i);'.format(i)
        elif el[0] == 'add_c':
            string += 'add_t_c(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i)
        elif el[0] == 'mul':
            string += 'mul_t(itd, ' + el[1] + ', ' + el[2] + ', link[{}], i);'.format(i)
        elif el[0] == 'mul_c':
            string += 'mul_t_c(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i)
        elif el[0] == 'pow_c':
            string += 'pow_t_c(itd, ' + el[1] + ', "' + el[2] + '", link[{}], i);'.format(i)
        elif el[0] == 'div':
            string += 'div_t(itd, ' + el[2] + ', ' + el[1] + ', link[{}], i);'.format(i)
        elif el[0] == 'div_c':
            string += 'div_t_cv(itd, "' + el[2] + '", ' + el[1] + ', link[{}], i);'.format(i)
        elif el[0] == 'log':
            string += 'log_t(itd, ' + el[1]  + ', link[{}], i);'.format(i)
        elif el[0] == 'exp':
            string += 'exp_t(itd, ' + el[1]  + ', link[{}], i);'.format(i)
        elif el[0] == 'sin':
            string += 'sin_t(itd, ' + el[1]  + ', link[{}], link[{}], i);'.format(i+1, i)
        elif el[0] == 'cos':
            string += 'cos_t(itd, ' + el[1]  + ', link[{}], link[{}], i);'.format(i-1, i)
        elif el[0] == 'atan':
            indarg = l0.index(str(1+l2[i][1]**2))-n
            string += 'atan_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i)
        elif el[0] == 'asin':
            indarg = l0.index(str(sqrt(1-l2[i][1]**2)))-n
            string += 'asin_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i)
        elif el[0] == 'acos':
            indarg = l0.index(str(-sqrt(1-l2[i][1]**2)))-n
            string += 'acos_t(itd, ' + el[1] + ', link[{}], link[{}], i);'.format(indarg, i)
        code.append(string)

    VAR = n-1
    PAR = len(parameters)
    TT =  len(code)+1-VAR

    outfile = open(integrator, 'a')

    auxstring = """
    /****************************************************************************
    This file has been created by Sage for its use with TIDES
    *****************************************************************************/

    #include "mp_tides.h"

    long  function_iteration(iteration_data *itd, mpfr_t t, mpfr_t v[], mpfr_t p[], int ORDER, mpfr_t *cvfd)
    {

    int i;
    int NCONST = 0;
    mpfr_t ct[0];
    """

    outfile.write(auxstring)

    outfile.write("\n\tstatic int VARIABLES = {};\n".format(VAR))
    outfile.write("\tstatic int PARAMETERS = {};\n".format(PAR))
    outfile.write("\tstatic int LINKS = {};\n".format(TT))
    outfile.write('\tstatic int   FUNCTIONS        = 0;\n')
    outfile.write('\tstatic int   POS_FUNCTIONS[1] = {0};\n')
    outfile.write('\n\tinitialize_mp_case();\n')
    outfile.write('\n\tfor(i=0;  i<=ORDER; i++) {\n')
    for i in code:
        outfile.write('\t\t'+i+'\n')

    auxstring = """
    }
    write_mp_solution();
    clear_vpl();
    clear_cts();
    return NUM_COLUMNS;
}
    """
    outfile.write(auxstring)
    outfile.close()


    npar = len(parameter_values)
    outfile = open(driver, 'a')

    auxstring = """
    /****************************************************************************
    Driver file of the mp_tides program
    This file has been created automatically by Sage
    *****************************************************************************/

    #include "mpfr.h"
    #include "mp_tides.h"
    long  function_iteration(iteration_data *itd, mpfr_t t, mpfr_t v[], mpfr_t p[], int ORDER, mpfr_t *cvfd);

    int main() {

        int i;



    int nfun = 0;
    """
    outfile.write(auxstring)
    outfile.write('\tset_precision_digits({});'.format(dig))
    outfile.write('\n\tint npar = {};\n'.format(npar))
    outfile.write('\tmpfr_t p[npar];\n')
    outfile.write('\tfor(i=0; i<npar; i++) mpfr_init2(p[i], TIDES_PREC);\n')

    for i in range(npar):
        outfile.write('\tmpfr_set_str(p[{}], "{}", 10, TIDES_RND);\n'.format(i,RR(parameter_values[i]).str(truncate=False)))
    outfile.write('\tint nvar = {};\n\tmpfr_t v[nvar];\n'.format(VAR))
    outfile.write('\tfor(i=0; i<nvar; i++) mpfr_init2(v[i], TIDES_PREC);\n')
    for i in range(len(ics)):
        outfile.write('\tmpfr_set_str(v[{}], "{}", 10, TIDES_RND);\n'.format(i,RR(ics[i]).str(truncate=False)))
    outfile.write('\tmpfr_t tolrel, tolabs;\n')
    outfile.write('\tmpfr_init2(tolrel, TIDES_PREC); \n')
    outfile.write('\tmpfr_init2(tolabs, TIDES_PREC); \n')
    outfile.write('\tmpfr_set_str(tolrel, "{}", 10, TIDES_RND);\n'.format(RR(tolrel).str(truncate=False)))
    outfile.write('\tmpfr_set_str(tolabs, "{}", 10, TIDES_RND);\n'.format(RR(tolabs).str(truncate=False)))

    outfile.write('\tmpfr_t tini, dt; \n')
    outfile.write('\tmpfr_init2(tini, TIDES_PREC); \n')
    outfile.write('\tmpfr_init2(dt, TIDES_PREC); \n')


    outfile.write('\tmpfr_set_str(tini, "{}", 10, TIDES_RND);;\n'.format(RR(initial).str(truncate=False)))
    outfile.write('\tmpfr_set_str(dt, "{}", 10, TIDES_RND);\n'.format(RR(delta).str(truncate=False)))
    outfile.write('\tint nipt = {};\n'.format(floor((final-initial)/delta)))
    outfile.write('\tFILE* fd = fopen("' + output + '", "w");\n')
    outfile.write('\tmp_tides_delta(function_iteration, NULL, nvar, npar, nfun, v, p, tini, dt, nipt, tolrel, tolabs, NULL, fd);\n')
    outfile.write('\tfclose(fd);\n\treturn 0;\n}')
    outfile.close()
示例#23
0
文件: tides.py 项目: wdv4758h/sage
def genfiles_mintides(integrator, driver, f, ics, initial, final, delta,
                      tolrel=1e-16, tolabs=1e-16, output = ''):
    r"""
    Generate the needed files for the min_tides library.

    INPUT:

    - ``integrator`` -- the name of the integrator file.

    - ``driver`` -- the name of the driver file.

    - ``f`` -- the function that determines the differential equation.

    - ``ics`` -- a list or tuple with the initial conditions.

    - ``initial`` -- the initial time for the integration.

    - ``final`` -- the final time for the integration.

    - ``delta`` -- the step of the output.

    - ``tolrel`` -- the relative tolerance.

    - ``tolabs`` -- the absolute tolerance.

    -  ``output`` -- the name of the file that the compiled integrator will write to

    This function creates two files, integrator and driver, that can be used
    later with the min_tides library [TI]_.


    TESTS::

        sage: from sage.interfaces.tides import genfiles_mintides
        sage: import os
        sage: import shutil
        sage: from sage.misc.temporary_file import tmp_dir
        sage: tempdir = tmp_dir()
        sage: intfile = os.path.join(tempdir, 'integrator.c')
        sage: drfile = os.path.join(tempdir ,'driver.c')
        sage: var('t,x,y,X,Y')
        (t, x, y, X, Y)
        sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)]
        sage: genfiles_mintides(intfile, drfile, f, [1,0, 0, 0.2], 0, 10, 0.1, output = 'out')
        sage: fileint = open(intfile)
        sage: l = fileint.readlines()
        sage: fileint.close()
        sage: l[5]
        '    #include "minc_tides.h"\n'
        sage: l[15]
        '    double XX[TT+1][MO+1];\n'
        sage: l[25]
        '\n'
        sage: l[35]
        '\t\tXX[1][i+1] = XX[3][i] / (i+1.0);\n'
        sage: filedr = open(drfile)
        sage: l = filedr.readlines()
        sage: filedr.close()
        sage: l[6]
        '    #include "minc_tides.h"\n'
        sage: l[15]
        '    double tolrel, tolabs, tini, tend, dt;\n'
        sage: l[25]
        '\ttolrel = 9.9999999999999998e-17 ;\n'
        sage: shutil.rmtree(tempdir)

    Check that ticket :trac:`17179` is fixed (handle expressions like `\\pi`)::

        sage: from sage.interfaces.tides import genfiles_mintides
        sage: import os
        sage: import shutil
        sage: from sage.misc.temporary_file import tmp_dir
        sage: tempdir = tmp_dir()
        sage: intfile = os.path.join(tempdir, 'integrator.c')
        sage: drfile = os.path.join(tempdir ,'driver.c')
        sage: var('t,x,y,X,Y')
        (t, x, y, X, Y)
        sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)]
        sage: genfiles_mintides(intfile, drfile, f, [pi, 0, 0, 0.2], 0, 10, 0.1, output = 'out')
        sage: fileint = open(intfile)
        sage: l = fileint.readlines()
        sage: fileint.close()
        sage: l[30]
        '\t\tXX[8][i] = pow_mc_c(XX[7],-1.5000000000000000,XX[8], i);\n'
        sage: filedr = open(drfile)
        sage: l = filedr.readlines()
        sage: filedr.close()
        sage: l[18]
        '    \tv[0] = 3.1415926535897931 ; \n'
        sage: shutil.rmtree(tempdir)


    """
    RR = RealField()

    l1, l2 = subexpressions_list(f)

    remove_repeated(l1, l2)
    remove_constants(l1, l2)
    l0 = map(str, l1)
    #generate the corresponding c lines

    l3=[]
    var = f[0].arguments()
    lv = map(str, var)
    for i in l2:
        oper = i[0]
        if oper in ["log", "exp", "sin", "cos"]:
            a = i[1]
            if a in var:
                l3.append((oper, 'XX[{}]'.format(lv.index(str(a)))))
            elif a in l1:
                l3.append((oper, 'XX[{}]'.format(l0.index(str(a))+len(var))))

        else:
            a=i[1]
            b=i[2]
            consta=False
            constb=False

            if str(a) in lv:
                aa = 'XX[{}]'.format(lv.index(str(a)))
            elif str(a) in l0:
                aa = 'XX[{}]'.format(l0.index(str(a))+len(var))
            else:
                consta=True
                aa = RR(a).str(truncate=False)
            if str(b) in lv:
                bb = 'XX[{}]'.format(lv.index(str(b)))
            elif str(b) in l0:
                bb = 'XX[{}]'.format(l0.index(str(b))+len(var))
            else:
                constb = True
                bb = RR(b).str(truncate=False)
            if consta:
                oper += '_c'
                if not oper=='div':
                    bb, aa = aa, bb
            elif constb:
                oper += '_c'
            l3.append((oper, aa, bb))


    n = len(var)
    res = []
    for i in range(len(l3)):
        el = l3[i]
        string = "XX[{}][i] = ".format(i + n)
        if el[0] == 'add':
            string += el[1] + "[i] + " + el[2] +"[i];"
        elif el[0] == 'add_c':
            string += "(i==0)? {}+".format(el[2]) + el[1] + "[0] : "+ el[1]+ "[i];"
        elif el[0] == 'mul':
            string += "mul_mc("+el[1]+","+el[2]+",i);"
        elif el[0] == 'mul_c':
            string += el[2] + "*"+ el[1] + "[i];"
        elif el[0] == 'pow_c':
            string += "pow_mc_c("+el[1]+","+el[2]+",XX[{}], i);".format(i+n)
        elif el[0] == 'div':
            string += "div_mc("+el[2]+","+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'div_c':
            string += "inv_mc("+el[2]+","+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'log':
            string += "log_mc("+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'exp':
            string += "exp_mc("+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'sin':
            string += "sin_mc("+el[1]+",XX[{}], i);".format(i+n+1)
        elif el[0] == 'cos':
            string += "cos_mc("+el[1]+",XX[{}], i);".format(i+n-1)


        res.append(string)

    l0 = lv + l0
    indices = [l0.index(str(i(*var))) + n for i in f]
    for i in range (1, n):
        res.append("XX[{}][i+1] = XX[{}][i] / (i+1.0);".format(i,indices[i-1]-n))


    code = res


    outfile = open(integrator, 'a')
    auxstring = """
    /****************************************************************************
    This file has been created by Sage for its use with TIDES
    *****************************************************************************/

    #include "minc_tides.h"

    void    mincseries(double t,double *v, double *p, double **XVAR,int ORDER, int MO)
    {
    int VAR,PAR,TT,i,j, inext;
    """
    outfile.write(auxstring)

    outfile.write("\tVAR = {};\n".format(n))
    outfile.write("\tPAR = {};\n".format(0))
    outfile.write("\tTT = {};\n".format(len(res)))

    auxstring = """

    double XX[TT+1][MO+1];

    for(j=0; j<=TT; j++)
        for(i=0; i<=ORDER; i++)
            XX[j][i] = 0.e0;
    XX[0][0] = t;
    XX[0][1] = 1.e0;
    for(i=1;i<=VAR;i++) {
        XX[i][0] = v[i-1];
    }

    for(i=0;i<ORDER;i++) {
    """
    outfile.write(auxstring)
    outfile.writelines(["\t\t"+i+"\n" for i in code])

    outfile.write('\t}\n')
    outfile.write('\n')
    outfile.write('\tfor(j=0; j<=VAR; j++)\n')
    outfile.write('\t\tfor(i=0; i<=ORDER; i++)\n')
    outfile.write('\t\t\tXVAR[i][j] = XX[j][i];\n')
    outfile.write('}\n')
    outfile.write('\n')

    outfile = open(driver, 'a')

    auxstring = """
    /****************************************************************************
        Driver file of the minc_tides program
        This file has been automatically created by Sage
    *****************************************************************************/

    #include "minc_tides.h"

    int main() {

        int  i, VARS, PARS;


    VARS = %s ;
    PARS = 1;
    double tolrel, tolabs, tini, tend, dt;
    double v[VARS], p[PARS];

    """%(n-1)
    outfile.write(auxstring)
    for i in range(len(ics)):
        outfile.write('\tv[{}] = {} ; \n'.format(i, RR(ics[i]).str(truncate=False)))
    outfile.write('\ttini = {} ;\n'.format(RR(initial).str(truncate=False)))
    outfile.write('\ttend = {} ;\n'.format(RR(final).str(truncate=False)))
    outfile.write('\tdt   = {} ;\n'.format(RR(delta).str(truncate=False)))
    outfile.write('\ttolrel = {} ;\n'.format(RR(tolrel).str(truncate=False)))
    outfile.write('\ttolabs = {} ;\n'.format(RR(tolabs).str(truncate=False)))
    outfile.write('\textern char ofname[500];')
    outfile.write('\tstrcpy(ofname, "'+ output +'");\n')
    outfile.write('\tminc_tides(v,VARS,p,PARS,tini,tend,dt,tolrel,tolabs);\n')
    outfile.write('\treturn 0; \n }')
    outfile.close()
示例#24
0
def bessel_K(nu, z, algorithm="pari", prec=53):
    r"""
    Implements the "K-Bessel function", or "modified Bessel function,
    2nd kind", with index (or "order") nu and argument z. Defn::
    
                    pi*(bessel_I(-nu, z) - bessel_I(nu, z))
                   ----------------------------------------
                                2*sin(pi*nu)
            
    
    if nu is not an integer and by taking a limit otherwise.
    
    Sometimes bessel_K(nu,z) is denoted K_nu(z) in the literature. In
    PARI, nu can be complex and z must be real and positive.
    
    EXAMPLES::
    
        sage: bessel_K(3,2,"scipy")
        0.64738539094...
        sage: bessel_K(3,2)
        0.64738539094...
        sage: bessel_K(1,1)
        0.60190723019...
        sage: bessel_K(1,1,"pari",10)
        0.60
        sage: bessel_K(1,1,"pari",100)
        0.60190723019723457473754000154

    TESTS::

        sage: bessel_K(2,1.1, algorithm="maxima")
        Traceback (most recent call last):
        ...
        NotImplementedError: The K-Bessel function is only implemented for the pari and scipy algorithms

        Check whether the return value is real whenever the argument is real (#10251)::

        sage: bessel_K(5, 1.5, algorithm='scipy') in RR
        True

    """
    if algorithm == "scipy":
        if prec != 53:
            raise ValueError, "for the scipy algorithm the precision must be 53"
        import scipy.special
        ans = str(scipy.special.kv(float(nu), float(z)))
        ans = ans.replace("(", "")
        ans = ans.replace(")", "")
        ans = ans.replace("j", "*I")
        ans = sage_eval(ans)
        return real(ans) if z in RR else ans
    elif algorithm == 'pari':
        from sage.libs.pari.all import pari
        try:
            R = RealField(prec)
            nu = R(nu)
            z = R(z)
        except TypeError:
            C = ComplexField(prec)
            nu = C(nu)
            z = C(z)
            K = C
        K = z.parent()
        return K(pari(nu).besselk(z, precision=prec))
    elif algorithm == 'maxima':
        raise NotImplementedError, "The K-Bessel function is only implemented for the pari and scipy algorithms"
    else:
        raise ValueError, "unknown algorithm '%s'" % algorithm
示例#25
0
文件: maple.py 项目: kliem/sage
    def _sage_(self):
        r"""
        Convert a maple expression back to a Sage expression.

        This currently does not implement a parser for the Maple output language,
        therefore only very simple expressions will convert successfully.

        REFERENCE:

        https://www.asc.tuwien.ac.at/compmath/download/Monagan_Maple_Programming.pdf

        EXAMPLES::

            sage: m = maple('x^2 + 5*y')        # optional - maple
            sage: m.sage()                      # optional - maple
            x^2 + 5*y
            sage: m._sage_()                    # optional - maple
            x^2 + 5*y

            sage: m = maple('sin(sqrt(1-x^2)) * (1 - cos(1/x))^2')  # optional - maple
            sage: m.sage()                                          # optional - maple
            (cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1))

        Some matrices can be converted back::

            sage: m = matrix(2, 2, [1, 2, x, 3])    # optional - maple
            sage: mm = maple(m)                     # optional - maple
            sage: mm.sage() == m                    # optional - maple
            True

        Some vectors can be converted back::

            sage: m = vector([1, x, 2, 3])          # optional - maple
            sage: mm = maple(m)                     # optional - maple
            sage: mm.sage() == m                    # optional - maple
            True

        Integers and rationals are converted as such::

            sage: maple(33).sage().parent()         # optional - maple
            Integer Ring
            sage: maple(191/5).sage().parent()      # optional - maple
            Rational Field

        Sets, lists, sequences::

            sage: maple("[4,5,6]").sage()           # optional - maple
            [4, 5, 6]
            sage: maple({14,33,6}).sage()           # optional - maple
            {6, 14, 33}
            sage: maple("seq(i**2,i=1..5)").sage()  # optional - maple
            (1, 4, 9, 16, 25)

        Strings::

            sage: maple('"banane"').sage()          # optional - maple
            '"banane"'

        Floats::

            sage: Z3 = maple('evalf(Zeta(3))')   # optional - maple
            sage: Z3.sage().parent()             # optional - maple
            Real Field with 53 bits of precision

            sage: sq5 = maple('evalf(sqrt(5),100)')   # optional - maple
            sage: sq5 = sq5.sage(); sq5               # optional - maple
            2.23606797749978969640...
            sage: sq5.parent()                        # optional - maple
            Real Field with 332 bits of precision

        Functions are not yet converted back correctly::

            sage: maple(hypergeometric([3,4],[5],x))  # optional - maple
            hypergeom([3, 4],[5],x)
            sage: _.sage()                # known bug # optional - maple
            hypergeometric((3, 4), (5,), x)
        """
        from sage.matrix.constructor import matrix
        from sage.modules.free_module_element import vector
        from sage.rings.integer_ring import ZZ
        # The next few lines are a very crude excuse for a maple "parser"
        maple_type = repr(self.whattype())
        result = repr(self)
        result = result.replace("Pi", "pi")
        if maple_type == 'symbol':       # pi
            pass   # left to symbolic ring
        elif maple_type == 'string':     # "banane"
            return result
        elif maple_type == 'exprseq':   # 2, 2
            n = self.parent()(f"[{self._name}]").nops()._sage_()
            return tuple(self[i] for i in range(1, n + 1))
        elif maple_type == 'set':        # {1, 2}
            n = self.nops()._sage_()
            return set(self.op(i)._sage_() for i in range(1, n + 1))
        elif maple_type == 'list':        # [1, 2]
            n = self.nops()._sage_()
            return [self.op(i)._sage_() for i in range(1, n + 1)]
        elif maple_type == "Matrix":     # Matrix(2, 2, [[1,2],[3,4]])
            mn = self.op(1)
            m = mn[1]._sage_()
            n = mn[2]._sage_()
            coeffs = [self[i + 1, j + 1]._sage_()
                      for i in range(m) for j in range(n)]
            return matrix(m, n, coeffs)
        elif maple_type[:6] == "Vector":  # Vector[row](3, [4,5,6])
            n = self.op(1)._sage_()
            return vector([self[i + 1]._sage_() for i in range(n)])
        elif maple_type == 'integer':
            return ZZ(result)
        elif maple_type == 'fraction':
            return self.op(1)._sage_() / self.op(2)._sage_()
        elif maple_type == "function":
            pass  # TODO : here one should translate back function names
        elif maple_type == "float":
            from sage.rings.real_mpfr import RealField
            mantissa = len(repr(self.op(1)))
            prec = max(53, (mantissa * 13301) // 4004)
            R = RealField(prec)
            return R(result)
        elif maple_type == '`=`':        # (1, 1) = 2
            return (self.op(1)._sage_() == self.op(2)._sage())
        try:
            from sage.symbolic.ring import SR
            return SR(result)
        except Exception:
            raise NotImplementedError("Unable to parse Maple output: %s" % result)
示例#26
0
def exponential_integral_1(x, n=0):
    r"""
    Returns the exponential integral `E_1(x)`. If the optional
    argument `n` is given, computes list of the first
    `n` values of the exponential integral
    `E_1(x m)`.

    The exponential integral `E_1(x)` is

    .. math::

                      E_1(x) = \int_{x}^{\infty} e^{-t}/t dt

    INPUT:

    - ``x`` -- a positive real number

    - ``n`` -- (default: 0) a nonnegative integer; if
      nonzero, then return a list of values ``E_1(x*m)`` for m =
      1,2,3,...,n. This is useful, e.g., when computing derivatives of
      L-functions.


    OUTPUT:

    A real number if n is 0 (the default) or a list of reals if n > 0.
    The precision is the same as the input, with a default of 53 bits
    in case the input is exact.

    EXAMPLES::

        sage: exponential_integral_1(2)
        0.0489005107080611
        sage: exponential_integral_1(2,4)  # abs tol 1e-18
        [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245]
        sage: exponential_integral_1(40,5)
        [1.03677326145166e-19, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90]
        sage: exponential_integral_1(0)
        +Infinity
        sage: r = exponential_integral_1(RealField(150)(1))
        sage: r
        0.21938393439552027367716377546012164903104729
        sage: parent(r)
        Real Field with 150 bits of precision
        sage: exponential_integral_1(RealField(150)(100))
        3.6835977616820321802351926205081189876552201e-46

    TESTS:

    The relative error for a single value should be less than 1 ulp::

        sage: for prec in [20..1000]:  # long time (22s on sage.math, 2013)
        ....:     R = RealField(prec)
        ....:     S = RealField(prec+64)
        ....:     for t in range(8):  # Try 8 values for each precision
        ....:         a = R.random_element(-15,10).exp()
        ....:         x = exponential_integral_1(a)
        ....:         y = exponential_integral_1(S(a))
        ....:         e = float(abs(S(x) - y)/x.ulp())
        ....:         if e >= 1.0:
        ....:             print "exponential_integral_1(%s) with precision %s has error of %s ulp"%(a, prec, e)

    The absolute error for a vector should be less than `c 2^{-p}`, where
    `p` is the precision in bits of `x` and `c = 2 max(1, exponential_integral_1(x))`::

        sage: for prec in [20..128]:  # long time (15s on sage.math, 2013)
        ....:     R = RealField(prec)
        ....:     S = RealField(prec+64)
        ....:     a = R.random_element(-15,10).exp()
        ....:     n = 2^ZZ.random_element(14)
        ....:     x = exponential_integral_1(a, n)
        ....:     y = exponential_integral_1(S(a), n)
        ....:     c = RDF(2 * max(1.0, y[0]))
        ....:     for i in range(n):
        ....:         e = float(abs(S(x[i]) - y[i]) << prec)
        ....:         if e >= c:
        ....:             print "exponential_integral_1(%s, %s)[%s] with precision %s has error of %s >= %s"%(a, n, i, prec, e, c)

    ALGORITHM: use the PARI C-library function ``eint1``.

    REFERENCE:

    - See Proposition 5.6.12 of Cohen's book "A Course in
      Computational Algebraic Number Theory".
    """
    if isinstance(x, Expression):
        if x.is_trivial_zero():
            from sage.rings.infinity import Infinity
            return Infinity
        else:
            raise NotImplementedError(
                "Use the symbolic exponential integral " +
                "function: exp_integral_e1.")
    elif not is_inexact(x):  # x is exact and not an expression
        if not x:  # test if exact x == 0 quickly
            from sage.rings.infinity import Infinity
            return Infinity

    # else x is not an exact 0
    from sage.libs.pari.all import pari
    # Figure out output precision
    try:
        prec = parent(x).precision()
    except AttributeError:
        prec = 53

    R = RealField(prec)
    if n <= 0:
        # Add extra bits to the input.
        # (experimentally verified -- Jeroen Demeyer)
        inprec = prec + math.ceil(math.log(2 * prec))
        x = RealField(inprec)(x)._pari_()
        return R(x.eint1())
    else:
        # PARI's algorithm is less precise as n grows larger:
        # add extra bits.
        # (experimentally verified -- Jeroen Demeyer)
        inprec = prec + 1 + math.ceil(1.4427 * math.log(n))
        x = RealField(inprec)(x)._pari_()
        return [R(z) for z in x.eint1(n)]
示例#27
0
def bdd_height(K, height_bound, tolerance=1e-2, precision=53):
    r"""
    Compute all elements in the number field `K` which have relative
    multiplicative height at most ``height_bound``.

    The function can only be called for number fields `K` with positive unit
    rank. An error will occur if `K` is `QQ` or an imaginary quadratic field.

    This algorithm computes 2 lists: L containing elements x in `K` such that
    H_k(x) <= B, and a list L' containing elements x in `K` that, due to
    floating point issues,
    may be slightly larger then the bound. This can be controlled
    by lowering the tolerance.

    In current implementation both lists (L,L') are merged and returned in
    form of iterator.

    ALGORITHM:

    This is an implementation of the revised algorithm (Algorithm 4) in
    [DK2013]_.

    INPUT:

    - ``height_bound`` -- real number

    - ``tolerance`` -- (default: 0.01) a rational number in (0,1]

    - ``precision`` -- (default: 53) positive integer

    OUTPUT:

    - an iterator of number field elements

    EXAMPLES:

    There are no elements of negative height::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<g> = NumberField(x^5 - x + 7)
        sage: list(bdd_height(K,-3))
        []

    The only nonzero elements of height 1 are the roots of unity::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<g> = QuadraticField(3)
        sage: list(bdd_height(K,1))
        [0, -1, 1]

    ::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<g> = QuadraticField(36865)
        sage: len(list(bdd_height(K,101))) # long time (4 s)
        131

    ::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<g> = NumberField(x^6 + 2)
        sage: len(list(bdd_height(K,60))) # long time (5 s)
        1899

    ::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<g> = NumberField(x^4 - x^3 - 3*x^2 + x + 1)
        sage: len(list(bdd_height(K,10)))
        99

    TESTS:

    Check that :trac:`22771` is fixed::

        sage: from sage.rings.number_field.bdd_height import bdd_height
        sage: K.<v> = NumberField(x^3 + x + 1)
        sage: len(list(bdd_height(K,3)))
        23
    """
    # global values, used in internal function
    B = height_bound
    theta = tolerance
    if B < 1:
        return
    embeddings = K.places(prec=precision)
    O_K = K.ring_of_integers()
    r1, r2 = K.signature()
    r = r1 + r2 - 1
    RF = RealField(precision)
    lambda_gens_approx = {}
    class_group_rep_norm_log_approx = []
    unit_log_dict = {}

    def rational_in(x, y):
        r"""
        Compute a rational number q, such that x<q<y using Archimedes' axiom
        """
        z = y - x
        if z == 0:
            n = 1
        else:
            n = RR(1/z).ceil() + 1
        if RR(n*y).ceil() is n*y:  # WHAT !?
            m = n*y - 1
        else:
            m = RR(n*y).floor()
        return m / n

    def delta_approximation(x, delta):
        r"""
        Compute a rational number in range (x-delta, x+delta)
        """
        return rational_in(x - delta, x + delta)

    def vector_delta_approximation(v, delta):
        r"""
        Compute a rational vector w=(w1, ..., wn)
        such that |vi-wi|<delta for all i in [1, n]
        """
        return [delta_approximation(vi, delta) for vi in v]

    def log_map(number):
        r"""
        Compute the image of an element of `K` under the logarithmic map.
        """
        x = number
        x_logs = []
        for i in range(r1):
            sigma = embeddings[i]  # real embeddings
            x_logs.append(sigma(x).abs().log())
        for i in range(r1, r + 1):
            tau = embeddings[i]  # Complex embeddings
            x_logs.append(2 * tau(x).abs().log())
        return vector(x_logs)

    def log_height_for_generators_approx(alpha, beta, Lambda):
        r"""
        Compute the rational approximation of logarithmic height function.
        Return a lambda approximation h_K(alpha/beta)
        """
        delta = Lambda / (r + 2)
        norm_log = delta_approximation(RR(O_K.ideal(alpha, beta).norm()).log(), delta)
        log_ga = vector_delta_approximation(log_map(alpha), delta)
        log_gb = vector_delta_approximation(log_map(beta), delta)
        arch_sum = sum([max(log_ga[k], log_gb[k]) for k in range(r + 1)])
        return (arch_sum - norm_log)

    def packet_height(n, pair, u):
        r"""
        Compute the height of the element of `K` encoded by a given packet.
        """
        gens = generator_lists[n]
        i = pair[0]
        j = pair[1]
        Log_gi = lambda_gens_approx[gens[i]]
        Log_gj = lambda_gens_approx[gens[j]]
        Log_u_gi = vector(Log_gi) + unit_log_dict[u]
        arch_sum = sum([max(Log_u_gi[k], Log_gj[k]) for k in range(r + 1)])
        return (arch_sum - class_group_rep_norm_log_approx[n])

    # Step 1
    # Computes ideal class representative and their rational approx norm
    t = theta / (3*B)
    delta_1 = t / (6*r+12)

    class_group_reps = []
    class_group_rep_norms = []

    for c in K.class_group():
        a = c.ideal()
        a_norm = a.norm()
        log_norm = RF(a_norm).log()
        log_norm_approx = delta_approximation(log_norm, delta_1)
        class_group_reps.append(a)
        class_group_rep_norms.append(a_norm)
        class_group_rep_norm_log_approx.append(log_norm_approx)
    class_number = len(class_group_reps)

    # Step 2
    # Find generators for principal ideals of bounded norm
    possible_norm_set = set([])
    for n in range(class_number):
        for m in range(1, (B + 1).ceil()):
            possible_norm_set.add(m * class_group_rep_norms[n])
    bdd_ideals = bdd_norm_pr_ideal_gens(K, possible_norm_set)

    # Stores it in form of an dictionary and gives lambda(g)_approx for key g
    for norm in possible_norm_set:
        gens = bdd_ideals[norm]
        for g in gens:
            lambda_g_approx = vector_delta_approximation(log_map(g), delta_1)
            lambda_gens_approx[g] = lambda_g_approx

    # Step 3
    # Find a list of all generators corresponding to each ideal a_l
    generator_lists = []
    for l in range(class_number):
        this_ideal = class_group_reps[l]
        this_ideal_norm = class_group_rep_norms[l]
        gens = []
        for i in range(1, (B + 1).ceil()):
            for g in bdd_ideals[i * this_ideal_norm]:
                if g in this_ideal:
                    gens.append(g)
        generator_lists.append(gens)

    # Step 4
    # Finds all relevant pair and their height
    gen_height_approx_dictionary = {}
    relevant_pair_lists = []

    for n in range(class_number):
        relevant_pairs = []
        gens = generator_lists[n]
        l = len(gens)
        for i in range(l):
            for j in range(i+1, l):
                if K.ideal(gens[i], gens[j]) == class_group_reps[n]:
                    relevant_pairs.append([i, j])
                    gen_height_approx_dictionary[(n, i, j)] = log_height_for_generators_approx(gens[i], gens[j], t/6)
        relevant_pair_lists.append(relevant_pairs)

    # Step 5
    b = rational_in(t/12 + RR(B).log(), t/4 + RR(B).log())
    maximum = 0
    for n in range(class_number):
        for p in relevant_pair_lists[n]:
            maximum = max(maximum, gen_height_approx_dictionary[(n, p[0], p[1])])
    d_tilde = b + t/6 + maximum

    # Step 6
    # computes fundamental units and their value under log map
    fund_units = UnitGroup(K).fundamental_units()
    fund_unit_logs = [log_map(fund_units[i]) for i in range(r)]
    S = column_matrix(fund_unit_logs).delete_rows([r])
    S_inverse = S.inverse()
    S_norm = S.norm(Infinity)
    S_inverse_norm = S_inverse.norm(Infinity)

    upper_bound = (r**2) * max(S_norm, S_inverse_norm)
    m = RR(upper_bound).ceil() + 1

    # Step 7
    # Variables needed for rational approximation
    lambda_tilde = (t/12) / (d_tilde*r*(1+m))
    delta_tilde = min(lambda_tilde/((r**2)*((m**2)+m*lambda_tilde)), 1/(r**2))
    M = d_tilde * (upper_bound+lambda_tilde*RR(r).sqrt())
    M = RR(M).ceil()
    d_tilde = RR(d_tilde)
    delta_2 = min(delta_tilde, (t/6)/(r*(r+1)*M))

    # Step 8, 9
    # Computes relevant points in polytope
    fund_unit_log_approx = [vector_delta_approximation(fund_unit_logs[i], delta_2) for i in range(r)]
    S_tilde = column_matrix(fund_unit_log_approx).delete_rows([r])
    S_tilde_inverse = S_tilde.inverse()
    U = integer_points_in_polytope(S_tilde_inverse, d_tilde)

    # Step 10
    # tilde suffixed list are used for computing second list (L_primed)
    yield K(0)
    U0 = []
    U0_tilde = []
    L0 = []
    L0_tilde = []

    # Step 11
    # Computes unit height
    unit_height_dict = {}
    U_copy = copy(U)
    inter_bound = b - (5*t)/12

    for u in U:
        u_log = sum([u[j]*vector(fund_unit_log_approx[j]) for j in range(r)])
        unit_log_dict[u] = u_log
        u_height = sum([max(u_log[k], 0) for k in range(r + 1)])
        unit_height_dict[u] = u_height
        if u_height < inter_bound:
                U0.append(u)
        if inter_bound <= u_height and u_height < b - (t/12):
            U0_tilde.append(u)
        if u_height > t/12 + d_tilde:
            U_copy.remove(u)
    U = U_copy

    relevant_tuples = set(U0 + U0_tilde)

    # Step 12
    # check for relevant packets
    for n in range(class_number):
        for pair in relevant_pair_lists[n]:
            i = pair[0]
            j = pair[1]
            u_height_bound = b + gen_height_approx_dictionary[(n, i, j)] + t/4
            for u in U:
                if unit_height_dict[u] < u_height_bound:
                    candidate_height = packet_height(n, pair, u)
                    if candidate_height <= b - 7*t/12:
                        L0.append([n, pair, u])
                        relevant_tuples.add(u)
                    elif candidate_height < b + t/4:
                        L0_tilde.append([n, pair, u])
                        relevant_tuples.add(u)

    # Step 13
    # forms a dictionary of all_unit_tuples and their value
    tuple_to_unit_dict = {}
    for u in relevant_tuples:
        unit = K.one()
        for k in range(r):
            unit *= fund_units[k]**u[k]
        tuple_to_unit_dict[u] = unit

    # Step 14
    # Build all output numbers
    roots_of_unity = K.roots_of_unity()
    for u in U0 + U0_tilde:
        for zeta in roots_of_unity:
            yield zeta * tuple_to_unit_dict[u]

    # Step 15
    for p in L0 + L0_tilde:
        gens = generator_lists[p[0]]
        i = p[1][0]
        j = p[1][1]
        u = p[2]
        c_p = tuple_to_unit_dict[u] * (gens[i] / gens[j])
        for zeta in roots_of_unity:
            yield zeta * c_p
            yield zeta / c_p
示例#28
0
def covariant_z0(F, z0_cov=False, prec=53, emb=None, error_limit=0.000001):
    r"""
    Return the covariant and Julia invariant from Cremona-Stoll [CS2003]_.

    In [CS2003]_ and [HS2018]_ the Julia invariant is denoted as `\Theta(F)`
    or `R(F, z(F))`. Note that you may get faster convergence if you first move
    `z_0(F)` to the fundamental domain before computing the true covariant

    INPUT:

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

    - ``z0_cov`` -- boolean, compute only the `z_0` invariant. Otherwise, solve
      the minimization problem

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

    - ``emb`` -- embedding into CC

    - ``error_limit`` -- sets the error tolerance (default:0.000001)


    OUTPUT: a complex number, a real number

    EXAMPLES::

        sage: from sage.rings.polynomial.binary_form_reduce import covariant_z0
        sage: R.<x,y> = QQ[]
        sage: F = 19*x^8 - 262*x^7*y + 1507*x^6*y^2 - 4784*x^5*y^3 + 9202*x^4*y^4\
        ....: - 10962*x^3*y^5 + 7844*x^2*y^6 - 3040*x*y^7 + 475*y^8
        sage: covariant_z0(F, prec=80, z0_cov=True)
        (1.3832330115323681438175 + 0.31233552177413614978744*I,
         3358.4074848663492819259)
        sage: F = -x^8 + 6*x^7*y - 7*x^6*y^2 - 12*x^5*y^3 + 27*x^4*y^4\
        ....: - 4*x^3*y^5 - 19*x^2*y^6 + 10*x*y^7 - 5*y^8
        sage: covariant_z0(F, prec=80)
        (0.64189877107807122203366 + 1.1852516565091601348355*I,
         3134.5148284344627168276)

    ::

        sage: R.<x,y> = QQ[]
        sage: covariant_z0(x^3 + 2*x^2*y - 3*x*y^2, z0_cov=True)[0]
        0.230769230769231 + 0.799408065031789*I
        sage: -1/covariant_z0(-y^3 + 2*y^2*x + 3*y*x^2, z0_cov=True)[0]
        0.230769230769231 + 0.799408065031789*I

    ::

        sage: R.<x,y> = QQ[]
        sage: covariant_z0(2*x^2*y - 3*x*y^2, z0_cov=True)[0]
        0.750000000000000 + 1.29903810567666*I
        sage: -1/covariant_z0(-x^3 - x^2*y + 2*x*y^2, z0_cov=True)[0] + 1
        0.750000000000000 + 1.29903810567666*I

    ::

        sage: R.<x,y> = QQ[]
        sage: covariant_z0(x^2*y - x*y^2, prec=100)
         (0.50000000000000000000000000003 + 0.86602540378443864676372317076*I,
         1.5396007178390020386910634147)

    TESTS::

        sage: R.<x,y>=QQ[] 
        sage: covariant_z0(x^2 + 24*x*y + y^2)
        Traceback (most recent call last):
        ...
        ValueError: must be at least degree 3
        sage: covariant_z0((x+y)^3, z0_cov=True)
        Traceback (most recent call last):
        ...
        ValueError: cannot have multiple roots for z0 invariant
        sage: covariant_z0(x^3 + 3*x*y + y)
        Traceback (most recent call last):
        ...
        TypeError: must be a binary form
        sage: covariant_z0(-2*x^2*y^3 + 3*x*y^4 + 127*y^5)
        Traceback (most recent call last):
        ...
        ValueError: cannot have a root with multiplicity >= 5/2
        sage: covariant_z0((x^2+2*y^2)^2)
        Traceback (most recent call last):
        ...
        ValueError: must have at least 3 distinct roots
    """
    R = F.parent()
    d = ZZ(F.degree())
    if R.ngens() != 2 or any([sum(t) != d for t in F.exponents()]):
        raise TypeError('must be a binary form')
    if d < 3:
        raise ValueError('must be at least degree 3')

    f = F.subs({R.gen(1):1}).univariate_polynomial()
    if f.degree() < d:
        # we have a root at infinity
        if f.constant_coefficient() != 0: 
            # invert so we find all roots!
            mat = matrix(ZZ,2,2,[0,-1,1,0])
        else:
            t = 0
            poly_ring = f.parent()
            while f(t) == 0:
                t += 1
            mat = matrix(ZZ,2,2,[t,-1,1,0])
    else:
        mat = matrix(ZZ,2,2,[1,0,0,1])
    f = F(list(mat * vector(R.gens()))).subs({R.gen(1):1}).univariate_polynomial()
    # now we have a single variable polynomial with all the roots of F
    K = ComplexField(prec=prec)
    if f.base_ring() != K:
        if emb == None:
            f = f.change_ring(K)
        else:
            f = f.change_ring(emb)
    roots = f.roots()
    if (max([ex for p,ex in roots]) > 1)\
      or (f.degree() < d-1):
        if z0_cov:
            raise ValueError('cannot have multiple roots for z0 invariant')
        else:
            # just need a starting point for Newton's method
            f = f.lc()*prod([p for p,ex in f.factor()])# removes multiple roots
            if f.degree() < 3:
                raise ValueError('must have at least 3 distinct roots')
            roots = f.roots()
    roots = [p for p,ex in roots]

    # finding quadratic Q_0, gives us our covariant, z_0
    dF = f.derivative()
    n = ZZ(f.degree())
    PR = PolynomialRing(K,'x,y')
    x,y = PR.gens()
    # finds Stoll and Cremona's Q_0
    q  = sum([(1/(dF(r).abs()**(2/(n-2)))) * ((x-(r*y)) * (x-(r.conjugate()*y)))\
              for r in roots])
    # this is Q_0 , always positive def as long as F has distinct roots
    A = q.monomial_coefficient(x**2)
    B = q.monomial_coefficient(x*y)
    C = q.monomial_coefficient(y**2)
    # need positive root
    try:
        z = ((-B + ((B**2)-(4*A*C)).sqrt())/(2*A))
    except ValueError:
        raise ValueError("not enough precision")
    if z.imag() < 0:
        z = (-B - ((B**2)-(4*A*C)).sqrt())/(2*A)

    if z0_cov:
        FM = f # for Julia's invariant
    else:
        # solve the minimization problem for 'true' covariant
        CF = ComplexIntervalField(prec=prec) # keeps trac of our precision error
        RF = RealField(prec=prec)
        z = CF(z)
        FM = F(list(mat * vector(R.gens()))).subs({R.gen(1):1}).univariate_polynomial()
        from sage.rings.polynomial.complex_roots import complex_roots
        L1 = complex_roots(FM, min_prec=prec)
        L = []
        err = z.diameter()
        # making sure multiplicity isn't too large using convergence conditions in paper
        for p,e in L1:
            if e >= d/2:
                raise ValueError('cannot have a root with multiplicity >= %s/2'%d)
            for _ in range(e):
                L.append(p)
        RCF = PolynomialRing(CF, 'u,t')
        a = RCF(0)
        c = RCF(0)
        u,t = RCF.gens()
        for l in L:
            a += u**2/((t-l) * (t-l.conjugate()) + u**2)
            c += (t-l.real())/((t-l) * (t-l.conjugate()) + u**2)
        # Newton's Method, to find solutions. Error bound is less than diameter of our z
        err = z.diameter()
        zz = z.diameter()
        g1 = a.numerator() - d/2*a.denominator()
        g2 = c.numerator()
        G = vector([g1, g2])
        J = jacobian(G, [u, t])
        v0 = vector([z.imag(), z.real()]) # z0 as starting point
        # finds our correct z
        while err <= zz:
            NJ = J.subs({u:v0[0], t:v0[1]})
            NJinv = NJ.inverse()
            # inverse for CIF matrix seems to return fractions not CIF elements, fix them
            if NJinv.base_ring() != CF:
                NJinv = matrix(CF, 2, 2, [CF(zw.numerator()/zw.denominator()) for zw in NJinv.list()])
            w = z
            v0 = v0 - NJinv*G.subs({u:v0[0], t:v0[1]})
            z = v0[1].constant_coefficient() + v0[0].constant_coefficient()*CF.gen(0)
            err = z.diameter() # precision
            zz = (w - z).abs() # difference in w and z
        else:
            if err > error_limit or err.is_NaN():
                raise ValueError("accuracy of Newton's root not within tolerance(%s > %s), increase precision"%(err, error_limit))
        if z.imag() <= z.diameter():
            raise ArithmeticError("Newton's method converged to z not in the upper half plane")
        z = z.center()

    # Julia's invariant
    if FM.base_ring() != ComplexField(prec=prec):
        FM = FM.change_ring(ComplexField(prec=prec))
    tF = z.real()
    uF = z.imag()
    th = FM.lc().abs()**2
    for r,ex in FM.roots():
        for _ in range(ex):
            th = th * ((((r-tF).abs())**2 + uF**2)/uF)

    # undo shift and invert (if needed)
    # since F \cdot m ~ m^(-1)\cdot z
    # we apply m to z to undo m acting on F
    l = mat*vector([z,1])
    return l[0]/l[1], th
示例#29
0
def cholesky_decomposition(self, bit_prec=53):
    r"""
    Give the Cholesky decomposition of this quadratic form `Q` as a real matrix
    of precision ``bit_prec``.

    RESTRICTIONS:

        Q must be given as a QuadraticForm defined over `\ZZ`, `\QQ`, or some
        real field. If it is over some real field, then an error is raised if
        the precision given is not less than the defined precision of the real
        field defining the quadratic form!

    REFERENCE:

        From Cohen's "A Course in Computational Algebraic Number Theory" book,
        p 103.

    INPUT:

        ``bit_prec`` -- a natural number (default 53).

    OUTPUT:

        an upper triangular real matrix of precision ``bit_prec``.


    TO DO:
        If we only care about working over the real double field (RDF), then we
        can use the ``cholesky()`` method present for square matrices over that.

    .. note::

        There is a note in the original code reading

        ::

            ##/////////////////////////////////////////////////////////////////////////////////////////////////
            ##/// Finds the Cholesky decomposition of a quadratic form -- as an upper-triangular matrix!
            ##/// (It's assumed to be global, hence twice the form it refers to.)  <-- Python revision asks:  Is this true?!? =|
            ##/////////////////////////////////////////////////////////////////////////////////////////////////


    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
        sage: Q.cholesky_decomposition()
        [ 1.00000000000000 0.000000000000000 0.000000000000000]
        [0.000000000000000  1.00000000000000 0.000000000000000]
        [0.000000000000000 0.000000000000000  1.00000000000000]

    ::

        sage: Q = QuadraticForm(QQ, 3, range(1,7)); Q
        Quadratic form in 3 variables over Rational Field with coefficients:
        [ 1 2 3 ]
        [ * 4 5 ]
        [ * * 6 ]
        sage: Q.cholesky_decomposition()
        [ 1.00000000000000  1.00000000000000  1.50000000000000]
        [0.000000000000000  3.00000000000000 0.333333333333333]
        [0.000000000000000 0.000000000000000  3.41666666666667]
    """

    ## Check that the precision passed is allowed.
    if isinstance(self.base_ring(),
                  RealField_class) and (self.base_ring().prec() < bit_prec):
        raise RuntimeError(
            "Oops! The precision requested is greater than that of the given quadratic form!"
        )

    ## 1. Initialization
    n = self.dim()
    R = RealField(bit_prec)
    MS = MatrixSpace(R, n, n)
    Q = MS(R(0.5)) * MS(
        self.matrix()
    )  ## Initialize the real symmetric matrix A with the matrix for Q(x) = x^t * A * x

    ## DIAGNOSTIC

    ## 2. Loop on i
    for i in range(n):
        for j in range(i + 1, n):
            Q[j, i] = Q[i, j]  ## Is this line redundant?
            Q[i, j] = Q[i, j] / Q[i, i]

        ## 3. Main Loop
        for k in range(i + 1, n):
            for l in range(k, n):
                Q[k, l] = Q[k, l] - Q[k, i] * Q[i, l]

    ## 4. Zero out the strictly lower-triangular entries
    for i in range(n):
        for j in range(i):
            Q[i, j] = 0

    return Q
示例#30
0
def theta_by_cholesky(self, q_prec):
    r"""
    Uses the real Cholesky decomposition to compute (the `q`-expansion of) the
    theta function of the quadratic form as a power series in `q` with terms
    correct up to the power `q^{\text{q\_prec}}`. (So its error is `O(q^
    {\text{q\_prec} + 1})`.)

    REFERENCE:
        From Cohen's "A Course in Computational Algebraic Number Theory" book,
        p 102.

    EXAMPLES::

        ## Check the sum of 4 squares form against Jacobi's formula
        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
        sage: Theta = Q.theta_by_cholesky(10)
        sage: Theta
        1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10
        sage: Expected =  [1] + [8*sum([d for d in divisors(n) if d%4 != 0])  for n in range(1,11)]
        sage: Expected
        [1, 8, 24, 32, 24, 48, 96, 64, 24, 104, 144]
        sage: Theta.list() == Expected
        True

    ::

        ## Check the form x^2 + 3y^2 + 5z^2 + 7w^2 represents everything except 2 and 22.
        sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
        sage: Theta = Q.theta_by_cholesky(50)
        sage: Theta_list = Theta.list()
        sage: [m  for m in range(len(Theta_list))  if Theta_list[m] == 0]
        [2, 22]

    """
    ## RAISE AN ERROR -- This routine is deprecated!
    #raise NotImplementedError, "This routine is deprecated.  Try theta_series(), which uses theta_by_pari()."

    n = self.dim()
    theta = [0 for i in range(q_prec + 1)]
    PS = PowerSeriesRing(ZZ, 'q')

    bit_prec = 53  ## TO DO: Set this precision to reflect the appropriate roundoff
    Cholesky = self.cholesky_decomposition(
        bit_prec
    )  ## error estimate, to be confident through our desired q-precision.
    Q = Cholesky  ##  <----  REDUNDANT!!!
    R = RealField(bit_prec)
    half = R(0.5)

    ## 1. Initialize
    i = n - 1
    T = [R(0) for j in range(n)]
    U = [R(0) for j in range(n)]
    T[i] = R(q_prec)
    U[i] = 0
    L = [0 for j in range(n)]
    x = [0 for j in range(n)]

    ## 2. Compute bounds
    #Z = sqrt(T[i] / Q[i,i])      ## IMPORTANT NOTE: sqrt preserves the precision of the real number it's given... which is not so good... =|
    #L[i] = floor(Z - U[i])       ## Note: This is a Sage Integer
    #x[i] = ceil(-Z - U[i]) - 1   ## Note: This is a Sage Integer too

    done_flag = False
    from_step4_flag = False
    from_step3_flag = True  ## We start by pretending this, since then we get to run through 2 and 3a once. =)

    #double Q_val_double;
    #unsigned long Q_val;                 // WARNING: Still need a good way of checking overflow for this value...

    ## Big loop which runs through all vectors
    while (done_flag == False):

        ## Loop through until we get to i=1 (so we defined a vector x)
        while from_step3_flag or from_step4_flag:  ## IMPORTANT WARNING:  This replaces a do...while loop, so it may have to be adjusted!

            ## Go to directly to step 3 if we're coming from step 4, otherwise perform step 2.
            if from_step4_flag:
                from_step4_flag = False
            else:
                ## 2. Compute bounds
                from_step3_flag = False
                Z = sqrt(T[i] / Q[i, i])
                L[i] = floor(Z - U[i])
                x[i] = ceil(-Z - U[i]) - 1

            ## 3a. Main loop

            ## DIAGNOSTIC
            #print
            #print "  L = ", L
            #print "  x = ", x

            x[i] += 1
            while (x[i] > L[i]):

                ## DIAGNOSTIC
                #print "  x = ", x

                i += 1
                x[i] += 1

            ## 3b. Main loop
            if (i > 0):
                from_step3_flag = True

                ## DIAGNOSTIC
                #print " i = " + str(i)
                #print " T[i] = " + str(T[i])
                #print " Q[i,i] = " + str(Q[i,i])
                #print " x[i] = " + str(x[i])
                #print " U[i] = " + str(U[i])
                #print " x[i] + U[i] = " + str(x[i] + U[i])
                #print " T[i-1] = " + str(T[i-1])

                T[i - 1] = T[i] - Q[i, i] * (x[i] + U[i]) * (x[i] + U[i])

                # DIAGNOSTIC
                #print " T[i-1] = " + str(T[i-1])
                #print

                i += -1
                U[i] = 0
                for j in range(i + 1, n):
                    U[i] += Q[i, j] * x[j]

        ## 4. Solution found (This happens when i=0)
        from_step4_flag = True
        Q_val_double = q_prec - T[0] + Q[0, 0] * (x[0] + U[0]) * (x[0] + U[0])
        Q_val = floor(
            Q_val_double + half
        )  ## Note: This rounds the value up, since the "round" function returns a float, but floor returns integer.

        ## DIAGNOSTIC
        #print " Q_val_double = ",  Q_val_double
        #print " Q_val = ",  Q_val
        #raise RuntimeError

        ## OPTIONAL SAFETY CHECK:
        eps = 0.000000001
        if (abs(Q_val_double - Q_val) > eps):
            raise RuntimeError, "Oh No!  We have a problem with the floating point precision... \n" \
                + " Q_val_double = " + str(Q_val_double) + "\n" \
                + " Q_val = " + str(Q_val) + "\n" \
                + " x = " + str(x) + "\n"

        ## DIAGNOSTIC
        #print " The float value is " + str(Q_val_double)
        #print " The associated long value is " + str(Q_val)
        #print

        if (Q_val <= q_prec):
            theta[Q_val] += 2

        ## 5. Check if x = 0, for exit condition. =)
        done_flag = True
        for j in range(n):
            if (x[j] != 0):
                done_flag = False

    ## Set the value: theta[0] = 1
    theta[0] = 1

    ## DIAGNOSTIC
    #print "Leaving ComputeTheta \n"

    ## Return the series, truncated to the desired q-precision
    return PS(theta)