示例#1
0
    def solve(self, verify = False):
        percent = RealField(prec=20)(0)
        holes = self._holes
        self._minholes = len(holes)
        while len(holes) > 0:
            h = holes.popleft()
            result = self.evaluate_hole(h)
            if result == -2:
                self._Nboundmax = max([self._Nboundmax,self._Nbound])
                self._holes.append(h)
            if result == -1:
                xh = (h.xmax+h.xmin)/2
                yh = (h.ymax+h.ymin)/2
                depth = h.depth()+1
                self._maxdepth = max([self._maxdepth,depth])
                h1 = Hole(self,[h.xmin,h.ymin,xh,yh],depth=depth)
                h2 = Hole(self,[h.xmin,yh,xh,h.ymax],depth=depth)
                h3 = Hole(self,[xh,h.ymin,h.xmax,yh],depth=depth)
                h4 = Hole(self,[xh,yh,h.xmax,h.ymax],depth=depth)
                holes.extendleft([h1,h2,h3,h4])
            else:
                percent += 100*(4**(-h.depth()))

            if len(holes) < self._minholes:
                self._minholes = len(holes)
                percent = RealField(prec=20)(0)
        if verify and not self.verify():
            raise RuntimeError("The result seems not to be correct. Verification failed.")
        self._solved = True
        return [self._disc, self._maxdepth, 1 + max([abs(self._F(reg[1][1]).norm()) for reg in self._used_regions]),len(self._used_regions),self._used_regions]
示例#2
0
    def verify(self):
        maxdepth = self._maxdepth
        self.initialize_fundom()
        percent = RealField(prec=20)(0)
        holes = self._holes
        self._minholes = len(holes)
        while len(holes) > 0:
            h = holes.popleft()
            result = self.evaluate_hole(h,verifying=True,maxdepth=maxdepth)
            if result == -2:
                print "The solution is incorrect."
                print "The ",h," is not covered by any region."
                return False
            if result == -1:
                xh = (h.xmax+h.xmin)/2
                yh = (h.ymax+h.ymin)/2
                depth = h.depth()+1
                self._maxdepth = max([self._maxdepth,depth])
                h1 = Hole(self,[h.xmin,h.ymin,xh,yh],depth=depth)
                h2 = Hole(self,[h.xmin,yh,xh,h.ymax],depth=depth)
                h3 = Hole(self,[xh,h.ymin,h.xmax,yh],depth=depth)
                h4 = Hole(self,[xh,yh,h.xmax,h.ymax],depth=depth)
                holes.extendleft([h1,h2,h3,h4])
            else:
                percent += 100*(4**(-h.depth()))

            if len(holes) < self._minholes:
                self._minholes=len(holes)
                percent=RealField(prec=20)(0)
        return True
示例#3
0
 def coincidence_index(self, prec=0):
     """
     Returns the probability of two randomly chosen characters being equal.
     """
     if prec == 0:
         RR = RealField()
     else:
         RR = RealField(prec)
     char_dict = {}
     for i in self._element_list:
         # if char_dict.has_key(i):
         # The method .has_key() has been deprecated since Python 2.2. Use
         # "k in Dict" instead of "Dict.has_key(k)".
         if i in char_dict:
             char_dict[i] += 1
         else:
             char_dict[i] = 1
     nn = 0
     ci_num = 0
     for i in char_dict.keys():
         ni = char_dict[i]
         nn += ni
         ci_num += ni * (ni - 1)
     ci_den = nn * (nn - 1)
     return RR(ci_num) / ci_den
示例#4
0
    def solve(self,verify=False):
        percent=RealField(prec=_sage_const_20 )(_sage_const_0 )
        holes=self._holes
        self._minholes=len(holes)
        while(len(holes)>_sage_const_0 ):
            if(len(holes)-self._minholes>_sage_const_1000 ):
                assert(_sage_const_0 )
            h=holes.popleft()
            result=self.evaluate_hole(h)
            if(result==-_sage_const_2 ):
                self._Nboundmax=max([self._Nboundmax,self._Nbound])
                self._holes.append(h)
            if(result==-_sage_const_1 ):
                xh=(h.xmax+h.xmin)/_sage_const_2 
                yh=(h.ymax+h.ymin)/_sage_const_2 
                depth=h.depth()+_sage_const_1 
                self._maxdepth=max([self._maxdepth,depth])
                h1=Hole(self,[h.xmin,h.ymin,xh,yh],depth=depth)
                h2=Hole(self,[h.xmin,yh,xh,h.ymax],depth=depth)
                h3=Hole(self,[xh,h.ymin,h.xmax,yh],depth=depth)
                h4=Hole(self,[xh,yh,h.xmax,h.ymax],depth=depth)

                holes.extendleft([h1,h2,h3,h4])
            else:
                percent+=_sage_const_100 *(_sage_const_4 **(-h.depth()))
                #print 'Finished hole ',self._minholes,' up to ',percent,'%'

            if(len(holes)<self._minholes):
                self._minholes=len(holes)
                percent=RealField(prec=_sage_const_20 )(_sage_const_0 )
                #print "Remaining ",self._minholes,' holes.'
        if(verify==True):
            assert(self.verify())
        self._solved=True
        return [self._disc,self._maxdepth,_sage_const_1 +max([abs(self._F(reg[_sage_const_1 ][_sage_const_1 ]).norm()) for reg in self._used_regions]),len(self._used_regions),self._used_regions]
示例#5
0
    def verify(self):
        maxdepth=self._maxdepth
        self.initialize_fundom()
        percent=RealField(prec=_sage_const_20 )(_sage_const_0 )
        holes=self._holes
        self._minholes=len(holes)
        while(len(holes)>_sage_const_0 ):
            if(len(holes)-self._minholes>_sage_const_1000 ):
                assert(_sage_const_0 )
            h=holes.popleft()
            result=self.evaluate_hole(h,verifying=True,maxdepth=maxdepth)
            if(result==-_sage_const_2 ):
                print "The solution is incorrect."
                print "The ",h," is not covered by any region."
                return False
            if(result==-_sage_const_1 ):
                xh=(h.xmax+h.xmin)/_sage_const_2 
                yh=(h.ymax+h.ymin)/_sage_const_2 
                depth=h.depth()+_sage_const_1 
                self._maxdepth=max([self._maxdepth,depth])
                h1=Hole(self,[h.xmin,h.ymin,xh,yh],depth=depth)
                h2=Hole(self,[h.xmin,yh,xh,h.ymax],depth=depth)
                h3=Hole(self,[xh,h.ymin,h.xmax,yh],depth=depth)
                h4=Hole(self,[xh,yh,h.xmax,h.ymax],depth=depth)
                holes.extendleft([h1,h2,h3,h4])
            else:
                percent+=_sage_const_100 *(_sage_const_4 **(-h.depth()))
                #print 'Finished hole ',self._minholes,' up to ',percent,'%'

            if(len(holes)<self._minholes):
                self._minholes=len(holes)
                percent=RealField(prec=_sage_const_20 )(_sage_const_0 )
                #print "Remaining ",self._minholes,' holes.'
        return True
