Пример #1
0
def necklaces(n, k, weights=None):
    """
    Returns the number of necklace colorings.

    Given integers n >= 1 and k >= 2, this returns the number of ways to color a
    necklace of n beads with k colors. A necklace of length n colored by k
    colors is an equivalence class of n-character strings over an alphabet of
    size k, taking all rotations as equivalent.

    The optional argument weights can be a list or tuple of positive integers
    summing to n. If the colors used are k_0, k_1, ..., k_{n - 1}, then
    weights[i] is the number of times that color k_i is used.

    See Charalambides - Enumerative Combinatorics chapter 13 for more details.

    Input:
        n: Positive integer.
        k: Positive integer >= 2.
        weights: Optional list of weights.

    Returns:
        The number of colorings.

    Examples:
        >>> necklaces(3, 2)
        4
        >>> necklaces(10, 5)
        976887

        This is how we would count the colorings of a necklace with 6 beads
        using 3 colors, where each color is used exactly 2 times:
        >>> necklaces(6, 3, [2, 2, 2])
        16
    """
    if weights:
        j = gcd(weights)
        ss = 0
        for d in xdivisors(j):
            ll = [e/d for e in weights]
            ss += euler_phi(d)*multinomial(n//d, ll)
        return ss//n
    else:
        ss = 0
        for d in xdivisors(n):
            ss += euler_phi(d)*k**(n//d)
        return ss//n
Пример #2
0
    def test_euler_phi_inverse(self):
        self.assertRaisesRegexp(ValueError, "euler_phi_inverse: Must have n > 0.", euler_phi_inverse, -1)
        self.assertEqual(euler_phi_inverse([(2, 2), (5, 2)]), [101, 125, 202, 250])
        values = defaultdict(list)

        for k in xrange(1, 1001):
            phi = euler_phi(k)
            values[phi].append(k)

        for v in xrange(1, 201):
            inv = euler_phi_inverse(v)
            self.assertEqual(inv, values[v])
Пример #3
0
    def test_euler_phi_inverse(self):
        self.assertRaisesRegexp(ValueError,
                                "euler_phi_inverse: Must have n > 0.",
                                euler_phi_inverse, -1)
        self.assertEqual(euler_phi_inverse([(2, 2), (5, 2)]),
                         [101, 125, 202, 250])
        values = defaultdict(list)

        for k in xrange(1, 1001):
            phi = euler_phi(k)
            values[phi].append(k)

        for v in xrange(1, 201):
            inv = euler_phi_inverse(v)
            self.assertEqual(inv, values[v])
Пример #4
0
    def test_euler_phi(self):
        self.assertRaisesRegexp(ValueError, "euler_phi: Must have n > 0.", euler_phi, -1)
        self.assertRaisesRegexp(ValueError, "euler_phi: Must have n > 0.", euler_phi, -1)

        values = [
            1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30,
            16, 20, 16, 24, 12, 36, 18, 24, 16, 40, 12, 42, 20, 24, 22, 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36, 28,
            58, 16, 60, 30, 36, 32, 48, 20, 66, 32, 44, 24, 70, 24, 72, 36, 40, 36, 60, 24, 78, 32, 54, 40, 82, 24, 64,
            42, 56, 40, 88, 24, 72, 44, 60, 46, 72, 32, 96, 42, 60, 40, 100, 32, 102, 48, 48, 52, 106, 36, 108, 40, 72,
            48, 112, 36, 88, 56, 72, 58, 96, 32, 110, 60, 80, 60, 100, 36, 126, 64, 84, 48, 130, 40, 108, 66, 72, 64,
            136, 44, 138, 48, 92, 70, 120, 48, 112, 72, 84, 72, 148, 40, 150, 72, 96, 60, 120, 48, 156, 78, 104, 64,
            132, 54, 162, 80, 80, 82, 166, 48, 156, 64, 108, 84, 172, 56, 120, 80, 116, 88, 178, 48, 180, 72, 120, 88,
            144, 60, 160, 92, 108, 72, 190, 64, 192, 96, 96, 84, 196, 60, 198, 80
        ]

        computed = [euler_phi(e) for e in xrange(1, 201)]
        self.assertEqual(values, computed)
Пример #5
0
    def test_euler_phi(self):
        self.assertRaisesRegexp(ValueError, "euler_phi: Must have n > 0.", euler_phi, -1)
        self.assertRaisesRegexp(ValueError, "euler_phi: Must have n > 0.", euler_phi, -1)

        values = [
            1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30,
            16, 20, 16, 24, 12, 36, 18, 24, 16, 40, 12, 42, 20, 24, 22, 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36, 28,
            58, 16, 60, 30, 36, 32, 48, 20, 66, 32, 44, 24, 70, 24, 72, 36, 40, 36, 60, 24, 78, 32, 54, 40, 82, 24, 64,
            42, 56, 40, 88, 24, 72, 44, 60, 46, 72, 32, 96, 42, 60, 40, 100, 32, 102, 48, 48, 52, 106, 36, 108, 40, 72,
            48, 112, 36, 88, 56, 72, 58, 96, 32, 110, 60, 80, 60, 100, 36, 126, 64, 84, 48, 130, 40, 108, 66, 72, 64,
            136, 44, 138, 48, 92, 70, 120, 48, 112, 72, 84, 72, 148, 40, 150, 72, 96, 60, 120, 48, 156, 78, 104, 64,
            132, 54, 162, 80, 80, 82, 166, 48, 156, 64, 108, 84, 172, 56, 120, 80, 116, 88, 178, 48, 180, 72, 120, 88,
            144, 60, 160, 92, 108, 72, 190, 64, 192, 96, 96, 84, 196, 60, 198, 80
        ]

        computed = [euler_phi(e) for e in xrange(1, 201)]
        self.assertEqual(values, computed)
Пример #6
0
def primitive_root(n, n_factorization=None, phi=None, phi_divisors=None):
    """Returns a primitive root modulo n.

    Given a positive integer n of the form n = 2, 4, p**a, or 2*p**a for p an
    odd prime and a >= 1, this function returns the least primitive root of n.

    Input:
        * n: int (n > 1)

        * n_factorization: list (default=None)
            The prime factorization of n.

        * phi: int (default=None)
            The value of euler_phi(n).

        * phi_divisors: list (default=None)
            A list of the prime divisors of euler_phi(n).

    Returns:
        * g: int
            The least primitive root of n.

    Raises:
        * ValueError: if primitive roots don't exist modulo n.

    Examples:
        >>> primitive_root(7)
        3
        >>> primitive_root(11)
        2
        >>> primitive_root(14)
        3
        >>> primitive_root(12)
        Traceback (most recent call last):
        ...
        ValueError: primitive_root: No primitive root for n.

    Details:
        An integer a is called a primitive root mod n if a generates the
        multiplicative group of units modulo n. Equivalently, a is a primitive
        root modulo n if the order of a modulo m is euler_phi(n).

        As noted above, primitive roots only exist for moduli of the form n = 2,
        4, p**a, 2*p**a, where p > 2 is prime, and a >= 1. See Theorem 6.11 of
        "Elementary Number Theory" by Jones and Jones for a proof of this fact.
        See also Chapter 10 of "Introduction to Analytic Number Theory" by
        Apostol.

        This method uses the fact that an integer a coprime to n is a primitive
        root if and only if a**(euler_phi(n)/p) != 1 (mod n) for each prime p
        dividing euler_phi(n). See Lemma 6.4 in Jones and Jones for a proof of
        this.

        Note also that there is another way to construct primitive roots for
        composite moduli. To find a primitive root modulu p**a for p an odd
        prime and a >= 2, first compute g, a primitive root modulo p using the
        above criteria. Next, compute g1 = g**(p - 1) (mod p**2). If g1 != 1,
        then g is a primitive root modulo p**a for every a >= 1. Otherwise, g +
        p is. Finally, note that when p is an odd prime, if g is a primitive
        root modulo p**a, then either g or g + p**a (whichever is odd) is a
        primitive root modulo 2*p**a. See Lemma 1.4.5 of "A Course in
        Computational Algebraic Number Theory" by Cohen for more details.
    """
    if n_factorization is None:
        n_factorization = factor.factor(n)

    if n % 4 == 0 and n != 4:
        raise ValueError("primitive_root: No primitive root for n.")

    if len(n_factorization) > 2:
        raise ValueError("primitive_root: No primitive root for n.")

    if n % 2 == 1 and len(n_factorization) > 1:
        raise ValueError("primitive_root: No primitive root for n.")

    if phi is None:
        phi = functions.euler_phi(n_factorization)

    if phi_divisors is None:
        phi_divisors = factor.prime_divisors(phi)

    for g in xrange(1, n):
        if is_primitive_root(g, n, phi=phi, phi_divisors=phi_divisors):
            return g
Пример #7
0
def is_primitive_root(a, n, phi=None, phi_divisors=None):
    """Returns True if a is a primitive root mod n and False otherwise.

    Given an integer a and modulus n, this method determines whether or not a is
    a primitive root modulo n.

    Input:
        * a: int

        * n: int (n > 0)
            The modulus.

        * phi: int (default=None)
            Value of euler_phi(n).

        * phi_divisors: list (default=None)
            List of prime divisors of euler_phi(n).

    Returns:
        * b: bool
            b is True if a is a primitive root mod n and False otherwise. Note
            that b will be False when no primitive roots exist modulo n.

    Raises:
        * ValueError: if n <= 1.

    Examples:
        >>> is_primitive_root(2, 11)
        True
        >>> is_primitive_root(3, 11)
        False
        >>> is_primitive_root(3, -2)
        Traceback (most recent call last):
        ...
        ValueError: is_primitive_root: n must be >= 2.

    Details:
        An integer a is called a primitive root mod n if a generates the
        multiplicative group of units modulo n. Equivalently, a is a primitive
        root modulo n if the order of a modulo m is euler_phi(n).

        The algorithm is based on the observation that an integer a coprime to n
        is a primitive root modulo n if and only if a**(euler_phi(n)/d) != 1
        (mod n) for each divisor d of euler_phi(n). See Lemma 6.4 of "Elementary
        Number Theory" by Jones and Jones for a proof.

        Primitive roots exist only for the moduli n = 1, 2, 4, p**a, and 2*p**a,
        where p is an odd prime and a >= 1. These cases are captured in the
        above Lemma, however some simple divisibility tests allow us to exit
        early for certain moduli. See Chapter 6 of "Elementary Number Theory" by
        Jones and Jones for more details. See also Chapter 10 of "Introduction
        to Analytic Number Theory" by Apostol.
    """
    if n <= 1:
        raise ValueError("is_primitive_root: n must be >= 2.")

    if n > 4 and n % 4 == 0:
        return False

    if gcd(a, n) != 1:
        return False

    if phi is None:
        phi = functions.euler_phi(n)

    if phi_divisors is None:
        phi_divisors = factor.prime_divisors(phi)

    for d in phi_divisors:
        if pow(a, phi // d, n) == 1:
            return False

    return True
Пример #8
0
def primitive_root(n, n_factorization=None, phi=None, phi_divisors=None):
    """Returns a primitive root modulo n.

    Given a positive integer n of the form n = 2, 4, p**a, or 2*p**a for p an
    odd prime and a >= 1, this function returns the least primitive root of n.

    Input:
        * n: int (n > 1)

        * n_factorization: list (default=None)
            The prime factorization of n.

        * phi: int (default=None)
            The value of euler_phi(n).

        * phi_divisors: list (default=None)
            A list of the prime divisors of euler_phi(n).

    Returns:
        * g: int
            The least primitive root of n.

    Raises:
        * ValueError: if primitive roots don't exist modulo n.

    Examples:
        >>> primitive_root(7)
        3
        >>> primitive_root(11)
        2
        >>> primitive_root(14)
        3
        >>> primitive_root(12)
        Traceback (most recent call last):
        ...
        ValueError: primitive_root: No primitive root for n.

    Details:
        An integer a is called a primitive root mod n if a generates the
        multiplicative group of units modulo n. Equivalently, a is a primitive
        root modulo n if the order of a modulo m is euler_phi(n).

        As noted above, primitive roots only exist for moduli of the form n = 2,
        4, p**a, 2*p**a, where p > 2 is prime, and a >= 1. See Theorem 6.11 of
        "Elementary Number Theory" by Jones and Jones for a proof of this fact.
        See also Chapter 10 of "Introduction to Analytic Number Theory" by
        Apostol.

        This method uses the fact that an integer a coprime to n is a primitive
        root if and only if a**(euler_phi(n)/p) != 1 (mod n) for each prime p
        dividing euler_phi(n). See Lemma 6.4 in Jones and Jones for a proof of
        this.

        Note also that there is another way to construct primitive roots for
        composite moduli. To find a primitive root modulu p**a for p an odd
        prime and a >= 2, first compute g, a primitive root modulo p using the
        above criteria. Next, compute g1 = g**(p - 1) (mod p**2). If g1 != 1,
        then g is a primitive root modulo p**a for every a >= 1. Otherwise, g +
        p is. Finally, note that when p is an odd prime, if g is a primitive
        root modulo p**a, then either g or g + p**a (whichever is odd) is a
        primitive root modulo 2*p**a. See Lemma 1.4.5 of "A Course in
        Computational Algebraic Number Theory" by Cohen for more details.
    """
    if n_factorization is None:
        n_factorization = factor.factor(n)

    if n % 4 == 0 and n != 4:
        raise ValueError("primitive_root: No primitive root for n.")

    if len(n_factorization) > 2:
        raise ValueError("primitive_root: No primitive root for n.")

    if n % 2 == 1 and len(n_factorization) > 1:
        raise ValueError("primitive_root: No primitive root for n.")

    if phi is None:
        phi = functions.euler_phi(n_factorization)

    if phi_divisors is None:
        phi_divisors = factor.prime_divisors(phi)

    for g in xrange(1, n):
        if is_primitive_root(g, n, phi=phi, phi_divisors=phi_divisors):
            return g
Пример #9
0
def is_primitive_root(a, n, phi=None, phi_divisors=None):
    """Returns True if a is a primitive root mod n and False otherwise.

    Given an integer a and modulus n, this method determines whether or not a is
    a primitive root modulo n.

    Input:
        * a: int

        * n: int (n > 0)
            The modulus.

        * phi: int (default=None)
            Value of euler_phi(n).

        * phi_divisors: list (default=None)
            List of prime divisors of euler_phi(n).

    Returns:
        * b: bool
            b is True if a is a primitive root mod n and False otherwise. Note
            that b will be False when no primitive roots exist modulo n.

    Raises:
        * ValueError: if n <= 1.

    Examples:
        >>> is_primitive_root(2, 11)
        True
        >>> is_primitive_root(3, 11)
        False
        >>> is_primitive_root(3, -2)
        Traceback (most recent call last):
        ...
        ValueError: is_primitive_root: n must be >= 2.

    Details:
        An integer a is called a primitive root mod n if a generates the
        multiplicative group of units modulo n. Equivalently, a is a primitive
        root modulo n if the order of a modulo m is euler_phi(n).

        The algorithm is based on the observation that an integer a coprime to n
        is a primitive root modulo n if and only if a**(euler_phi(n)/d) != 1
        (mod n) for each divisor d of euler_phi(n). See Lemma 6.4 of "Elementary
        Number Theory" by Jones and Jones for a proof.

        Primitive roots exist only for the moduli n = 1, 2, 4, p**a, and 2*p**a,
        where p is an odd prime and a >= 1. These cases are captured in the
        above Lemma, however some simple divisibility tests allow us to exit
        early for certain moduli. See Chapter 6 of "Elementary Number Theory" by
        Jones and Jones for more details. See also Chapter 10 of "Introduction
        to Analytic Number Theory" by Apostol.
    """
    if n <= 1:
        raise ValueError("is_primitive_root: n must be >= 2.")

    if n > 4 and n % 4 == 0:
        return False

    if gcd(a, n) != 1:
        return False

    if phi is None:
        phi = functions.euler_phi(n)

    if phi_divisors is None:
        phi_divisors = factor.prime_divisors(phi)

    for d in phi_divisors:
        if pow(a, phi//d, n) == 1:
            return False

    return True