def iter_indefinite_forms(self) :
        fm = Integer(4 * self.__m)
        
        if self.__reduced :
            if self.__weak_forms :
                msq = self.__m**2
                for n in xrange(0, min(self.__m // 4 + 1, self.__bound)) :
                    for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0,
                                     isqrt(fm * n + msq + 1) ) :
                        yield (n, r)
            else :

                for r in xrange(0, min(self.__m + 1,
                                       isqrt((self.__bound - 1) * fm) + 1) ) :
                    if fm.divides(r**2) :
                        yield (r**2 // fm, r)
        else :
            if self.__weak_forms :
                msq = self.__m**2
                for n in xrange(0, self.__bound) :
                    for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0,
                                     isqrt(fm * n + msq + 1) ) :
                        yield (n, r)
            else :
                for n in xrange(0, self.__bound) :
                    if (fm * n).is_square() :
                        yield(n, isqrt(fm * n))

        raise StopIteration
Ejemplo n.º 2
0
    def __init__(self, p, check=True, modulus=None):
        """
        Return a new finite field of order `p` where `p` is prime.

        INPUT:

        - ``p`` -- an integer at least 2

        - ``check`` -- bool (default: ``True``); if ``False``, do not
          check ``p`` for primality

        EXAMPLES::

            sage: F = FiniteField(3); F
            Finite Field of size 3
        """
        p = Integer(p)
        if check and not p.is_prime():
            raise ArithmeticError("p must be prime")
        self.__char = p
        # FiniteField_generic does nothing more than IntegerModRing_generic, and
        # it saves a non trivial overhead
        integer_mod_ring.IntegerModRing_generic.__init__(self, p, category=_FiniteFields)

        # If modulus is None, it will be created on demand as x-1
        # by the modulus() method.
        if modulus is not None:
            self._modulus = modulus
Ejemplo n.º 3
0
def hurwitz_kronecker_class_no_x( n, D):
    r"""
    OUTPUT
        The generalized Hurwitz-Kronecker class number $H_n(D)$
        as defined in [S-Z].

    INPUT
        n -- an integer $\ge 1$
        D -- an integer $\le 0$
    """
    n = Integer(n)
    D = Integer(D)
    if n <= 0:
        raise ValueError, "%s: must be an integer >=1" % n
    if D > 0:
        raise ValueError, "%s: must be an integer <= 0" % D
    g = D.gcd( n)
    a,b = _ab(g)
    h = g*b
    if 0 != D%h:
        return 0
    Dp = D//h
    H1 = Rational( gp.qfbhclassno( -Dp))
    if 0 == H1:
        return H1
    return g * Dp.kronecker( n//g) * H1
Ejemplo n.º 4
0
    def _validate(self, n):
        """
        Verify that n is positive and has at most 4095 digits.

        INPUT:
            n

        This function raises a ValueError if the two conditions listed above
        are not both satisfied.  It is here because GMP-ECM silently ignores
        all digits of input after the 4095th!

        EXAMPLES:
            sage: ecm = ECM()
            sage: ecm._validate(0)
            Traceback (most recent call last):
            ...
            ValueError: n must be positive
            sage: ecm._validate(10^5000)
            Traceback (most recent call last):
            ...
            ValueError: n must have at most 4095 digits
        """
        n = Integer(n)
        if n <= 0:
            raise ValueError, "n must be positive"
        if n.ndigits() > 4095:
            raise ValueError, "n must have at most 4095 digits"
Ejemplo n.º 5
0
    def nth_root(self, n):
        """
        Return an `n`-th root of ``self``.

        EXAMPLES::

            sage: F = GF(5).algebraic_closure()
            sage: t = F.gen(2) + 1
            sage: s = t.nth_root(15); s
            4*z6^5 + 3*z6^4 + 2*z6^3 + 2*z6^2 + 4
            sage: s**15 == t
            True

        .. TODO::

            This function could probably be made faster.

        """
        from sage.rings.integer import Integer
        F = self.parent()
        x = self._value
        n = Integer(n)
        l = self._level
        # In order to be smart we look for the smallest subfield that
        # actually contains the root.
        for d in n.divisors():
            xx = F.inclusion(l, d*l)(x)
            try:
                y = xx.nth_root(n, extend=False)
            except ValueError:
                continue
            return self.__class__(F, y)

        raise AssertionError('cannot find n-th root in algebraic closure of finite field')
Ejemplo n.º 6
0
    def __getitem__(self,level):
        """
        Return the modular polynomial of given level, or an error if
        there is no such polynomial in the database.
        
        EXAMPLES:
            sage: DBMP = ClassicalModularPolynomialDatabase()  #optional requires database_hohel
            sage: f = DBMP[29]                                 #optional
            sage: f.degree()                                   #optional
            58
            sage: f.coefficient([28,28])                       #optional
            400152899204646997840260839128

            sage: DBMP[50]                                     #optional
            Traceback (most recent call last):
            ...
            RuntimeError: No database entry for modular polynomial of level 50
        """
        if self.model in ("Atk","Eta"):
            level = Integer(level)
            if not level.is_prime():
                raise TypeError, "Argument level (= %s) must be prime."%level 
        elif self.model in ("AtkCrr","EtaCrr"):
            N = Integer(level[0])
            if not N in (2,3,5,7,13):
                raise TypeError, "Argument level (= %s) must be prime."%N
        modpol = self._dbpath(level)
        try:
            coeff_list = _dbz_to_integer_list(modpol)
        except RuntimeError, msg:
            print msg
            raise RuntimeError, \
                  "No database entry for modular polynomial of level %s"%level
Ejemplo n.º 7
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError, "Unknown representation %s" % repr

        q = Integer(q)
        if q < 2:
            raise ValueError, "q  must be a prime power"
        F = q.factor()
        if len(F) > 1:
            raise ValueError, "q must be a prime power"
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError, "q must be < 2^16"

        import constructor

        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        self._is_conway = False
        if modulus is None or modulus == "conway":
            if k == 1:
                modulus = "random"  # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.constructor import conway_polynomial

                modulus = conway_polynomial(p, k)
                self._is_conway = True
            elif modulus is None:
                modulus = "random"
            else:
                raise ValueError, "Conway polynomial not found"

        from sage.rings.polynomial.all import is_Polynomial

        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
Ejemplo n.º 8
0
def QuadraticResidueCodeOddPair(n, F):
    """
    Quadratic residue codes of a given odd prime length and base ring
    either don't exist at all or occur as 4-tuples - a pair of
    "odd-like" codes and a pair of "even-like" codes. If n 2 is prime
    then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a
    quadratic residue mod n.

    They are constructed as "odd-like" duadic codes associated the
    splitting (Q,N) mod n, where Q is the set of non-zero quadratic
    residues and N is the non-residues.

    EXAMPLES::

        sage: codes.QuadraticResidueCodeOddPair(17,GF(13))
        (Linear code of length 17, dimension 9 over Finite Field of size 13,
         Linear code of length 17, dimension 9 over Finite Field of size 13)
        sage: codes.QuadraticResidueCodeOddPair(17,GF(2))
        (Linear code of length 17, dimension 9 over Finite Field of size 2,
         Linear code of length 17, dimension 9 over Finite Field of size 2)
        sage: codes.QuadraticResidueCodeOddPair(13,GF(9,"z"))
        (Linear code of length 13, dimension 7 over Finite Field in z of size 3^2,
         Linear code of length 13, dimension 7 over Finite Field in z of size 3^2)
        sage: C1 = codes.QuadraticResidueCodeOddPair(17,GF(2))[1]
        sage: C1x = C1.extended_code()
        sage: C2 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
        sage: C2x = C2.extended_code()
        sage: C2x.spectrum(); C1x.spectrum()
        [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1]
        [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1]
        sage: C3 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0]
        sage: C3x = C3.extended_code()
        sage: C3x.spectrum()
        [1, 0, 0, 0, 14, 0, 0, 0, 1]

    This is consistent with Theorem 6.6.14 in [HP]_.

    TESTS::

        sage: codes.QuadraticResidueCodeOddPair(9,GF(2))
        Traceback (most recent call last):
        ...
        ValueError: the argument n must be an odd prime
    """
    from sage.arith.srange import srange
    from sage.categories.finite_fields import FiniteFields

    if F not in FiniteFields():
        raise ValueError("the argument F must be a finite field")
    q = F.order()
    n = Integer(n)
    if n <= 2 or not n.is_prime():
        raise ValueError("the argument n must be an odd prime")
    Q = quadratic_residues(n)
    Q.remove(0)  # non-zero quad residues
    N = [x for x in srange(1, n) if x not in Q]  # non-zero quad non-residues
    if q not in Q:
        raise ValueError("the order of the finite field must be a quadratic residue modulo n")
    return DuadicCodeOddPair(F, Q, N)
    def iter_indefinite_forms(self) :
        r"""
        Iterate over indices with non-positive discriminant.
        
        TESTS::
        
            sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import *
            sage: list(JacobiFormD1NNFilter(2, 2, reduced = False, weak_forms = True).iter_indefinite_forms())
            [(0, -1), (1, 3), (0, 0), (1, -3), (0, 1), (0, -2), (0, 2)]
            sage: list(JacobiFormD1NNFilter(3, 2, reduced = False, weak_forms = True).iter_indefinite_forms())
            [(0, -1), (1, 3), (2, -4), (0, 0), (2, 4), (1, -3), (0, 1), (0, -2), (0, 2)]
            sage: list(JacobiFormD1NNFilter(10, 2, reduced = True, weak_forms = True).iter_indefinite_forms())
            [(0, 0), (0, 1), (0, 2)]
            sage: list(JacobiFormD1NNFilter(10, 3, reduced = True, weak_forms = True).iter_indefinite_forms())
            [(0, 0), (0, 1), (0, 2), (0, 3)]
            sage: list(JacobiFormD1NNFilter(10, 10, reduced = True, weak_forms = True).iter_indefinite_forms())                                                  
            [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (1, 7), (1, 8), (1, 9), (1, 10), (2, 9), (2, 10)]
        """
        B = self.__bound
        m = self.__m
        fm = Integer(4 * self.__m)
        
        if self.__reduced :
            if self.__weak_forms :
                for n in xrange(0, min(self.__m // 4 + 1, self.__bound)) :
                    for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0, self.__m + 1 ) :
                        yield (n, r)
            else :
                for r in xrange(0, min(self.__m + 1,
                                       isqrt((self.__bound - 1) * fm) + 1) ) :
                    if fm.divides(r**2) :
                        yield (r**2 // fm, r)
        else :
            if self.__weak_forms :
                ## We first determine the reduced indices.
                for n in xrange(0, min(m // 4 + 1, B)) :
                    if n == 0 :
                        r_iteration = range(-m + 1, m + 1)
                    else :
                        r_iteration =   range( -m + 1, -isqrt(fm * n - 1) ) \
                                       + range( isqrt(fm * n - 1) + 1, m + 1 )
                    for r in  r_iteration :
                        for l in range( (- r - isqrt(r**2 - 4 * m * (n - (B - 1))) - 1) // (2 * m) + 1,
                                        (- r + isqrt(r**2 - 4 * m * (n - (B - 1)))) // (2 * m) + 1 ) :
                            if n + l * r + m * l**2 >= B :
                                print l, n, r
                            yield (n + l * r + m * l**2, r + 2 * m * l)
            else :
                if self.__bound > 0 :
                    yield (0,0)

                for n in xrange(1, self.__bound) :
                    if (fm * n).is_square() :
                        rt_fmm = isqrt(fm * n)
                        yield(n, rt_fmm)
                        yield(n, -rt_fmm)
        
        raise StopIteration
    def __init__(self, A, elt=None, check=True):
        """
        TESTS::

            sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])])
            sage: A(QQ(4))
            Traceback (most recent call last):
            ...
            TypeError: elt should be a vector, a matrix, or an element of the base field

            sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])])
            sage: elt = B(Matrix([[1,1], [-1,1]])); elt
            e0 + e1
            sage: TestSuite(elt).run()
            sage: B(Matrix([[0,1], [1,0]]))
            Traceback (most recent call last):
            ...
            ValueError: matrix does not define an element of the algebra
        """
        AlgebraElement.__init__(self, A)
        k = A.base_ring()
        n = A.degree()
        if elt is None:
            self._vector = vector(k, n)
            self._matrix = Matrix(k, n)
        else:
            if isinstance(elt, int):
                elt = Integer(elt)
            elif isinstance(elt, list):
                elt = vector(elt)
            if A == elt.parent():
                self._vector = elt._vector.base_extend(k)
                self._matrix = elt._matrix.base_extend(k)
            elif k.has_coerce_map_from(elt.parent()):
                e = k(elt)
                if e == 0:
                    self._vector = vector(k, n)
                    self._matrix = Matrix(k, n)
                elif A.is_unitary():
                    self._vector = A._one * e
                    self._matrix = Matrix.identity(k, n) * e
                else:
                    raise TypeError("algebra is not unitary")
            elif is_Vector(elt):
                self._vector = elt.base_extend(k)
                self._matrix = Matrix(k, sum([elt[i] * A.table()[i] for i in xrange(n)]))
            elif is_Matrix(elt):
                if not A.is_unitary():
                    raise TypeError("algebra is not unitary")
                self._vector = A._one * elt
                if not check or sum([self._vector[i]*A.table()[i] for i in xrange(n)]) == elt:
                    self._matrix = elt
                else:
                    raise ValueError("matrix does not define an element of the algebra")
            else:
                raise TypeError("elt should be a vector, a matrix, " +
                                "or an element of the base field")
Ejemplo n.º 11
0
def _lexi_gen(zeroes=False):
    """
    Return a generator object that produces variable names suitable for the
    generators of a free group.

    INPUT:

    - ``zeroes`` -- Boolean defaulting as ``False``. If ``True``, the
      integers appended to the output string begin at zero at the
      first iteration through the alphabet.

    OUTPUT:

    Python generator object which outputs a character from the alphabet on each
    ``next()`` call in lexicographical order. The integer `i` is appended
    to the output string on the `i^{th}` iteration through the alphabet.

    EXAMPLES::

        sage: from train_track import *
        sage: from train_track.free_group import _lexi_gen
        sage: itr = _lexi_gen()
        sage: F = FreeGroup([next(itr) for i in [1..10]]); F
        Free Group on generators {a, b, c, d, e, f, g, h, i, j}
        sage: it = _lexi_gen()
        sage: [next(it) for i in range(10)]
        ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
        sage: itt = _lexi_gen(True)
        sage: [next(itt) for i in range(10)]
        ['a0', 'b0', 'c0', 'd0', 'e0', 'f0', 'g0', 'h0', 'i0', 'j0']
        sage: test = _lexi_gen()
        sage: ls = [next(test) for i in range(3*26)]
        sage: ls[2*26:3*26]
        ['a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2', 'i2', 'j2', 'k2', 'l2', 'm2',
         'n2', 'o2', 'p2', 'q2', 'r2', 's2', 't2', 'u2', 'v2', 'w2', 'x2', 'y2', 'z2']

    TESTS::

        sage: from train_track import *
        sage: from train_track.free_group import _lexi_gen
        sage: test = _lexi_gen()
        sage: ls = [next(test) for i in range(500)]
        sage: ls[234], ls[260]
        ('a9', 'a10')

    """
    count = Integer(0)
    while True:
        mwrap, ind  = count.quo_rem(26)
        if mwrap == 0 and not(zeroes):
            name = ''
        else:
            name = str(mwrap)
        name = chr(ord('a') + ind) + name
        yield name
        count = count + 1
Ejemplo n.º 12
0
    def __init__(self, q, names="a",  modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: Modulus parameter not understood
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3 = k1._finite_field_ext_pari_()
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        p = Integer(2)
        FiniteField.__init__(self, GF(p), names, normalize=True)

        self._kwargs = {'repr':repr}
        self._is_conway = False

        if modulus is None or modulus == 'default':
            if exists_conway_polynomial(p, k):
                modulus = "conway"
            else:
                modulus = "minimal_weight"
        if modulus == "conway":
            modulus = conway_polynomial(p, k)
            self._is_conway = True
        if is_Polynomial(modulus):
            modulus = modulus.list()
        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._polynomial = {}
Ejemplo n.º 13
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ["int", "log", "poly"]:
            raise ValueError("Unknown representation %s" % repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1 << 16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF

        FiniteField.__init__(self, GF(p), name, normalize=False)

        self._kwargs["repr"] = repr
        self._kwargs["cache"] = cache

        from sage.rings.polynomial.polynomial_element import is_Polynomial

        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation

            deprecation(
                16930,
                "constructing a FiniteField_givaro without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead",
            )
            R = GF(p)["x"]
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Ejemplo n.º 14
0
    def __classcall_private__(cls, begin, end=None, step=Integer(1), middle_point=None):
        """
        TESTS::

            sage: IntegerRange(2,5,0)
            Traceback (most recent call last):
            ...
            ValueError: IntegerRange() step argument must not be zero
            sage: IntegerRange(2) is IntegerRange(0, 2)
            True
            sage: IntegerRange(1.0)
            Traceback (most recent call last):
            ...
            TypeError: end must be Integer or Infinity, not <type 'sage.rings.real_mpfr.RealLiteral'>
        """
        if isinstance(begin, int): begin = Integer(begin)
        if isinstance(end, int): end = Integer(end)
        if isinstance(step,int): step = Integer(step)

        if end is None:
            end = begin
            begin = Integer(0)
        # check of the arguments
        if not isinstance(begin, (Integer, MinusInfinity, PlusInfinity)):
            raise TypeError("begin must be Integer or Infinity, not %r" % type(begin))
        if not isinstance(end, (Integer, MinusInfinity, PlusInfinity)):
            raise TypeError("end must be Integer or Infinity, not %r" % type(end))
        if not isinstance(step, Integer):
            raise TypeError("step must be Integer, not %r" % type(step))
        if step.is_zero():
            raise ValueError("IntegerRange() step argument must not be zero")

        # If begin and end are infinite, middle_point and step will defined the set.
        if begin == -Infinity and end == Infinity:
            if middle_point is None:
                raise ValueError("Can't iterate over this set, please provide middle_point")

        # If we have a middle point, we go on the special enumeration way...
        if middle_point is not None:
            return IntegerRangeFromMiddle(begin, end, step, middle_point)

        if (begin == -Infinity) or (begin == Infinity):
            raise ValueError("Can't iterate over this set: It is impossible to begin an enumeration with plus/minus Infinity")

        # Check for empty sets
        if step > 0 and begin >= end or step < 0 and begin <= end:
            return IntegerRangeEmpty()

        if end != Infinity and end != -Infinity:
            # Normalize the input
            sgn = 1 if step > 0 else -1
            end = begin+((end-begin-sgn)//(step)+1)*step
            return IntegerRangeFinite(begin, end, step)
        else:
            return IntegerRangeInfinite(begin, step)
Ejemplo n.º 15
0
    def __init__(self, q, name="a",  modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        self._kwargs = {}

        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q  must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        import constructor
        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)

        self._kwargs['repr'] = repr
        self._kwargs['cache'] = cache

        if modulus is None or modulus == 'conway':
            if k == 1:
                modulus = 'random' # this will use the gfq_factory_pk function.
            elif ConwayPolynomials().has_polynomial(p, k):
                from sage.rings.finite_rings.conway_polynomials import conway_polynomial
                modulus = conway_polynomial(p, k)
            elif modulus is None:
                modulus = 'random'
            else:
                raise ValueError("Conway polynomial not found")

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if is_Polynomial(modulus):
            modulus = modulus.list()

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
Ejemplo n.º 16
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        self._kwargs = {'repr':repr}

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            from sage.misc.superseded import deprecation
            deprecation(16983, "constructing a FiniteField_ntl_gf2e without giving a polynomial as modulus is deprecated, use the more general FiniteField constructor instead")
            R = GF2['x']
            if modulus is None or isinstance(modulus, str):
                modulus = R.irreducible_element(k, algorithm=modulus)
            else:
                modulus = R(modulus)

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Ejemplo n.º 17
0
def _big_delta_coeff(aa, bb, cc, prec=None):
    r"""
    Calculates the Delta coefficient of the 3 angular momenta for
    Racah symbols. Also checks that the differences are of integer
    value.

    INPUT:

    -  ``aa`` - first angular momentum, integer or half integer

    -  ``bb`` - second angular momentum, integer or half integer

    -  ``cc`` - third angular momentum, integer or half integer

    -  ``prec`` - precision of the ``sqrt()`` calculation

    OUTPUT:

    double - Value of the Delta coefficient

    EXAMPLES::

        sage: from sage.functions.wigner import _big_delta_coeff
        sage: _big_delta_coeff(1,1,1)
        1/2*sqrt(1/6)
    """
    if int(aa + bb - cc) != (aa + bb - cc):
        raise ValueError("j values must be integer or half integer and fulfill the triangle relation")
    if int(aa + cc - bb) != (aa + cc - bb):
        raise ValueError("j values must be integer or half integer and fulfill the triangle relation")
    if int(bb + cc - aa) != (bb + cc - aa):
        raise ValueError("j values must be integer or half integer and fulfill the triangle relation")
    if (aa + bb - cc) < 0:
        return 0
    if (aa + cc - bb) < 0:
        return 0
    if (bb + cc - aa) < 0:
        return 0

    maxfact = max(aa + bb - cc, aa + cc - bb, bb + cc - aa, aa + bb + cc + 1)
    _calc_factlist(maxfact)

    argsqrt = Integer(_Factlist[int(aa + bb - cc)] * \
                          _Factlist[int(aa + cc - bb)] * \
                          _Factlist[int(bb + cc - aa)]) / \
                          Integer(_Factlist[int(aa + bb + cc + 1)])

    ressqrt = argsqrt.sqrt(prec)
    if isinstance(ressqrt, ComplexNumber):
        res = ressqrt.real()
    else:
        res = ressqrt
    return res
Ejemplo n.º 18
0
def _ab( m):
    r"""
    OUTPUT
        The unique pair of integers $a,b$ such that $m=a^2b$
        with squarefree $b$.

    INPUT
        m -- a nonzero integer
    """
    m = Integer(m)
    b = m.squarefree_part()
    a = (m//b).isqrt()
    return a, b
Ejemplo n.º 19
0
    def __getitem__(self, level):
        """
        Return the modular polynomial of given level, or an error if
        there is no such polynomial in the database.

        EXAMPLES::

            sage: DBMP = ClassicalModularPolynomialDatabase()
            sage: f = DBMP[29]                                 # optional - database_kohel
            sage: f.degree()                                   # optional - database_kohel
            58
            sage: f.coefficient([28,28])                       # optional - database_kohel
            400152899204646997840260839128

            sage: DBMP[50]                                     # optional - database_kohel
            Traceback (most recent call last):
            ...
            LookupError: filename .../kohel/PolMod/Cls/pol.050.dbz does not exist
        """
        from sage.rings.integer import Integer
        from sage.rings.integer_ring import IntegerRing
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

        if self.model in ("Atk","Eta"):
            level = Integer(level)
            if not level.is_prime():
                raise TypeError("Argument level (= %s) must be prime."%level)
        elif self.model in ("AtkCrr","EtaCrr"):
            N = Integer(level[0])
            if not N in (2,3,5,7,13):
                raise TypeError("Argument level (= %s) must be prime."%N)
        modpol = self._dbpath(level)
        coeff_list = _dbz_to_integer_list(modpol)
        if self.model == "Cls":
            P = PolynomialRing(IntegerRing(),2,"j")
        else:
            P = PolynomialRing(IntegerRing(),2,"x,j")
        poly = {}
        if self.model == "Cls":
            if level == 1:
                return P({(1,0):1,(0,1):-1})
            for cff in coeff_list:
                i = cff[0]
                j = cff[1]
                poly[(i,j)] = Integer(cff[2])
                if i != j:
                    poly[(j,i)] = Integer(cff[2])
        else:
            for cff in coeff_list:
                poly[(cff[0],cff[1])] = Integer(cff[2])
        return P(poly)
Ejemplo n.º 20
0
    def __getitem__(self,level):
        """
        Return the modular polynomial of given level, or an error if
        there is no such polynomial in the database.

        EXAMPLES:
            sage: DBMP = ClassicalModularPolynomialDatabase()  # optional - database_kohel
            sage: f = DBMP[29]                                 #optional
            sage: f.degree()                                   #optional
            58
            sage: f.coefficient([28,28])                       #optional
            400152899204646997840260839128

            sage: DBMP[50]                                     #optional
            Traceback (most recent call last):
            ...
            RuntimeError: No database entry for modular polynomial of level 50
        """
        if self.model in ("Atk","Eta"):
            level = Integer(level)
            if not level.is_prime():
                raise TypeError("Argument level (= %s) must be prime."%level)
        elif self.model in ("AtkCrr","EtaCrr"):
            N = Integer(level[0])
            if not N in (2,3,5,7,13):
                raise TypeError("Argument level (= %s) must be prime."%N)
        modpol = self._dbpath(level)
        try:
            coeff_list = _dbz_to_integer_list(modpol)
        except RuntimeError as msg:
            print(msg)
            raise RuntimeError("No database entry for modular polynomial of level %s"%level)
        if self.model == "Cls":
            P = PolynomialRing(IntegerRing(),2,"j")
        else:
            P = PolynomialRing(IntegerRing(),2,"x,j")
        poly = {}
        if self.model == "Cls":
            if level == 1:
                return P({(1,0):1,(0,1):-1})
            for cff in coeff_list:
                i = cff[0]
                j = cff[1]
                poly[(i,j)] = Integer(cff[2])
                if i != j:
                    poly[(j,i)] = Integer(cff[2])
        else:
            for cff in coeff_list:
                poly[(cff[0],cff[1])] = Integer(cff[2])
        return P(poly)
Ejemplo n.º 21
0
def isqrt(x):
    """
    Return an integer square root, i.e., the floor of a square root.

    EXAMPLES::

        sage: isqrt(10)
        3
        sage: isqrt(10r)
        3
    """
    try:
        return x.isqrt()
    except AttributeError:
        from sage.functions.all import floor
        n = Integer(floor(x))
        return n.isqrt()
Ejemplo n.º 22
0
    def __init__(self, q, names="a", modulus=None, repr="poly"):
        """
        Initialize ``self``.

        TESTS::

            sage: k.<a> = GF(2^100, modulus='strangeinput')
            Traceback (most recent call last):
            ...
            ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
            sage: k.<a> = GF(2^20) ; type(k)
            <class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
            sage: loads(dumps(k)) is k
            True
            sage: k1.<a> = GF(2^16)
            sage: k2.<a> = GF(2^17)
            sage: k1 == k2
            False
            sage: k3.<a> = GF(2^16, impl="pari_ffelt")
            sage: k1 == k3
            False

            sage: TestSuite(k).run()

            sage: k.<a> = GF(2^64)
            sage: k._repr_option('element_is_atomic')
            False
            sage: P.<x> = PolynomialRing(k)
            sage: (a+1)*x # indirect doctest
            (a + 1)*x
        """
        late_import()
        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a 2-power")
        k = q.exact_log(2)
        if q != 1 << k:
            raise ValueError("q must be a 2-power")
        FiniteField.__init__(self, GF2, names, normalize=True)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_ntl_gf2e(self, k, modulus)
        self._modulus = modulus
Ejemplo n.º 23
0
    def __init__(self, p, modulus, name=None):
        """
        Create a finite field of characteristic `p` defined by the
        polynomial ``modulus``, with distinguished generator called
        ``name``.

        EXAMPLE::

            sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt
            sage: R.<x> = PolynomialRing(GF(3))
            sage: k = FiniteField_pari_ffelt(3, x^2 + 2*x + 2, 'a'); k
            Finite Field in a of size 3^2
        """
        import constructor
        from sage.libs.pari.all import pari
        from sage.rings.integer import Integer
        from sage.structure.proof.all import arithmetic
        proof = arithmetic()

        p = Integer(p)
        if ((p < 2)
            or (proof and not p.is_prime())
            or (not proof and not p.is_pseudoprime())):
            raise ArithmeticError("p must be a prime number")
        Fp = constructor.FiniteField(p)

        if name is None:
            name = modulus.variable_name()

        FiniteField.__init__(self, base=Fp, names=name, normalize=True)

        modulus = self.polynomial_ring()(modulus)
        n = modulus.degree()
        if n < 2:
            raise ValueError("the degree must be at least 2")

        self._modulus = modulus
        self._degree = n
        self._card = p ** n
        self._kwargs = {}

        self._gen_pari = pari(modulus).ffgen()
        self._zero_element = self.element_class(self, 0)
        self._one_element = self.element_class(self, 1)
        self._gen = self.element_class(self, self._gen_pari)
Ejemplo n.º 24
0
def __check( k, m, l, n):
    k = Integer(k)
    m = Integer(m)
    l = Integer(l)
    n = Integer(n)

    if m <= 0:
        raise ValueError, "%s: m must be a positive integer" % m

    if l < 1 or 1 != l.gcd( m):
        raise ValueError, "%s: l must be a positive integer prime to %d" \
              % ( l, m)

    if n <=0 or 0 != m%n or 1 != n.gcd( m//n):
        raise ValueError, "%s: n must be an exact divisor of %d" \
              ( n, m)

    return k, m, l, n
Ejemplo n.º 25
0
    def __init__(self, level, weight):
        if weight % 2 != 0:
            raise NotImplementedError, "Only even weight forms are implemented."

        if level != 1 and not Integer(level).is_prime():
            raise NotImplementedError, "Only prime level or level 1 is implemented."

        self.__level = Integer(level)
        self.__weight = weight
Ejemplo n.º 26
0
    def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: k.<a> = GF(2^3)
            sage: j.<b> = GF(3^4)
            sage: k == j
            False

            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
            True
            sage: TestSuite(GF(2^3, 'a')).run()
        """
        if repr not in ['int', 'log', 'poly']:
            raise ValueError("Unknown representation %s"%repr)

        q = Integer(q)
        if q < 2:
            raise ValueError("q must be a prime power")
        F = q.factor()
        if len(F) > 1:
            raise ValueError("q must be a prime power")
        p = F[0][0]
        k = F[0][1]

        if q >= 1<<16:
            raise ValueError("q must be < 2^16")

        from .finite_field_constructor import GF
        FiniteField.__init__(self, GF(p), name, normalize=False)

        from sage.rings.polynomial.polynomial_element import is_Polynomial
        if not is_Polynomial(modulus):
            raise TypeError("modulus must be a polynomial")

        self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
        self._modulus = modulus
Ejemplo n.º 27
0
    def _init_Vrepresentation_from_ppl(self, minimize):
        """
        Create the Vrepresentation objects from the ppl polyhedron.

        EXAMPLES::

            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
            ....:                backend='ppl')  # indirect doctest
            sage: p.Hrepresentation()
            (An inequality (1, 4) x - 2 >= 0,
             An inequality (1, -12) x + 6 >= 0,
             An inequality (-5, 12) x + 10 >= 0)
            sage: p._ppl_polyhedron.minimized_constraints()
            Constraint_System {x0+4*x1-2>=0, x0-12*x1+6>=0, -5*x0+12*x1+10>=0}
            sage: p.Vrepresentation()
            (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6))
            sage: p._ppl_polyhedron.minimized_generators()
            Generator_System {point(0/2, 1/2), point(2/1, 0/1), point(24/6, 5/6)}
        """
        self._Vrepresentation = []
        gs = self._ppl_polyhedron.minimized_generators()
        parent = self.parent()
        for g in gs:
            coefficients = [Integer(mpz) for mpz in g.coefficients()]
            if g.is_point():
                d = Integer(g.divisor())
                if d.is_one():
                    parent._make_Vertex(self, coefficients)
                else:
                    parent._make_Vertex(self, [x/d for x in coefficients])
            elif g.is_ray():
                parent._make_Ray(self, coefficients)
            elif g.is_line():
                parent._make_Line(self, coefficients)
            else:
                assert False
        self._Vrepresentation = tuple(self._Vrepresentation)
Ejemplo n.º 28
0
    def __init__(self, p, check=True):
        """
        Return a new finite field of order `p` where `p` is prime.

        INPUT:

        - ``p`` -- an integer at least 2

        - ``check`` -- bool (default: ``True``); if ``False``, do not
          check ``p`` for primality

        EXAMPLES::

            sage: F = FiniteField(3); F
            Finite Field of size 3
        """
        p = Integer(p)
        if check and not p.is_prime():
            raise ArithmeticError("p must be prime")
        self.__char = p
        self._kwargs = {}
        # FiniteField_generic does nothing more than IntegerModRing_generic, and
        # it saves a non trivial overhead
        integer_mod_ring.IntegerModRing_generic.__init__(self, p, category = _FiniteFields)
Ejemplo n.º 29
0
def _sz_s( k, m, l, n):
    r"""
    OUTPUT
        The function  $s_{k,m}(l,n)$, i.e.~the trace
        of $T(l) \circ W_n$ on the "certain" space
        $\mathcal{M}_{2k-2}^{\text{cusp}}(m)$ of modular forms
        as defined in [S-Z].

    INPUT
        l -- index of the Hecke operator, rel. prime to the level $m$
        n -- index of the Atkin-Lehner involution (exact divisor of $m$)
        k -- integer ($2k-2$ is the weight)
        m -- level
    """
    k = Integer(k)
    m = Integer(m)
    l = Integer(l)
    n = Integer(n)
    if k < 2:
        return 0
    if 1 != m.gcd(l):
        raise ValueError, \
              "gcd(%s,%s) != 1: not yet implemented" % (m,l)

    ellT = 0
    for np in n.divisors():
        ellT -= sum( l**(k-2) \
                     * _gegenbauer_pol( k-2, s*s*np/l) \
                     * hurwitz_kronecker_class_no_x( m/n, s*s*np*np - 4*l*np) \
                     for s in range( -(Integer(4*l*np).isqrt()//np), \
                                     1+(Integer(4*l*np).isqrt()//np)) \
                     if (n//np).gcd(s*s).is_squarefree())/2

    parT = -sum( min( lp, l//lp)**(2*k-3) \
                 * _ab(n)[0].gcd( lp+l//lp) \
                 * _ab(m/n)[0].gcd( lp-l//lp) \
                 for lp in l.divisors())/2
    
    if 2 == k and (m//n).is_square():
        corT = sigma(n,0)*sigma(l,1)
    else:
        corT = 0
        
    return Integer( ellT + parT + corT)
Ejemplo n.º 30
0
def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None):
    r"""
    Calculate the Gaunt coefficient.

    The Gaunt coefficient is defined as the integral over three
    spherical harmonics:

    .. MATH::

        Y(l_1,l_2,l_3,m_1,m_2,m_3) \hspace{12em} \\ 
        =\int Y_{l_1,m_1}(\Omega) \
         Y_{l_2,m_2}(\Omega) \ Y_{l_3,m_3}(\Omega) \ d\Omega \hspace{5em} \\
        =\sqrt{\frac{(2l_1+1)(2l_2+1)(2l_3+1)}{4\pi}} \hspace{6.5em} \\ 
         \times \begin{pmatrix} l_1 & l_2 & l_3 \\ 0 & 0 & 0 \end{pmatrix}
         \begin{pmatrix} l_1 & l_2 & l_3 \\ m_1 & m_2 & m_3 \end{pmatrix}

    INPUT:

    -  ``l_1``, ``l_2``, ``l_3``, ``m_1``, ``m_2``, ``m_3`` - integer

    -  ``prec`` - precision, default: ``None``. Providing a precision can
       drastically speed up the calculation.

    OUTPUT:

    Rational number times the square root of a rational number
    (if ``prec=None``), or real number if a precision is given.

    EXAMPLES::

        sage: gaunt(1,0,1,1,0,-1)
        -1/2/sqrt(pi)
        sage: gaunt(1,0,1,1,0,0)
        0
        sage: gaunt(29,29,34,10,-5,-5)
        1821867940156/215552371055153321*sqrt(22134)/sqrt(pi)
        sage: gaunt(20,20,40,1,-1,0)
        28384503878959800/74029560764440771/sqrt(pi)
        sage: gaunt(12,15,5,2,3,-5)
        91/124062*sqrt(36890)/sqrt(pi)
        sage: gaunt(10,10,12,9,3,-12)
        -98/62031*sqrt(6279)/sqrt(pi)
        sage: gaunt(1000,1000,1200,9,3,-12).n(64)
        0.00689500421922113448

    If the sum of the `l_i` is odd, the answer is zero, even for Python
    ints (see :trac:`14766`)::

        sage: gaunt(1,2,2,1,0,-1)
        0
        sage: gaunt(int(1),int(2),int(2),1,0,-1)
        0

    It is an error to use non-integer values for `l` or `m`::

        sage: gaunt(1.2,0,1.2,0,0,0)
        Traceback (most recent call last):
        ...
        TypeError: Attempt to coerce non-integral RealNumber to Integer
        sage: gaunt(1,0,1,1.1,0,-1.1)
        Traceback (most recent call last):
        ...
        TypeError: Attempt to coerce non-integral RealNumber to Integer

    NOTES:

    The Gaunt coefficient obeys the following symmetry rules:

    - invariant under any permutation of the columns

      .. MATH::

          Y(l_1,l_2,l_3,m_1,m_2,m_3)
          =Y(l_3,l_1,l_2,m_3,m_1,m_2) \hspace{3em} \\ \hspace{3em}
          =Y(l_2,l_3,l_1,m_2,m_3,m_1)
          =Y(l_3,l_2,l_1,m_3,m_2,m_1) \\ \hspace{3em}
          =Y(l_1,l_3,l_2,m_1,m_3,m_2)
          =Y(l_2,l_1,l_3,m_2,m_1,m_3)

    - invariant under space inflection, i.e.

      .. MATH::

          Y(l_1,l_2,l_3,m_1,m_2,m_3)
          =Y(l_1,l_2,l_3,-m_1,-m_2,-m_3)

    - symmetric with respect to the 72 Regge symmetries as inherited
      for the 3-`j` symbols [Reg1958]_

    - zero for `l_1`, `l_2`, `l_3` not fulfilling triangle relation

    - zero for violating any one of the conditions: `l_1 \ge |m_1|`,
      `l_2 \ge |m_2|`, `l_3 \ge |m_3|`

    - non-zero only for an even sum of the `l_i`, i.e.
      `J=l_1+l_2+l_3=2n` for `n` in `\Bold{N}`

    ALGORITHM:

    This function uses the algorithm of [LdB1982]_ to
    calculate the value of the Gaunt coefficient exactly. Note that
    the formula contains alternating sums over large factorials and is
    therefore unsuitable for finite precision arithmetic and only
    useful for a computer algebra system [RH2003]_.

    AUTHORS:

    - Jens Rasch (2009-03-24): initial version for Sage
    """
    l_1 = Integer(l_1)
    l_2 = Integer(l_2)
    l_3 = Integer(l_3)
    m_1 = Integer(m_1)
    m_2 = Integer(m_2)
    m_3 = Integer(m_3)

    bigL = (l_1 + l_2 + l_3) / 2
    a1 = l_1 + l_2 - l_3
    if a1 < 0:
        return 0
    a2 = l_1 - l_2 + l_3
    if a2 < 0:
        return 0
    a3 = -l_1 + l_2 + l_3
    if a3 < 0:
        return 0
    if Mod(2 * bigL, 2) != 0:
        return 0
    if (m_1 + m_2 + m_3) != 0:
        return 0
    if (abs(m_1) > l_1) or (abs(m_2) > l_2) or (abs(m_3) > l_3):
        return 0

    imin = max(-l_3 + l_1 + m_2, -l_3 + l_2 - m_1, 0)
    imax = min(l_2 + m_2, l_1 - m_1, l_1 + l_2 - l_3)

    maxfact = max(l_1 + l_2 + l_3 + 1, imax + 1)
    _calc_factlist(maxfact)

    argsqrt = (2 * l_1 + 1) * (2 * l_2 + 1) * (2 * l_3 + 1) * \
        _Factlist[l_1 - m_1] * _Factlist[l_1 + m_1] * _Factlist[l_2 - m_2] * \
        _Factlist[l_2 + m_2] * _Factlist[l_3 - m_3] * _Factlist[l_3 + m_3] / \
        (4*pi)
    ressqrt = argsqrt.sqrt()

    prefac = Integer(_Factlist[bigL] * _Factlist[l_2 - l_1 + l_3] * \
                     _Factlist[l_1 - l_2 + l_3] * _Factlist[l_1 + l_2 - l_3])/ \
                     _Factlist[2 * bigL+1]/ \
                     (_Factlist[bigL - l_1] * _Factlist[bigL - l_2] * _Factlist[bigL - l_3])

    sumres = 0
    for ii in range(imin, imax + 1):
        den = _Factlist[ii] * _Factlist[ii + l_3 - l_1 - m_2] * \
            _Factlist[l_2 + m_2 - ii] * _Factlist[l_1 - ii - m_1] * \
            _Factlist[ii + l_3 - l_2 + m_1] * _Factlist[l_1 + l_2 - l_3 - ii]
        sumres = sumres + Integer((-1)**ii) / den

    res = ressqrt * prefac * sumres * (-1)**(bigL + l_3 + m_1 - m_2)
    if prec is not None:
        res = res.n(prec)
    return res
Ejemplo n.º 31
0
def wigner_3j(j_1, j_2, j_3, m_1, m_2, m_3, prec=None):
    r"""
    Calculate the Wigner 3-`j` symbol `\begin{pmatrix} j_1 & j_2 & j_3 \\ m_1 & m_2 & m_3 \end{pmatrix}`.

    INPUT:

    -  ``j_1``, ``j_2``, ``j_3``, ``m_1``, ``m_2``, ``m_3`` - integer or half integer

    -  ``prec`` - precision, default: ``None``. Providing a precision can
       drastically speed up the calculation.

    OUTPUT:

    Rational number times the square root of a rational number
    (if ``prec=None``), or real number if a precision is given.

    EXAMPLES::

        sage: wigner_3j(2, 6, 4, 0, 0, 0)
        sqrt(5/143)
        sage: wigner_3j(2, 6, 4, 0, 0, 1)
        0
        sage: wigner_3j(0.5, 0.5, 1, 0.5, -0.5, 0)
        sqrt(1/6)
        sage: wigner_3j(40, 100, 60, -10, 60, -50)
        95608/18702538494885*sqrt(21082735836735314343364163310/220491455010479533763)
        sage: wigner_3j(2500, 2500, 5000, 2488, 2400, -4888, prec=64)
        7.60424456883448589e-12

    It is an error to have arguments that are not integer or half
    integer values::

        sage: wigner_3j(2.1, 6, 4, 0, 0, 0)
        Traceback (most recent call last):
        ...
        ValueError: j values must be integer or half integer
        sage: wigner_3j(2, 6, 4, 1, 0, -1.1)
        Traceback (most recent call last):
        ...
        ValueError: m values must be integer or half integer

    NOTES:

    The Wigner 3-`j` symbol obeys the following symmetry rules:

    - invariant under any permutation of the columns (with the
      exception of a sign change where `J=j_1+j_2+j_3`):

      .. MATH::

         \begin{pmatrix} j_1 & j_2 & j_3 \\ m_1 & m_2 & m_3 \end{pmatrix}
          =\begin{pmatrix} j_3 & j_1 & j_2 \\ m_3 & m_1 & m_2 \end{pmatrix}
          =\begin{pmatrix} j_2 & j_3 & j_1 \\ m_2 & m_3 & m_1 \end{pmatrix} \hspace{10em} \\
          =(-1)^J \begin{pmatrix} j_3 & j_2 & j_1 \\ m_3 & m_2 & m_1 \end{pmatrix}
          =(-1)^J \begin{pmatrix} j_1 & j_3 & j_2 \\ m_1 & m_3 & m_2 \end{pmatrix}
          =(-1)^J \begin{pmatrix} j_2 & j_1 & j_3 \\ m_2 & m_1 & m_3 \end{pmatrix}

    - invariant under space inflection, i.e.

      .. MATH::

         \begin{pmatrix} j_1 & j_2 & j_3 \\ m_1 & m_2 & m_3 \end{pmatrix}
         =(-1)^J \begin{pmatrix} j_1 & j_2 & j_3 \\ -m_1 & -m_2 & -m_3 \end{pmatrix}

    - symmetric with respect to the 72 additional symmetries based on
      the work by [Reg1958]_

    - zero for `j_1`, `j_2`, `j_3` not fulfilling triangle relation

    - zero for `m_1 + m_2 + m_3 \neq 0`

    - zero for violating any one of the conditions
      `j_1 \ge |m_1|`,  `j_2 \ge |m_2|`,  `j_3 \ge |m_3|`

    ALGORITHM:

    This function uses the algorithm of [Ed1974]_ to calculate the
    value of the 3-`j` symbol exactly. Note that the formula contains
    alternating sums over large factorials and is therefore unsuitable
    for finite precision arithmetic and only useful for a computer
    algebra system [RH2003]_.

    AUTHORS:

    - Jens Rasch (2009-03-24): initial version
    """
    if int(j_1 * 2) != j_1 * 2 or int(j_2 * 2) != j_2 * 2 or \
            int(j_3 * 2) != j_3 * 2:
        raise ValueError("j values must be integer or half integer")
    if int(m_1 * 2) != m_1 * 2 or int(m_2 * 2) != m_2 * 2 or \
            int(m_3 * 2) != m_3 * 2:
        raise ValueError("m values must be integer or half integer")
    if m_1 + m_2 + m_3 != 0:
        return 0
    prefid = Integer((-1)**int(j_1 - j_2 - m_3))
    m_3 = -m_3
    a1 = j_1 + j_2 - j_3
    if a1 < 0:
        return 0
    a2 = j_1 - j_2 + j_3
    if a2 < 0:
        return 0
    a3 = -j_1 + j_2 + j_3
    if a3 < 0:
        return 0
    if (abs(m_1) > j_1) or (abs(m_2) > j_2) or (abs(m_3) > j_3):
        return 0

    maxfact = max(j_1 + j_2 + j_3 + 1, j_1 + abs(m_1), j_2 + abs(m_2), \
                  j_3 + abs(m_3))
    _calc_factlist(maxfact)

    argsqrt = Integer(_Factlist[int(j_1 + j_2 - j_3)] * \
                          _Factlist[int(j_1 - j_2 + j_3)] * \
                          _Factlist[int(-j_1 + j_2 + j_3)] * \
                          _Factlist[int(j_1 - m_1)] * \
                          _Factlist[int(j_1 + m_1)] * \
                          _Factlist[int(j_2 - m_2)] * \
                          _Factlist[int(j_2 + m_2)] * \
                          _Factlist[int(j_3 - m_3)] * \
                          _Factlist[int(j_3 + m_3)]) / \
                          _Factlist[int(j_1 + j_2 + j_3 + 1)]

    ressqrt = argsqrt.sqrt(prec)
    if isinstance(ressqrt, ComplexNumber):
        ressqrt = ressqrt.real()

    imin = int(max(-j_3 + j_1 + m_2, -j_3 + j_2 - m_1, 0))
    imax = int(min(j_2 + m_2, j_1 - m_1, j_1 + j_2 - j_3))
    sumres = 0
    for ii in range(imin, imax + 1):
        den = _Factlist[ii] * \
            _Factlist[int(ii + j_3 - j_1 - m_2)] * \
            _Factlist[int(j_2 + m_2 - ii)] * \
            _Factlist[int(j_1 - ii - m_1)] * \
            _Factlist[int(ii + j_3 - j_2 + m_1)] * \
            _Factlist[int(j_1 + j_2 - j_3 - ii)]
        sumres = sumres + Integer((-1)**ii) / den

    res = ressqrt * sumres * prefid
    return res
Ejemplo n.º 32
0
def are_hyperplanes_in_projective_geometry_parameters(v, k, lmbda, return_parameters=False):
    r"""
    Return ``True`` if the parameters ``(v,k,lmbda)`` are the one of hyperplanes in
    a (finite Desarguesian) projective space.

    In other words, test whether there exists a prime power ``q`` and an integer
    ``d`` greater than two such that:

    - `v = (q^{d+1}-1)/(q-1) = q^d + q^{d-1} + ... + 1`
    - `k = (q^d - 1)/(q-1) = q^{d-1} + q^{d-2} + ... + 1`
    - `lmbda = (q^{d-1}-1)/(q-1) = q^{d-2} + q^{d-3} + ... + 1`

    If it exists, such a pair ``(q,d)`` is unique.

    INPUT:

    - ``v,k,lmbda`` (integers)

    OUTPUT:

    - a boolean or, if ``return_parameters`` is set to ``True`` a pair
      ``(True, (q,d))`` or ``(False, (None,None))``.

    EXAMPLES::

        sage: from sage.combinat.designs.block_design import are_hyperplanes_in_projective_geometry_parameters
        sage: are_hyperplanes_in_projective_geometry_parameters(40,13,4)
        True
        sage: are_hyperplanes_in_projective_geometry_parameters(40,13,4,return_parameters=True)
        (True, (3, 3))
        sage: PG = designs.ProjectiveGeometryDesign(3,2,GF(3))
        sage: PG.is_t_design(return_parameters=True)
        (True, (2, 40, 13, 4))

        sage: are_hyperplanes_in_projective_geometry_parameters(15,3,1)
        False
        sage: are_hyperplanes_in_projective_geometry_parameters(15,3,1,return_parameters=True)
        (False, (None, None))

    TESTS::

        sage: sgp = lambda q,d: ((q**(d+1)-1)//(q-1), (q**d-1)//(q-1), (q**(d-1)-1)//(q-1))
        sage: for q in [3,4,5,7,8,9,11]:
        ....:     for d in [2,3,4,5]:
        ....:         v,k,l = sgp(q,d)
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l,True) == (True, (q,d))
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v+1,k,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v-1,k,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k+1,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k-1,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l+1) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l-1) is False
    """
    import sage.arith.all as arith

    q1 = Integer(v - k)
    q2 = Integer(k - lmbda)

    if (lmbda <= 0 or q1 < 4 or q2 < 2 or
        not q1.is_prime_power() or
        not q2.is_prime_power()):
        return (False,(None,None)) if return_parameters else False

    p1,e1 = q1.factor()[0]
    p2,e2 = q2.factor()[0]

    k = arith.gcd(e1,e2)
    d = e1//k
    q = p1**k
    if e2//k != d-1 or lmbda != (q**(d-1)-1)//(q-1):
        return (False,(None,None)) if return_parameters else False

    return (True, (q,d)) if return_parameters else True
    def RandomPoset(n, p):
        r"""
        Generate a random poset on ``n`` vertices according to a
        probability ``p``.

        INPUT:

        - ``n`` - number of vertices, a non-negative integer

        - ``p`` - a probability, a real number between 0 and 1 (inclusive)

        OUTPUT:

        A poset on ``n`` vertices.  The construction decides to make an
        ordered pair of vertices comparable in the poset with probability
        ``p``, however a pair is not made comparable if it would violate
        the defining properties of a poset, such as transitivity.

        So in practice, once the probability exceeds a small number the
        generated posets may be very similar to a chain.  So to create
        interesting examples, keep the probability small, perhaps on the
        order of `1/n`.

        EXAMPLES::

            sage: Posets.RandomPoset(17,.15)
            Finite poset containing 17 elements

        TESTS::

            sage: Posets.RandomPoset('junk', 0.5)
            Traceback (most recent call last):
            ...
            TypeError: number of elements must be an integer, not junk

            sage: Posets.RandomPoset(-6, 0.5)
            Traceback (most recent call last):
            ...
            ValueError: number of elements must be non-negative, not -6

            sage: Posets.RandomPoset(6, 'garbage')
            Traceback (most recent call last):
            ...
            TypeError: probability must be a real number, not garbage

            sage: Posets.RandomPoset(6, -0.5)
            Traceback (most recent call last):
            ...
            ValueError: probability must be between 0 and 1, not -0.5
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        try:
            p = float(p)
        except Exception:
            raise TypeError(
                "probability must be a real number, not {0}".format(p))
        if p < 0 or p > 1:
            raise ValueError(
                "probability must be between 0 and 1, not {0}".format(p))

        D = DiGraph(loops=False, multiedges=False)
        D.add_vertices(range(n))
        for i in range(n):
            for j in range(n):
                if random.random() < p:
                    D.add_edge(i, j)
                    if not D.is_directed_acyclic():
                        D.delete_edge(i, j)
        return Poset(D, cover_relations=False)
Ejemplo n.º 34
0
def discrete_log_rho(a, base, ord=None, operation='*', hash_function=hash):
    """
    Pollard Rho algorithm for computing discrete logarithm in cyclic
    group of prime order.
    If the group order is very small it falls back to the baby step giant step
    algorithm.

    INPUT:

    - ``a`` -- a group element
    - ``base`` -- a group element
    - ``ord`` -- the order of ``base`` or ``None``, in this case we try
      to compute it
    - ``operation`` -- a string (default: ``'*'``) denoting whether we
      are in an additive group or a multiplicative one
    - ``hash_function`` -- having an efficient hash function is critical
      for this algorithm (see examples)

    OUTPUT: an integer `n` such that `a = base^n` (or `a = n*base`)

    ALGORITHM: Pollard rho for discrete logarithm, adapted from the
    article of Edlyn Teske, 'A space efficient algorithm for group
    structure computation'.

    EXAMPLES::

        sage: F.<a> = GF(2^13)
        sage: g = F.gen()
        sage: discrete_log_rho(g^1234, g)
        1234

        sage: F.<a> = GF(37^5)
        sage: E = EllipticCurve(F, [1,1])
        sage: G = (3*31*2^4)*E.lift_x(a)
        sage: discrete_log_rho(12345*G, G, ord=46591, operation='+')
        12345

    It also works with matrices::

        sage: A = matrix(GF(50021),[[10577,23999,28893],[14601,41019,30188],[3081,736,27092]])
        sage: discrete_log_rho(A^1234567, A)
        1234567

    Beware, the order must be prime::

        sage: I = IntegerModRing(171980)
        sage: discrete_log_rho(I(2), I(3))
        Traceback (most recent call last):
        ...
        ValueError: for Pollard rho algorithm the order of the group must be prime

    If it fails to find a suitable logarithm, it raises a ``ValueError``::

        sage: I = IntegerModRing(171980)
        sage: discrete_log_rho(I(31002),I(15501))
        Traceback (most recent call last):
        ...
        ValueError: Pollard rho algorithm failed to find a logarithm

    The main limitation on the hash function is that we don't want to have
    `hash(x*y) = hash(x) + hash(y)`::

        sage: I = IntegerModRing(next_prime(2^23))
        sage: def test():
        ....:     try:
        ....:          discrete_log_rho(I(123456),I(1),operation='+')
        ....:     except Exception:
        ....:          print "FAILURE"
        sage: test()  # random failure
        FAILURE

    If this happens, we can provide a better hash function::

        sage: discrete_log_rho(I(123456),I(1),operation='+', hash_function=lambda x: hash(x*x))
        123456

    AUTHOR:

    - Yann Laigle-Chapuy (2009-09-05)

    """
    from sage.rings.integer import Integer
    from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
    from operator import mul, add, pow

    # should be reasonable choices
    partition_size = 20
    memory_size = 4

    if operation in addition_names:
        mult = add
        power = mul
        if ord is None:
            ord = base.additive_order()
    elif operation in multiplication_names:
        mult = mul
        power = pow
        if ord is None:
            ord = base.multiplicative_order()
    else:
        raise ValueError

    ord = Integer(ord)

    if not ord.is_prime():
        raise ValueError(
            "for Pollard rho algorithm the order of the group must be prime")

    # check if we need to set immutable before hashing
    mut = hasattr(base, 'set_immutable')

    isqrtord = ord.isqrt()

    if isqrtord < partition_size:  #setup to costly, use bsgs
        return bsgs(base, a, bounds=(0, ord), operation=operation)

    reset_bound = 8 * isqrtord  # we take some margin

    I = IntegerModRing(ord)

    for s in xrange(10):  # to avoid infinite loops
        # random walk function setup
        m = [I.random_element() for i in xrange(partition_size)]
        n = [I.random_element() for i in xrange(partition_size)]
        M = [
            mult(power(base, Integer(m[i])), power(a, Integer(n[i])))
            for i in xrange(partition_size)
        ]

        ax = I.random_element()
        x = power(base, Integer(ax))
        if mut:
            x.set_immutable()

        bx = I(0)

        sigma = [(0, None)] * memory_size
        H = {}  # memory
        i0 = 0
        nextsigma = 0
        for i in xrange(reset_bound):
            #random walk, we need an efficient hash
            s = hash_function(x) % partition_size
            (x, ax, bx) = (mult(M[s], x), ax + m[s], bx + n[s])
            if mut:
                x.set_immutable()
            # look for collisions
            if x in H:
                ay, by = H[x]
                if bx == by:
                    break
                else:
                    res = sage.rings.integer.Integer((ay - ax) / (bx - by))
                    if power(base, res) == a:
                        return res
                    else:
                        break
            # should we remember this value?
            elif i >= nextsigma:
                if sigma[i0][1] is not None:
                    H.pop(sigma[i0][1])
                sigma[i0] = (i, x)
                i0 = (i0 + 1) % memory_size
                nextsigma = 3 * sigma[i0][0]  #3 seems a good choice
                H[x] = (ax, bx)

    raise ValueError("Pollard rho algorithm failed to find a logarithm")
Ejemplo n.º 35
0
def count(arg,
          ehrhart_polynomial=False,
          multivariate_generating_function=False,
          raw_output=False,
          verbose=False,
          **kwds):
    r"""
    Call to the program count from LattE integrale

    INPUT:

    - ``arg`` -- a cdd or LattE description string

    - ``ehrhart_polynomial``, ``multivariate_generating_function``  -- to
      compute Ehrhart polynomial or multivariate generating function instead of
      just counting points

    - ``raw_output`` -- if ``True`` then return directly the output string from LattE

    - For all other options of the count program, consult the LattE manual

    OUTPUT:

    Either a string (if ``raw_output`` if set to ``True``) or an integer (when
    counting points), or a polynomial (if ``ehrhart_polynomial`` is set to
    ``True``) or a multivariate THING (if ``multivariate_generating_function``
    is set to ``True``)

    EXAMPLES::

        sage: from sage.interfaces.latte import count    # optional - latte_int
        sage: P = 2 * polytopes.cube()

    Counting integer points from either the H or V representation::

        sage: count(P.cdd_Hrepresentation(), cdd=True)   # optional - latte_int
        125
        sage: count(P.cdd_Vrepresentation(), cdd=True)   # optional - latte_int
        125

    Ehrhart polynomial::

        sage: count(P.cdd_Hrepresentation(), cdd=True, ehrhart_polynomial=True)  # optional - latte_int
        64*t^3 + 48*t^2 + 12*t + 1

    Multivariate generating function currently only work with ``raw_output=True``::

        sage: opts = {'cdd': True,
        ....:         'multivariate_generating_function': True,
        ....:         'raw_output': True}
        sage: cddin = P.cdd_Hrepresentation()
        sage: print(count(cddin, **opts))  # optional - latte_int
        x[0]^2*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]))
         + x[0]^2*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[2]^(-1))*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0])*(1-x[2]^(-1)))
         + x[0]^2*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[1]^(-1))*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0])*(1-x[1]^(-1)))
         + x[0]^2*x[1]^2*x[2]^2/((1-x[2]^(-1))*(1-x[1]^(-1))*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^2/((1-x[0])*(1-x[2]^(-1))*(1-x[1]^(-1)))

    TESTS:

    Testing raw output::

        sage: from sage.interfaces.latte import count   # optional - latte_int
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: count(cddin, cdd=True, raw_output=True)  # optional - latte_int
        '19'
        sage: count(cddin, cdd=True, raw_output=True, ehrhart_polynomial=True) # optional - latte_int
        ' + 1 * t^0 + 10/3 * t^1 + 8 * t^2 + 20/3 * t^3'
        sage: count(cddin, cdd=True, raw_output=True, multivariate_generating_function=True) # optional - latte_int
        'x[0]^(-1)*x[1]^(-1)/((1-x[0]*x[2])*(1-x[0]^(-1)*x[1])*...x[0]^(-1)*x[2]^(-1)))\n'

    Testing the ``verbose`` option::

        sage: n = count(cddin, cdd=True, verbose=True, raw_output=True)  # optional - latte_int
        This is LattE integrale ...
        ...
        Invocation: count '--redundancy-check=none' --cdd /dev/stdin
        ...
        Total Unimodular Cones: ...
        Maximum number of simplicial cones in memory at once: ...
        <BLANKLINE>
        ****  The number of lattice points is:   ****
        Total time: ... sec

    Trivial input for which LattE's preprocessor does all the work::

        sage: P = Polyhedron(vertices=[[0,0,0]])
        sage: cddin = P.cdd_Hrepresentation()
        sage: count(cddin, cdd=True, raw_output=False)  # optional - latte_int
        1

    """
    # Check that LattE is present
    Latte().require()

    arg = str_to_bytes(arg)

    args = ['count']
    if ehrhart_polynomial and multivariate_generating_function:
        raise ValueError
    if ehrhart_polynomial:
        args.append('--ehrhart-polynomial')
    elif multivariate_generating_function:
        args.append('--multivariate-generating-function')

    if 'redundancy_check' not in kwds:
        args.append('--redundancy-check=none')

    for key, value in kwds.items():
        if value is None or value is False:
            continue

        key = key.replace('_', '-')
        if value is True:
            args.append('--{}'.format(key))
        else:
            args.append('--{}={}'.format(key, value))

    if multivariate_generating_function:
        from sage.misc.temporary_file import tmp_filename
        filename = tmp_filename()
        with open(filename, 'w') as f:
            f.write(bytes_to_str(arg))
        args += [filename]
    else:
        args += ['/dev/stdin']

    # The cwd argument is needed because latte
    # always produces diagnostic output files.
    latte_proc = Popen(args,
                       stdin=PIPE,
                       stdout=PIPE,
                       stderr=(None if verbose else PIPE),
                       cwd=str(SAGE_TMP))

    ans, err = latte_proc.communicate(arg)
    if err:
        err = bytes_to_str(err)
    ret_code = latte_proc.poll()
    if ret_code:
        if err is None:
            err = ", see error message above"
        else:
            err = ":\n" + err
        raise RuntimeError(
            "LattE integrale program failed (exit code {})".format(ret_code) +
            err.strip())

    ans = bytes_to_str(ans)

    if ehrhart_polynomial:
        ans = ans.splitlines()[-2]
        if raw_output:
            return ans
        else:
            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            from sage.rings.rational_field import QQ
            R = PolynomialRing(QQ, 't')
            return R(ans)
    elif multivariate_generating_function:
        with open(filename + '.rat') as f:
            ans = f.read()
        if raw_output:
            return ans
        else:
            raise NotImplementedError(
                "there is no Sage object to handle multivariate series from LattE, use raw_output=True"
            )
    else:
        if ans:  # Sometimes (when LattE's preproc does the work), no output appears on stdout.
            ans = ans.splitlines()[-1]
        if not ans:
            # opening a file is slow (30e-6s), so we read the file
            # numOfLatticePoints only in case of a IndexError above
            with open(SAGE_TMP + '/numOfLatticePoints', 'r') as f:
                ans = f.read()

        if raw_output:
            return ans
        else:
            return Integer(ans)
Ejemplo n.º 36
0
from sage.modular.modsym.all import ModularSymbols
from sage.libs.cremona.newforms import ECModularSymbol
from sage.databases.cremona import parse_cremona_label

from sage.rings.arith import next_prime, kronecker_symbol, prime_divisors, valuation
from sage.rings.infinity import unsigned_infinity as infinity
from sage.rings.integer import Integer
from sage.modular.cusps import Cusps
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.misc.all import verbose

from sage.schemes.elliptic_curves.constructor import EllipticCurve

oo = Cusps(infinity)
zero = Integer(0)


def modular_symbol_space(E, sign, base_ring, bound=None):
    r"""
    Creates the space of modular symbols of a given sign over a give base_ring,
    attached to the isogeny class of elliptic curves.
    
    INPUT:
    
     - ``E`` - an elliptic curve over `\QQ`
     - ``sign`` - integer, -1, 0, or 1
     - ``base_ring`` - ring
     - ``bound`` - (default: None) maximum number of Hecke operators to
       use to cut out modular symbols factor.  If None, use
       enough to provably get the correct answer.
Ejemplo n.º 37
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError(
                    "the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]

                # The following is a temporary solution that allows us
                # to construct compatible systems of finite fields
                # until algebraic closures of finite fields are
                # implemented in Sage.  It requires the user to
                # specify two parameters:
                #
                # - `conway` -- boolean; if True, this field is
                #   constructed to fit in a compatible system using
                #   a Conway polynomial.
                # - `prefix` -- a string used to generate names for
                #   automatically constructed finite fields
                #
                # See the docstring of FiniteFieldFactory for examples.
                #
                # Once algebraic closures of finite fields are
                # implemented, this syntax should be superseded by
                # something like the following:
                #
                #     sage: Fpbar = GF(5).algebraic_closure('z')
                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
                #     sage: F
                #     Finite field in z3 of size 5^3
                #
                # This temporary solution only uses actual Conway
                # polynomials (no pseudo-Conway polynomials), since
                # pseudo-Conway polynomials are not unique, and until
                # we have algebraic closures of finite fields, there
                # is no good place to store a specific choice of
                # pseudo-Conway polynomials.
                if name is None:
                    if not ('conway' in kwds and kwds['conway']):
                        raise ValueError(
                            "parameter 'conway' is required if no name given")
                    if 'prefix' not in kwds:
                        raise ValueError(
                            "parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if 'conway' in kwds and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if 'prefix' not in kwds:
                        raise ValueError(
                            "a prefix must be specified if conway=True")
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if conway=True")
                    # The following raises a RuntimeError if no polynomial is found.
                    modulus = conway_polynomial(p, n)

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":
                        from sage.misc.superseded import deprecation
                        deprecation(
                            16983,
                            "the modulus 'default' is deprecated, use modulus=None instead (which is the default)"
                        )
                        modulus = None
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Ejemplo n.º 38
0
def BraidGroup(n=None, names='s'):
    """
    Construct a Braid Group

    INPUT:

    - ``n`` -- integer or ``None`` (default). The number of
      strands. If not specified the ``names`` are counted and the
      group is assumed to have one more strand than generators.

    - ``names`` -- string or list/tuple/iterable of strings (default:
      ``'x'``). The generator names or name prefix.

    EXAMPLES::

        sage: B.<a,b> = BraidGroup();  B
        Braid group on 3 strands
        sage: H = BraidGroup('a, b')
        sage: B is H
        True
        sage: BraidGroup(3)
        Braid group on 3 strands

    The entry can be either a string with the names of the generators,
    or the number of generators and the prefix of the names to be
    given. The default prefix is ``'s'`` ::

        sage: B=BraidGroup(3); B.generators()
        (s0, s1)
        sage: BraidGroup(3, 'g').generators()
        (g0, g1)

    Since the word problem for the braid groups is solvable, their Cayley graph
    can be localy obtained as follows (see :trac:`16059`)::

        sage: def ball(group, radius):
        ....:     ret = set()
        ....:     ret.add(group.one())
        ....:     for length in range(1, radius):
        ....:         for w in Words(alphabet=group.gens(), length=length):
        ....:              ret.add(prod(w))
        ....:     return ret
        sage: B = BraidGroup(4)
        sage: GB = B.cayley_graph(elements=ball(B, 4), generators=B.gens()); GB
        Digraph on 31 vertices

    Since the braid group has nontrivial relations, this graph contains less
    vertices than the one associated to the free group (which is a tree)::

        sage: F = FreeGroup(3)
        sage: GF = F.cayley_graph(elements=ball(F, 4), generators=F.gens()); GF
        Digraph on 40 vertices

    TESTS::

        sage: G1 = BraidGroup(3, 'a,b')
        sage: G2 = BraidGroup('a,b')
        sage: G3.<a,b> = BraidGroup()
        sage: G1 is G2, G2 is G3
        (True, True)
    """
    # Support Freegroup('a,b') syntax
    if n is not None:
        try:
            n = Integer(n) - 1
        except TypeError:
            names = n
            n = None
    # derive n from counting names
    if n is None:
        if isinstance(names, basestring):
            n = len(names.split(','))
        else:
            names = list(names)
            n = len(names)
    from sage.structure.parent import normalize_names
    names = tuple(normalize_names(n, names))
    return BraidGroup_class(names)
Ejemplo n.º 39
0
    def symmetrisation(self,
                       N=None,
                       tailreduce=False,
                       report=None,
                       use_full_group=False):
        """
        Apply permutations to the generators of self and interreduce

        INPUT:

        - ``N`` -- (integer, default ``None``) Apply permutations in
          `Sym(N)`. If it is not given then it will be replaced by the
          maximal variable index occurring in the generators of
          ``self.interreduction().squeezed()``.
        - ``tailreduce`` -- (bool, default ``False``) If ``True``, perform
          tail reductions.
        - ``report`` -- (object, default ``None``) If not ``None``, report
          on the progress of computations.
        - ``use_full_group`` (optional) -- If True, apply *all* elements of
          `Sym(N)` to the generators of self (this is what [AB2008]_
          originally suggests). The default is to apply all elementary
          transpositions to the generators of ``self.squeezed()``,
          interreduce, and repeat until the result stabilises, which is
          often much faster than applying all of `Sym(N)`, and we are
          convinced that both methods yield the same result.

        OUTPUT:

        A symmetrically interreduced symmetric ideal with respect to
        which any `Sym(N)`-translate of a generator of self is
        symmetrically reducible, where by default ``N`` is the maximal
        variable index that occurs in the generators of
        ``self.interreduction().squeezed()``.

        NOTE:

        If ``I`` is a symmetric ideal whose generators are monomials,
        then ``I.symmetrisation()`` is its reduced Groebner basis.  It
        should be noted that without symmetrisation, monomial
        generators, in general, do not form a Groebner basis.

        EXAMPLES::

            sage: X.<x> = InfinitePolynomialRing(QQ)
            sage: I = X*(x[1]+x[2], x[1]*x[2])
            sage: I.symmetrisation()
            Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field
            sage: I.symmetrisation(N=3)
            Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field
            sage: I.symmetrisation(N=3, use_full_group=True)
            Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field

        """
        newOUT = self.interreduction(tailreduce=tailreduce,
                                     report=report).squeezed()
        R = self.ring()
        OUT = R * ()
        if N is None:
            N = max([Y.max_index() for Y in newOUT.gens()] + [1])
        else:
            N = Integer(N)
        if hasattr(R, '_max') and R._max < N:
            R.gen()[N]
        if report is not None:
            print("Symmetrise %d polynomials at level %d" %
                  (len(newOUT.gens()), N))
        if use_full_group:
            from sage.combinat.permutation import Permutations
            NewGens = []
            Gens = self.gens()
            for P in Permutations(N):
                NewGens.extend([p**P for p in Gens])
            return (NewGens * R).interreduction(tailreduce=tailreduce,
                                                report=report)
        from sage.combinat.permutation import Permutation
        from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy
        RStrat = SymmetricReductionStrategy(self.ring(),
                                            OUT.gens(),
                                            tailreduce=tailreduce)
        while (OUT != newOUT):
            OUT = newOUT
            PermutedGens = list(OUT.gens())
            if not (report is None):
                print("Apply permutations")
            for i in range(1, N):
                for j in range(i + 1, N + 1):
                    P = Permutation(((i, j)))
                    for X in OUT.gens():
                        p = RStrat.reduce(X**P, report=report)
                        if p._p != 0:
                            PermutedGens.append(p)
                            RStrat.add_generator(p, good_input=True)
            newOUT = (PermutedGens * R).interreduction(tailreduce=tailreduce,
                                                       report=report)
        return OUT
Ejemplo n.º 40
0
    def _name_maker(self, names):
        r"""
        Helper function to create names of elements of algebraic structures.

        INPUT:
        Identical to the input for :class:`OperationTable` and :meth:`change_names`,
        so look there for details.

        OUTPUT:

        - ``width`` - an integer giving the maximum width of the strings
          describing the elements.  This is used for formatting the ASCII
          version of the table.
        - ``name_list`` - a list of strings naming the elements, in the
          same order as given by the :meth:`list` method.
        - ``name_dict`` - a dictionary giving the correspondence between the
          strings and the actual elements.  So the keys are the strings and
          the values are the elements of the structure.

        EXAMPLE:
        This routine is tested extensively in the :class:`OperationTable`
        and :meth:`change_names` methods.  So we just just demonstrate
        the nature of the output here. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=SymmetricGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: w, l, d = T._name_maker('letters')
            sage: w
            1
            sage: l[0]
            'a'
            sage: d['a']
            ()

        TESTS:
        We test the error conditions here, rather than as part of the
        doctests for the :class:`OperationTable` and :meth:`change_names`
        methods that rely on this one. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=AlternatingGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: T._name_maker(['x'])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must be the same size as the set, 1 != 3
            sage: T._name_maker(['x', 'y', 4])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must only contain strings, not 4
            sage: T._name_maker('blatzo')
            Traceback (most recent call last):
            ...
            ValueError: element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'
        """
        from sage.functions.log import log
        name_list = []
        if names == 'digits':
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n - 1, 10)) + 1
            for i in range(self._n):
                name_list.append('{0:0{1}d}'.format(i, width))
        elif names == 'letters':
            from string import ascii_lowercase as letters
            from sage.rings.integer import Integer
            base = len(letters)
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n - 1, base)) + 1
            for i in range(self._n):
                places = Integer(i).digits(base=base,
                                           digits=letters,
                                           padto=width)
                places.reverse()
                name_list.append(''.join(places))
        elif names == 'elements':
            width = 0
            for e in self._elts:
                estr = repr(e)
                if len(estr) > width:
                    width = len(estr)
                name_list.append(estr)
        elif isinstance(names, list):
            if len(names) != self._n:
                raise ValueError(
                    'list of element names must be the same size as the set, %s != %s'
                    % (len(names), self._n))
            width = 0
            for str in names:
                if not isinstance(str, basestring):
                    raise ValueError(
                        'list of element names must only contain strings, not %s'
                        % str)
                if len(str) > width:
                    width = len(str)
                name_list.append(str)
        else:
            raise ValueError(
                "element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'"
            )
        name_dict = {}
        for i in range(self._n):
            name_dict[name_list[i]] = self._elts[i]
        return width, name_list, name_dict
Ejemplo n.º 41
0
    def _parse_path_file(self, input_filename, verbose=False):
        """
        Takes a phpack output file containing path tracking information
        and parses it into a list of lists of dictionaries - i.e. a
        list of solutions paths, where each solution path is a list of
        dictionaries of variable and homotopy parameter values.

        INPUT:

        - input_filename -- file must have path-tracking information

        OUTPUT:

        - a list of lists of dictionaries, described above

        EXAMPLES::

            sage: from sage.interfaces.phc import *
            sage: R2.<x,y> = PolynomialRing(QQ,2)
            sage: start_sys = [x^5-y^2,y^5-1]
            sage: sol = phc.blackbox(start_sys, R2)    # optional -- phc
            sage: start_save = sol.save_as_start()     # optional -- phc
            sage: end_sys = [x^5-2,y^5-x^2]            # optional -- phc
            sage: path_track_filename = phc._path_track_file(start_save, end_sys, R2, c_skew = .001)  # optional -- phc
            sage: sol_paths = phc._parse_path_file(path_track_filename)   # optional -- phc
            sage: len(sol_paths)  # optional -- phc
            25
        """

        if not os.path.exists(input_filename):
            raise RuntimeError("The file containing output from phc (" +
                               input_filename + ") cannot be found")

        fh = open(input_filename)
        line_idx = 0
        begin = 0
        count = 0
        solutions_dicts = []
        steps_dicts = []

        # regular expressions for matching certain output types
        var_cnt_regex = re.compile('^ +([0-9]+)')
        output_regex = re.compile('^OUTPUT INFORMATION DURING')
        t_regex = re.compile(
            r'(^t +: +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+) +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+)$)',
            re.IGNORECASE)
        sols_regex = re.compile(
            r'(^ *(([a-z]|[0-9])+) +: +(-?[0-9]+\.[0-9]+E[-+][0-9]+) +(-?[0-9]+\.[0-9]+E[-+][0-9]+)$)',
            re.IGNORECASE)
        complete_regex = re.compile('^TIMING INFORMATION')

        breakfast = False
        a_line = fh.readline()
        end_test = ''
        while a_line:
            # processing....
            a_line = a_line.replace("\n", '')
            if line_idx == 0:
                m = var_cnt_regex.match(a_line)
                if m:
                    count = Integer(m.group(1))
            if count > 0:
                m = output_regex.match(a_line)
                if m:
                    begin = 1
                if begin:
                    m = t_regex.match(a_line)
                    if m:
                        # put the t-values into a dict
                        # m.group(2) contains the real val
                        # m.group(3) contains the imaginary val
                        # fh_w.write( "T=> G1(" + m.group(2) + '),G2(' + m.group(3) + ")\n")
                        # read off two lines - this should be 'm' and 'the solution for t :'
                        a_line = fh.readline()
                        end_test = a_line  # store this to check for end of solution
                        a_line = fh.readline()
                        t_val = CC(m.group(2), m.group(3))
                        temp_dict = {}
                        temp_dict["t"] = t_val
                        for i in range(0, count):
                            a_line = fh.readline()
                            m = sols_regex.match(a_line)
                            if m:
                                # m.group(2) contains our var name
                                # m.group(4) contains our real val
                                # m.group(5) contains our imaginary val
                                temp_dict[m.group(2)] = CC(
                                    m.group(4), m.group(5))
                        steps_dicts.append(temp_dict)
                    # check if its the end of a solution
                    if end_test.find('Length of path') != -1:
                        if verbose:
                            print("recording sol")
                        if steps_dicts != []:
                            solutions_dicts.append(steps_dicts)
                        steps_dicts = []
                    m = complete_regex.match(a_line)
                    if m:
                        breakfast = True
            if breakfast:
                break
            line_idx += 1
            a_line = fh.readline()
        fh.close()
        return solutions_dicts
Ejemplo n.º 42
0
    def shapley_value(self):
        r"""
        Return the Shapley value for ``self``.

        The Shapley value is the "fair" payoff vector and
        is computed by the following formula:

        .. MATH::

            \phi_i(G) = \sum_{S \subseteq \Omega} \sum_{p \in S}
            \frac{1}{|S|\binom{N}{|S|}}
            \bigl( v(S) - v(S \setminus \{p\}) \bigr).

        EXAMPLES:

        A typical example of computing the Shapley value::

            sage: integer_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2,): 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: integer_game = CooperativeGame(integer_function)
            sage: integer_game.player_list
            (1, 2, 3)
            sage: integer_game.shapley_value()
            {1: 2, 2: 5, 3: 35}

        A longer example of the Shapley value::

            sage: long_function = {(): 0,
            ....:                  (1,): 0,
            ....:                  (2,): 0,
            ....:                  (3,): 0,
            ....:                  (4,): 0,
            ....:                  (1, 2): 0,
            ....:                  (1, 3): 0,
            ....:                  (1, 4): 0,
            ....:                  (2, 3): 0,
            ....:                  (2, 4): 0,
            ....:                  (3, 4): 0,
            ....:                  (1, 2, 3): 0,
            ....:                  (1, 2, 4): 45,
            ....:                  (1, 3, 4): 40,
            ....:                  (2, 3, 4): 0,
            ....:                  (1, 2, 3, 4): 65}
            sage: long_game = CooperativeGame(long_function)
            sage: long_game.shapley_value()
            {1: 70/3, 2: 10, 3: 25/3, 4: 70/3}
        """
        payoff_vector = {}
        n = Integer(len(self.player_list))
        for player in self.player_list:
            weighted_contribution = 0
            for coalition in powerset(self.player_list):
                if coalition:  # If non-empty
                    k = Integer(len(coalition))
                    weight = 1 / (n.binomial(k) * k)
                    t = tuple(p for p in coalition if p != player)
                    weighted_contribution += weight * (
                        self.ch_f[tuple(coalition)] - self.ch_f[t])
            payoff_vector[player] = weighted_contribution

        return payoff_vector
Ejemplo n.º 43
0
    def __add__(self, Nelt):
        r"""
        Concatenate two ascii art object.

        By default, when two object are concatenated, the new one will be
        splittable between both.

        If the baseline is defined, the concatenation is computed such that the
        new baseline coincidate with the olders.

        For example, let `T` be a tree with it's baseline ascii art
        representation in the middle::

            o
             \
              o
             / \
            o   o

        and let `M` be a matrix with it's baseline ascii art representation at
        the middle two::

            [1 2 3]
            [4 5 6]
            [7 8 9]

        then the concatenation of both will give::

            o
             \   [1 2 3]
              o  [4 5 6]
             / \ [7 8 9]
            o   o

        If one of the objects has not baseline, the concatenation is realized
        from the top::

            o    [1 2 3]
             \   [4 5 6]
              o  [7 8 9]
             / \
            o   o

        TESTS::

            sage: from sage.misc.ascii_art import AsciiArt
            sage: l5 = AsciiArt(lines=['|' for _ in range(5)], baseline=2); l5
            |
            |
            |
            |
            |
            sage: l3 = AsciiArt(lines=['|' for _ in range(3)], baseline=1); l3
            |
            |
            |
            sage: l3 + l5
             |
            ||
            ||
            ||
             |
            sage: l5 + l3
            |
            ||
            ||
            ||
            |
            sage: l5._baseline = 0
            sage: l5 + l3
            |
            |
            |
            ||
            ||
             |
            sage: l5._baseline = 4
            sage: l5 + l3
             |
            ||
            ||
            |
            |
            |
            sage: l3._baseline = 0
            sage: l3 + l5
            |
            |
            ||
             |
             |
             |
             |
        """
        new_matrix = []
        new_h = AsciiArt._compute_new_h(self, Nelt)
        new_baseline = AsciiArt._compute_new_baseline(self, Nelt)

        if self._baseline != None and Nelt._baseline != None:
            # left traitement
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))

            if new_h > self._h:
                # |                 new_h > self._h
                # |                 new_baseline > self._baseline
                # ||<-- baseline    number of white lines at the bottom
                #  | }               :: Nelt._baseline - self._baseline
                #  | }
                if new_baseline > self._baseline:
                    for k in range(new_baseline - self._baseline):
                        new_matrix.append(" "**Integer(self._l))
                #  | }              new_h > self._h
                #  | }              new_h - new_baseline > self._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - self._h + self._baseline
                # ||
                #  |
                #  |
                if new_h - new_baseline > self._h - self._baseline:
                    for _ in range((new_h - new_baseline) -
                                   (self._h - self._baseline)):
                        new_matrix.insert(0, " "**Integer(self._l))

            # right traitement
            i = 0
            if new_h > Nelt._h:
                # |  }              new_h > Nelt._h
                # |  }              new_h - new_baseline > Nelt._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - Nelt._h + Nelt._baseline
                # ||
                # ||
                # |

                i = max(new_h - new_baseline - Nelt._h + Nelt._baseline, 0)

            for j in range(Nelt._h):
                new_matrix[i + j] += Nelt._matrix[j]
        else:
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))
            for i, line_i in enumerate(Nelt._matrix):
                if i == len(new_matrix):
                    new_matrix.append(" "**Integer(self._l) + line_i)
                else:
                    new_matrix[i] += line_i

        # breakpoint
        new_breakpoints = list(self._breakpoints)
        new_breakpoints.append(self._l)
        for bp in Nelt._breakpoints:
            new_breakpoints.append(bp + self._l)
        from sage.misc.misc import uniq
        return AsciiArt(lines=new_matrix,
                        breakpoints=uniq(new_breakpoints),
                        baseline=new_baseline,
                        atomic=False)
Ejemplo n.º 44
0
def c8_c9_func(SUK, v, A, prec=106):
    r"""
    Return the constants `c_8` and `c_9` from Smart's TCDF paper, [Sma1995]_

    INPUT:

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

    OUTPUT:

    The constants ``c8`` and ``c9``, as real numbers

    EXAMPLES::

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

        sage: c8_c9_func(SUK, v_fin,A) # abs tol 1e-29
        (4.524941291354698258804956696127e15, 1.621521281297160786545580368612e16)

    REFERENCES:

    - [Sma1995]_ p. 825
    - [Sma1998]_ p. 226, Theorem A.2 for the local constants

    """
    R = RealField(prec)
    num_mus = len(mus(SUK, v))+1
    p = v.smallest_integer()
    f_p = v.residue_class_degree()
    d = SUK.number_field().degree()
    if p == 2:
        local_c2 = Integer(197142) * Integer(36)**num_mus
    elif p%4 == 1:
        local_c2 = Integer(35009) * (Integer(45)/Integer(2))**num_mus
    else:
        local_c2 = Integer(30760) * Integer(25)**num_mus
    x = polygen(SUK.number_field())
    if (p > 2 and not ((x**2+1).is_irreducible())) or (p==2 and not ((x**2+3).is_irreducible())):
        D = d
    else:
        D = 2*d
    l_c3 = (num_mus+1)**(2*num_mus+4) * p**(D * f_p/d) * (f_p*R(p).log())**(-num_mus-1) * D**(num_mus+2)

    def modified_height(SUK, v, D, b):
        #[Sma1998]_ p. 226
        max_log_b = max([phi(b).log().abs() for phi in SUK.number_field().places(prec)])
        return R(max([b.global_height(), max_log_b/(2*R.pi()*D), f_p*R(p).log()/d]))

    mus_prod = prod([modified_height(SUK,v,D,b) for b in mus(SUK,v)])
    local_c3 = R(max([mus_prod*modified_height(SUK, v, D, mu0) for mu0 in possible_mu0s(SUK, v)]))

    l_c3 *= local_c3
    H = max([modified_height(SUK, v, D, alpha) for alpha in mus(SUK, v)+possible_mu0s(SUK, v)])
    if p == 2:
        local_c4 = R(3 * 2**10 * (num_mus+1)**2 * D**2 * H).log()
    else:
        local_c4 = R(2**11 * (num_mus+1)**2 * D**2 * H).log()
    local_c5 = 2 * R(D).log()
    return R(local_c2*l_c3*local_c4), R(local_c2*l_c3*local_c4*local_c5)
Ejemplo n.º 45
0
def build_alphabet(data=None, names=None, name=None):
    r"""
    Return an object representing an ordered alphabet.

    INPUT:

    - ``data`` -- the letters of the alphabet; it can be:

      * a list/tuple/iterable of letters; the iterable may be infinite
      * an integer `n` to represent `\{1, \ldots, n\}`, or infinity to
        represent `\NN`

    - ``names`` -- (optional) a list for the letters (i.e. variable names) or
      a string for prefix for all letters; if given a list, it must have the
      same cardinality as the set represented by ``data``

    - ``name`` -- (optional) if given, then return a named set and can be
      equal to : ``'lower', 'upper', 'space',
      'underscore', 'punctuation', 'printable', 'binary', 'octal', 'decimal',
      'hexadecimal', 'radix64'``.

      You can use many of them at once, separated by spaces : ``'lower
      punctuation'`` represents the union of the two alphabets ``'lower'`` and
      ``'punctuation'``.

      Alternatively, ``name`` can be set to ``"positive integers"`` (or
      ``"PP"``) or ``"natural numbers"`` (or ``"NN"``).

      ``name`` cannot be combined with ``data``.

    EXAMPLES:

    If the argument is a Set, it just returns it::

        sage: build_alphabet(ZZ) is ZZ
        True
        sage: F = FiniteEnumeratedSet('abc')
        sage: build_alphabet(F) is F
        True

    If a list, tuple or string is provided, then it builds a proper Sage class
    (:class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet`)::

        sage: build_alphabet([0,1,2])
        {0, 1, 2}
        sage: F = build_alphabet('abc'); F
        {'a', 'b', 'c'}
        sage: print type(F).__name__
        TotallyOrderedFiniteSet_with_category

    If an integer and a set is given, then it constructs a
    :class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet`::

        sage: build_alphabet(3, ['a','b','c'])
        {'a', 'b', 'c'}

    If an integer and a string is given, then it considers that string as a
    prefix::

        sage: build_alphabet(3, 'x')
        {'x0', 'x1', 'x2'}

    If no data is provided, ``name`` may be a string which describe an alphabet.
    The available names decompose into two families. The first one are 'positive
    integers', 'PP', 'natural numbers' or 'NN' which refer to standard set of
    numbers::

        sage: build_alphabet(name="positive integers")
        Positive integers
        sage: build_alphabet(name="PP")
        Positive integers
        sage: build_alphabet(name="natural numbers")
        Non negative integers
        sage: build_alphabet(name="NN")
        Non negative integers

    The other families for the option ``name`` are among 'lower', 'upper',
    'space', 'underscore', 'punctuation', 'printable', 'binary', 'octal',
    'decimal', 'hexadecimal', 'radix64' which refer to standard set of
    charaters. Theses names may be combined by separating them by a space::

        sage: build_alphabet(name="lower")
        {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
        sage: build_alphabet(name="hexadecimal")
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}
        sage: build_alphabet(name="decimal punctuation")
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ',', '.', ';', ':', '!', '?'}

    In the case the alphabet is built from a list or a tuple, the order on the
    alphabet is given by the elements themselves::

        sage: A = build_alphabet([0,2,1])
        sage: A(0) < A(2)
        True
        sage: A(2) < A(1)
        False

    If a different order is needed, you may use
    :class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet` and
    set the option ``facade`` to ``False``. That way, the comparison fits the
    order of the input::

        sage: A = TotallyOrderedFiniteSet([4,2,6,1], facade=False)
        sage: A(4) < A(2)
        True
        sage: A(1) < A(6)
        False

    Be careful, the element of the set in the last example are no more
    integers and do not compare equal with integers::

        sage: type(A.an_element())
        <class 'sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet_with_category.element_class'>
        sage: A(1) == 1
        False
        sage: 1 == A(1)
        False

    We give an example of an infinite alphabet indexed by the positive
    integers and the prime numbers::

        sage: build_alphabet(oo, 'x')
        Lazy family (x(i))_{i in Non negative integers}
        sage: build_alphabet(Primes(), 'y')
        Lazy family (y(i))_{i in Set of all prime numbers: 2, 3, 5, 7, ...}

    TESTS::

        sage: Alphabet(3, name="punctuation")
        Traceback (most recent call last):
        ...
        ValueError: name cannot be specified with any other argument
        sage: Alphabet(8, ['e']*10)
        Traceback (most recent call last):
        ...
        ValueError: invalid value for names
        sage: Alphabet(8, x)
        Traceback (most recent call last):
        ...
        ValueError: invalid value for names
        sage: Alphabet(name=x, names="punctuation")
        Traceback (most recent call last):
        ...
        ValueError: name cannot be specified with any other argument
        sage: Alphabet(x)
        Traceback (most recent call last):
        ...
        ValueError: unable to construct an alphabet from the given parameters
    """
    # If both 'names' and 'data' are defined
    if name is not None and (data is not None or names is not None):
        raise ValueError("name cannot be specified with any other argument")

    # Swap arguments if we need to to try and make sure we have "good" user input
    if isinstance(names, (int,long,Integer)) or names == Infinity \
            or (data is None and names is not None):
        data, names = names, data

    # data is an integer
    if isinstance(data, (int, long, Integer)):
        if names is None:
            from sage.sets.integer_range import IntegerRange
            return IntegerRange(Integer(data))
        if isinstance(names, str):
            return TotallyOrderedFiniteSet(
                [names + '%d' % i for i in xrange(data)])
        if len(names) == data:
            return TotallyOrderedFiniteSet(names)
        raise ValueError("invalid value for names")

    if data == Infinity:
        data = NonNegativeIntegers()

    # data is an iterable
    if isinstance(data, (tuple, list, str)) or data in Sets():
        if names is not None:
            if not isinstance(names, str):
                raise TypeError("names must be a string when data is a set")
            return Family(data, lambda i: names + str(i), name=names)
        if data in Sets():
            return data
        return TotallyOrderedFiniteSet(data)

    # Alphabet defined from a name
    if name is not None:
        if not isinstance(name, str):
            raise TypeError("name must be a string")
        if name == "positive integers" or name == "PP":
            from sage.sets.positive_integers import PositiveIntegers
            return PositiveIntegers()
        if name == "natural numbers" or name == "NN":
            return NonNegativeIntegers()

        data = []
        for alpha_name in name.split(' '):
            try:
                data.extend(list(set_of_letters[alpha_name]))
            except KeyError:
                raise TypeError("name is not recognized")
        return TotallyOrderedFiniteSet(data)

    # Alphabet(**nothing**)
    if data is None:  # name is also None
        from sage.structure.parent import Set_PythonType
        return Set_PythonType(object)

    raise ValueError(
        "unable to construct an alphabet from the given parameters")
Ejemplo n.º 46
0
    def _multiply(self, left, right):
        """
        Return the product of ``left`` and ``right``.

        - ``left``, ``right`` -- symmetric functions written in the
          monomial basis ``self``.

        OUTPUT:

        - the product of ``left`` and ``right``, expanded in the
          monomial basis, as a dictionary whose keys are partitions and
          whose values are the coefficients of these partitions (more
          precisely, their respective monomial symmetric functions) in the
          product.

        EXAMPLES::

            sage: m = SymmetricFunctions(QQ).m()
            sage: a = m([2,1])
            sage: a^2
            4*m[2, 2, 1, 1] + 6*m[2, 2, 2] + 2*m[3, 2, 1] + 2*m[3, 3] + 2*m[4, 1, 1] + m[4, 2]

        ::

            sage: QQx.<x> = QQ['x']
            sage: m = SymmetricFunctions(QQx).m()
            sage: a = m([2,1])+x
            sage: 2*a # indirect doctest
            2*x*m[] + 2*m[2, 1]
            sage: a^2
            x^2*m[] + 2*x*m[2, 1] + 4*m[2, 2, 1, 1] + 6*m[2, 2, 2] + 2*m[3, 2, 1] + 2*m[3, 3] + 2*m[4, 1, 1] + m[4, 2]
        """
        #Use symmetrica to do the multiplication
        #A = left.parent()

        #Hack due to symmetrica crashing when both of the
        #partitions are the empty partition
        #if  R is ZZ or R is QQ:
        #    return symmetrica.mult_monomial_monomial(left, right)

        z_elt = {}
        for (left_m, left_c) in left._monomial_coefficients.iteritems():
            for (right_m, right_c) in right._monomial_coefficients.iteritems():

                #Hack due to symmetrica crashing when both of the
                #partitions are the empty partition
                if left_m == [] and right_m == []:
                    z_elt[left_m] = left_c * right_c
                    continue

                d = symmetrica.mult_monomial_monomial({
                    left_m: Integer(1)
                }, {
                    right_m: Integer(1)
                }).monomial_coefficients()
                for m in d:
                    if m in z_elt:
                        z_elt[m] = z_elt[m] + left_c * right_c * d[m]
                    else:
                        z_elt[m] = left_c * right_c * d[m]
        return z_elt
Ejemplo n.º 47
0
    def create_object(self, version, key, **kwds):
        """
        EXAMPLES::

            sage: K = GF(19) # indirect doctest
            sage: TestSuite(K).run()

        We try to create finite fields with various implementations::

            sage: k = GF(2, impl='modn')
            sage: k = GF(2, impl='givaro')
            sage: k = GF(2, impl='ntl')
            sage: k = GF(2, impl='pari_ffelt')
            Traceback (most recent call last):
            ...
            ValueError: the degree must be at least 2
            sage: k = GF(2, impl='pari_mod')
            Traceback (most recent call last):
            ...
            ValueError: The size of the finite field must not be prime.
            sage: k = GF(2, impl='supercalifragilisticexpialidocious')
            Traceback (most recent call last):
            ...
            ValueError: no such finite field implementation: 'supercalifragilisticexpialidocious'
            sage: k.<a> = GF(2^15, impl='modn')
            Traceback (most recent call last):
            ...
            ValueError: the 'modn' implementation requires a prime order
            sage: k.<a> = GF(2^15, impl='givaro')
            sage: k.<a> = GF(2^15, impl='ntl')
            sage: k.<a> = GF(2^15, impl='pari_ffelt')
            sage: k.<a> = GF(2^15, impl='pari_mod')
            sage: k.<a> = GF(3^60, impl='modn')
            Traceback (most recent call last):
            ...
            ValueError: the 'modn' implementation requires a prime order
            sage: k.<a> = GF(3^60, impl='givaro')
            Traceback (most recent call last):
            ...
            ValueError: q must be < 2^16
            sage: k.<a> = GF(3^60, impl='ntl')
            Traceback (most recent call last):
            ...
            ValueError: q must be a 2-power
            sage: k.<a> = GF(3^60, impl='pari_ffelt')
            sage: k.<a> = GF(3^60, impl='pari_mod')
        """
        # IMPORTANT!  If you add a new class to the list of classes
        # that get cached by this factor object, then you *must* add
        # the following method to that class in order to fully support
        # pickling:
        #
        #     def __reduce__(self):   # and include good doctests, please!
        #         return self._factory_data[0].reduce_data(self)
        #
        # This is not in the base class for finite fields, since some finite
        # fields need not be created using this factory object, e.g., residue
        # class fields.

        if len(key) == 5:
            # for backward compatibility of pickles (see trac 10975).
            order, name, modulus, impl, _ = key
            p, n = Integer(order).factor()[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        if impl == 'modn':
            if n != 1:
                raise ValueError(
                    "the 'modn' implementation requires a prime order")
            from finite_field_prime_modn import FiniteField_prime_modn
            # Using a check option here is probably a worthwhile
            # compromise since this constructor is simple and used a
            # huge amount.
            K = FiniteField_prime_modn(order, check=False, modulus=modulus)
        else:
            # We have to do this with block so that the finite field
            # constructors below will use the proof flag that was
            # passed in when checking for primality, factoring, etc.
            # Otherwise, we would have to complicate all of their
            # constructors with check options.
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if impl == 'givaro':
                    repr = kwds.get('repr', 'poly')
                    elem_cache = kwds.get('elem_cache', order < 500)
                    K = FiniteField_givaro(order,
                                           name,
                                           modulus,
                                           repr=repr,
                                           cache=elem_cache)
                elif impl == 'ntl':
                    from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
                    K = FiniteField_ntl_gf2e(order, name, modulus)
                elif impl == 'pari_ffelt':
                    from finite_field_pari_ffelt import FiniteField_pari_ffelt
                    K = FiniteField_pari_ffelt(p, modulus, name)
                elif (impl == 'pari_mod'
                      or impl == 'pari'):  # for unpickling old pickles
                    # This implementation is deprecated, a warning will
                    # be given when this field is created.
                    # See http://trac.sagemath.org/ticket/17297
                    from finite_field_ext_pari import FiniteField_ext_pari
                    K = FiniteField_ext_pari(order, name, modulus)
                else:
                    raise ValueError(
                        "no such finite field implementation: %r" % impl)

            # Temporary; see create_key_and_extra_args() above.
            if 'prefix' in kwds:
                K._prefix = kwds['prefix']

        return K
Ejemplo n.º 48
0
    def _element_constructor_(self, x):
        """
        Convert ``x`` into ``self``, if coercion failed

        INPUT:

        - ``self`` -- a basis of the symmetric functions
        - ``x`` -- an element of the symmetric functions

        EXAMPLES::

            sage: s = SymmetricFunctions(QQ).s()
            sage: s(2)
            2*s[]
            sage: s([2,1]) # indirect doctest
            s[2, 1]

            sage: s([[2,1],[1]])
            s[1, 1] + s[2]
            sage: s([[],[]])
            s[]

            sage: McdJ = SymmetricFunctions(QQ['q','t'].base_ring())
            sage: s = SymmetricFunctions(McdJ.base_ring()).s()
            sage: s._element_constructor_(McdJ(s[2,1]))
            s[2, 1]
        """
        R = self.base_ring()

        eclass = self.element_class
        if isinstance(x, int):
            x = Integer(x)

        ##############
        # Partitions #
        ##############
        if x in sage.combinat.partition.Partitions():
            return eclass(
                self, {
                    sage.combinat.partition.Partition(
                        filter(lambda x: x != 0, x)):
                    R(1)
                })

        # Todo: discard all of this which is taken care by Sage's coercion
        # (up to changes of base ring)

        ##############
        # Dual bases #
        ##############
        elif sfa.is_SymmetricFunction(x) and hasattr(x, 'dual'):
            #Check to see if it is the dual of some other basis
            #If it is, try to coerce its corresponding element
            #in the other basis
            return self(x.dual())

        ##################################################################
        # Symmetric Functions, same basis, possibly different coeff ring #
        ##################################################################

        # self.Element is used below to test if another symmetric
        # function is expressed in the same basis but in another
        # ground ring.  This idiom is fragile and depends on the
        # internal (unstable) specifications of parents and categories
        #
        # TODO: find the right idiom
        #
        # One cannot use anymore self.element_class: it is build by
        # the category mechanism, and depends on the coeff ring.

        elif isinstance(x, self.Element):
            P = x.parent()
            #same base ring
            if P is self:
                return x
            #different base ring
            else:
                return eclass(
                    self,
                    dict([(e1, R(e2))
                          for e1, e2 in x._monomial_coefficients.items()]))

        ##################################################
        # Classical Symmetric Functions, different basis #
        ##################################################
        elif isinstance(x, SymmetricFunctionAlgebra_classical.Element):

            R = self.base_ring()
            xP = x.parent()
            xm = x.monomial_coefficients()

            #determine the conversion function.
            try:
                t = conversion_functions[(xP.basis_name(), self.basis_name())]
            except AttributeError:
                raise TypeError, "do not know how to convert from %s to %s" % (
                    xP.basis_name(), self.basis_name())

            if R == QQ and xP.base_ring() == QQ:
                if xm:
                    return self._from_dict(t(xm)._monomial_coefficients,
                                           coerce=True)
                else:
                    return self(0)
            else:
                f = lambda part: self._from_dict(
                    t({
                        part: Integer(1)
                    })._monomial_coefficients)
                return self._apply_module_endomorphism(x, f)

        ###############################
        # Hall-Littlewood Polynomials #
        ###############################
        elif isinstance(x, hall_littlewood.HallLittlewood_generic.Element):
            #
            #Qp: Convert to Schur basis and then convert to self
            #
            if isinstance(x, hall_littlewood.HallLittlewood_qp.Element):
                Qp = x.parent()
                sx = Qp._s._from_cache(x,
                                       Qp._s_cache,
                                       Qp._self_to_s_cache,
                                       t=Qp.t)
                return self(sx)
            #
            #P: Convert to Schur basis and then convert to self
            #
            elif isinstance(x, hall_littlewood.HallLittlewood_p.Element):
                P = x.parent()
                sx = P._s._from_cache(x, P._s_cache, P._self_to_s_cache, t=P.t)
                return self(sx)
            #
            #Q: Convert to P basis and then convert to self
            #
            elif isinstance(x, hall_littlewood.HallLittlewood_q.Element):
                return self(x.parent()._P(x))

        #######
        # LLT #
        #######
        #Convert to m and then to self.
        elif isinstance(x, llt.LLT_generic.Element):
            P = x.parent()
            BR = self.base_ring()
            zero = BR(0)
            PBR = P.base_ring()
            if not BR.has_coerce_map_from(PBR):
                raise TypeError, "no coerce map from x's parent's base ring (= %s) to self's base ring (= %s)" % (
                    PBR, self.base_ring())

            z_elt = {}
            for m, c in x._monomial_coefficients.iteritems():
                n = sum(m)
                P._m_cache(n)
                for part in P._self_to_m_cache[n][m]:
                    z_elt[part] = z_elt.get(part, zero) + BR(
                        c * P._self_to_m_cache[n][m][part].subs(t=P.t))

            m = P._sym.monomial()
            return self(m._from_dict(z_elt))

        #########################
        # Macdonald Polynomials #
        #########################
        elif isinstance(x, macdonald.MacdonaldPolynomials_generic.Element):
            if isinstance(x, macdonald.MacdonaldPolynomials_j.Element):
                J = x.parent()
                sx = J._s._from_cache(x,
                                      J._s_cache,
                                      J._self_to_s_cache,
                                      q=J.q,
                                      t=J.t)
                return self(sx)
            elif isinstance(x, (macdonald.MacdonaldPolynomials_q.Element,
                                macdonald.MacdonaldPolynomials_p.Element)):
                J = x.parent()._J
                jx = J(x)
                sx = J._s._from_cache(jx,
                                      J._s_cache,
                                      J._self_to_s_cache,
                                      q=J.q,
                                      t=J.t)
                return self(sx)
            elif isinstance(x, (macdonald.MacdonaldPolynomials_h.Element,
                                macdonald.MacdonaldPolynomials_ht.Element)):
                H = x.parent()
                sx = H._s._from_cache(x,
                                      H._s_cache,
                                      H._self_to_s_cache,
                                      q=H.q,
                                      t=H.t)
                return self(sx)
            elif isinstance(x, macdonald.MacdonaldPolynomials_s.Element):
                S = x.parent()
                sx = S._s._from_cache(x,
                                      S._s_cache,
                                      S._self_to_s_cache,
                                      q=S.q,
                                      t=S.t)
                return self(sx)
            else:
                raise TypeError

        ####################
        # Jack Polynomials #
        ####################
        elif isinstance(x, jack.JackPolynomials_generic.Element):
            if isinstance(x, jack.JackPolynomials_p.Element):
                P = x.parent()
                mx = P._m._from_cache(x, P._m_cache, P._self_to_m_cache, t=P.t)
                return self(mx)
            if isinstance(x, (jack.JackPolynomials_j.Element,
                              jack.JackPolynomials_q.Element)):
                return self(x.parent()._P(x))
            else:
                raise TypeError

        #####################
        # k-Schur Functions #
        #####################
        if isinstance(x, kschur.kSchurFunctions_generic.Element):
            if isinstance(x, kschur.kSchurFunctions_t.Element):
                P = x.parent()
                sx = P._s._from_cache(x, P._s_cache, P._self_to_s_cache, t=P.t)
                return self(sx)
            else:
                raise TypeError

        ####################################################
        # Bases defined by orthogonality and triangularity #
        ####################################################
        elif isinstance(
                x, orthotriang.SymmetricFunctionAlgebra_orthotriang.Element):
            #Convert to its base and then to self
            xp = x.parent()
            if self is xp._sf_base:
                return xp._sf_base._from_cache(x, xp._base_cache,
                                               xp._self_to_base_cache)
            else:
                return self(xp._sf_base(x))

        ###################
        # Skew Partitions #
        ###################
        elif x in sage.combinat.skew_partition.SkewPartitions():
            import sage.libs.lrcalc.lrcalc as lrcalc
            skewschur = lrcalc.skew(x[0], x[1])
            return self._from_dict(skewschur)

        #############################
        # Elements of the base ring #
        #############################
        elif x.parent() is R:
            return eclass(self, {sage.combinat.partition.Partition([]): x})

        ###########################################
        # Elements that coerce into the base ring #
        ###########################################
        elif R.has_coerce_map_from(x.parent()):
            return eclass(self, {sage.combinat.partition.Partition([]): R(x)})

        #################################
        # Last shot -- try calling R(x) #
        #################################
        else:
            try:
                return eclass(self,
                              {sage.combinat.partition.Partition([]): R(x)})
            except StandardError:
                raise TypeError, "do not know how to make x (= %s) an element of self" % (
                    x)
Ejemplo n.º 49
0
def discrete_log_lambda(a, base, bounds, operation='*', hash_function=hash):
    """
    Pollard Lambda algorithm for computing discrete logarithms. It uses
    only a logarithmic amount of memory. It's useful if you have
    bounds on the logarithm. If you are computing logarithms in a
    whole finite group, you should use Pollard Rho algorithm.

    INPUT:

    - a - a group element
    - base - a group element
    - bounds - a couple (lb,ub) representing the range where we look for a logarithm
    - operation - string: '+', '*' or 'other'
    - hash_function -- having an efficient hash function is critical for this algorithm

    OUTPUT: Returns an integer `n` such that `a=base^n` (or `a=n*base`)

    ALGORITHM: Pollard Lambda, if bounds are (lb,ub) it has time complexity
        O(sqrt(ub-lb)) and space complexity O(log(ub-lb))

    EXAMPLES::

        sage: F.<a> = GF(2^63)
        sage: discrete_log_lambda(a^1234567, a, (1200000,1250000))
        1234567

        sage: F.<a> = GF(37^5)
        sage: E = EllipticCurve(F, [1,1])
        sage: P = E.lift_x(a); P
        (a : 9*a^4 + 22*a^3 + 23*a^2 + 30 : 1)

    This will return a multiple of the order of P::

        sage: discrete_log_lambda(P.parent()(0), P, Hasse_bounds(F.order()), operation='+')
        69327408

        sage: K.<a> = GF(89**5)
        sage: hs = lambda x: hash(x) + 15
        sage: discrete_log_lambda(a**(89**3 - 3), a, (89**2, 89**4), operation = '*', hash_function = hs)  # long time (10s on sage.math, 2011)
        704966

    AUTHOR:

        -- Yann Laigle-Chapuy (2009-01-25)

    """
    from sage.rings.integer import Integer
    from operator import mul, add, pow

    if operation in addition_names:
        mult = add
        power = mul
    elif operation in multiplication_names:
        mult = mul
        power = pow
    else:
        raise ValueError("unknown operation")

    lb, ub = bounds
    if lb < 0 or ub < lb:
        raise ValueError("discrete_log_lambda() requires 0<=lb<=ub")

    # check for mutability
    mut = hasattr(base, 'set_immutable')

    width = Integer(ub - lb)
    N = width.isqrt() + 1

    M = dict()
    for s in xrange(10):  #to avoid infinite loops
        #random walk function setup
        k = 0
        while (2**k < N):
            r = sage.misc.prandom.randrange(1, N)
            M[k] = (r, power(base, r))
            k += 1
        #first random walk
        H = power(base, ub)
        c = ub
        for i in xrange(N):
            if mut: H.set_immutable()
            r, e = M[hash_function(H) % k]
            H = mult(H, e)
            c += r
        if mut: H.set_immutable()
        mem = set([H])
        #second random walk
        H = a
        d = 0
        while c - d >= lb:
            if mut: H.set_immutable()
            if ub > c - d and H in mem:
                return c - d
            r, e = M[hash_function(H) % k]
            H = mult(H, e)
            d += r

    raise ValueError("Pollard Lambda failed to find a log")
Ejemplo n.º 50
0
    def __init__(self, symbol):
        r"""
        Constructor for Kodaira Symbol class.

        INPUT:

        - ``symbol`` (string or integer) -- The string should be a
           standard string representation (e.g. III*) of a Kodaira
           symbol, which will be parsed.  Alternatively, use the PARI
           encoding of Kodaira symbols as integers.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol_class
            sage: KodairaSymbol_class(14)
            I10
            sage: KodairaSymbol_class('III*')
            III*
            sage: latex(KodairaSymbol_class('In'))
            I_n
            sage: KodairaSymbol_class('In')
            In
        """
        if not isinstance(symbol, str):
            n = Integer(symbol)
            self._n = None
            if n == 0:
                raise ValueError("Kodaira Symbol code number must be nonzero.")
            if n == 1:
                self._n = 0
                self._roman = 1
                self._str = 'I0'
                self._latex = 'I_0'
            elif n == 2:
                self._roman = 2
                self._str = 'II'
                self._latex = 'II'
            elif n == 3:
                self._roman = 3
                self._str = 'III'
                self._latex = 'III'
            elif n == 4:
                self._roman = 4
                self._str = 'IV'
                self._latex = 'IV'
            elif n > 4:
                nu = n - 4
                self._n = nu
                self._roman = 1
                self._str = 'I' + nu.str()
                self._latex = 'I_{' + nu.str() + '}'
            elif n == -1:
                self._roman = 1
                self._n = 0
                self._str = 'I0*'
                self._latex = 'I_0^{*}'
            elif n == -2:
                self._roman = 2
                self._str = 'II*'
                self._latex = 'II^{*}'
            elif n == -3:
                self._roman = 3
                self._str = 'III*'
                self._latex = 'III^{*}'
            elif n == -4:
                self._roman = 4
                self._str = 'IV*'
                self._latex = 'IV^{*}'
            elif n < -4:
                nu = -n - 4
                self._roman = 1
                self._n = nu
                self._str = 'I' + nu.str() + '*'
                self._latex = 'I_' + nu.str() + '^{*}'
            self._starred = (n < 0)
            self._pari = n
            return
        elif len(symbol) == 0:
            raise TypeError("symbol must be a nonempty string")
        if symbol[0] == "I":
            symbol = symbol[1:]
        starred = False
        if symbol[-1] == "*":
            starred = True
            symbol = symbol[:-1]
        self._starred = starred
        if symbol in ["I", "II",
                      "V"]:  # NB we have already stripped off the leading 'I'
            self._roman = ["I", "II", "V"].index(symbol) + 2  # =2, 3 or 4
            self._n = None
            if starred:
                sign = -1
                self._str = "I" + symbol + "*"
                self._latex = "I" + symbol + "^*"
            else:
                sign = 1
                self._str = "I" + symbol
                self._latex = "" + self._str + ""
            if symbol == "I":
                self._pari = 2 * sign
            elif symbol == "II":
                self._pari = 3 * sign
            elif symbol == "V":
                self._pari = 4 * sign
        elif symbol == "n":
            self._roman = 1
            self._pari = None
            self._n = "generic"
            if starred:
                self._str = "In*"
                self._latex = "I_n^*"
            else:
                self._str = "In"
                self._latex = "I_n"
        elif symbol.isdigit():
            self._roman = 1
            self._n = Integer(symbol)
            if starred:
                if self._n == 0:
                    self._pari = -1
                else:
                    self._pari = -self._n - 4
                self._str = "I" + symbol + "*"
                self._latex = "I_{%s}^*" % (symbol)
            else:
                if self._n == 0:
                    self._pari = 1
                else:
                    self._pari = self._n + 4
                self._str = "I" + symbol
                self._latex = "I_{%s}" % (symbol)
        else:
            raise ValueError("input is not a Kodaira symbol")
Ejemplo n.º 51
0
    def restricted_automorphism_group(self, vertex_labels=None):
        r"""
        Return the restricted automorphism group.

        First, let the linear automorphism group be the subgroup of
        the Euclidean group `E(d) = GL(d,\RR) \ltimes \RR^d`
        preserving the `d`-dimensional polyhedron. The Euclidean group
        acts in the usual way `\vec{x}\mapsto A\vec{x}+b` on the
        ambient space. The restricted automorphism group is the
        subgroup of the linear automorphism group generated by
        permutations of vertices. If the polytope is full-dimensional,
        it is equal to the full (unrestricted) automorphism group.

        INPUT:

        - ``vertex_labels`` -- a tuple or ``None`` (default). The
          labels of the vertices that will be used in the output
          permutation group. By default, the vertices are used
          themselves.

        OUTPUT:

        A
        :class:`PermutationGroup<sage.groups.perm_gps.permgroup.PermutationGroup_generic>`
        acting on the vertices (or the ``vertex_labels``, if
        specified).

        REFERENCES:

        [BSS2009]_

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3))
            sage: Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) == PermutationGroup([[(2,3)],[(1,2),(3,4)]])
            True
            sage: G = Z3square.restricted_automorphism_group()
            sage: G == PermutationGroup([[((1,2),(2,1))],[((0,0),(1,2)),((2,1),(3,3))],[((0,0),(3,3))]])
            True
            sage: set(G.domain()) == set(Z3square.vertices())
            True
            sage: set(map(tuple,G.orbit(Z3square.vertices()[0]))) == set([(0, 0), (1, 2), (3, 3), (2, 1)])
            True
            sage: cell24 = LatticePolytope_PPL(
            ....: (1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1),(1,-1,-1,1),(0,0,-1,1),
            ....: (0,-1,0,1),(-1,0,0,1),(1,0,0,-1),(0,1,0,-1),(0,0,1,-1),(-1,1,1,-1),
            ....: (1,-1,-1,0),(0,0,-1,0),(0,-1,0,0),(-1,0,0,0),(1,-1,0,0),(1,0,-1,0),
            ....: (0,1,1,-1),(-1,1,1,0),(-1,1,0,0),(-1,0,1,0),(0,-1,-1,1),(0,0,0,-1))
            sage: cell24.restricted_automorphism_group().cardinality()
            1152
        """
        if not self.is_full_dimensional():
            return self.affine_lattice_polytope().\
                restricted_automorphism_group(vertex_labels=vertex_labels)
        if vertex_labels is None:
            vertex_labels = self.vertices()
        from sage.groups.perm_gps.permgroup import PermutationGroup
        from sage.graphs.graph import Graph
        # good coordinates for the vertices
        v_list = []
        for v in self.minimized_generators():
            assert v.divisor() == 1
            v_coords = (1, ) + tuple(Integer(mpz) for mpz in v.coefficients())
            v_list.append(vector(v_coords))

        # Finally, construct the graph
        Qinv = sum(v.column() * v.row() for v in v_list).inverse()
        G = Graph()
        for i in range(0, len(v_list)):
            for j in range(i + 1, len(v_list)):
                v_i = v_list[i]
                v_j = v_list[j]
                G.add_edge(vertex_labels[i], vertex_labels[j],
                           v_i * Qinv * v_j)
        return G.automorphism_group(edge_labels=True)
Ejemplo n.º 52
0
        def _cardinality_from_iterator(self, *ignored_args, **ignored_kwds):
            """
            The cardinality of ``self``.

            OUTPUT: an ``Integer``

            This brute force implementation of :meth:`cardinality`
            iterates through the elements of ``self`` to count them.

            EXAMPLES::

                sage: C = FiniteEnumeratedSets().example(); C
                An example of a finite enumerated set: {1,2,3}
                sage: C._cardinality_from_iterator()
                3

            This is the default implementation of :meth:`cardinality`
            from the category ``FiniteEnumeratedSet()``. To test this,
            we need a fresh example::

                sage: from sage.categories.examples.finite_enumerated_sets import Example
                sage: class FreshExample(Example): pass
                sage: C = FreshExample(); C.rename("FreshExample")
                sage: C.cardinality
                <bound method FreshExample_with_category._cardinality_from_iterator of FreshExample>

            TESTS:

            This method shall return an ``Integer``; we test this
            here, because :meth:`_test_enumerated_set_iter_cardinality`
            does not do it for us::

                sage: type(C._cardinality_from_iterator())
                <type 'sage.rings.integer.Integer'>

            We ignore additional inputs since during doctests classes which
            override ``cardinality()`` call up to the category rather than
            their own ``cardinality()`` method (see :trac:`13688`)::

                sage: C = FiniteEnumeratedSets().example()
                sage: C._cardinality_from_iterator(algorithm='testing')
                3

            Here is a more complete example::

                sage: class TestParent(Parent):
                ...     def __init__(self):
                ...         Parent.__init__(self, category=FiniteEnumeratedSets())
                ...     def __iter__(self):
                ...         yield 1
                ...         return
                ...     def cardinality(self, dummy_arg):
                ...         return 1 # we don't want to change the semantics of cardinality()
                sage: P = TestParent()
                sage: P.cardinality(-1)
                1
                sage: v = P.list(); v
                [1]
                sage: P.cardinality()
                1
                sage: P.cardinality('use alt algorithm') # Used to break here: see trac #13688
                1
                sage: P.cardinality(dummy_arg='use alg algorithm') # Used to break here: see trac #13688
                1
            """
            c = 0
            for _ in self:
                c += 1
            return Integer(c)
Ejemplo n.º 53
0
    def frequency_distribution(self, length=1, prec=0):
        """
        Returns the probability space of character frequencies. The output
        of this method is different from that of the method
        :func:`characteristic_frequency()
        <sage.monoids.string_monoid.AlphabeticStringMonoid.characteristic_frequency>`.
        One can think of the characteristic frequency probability of an
        element in an alphabet `A` as the expected probability of that element
        occurring. Let `S` be a string encoded using elements of `A`. The
        frequency probability distribution corresponding to `S` provides us
        with the frequency probability of each element of `A` as observed
        occurring in `S`. Thus one distribution provides expected
        probabilities, while the other provides observed probabilities.

        INPUT:

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

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

        EXAMPLES:

        Capital letters of the English alphabet::

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

        The binary number system::

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

        The hexadecimal number system::

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

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

            sage: M = AlphabeticStrings().encoding("abcd")
            sage: D = M.frequency_distribution(length=2).function()
            sage: sorted(D.items())
            [(AB, 0.333333333333333), (BC, 0.333333333333333), (CD, 0.333333333333333)]
        """
        from sage.probability.random_variable import DiscreteProbabilitySpace
        if not length in (1, 2):
            raise NotImplementedError("Not implemented")
        if prec == 0:
            RR = RealField()
        else:
            RR = RealField(prec)
        S = self.parent()
        if length == 1:
            Alph = S.gens()
        else:
            Alph = tuple(x * y for x in S.gens() for y in S.gens())
        X = {}
        N = len(self) - length + 1
        eps = RR(Integer(1) / N)
        for i in range(N):
            c = self[i:i + length]
            if c in X:
                X[c] += eps
            else:
                X[c] = eps
        # Return a dictionary of probability distribution. This should
        # allow for easier parsing of the dictionary.
        return DiscreteProbabilitySpace(Alph, X, RR)
Ejemplo n.º 54
0
def racah(aa, bb, cc, dd, ee, ff, prec=None):
    r"""
    Calculate the Racah symbol `W(aa,bb,cc,dd;ee,ff)`.

    INPUT:

    -  ``aa``, ..., ``ff`` - integer or half integer

    -  ``prec`` - precision, default: ``None``. Providing a precision can
       drastically speed up the calculation.

    OUTPUT:

    Rational number times the square root of a rational number
    (if ``prec=None``), or real number if a precision is given.

    EXAMPLES::

        sage: racah(3,3,3,3,3,3)
        -1/14

    NOTES:

    The Racah symbol is related to the Wigner 6-`j` symbol:

    .. MATH::

       \begin{Bmatrix} j_1 & j_2 & j_3 \\ j_4 & j_5 & j_6 \end{Bmatrix}
       =(-1)^{j_1+j_2+j_4+j_5} W(j_1,j_2,j_5,j_4;j_3,j_6)

    Please see the 6-`j` symbol for its much richer symmetries and for
    additional properties.

    ALGORITHM:

    This function uses the algorithm of [Ed1974]_ to calculate the
    value of the 6-`j` symbol exactly. Note that the formula contains
    alternating sums over large factorials and is therefore unsuitable
    for finite precision arithmetic and only useful for a computer
    algebra system [RH2003]_.

    AUTHORS:

    - Jens Rasch (2009-03-24): initial version
    """
    prefac = _big_delta_coeff(aa, bb, ee, prec) * \
        _big_delta_coeff(cc, dd, ee, prec) * \
        _big_delta_coeff(aa, cc, ff, prec) * \
        _big_delta_coeff(bb, dd, ff, prec)
    if prefac == 0:
        return 0
    imin = int(max(aa + bb + ee, cc + dd + ee, aa + cc + ff, bb + dd + ff))
    imax = int(min(aa + bb + cc + dd, aa + dd + ee + ff, bb + cc + ee + ff))

    maxfact = max(imax + 1, aa + bb + cc + dd, aa + dd + ee + ff, \
                      bb + cc + ee + ff)
    _calc_factlist(maxfact)

    sumres = 0
    for kk in range(imin, imax + 1):
        den = _Factlist[int(kk - aa - bb - ee)] * \
            _Factlist[int(kk - cc - dd - ee)] * \
            _Factlist[int(kk - aa - cc - ff)] * \
            _Factlist[int(kk - bb - dd - ff)] * \
            _Factlist[int(aa + bb + cc + dd - kk)] * \
            _Factlist[int(aa + dd + ee + ff - kk)] * \
            _Factlist[int(bb + cc + ee + ff - kk)]
        sumres = sumres + Integer((-1)**kk * _Factlist[kk + 1]) / den

    res = prefac * sumres * (-1)**int(aa + bb + cc + dd)
    return res
Ejemplo n.º 55
0
def _semistable_reducible_primes(E):
    r"""Find a list containing all semistable primes l unramified in K/QQ
    for which the Galois image for E could be reducible.

    INPUT:

    - ``E`` - EllipticCurve - over a number field.

    OUTPUT:

    A list of primes, which contains all primes `l` unramified in
    `K/\mathbb{QQ}`, such that `E` is semistable at all primes lying
    over `l`, and the Galois image at `l` is reducible. If `E` has CM
    defined over its ground field, a ``ValueError`` is raised.

    EXAMPLES::

        sage: E = EllipticCurve([0, -1, 1, -10, -20]) # X_0(11)
        sage: 5 in sage.schemes.elliptic_curves.gal_reps_number_field._semistable_reducible_primes(E)
        True
    """

    E = _over_numberfield(E)
    K = E.base_field()
    deg_one_primes = K.primes_of_degree_one_iter()

    bad_primes = set([])  # This will store the output.

    # We find two primes (of distinct residue characteristics) which are
    # of degree 1, unramified in K/Q, and at which E has good reduction.
    # Both of these primes will give us a nontrivial divisibility constraint
    # on the exceptional primes l. For both of these primes P, we precompute
    # a generator and the trace of Frob_P^12.

    precomp = []
    last_char = 0  # The residue characteristic of the most recent prime.

    while len(precomp) < 2:
        P = next(deg_one_primes)

        if not P.is_principal():
            continue

        det = P.norm()
        if det == last_char:
            continue

        if P.ramification_index() != 1:
            continue

        try:
            tr = E.change_ring(P.residue_field()).trace_of_frobenius()
        except ArithmeticError:  # Bad reduction at P.
            continue

        x = P.gens_reduced()[0]

        precomp.append((x, _tr12(tr, det)))
        last_char = det

    x, tx = precomp[0]
    y, ty = precomp[1]

    Kgal = K.galois_closure('b')
    maps = K.embeddings(Kgal)

    for i in xrange(2**(K.degree() - 1)):
        ## We iterate through all possible characters. ##

        # Here, if i = i_{l-1} i_{l-2} cdots i_1 i_0 in binary, then i
        # corresponds to the character prod sigma_j^{i_j}.

        phi1x = 1
        phi2x = 1
        phi1y = 1
        phi2y = 1

        # We compute the two algebraic characters at x and y:
        for j in xrange(K.degree()):
            if i % 2 == 1:
                phi1x *= maps[j](x)
                phi1y *= maps[j](y)
            else:
                phi2x *= maps[j](x)
                phi2y *= maps[j](y)
            i = int(i / 2)

        # Any prime with reducible image must divide both of:
        gx = phi1x**12 + phi2x**12 - tx
        gy = phi1y**12 + phi2y**12 - ty

        if (gx != 0) or (gy != 0):
            for prime in Integer(Kgal.ideal([gx, gy]).norm()).prime_factors():
                bad_primes.add(prime)

            continue

        ## It is possible that our curve has CM. ##

        # Our character must be of the form Nm^K_F for an imaginary
        # quadratic subfield F of K (which is the CM field if E has CM).
        # We compute F:

        a = (Integer(phi1x + phi2x)**2 - 4 * x.norm()).squarefree_part()

        y = QQ['y'].gen()
        F = NumberField(y**2 - a, 'a')

        # Next, we turn K into relative number field over F.

        K = K.relativize(F.embeddings(K)[0], 'b')
        E = E.change_ring(K.structure()[1])

        ## We try to find a nontrivial divisibility condition. ##

        patience = 5 * K.absolute_degree()
        # Number of Frobenius elements to check before suspecting that E
        # has CM and computing the set of CM j-invariants of K to check.
        # TODO: Is this the best value for this parameter?

        while True:
            P = next(deg_one_primes)

            if not P.is_principal():
                continue

            try:
                tr = E.change_ring(P.residue_field()).trace_of_frobenius()
            except ArithmeticError:  # Bad reduction at P.
                continue

            x = P.gens_reduced()[0].norm(F)
            div = (x**12).trace() - _tr12(tr, x.norm())

            patience -= 1

            if div != 0:
                # We found our divisibility constraint.

                for prime in Integer(div).prime_factors():
                    bad_primes.add(prime)

                # Turn K back into an absolute number field.

                E = E.change_ring(K.structure()[0])
                K = K.structure()[0].codomain()

                break

            if patience == 0:
                # We suspect that E has CM, so we check:
                f = K.structure()[0]
                if f(E.j_invariant()) in cm_j_invariants(f.codomain()):
                    raise ValueError("The curve E should not have CM.")

    L = sorted(bad_primes)
    return L
Ejemplo n.º 56
0
    def __init__(self, x, unit=None, cr=False, sort=True, simplify=True):
        """
        Create a :class:`Factorization` object.

        INPUT:

        - ``x`` - a list of pairs (p, e) with e an integer;
          otherwise a TypeError is raised

        - ``unit`` - (default: 1) the unit part of the factorization.

        - ``cr`` - (default: False) if True, print the factorization with
          carriage returns between factors.

        - ``sort`` - (default: True) if True, sort the factors by calling
          the sort function ``self.sort()`` after creating the factorization

        - ``simplify`` - (default: True) if True, remove duplicate
          factors from the factorization.  See the documentation for
          self.simplify.

        OUTPUT:

        - a Factorization object

        EXAMPLES:
        We create a factorization with all the default options::

            sage: Factorization([(2,3), (5, 1)])
            2^3 * 5

        We create a factorization with a specified unit part::

            sage: Factorization([(2,3), (5, 1)], unit=-1)
            -1 * 2^3 * 5

        We try to create a factorization but with a string an exponent, which
        results in a TypeError::

            sage: Factorization([(2,3), (5, 'x')])
            Traceback (most recent call last):
            ...
            TypeError: exponents of factors must be integers

        We create a factorization that puts newlines after each multiply sign
        when printing.  This is mainly useful when the primes are large::

            sage: Factorization([(2,3), (5, 2)], cr=True)
            2^3 *
            5^2

        Another factorization with newlines and nontrivial unit part, which
        appears on a line by itself::

            sage: Factorization([(2,3), (5, 2)], cr=True, unit=-2)
            -2 *
            2^3 *
            5^2

        A factorization, but where we do not sort the factors::

            sage: Factorization([(5,3), (2, 3)], sort=False)
            5^3 * 2^3

        By default, in the commutative case, factorizations are sorted by the
        prime base::

            sage: Factorization([(2, 7), (5,2), (2, 5)])
            2^12 * 5^2
            sage: R.<a,b> = FreeAlgebra(QQ,2)
            sage: Factorization([(a,1),(b,1),(a,2)])
            a * b * a^2

        Autosorting (the default) swaps around the factors below::

            sage: F = Factorization([(ZZ^3, 2), (ZZ^2, 5)], cr=True); F
            (Ambient free module of rank 2 over the principal ideal domain Integer Ring)^5 *
            (Ambient free module of rank 3 over the principal ideal domain Integer Ring)^2
        """
        if not isinstance(x, list):
            raise TypeError, "x must be a list"
        for i in xrange(len(x)):
            t = x[i]
            if not (isinstance(t, tuple) and len(t) == 2):
                raise TypeError, "x must be a list of pairs (p, e) with e an integer"
            if not isinstance(t[1], (int, long, Integer)):
                try:
                    x[i] = (t[0], Integer(t[1]))
                except TypeError:
                    raise TypeError, "exponents of factors must be integers"

        try:
            self.__universe = Sequence(t[0] for t in x).universe()
        except TypeError:
            self.__universe = None

        self.__x = [(t[0], int(t[1])) for t in x]
        if unit is None:
            if len(x) > 0:
                try:
                    unit = self.__universe(1)
                except (AttributeError, TypeError):
                    unit = Integer(1)
            else:
                unit = Integer(1)
        self.__unit = unit
        self.__cr = cr
        if sort and self.is_commutative():
            self.sort()
        if simplify:
            self.simplify()
Ejemplo n.º 57
0
def FreeGroup(n=None, names='x', index_set=None, abelian=False, **kwds):
    """
    Construct a Free Group.

    INPUT:

    - ``n`` -- integer or ``None`` (default). The number of
      generators. If not specified the ``names`` are counted.

    - ``names`` -- string or list/tuple/iterable of strings (default:
      ``'x'``). The generator names or name prefix.

    - ``index_set`` -- (optional) an index set for the generators; if
      specified then the optional keyword ``abelian`` can be used

    - ``abelian`` -- (default: ``False``) whether to construct a free
      abelian group or a free group

    .. NOTE::

        If you want to create a free group, it is currently preferential to
        use ``Groups().free(...)`` as that does not load GAP.

    EXAMPLES::

        sage: G.<a,b> = FreeGroup();  G
        Free Group on generators {a, b}
        sage: H = FreeGroup('a, b')
        sage: G is H
        True
        sage: FreeGroup(0)
        Free Group on generators {}

    The entry can be either a string with the names of the generators,
    or the number of generators and the prefix of the names to be
    given. The default prefix is ``'x'`` ::

        sage: FreeGroup(3)
        Free Group on generators {x0, x1, x2}
        sage: FreeGroup(3, 'g')
        Free Group on generators {g0, g1, g2}
        sage: FreeGroup()
        Free Group on generators {x}

    We give two examples using the ``index_set`` option::

        sage: FreeGroup(index_set=ZZ)
        Free group indexed by Integer Ring
        sage: FreeGroup(index_set=ZZ, abelian=True)
        Free abelian group indexed by Integer Ring

    TESTS::

        sage: G1 = FreeGroup(2, 'a,b')
        sage: G2 = FreeGroup('a,b')
        sage: G3.<a,b> = FreeGroup()
        sage: G1 is G2, G2 is G3
        (True, True)
    """
    # Support Freegroup('a,b') syntax
    if n is not None:
        try:
            n = Integer(n)
        except TypeError:
            names = n
            n = None
    # derive n from counting names
    if n is None:
        if isinstance(names, six.string_types):
            n = len(names.split(','))
        else:
            names = list(names)
            n = len(names)
    from sage.structure.category_object import normalize_names
    names = normalize_names(n, names)
    if index_set is not None or abelian:
        if abelian:
            from sage.groups.indexed_free_group import IndexedFreeAbelianGroup
            return IndexedFreeAbelianGroup(index_set, names=names, **kwds)

        from sage.groups.indexed_free_group import IndexedFreeGroup
        return IndexedFreeGroup(index_set, names=names, **kwds)
    return FreeGroup_class(names)
Ejemplo n.º 58
0
def singer_difference_set(q, d):
    r"""
    Return a difference set associated to the set of hyperplanes in a projective
    space of dimension `d` over `GF(q)`.

    A Singer difference set has parameters:

    .. MATH::

        v = \frac{q^{d+1}-1}{q-1}, \quad
        k = \frac{q^d-1}{q-1}, \quad
        \lambda = \frac{q^{d-1}-1}{q-1}.

    The idea of the construction is as follows. One consider the finite field
    `GF(q^{d+1})` as a vector space of dimension `d+1` over `GF(q)`. The set of
    `GF(q)`-lines in `GF(q^{d+1})` is a projective plane and its set of
    hyperplanes form a balanced incomplete block design.

    Now, considering a multiplicative generator `z` of `GF(q^{d+1})`, we get a
    transitive action of a cyclic group on our projective plane from which it is
    possible to build a difference set.

    The construction is given in details in [Stinson2004]_, section 3.3.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_family import singer_difference_set, is_difference_family
        sage: G,D = singer_difference_set(3,2)
        sage: is_difference_family(G,D,verbose=True)
        It is a (13,4,1)-difference family
        True

        sage: G,D = singer_difference_set(4,2)
        sage: is_difference_family(G,D,verbose=True)
        It is a (21,5,1)-difference family
        True

        sage: G,D = singer_difference_set(3,3)
        sage: is_difference_family(G,D,verbose=True)
        It is a (40,13,4)-difference family
        True

        sage: G,D = singer_difference_set(9,3)
        sage: is_difference_family(G,D,verbose=True)
        It is a (820,91,10)-difference family
        True
    """
    q = Integer(q)
    assert q.is_prime_power()
    assert d >= 2

    from sage.rings.finite_rings.constructor import GF
    from sage.rings.finite_rings.conway_polynomials import conway_polynomial
    from sage.rings.finite_rings.integer_mod_ring import Zmod

    # build a polynomial c over GF(q) such that GF(q)[x] / (c(x)) is a
    # GF(q**(d+1)) and such that x is a multiplicative generator.
    p, e = q.factor()[0]
    c = conway_polynomial(p, e * (d + 1))
    if e != 1:  # i.e. q is not a prime, so we factorize c over GF(q) and pick
        # one of its factor
        K = GF(q, 'z')
        c = c.change_ring(K).factor()[0][0]
    else:
        K = GF(q)
    z = c.parent().gen()

    # Now we consider the GF(q)-subspace V spanned by (1,z,z^2,...,z^(d-1)) inside
    # GF(q^(d+1)). The multiplication by z is an automorphism of the
    # GF(q)-projective space built from GF(q^(d+1)). The difference family is
    # obtained by taking the integers i such that z^i belong to V.
    powers = [0]
    i = 1
    x = z
    k = (q**d - 1) // (q - 1)
    while len(powers) < k:
        if x.degree() <= (d - 1):
            powers.append(i)
        x = (x * z).mod(c)
        i += 1

    return Zmod((q**(d + 1) - 1) // (q - 1)), [powers]
Ejemplo n.º 59
0
def QuadraticResidueCodeEvenPair(n,F):
    """
    Quadratic residue codes of a given odd prime length and base ring
    either don't exist at all or occur as 4-tuples - a pair of
    "odd-like" codes and a pair of "even-like" codes. If `n > 2` is prime
    then (Theorem 6.6.2 in [HP2003]_) a QR code exists over `GF(q)` iff q is a
    quadratic residue mod `n`.

    They are constructed as "even-like" duadic codes associated the
    splitting (Q,N) mod n, where Q is the set of non-zero quadratic
    residues and N is the non-residues.

    EXAMPLES::

        sage: codes.QuadraticResidueCodeEvenPair(17, GF(13))
        ([17, 8] Cyclic Code over GF(13),
         [17, 8] Cyclic Code over GF(13))
        sage: codes.QuadraticResidueCodeEvenPair(17, GF(2))
        ([17, 8] Cyclic Code over GF(2),
         [17, 8] Cyclic Code over GF(2))
        sage: codes.QuadraticResidueCodeEvenPair(13,GF(9,"z"))
        ([13, 6] Cyclic Code over GF(9),
         [13, 6] Cyclic Code over GF(9))
        sage: C1,C2 = codes.QuadraticResidueCodeEvenPair(7,GF(2))
        sage: C1.is_self_orthogonal()
        True
        sage: C2.is_self_orthogonal()
        True
        sage: C3 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
        sage: C4 = codes.QuadraticResidueCodeEvenPair(17,GF(2))[1]
        sage: C3.systematic_generator_matrix() == C4.dual_code().systematic_generator_matrix()
        True

    This is consistent with Theorem 6.6.9 and Exercise 365 in [HP2003]_.

    TESTS::

        sage: codes.QuadraticResidueCodeEvenPair(14,Zmod(4))
        Traceback (most recent call last):
        ...
        ValueError: the argument F must be a finite field
        sage: codes.QuadraticResidueCodeEvenPair(14,GF(2))
        Traceback (most recent call last):
        ...
        ValueError: the argument n must be an odd prime
        sage: codes.QuadraticResidueCodeEvenPair(5,GF(2))
        Traceback (most recent call last):
        ...
        ValueError: the order of the finite field must be a quadratic residue modulo n
    """
    from sage.arith.srange import srange
    from sage.categories.finite_fields import FiniteFields
    if F not in FiniteFields():
        raise ValueError("the argument F must be a finite field")
    q = F.order()
    n = Integer(n)
    if n <= 2 or not n.is_prime():
        raise ValueError("the argument n must be an odd prime")
    Q = quadratic_residues(n); Q.remove(0)       # non-zero quad residues
    N = [x for x in srange(1,n) if x not in Q]   # non-zero quad non-residues
    if q not in Q:
        raise ValueError("the order of the finite field must be a quadratic residue modulo n")
    return DuadicCodeEvenPair(F,Q,N)
Ejemplo n.º 60
0
def Subsets(s, k=None, submultiset=False):
    """
    Returns the combinatorial class of the subsets of the finite set
    s. The set can be given as a list, Set or any iterable convertible
    to a set. It can alternatively be given a non-negative integer `n`
    which encode the set `\{1,2,\dots,n\}` (i.e. the Sage
    ``range(1,s+1)``).

    A second optional parameter k can be given. In this case, Subsets returns
    the combinatorial class of subsets of s of size k.

    Finally the option ``submultiset`` allows one to deal with sets with
    repeated elements usually called multisets.

    EXAMPLES::

        sage: S = Subsets([1, 2, 3]); S
        Subsets of {1, 2, 3}
        sage: S.cardinality()
        8
        sage: S.first()
        {}
        sage: S.last()
        {1, 2, 3}
        sage: S.random_element()
        {2}
        sage: S.list()
        [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]

    Here is the same example where the set is given as an integer::

        sage: S = Subsets(3)
        sage: S.list()
        [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}]

    We demonstrate various the effect of the various options::

        sage: S = Subsets(3, 2); S
        Subsets of {1, 2, 3} of size 2
        sage: S.list()
        [{1, 2}, {1, 3}, {2, 3}]

        sage: S = Subsets([1, 2, 2], submultiset=True); S
        SubMultiset of [1, 2, 2]
        sage: S.list()
        [[], [1], [2], [1, 2], [2, 2], [1, 2, 2]]

        sage: S = Subsets([1, 2, 2, 3], 3, submultiset=True); S
        SubMultiset of [1, 2, 2, 3] of size 3
        sage: S.list()
        [[1, 2, 2], [1, 2, 3], [2, 2, 3]]

        sage: S = Subsets(['a','b','a','b'], 2, submultiset=True); S.list()
        [['a', 'a'], ['a', 'b'], ['b', 'b']]
    """
    if k is not None:
        k=Integer(k)

    if isinstance(s, (int, Integer)):
        if s < 0:
            raise ValueError("s must be non-negative")
        s = Set(range(1,s+1))

#    if len(Set(s)) != len(s):
#        multi = True

    if k is None:
        if submultiset:
            return SubMultiset_s(s)
        else:
            return Subsets_s(s)
    else:
        if submultiset:
            return SubMultiset_sk(s, k)
        else:
            return Subsets_sk(s, k)