示例#6
0
def riemann_sum(G, phi, hc, depth=1, mult=False, progress_bar=False, K=None):
    prec = max([20, 2 * depth])
    res = 1 if mult else 0
    if K is None:
        K = phi.parent().base_ring()
    cover = G.get_covering(depth)
    n_ints = 0
    for e in cover:
        if n_ints % 500 == 499:
            verbose('Done %s percent' %
                    (100 * RealField(10)(n_ints) / len(cover)))
        if progress_bar:
            update_progress(float(RealField(10)(n_ints + 1) / len(cover)),
                            'Riemann sum')
        n_ints += 1
        val = hc(e)
        vmom = val[0]  #.moment(0)
        if vmom.parent().is_exact():
            hce = ZZ(vmom)
        else:
            hce = ZZ(vmom.rational_reconstruction())
        if hce == 0:
            continue
        #verbose('hc = %s'%hce)
        te = sample_point(G, e, prec)
        if te == Infinity:
            continue
        if mult:
            res *= phi(K(te))**hce
        else:
            res += phi(K(te)) * hce
    return res
示例#7
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))
示例#8
0
def coincidence_index(S, n=1):
    """
    The coincidence index of the string S.

    EXAMPLES::

        sage: S = strip_encoding("The cat in the hat.")
        sage: coincidence_index(S)
        0.120879120879121
    """
    if not isinstance(S, str):
        try:
            S.coincidence_index(n)
        except AttributeError:
            raise TypeError("Argument S (= %s) must be a string.")
    S = strip_encoding(S)
    N = len(S) - n + 1
    X = {}
    for i in range(N):
        c = S[i:i + n]
        if c in X:
            X[c] += 1
        else:
            X[c] = 1
    RR = RealField()
    return RR(sum([m * (m - 1) for m in X.values()])) / RR(N * (N - 1))
示例#9
0
    def __init__(self,F,Nbound=_sage_const_50 ,Tbound=_sage_const_5 ):
        self._F=F
        self._solved=False
        self._disc=self._F.discriminant()
        self._w=self._F.maximal_order().ring_generators()[_sage_const_0 ]
        self._eps=self._F.units()[_sage_const_0 ]
        self._Phi=self._F.real_embeddings(prec=_sage_const_500 )
        a=F.gen()
        self.Pointxy=namedtuple('Pointxy','x y')
        if(self._disc%_sage_const_2 ==_sage_const_0 ):
            self._changebasismatrix=_sage_const_1 
        else:
            self._changebasismatrix=Matrix(IntegerRing(),_sage_const_2 ,_sage_const_2 ,[_sage_const_1 ,-_sage_const_1 ,_sage_const_0 ,_sage_const_2 ])

        # We assume here that Phi orders the embeddings to that
        # Phi[1] is the largest
        self._Rw=self._Phi[_sage_const_1 ](self._w)
        self._Rwconj=self._Phi[_sage_const_0 ](self._w)

        self._used_regions=[]
        self._Nboundmin=_sage_const_2 
        self._Nboundmax=Nbound
        self._Nboundinc=_sage_const_1 
        self._Nbound=Nbound
        self._epsto=[self._F(_sage_const_1 )]
        self._Dmax=self.embed(self._w)
        self._Tbound=Tbound
        self._ranget=sorted(range(-self._Tbound,self._Tbound+_sage_const_2 ),key=abs)
        self._M=Matrix(RealField(),_sage_const_2 ,_sage_const_2 ,[_sage_const_1 ,self._Rw,_sage_const_1 ,self._Rwconj]).inverse()
        self.initialize_fundom()
        self._master_regs=Regions(self)
        self._maxdepth=_sage_const_0 
示例#10
0
    def __init__(self, F, Nbound = 50,Tbound = 5, prec = 500):
        self._F = F
        self._solved = False
        self._disc = self._F.discriminant()
        self._w = self._F.maximal_order().ring_generators()[0]
        self._eps = self._F.units()[0]
        self._Phi = self._F.real_embeddings(prec=prec)
        a = F.gen()
        self.Pointxy = namedtuple('Pointxy', 'x y')
        if self._disc % 2 ==0 :
            self._changebasismatrix = 1
        else:
            self._changebasismatrix = Matrix(IntegerRing(),2,2,[1,-1,0,2])

        # We assume here that Phi orders the embeddings to that
        # Phi[1] is the largest
        self._Rw = self._Phi[1](self._w)
        self._Rwconj = self._Phi[0](self._w)

        self._used_regions = []
        self._Nboundmin = 2
        self._Nboundmax = Nbound
        self._Nboundinc = 1
        self._Nbound = Nbound
        self._epsto = [self._F(1)]
        self._Dmax = self.embed(self._w)
        self._Tbound = Tbound
        self._ranget = sorted(range(-self._Tbound,self._Tbound+2),key=abs)
        self._M = ~Matrix(RealField(), 2, 2, [1,self._Rw,1,self._Rwconj])
        self.initialize_fundom()
        self._master_regs = Regions(self)
        self._maxdepth = 0
