예제 #1
0
def construct_spx(spx, max=Integer(1280)):
    for r in range(3, max / 4 + 1):
        spx[r] = {}
        s = Integer(1)
        m = Integer(4) * r
        while m <= max:
            c = sum([[(tuple(v), n) for n in Integers(r)]
                     for v in Integers(2)**Integer(s)], [])
            c = [(v, n, Integer(1)) for v, n in c] + [(v, n, Integer(-1))
                                                      for v, n in c]
            spx[r][s] = Graph([c, spx_adj])
            s += 1
            m *= 2
        print "Finished r = %d, constructed %d graphs" % (r, len(spx[r]))
예제 #2
0
    def __call__(self, n, modulus=0):
        """
        Give the nth term of a binary recurrence sequence, possibly mod some modulus.

        INPUT:

        - ``n`` -- an integer (the index of the term in the binary recurrence sequence)

        - ``modulus`` -- a natural number (optional --  default value is 0)

        OUTPUT:

        - An integer (the nth term of the binary recurrence sequence modulo ``modulus``)

        EXAMPLES::

            sage: R = BinaryRecurrenceSequence(3,3,2,1)
            sage: R(2)
            9
            sage: R(101)
            16158686318788579168659644539538474790082623100896663971001
            sage: R(101,12)
            9
            sage: R(101)%12
            9

        """
        R = Integers(modulus)
        F = matrix(
            R, [[0, 1], [self.c, self.b]]
        )  # F*[u_{n}, u_{n+1}]^T = [u_{n+1}, u_{n+2}]^T (T indicates transpose).
        v = matrix(R, [[self.u0], [self.u1]])
        return list(F**n * v)[0][0]
    def __init__(self, n):
        """
        Args:
            n (int): The number of elements in the finite ring.
        """

        f = Integers(n)
        operations = {'+': lambda x, y: x + y, '*': lambda x, y: x * y}
        AlgebraicStructure.__init__(self, set(f), operations)
예제 #4
0
def construct_spx(r, s, multiedges=None, **kargs):
    r"""
    Construct a SPX(2, r, s) graph.

    Return a tuple containing the data that can be used to construct
    the requested SPX graph, and a boolean indicating whether the
    constructed graph should be considered a multigraph.

    INPUT:

    - ``r`` - the ``r`` parameter indicating the range of the counter.

    - ``s`` - the ``s`` parameter indicating the length of the string.

    - ``multiedges`` - whether the constructed graph should be considered
      a multigraph. If ``None`` (default), the second element of the output
      will be set to ``True`` when ``r == 1``. If ``False`` and ``r == 1``,
      a ``ValueError`` is raised. Otherwise, the second element of the
      output will be ``multiedges``.

    - any other named parameters are silently ignored.
    """
    c = [tuple(x) for x
         in cartesian_product([[tuple(y) for y
                                in Integers(2)**Integer(s)], Integers(r),
                               [Integer(1), Integer(-1)]])]
    if r == 1:
        if multiedges is False:
            raise ValueError("A SPX graph with r = 1 has multiple edges")
        data = sum([[((v, n, t), (v, n, -t)),
                     ((v, n, t), (v[1:] + (Integer(0),), n, -t)),
                     ((v, n, t), (v[1:] + (Integer(1),), n, -t))]
                    for v, n, t in c if t == 1], [])
        multiedges = True
    else:
        data = [c, spx_adj]
    return (data, multiedges)
예제 #5
0
    def n_cylinders_edges(self, n):
        r"""
        EXAMPLES::

            sage: from slabbe.markov_transformation import markov_transformations
            sage: T = markov_transformations.Selmer()
            sage: E = T.n_cylinders_edges(1)
            sage: len(E)
            39
        """
        from sage.rings.finite_rings.integer_mod_ring import Integers
        edges = set()
        for w, cyl in self.n_cylinders_iterator(n):
            cols = cyl.columns()
            indices = Integers(len(cols))
            edges.update(frozenset((cols[i], cols[i + 1])) for i in indices)
        return edges
    def __init__(self, n):
        """
        Args:
            n (int): The size of the underlying set.
        """

        self.n = n
        coeffs = product(range(n), repeat=n)
        polys = frozenset(PolynomialRing(Integers(n), 'x')(r) for r in coeffs)
        mats = set()
        element_names = {}
        for poly in polys:
            m = matrix(n, sparse=True)
            for i in range(n):
                m[i, poly(i) % n] = 1
            m.set_immutable()
            mats.add(m)
            element_names[m] = poly
        operation = {'*': lambda x, y: x * y}
        AlgebraicStructure.__init__(self, mats, operation, element_names)
