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
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
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
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"
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')
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
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)
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")
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
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 = {}
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
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)
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)
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
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
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
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)
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)
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()
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
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)
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
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
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
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)
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)
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)
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
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
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)
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")
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)
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.
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
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)
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
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
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
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
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)
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)
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")
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
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
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)
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")
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")
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)
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)
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)
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
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
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()
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)
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]
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)
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)