示例#11
0
def _do_sqrt(x, prec=None, extend=True, all=False):
    r"""
        Used internally to compute the square root of x.
        
        INPUT:
        
        -  ``x`` - a number
        
        -  ``prec`` - None (default) or a positive integer
           (bits of precision) If not None, then compute the square root
           numerically to prec bits of precision.
        
        -  ``extend`` - bool (default: True); this is a place
           holder, and is always ignored since in the symbolic ring everything
           has a square root.
        
        -  ``extend`` - bool (default: True); whether to extend
           the base ring to find roots. The extend parameter is ignored if
           prec is a positive integer.
        
        -  ``all`` - bool (default: False); whether to return
           a list of all the square roots of x.
        
        
        EXAMPLES::
        
            sage: from sage.functions.other import _do_sqrt
            sage: _do_sqrt(3)
            sqrt(3)
            sage: _do_sqrt(3,prec=10)
            1.7
            sage: _do_sqrt(3,prec=100)
            1.7320508075688772935274463415
            sage: _do_sqrt(3,all=True)
            [sqrt(3), -sqrt(3)]
        
        Note that the extend parameter is ignored in the symbolic ring::
        
            sage: _do_sqrt(3,extend=False)
            sqrt(3)
        """
    from sage.rings.all import RealField, ComplexField
    if prec:
        if x >= 0:
            return RealField(prec)(x).sqrt(all=all)
        else:
            return ComplexField(prec)(x).sqrt(all=all)
    if x == -1:
        from sage.symbolic.pynac import I
        z = I
    else:
        z = SR(x)**one_half

    if all:
        if z:
            return [z, -z]
        else:
            return [z]
    return z
示例#12
0
    def __call__(self, x, prec=None, coerce=True, hold=False):
        """
        Note that the ``prec`` argument is deprecated. The precision for
        the result is deduced from the precision of the input. Convert
        the input to a higher precision explicitly if a result with higher
        precision is desired.::

            sage: t = gamma(RealField(100)(2.5)); t
            1.3293403881791370204736256125
            sage: t.prec()
            100

            sage: gamma(6, prec=53)
            doctest:...: DeprecationWarning: The prec keyword argument is deprecated. Explicitly set the precision of the input, for example gamma(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., gamma(1).n(300), instead.
            120.000000000000

        TESTS::

            sage: gamma(pi,prec=100)
            2.2880377953400324179595889091

            sage: gamma(3/4,prec=100)
            1.2254167024651776451290983034
        """
        if prec is not None:
            from sage.misc.misc import deprecation
            deprecation(
                "The prec keyword argument is deprecated. Explicitly set the precision of the input, for example gamma(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., gamma(1).n(300), instead."
            )
            import mpmath
            return mpmath_utils.call(mpmath.gamma, x, prec=prec)

        # this is a kludge to keep
        #     sage: Q.<i> = NumberField(x^2+1)
        #     sage: gamma(i)
        # working, since number field elements cannot be coerced into SR
        # without specifying an explicit embedding into CC any more
        try:
            res = GinacFunction.__call__(self, x, coerce=coerce, hold=hold)
        except TypeError, err:
            # the __call__() method returns a TypeError for fast float arguments
            # as well, we only proceed if the error message says that
            # the arguments cannot be coerced to SR
            if not str(err).startswith("cannot coerce"):
                raise

            from sage.misc.misc import deprecation
            deprecation(
                "Calling symbolic functions with arguments that cannot be coerced into symbolic expressions is deprecated."
            )
            parent = RR if prec is None else RealField(prec)
            try:
                x = parent(x)
            except (ValueError, TypeError):
                x = parent.complex_field()(x)
            res = GinacFunction.__call__(self, x, coerce=coerce, hold=hold)
示例#13
0
    def get_regions(self, B):
        regions = self._regions
        if B <= self._N:
            return [reg for nn,lst in regions.iteritems() if nn < B for reg in lst]
        F = self._F
        eps = self._eps
        newelts = dict([(IntegerRing()(n),[I.gens_reduced()[0] for I in v if I.is_principal()]) for n,v in self._F.ideals_of_bdd_norm(B-1).iteritems() if n >= self._N])
        self._N = B
        for nn in range(len(self._epsto), B):
            self._epsto.append(self._epsto[nn-1]*eps)
        for nn, v in newelts.iteritems():
            assert not regions.has_key(nn)
            regions[nn] = []
            for q in v:
                invden = 1/q
                invden_red = self.fundom_rep(invden)
                q0 = invden_red-invden
                m_invden_red = self.fundom_rep(-invden)
                m_q0 = m_invden_red+invden

                a, b = self._parent._change_basis(invden_red)
                am, bm = self._parent._change_basis(m_invden_red)

                regions[nn].extend([[invden_red,[q0,q],Region(self.embed(invden_red),RealField()(1/nn)),[a,b],nn],[m_invden_red,[m_q0,-q],Region(self.embed(m_invden_red),RealField()(1/nn)),[am,bm],nn]])

                for jj in range(1,nn):
                    x = self._epsto[jj] * invden
                    x_red = self.fundom_rep(x)
                    x_red_minus = self.fundom_rep(-x_red)
                    regs = regions[nn]
                    if x_red == regs[0][0] or x_red_minus == regs[0][0]:
                        continue

                    q0_minus = x_red_minus+x
                    q0 = x_red-x
                    q1 = 1/x
                    a, b = self._parent._change_basis(x_red)
                    am, bm = self._parent._change_basis(x_red_minus)
                    regions[nn].extend([[x_red,[q0,q1],Region(self.embed(x_red),RealField()(1/nn)),[a,b],nn],[x_red_minus,[q0_minus,-q1],Region(self.embed(x_red_minus),RealField()(1/nn)),[am,bm],nn]])
        return [reg for nn, lst in regions.iteritems() if nn < B for reg in lst]
示例#14
0
 def coincidence_index(self, prec=0):
     """
     Returns the probability of two randomly chosen characters being equal.
     """
     if prec == 0:
         RR = RealField()
     else:
         RR = RealField(prec)
     char_dict = {}
     for i in self._element_list:
         if i in char_dict:
             char_dict[i] += 1
         else:
             char_dict[i] = 1
     nn = 0
     ci_num = 0
     for i in char_dict.keys():
         ni = char_dict[i]
         nn += ni
         ci_num += ni*(ni-1)
     ci_den = nn*(nn-1)
     return RR(ci_num)/ci_den