예제 #7
0
    def n_cylinders_edges(self, n):
        r"""
        Return the set of edges of the n-cylinders.

        EXAMPLES::

            sage: from slabbe.matrix_cocycle import cocycles
            sage: ARP = cocycles.ARP()
            sage: ARP.n_cylinders_edges(1)
            {frozenset({(1, 1, 0), (1, 1, 1)}),
             frozenset({(0, 1, 0), (1, 1, 0)}),
             frozenset({(1, 1, 1), (2, 1, 1)}),
             frozenset({(0, 0, 1), (1, 0, 1)}),
             frozenset({(0, 1, 0), (0, 1, 1)}),
             frozenset({(0, 1, 1), (1, 0, 1)}),
             frozenset({(1, 0, 0), (1, 1, 0)}),
             frozenset({(1, 1, 0), (2, 1, 1)}),
             frozenset({(1, 0, 1), (1, 1, 2)}),
             frozenset({(1, 1, 0), (1, 2, 1)}),
             frozenset({(1, 0, 1), (2, 1, 1)}),
             frozenset({(0, 0, 1), (0, 1, 1)}),
             frozenset({(1, 0, 1), (1, 1, 1)}),
             frozenset({(0, 1, 1), (1, 2, 1)}),
             frozenset({(0, 1, 1), (1, 1, 2)}),
             frozenset({(1, 0, 0), (1, 0, 1)}),
             frozenset({(1, 1, 1), (1, 2, 1)}),
             frozenset({(1, 0, 1), (1, 1, 0)}),
             frozenset({(0, 1, 1), (1, 1, 1)}),
             frozenset({(0, 1, 1), (1, 1, 0)}),
             frozenset({(1, 1, 1), (1, 1, 2)})}
        """
        from sage.rings.finite_rings.integer_mod_ring import Integers
        edges = set()
        for w,cyl in self.n_cylinders_iterator(n):
            cols = cyl.columns()
            indices = Integers(len(cols))
            edges.update(frozenset((cols[i], cols[i+1])) for i in indices)
        return edges
예제 #8
0
def logarithmTable(a, p, base, trace=False):
    """
    Compute the tables of logarithms with base a modulo a prime p
    for the given factor base, as needed by the Index calculus algorithm.

    Requires Sage to run.
    """
    from sage.matrix.constructor import Matrix
    from sage.rings.finite_rings.integer_mod_ring import Integers
    v = []
    s = set()
    r, l = 0, len(base)
    M = Matrix(nrows=0, ncols=l)
    fields = [
        Integers(q) for q in totalFactorization(p - 1, trace=descend(trace))
    ]
    while r < l:
        i = randint(1, p - 1)
        if i in s:
            continue
        s.add(i)
        x = pow(a, i, p)
        f = factorizeByBase(int(x), base, p)
        if not f:
            continue
        if trace:
            print("found factorization %d^%d = %s (mod %d)" %
                  (a, i, ' * '.join("%d^%d" % (q, e)
                                    for q, e in zip(base, f) if e != 0), p))
        MM = Matrix(list(M) + [f])
        if all(Matrix(F, MM).rank() > r for F in fields):
            M = MM
            r += 1
            v.append(i)
        elif trace:
            print("rank not increased, discarding")
    return [e for e, in M**-1 * Matrix(zip(v)) % (p - 1)]
