Example #1
0
File: lwe.py Project: sagemath/sage
    def __init__(self, n, instance='key', m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        all other parameters are chosen as in [CGW2013]_.

        INPUT:

        - ``n`` - security parameter (integer >= 89)
        - ``instance`` - one of

          - "key" - the LWE-instance that hides the secret key is generated
          - "encrypt" - the LWE-instance that hides the message is generated
            (default: ``key``)

        - ``m`` - number of allowed samples or ``None`` in which case ``m`` is
          chosen as in [CGW2013]_.  (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import UniformNoiseLWE
            sage: UniformNoiseLWE(89)
            LWE(89, 154262477, UniformSampler(0, 351), 'noise', 131)

            sage: UniformNoiseLWE(89, instance='encrypt')
            LWE(131, 154262477, UniformSampler(0, 497), 'noise', 181)
        """

        if n<89:
            raise TypeError("Parameter too small")

        n2 = n
        C  = 4/sqrt(2*pi)
        kk = floor((n2-2*log(n2, 2)**2)/5)
        n1 = floor((3*n2-5*kk)/2)
        ke = floor((n1-2*log(n1, 2)**2)/5)
        l  = floor((3*n1-5*ke)/2)-n2
        sk = ceil((C*(n1+n2))**(3/2))
        se = ceil((C*(n1+n2+l))**(3/2))
        q = next_prime(max(ceil((4*sk)**((n1+n2)/n1)), ceil((4*se)**((n1+n2+l)/(n2+l))), ceil(4*(n1+n2)*se*sk+4*se+1)))

        if kk<=0:
            raise TypeError("Parameter too small")

        if instance == 'key':
            D  = UniformSampler(0, sk-1)
            if m is None:
                m = n1
            LWE.__init__(self, n=n2, q=q, D=D, secret_dist='noise', m=m)
        elif instance == 'encrypt':
            D   = UniformSampler(0, se-1)
            if m is None:
                m = n2+l
            LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m)
        else:
            raise TypeError("Parameter instance=%s not understood."%(instance))
Example #2
0
    def holonomy_representation(self):
        r"""
        Return the holonomy representation in `SO(2)` as two lists.

        The first list correspond to cycles around vertices, while the second
        correspond to a cycle basis that generate homology.

        EXAMPLES::

            sage: from surface_dynamics.all import *

            sage: e = '(0,1)(2,3)'
            sage: f = '(0,2,1,3)'
            sage: a = [1/2,1/2,1/2,1/2]
            sage: r = RibbonGraphWithAngles(edges=e,faces=f,angles=a)
            sage: r.holonomy_representation()
            ([0], [0, 0])

        The standard cube::

            sage: e = tuple((i,i+1) for i in xrange(0,24,2))
            sage: f = '(0,20,7,10)(16,22,19,21)(2,9,5,23)(14,3,17,1)(12,8,15,11)(18,4,13,6)'
            sage: a = [1/2]*24
            sage: r = RibbonGraphWithAngles(edges=e,faces=f,angles=a)
            sage: r.holonomy_representation()
            ([3/2, 3/2, 3/2, 3/2, 3/2, 3/2, 3/2, 3/2], [])

        Two copies of a triangle::

            sage: e = '(0,1)(2,3)(4,5)'
            sage: f = '(0,2,4)(1,5,3)'
            sage: a = [1/2,1/6,1/3,1/3,1/6,1/2]
            sage: r = RibbonGraphWithAngles(edges=e,faces=f,angles=a)
            sage: r.holonomy_representation()
            ([1, 1/2, 1/2], [])

            sage: a = [1/3,7/15,1/5,1/5,7/15,1/3]
            sage: r = RibbonGraphWithAngles(edges=e,faces=f,angles=a)
            sage: r.holonomy_representation()
            ([2/3, 2/3, 2/3], [])
        """
        from sage.functions.other import floor

        l1 = []
        for c in xrange(self.num_vertices()):
            w = self.angle_at_vertex(c)
            l1.append(w - 2*floor(w/2))

        l2 = []
        for c in self.cycle_basis():
            w = self.winding(c)
            l2.append(w - 2*floor(w/2))

        return l1,l2
Example #3
0
def calcPrecisionDimension(B_cF, S):
	"""
	When calculating the Fourier expansion `a[S]` of the reduction Elliptic modular form,
	this gives the maximum precision we can calculate from a Fourier expansion `a` of
	a Hermitian modular form, where the precision of `a` is given by `B_cF`.

	See the text for details.

	Note: This is like the C++ implementation `calcPrecisionDimension()` in `algo_cpp.cpp`.
	We don't actually need this function in Python, except for testing.

	INPUT:

	- `B_cF` -- an integer: the precision of the FE of the Hermitian modular forms.

	- `S` -- the reduction matrix for `a[S]`.

	OUTPUT:

	- an integer: the precision of the FE of the Elliptic modular forms.
	"""

	assert S[0,1] == S[1,0].conjugate()
	s,t,u = S[0,0], S[0,1], S[1,1]
	s, u = QQ(s), QQ(u)
	precDim = B_cF * (min(s, u) - 2 * abs(t))
	precDim = RR(precDim)
	if precDim < 0: return 0
	precDim = floor(precDim)
	return precDim
Example #4
0
def mod_one(x):
    """
    Return ``x`` mod 1.

    INPUT:

    - ``x`` -- a real number

    OUTPUT:

    ``x`` mod 1, a number in `[0,1)`.

    TESTS::

        sage: from sage.dynamics.foliations.base import mod_one
        sage: mod_one(2.5)
        0.500000000000000
        sage: mod_one(-1.7)
        0.300000000000000
        sage: mod_one(7/6)
        1/6
        sage: mod_one(-1/6)
        5/6
        sage: a = QQbar(sqrt(2)); a
        1.414213562373095?
        sage: mod_one(a)
        0.4142135623730951?

    """
    return x - floor(x)
Example #5
0
def repr_matrix(coeffs):
    from sage.functions.other import floor
    ncols = 0
    lengths = [ ]
    for row in coeffs:
        l = len(row)
        if ncols < l:
            lengths.extend([0] * (l-ncols))
            ncols = l
        for j in range(l):
            elt = str(row[j]); l = len(elt)
            if lengths[j] < len(elt)+2:
                lengths[j] = len(elt)+2
    s = ""
    for row in coeffs:
        s += "["
        for j in range(len(row)):
            elt = str(row[j]); l = len(elt)
            nbspace = floor((lengths[j]-l)/2)
            s += " " * nbspace
            s += elt
            s += " " * (lengths[j]-l-nbspace)
        for j in range(len(row),ncols):
            s += " " * lengths[j]
        s += "]\n"
    return s[:-1]
    def iter_positive_forms_with_content(self) :
        if self.__disc is infinity :
            raise ValueError, "infinity is not a true filter index"
        
        
        if self.__reduced :        
            for a in xrange(1,isqrt(self.__disc // 3) + 1) :
                for b in xrange(a+1) :
                    g = gcd(a, b)
                    for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                        yield (a,b,c), gcd(g,c)
        else :
            maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
            for a in xrange(1, maxtrace + 1) :
                for c in xrange(1, maxtrace - a + 1) :
                    g = gcd(a,c)
                    
                    Bu = isqrt(4*a*c - 1)

                    di = 4*a*c - self.__disc
                    if di >= 0 :
                        Bl = isqrt(di) + 1 
                    else :
                        Bl = 0
                    
                    for b in xrange(-Bu, -Bl + 1) :
                        yield (a,b,c), gcd(g,b)
                    for b in xrange(Bl, Bu + 1) :
                        yield (a,b,c), gcd(g,b)
        #! if self.__reduced

        raise StopIteration
Example #7
0
 def calc_prec():
     if self.prec != None:
         return self.prec
     iv0 = IntuitiveAbel(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym)
     self.iv0 = iv0
     self.err = abs(iv0.sexp(0.5) - self.sexp(0.5))
     print "err:", self.err.n(20)
     self.prec = floor(-log(self.err)/log(2.0))
Example #8
0
	def normalize_aws(self):
		"""Arizona Winter School filtration (for families) -- reduces the j-th moment modulo p^(floor((N+1-j)*(p-2)/(p-1))"""
		p=self.p
		N=self.num_moments()
		assert self.valuation() >= 0, "moments not integral in normalization"
		
		v=vector([self.moment(j)%(p**(floor((N+1-j)*(p-2)/(p-1)))) for j in range(0,self.num_moments())])	
		return dist(self.p,self.weight,v)
Example #9
0
	def divmod(self, a, b):
		"""
		Returns q,r such that a = q*b + r.
		This is division with remainder.
		It holds that `self.euclidean_func(r) < `self.euclidean_func(b)`.
		"""
		# Note that this implementation is quite naive!
		# Later, we can do better with QuadraticForm(...). (TODO)
		# Also, read here: http://www.fen.bilkent.edu.tr/~franz/publ/survey.pdf

		if b == 0: raise ZeroDivisionError
		a1,a2 = self.as_tuple_b(a)
		b1,b2 = self.as_tuple_b(b)

		#B = matrix([
		#	[b1, -b2 * (self.D**2 - self.D)/4],
		#	[b2, b1 + b2*self.D]
		#])
		Bdet = b1*b1 + b1*b2*self.D + b2*b2*(self.D**2 - self.D)/4
		Bdet = _simplify(Bdet)
		assert Bdet > 0
		qq1 = (a1*b1 + a1*b2*self.D + a2*b2*(self.D**2 - self.D)/4) / Bdet
		qq2 = (-a1*b2 + a2*b1) / Bdet
		assert _simplify(self.from_tuple_b(qq1,qq2) * b - a) == 0

		# Not sure on this.
		# From qq1 and qq2, we want to select q1,q2 \in \Z such that
		# `r = a - q * b` is minimal with regards to `self.euclidean_func`,
		# where `q = self.from_tuple_b(q1,q2)`.
		# Simply using `round` will not work in all cases; neither does `floor`.
		# Many test cases are (indirectly) in `test_solveR()`.
		# Now we are just checking multiple possibilities and use
		# the smallest one. Note that these are not all possible cases.
		solutions = []
		for q1 in [int(floor(qq1)) + i for i in [-1,0,1,2]]:
			for q2 in [int(floor(qq2)) + i for i in [-1,0,1,2]]:
				q = self.from_tuple_b(q1,q2)
				# q * b + r == a
				r = _simplify(a - q * b)
				euc_r = self.euclidean_func(r)
				solutions += [(euc_r, q, r)]
		euc_b = self.euclidean_func(b)
		euc_r, q, r = min(solutions)
		assert euc_r < euc_b, "%r < %r; r=%r, b=%r, a=%r" % (euc_r, euc_b, r, b, a)
		return q, r
Example #10
0
 def calc_prec(self):
     if self.prec != None:
         return self.prec
     iv0 = IntuitiveTetration(self.bsym,self.N-1,iprec=self.iprec,x0=self.x0sym)
     self.iv0 = iv0
     d = lambda x: self.slog(x) - iv0.slog(x)
     maximum = find_maximum_on_interval(d,0,1,maxfun=20)
     minimum = find_minimum_on_interval(d,0,1,maxfun=20)
     print "max:", maximum[0].n(20), 'at:', maximum[1]
     print "min:", minimum[0].n(20), 'at:', minimum[1]
     self.err = max( abs(maximum[0]), abs(minimum[0]))
     print "slog err:", self.err.n(20)
     self.prec = floor(-self.err.log(2))
     
     self.sexp_err = abs(iv0.sexp(0.5) - self.sexp(0.5))
     print "sexp err:", self.sexp_err.n(20)
     self.sexp_prec = floor(-log(self.sexp_err)/log(2.0))
     return self
Example #11
0
    def _transposition_to_reduced_word(self, t):
        r"""
        Converts the transposition `t = [r,s]` to a reduced word.

        INPUT:

        - a tuple `[r,s]` such that `r` and `s` are not equivalent mod `k`

        OUTPUT:

        - a list of integers in `\{0,1,\ldots,k-1\}` representing a reduced word for the transposition `t`

        EXAMPLE::

            sage: c = Core([],4)
            sage: c._transposition_to_reduced_word([2, 5])
            [2, 3, 0, 3, 2]
            sage: c._transposition_to_reduced_word([2, 5]) == c._transposition_to_reduced_word([5,2])
            True
            sage: c._transposition_to_reduced_word([2, 2])
            Traceback (most recent call last):
            ...
            ValueError: t_0 and t_1 cannot be equal mod k

            sage: c = Core([],30)
            sage: c._transposition_to_reduced_word([4, 12])
            [4, 5, 6, 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5, 4]

            sage: c = Core([],3)
            sage: c._transposition_to_reduced_word([4, 12])
            [1, 2, 0, 1, 2, 0, 2, 1, 0, 2, 1]
        """
        k = self.k()
        if (t[0] - t[1]) % k == 0:
            raise ValueError("t_0 and t_1 cannot be equal mod k")
        if t[0] > t[1]:
            return self._transposition_to_reduced_word([t[1], t[0]])
        else:
            return [i % k for i in range(t[0], t[1] - floor((t[1] - t[0]) / k))] + [
                (t[1] - floor((t[1] - t[0]) / k) - 2 - i) % (k)
                for i in range(t[1] - floor((t[1] - t[0]) / k) - t[0] - 1)
            ]
Example #12
0
File: lwe.py Project: sagemath/sage
    def __init__(self, n, delta=0.01, m=None):
        """
        Construct LWE instance parameterised by security parameter ``n`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP2011]_.

        INPUT:

        - ``n`` - security parameter (integer > 0)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``m=2*n +
          128`` as in [LP2011]_ (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import LindnerPeikert
            sage: LindnerPeikert(n=20)
            LWE(20, 2053, Discrete Gaussian sampler over the Integers with sigma = 3.600954 and c = 0, 'noise', 168)
        """
        if m is None:
            m = 2*n + 128
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #         (c*exp((1-c**2)/2))**(2*n) == 2**-40
        #    log((c*exp((1-c**2)/2))**(2*n)) == -40*log(2)
        #       (2*n)*log(c*exp((1-c**2)/2)) == -40*log(2)
        #  2*n*(log(c)+log(exp((1-c**2)/2))) == -40*log(2)
        #            2*n*(log(c)+(1-c**2)/2) == -40*log(2)
        #              2*n*log(c)+n*(1-c**2) == -40*log(2)
        #  2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP2011]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP2011]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D   = DiscreteGaussianDistributionIntegerSampler(stddev)
        LWE.__init__(self, n=n, q=q, D=D, secret_dist='noise', m=m)
Example #13
0
 def find_integral_max(real_max, f):
     """Given a real (local) maximum of a function `f`, return that of
     the integers around `real_max` which gives the (local) integral
     maximum, and the value of at that point."""
     if real_max in ZZ:
         int_max = Integer(real_max)
         return (int_max, f(int_max))
     else:
         x_f = floor(real_max)
         x_c = x_f + 1
         f_f, f_c = f(x_f), f(x_c)
         return (x_f, f_f) if f_f >= f_c else (x_c, f_c)
Example #14
0
 def calc_diff(self,iv0,debug=0):
     self.prec=None
     iv0.prec=None
     d = lambda x: self.abel(x) - iv0.abel(x)
     a = find_root(lambda x: (self.f(x)+x)/2-self.x0,self.x0-100,self.f(self.x0))
     maximum = find_maximum_on_interval(d,self.x0-a,self.x0+self.f(a),maxfun=20)
     minimum = find_minimum_on_interval(d,self.x0-a,self.x0+self.f(a),maxfun=20)
     if debug>=1: print "max:", maximum[0].n(20), 'at:', maximum[1]
     if debug>=1: print "min:", minimum[0].n(20), 'at:', minimum[1]
     self.err = max( abs(maximum[0]), abs(minimum[0]))
     print "err:", self.err.n(20)
     self.prec = floor(-self.err.log(2))
Example #15
0
 def log(self,workprec=Infinity):
     from sage.functions.log import log
     from sage.functions.other import floor
     if workprec is Infinity:
         raise ApproximationError("unable to compute log to infinite precision")
     parent = self.parent()
     pow = parent(-1)
     res = parent(0)
     t = parent(1) - self
     iter = workprec + floor(log(workprec)/log(parent._p)) + 1
     for i in range(1,iter):
         pow *= t
         res += pow / parent(i)
         res = res.truncate(workprec)
     return res
Example #16
0
File: lwe.py Project: sagemath/sage
    def __init__(self, N, delta=0.01, m=None):
        """
        Construct a Ring-LWE oracle in dimension ``n=phi(N)`` where
        the modulus ``q`` and the ``stddev`` of the noise is chosen as in
        [LP2011]_.

        INPUT:

        - ``N`` - index of cyclotomic polynomial (integer > 0, must be power of 2)
        - ``delta`` - error probability per symbol (default: 0.01)
        - ``m`` - number of allowed samples or ``None`` in which case ``3*n`` is
          used (default: ``None``)

        EXAMPLES::

            sage: from sage.crypto.lwe import RingLindnerPeikert
            sage: RingLindnerPeikert(N=16)
            RingLWE(16, 1031, Discrete Gaussian sampler for polynomials of degree < 8 with σ=2.803372 in each component, x^8 + 1, 'noise', 24)
        """
        n = euler_phi(N)
        if m is None:
            m = 3*n
        # Find c>=1 such that c*exp((1-c**2)/2))**(2*n) == 2**-40
        #  i.e c>=1 such that 2*n*log(c)+n*(1-c**2) + 40*log(2) == 0
        c = SR.var('c')
        c = find_root(2*n*log(c)+n*(1-c**2) + 40*log(2) == 0, 1, 10)
        # Upper bound on s**2/t
        s_t_bound = (sqrt(2) * pi / c / sqrt(2*n*log(2/delta))).n()
        # Interpretation of "choose q just large enough to allow for a Gaussian parameter s>=8" in [LP2011]_
        q = next_prime(floor(2**round(log(256 / s_t_bound, 2))))
        # Gaussian parameter as defined in [LP2011]_
        s = sqrt(s_t_bound*floor(q/4))
        # Transform s into stddev
        stddev = s/sqrt(2*pi.n())
        D = DiscreteGaussianDistributionPolynomialSampler(ZZ['x'], n, stddev)
        RingLWE.__init__(self, N=N, q=q, D=D, poly=None, secret_dist='noise', m=m)
Example #17
0
def ligt(x):
    r"""
    Returns the least integer greater than ``x``.

    EXAMPLES::

        sage: from sage.coding.guruswami_sudan.utils import ligt
        sage: ligt(41)
        42

    It works with any type of numbers (not only integers)::

        sage: ligt(41.041)
        42
    """
    return floor(x+1)
Example #18
0
def trunc(i):
    """
    Truncates to the integer closer to zero

    EXAMPLES::

        sage: from sage.combinat.crystals.tensor_product import trunc
        sage: trunc(-3/2), trunc(-1), trunc(-1/2), trunc(0), trunc(1/2), trunc(1), trunc(3/2)
        (-1, -1, 0, 0, 0, 1, 1)
        sage: isinstance(trunc(3/2), Integer)
        True
    """
    if i>= 0:
        return floor(i)
    else:
        return ceil(i)
Example #19
0
    def P(self, x, y):
        """
        Returns the Kazhdan-Lusztig P polynomial.

        If the rank is large, this runs slowly at first but speeds up
        as you do repeated calculations due to the caching.

        INPUT:

        - ``x``, ``y`` -- elements of the underlying Coxeter group

        .. SEEALSO::

            :mod:`~sage.libs.coxeter3.coxeter_group.CoxeterGroup.kazhdan_lusztig_polynomial`
            for a faster implementation using Fokko Ducloux's Coxeter3 C++ library.

        EXAMPLES ::

            sage: R.<q>=QQ[]
            sage: W = WeylGroup("A3", prefix="s")
            sage: [s1,s2,s3]=W.simple_reflections()
            sage: KL = KazhdanLusztigPolynomial(W, q)
            sage: KL.P(s2,s2*s1*s3*s2)
            q + 1
        """
        if x == 1:
            x = self._one
        if y == 1:
            y = self._one
        if x == y:
            return self._base_ring.one()
        if not x.bruhat_le(y):
            return self._base_ring.zero()
        if y.length() == 0:
            if x.length() == 0:
                return self._base_ring.one()
            else:
                return self._base_ring.zero()
        p = sum(-self.R(x,t)*self.P(t,y) for t in self._coxeter_group.bruhat_interval(x,y) if t != x)
        tr = floor((y.length()-x.length()+1)/2)
        try:
            ret = p.truncate(tr)
        except StandardError:
            ret = laurent_polynomial_truncate(p, tr)
        if self._trace:
            print "    P(%s,%s)=%s"%(x, y, ret)
        return ret
Example #20
0
    def __call__(self, x):
        """
        Returns `self(x)`

        INPUT:

        - ``x`` -- a real number

        OUTPUT:

        The value of this Newton polygon at abscissa `x`

        EXAMPLES:

            sage: from sage.geometry.newton_polygon import NewtonPolygon
            sage: NP = NewtonPolygon([ (0,0), (1,1), (3,6) ]); NP
            Finite Newton polygon with 3 vertices: (0, 0), (1, 1), (3, 6)

            sage: [ NP(i) for i in range(4) ]
            [0, 1, 7/2, 6]
        """
        # complexity: O(log(n))
        from sage.functions.other import floor
        vertices = self.vertices()
        lastslope = self.last_slope()
        if len(vertices) == 0 or x < vertices[0][0]:
            return Infinity
        if x == vertices[0][0]:
            return vertices[0][1]
        if x == vertices[-1][0]:
            return vertices[-1][1]
        if x > vertices[-1][0]:
            return vertices[-1][1] + lastslope * (x - vertices[-1][0])
        a = 0; b = len(vertices)
        while b - a > 1:
            c = floor((a+b)/2)
            if vertices[c][0] < x:
                a = c
            else:
                b = c
        (xg,yg) = vertices[a]
        (xd,yd) = vertices[b]
        return ((x-xg)*yd + (xd-x)*yg) / (xd-xg)
Example #21
0
def gilt(x):
    r"""
    Returns the greatest integer smaller than ``x``.

    EXAMPLES::

        sage: from sage.coding.guruswami_sudan.utils import gilt
        sage: gilt(43)
        42

    It works with any type of numbers (not only integers)::

        sage: gilt(43.041)
        43
    """
    if x in ZZ:
        return Integer(x-1)
    else:
        return floor(x)
Example #22
0
 def _repr_(self,model):
     from sage.functions.other import floor
     l = [ ]
     maxlen = self.ncols() * [0]
     for i in range(self.nrows()):
         lp = [ ]
         for j in range(self.ncols()):
             s = self[i,j].__repr__()
             if len(s) > maxlen[j]: maxlen[j] = len(s)
             lp.append(s)
         l.append(lp)
     s = ""
     for i in range(self.nrows()):
         s += "["
         lp = l[i]
         for j in range(self.ncols()):
             length = len(lp[j]) 
             nbspace = floor((maxlen[j]-length) / 2)
             s += (nbspace + 1)*" " + lp[j] + (maxlen[j] - length - nbspace + 1)*" "
         s += "]\n"
     return s[:-1]
    def segment_index_at_parameter(self, s):
        r"""Returns the index of the complex path segment located at the given
        parameter :math:`s \in [0,1]`.

        Parameters
        ----------
        s : float
            Path parameter in the interval [0,1].

        Returns
        -------
        index : int
            The index `k` of the path segment :math:`\gamma_k`.
        """
        # the following is a fast way to divide the interval [0,1] into n
        # partitions and determine which partition s lies in. since this is
        # done often it needs to be fast
        k = floor(s * self._nsegments)
        diff = (self._nsegments - 1) - k
        dsgn = diff >> 31
        return k + (diff & dsgn)
    def segment_index_at_parameter(self, s):
        r"""Returns the index of the complex path segment located at the given
        parameter :math:`s \in [0,1]`.

        Parameters
        ----------
        s : float
            Path parameter in the interval [0,1].

        Returns
        -------
        index : int
            The index `k` of the path segment :math:`\gamma_k`.
        """
        # the following is a fast way to divide the interval [0,1] into n
        # partitions and determine which partition s lies in. since this is
        # done often it needs to be fast
        k = floor(s*self._nsegments)
        diff = (self._nsegments - 1) - k
        dsgn = diff >> 31
        return k + (diff & dsgn)
Example #25
0
    def P(self, x, y):
        """
        Returns the Kazhdan-Lusztig P polynomial. If the rank is large,
        this runs slowly at first but speeds up as you do repeated calculations
        due to the caching.

        EXAMPLES ::

            sage: R.<q>=QQ[]
            sage: W = WeylGroup("A3", prefix="s")
            sage: [s1,s2,s3]=W.simple_reflections()
            sage: KL = KazhdanLusztigPolynomial(W, q)
            sage: KL.P(s2,s2*s1*s3*s2)
            q + 1
        """
        if x == 1:
            x = self._one
        if y == 1:
            y = self._one
        if x == y:
            return 1
        if not x.bruhat_le(y):
            return 0
        if y.length() == 0:
            if x.length() == 0:
                return 1
            else:
                return 0
        p = sum(-self.R(x, t) * self.P(t, y)
                for t in self._coxeter_group.bruhat_interval(x, y) if t != x)
        tr = floor((y.length() - x.length() + 1) / 2)
        try:
            ret = p.truncate(tr)
        except:
            ret = laurent_polynomial_truncate(p, tr)
        if self._trace:
            print "    P(%s,%s)=%s" % (x, y, ret)
        return ret
Example #26
0
    def __iter__(self):
        if self.__disc is infinity:
            raise ValueError("infinity is not a true filter index")

        if self.__reduced:
            for c in range(0, self._indefinite_content_bound()):
                yield (0, 0, c)

            for a in range(1, isqrt(self.__disc // 3) + 1):
                for b in range(a + 1):
                    for c in range(a,
                                   (b**2 + (self.__disc - 1)) // (4 * a) + 1):
                        yield (a, b, c)
        else:
            ##FIXME: These are not all matrices
            for a in range(0, self._indefinite_content_bound()):
                yield (a, 0, 0)
            for c in range(1, self._indefinite_content_bound()):
                yield (0, 0, c)

            maxtrace = floor(5 * self.__disc / 15 + sqrt(self.__disc) / 2)
            for a in range(1, maxtrace + 1):
                for c in range(1, maxtrace - a + 1):
                    Bu = isqrt(4 * a * c - 1)

                    di = 4 * a * c - self.__disc
                    if di >= 0:
                        Bl = isqrt(di) + 1
                    else:
                        Bl = 0

                    for b in range(-Bu, -Bl + 1):
                        yield (a, b, c)
                    for b in range(Bl, Bu + 1):
                        yield (a, b, c)
        #! if self.__reduced

        raise StopIteration
    def __iter__(self) :
        if self.__disc is infinity :
            raise ValueError, "infinity is not a true filter index"
        
        if self.__reduced :
            for c in xrange(0, self._indefinite_content_bound()) :
                yield (0,0,c)
                
            for a in xrange(1,isqrt(self.__disc // 3) + 1) :
                for b in xrange(a+1) :
                    for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                        yield (a,b,c)
        else :
            ##FIXME: These are not all matrices
            for a in xrange(0, self._indefinite_content_bound()) :
                yield (a,0,0)
            for c in xrange(1, self._indefinite_content_bound()) :
                yield (0,0,c)
            
            maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
            for a in xrange(1, maxtrace + 1) :
                for c in xrange(1, maxtrace - a + 1) :
                    Bu = isqrt(4*a*c - 1)

                    di = 4*a*c - self.__disc
                    if di >= 0 :
                        Bl = isqrt(di) + 1 
                    else :
                        Bl = 0
                    
                    for b in xrange(-Bu, -Bl + 1) :
                        yield (a,b,c)
                    for b in xrange(Bl, Bu + 1) :
                        yield (a,b,c)
        #! if self.__reduced
        
        raise StopIteration
Example #28
0
    def P(self, x, y):
        """
        Returns the Kazhdan-Lusztig P polynomial. If the rank is large,
        this runs slowly at first but speeds up as you do repeated calculations
        due to the caching.

        EXAMPLES ::

            sage: R.<q>=QQ[]
            sage: W = WeylGroup("A3", prefix="s")
            sage: [s1,s2,s3]=W.simple_reflections()
            sage: KL = KazhdanLusztigPolynomial(W, q)
            sage: KL.P(s2,s2*s1*s3*s2)
            q + 1
        """
        if x == 1:
            x = self._one
        if y == 1:
            y = self._one
        if x == y:
            return 1
        if not x.bruhat_le(y):
            return 0
        if y.length() == 0:
            if x.length() == 0:
                return 1
            else:
                return 0
        p = sum(-self.R(x,t)*self.P(t,y) for t in self._coxeter_group.bruhat_interval(x,y) if t != x)
        tr = floor((y.length()-x.length()+1)/2)
        try:
            ret = p.truncate(tr)
        except:
            ret = laurent_polynomial_truncate(p, tr)
        if self._trace:
            print "    P(%s,%s)=%s"%(x, y, ret)
        return ret
Example #29
0
 def __init__(self, bleachermark, runs):
     from sage.parallel.decorate import parallel
     from sage.functions.other import ceil, floor
     self._benchmarks = bleachermark._benchmarks
     # profiling we run each benchmark once
     self._totaltime = reduce(lambda a,b: a+b, [r[0] for bm in self._benchmarks for r in bm.run(runs[0])[1:]])
     #divide the runs in chunks
     self._chunksize = ceil(2.0 / self._totaltime)
     self._nchunks = floor(len(runs)/self._chunksize)
     self._chunks = [runs[i*self._chunksize:(i+1)*self._chunksize] for i in range(self._nchunks)]
     if (self._nchunks)*self._chunksize < len(runs):
         self._chunks.append(runs[(self._nchunks)*self._chunksize:])
     # we define the parallel function
     @parallel
     def f(indices):
         results = []
         for frun in indices:
             for i in range(len(self._benchmarks)):
                 bm = self._benchmarks[i]
                 res = bm.run(frun)
                 results.append((i, res))
         return results
     self._getchunks = f(self._chunks)
     self._currentchunk = []
Example #30
0
def frac(x):
    r"""
    Return the fractional part of real number x.

    Not always perfect...

    EXAMPLES::

        sage: from slabbe.diophantine_approx import frac
        sage: frac(3.2)
        0.200000000000000
        sage: frac(-3.2)
        0.800000000000000
        sage: frac(pi)
        pi - 3
        sage: frac(pi).n()
        0.141592653589793

    This looks suspicious...::

        sage: frac(pi*10**15).n()
        0.000000000000000
    """
    return x - floor(x)
Example #31
0
 def _dismantle(self, r):
     """
     Return parameters for an r-part dismantlement
     of a Q-antipodal association scheme.
     """
     if r == self._.r:
         return self
     elif r == 1:
         return self.antipodalFraction()
     if self._.d == 1:
         scheme = QPolyParameters((r-1, ), (Integer(1), ))
     elif self._.d == 2:
         m = self._.m[1] * r / self._.r
         scheme = QPolyParameters((m, r-1), (Integer(1), m))
     else:
         m = floor(self._.d / 2)
         b, c = (list(t) for t in self.kreinArray())
         c[self._.d - m - 1] *= self._.r / r
         b[m] = (r-1) * c[self._.d - m - 1]
         scheme = QPolyParameters(b, c)
     r = min(len(scheme._.dismantled_schemes),
             len(self._.dismantled_schemes))
     scheme._.dismantled_schemes[:r] = self._.dismantled_schemes[:r]
     return scheme
Example #32
0
def dirichlet_convergents_dependance(v, n, verbose=False):
    r"""
    INPUT:

    - ``v`` -- list of real numbers
    - ``n`` -- integer, number of iterations
    - ``verbose`` -- bool (default: ``False``),

    OUTPUT:

    - table of linear combinaisons of dirichlet approximations in terms of
      previous dirichlet approximations

    EXAMPLES::

        sage: from slabbe.diophantine_approx import dirichlet_convergents_dependance
        sage: dirichlet_convergents_dependance([e,pi], 4)
          i   vi                      lin. rec.     remainder
        +---+-----------------------+-------------+-----------+
          0   (3, 3, 1)               []            (3, 3, 1)
          1   (19, 22, 7)             [6]           (1, 4, 1)
          2   (1843, 2130, 678)       [96, 6]       (1, 0, 0)
          3   (51892, 59973, 19090)   [28, 15, 1]   (0, 0, 0)

    The last 3 seems enough::

        sage: dirichlet_convergents_dependance([e,pi], 8)
          i   vi                         lin. rec.     remainder
        +---+--------------------------+-------------+-----------+
          0   (3, 3, 1)                  []            (3, 3, 1)
          1   (19, 22, 7)                [6]           (1, 4, 1)
          2   (1843, 2130, 678)          [96, 6]       (1, 0, 0)
          3   (51892, 59973, 19090)      [28, 15, 1]   (0, 0, 0)
          4   (113018, 130618, 41577)    [2, 5, 1]     (0, 0, 0)
          5   (114861, 132748, 42255)    [1, 0, 1]     (0, 0, 0)
          6   (166753, 192721, 61345)    [1, 0, 1]     (0, 0, 0)
          7   (446524, 516060, 164267)   [2, 0, 1]     (0, 0, 0)

    But not in this case::

        sage: dirichlet_convergents_dependance([pi,sqrt(3)], 12)
          i    vi                      lin. rec.                  remainder
        +----+-----------------------+--------------------------+-----------+
          0    (3, 2, 1)               []                         (3, 2, 1)
          1    (22, 12, 7)             [6]                        (4, 0, 1)
          2    (47, 26, 15)            [2, 1]                     (0, 0, 0)
          3    (69, 38, 22)            [1, 1]                     (0, 0, 0)
          4    (176, 97, 56)           [2, 0, 1, 4]               (4, 1, 1)
          5    (223, 123, 71)          [1, 0, 1]                  (0, 0, 0)
          6    (399, 220, 127)         [1, 1]                     (0, 0, 0)
          7    (1442, 795, 459)        [3, 1, 0, 0, 0, 1]         (0, 0, 0)
          8    (6390, 3523, 2034)      [4, 1, 1]                  (0, 0, 0)
          9    (26603, 14667, 8468)    [4, 0, 2, 1, 0, 0, 0, 1]   (0, 0, 0)
          10   (32993, 18190, 10502)   [1, 1]                     (0, 0, 0)
          11   (40825, 22508, 12995)   [1, 0, 1, 1]               (0, 0, 0)

    The v4 is not a lin. comb. of the previous four::

        sage: dirichlet_convergents_dependance([e,pi,sqrt(3)], 5)
          i   vi                                lin. rec.        remainder
        +---+---------------------------------+----------------+--------------+
          0   (3, 3, 2, 1)                      []               (3, 3, 2, 1)
          1   (19, 22, 12, 7)                   [6]              (1, 4, 0, 1)
          2   (193, 223, 123, 71)               [10, 1]          (0, 0, 1, 0)
          3   (5529, 6390, 3523, 2034)          [28, 6, 3]       (2, 5, 1, 1)
          4   (163067, 188461, 103904, 59989)   [29, 14, 1, 1]   (2, 4, 1, 1)
    """
    L = []
    it = best_simultaneous_convergents(v)
    rows = []
    for i in range(n):
        vi = vector(next(it))
        t = vi
        M = []
        for u in reversed(L):
            m = floor(min(a / b for a, b in zip(t, u)))
            M.append(m)
            t -= m * u
            if t == 0:
                if verbose:
                    c = ','.join("v{}".format(len(L) - j)
                                 for j in range(len(M)))
                    print "v{} = {} = <{}>.<{}>".format(i, vi, M, c)
                break
        else:
            if verbose:
                print "v{} = {} = <{}>.<v{}, ..., v0> + {}".format(
                    i, vi, M, i - 1, t)
        L.append(vi)
        row = [i, vi, M, t]
        rows.append(row)
    header_row = ['i', 'vi', 'lin. rec.', 'remainder']
    from sage.misc.table import table
    return table(rows=rows, header_row=header_row)
Example #33
0
def _sanitise_rootfinding_input(Q, maxd, precision):
    r"""
    Verifies, converts and sanitises legal input to the root-finding procedures,
    as well as returning relevant helper variables.

    INPUT:

    - ``Q`` -- a bivariate polynomial, represented either over `F[x,y]`, `F[x][y]` or `F[x]` list.

    - ``maxd``, an integer, the maximal degree of a root of ``Q`` that we're
      interested in, possibly ``None``.

    - ``precision``, an integer, the precision asked for modular roots of ``Q``, possibly ``None``.

    OUTPUT:

    - ``Q``, a modified version of ``Q``, where all monomials have been
      truncated to ``precision``. Represented as an `F[x]` list.

    - ``Qinp``,  the original ``Q`` passed in input, represented as an `F[x]` list.

    - ``F``, the base ring of the coefficients in ``Q``'s first variable.

    - ``Rx``, the polynomial ring `F[x]`.

    - ``x``, the generator of ``Rx``.

    - ``maxd``, the maximal degree of a root of ``Q`` that we're interested in,
      possibly inferred according ``precision``.

    EXAMPLES::

        sage: from sage.coding.guruswami_sudan.rootfinding import _sanitise_rootfinding_input
        sage: F = GF(17)
        sage: Px.<x> = F[]
        sage: Pxy.<y> = Px[]
        sage: Q = (y - (x**2 + x + 1)) * (y**2 - x + 1) * (y - (x**3 + 4*x + 16))
        sage: _sanitise_rootfinding_input(Q, None, None)
        ([16*x^6 + 13*x^4 + 2*x^3 + 4*x + 16,
          x^4 + 4*x^2 + 12*x,
          x^5 + x^4 + 5*x^3 + 3*x^2 + 2*x,
          16*x^3 + 16*x^2 + 12*x,
          1],
         [16*x^6 + 13*x^4 + 2*x^3 + 4*x + 16,
          x^4 + 4*x^2 + 12*x,
          x^5 + x^4 + 5*x^3 + 3*x^2 + 2*x,
          16*x^3 + 16*x^2 + 12*x,
          1],
         Finite Field of size 17,
         Univariate Polynomial Ring in x over Finite Field of size 17,
         x,
         3)
    """
    (Q, Rx) = _convert_Q_representation(Q)
    if Q == []:
        return ([], [], None, Rx, None, 0)  # Q == 0 so just bail
    Qinp = Q
    F = Rx.base_ring()
    x = Rx.gen()

    if not maxd:
        if precision:
            maxd = precision - 1
        else:
            #The maximal degree of a root is at most
            #(di-dl)/(l-i) d being the degree of a monomial
            maxd = 0
            l = len(Q) - 1
            dl = Q[l].degree()
            for i in range(l):
                qi = Q[i]
                if not qi.is_zero():
                    tmp = floor((qi.degree() - dl) / (l - i))
                    if tmp > maxd:
                        maxd = tmp
    if precision:
        for t in range(len(Q)):
            if Q[t].degree >= precision:
                Q[t] = Q[t].truncate(precision)
    return (Q, Qinp, F, Rx, x, maxd)
Example #34
0
    def dimension_new_cusp_forms(self, k=2, p=0):
        r"""
        Return the dimension of the space of new (or `p`-new)
        weight `k` cusp forms for this congruence subgroup.

        INPUT:

        - `k` -- an integer (default: 2), the weight. Not fully
          implemented for `k = 1`.
        - `p` -- integer (default: 0); if nonzero, compute the
          `p`-new subspace.

        OUTPUT: Integer

        ALGORITHM:

        This comes from the formula given in Theorem 1 of
        http://www.math.ubc.ca/~gerg/papers/downloads/DSCFN.pdf

        EXAMPLES::

            sage: Gamma0(11000).dimension_new_cusp_forms()
            240
            sage: Gamma0(11000).dimension_new_cusp_forms(k=1)
            0
            sage: Gamma0(22).dimension_new_cusp_forms(k=4)
            3
            sage: Gamma0(389).dimension_new_cusp_forms(k=2,p=17)
            32

        TESTS::

             sage: L = [1213, 1331, 2169, 2583, 2662, 2745, 3208,
             ....:      3232, 3465, 3608, 4040, 4302, 4338]
             sage: all(Gamma0(N).dimension_new_cusp_forms(2)==100 for N in L)
             True
        """
        from sage.arith.all import moebius
        from sage.functions.other import floor

        N = self.level()
        k = ZZ(k)

        if not (p == 0 or N % p):
            return (self.dimension_cusp_forms(k) -
                    2 * self.restrict(N // p).dimension_new_cusp_forms(k))

        if k < 2 or k % 2:
            return ZZ.zero()

        factors = list(N.factor())

        def s0(q, a):
            # function s_0^#
            if a == 1:
                return 1 - 1 / q
            elif a == 2:
                return 1 - 1 / q - 1 / q**2
            else:
                return (1 - 1 / q) * (1 - 1 / q**2)

        def vinf(q, a):
            # function v_oo^#
            if a % 2:
                return 0
            elif a == 2:
                return q - 2
            else:
                return q**(a / 2 - 2) * (q - 1)**2

        def v2(q, a):
            # function v_2^#
            if q % 4 == 1:
                if a == 2:
                    return -1
                else:
                    return 0
            elif q % 4 == 3:
                if a == 1:
                    return -2
                elif a == 2:
                    return 1
                else:
                    return 0
            elif a in (1, 2):
                return -1
            elif a == 3:
                return 1
            else:
                return 0

        def v3(q, a):
            # function v_3^#
            if q % 3 == 1:
                if a == 2:
                    return -1
                else:
                    return 0
            elif q % 3 == 2:
                if a == 1:
                    return -2
                elif a == 2:
                    return 1
                else:
                    return 0
            elif a in (1, 2):
                return -1
            elif a == 3:
                return 1
            else:
                return 0

        res = (k - 1) / 12 * N * prod(s0(q, a) for q, a in factors)
        res -= prod(vinf(q, a) for q, a in factors) / ZZ(2)
        res += (
            (1 - k) / 4 + floor(k / 4)) * prod(v2(q, a) for q, a in factors)
        res += (
            (1 - k) / 3 + floor(k / 3)) * prod(v3(q, a) for q, a in factors)
        if k == 2:
            res += moebius(N)
        return res
Example #35
0
    def _suitable_parameters_given_tau(tau, C=None, n_k=None):
        r"""
        Return quite good multiplicity and list size parameters for the code
        parameters and the decoding radius.

        These parameters are not guaranteed to be the best ones possible
        for the provided ``tau``, but arise from easily-evaluated closed
        expressions and are very good approximations of the best ones.

        See [Nie2013]_ pages 53-54, proposition 3.11 for details.

        INPUT:

        - ``tau`` -- an integer, number of errors one wants the Guruswami-Sudan
          algorithm to correct
        - ``C`` -- (default: ``None``) a :class:`GeneralizedReedSolomonCode`
        - ``n_k`` -- (default: ``None``) a pair of integers, respectively the
          length and the dimension of the :class:`GeneralizedReedSolomonCode`

        OUTPUT:

        - ``(s, l)`` -- a pair of integers, where:
            - ``s`` is the multiplicity parameter, and
            - ``l`` is the list size parameter.

        .. NOTE::

            One has to provide either ``C`` or ``(n, k)``. If neither or both
            are given, an exception will be raised.

        EXAMPLES:


        The following is an example where the parameters are optimal::

            sage: tau = 98
            sage: n, k = 250, 70
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, n_k = (n, k))
            (2, 3)
            sage: codes.decoders.GRSGuruswamiSudanDecoder.parameters_given_tau(tau, n_k = (n, k))
            (2, 3)

        This is an example where they are not::

            sage: tau = 97
            sage: n, k = 250, 70
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, n_k = (n, k))
            (2, 3)
            sage: codes.decoders.GRSGuruswamiSudanDecoder.parameters_given_tau(tau, n_k = (n, k))
            (1, 2)

        We can provide a GRS code instead of `n` and `k` directly::

            sage: C = codes.GeneralizedReedSolomonCode(GF(251).list()[:250], 70)
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, C = C)
            (2, 3)

        Another one with a bigger ``tau``::

            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(118, C = C)
            (47, 89)
        """
        n, k = n_k_params(C, n_k)
        w = k - 1
        atau = n - tau
        smin = tau * w / (atau**2 - n * w)
        s = floor(1 + smin)
        D = (s - smin) * (atau**2 - n * w) * s + (w**2) / 4
        l = floor(atau / w * s + 0.5 - sqrt(D) / w)
        return (s, l)
 def _contained_discriminant_bound(self) :
     return floor( (self.index() / ( Integer(1) + self.__level + self.__level**2) )**2 )
Example #37
0
    def guess(self, sequence, algorithm='sage'):
        """
        Return the minimal CFiniteSequence that generates the sequence.

        Assume the first value has index 0.

        INPUT:

        - ``sequence`` -- list of integers
        - ``algorithm`` -- string
            - 'sage' - the default is to use Sage's matrix kernel function
            - 'pari' - use Pari's implementation of LLL
            - 'bm' - use Sage's Berlekamp-Massey algorithm

        OUTPUT:

        - a CFiniteSequence, or 0 if none could be found

        With the default kernel method, trailing zeroes are chopped
        off before a guessing attempt. This may reduce the data
        below the accepted length of six values.

        EXAMPLES::

            sage: C.<x> = CFiniteSequences(QQ)
            sage: C.guess([1,2,4,8,16,32])
            C-finite sequence, generated by -1/2/(x - 1/2)
            sage: r = C.guess([1,2,3,4,5])
            Traceback (most recent call last):
            ...
            ValueError: Sequence too short for guessing.

        With Berlekamp-Massey, if an odd number of values is given, the last one is dropped.
        So with an odd number of values the result may not generate the last value::

            sage: r = C.guess([1,2,4,8,9], algorithm='bm'); r
            C-finite sequence, generated by -1/2/(x - 1/2)
            sage: r[0:5]
            [1, 2, 4, 8, 16]
        """
        S = self.polynomial_ring()
        if algorithm == 'bm':
            from sage.matrix.berlekamp_massey import berlekamp_massey
            if len(sequence) < 2:
                raise ValueError('Sequence too short for guessing.')
            R = PowerSeriesRing(QQ, 'x')
            if len(sequence) % 2 == 1:
                sequence = sequence[:-1]
            l = len(sequence) - 1
            denominator = S(berlekamp_massey(sequence).list()[::-1])
            numerator = R(S(sequence) * denominator, prec=l).truncate()

            return CFiniteSequence(numerator / denominator)
        elif algorithm == 'pari':
            global _gp
            if len(sequence) < 6:
                raise ValueError('Sequence too short for guessing.')
            if _gp is None:
                _gp = Gp()
                _gp("ggf(v)=local(l,m,p,q,B);l=length(v);B=floor(l/2);\
                if(B<3,return(0));m=matrix(B,B,x,y,v[x-y+B+1]);\
                q=qflll(m,4)[1];if(length(q)==0,return(0));\
                p=sum(k=1,B,x^(k-1)*q[k,1]);\
                q=Pol(Pol(vector(l,n,v[l-n+1]))*p+O(x^(B+1)));\
                if(polcoeff(p,0)<0,q=-q;p=-p);q=q/p;p=Ser(q+O(x^(l+1)));\
                for(m=1,l,if(polcoeff(p,m-1)!=v[m],return(0)));q")
            _gp.set('gf', sequence)
            _gp("gf=ggf(gf)")
            num = S(sage_eval(_gp.eval("Vec(numerator(gf))"))[::-1])
            den = S(sage_eval(_gp.eval("Vec(denominator(gf))"))[::-1])
            if num == 0:
                return 0
            else:
                return CFiniteSequence(num / den)
        else:
            from sage.matrix.constructor import matrix
            from sage.functions.other import floor, ceil
            from numpy import trim_zeros
            l = len(sequence)
            while l > 0 and sequence[l - 1] == 0:
                l -= 1
            sequence = sequence[:l]
            if l == 0:
                return 0
            if l < 6:
                raise ValueError('Sequence too short for guessing.')

            hl = ceil(ZZ(l) / 2)
            A = matrix([sequence[k:k + hl] for k in range(hl)])
            K = A.kernel()
            if K.dimension() == 0:
                return 0
            R = PolynomialRing(QQ, 'x')
            den = R(trim_zeros(K.basis()[-1].list()[::-1]))
            if den == 1:
                return 0
            offset = next((i for i, x in enumerate(sequence) if x != 0), None)
            S = PowerSeriesRing(QQ, 'x', default_prec=l - offset)
            num = S(R(sequence) * den).add_bigoh(floor(ZZ(l) / 2 +
                                                       1)).truncate()
            if num == 0 or sequence != S(num / den).list():
                return 0
            else:
                return CFiniteSequence(num / den)
Example #38
0
 def my_log(number):
     return floor(log(abs(number), 10.))
Example #39
0
    def amortized_padic_H_values_interval(self,
                                          ans,
                                          t,
                                          start,
                                          end,
                                          pclass,
                                          fixbreak,
                                          testp=None,
                                          use_c=False):
        r"""
        Return a dictionary
            p -> M[p]

        (0, P_m0)*A[p] = A[p][0,0] (S, P_m1)
        where
        P_m = t^m \prod_i (alpha_i)_m ^* / (beta_i)_m ^* mod p,
        m0 = floor(start(p-1)) + 1,
        m1 = floor(end(p-1)),
        S = \sum_{m = m0} ^{m1 - 1} P_m


        EXAMPLES::

            sage: for cyca, cycb, start, end, p, t in [
            ....:     ([6], [1, 1], 0, 1/6, 97, 1),
            ....:     ([4, 2, 2], [3, 1, 1], 1/3, 1/2, 97, 1),
            ....:     ([22], [1, 1, 20], 3/20, 5/22, 1087, 1),
            ....:     ([22], [1, 1, 20], 3/20, 5/22, 1087, 1337/507734),
            ....:     ([22], [1, 1, 20], 3/20, 5/22, 1019, 1337/507734)]:
            ....:     H = AmortizingHypergeometricData(p+40, cyclotomic=(cyca, cycb))
            ....:     pclass = p % start.denominator()
            ....:     shift, offset = H._starts_to_rationals[start][pclass]
            ....:     amortized = H.amortized_padic_H_values_interval(t=t, start=start, end=end, pclass=pclass)
            ....:     t = GF(p)(t)
            ....:     naive_sum = 0
            ....:     for k in range(floor(start*(p-1))+1, floor(end * (p-1))):
            ....:         naive_sum += t**k * H.pochhammer_quotient(p, k)
            ....:     naive_res = vector(GF(p), (naive_sum, t**floor(end * (p-1)) * H.pochhammer_quotient(p, floor(end * (p-1) ))))
            ....:     M = matrix(GF(p), amortized[p])
            ....:     res = (vector(GF(p), [0,t**(floor(start*(p-1))+1) * H.pochhammer_quotient(p, floor(start*(p-1))+1 )])*M/M[0,0])
            ....:     if naive_res != res:
            ....:         print(cyca, cycb, start, end, p, t, naive_res, res)

        """
        d = start.denominator()
        shift, offset = self._starts_to_rationals[start][pclass]

        def mbound(p):
            # FIXME
            # in practice we are getting
            # prod up mbound - 1
            # there is something wrong with the Tree
            # once we fix that, we should fix the bound here
            return max((end * (p - 1)).floor() - (start * (p - 1)).floor(), 1)

        f, g, mats = self._matrices(t=t,
                                    start=start,
                                    shift=shift,
                                    offset=offset)

        if use_c:
            k = f.parent().gen()
            y = self.interval_mults[start]
            M = matrix([[g, 0], [y * g, f]])
            indices = self._prime_range(t)[d][pclass]
            remainder_forest(
                M,
                lambda p: p,  #lambda p: mbound_c(p,start,end),
                mbound_dict_c(indices, start, end),
                kbase=1,
                indices=indices,
                V=fixbreak,
                ans=ans)
        else:
            forest = AccRemForest(
                self.N,
                cut_functions={None: mbound},
                bottom_generator=mats,
                prec=1,
                primes=self._prime_range(t)[d][pclass],
            )
            bottom = forest.tree_bottom()
            # Now we have a formula for
            # (0, P_m0)*A[p] =  A[p][0,0] (\sum_{m = m0} ^{m1 - 1} P_m, P_m1)
            # with
            # m0 = floor(start * (p-1)) + 1
            # m1 = floor(end * (p-1))
            if testp in bottom:
                print(
                    "amortized_padic_H_values_interval(t=%s, start=%s, end=%s, pclass=%s)"
                    % (t, start, end, pclass))
                p = testp
                R = GF(p)
                if bottom[testp] != 1:
                    M = bottom[testp].change_ring(R)
                    # FIXME why the -1?  Probably because partial_factorial doesn't include right endpoint
                    assert M == prod(
                        elt.change_ring(GF(R)) for elt in mats(
                            floor(end * (p - 1)) - floor(start * (p - 1)) - 1))

                    t = R(t)
                    naive_sum = 0
                    pmult = self.interval_mults[start]
                    for k in range(
                            floor(start * (p - 1)) + 1, floor(end * (p - 1))):
                        naive_sum += t**k * self.pochhammer_quotient(p, k)
                    naive_sum *= pmult
                    naive_res = vector(
                        R, (naive_sum, t**floor(end * (p - 1)) *
                            self.pochhammer_quotient(p, floor(end * (p - 1)))))

                    res = vector(R, [
                        0, t**(floor(start * (p - 1)) + 1) *
                        self.pochhammer_quotient(p,
                                                 floor(start * (p - 1)) + 1)
                    ]) * M / M[0, 0]
                    assert naive_res == res, "%s != %s, M = %s" % (naive_res,
                                                                   res, M)
            # set ans
            for k, M in bottom.items():
                ans[k] = ans[k] * fixbreak * M
Example #40
0
    def _init_frob(self, desired_prec=None):
        """
        Initialise everything for Frobenius polynomial computation.

        TESTS::

            sage: p = 4999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
            sage: C._init_frob()
            sage: C._init_frobQ
            True
            sage: C._plarge
            True
            sage: C._sqrtp
            True
        """
        def _N0_RH():
            return ceil(
                log(2 * binomial(2 * self._genus, self._genus), self._p) +
                self._genus * self._n / ZZ(2))

        def _find_N0():
            if self._nodenominators:
                return _N0_nodenominators(self._p, self._genus, self._n)
            else:
                return _N0_RH() + self._extraprec

        def _find_N_43():
            """
            Find the precision used for thm 4.3 in Goncalves
            for p >> 0, N = N0 + 2
            """
            p = self._p
            r = self._r
            d = self._d
            delta = self._delta
            N0 = self._N0
            left_side = N0 + floor(log((d * p * (r - 1) + r) / delta) / log(p))

            def right_side_log(n):
                return floor(log(p * (r * n - 1) - r) / log(p))

            n = left_side
            while n <= left_side + right_side_log(n):
                n += 1
            return n

        if not self._init_frobQ or self._N0 != desired_prec:
            if self._r < 2 or self._d < 2:
                raise NotImplementedError(
                    "Only implemented for r, f.degree() >= 2")

            self._init_frobQ = True

            self._Fq = self._f.base_ring()
            self._p = self._Fq.characteristic()
            self._q = self._Fq.cardinality()
            self._n = self._Fq.degree()
            self._epsilon = 0 if self._delta == 1 else 1

            # our basis choice doesn't always give an integral matrix
            if self._epsilon == 0:
                self._extraprec = floor(
                    log(self._r, self._p) +
                    log((2 * self._genus +
                         (self._delta - 2)) / self._delta, self._p))
            else:
                self._extraprec = floor(log(self._r * 2 - 1, self._p))

            self._nodenominators = self._extraprec == 0

            if desired_prec is None:
                self._N0 = _find_N0()
            else:
                self._N0 = desired_prec

            self._plarge = self._p > self._d * self._r * (self._N0 +
                                                          self._epsilon)

            # working prec
            if self._plarge:
                self._N = self._N0 + 1
            else:
                self._N = _find_N_43()

            # we will use the sqrt(p) version?
            self._sqrtp = self._plarge and self._p == self._q
            self._extraworkingprec = self._extraprec
            if not self._plarge:
                # we might have some denominators showing up during horizontal
                # and vertical reductions
                self._extraworkingprec += 2 * ceil(
                    log(self._d * self._r *
                        (self._N0 + self._epsilon), self._p))

            # Rings
            if self._plarge and self._nodenominators:
                if self._n == 1:
                    # IntegerModRing is significantly faster than Zq
                    self._Zq = IntegerModRing(self._p**self._N)
                    if self._sqrtp:
                        self._Zq0 = IntegerModRing(self._p**(self._N - 1))
                    self._Qq = Qq(self._p, prec=self._N, type="capped-rel")
                    self._w = 1
                else:
                    self._Zq = Zq(
                        self._q,
                        names="w",
                        modulus=self._Fq.polynomial(),
                        prec=self._N,
                        type="capped-abs",
                    )
                    self._w = self._Zq.gen()
                    self._Qq = self._Zq.fraction_field()
            else:
                self._Zq = Qq(
                    self._q,
                    names="w",
                    modulus=self._Fq.polynomial(),
                    prec=self._N + self._extraworkingprec,
                )
                self._w = self._Zq.gen()
                self._Qq = self._Zq
            self._Zp = Zp(self._p, prec=self._N + self._extraworkingprec)

            self._Zqx = PolynomialRing(self._Zq, "x")

            # Want to take a lift of f from Fq to Zq
            if self._n == 1:
                # When n = 1, can lift from Fp[x] to Z[x] and then to Zp[x]
                self._flift = self._Zqx([elt.lift() for elt in self._f.list()])
                self._frobf = self._Zqx(self._flift.list())
            else:  # When n > 1, need to be more careful with the lift
                self._flift = self._Zqx([
                    elt.polynomial().change_ring(ZZ)(self._Zq.gen())
                    for elt in self._f.list()
                ])

                self._frobf = self._Zqx(
                    [elt.frobenius() for elt in self._flift.list()])

            self._dflift = self._flift.derivative()

            # Set up local cache for Frob(f)^s

            # This variable will store the powers of frob(f)
            frobpow = [None] * (self._N0 + 2)
            frobpow[0] = self._Zqx(1)
            for k in range(self._N0 + 1):
                frobpow[k + 1] = self._frobf * frobpow[k]
            # We don't make it a polynomials as we need to keep track that the
            # ith coefficient represents  (i*p)-th
            self._frobpow_list = [elt.list() for elt in frobpow]

            if self._sqrtp:
                # precision of self._Zq0
                N = self._N - 1
                vandermonde = matrix(self._Zq0, N, N)
                for i in range(N):
                    vandermonde[i, 0] = 1
                    for j in range(1, N):
                        vandermonde[i, j] = vandermonde[i, j - 1] * (i + 1)
                self._vandermonde = vandermonde.inverse()

                self._horizontal_fat_s = {}
                self._vertical_fat_s = {}
Example #41
0
 def right_side_log(n):
     return floor(log(p * (r * n - 1) - r) / log(p))
 def iter_positive_forms(self) :
     if self.__disc is infinity :
         raise ValueError, "infinity is not a true filter index"
     
     if self.__reduced :
         for (l, (u,x)) in enumerate(self.__p1list) :
             if u == 0 :
                 for a in xrange(self.__level, isqrt(self.__disc // 4) + 1, self.__level) :
                     for b in xrange(a+1) :
                         for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                             yield ((a,b,c), l)
             else :
                 for a in xrange(1, isqrt(self.__disc // 3) + 1) :
                     for b in xrange(a+1) :
                         ## We need x**2 * a + x * b + c % N == 0
                         h = (-((x**2 + 1) * a + x * b)) % self.__level
                         for c in xrange( a + h,
                                          (b**2 + (self.__disc - 1))//(4*a) + 1, self.__level ) :
                             yield ((a,b,c), l)
     #! if self.__reduced
     else :
         maxtrace = floor(self.__disc / Integer(3) + sqrt(self.__disc / Integer(3)))
         for (l, (u,x)) in enumerate(self.__p1list) :
             if u == 0 :
                 for a in xrange(self.__level, maxtrace + 1, self.__level) :
                     for c in xrange(1, maxtrace - a + 1) :
                         Bu = isqrt(4*a*c - 1)
     
                         di = 4*a*c - self.__disc
                         if di >= 0 :
                             Bl = isqrt(di) + 1 
                         else :
                             Bl = 0
                         
                         for b in xrange(-Bu, -Bl + 1) :
                             yield ((a,b,c), l)
                         for b in xrange(Bl, Bu + 1) :
                             yield ((a,b,c), l)
             else :
                 for a in xrange(1, maxtrace + 1) :
                     for c in xrange(1, maxtrace - a + 1) :
                         Bu = isqrt(4*a*c - 1)
     
                         di = 4*a*c - self.__disc
                         if di >= 0 :
                             Bl = isqrt(di) + 1 
                         else :
                             Bl = 0
                         
                         h = (-x * a - int(Mod(x, self.__level)**-1) * c - Bu) % self.__level \
                             if x != 0 else \
                             (-Bu) % self.__level
                         for b in xrange(-Bu + self.__level - h, -Bl + 1, self.__level) :
                             yield ((a,b,c), l)
                         h = (-x * a - int(Mod(x, self.__level)**-1) * c + Bl) % self.__level \
                             if x !=0 else \
                             Bl % self.__level
                         for b in xrange(Bl + self.__level - h, Bu + 1, self.__level) :
                             yield ((a,b,c), l)
     #! else self.__reduced
     
     raise StopIteration
Example #43
0
 def _borcherds_product_polyhedron(self, pole_order, prec, verbose=False):
     r"""
     Construct a polyhedron representing a cone of Heegner divisors. For internal use in the methods borcherds_input_basis() and borcherds_input_Qbasis().
     INPUT:
     - ``pole_order`` -- pole order
     - ``prec`` -- precision
     OUTPUT: a tuple consisting of an integral matrix M, a Polyhedron p, and a WeilRepModularFormsBasis X
     """
     K = self.weilrep().base_field()
     O_K = K.maximal_order()
     S = self.gram_matrix()
     wt = self.input_wt()
     w = self.weilrep()
     rds = w.rds()
     norm_dict = w.norm_dict()
     X = w.nearly_holomorphic_modular_forms_basis(wt,
                                                  pole_order,
                                                  prec,
                                                  verbose=verbose)
     N = len([g for g in rds if not norm_dict[tuple(g)]])
     v_list = w.coefficient_vector_exponents(0,
                                             1,
                                             starting_from=-pole_order,
                                             include_vectors=True)
     exp_list = [v[1] for v in v_list]
     d = w._ds_to_hds()
     v_list = [vector(d[tuple(v[0])]) for v in v_list]
     d = K.discriminant()
     positive = []
     zero = vector([0] * (len(exp_list) + 1))
     M = Matrix([
         x.coefficient_vector(starting_from=-pole_order, ending_with=0)[:-N]
         for x in X
     ])
     vs = M.transpose().kernel().basis()
     prec = floor(min(exp_list) / max(filter(bool, exp_list)))
     norm_list = w._norm_form().short_vector_list_up_to_length(prec + 1)
     units = w._units()
     _w = w._w()
     norm_list = [[a + b * _w for a, b in x] for x in norm_list]
     excluded_list = set([])
     if d >= -4:
         if d == -4:
             f = w.multiplication_by_i()
             f2 = None
         else:
             f = w.multiplication_by_zeta()
             f2 = f * f
     ys = []
     mult = len(units) // 2
     for i, n in enumerate(exp_list):
         if i not in excluded_list:
             ieq = copy(zero)
             ieq[i + 1] = 1
             v1 = v_list[i]
             if d >= -4:
                 v2 = f(v1)
                 j = next(j for j, x in enumerate(v_list)
                          if exp_list[i] == exp_list[j] and (all(
                              t in O_K
                              for t in x - v2) or all(t in O_K
                                                      for t in x + v2)))
                 ieq[j + 1] += 1
                 if i != j:
                     excluded_list.add(j)
                     y = copy(zero)
                     y[i + 1] = 1
                     y[j + 1] = -1
                     ys.append(y)
                 if f2 is not None:
                     v2 = f2(v1)
                     j = next(j for j, x in enumerate(v_list)
                              if exp_list[i] == exp_list[j] and (all(
                                  t in O_K
                                  for t in x - v2) or all(t in O_K
                                                          for t in x + v2)))
                     ieq[j + 1] += 1
                     if i != j:
                         excluded_list.add(j)
                         y = copy(zero)
                         y[i + 1] = 1
                         y[j + 1] = -1
                         ys.append(y)
             for j, m in enumerate(exp_list[:i]):
                 if j not in excluded_list:
                     N = m / n
                     if N in ZZ and N > 1:
                         v2 = v_list[j]
                         ieq[j + 1] = mult * any(
                             all(t in O_K for t in x * v1 + u * v2)
                             for x in norm_list[N] for u in units)
             positive.append(ieq)  # * denominator(ieq)
     p = Polyhedron(ieqs=positive,
                    eqns=[vector([0] + list(v)) for v in vs] + ys)
     return M, p, X
Example #44
0
    def guess(self, sequence, algorithm="sage"):
        """
        Return the minimal CFiniteSequence that generates the sequence.

        Assume the first value has index 0.

        INPUT:

        - ``sequence`` -- list of integers
        - ``algorithm`` -- string
            - 'sage' - the default is to use Sage's matrix kernel function
            - 'pari' - use Pari's implementation of LLL
            - 'bm' - use Sage's Berlekamp-Massey algorithm

        OUTPUT:

        - a CFiniteSequence, or 0 if none could be found

        With the default kernel method, trailing zeroes are chopped
        off before a guessing attempt. This may reduce the data
        below the accepted length of six values.

        EXAMPLES::

            sage: C.<x> = CFiniteSequences(QQ)
            sage: C.guess([1,2,4,8,16,32])
            C-finite sequence, generated by 1/(-2*x + 1)
            sage: r = C.guess([1,2,3,4,5])
            Traceback (most recent call last):
            ...
            ValueError: Sequence too short for guessing.

        With Berlekamp-Massey, if an odd number of values is given, the last one is dropped.
        So with an odd number of values the result may not generate the last value::

            sage: r = C.guess([1,2,4,8,9], algorithm='bm'); r
            C-finite sequence, generated by 1/(-2*x + 1)
            sage: r[0:5]
            [1, 2, 4, 8, 16]
        """
        S = self.polynomial_ring()
        if algorithm == "bm":
            from sage.matrix.berlekamp_massey import berlekamp_massey

            if len(sequence) < 2:
                raise ValueError("Sequence too short for guessing.")
            R = PowerSeriesRing(QQ, "x")
            if len(sequence) % 2 == 1:
                sequence = sequence[:-1]
            l = len(sequence) - 1
            denominator = S(berlekamp_massey(sequence).list()[::-1])
            numerator = R(S(sequence) * denominator, prec=l).truncate()

            return CFiniteSequence(numerator / denominator)
        elif algorithm == "pari":
            global _gp
            if len(sequence) < 6:
                raise ValueError("Sequence too short for guessing.")
            if _gp is None:
                _gp = Gp()
                _gp(
                    "ggf(v)=local(l,m,p,q,B);l=length(v);B=floor(l/2);\
                if(B<3,return(0));m=matrix(B,B,x,y,v[x-y+B+1]);\
                q=qflll(m,4)[1];if(length(q)==0,return(0));\
                p=sum(k=1,B,x^(k-1)*q[k,1]);\
                q=Pol(Pol(vector(l,n,v[l-n+1]))*p+O(x^(B+1)));\
                if(polcoeff(p,0)<0,q=-q;p=-p);q=q/p;p=Ser(q+O(x^(l+1)));\
                for(m=1,l,if(polcoeff(p,m-1)!=v[m],return(0)));q"
                )
            _gp.set("gf", sequence)
            _gp("gf=ggf(gf)")
            num = S(sage_eval(_gp.eval("Vec(numerator(gf))"))[::-1])
            den = S(sage_eval(_gp.eval("Vec(denominator(gf))"))[::-1])
            if num == 0:
                return 0
            else:
                return CFiniteSequence(num / den)
        else:
            from sage.matrix.constructor import matrix
            from sage.functions.other import floor, ceil
            from numpy import trim_zeros

            l = len(sequence)
            while l > 0 and sequence[l - 1] == 0:
                l -= 1
            sequence = sequence[:l]
            if l == 0:
                return 0
            if l < 6:
                raise ValueError("Sequence too short for guessing.")

            hl = ceil(ZZ(l) / 2)
            A = matrix([sequence[k : k + hl] for k in range(hl)])
            K = A.kernel()
            if K.dimension() == 0:
                return 0
            R = PolynomialRing(QQ, "x")
            den = R(trim_zeros(K.basis()[-1].list()[::-1]))
            if den == 1:
                return 0
            offset = next((i for i, x in enumerate(sequence) if x != 0), None)
            S = PowerSeriesRing(QQ, "x", default_prec=l - offset)
            num = S(R(sequence) * den).add_bigoh(floor(ZZ(l) / 2 + 1)).truncate()
            if num == 0 or sequence != S(num / den).list():
                return 0
            else:
                return CFiniteSequence(num / den)
Example #45
0
    def __init__(self, cyclotomic=None, alpha_beta=None, gamma_list=None):
        r"""
        Creation of hypergeometric motives.

        INPUT:

        three possibilities are offered, each describing a quotient
        of products of cyclotomic polynomials.

        - ``cyclotomic`` -- a pair of lists of nonnegative integers,
          each integer `k` represents a cyclotomic polynomial `\Phi_k`

        - ``alpha_beta`` -- a pair of lists of rationals,
          each rational represents a root of unity

        - ``gamma_list`` -- a pair of lists of nonnegative integers,
          each integer `n` represents a polynomial `x^n - 1`

        In the last case, it is also allowed to send just one list of signed
        integers where signs indicate to which part the integer belongs to.

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: Hyp(cyclotomic=([2],[1]))
            Hypergeometric data for [1/2] and [0]

            sage: Hyp(alpha_beta=([1/2],[0]))
            Hypergeometric data for [1/2] and [0]
            sage: Hyp(alpha_beta=([1/5,2/5,3/5,4/5],[0,0,0,0]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]

            sage: Hyp(gamma_list=([5],[1,1,1,1,1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
            sage: Hyp(gamma_list=([5,-1,-1,-1,-1,-1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
        """
        if gamma_list is not None:
            if isinstance(gamma_list[0], (list, tuple)):
                pos, neg = gamma_list
                gamma_list = pos + [-u for u in neg]
            cyclotomic = gamma_list_to_cyclotomic(gamma_list)
        if cyclotomic is not None:
            cyclo_up, cyclo_down = cyclotomic
            if any(x in cyclo_up for x in cyclo_down):
                raise ValueError('overlapping parameters not allowed')
            deg = sum(euler_phi(x) for x in cyclo_down)
            up_deg = sum(euler_phi(x) for x in cyclo_up)
            if up_deg != deg:
                msg = 'not the same degree: {} != {}'.format(up_deg, deg)
                raise ValueError(msg)
            cyclo_up.sort()
            cyclo_down.sort()
            alpha = cyclotomic_to_alpha(cyclo_up)
            beta = cyclotomic_to_alpha(cyclo_down)
        elif alpha_beta is not None:
            alpha, beta = alpha_beta
            if len(alpha) != len(beta):
                raise ValueError('alpha and beta not of the same length')
            alpha = sorted(u - floor(u) for u in alpha)
            beta = sorted(u - floor(u) for u in beta)
            cyclo_up = alpha_to_cyclotomic(alpha)
            cyclo_down = alpha_to_cyclotomic(beta)
            deg = sum(euler_phi(x) for x in cyclo_down)

        self._cyclo_up = tuple(cyclo_up)
        self._cyclo_down = tuple(cyclo_down)
        self._alpha = tuple(alpha)
        self._beta = tuple(beta)
        self._deg = deg
        self._gamma_array = cyclotomic_to_gamma(cyclo_up, cyclo_down)
        self._trace_coeffs = {}
        up = QQ.prod(capital_M(d) for d in cyclo_up)
        down = QQ.prod(capital_M(d) for d in cyclo_down)
        self._M_value = up / down
        if 0 in alpha:
            self._swap = HypergeometricData(alpha_beta=(beta, alpha))
        if self.weight() % 2:
            self._sign_param = 1
        else:
            if (deg % 2) != (0 in alpha):
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_down)
            else:
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_up)
Example #46
0
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()
 def floor(self):
     result = floor(self.val())
     result <= self < result + 1
     return result
Example #48
0
def e_phipsi(phi,
             psi,
             k,
             t=1,
             prec=5,
             mat=Matrix([[1, 0], [0, 1]]),
             base_ring=None):
    r"""
    Computes the Eisenstein series attached to the characters psi, phi as
    defined on p129 of Diamond--Shurman hit by mat \in \SL_2(\Z)
    INPUT:
     - psi, a primitive Dirichlet character
     - phi, a primitive Dirichlet character
     - k, int -- the weight
     - t, int -- the shift
     - prec, the desired absolute precision, can be fractional. The expansion will be up to O(q_w^(floor(w*prec))), where w is the width of the cusp.
     - mat, a matrix - typically taking $i\infty$ to some other cusp
     - base_ring, a ring - the ring in which the modular forms are defined
    OUTPUT:
     - an instance of QExpansion
    """
    chi2 = phi
    chi1 = psi
    try:
        assert (QQ(chi1(-1)) * QQ(chi2(-1)) == (-1)**k)
    except AssertionError:
        print("Parity of characters must match parity of weight")
        return None
    N1 = chi1.level()
    N2 = chi2.level()
    N = t * N1 * N2
    mat2, Tn = find_correct_matrix(mat, N)
    #By construction gamma = mat2 * Tn * mat**(-1) is in Gamma0(N) so if E is our Eisenstein series we can evaluate E|mat = chi(gamma) * E|mat2*Tn.
    #Since E|mat2 has a Fourier expansion in qN, the matrix Tn acts as a a twist. The value c_gamma = chi(gamma) is calculated below.
    #The point of swapping mat with mat2 is that mat2 satisfies C|N, C>0, (A,N)=1 and N|B and our formulas for the coefficients require this condition.
    A, B, C, D = mat2.list()
    gamma = mat2 * Tn * mat**(-1)
    if base_ring == None:
        Nbig = lcm(N, euler_phi(N1 * N2))
        base_ring = CyclotomicField(Nbig, 'zeta' + str(Nbig))
        zetaNbig = base_ring.gen()
        zetaN = zetaNbig**(Nbig / N)
    else:
        zetaN = base_ring.zeta(N)
    g = gcd(t, C)
    g1 = gcd(N1 * g, C)
    g2 = gcd(N2 * g, C)
    #Resulting Eisenstein series will have Fourier expansion in q_N**(g1g2)=q_(N/gcd(N,g1g2))**(g1g2/gcd(N,g1g2))
    Q = PowerSeriesRing(base_ring, 'q' + str(N / gcd(N, g1 * g2)))
    qN = Q.gen()
    zeta_Cg = zetaN**(N / (C / g))
    zeta_tmp = zeta_Cg**(inverse_mod(-A * ZZ(t / g), C / g))
    #Calculating a few values that will be used repeatedly
    chi1bar_vals = [base_ring(chi1.bar()(i)) for i in range(N1)]
    cp_list1 = [i for i in range(N1) if gcd(i, N1) == 1]
    chi2bar_vals = [base_ring(chi2.bar()(i)) for i in range(N2)]
    cp_list2 = [i for i in range(N2) if gcd(i, N2) == 1]

    #Computation of the Fourier coefficients
    ser = O(qN**floor(prec * N / gcd(N, g1 * g2)))
    for n in range(1, ceil(prec * N / QQ(g1 * g2)) + 1):
        f = 0
        for m in divisors(n) + list(map(lambda x: -x, divisors(n))):
            a = 0
            for r1 in cp_list1:
                b = 0
                if ((C / g1) * r1 - QQ(n) / QQ(m)) % ((N1 * g) / g1) == 0:
                    for r2 in cp_list2:
                        if ((C / g2) * r2 - m) % ((N2 * g) / g2) == 0:
                            b += chi2bar_vals[r2] * zeta_tmp**(
                                (n / m - (C / g1) * r1) / ((N1 * g) / g1) *
                                (m - (C / g2) * r2) / ((N2 * g) / g2))
                    a += chi1bar_vals[r1] * b
            a *= sign(m) * m**(k - 1)
            f += a
        f *= zetaN**(inverse_mod(A, N) * (g1 * g2) / C * n)
        #The additional factor zetaN**(n*Tn[0][1]) comes from the twist by Tn
        ser += zetaN**(n * g1 * g2 * Tn[0][1]) * f * qN**(n * (
            (g1 * g2) / gcd(N, g1 * g2)))

    #zk(chi1, chi2, c)
    gauss1 = base_ring(gauss_sum_corr(chi1.bar()))
    gauss2 = base_ring(gauss_sum_corr(chi2.bar()))
    zk = 2 * (N2 * t / QQ(g2))**(k - 1) * (t / g) * gauss1 * gauss2
    #The following is a temporary fix for a bug in sage
    if base_ring == CC:
        G = DirichletGroup(N1 * N2, CC)
        G[0]  #Otherwise chi1.bar().extend(N1*N2).base_extend(CC) or chi2.bar().extend(N1*N2).base_extend(CC) will produce an error
    #Constant term
    #c_gamma comes from replacing mat with mat2.
    c_gamma = chi1bar_vals[gamma[1][1] % N1] * chi2bar_vals[gamma[1][1] % N2]
    if N1.divides(C) and ZZ(C / N1).divides(t) and gcd(t / (C / N1), N1) == 1:
        ser += (-1)**(k - 1) * gauss2 / QQ(
            N2 * (g2 / g)**(k - 1)) * chi1bar_vals[(-A * t / g) % N1] * Sk(
                chi1.bar().extend(N1 * N2).base_extend(base_ring) *
                chi2.extend(N1 * N2).base_extend(base_ring), k)
    elif k == 1 and N2.divides(C) and ZZ(C / N2).divides(t) and gcd(
            t / (C / N2), N2) == 1:
        ser += gauss1 / QQ(N1) * chi2bar_vals[(-A * t / g) % N2] * Sk(
            chi1.extend(N1 * N2).base_extend(base_ring) *
            chi2.bar().extend(N1 * N2).base_extend(base_ring), k)
    return QExpansion(
        N, k,
        2 / zk * c_gamma * ser + O(qN**floor(prec * N / gcd(N, g1 * g2))),
        N / gcd(N, g1 * g2))
Example #49
0
    def _suitable_parameters_given_tau(tau, C = None, n_k = None):
        r"""
        Return quite good multiplicity and list size parameters for the code
        parameters and the decoding radius.

        These parameters are not guaranteed to be the best ones possible
        for the provided ``tau``, but arise from easily-evaluated closed
        expressions and are very good approximations of the best ones.

        See [Nie2013]_ pages 53-54, proposition 3.11 for details.

        INPUT:

        - ``tau`` -- an integer, number of errors one wants the Guruswami-Sudan
          algorithm to correct
        - ``C`` -- (default: ``None``) a :class:`GeneralizedReedSolomonCode`
        - ``n_k`` -- (default: ``None``) a pair of integers, respectively the
          length and the dimension of the :class:`GeneralizedReedSolomonCode`

        OUTPUT:

        - ``(s, l)`` -- a pair of integers, where:
            - ``s`` is the multiplicity parameter, and
            - ``l`` is the list size parameter.

        .. NOTE::

            One has to provide either ``C`` or ``(n, k)``. If neither or both
            are given, an exception will be raised.

        EXAMPLES:


        The following is an example where the parameters are optimal::

            sage: tau = 98
            sage: n, k = 250, 70
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, n_k = (n, k))
            (2, 3)
            sage: codes.decoders.GRSGuruswamiSudanDecoder.parameters_given_tau(tau, n_k = (n, k))
            (2, 3)

        This is an example where they are not::

            sage: tau = 97
            sage: n, k = 250, 70
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, n_k = (n, k))
            (2, 3)
            sage: codes.decoders.GRSGuruswamiSudanDecoder.parameters_given_tau(tau, n_k = (n, k))
            (1, 2)

        We can provide a GRS code instead of `n` and `k` directly::

            sage: C = codes.GeneralizedReedSolomonCode(GF(251).list()[:250], 70)
            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(tau, C = C)
            (2, 3)

        Another one with a bigger ``tau``::

            sage: codes.decoders.GRSGuruswamiSudanDecoder._suitable_parameters_given_tau(118, C = C)
            (47, 89)
        """
        n,k = n_k_params(C, n_k)
        w = k - 1
        atau = n - tau
        smin = tau * w / (atau ** 2 - n * w)
        s = floor(1 + smin)
        D = (s - smin) * (atau ** 2 - n * w) * s + (w**2) /4
        l = floor(atau / w * s + 0.5 - sqrt(D)/w)
        return (s, l)
Example #50
0
def random_dist(p,k,M):	
	"""Returns a random distribution with prime p, weight k, and M moments"""
	moments=vector([ZZ(floor(random()*(p**M))) for i in range(1,M+1)])
	
	return dist(p,k,moments)
Example #51
0
def kneading_sequence(theta):
    r"""
    Determines the kneading sequence for an angle theta in RR/ZZ which
    is periodic under doubling. We use the definition for the kneading
    sequence given in Definition 3.2 of [LS1994]_.

    INPUT:

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

    OUTPUT:

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

    REFERENCES:

    [LS1994]_

    EXAMPLES::

        sage: kneading_sequence(0)
        '*'

    ::

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

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

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

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

        sage: kneading_sequence(1.2)
        '110*'

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

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

    if theta not in QQ:
        raise TypeError('input must be a rational number with odd denominator')
    elif QQ(theta).valuation(2) < 0:
        raise ValueError(
            'input must be a rational number with odd denominator')
    else:
        theta = QQ(theta)
        theta = theta - floor(theta)
        KS = []
        not_done = True
        left = theta / 2
        right = (theta + 1) / 2
        y = theta
        while not_done:
            if ((y < left) or (y > right)):
                KS.append('0')
            elif ((y > left) and (y < right)):
                KS.append('1')
            else:
                not_done = False
            y = 2 * y - floor(2 * y)
        KS_str = ''.join(KS) + '*'
    return KS_str
Example #52
0
        def e(self, i, power=1, to_string_end=False, length_only=False):
            r"""
            Returns the `i`-th crystal raising operator on ``self``.

            INPUT:

            - ``i`` -- element of the index set of the underlying root system
            - ``power`` -- positive integer; specifies the power of the raising operator
               to be applied (default: 1)
            - ``to_string_end`` -- boolean; if set to True, returns the dominant end of the
              `i`-string of ``self``. (default: False)
            - ``length_only`` -- boolean; if set to True, returns the distance to the dominant
               end of the `i`-string of ``self``.

            EXAMPLES::

                sage: C = CrystalOfLSPaths(['A',2],[1,1])
                sage: c = C[2]; c
                (1/2*Lambda[1] - Lambda[2], -1/2*Lambda[1] + Lambda[2])
                sage: c.e(1)
                sage: c.e(2)
                (-Lambda[1] + 2*Lambda[2],)
                sage: c.e(2,to_string_end=True)
                (-Lambda[1] + 2*Lambda[2],)
                sage: c.e(1,to_string_end=True)
                (1/2*Lambda[1] - Lambda[2], -1/2*Lambda[1] + Lambda[2])
                sage: c.e(1,length_only=True)
                0
            """
            assert i in self.index_set()
            data = self._string_data(i)
            # compute the minimum i-height M on the path
            if len(data) == 0:
                M = 0
            else:
                M = data[-1][1]
            max_raisings = floor(-M)
            if length_only:
                return max_raisings
            # set the power of e_i to apply
            if to_string_end:
                p = max_raisings
            else:
                p = power
            if p > max_raisings:
                return None

            # copy the vector sequence into a working vector sequence ws
            #!!! ws only needs to be the actual vector sequence, not some
            #!!! fancy crystal graph element
            ws = self.parent()(self.value)

            ix = len(data)-1
            while ix >= 0 and data[ix][1] < M + p:
            # get the index of the current step to be processed
                j = data[ix][0]
                # find the i-height where the current step might need to be split
                if ix == 0:
                    prev_ht = M + p
                else:
                    prev_ht = min(data[ix-1][1],M+p)
                # if necessary split the step. Then reflect the wet part.
                if data[ix][1] - data[ix][2] > prev_ht:
                    ws = ws.split_step(j,1-(prev_ht-data[ix][1])/(-data[ix][2]))
                    ws = ws.reflect_step(j+1,i)
                else:
                    ws = ws.reflect_step(j,i)
                ix = ix - 1
            #!!! at this point we should return the fancy crystal graph element
            #!!! corresponding to the humble vector sequence ws
            return self.parent()(ws.compress())
Example #53
0
def best_simultaneous_convergents_upto(v, Q, start=1, verbose=False):
    r"""
    Return a list of all best simultaneous diophantine approximations p,q of vector
    ``v`` at distance ``|qv-p|<=1/Q`` such that `1<=q<Q^d`.

    INPUT:

    - ``v`` -- list of real numbers
    - ``Q`` -- real number, Q>1
    - ``start`` -- integer (default: ``1``), starting value to check
    - ``verbose`` -- boolean (default: ``False``)

    EXAMPLES::

        sage: from slabbe.diophantine_approx import best_simultaneous_convergents_upto
        sage: best_simultaneous_convergents_upto([e,pi], 2)
        [((3, 3, 1), 3.549646778303845)]
        sage: best_simultaneous_convergents_upto([e,pi], 4)
        [((19, 22, 7), 35.74901433260719)]
        sage: best_simultaneous_convergents_upto([e,pi], 36, start=4**2)
        [((1843, 2130, 678), 203.23944293852406)]
        sage: best_simultaneous_convergents_upto([e,pi], 204, start=36**2)
        [((51892, 59973, 19090), 266.16775098010373),
         ((113018, 130618, 41577), 279.18598227531174)]
        sage: best_simultaneous_convergents_upto([e,pi], 280, start=204**2)
        [((114861, 132748, 42255), 412.7859137824949),
         ((166753, 192721, 61345), 749.3634909055199)]
        sage: best_simultaneous_convergents_upto([e,pi], 750, start=280**2)
        [((446524, 516060, 164267), 896.4734658499202),
         ((1174662, 1357589, 432134), 2935.314937919726)]
        sage: best_simultaneous_convergents_upto([e,pi], 2936, start=750**2)
        [((3970510, 4588827, 1460669), 3654.2989332956854),
         ((21640489, 25010505, 7961091), 6257.014011585661)]

    TESTS::

        sage: best_simultaneous_convergents_upto([e,pi], 102300.1, start=10^9) # not tested (1 min)
        [((8457919940, 9775049397, 3111494861), 194686.19839453633)]
    """
    from slabbe.diophantine_approx_pyx import good_simultaneous_convergents_upto
    from sage.parallel.decorate import parallel
    from sage.parallel.ncpus import ncpus
    step = ncpus()

    @parallel
    def F(shift):
        return good_simultaneous_convergents_upto(v,
                                                  Q,
                                                  start + shift,
                                                  step=step)

    shifts = range(step)
    goods = []
    for (arg, kwds), output in F(shifts):
        if output == 'NO DATA':
            print(
                "problem with v={}, Q={}, start={}, shift={}"
                " because output={}".format(v, Q, start, arg[0], output))
        else:
            goods.extend(output)
    if not goods:
        raise ValueError(
            "Did not find an approximation p,q to v={} s.t.  |p-qv|<=1/Q"
            " where Q={}".format(v, Q))
    goods.sort()
    bests = []
    best_error_inv = 0
    # keep only the best ones
    for q in goods:
        q_v = [q * a for a in v]
        frac_q_v = [a - floor(a) for a in q_v]
        error = max((a if a < .5 else 1 - a) for a in frac_q_v)
        error_inv = 1. / error.n(digits=50)
        if verbose:
            print "q={}, error_inv={}, best_error_inv={}".format(
                q, error_inv, best_error_inv)
        if error_inv > best_error_inv:
            p = [round(a) for a in q_v]
            p.append(q)
            bests.append((tuple(p), error_inv))
            best_error_inv = error_inv
    return bests