示例#15
0
    def __init__(self):
        r"""
        Create free alphabetic string monoid on generators A-Z.

        EXAMPLES::

            sage: S = AlphabeticStrings(); S
            Free alphabetic string monoid on A-Z
            sage: S.gen(0)
            A
            sage: S.gen(25)
            Z
            sage: S([ i for i in range(26) ])
            ABCDEFGHIJKLMNOPQRSTUVWXYZ
        """
        from sage.rings.all import RealField
        RR = RealField()
        # The characteristic frequency probability distribution of
        # Robert Edward Lewand.
        self._characteristic_frequency_lewand = {
            "A": RR(0.08167), "B": RR(0.01492),
            "C": RR(0.02782), "D": RR(0.04253),
            "E": RR(0.12702), "F": RR(0.02228),
            "G": RR(0.02015), "H": RR(0.06094),
            "I": RR(0.06966), "J": RR(0.00153),
            "K": RR(0.00772), "L": RR(0.04025),
            "M": RR(0.02406), "N": RR(0.06749),
            "O": RR(0.07507), "P": RR(0.01929),
            "Q": RR(0.00095), "R": RR(0.05987),
            "S": RR(0.06327), "T": RR(0.09056),
            "U": RR(0.02758), "V": RR(0.00978),
            "W": RR(0.02360), "X": RR(0.00150),
            "Y": RR(0.01974), "Z": RR(0.00074)}
        # The characteristic frequency probability distribution of
        # H. Beker and F. Piper.
        self._characteristic_frequency_beker_piper = {
            "A": RR(0.082), "B": RR(0.015),
            "C": RR(0.028), "D": RR(0.043),
            "E": RR(0.127), "F": RR(0.022),
            "G": RR(0.020), "H": RR(0.061),
            "I": RR(0.070), "J": RR(0.002),
            "K": RR(0.008), "L": RR(0.040),
            "M": RR(0.024), "N": RR(0.067),
            "O": RR(0.075), "P": RR(0.019),
            "Q": RR(0.001), "R": RR(0.060),
            "S": RR(0.063), "T": RR(0.091),
            "U": RR(0.028), "V": RR(0.010),
            "W": RR(0.023), "X": RR(0.001),
            "Y": RR(0.020), "Z": RR(0.001)}
        alph = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        StringMonoid_class.__init__(self, 26, [ alph[i] for i in range(26) ])
示例#16
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()
                1.9997253418
     
     A probability space can be defined on any list of elements.
     
     EXAMPLES::
     
         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()
                1.5
     """
     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)
示例#17
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 is_RealField(n.parent()):
        R = n.parent()
    else:
        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
示例#18
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
示例#19
0
    def __init__(self, lfun, prec=None):
        """
        Initialization of the L-function from a PARI L-function.

        INPUT:

        - lfun -- a PARI :pari:`lfun` object or an instance of :class:`lfun_generic`
        - prec -- integer (default: 53) number of *bits* of precision

        EXAMPLES::

            sage: from sage.lfunctions.pari import lfun_generic, LFunction
            sage: lf = lfun_generic(conductor=1, gammaV=[0], weight=1, eps=1, poles=[1], residues=[-1], v=pari('k->vector(k,n,1)'))
            sage: L = LFunction(lf)
            sage: L.num_coeffs()
            4
        """
        if isinstance(lfun, lfun_generic):
            # preparation using motivic data
            self._L = lfun.__pari__()
            if prec is None:
                prec = lfun.prec
        elif isinstance(lfun, Gen):
            # already some PARI lfun
            self._L = lfun
        else:
            # create a PARI lfunction from other input data
            self._L = pari.lfuncreate(lfun)

        self._conductor = ZZ(self._L[4])  # needs check
        self._weight = ZZ(self._L[3])  # needs check
        if prec is None:
            self.prec = 53
        else:
            self.prec = PyNumber_Index(prec)
        self._RR = RealField(self.prec)
        self._CC = ComplexField(self.prec)
        # Complex field used for inputs, which ensures exact 1-to-1
        # conversion to/from PARI. Since PARI objects have a precision
        # in machine words (not bits), this is typically higher. For
        # example, the default of 53 bits of precision would become 64.
        self._CCin = ComplexField(pari.bitprecision(self._RR(1)))
示例#20
0
def scale_by_units(E):
    r""" Return a model of E reduced with respect to scaling by units, then
    w.r.t. q1,q2,q3 mod 2,3,2.  The latter is Sage's
    E._reduce_model().  The former is new (but the function here is
    similar to both one which Nook write for Magma and the
    ReducedModel() function in Magma); it is only implemented for real
    quadratic fields so far.

    INPUT:

    - ``E`` -- an elliptic curve over a number field K, assumed integral

    OUTPUT:

    A model for E, optimally scaled with repect to units when K is
    real quadratic; unchanged otherwise.
    """
    K = E.base_field()
    if not K.signature() == (2, 0):
        return E

    embs = K.embeddings(RealField(1000))  # lower precision works badly!
    u = K.units()[0]
    uv = [e(u).abs().log() for e in embs]

    c4, c6 = E.c_invariants()
    c4s = [e(c4) for e in embs]
    c6s = [e(c6) for e in embs]
    v = [(x4.abs()**(1 / 4) + x6.abs()**(1 / 6)).log()
         for x4, x6 in zip(c4s, c6s)]
    kr = -(v[0] * uv[0] + v[1] * uv[1]) / (uv[0]**2 + uv[1]**2)
    k1 = kr.floor()
    k2 = kr.ceil()
    nv1 = (v[0] + k1 * uv[0])**2 + (v[1] + k1 * uv[1])**2
    nv2 = (v[0] + k2 * uv[0])**2 + (v[1] + k2 * uv[1])**2
    if nv1 < nv2:
        k = k1
    else:
        k = k2
    return E.scale_curve(u**k)
示例#21
0
def frequency_distribution(S, n=1, field=None):
    """
    The probability space of frequencies of n-character substrings of S.
    """
    if isinstance(S, tuple):
        S = list(S)
    elif isinstance(S, (str, StringMonoidElement)):
        S = [S[i:i + n] for i in range(len(S) - n + 1)]
    if field is None:
        field = RealField()
    if isinstance(S, list):
        P = {}
        N = len(S)
        eps = field(1) / N
        for i in range(N):
            c = S[i]
            if P.has_key(c):
                P[c] += eps
            else:
                P[c] = eps
        return DiscreteProbabilitySpace(S, P, field)
    raise TypeError, "Argument S (= %s) must be a string, list, or tuple."
示例#22
0
    def initialize_fundom(self):
        F = self._F
        Pts = [self.embed_coords(a,b) for a in [0,1] for b in [0,1]]
        xmin = min([P.x for P in Pts])
        xmax = max([P.x for P in Pts])
        ymin = min([P.y for P in Pts])
        ymax = max([P.y for P in Pts])

        self._aplusbomega = dict([])
        rangea = self.rangea_gen(xmin-1,ymin-1,xmax+1,ymax+1)
        for b in self._ranget:
            bw = b * self._w
            for a in rangea(b):
                self._aplusbomega[(a,b)] = a + bw

        dx = RealField()(0.49)
        dy = dx
        Nx = ceil((xmax-xmin) / dx)
        Ny = ceil((ymax-ymin) / dy)
        self._holes = deque([])
        for ii, jj in product(range(Nx), range(Ny)):
            self._holes.append(Hole(self,[xmin+ii*dx,ymin+jj*dy,xmin+(ii+1)*dx,ymin+(jj+1)*dy]))
示例#23
0
    def __getattr__(self, name):
        """
        EXAMPLE::

            sage: DiscreteGaussianSamplerRejection(3.0).foo
            Traceback (most recent call last):
            ...
            AttributeError: 'DiscreteGaussianSamplerRejection' object has no attribute 'foo'
        """
        if name == "rho":
            # we delay the creation of rho until we actually need it
            R = RealField(self.precision)
            self.rho = [
                round(self.max_precs * exp(
                    (-(R(x) / R(self.stddev))**2) / R(2)))
                for x in range(0, self.upper_bound)
            ]
            self.rho[0] = self.rho[0] / 2
            return self.rho
        else:
            raise AttributeError("'%s' object has no attribute '%s'" %
                                 (self.__class__.__name__, name))
示例#24
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::

        sage:  ## Test several values for a given character
        sage: RR = RealField(100)
        sage: for i in range(5):
        ...       print "L(" + str(1+2*i) + ", (-4/.)): ", 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

        sage: ## Testing the accuracy of the negative special values
        sage: ## ---- THIS FAILS SINCE THE DIRICHLET SERIES DOESN'T CONVERGE HERE! ----

        sage: ## Test several characters agree with the exact value, to a given accuracy.
        sage: for d in range(-20,0):
        ...       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 = ", d, "    exact = ", RR(quadratic_L_function__exact(1, d)), "    numerical = ", RR(quadratic_L_function__numerical(1, d))
        ...

    """
    ## Set the correct precision if it's given (for n).
    if is_RealField(n.parent()):
        R = n.parent()
    else:
        R = RealField()

    d1 = fundamental_discriminant(d)
    ans = R(0)
    for i in range(1, num_terms):
        ans += R(kronecker_symbol(d1, i) / R(i)**n)
    return ans