예제 #9
0
def _is_p_power_mod(a, p, N):
    """
    Determine if ``a`` is a ``p`` th power modulo ``N``.

    By the CRT, this is equivalent to the condition that ``a`` be a ``p`` th power mod all
    distinct prime powers dividing ``N``.  For each of these, we use the strong statement of
    Hensel's lemma to lift ``p`` th powers mod `q` or `q^2` or `q^3` to ``p`` th powers mod `q^e`.

    INPUT:

    - ``a`` -- an integer

    - ``p`` -- a rational prime number

    - ``N`` -- a positive integer

    OUTPUT:

    - True if ``a`` is a ``p`` th power modulo ``N``; False otherwise.

    EXAMPLES::

        sage: sage.combinat.binary_recurrence_sequences._is_p_power_mod(2**3,7,29)
        False
        sage: sage.combinat.binary_recurrence_sequences._is_p_power_mod(2**3,3,29)
        True

    """

    #By the chinese remainder theorem, we can answer this question by examining whether
    #a is a pth power mod q^e, for all distinct prime powers q^e dividing N.

    for q, e in N.factor():

        #If a = q^v*x, with

        v = a.valuation(q)

        #then if v>=e, a is congruent to 0 mod q^e and is thus a pth power trivially.

        if v >= e:
            continue

        #otherwise, it can only be a pth power if v is a multiple of p.

        if v % p != 0:
            return False

        #in this cse it is a pth power if x is a pth power mod q^(e-v), so let x = aa,
        #and (e-v) = ee:

        aa = a / q**v
        ee = e - v

        #The above steps are equivalent to the statement that we may assume a and qq are
        #relatively prime, if we replace a with aa and e with ee.  Now we must determine when
        #aa is a pth power mod q^ee for (aa,q)=1.

        #If q != p, then by Hensel's lemma, we may lift a pth power mod q, to a pth power
        #mod q^2, etc.

        if q != p:

            #aa is necessarily a pth power mod q if p does not divide the order of the multiplicative
            #group mod q, ie if q is not 1 mod p.

            if q % p == 1:

                #otherwise aa if a pth power mod q iff aa^(q-1)/p == 1

                if GF(q)(aa)**((q - 1) / p) != 1:
                    return False

        #If q = p and ee = 1, then everything is a pth power p by Fermat's little theorem.

        elif ee > 1:

            #We use the strong statement of Hensel's lemma, which implies that if p is odd
            #and aa is a pth power mod p^2, then aa is a pth power mod any higher power of p

            if p % 2 == 1:

                #ZZ/(p^2)ZZ^\times is abstractly isomorphic to ZZ/(p)ZZ cross ZZ/(p-1)ZZ. then
                #aa is a pth power mod p^2 if (aa)^(p*(p-1)/p) == 1, ie if aa^(p-1) == 1.

                if Integers(p**2)(aa)**(p - 1) != 1:
                    return False

            #Otherwise, p=2.  By the strong statement of Hensel's lemma, if aa is a pth power
            #mod p^3, then it is a pth power mod higher powers of p.  So we need only check if it
            #is a pth power mod p^2 and p^3.

            elif ee == 2:

                #all odd squares a 1 mod 4

                if aa % 4 != 1:
                    return False

            #all odd squares are 1 mod 8

            elif aa % 8 != 1:
                return False

    return True
예제 #10
0
    def period(self, m):
        """
        Return the period of the binary recurrence sequence modulo
        an integer ``m``.

        If `n_1` is congruent to `n_2` modulu ``period(m)``, then `u_{n_1}` is
        is congruent to `u_{n_2}` modulo ``m``.

        INPUT:

        - ``m`` -- an integer (modulo which the period of the recurrence relation is calculated).

        OUTPUT:

        - The integer (the period of the sequence modulo m)

        EXAMPLES:

        If `p = \\pm 1 \\mod 5`, then the period of the Fibonacci sequence
        mod `p` is `p-1` (c.f. Lemma 3.3 of [BMS06]).

        ::

            sage: R = BinaryRecurrenceSequence(1,1)
            sage: R.period(31)
            30

            sage: [R(i) % 4 for i in range(12)]
            [0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1]
            sage: R.period(4)
            6

        This function works for degenerate sequences as well.

        ::

            sage: S = BinaryRecurrenceSequence(2,0,1,2)
            sage: S.is_degenerate()
            True
            sage: S.is_geometric()
            True
            sage: [S(i) % 17 for i in range(16)]
            [1, 2, 4, 8, 16, 15, 13, 9, 1, 2, 4, 8, 16, 15, 13, 9]
            sage: S.period(17)
            8

        Note: the answer is cached.
        """

        #If we have already computed the period mod m, then we return the stored value.

        if m in self._period_dict:
            return self._period_dict[m]

        else:
            R = Integers(m)
            A = matrix(R, [[0, 1], [self.c, self.b]])
            w = matrix(R, [[self.u0], [self.u1]])
            Fac = list(m.factor())
            Periods = {}

            #To compute the period mod m, we compute the least integer n such that A^n*w == w.  This necessarily
            #divides the order of A as a matrix in GL_2(Z/mZ).

            #We compute the period modulo all distinct prime powers dividing m, and combine via the lcm.
            #To compute the period mod p^e, we first compute the order mod p.  Then the period mod p^e
            #must divide p^{4e-4}*period(p), as the subgroup of matrices mod p^e, which reduce to
            #the identity mod p is of order (p^{e-1})^4.  So we compute the period mod p^e by successively
            #multiplying the period mod p by powers of p.

            for i in Fac:
                p = i[0]
                e = i[1]
                #first compute the period mod p
                if p in self._period_dict:
                    perp = self._period_dict[p]
                else:
                    F = A.change_ring(GF(p))
                    v = w.change_ring(GF(p))
                    FF = F**(p - 1)
                    p1fac = list((p - 1).factor())

                    #The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1).
                    #The order divides p-1 if it is diagonalizable.  In any case, det(F^(p-1))=1,
                    #so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]].
                    #The order of the subgroup of matrices of this form is p, so the order must divide
                    #p(p-1) -- in fact it must be a multiple of p.  If this is not the case, then the
                    #order divides (p-1)(p+1).  As the period divides the order of the matrix in GL_2(F_p),
                    #these conditions hold for the period as well.

                    #check if the order divides (p-1)
                    if FF * v == v:
                        M = p - 1
                        Mfac = p1fac

                    #check if the trace is 2, then the order is a multiple of p dividing p*(p-1)
                    elif (FF).trace() == 2:
                        M = p - 1
                        Mfac = p1fac
                        F = F**p  #replace F by F^p as now we only need to determine the factor dividing (p-1)

                    #otherwise it will divide (p+1)(p-1)
                    else:
                        M = (p + 1) * (p - 1)
                        p2fac = list(
                            (p + 1).factor()
                        )  #factor the (p+1) and (p-1) terms separately and then combine for speed
                        Mfac_dic = {}
                        for i in list(p1fac + p2fac):
                            if i[0] not in Mfac_dic:
                                Mfac_dic[i[0]] = i[1]
                            else:
                                Mfac_dic[i[0]] = Mfac_dic[i[0]] + i[1]
                        Mfac = [(i, Mfac_dic[i]) for i in Mfac_dic]

                    #Now use a fast order algorithm to compute the period.  We know that the period divides
                    #M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors.  As
                    #F^M*v == v, for each i_j, if F^(M/i_j)*v == v, then the period divides (M/i_j).  After
                    #all factors have been iterated over, the result is the period mod p.

                    Mfac = list(Mfac)
                    C = []

                    #expand the list of prime factors so every factor is with multiplicity 1

                    for i in range(len(Mfac)):
                        for j in range(Mfac[i][1]):
                            C.append(Mfac[i][0])

                    Mfac = C
                    n = M
                    for i in Mfac:
                        b = Integer(n / i)
                        if F**b * v == v:
                            n = b
                    perp = n

                #Now compute the period mod p^e by stepping up by multiples of p
                F = A.change_ring(Integers(p**e))
                v = w.change_ring(Integers(p**e))
                FF = F**perp
                if FF * v == v:
                    perpe = perp
                else:
                    tries = 0
                    while True:
                        tries += 1
                        FF = FF**p
                        if FF * v == v:
                            perpe = perp * p**tries
                            break
                Periods[p] = perpe

            #take the lcm of the periods mod all distinct primes dividing m
            period = 1
            for p in Periods:
                period = lcm(Periods[p], period)

            self._period_dict[m] = period  #cache the period mod m
            return period