示例#25
0
    def frequency_distribution(self, length=1, prec=0):
        """
        Returns the probability space of character frequencies. The output
        of this method is different from that of the method
        :func:`characteristic_frequency()
        <sage.monoids.string_monoid.AlphabeticStringMonoid.characteristic_frequency>`.
        One can think of the characteristic frequency probability of an
        element in an alphabet `A` as the expected probability of that element
        occurring. Let `S` be a string encoded using elements of `A`. The
        frequency probability distribution corresponding to `S` provides us
        with the frequency probability of each element of `A` as observed
        occurring in `S`. Thus one distribution provides expected
        probabilities, while the other provides observed probabilities.

        INPUT:

        - ``length`` -- (default ``1``) if ``length=1`` then consider the
          probability space of monogram frequency, i.e. probability
          distribution of single characters. If ``length=2`` then consider
          the probability space of digram frequency, i.e. probability
          distribution of pairs of characters. This method currently
          supports the generation of probability spaces for monogram
          frequency (``length=1``) and digram frequency (``length=2``).

        - ``prec`` -- (default ``0``) a non-negative integer representing
          the precision (in number of bits) of a floating-point number. The
          default value ``prec=0`` means that we use 53 bits to represent
          the mantissa of a floating-point number. For more information on
          the precision of floating-point numbers, see the function
          :func:`RealField() <sage.rings.real_mpfr.RealField>` or refer to the module
          :mod:`real_mpfr <sage.rings.real_mpfr>`.

        EXAMPLES:

        Capital letters of the English alphabet::

            sage: M = AlphabeticStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            <BLANKLINE>
            [(A, 0.250000000000000),
            (B, 0.250000000000000),
            (C, 0.250000000000000),
            (D, 0.250000000000000)]

        The binary number system::

            sage: M = BinaryStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            [(0, 0.593750000000000), (1, 0.406250000000000)]

        The hexadecimal number system::

            sage: M = HexadecimalStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            <BLANKLINE>
            [(1, 0.125000000000000),
            (2, 0.125000000000000),
            (3, 0.125000000000000),
            (4, 0.125000000000000),
            (6, 0.500000000000000)]

        Get the observed frequency probability distribution of digrams in the
        string "ABCD". This string consists of the following digrams: "AB",
        "BC", and "CD". Now find out the frequency probability of each of
        these digrams as they occur in the string "ABCD"::

            sage: M = AlphabeticStrings().encoding("abcd")
            sage: D = M.frequency_distribution(length=2).function()
            sage: sorted(D.items())
            [(AB, 0.333333333333333), (BC, 0.333333333333333), (CD, 0.333333333333333)]
        """
        if not length in (1, 2):
            raise NotImplementedError("Not implemented")
        if prec == 0:
            RR = RealField()
        else:
            RR = RealField(prec)
        S = self.parent()
        n = S.ngens()
        if length == 1:
            Alph = S.gens()
        else:
            Alph = tuple([ x*y for x in S.gens() for y in S.gens() ])
        X = {}
        N = len(self)-length+1
        eps = RR(Integer(1)/N)
        for i in range(N):
            c = self[i:i+length]
            if c in X:
                X[c] += eps
            else:
                X[c] = eps
        # Return a dictionary of probability distribution. This should
        # allow for easier parsing of the dictionary.
        from sage.probability.random_variable import DiscreteProbabilitySpace
        return DiscreteProbabilitySpace(Alph, X, RR)
示例#26
0
    def an_numerical(self, prec = None,
                         use_database=True, proof=None):
        r"""
        Return the numerical analytic order of `Sha`, which is
        a floating point number in all cases.

        INPUT:

        - ``prec`` - integer (default: 53) bits precision -- used
          for the L-series computation, period,  regulator, etc.
        - ``use_database`` - whether the rank and generators should
          be looked up in the database if possible. Default is ``True``
        - ``proof`` - bool or ``None`` (default: ``None``, see proof.[tab] or
          sage.structure.proof) proof option passed
          onto regulator and rank computation.

        .. note::

            See also the :meth:`an` command, which will return a
            provably correct integer when the rank is 0 or 1.

        .. WARNING::

            If the curve's generators are not known, computing
            them may be very time-consuming.  Also, computation of the
            L-series derivative will be time-consuming for large rank and
            large conductor, and the computation time for this may
            increase substantially at greater precision.  However, use of
            very low precision less than about 10 can cause the underlying
            PARI library functions to fail.

        EXAMPLES::

            sage: EllipticCurve('11a').sha().an_numerical()
            1.00000000000000
            sage: EllipticCurve('37a').sha().an_numerical()
            1.00000000000000
            sage: EllipticCurve('389a').sha().an_numerical()
            1.00000000000000
            sage: EllipticCurve('66b3').sha().an_numerical()
            4.00000000000000
            sage: EllipticCurve('5077a').sha().an_numerical()
            1.00000000000000

        A rank 4 curve::

            sage: EllipticCurve([1, -1, 0, -79, 289]).sha().an_numerical()  # long time (3s on sage.math, 2011)
            1.00000000000000

        A rank 5 curve::

            sage: EllipticCurve([0, 0, 1, -79, 342]).sha().an_numerical(prec=10, proof=False)  # long time (22s on sage.math, 2011)
            1.0

        See :trac:`1115`::

            sage: sha=EllipticCurve('37a1').sha()
            sage: [sha.an_numerical(prec) for prec in xrange(40,100,10)]  # long time (3s on sage.math, 2013)
            [1.0000000000,
            1.0000000000000,
            1.0000000000000000,
            1.0000000000000000000,
            1.0000000000000000000000,
            1.0000000000000000000000000]
        """
        if prec is None:
            prec = RealField().precision()
        RR = RealField(prec)
        prec2 = prec+2
        RR2 = RealField(prec2)
        try:
            an = self.__an_numerical
            if an.parent().precision() >= prec:
                return RR(an)
            else: # cached precision too low
                pass
        except AttributeError:
            pass
        # it's critical to switch to the minimal model.
        E = self.Emin
        r = Integer(E.rank(use_database=use_database, proof=proof))
        L = E.lseries().dokchitser(prec=prec2)
        Lr= RR2(L.derivative(1,r))  # L.derivative() returns a Complex
        Om = RR2(E.period_lattice().omega(prec2))
        Reg = E.regulator(use_database=use_database, proof=proof, precision=prec2)
        T = E.torsion_order()
        cp = E.tamagawa_product()
        Sha = RR((Lr*T*T)/(r.factorial()*Om*cp*Reg))
        self.__an_numerical = Sha
        return Sha
示例#27
0
    def _sage_(self):
        """
        Convert self to a Sage object.

        EXAMPLES::
        
            sage: a = axiom(1/2); a #optional - axiom
              1
              -
              2
            sage: a.sage()          #optional - axiom
            1/2
            sage: _.parent()        #optional - axiom
            Rational Field

            sage: gp(axiom(1/2))    #optional - axiom
            1/2

            sage: fricas(1/2).sage() #optional - fricas
            1/2

        DoubleFloat's in Axiom are converted to be in RDF in Sage.

        ::
        
            sage: axiom(2.0).as_type('DoubleFloat').sage()  #optional - axiom
            2.0
            sage: _.parent() #optional - axiom
            Real Double Field


            sage: axiom(2.1234)._sage_() #optional - axiom
            2.12340000000000
            sage: _.parent()             #optional - axiom
            Real Field with 53 bits of precision
            sage: a = RealField(100)(pi)
            sage: axiom(a)._sage_()      #optional - axiom 
            3.1415926535897932384626433833
            sage: _.parent()             #optional - axiom
            Real Field with 100 bits of precision
            sage: axiom(a)._sage_() == a #optional - axiom
            True
            sage: axiom(2.0)._sage_() #optional - axiom
            2.00000000000000
            sage: _.parent() #optional  - axiom
            Real Field with 53 bits of precision


        We can also convert Axiom's polynomials to Sage polynomials.
            sage: a = axiom(x^2 + 1)   #optional - axiom
            sage: a.type()             #optional - axiom
            Polynomial Integer
            sage: a.sage()             #optional - axiom
            x^2 + 1
            sage: _.parent()           #optional - axiom
            Univariate Polynomial Ring in x over Integer Ring
            sage: axiom('x^2 + y^2 + 1/2').sage()    #optional - axiom
            y^2 + x^2 + 1/2
            sage: _.parent()                         #optional - axiom
            Multivariate Polynomial Ring in y, x over Rational Field

        
        """
        P = self._check_valid()
        type = str(self.type())

        if type in ["Type", "Domain"]:
            return self._sage_domain()

        if type == "Float":
            from sage.rings.all import RealField, ZZ
            prec = max(self.mantissa().length()._sage_(), 53)
            R = RealField(prec)
            x, e, b = self.unparsed_input_form().lstrip('float(').rstrip(
                ')').split(',')
            return R(ZZ(x) * ZZ(b)**ZZ(e))
        elif type == "DoubleFloat":
            from sage.rings.all import RDF
            return RDF(repr(self))
        elif type.startswith('Polynomial'):
            from sage.rings.all import PolynomialRing
            base_ring = P(type.lstrip('Polynomial '))._sage_domain()
            vars = str(self.variables())[1:-1]
            R = PolynomialRing(base_ring, vars)
            return R(self.unparsed_input_form())

        #If all else fails, try using the unparsed input form
        try:
            import sage.misc.sage_eval
            return sage.misc.sage_eval.sage_eval(self.unparsed_input_form())
        except:
            raise NotImplementedError
    def __init__(self, B, sigma=1, c=None, precision=None):
        r"""
        Construct a discrete Gaussian sampler over the lattice `Λ(B)`
        with parameter ``sigma`` and center `c`.

        INPUT:

        - ``B`` -- a basis for the lattice, one of the following:

          - an integer matrix,
          - an object with a ``matrix()`` method, e.g. ``ZZ^n``, or
          - an object where ``matrix(B)`` succeeds, e.g. a list of vectors.

        - ``sigma`` -- Gaussian parameter `σ>0`.
        - ``c`` -- center `c`, any vector in `\ZZ^n` is supported, but `c ∈ Λ(B)` is faster.
        - ``precision`` -- bit precision `≥ 53`.

        EXAMPLES::

            sage: from sage.stats.distributions.discrete_gaussian_lattice import DiscreteGaussianDistributionLatticeSampler
            sage: n = 2; sigma = 3.0; m = 5000
            sage: D = DiscreteGaussianDistributionLatticeSampler(ZZ^n, sigma)
            sage: f = D.f
            sage: c = D._normalisation_factor_zz(); c
            56.2162803067524

            sage: l = [D() for _ in range(m)]
            sage: v = vector(ZZ, n, (-3,-3))
            sage: l.count(v), ZZ(round(m*f(v)/c))
            (39, 33)

            sage: target = vector(ZZ, n, (0,0))
            sage: l.count(target), ZZ(round(m*f(target)/c))
            (116, 89)

            sage: from sage.stats.distributions.discrete_gaussian_lattice import DiscreteGaussianDistributionLatticeSampler
            sage: qf = QuadraticForm(matrix(3, [2, 1, 1,  1, 2, 1,  1, 1, 2]))
            sage: D = DiscreteGaussianDistributionLatticeSampler(qf, 3.0); D
            Discrete Gaussian sampler with σ = 3.000000, c=(0, 0, 0) over lattice with basis
            <BLANKLINE>
            [2 1 1]
            [1 2 1]
            [1 1 2]
            sage: D()
            (0, 1, -1)
        """
        precision = DiscreteGaussianDistributionLatticeSampler.compute_precision(precision, sigma)

        self._RR = RealField(precision)
        self._sigma = self._RR(sigma)

        try:
            B = matrix(B)
        except (TypeError, ValueError):
            pass

        try:
            B = B.matrix()
        except AttributeError:
            pass

        self.B = B
        self._G = B.gram_schmidt()[0]

        try:
            c = vector(ZZ, B.ncols(), c)
        except TypeError:
            try:
                c = vector(QQ, B.ncols(), c)
            except TypeError:
                c = vector(RR, B.ncols(), c)

        self._c = c

        self.f = lambda x: exp(-(vector(ZZ, B.ncols(), x) - c).norm() ** 2 / (2 * self._sigma ** 2))

        # deal with trivial case first, it is common
        if self._G == 1 and self._c == 0:
            self._c_in_lattice = True
            D = DiscreteGaussianDistributionIntegerSampler(sigma=sigma)
            self.D = tuple([D for _ in range(self.B.nrows())])
            self.VS = FreeModule(ZZ, B.nrows())
            return

        w = B.solve_left(c)
        if w in ZZ ** B.nrows():
            self._c_in_lattice = True
            D = []
            for i in range(self.B.nrows()):
                sigma_ = self._sigma / self._G[i].norm()
                D.append(DiscreteGaussianDistributionIntegerSampler(sigma=sigma_))
            self.D = tuple(D)
            self.VS = FreeModule(ZZ, B.nrows())
        else:
            self._c_in_lattice = False