예제 #11
0
    def residue(self, absprec=1, field=None, check_prec=True):
        r"""
        Reduces this element modulo `p^{\mathrm{absprec}}`.

        INPUT:

        - ``absprec`` -- a non-negative integer (default: ``1``)

        - ``field`` -- boolean (default ``None``).  Whether to return an element of GF(p) or Zmod(p).

        - ``check_prec`` -- boolean (default ``True``).  Whether to raise an error if this
          element has insufficient precision to determine the reduction.

        OUTPUT:

        This element reduced modulo `p^\mathrm{absprec}` as an element of
        `\ZZ/p^\mathrm{absprec}\ZZ`

        EXAMPLES::

            sage: R = ZpLC(7,4)
            sage: a = R(8)
            sage: a.residue(1)
            1

        TESTS::

            sage: R = ZpLC(7,4)
            sage: a = R(8)
            sage: a.residue(0)
            0
            sage: a.residue(-1)
            Traceback (most recent call last):
            ...
            ValueError: cannot reduce modulo a negative power of p.
            sage: a.residue(5)
            Traceback (most recent call last):
            ...
            PrecisionError: not enough precision known in order to compute residue.
            sage: a.residue(5, check_prec=False)
            8

            sage: a.residue(field=True).parent()
            Finite Field of size 7
        """
        if not isinstance(absprec, Integer):
            absprec = Integer(absprec)
        if check_prec and absprec > self.precision_absolute():
            raise PrecisionError(
                "not enough precision known in order to compute residue.")
        elif absprec < 0:
            raise ValueError("cannot reduce modulo a negative power of p.")
        if self.valuation() < 0:
            raise ValueError(
                "element must have non-negative valuation in order to compute residue."
            )
        if field is None:
            field = (absprec == 1)
        elif field and absprec != 1:
            raise ValueError("field keyword may only be set at precision 1")
        p = self._parent.prime()
        if field:
            from sage.rings.finite_rings.finite_field_constructor import GF
            ring = GF(p)
        else:
            from sage.rings.finite_rings.integer_mod_ring import Integers
            ring = Integers(p**absprec)
        return ring(self.value())
예제 #12
0
 def suspenders(self):
     # from sage.rings import Integers
     return Integers()