示例#29
0
    def deriv_at1(self, k=None, prec=None):
        r"""
        Compute `L'(E,1)` using `k` terms of the series for `L'(E,1)`,
        under the assumption that `L(E,1) = 0`.

        The algorithm used is from Section 7.5.3 of Henri Cohen's book
        *A Course in Computational Algebraic Number Theory*.

        INPUT:

        - ``k`` -- number of terms of the series. If zero or ``None``,
          use `k = \sqrt{N}`, where `N` is the conductor.

        - ``prec`` -- numerical precision in bits. If zero or ``None``,
          use a reasonable automatic default.

        OUTPUT:

        A tuple of real numbers ``(L1, err)`` where ``L1`` is an
        approximation for `L'(E,1)` and ``err`` is a bound on the error
        in the approximation.

        .. WARNING::

            This function only makes sense if `L(E)` has positive order
            of vanishing at 1, or equivalently if `L(E,1) = 0`.

        ALGORITHM:

        - Compute the root number eps.  If it is 1, return 0.

        - Compute the Fourier coefficients `a_n`, for `n` up to and
          including `k`.

        - Compute the sum

          .. MATH::

                 2 \cdot \sum_{n=1}^{k} (a_n / n) \cdot E_1(2 \pi n/\sqrt{N}),

          where `N` is the conductor of `E`, and `E_1` is the
          exponential integral function.

        - Compute a bound on the tail end of the series, which is

          .. MATH::

                 2 e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \pi/\sqrt{N}}).

          For a proof see [Grigorov-Jorza-Patrascu-Patrikis-Stein].  This
          is exactly the same as the bound for the approximation to
          `L(E,1)` produced by :meth:`at1`.

        EXAMPLES::

            sage: E = EllipticCurve('37a')
            sage: E.lseries().deriv_at1()
            (0.3059866, 0.000801045)
            sage: E.lseries().deriv_at1(100)
            (0.3059997738340523018204836833216764744526377745903, 1.52493e-45)
            sage: E.lseries().deriv_at1(1000)
            (0.305999773834052301820483683321676474452637774590771998..., 2.75031e-449)

        With less numerical precision, the error is bounded by numerical accuracy::

            sage: L,err = E.lseries().deriv_at1(100, prec=64)
            sage: L,err
            (0.305999773834052302, 5.55318e-18)
            sage: parent(L)
            Real Field with 64 bits of precision
            sage: parent(err)
            Real Field with 24 bits of precision and rounding RNDU

        Rank 2 and rank 3 elliptic curves::

            sage: E = EllipticCurve('389a1')
            sage: E.lseries().deriv_at1()
            (0.0000000, 0.000000)
            sage: E = EllipticCurve((1, 0, 1, -131, 558))  # curve 59450i1
            sage: E.lseries().deriv_at1()
            (-0.00010911444, 0.142428)
            sage: E.lseries().deriv_at1(4000)
            (6.990...e-50, 1.31318e-43)
        """
        sqrtN = sqrt(self.__E.conductor())
        if k:
            k = int(k)
        else:
            k = int(ceil(sqrtN))

        if prec:
            prec = int(prec)
        else:
            # Estimate number of bits for the computation, based on error
            # estimate below (the denominator of that error is close enough
            # to 1 that we can ignore it).
            # 9.065 = 2*Pi/log(2)
            # 1.443 = 1/log(2)
            # 12 is an arbitrary extra number of bits (it is chosen
            #    such that the precision is 24 bits when the conductor
            #    equals 11 and k is the default value 4)
            prec = int(9.065 * k / sqrtN + 1.443 * log(k)) + 12
        R = RealField(prec)
        # Compute error term with bounded precision of 24 bits and
        # round towards +infinity
        Rerror = RealField(24, rnd='RNDU')

        if self.__E.root_number() == 1:
            # Order of vanishing at 1 of L(E) is even and assumed to be
            # positive, so L'(E,1) = 0.
            return (R.zero(), Rerror.zero())

        an = self.__E.anlist(k)  # list of Sage Integers
        pi = R.pi()
        sqrtN = R(self.__E.conductor()).sqrt()
        v = exp_integral.exponential_integral_1(2 * pi / sqrtN, k)

        # Compute series sum and accumulate floating point errors
        L = R.zero()
        error = Rerror.zero()
        # Sum of |an[n]|/n
        sumann = Rerror.zero()

        for n in xrange(1, k + 1):
            term = (v[n - 1] * an[n]) / n
            L += term
            error += term.epsilon(Rerror) * 5 + L.ulp(Rerror)
            sumann += Rerror(an[n].abs()) / n
        L *= 2

        # Add error term for exponential_integral_1() errors.
        # Absolute error for 2*v[i] is 4*max(1, v[0])*2^-prec
        if v[0] > 1.0:
            sumann *= Rerror(v[0])
        error += (sumann >> (prec - 2))

        # Add series error (we use (-2)/(z-1) instead of 2/(1-z)
        # because this causes 1/(1-z) to be rounded up)
        z = (-2 * pi / sqrtN).exp()
        zpow = ((-2 * (k + 1)) * pi / sqrtN).exp()
        error += ((-2) * Rerror(zpow)) / Rerror(z - 1)
        return (L, error)
示例#30
0
    def at1(self, k=None, prec=None):
        r"""
        Compute `L(E,1)` using `k` terms of the series for `L(E,1)` as
        explained in Section 7.5.3 of Henri Cohen's book *A Course in
        Computational Algebraic Number Theory*.  If the argument `k`
        is not specified, then it defaults to `\sqrt{N}`, where `N` is
        the conductor.

        INPUT:

        - ``k`` -- number of terms of the series. If zero or ``None``,
          use `k = \sqrt{N}`, where `N` is the conductor.

        - ``prec`` -- numerical precision in bits. If zero or ``None``,
          use a reasonable automatic default.

        OUTPUT:

        A tuple of real numbers ``(L, err)`` where ``L`` is an
        approximation for `L(E,1)` and ``err`` is a bound on the error
        in the approximation.

        This function is disjoint from the PARI ``elllseries``
        command, which is for a similar purpose.  To use that command
        (via the PARI C library), simply type
        ``E.pari_mincurve().elllseries(1)``.

        ALGORITHM:

        - Compute the root number eps.  If it is -1, return 0.

        - Compute the Fourier coefficients `a_n`, for `n` up to and
          including `k`.

        - Compute the sum

          .. MATH::

              2 \cdot \sum_{n=1}^{k} \frac{a_n}{n} \cdot \exp(-2*pi*n/\sqrt{N}),

          where `N` is the conductor of `E`.

        - Compute a bound on the tail end of the series, which is

          .. MATH::

                2 e^{-2 \pi (k+1) / \sqrt{N}} / (1 - e^{-2 \pi/\sqrt{N}}).

          For a proof see [Grigov-Jorza-Patrascu-Patrikis-Stein].

        EXAMPLES::

            sage: L, err = EllipticCurve('11a1').lseries().at1()
            sage: L, err
            (0.253804, 0.000181444)
            sage: parent(L)
            Real Field with 24 bits of precision
            sage: E = EllipticCurve('37b')
            sage: E.lseries().at1()
            (0.7257177, 0.000800697)
            sage: E.lseries().at1(100)
            (0.7256810619361527823362055410263965487367603361763, 1.52469e-45)
            sage: L,err = E.lseries().at1(100, prec=128)
            sage: L
            0.72568106193615278233620554102639654873
            sage: parent(L)
            Real Field with 128 bits of precision
            sage: err
            1.70693e-37
            sage: parent(err)
            Real Field with 24 bits of precision and rounding RNDU

        Rank 1 through 3 elliptic curves::

            sage: E = EllipticCurve('37a1')
            sage: E.lseries().at1()
            (0.0000000, 0.000000)
            sage: E = EllipticCurve('389a1')
            sage: E.lseries().at1()
            (-0.001769566, 0.00911776)
            sage: E = EllipticCurve('5077a1')
            sage: E.lseries().at1()
            (0.0000000, 0.000000)
        """
        sqrtN = sqrt(self.__E.conductor())
        if k:
            k = int(k)
        else:
            k = int(ceil(sqrtN))

        if prec:
            prec = int(prec)
        else:
            # Use the same precision as deriv_at1() below for
            # consistency
            prec = int(9.065 * k / sqrtN + 1.443 * log(k)) + 12
        R = RealField(prec)
        # Compute error term with bounded precision of 24 bits and
        # round towards +infinity
        Rerror = RealField(24, rnd='RNDU')

        if self.__E.root_number() == -1:
            return (R.zero(), Rerror.zero())

        an = self.__E.anlist(k)  # list of Sage Integers
        pi = R.pi()
        sqrtN = R(self.__E.conductor()).sqrt()

        z = (-2 * pi / sqrtN).exp()
        zpow = z
        # Compute series sum and accumulate floating point errors
        L = R.zero()
        error = Rerror.zero()

        for n in xrange(1, k + 1):
            term = (zpow * an[n]) / n
            zpow *= z
            L += term
            # We express relative error in units of epsilon, where
            # epsilon is a number divided by 2^precision.
            # Instead of multiplying the error by 2 after the loop
            # (to account for L *= 2), we already multiply it now.
            #
            # For multiplication and division, the relative error
            # in epsilons is bounded by (1+e)^n - 1, where n is the
            # number of operations (assuming exact inputs).
            # exp(x) additionally multiplies this error by abs(x) and
            # adds one epsilon. The inputs pi and sqrtN each contribute
            # another epsilon.
            # Assuming that 2*pi/sqrtN <= 2, the relative error for z is
            # 7 epsilon. This implies a relative error of (8n-1) epsilon
            # for zpow. We add 2 for the computation of term and 1/2 to
            # compensate for the approximation (1+e)^n = 1+ne.
            #
            # The error of the addition is at most half an ulp of the
            # result.
            #
            # Multiplying everything by two gives:
            error += term.epsilon(Rerror) * (16 * n + 3) + L.ulp(Rerror)
        L *= 2

        # Add series error (we use (-2)/(z-1) instead of 2/(1-z)
        # because this causes 1/(1-z) to be rounded up)
        error += ((-2) * Rerror(zpow)) / Rerror(z - 1)
        return (L, error)