def number_of_classes(self, invertible=False, q=None): """ Return the number of similarity classes of matrices of type ``self``. IMPUT: - ``invertible`` -- Boolean; return number of invertible classes if set to ``True`` - ``q`` -- An integer or an indeterminate EXAMPLES:: sage: tau = SimilarityClassType([[1, [1]], [1, [1]]]) sage: tau.number_of_classes() 1/2*q^2 - 1/2*q """ if q is None: q = ZZ["q"].gen() if self.size() == 0: return q.parent().one() list_of_degrees = [PT.degree() for PT in self] maximum_degree = max(list_of_degrees) numerator = prod( [ prod([primitives(d + 1, invertible=invertible, q=q) - i for i in range(list_of_degrees.count(d + 1))]) for d in range(maximum_degree) ] ) tau_list = list(self) D = dict((i, tau_list.count(i)) for i in tau_list) denominator = reduce(mul, [factorial(D[primary_type]) for primary_type in D.keys()]) return numerator / denominator
def Pall_mass_density_at_odd_prime(self, p): """ Returns the local representation density of a form (for representing itself) defined over `ZZ`, at some prime `p>2`. REFERENCES: Pall's article "The Weight of a Genus of Positive n-ary Quadratic Forms" appearing in Proc. Symp. Pure Math. VIII (1965), pp95--105. INPUT: `p` -- a prime number > 2. OUTPUT: a rational number. EXAMPLES:: sage: Q = QuadraticForm(ZZ, 3, [1,0,0,1,0,1]) sage: Q.Pall_mass_density_at_odd_prime(3) [(0, Quadratic form in 3 variables over Integer Ring with coefficients: [ 1 0 0 ] [ * 1 0 ] [ * * 1 ])] [(0, 3, 8)] [8/9] 8/9 8/9 """ ## Check that p is a positive prime -- unnecessary since it's done implicitly in the next step. =) if p<=2: raise TypeError, "Oops! We need p to be a prime > 2." ## Step 1: Obtain a p-adic (diagonal) local normal form, and ## compute the invariants for each Jordan block. jordan_list = self.jordan_blocks_by_scale_and_unimodular(p) modified_jordan_list = [(a, Q.dim(), Q.det()) for (a,Q) in jordan_list] ## List of pairs (scale, det) #print jordan_list #print modified_jordan_list ## Step 2: Compute the list of local masses for each Jordan block jordan_mass_list = [] for (s,n,d) in modified_jordan_list: generic_factor = prod([1 - p**(-2*j) for j in range(1, floor((n-1)/2)+1)]) #print "generic factor: ", generic_factor if (n % 2 == 0): m = n/2 generic_factor *= (1 + legendre_symbol(((-1)**m) * d, p) * p**(-m)) #print "jordan_mass: ", generic_factor jordan_mass_list = jordan_mass_list + [generic_factor] ## Step 3: Compute the local mass $\al_p$ at p. MJL = modified_jordan_list s = len(modified_jordan_list) M = [sum([MJL[j][1] for j in range(i, s)]) for i in range(s-1)] ## Note: It's s-1 since we don't need the last M. #print "M = ", M nu = sum([M[i] * MJL[i][0] * MJL[i][1] for i in range(s-1)]) - ZZ(sum([J[0] * J[1] * (J[1]-1) for J in MJL]))/ZZ(2) p_mass = prod(jordan_mass_list) p_mass *= 2**(s-1) * p**nu print jordan_list, MJL, jordan_mass_list, p_mass ## Return the result return p_mass
def q_catalan_number(n,p=None): """ Returns the `q`-Catalan number of index `n`. If `p` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. There are several `q`-Catalan numbers. This procedure returns the one which can be written using the `q`-binomial coefficients. EXAMPLES:: sage: from sage.combinat.q_analogues import q_catalan_number sage: q_catalan_number(4) q^12 + q^10 + q^9 + 2*q^8 + q^7 + 2*q^6 + q^5 + 2*q^4 + q^3 + q^2 + 1 sage: p = ZZ['p'].0 sage: q_catalan_number(4,p) p^12 + p^10 + p^9 + 2*p^8 + p^7 + 2*p^6 + p^5 + 2*p^4 + p^3 + p^2 + 1 The `q`-Catalan number of index `n` is only defined for `n` a nonnegative integer (:trac:`11411`):: sage: q_catalan_number(-2) Traceback (most recent call last): ... ValueError: Argument (-2) must be a nonnegative integer. """ if n in ZZ and n >= 0: return prod(q_int(j, p) for j in range(n+2, 2*n+1)) / prod(q_int(j, p) for j in range(2,n+1)) else: raise ValueError("Argument (%s) must be a nonnegative integer." %n)
def q_binomial(n,k,p=None): """ Returns the ``q``-binomial coefficient. If ``p`` is unspecified, then it defaults to using the generator ``q`` for a univariate polynomial ring over the integers. EXAMPLES:: sage: import sage.combinat.q_analogues as q_analogues sage: q_analogues.q_binomial(4,2) q^4 + q^3 + 2*q^2 + q + 1 sage: p = ZZ['p'].0 sage: q_analogues.q_binomial(4,2,p) p^4 + p^3 + 2*p^2 + p + 1 The ``q``-analogue of ``binomial(n,k)`` is currently only defined for ``n`` a nonnegative integer, it is zero for negative k (trac #11411):: sage: q_analogues.q_binomial(5, -1) 0 """ if not (n in ZZ and k in ZZ): raise ValueError, "Argument (%s, %s) must be integers."%(n, k) if n < 0: raise NotImplementedError if 0 <= k and k <= n: k=min(k, n-k) return (prod(q_int(j, p) for j in range(n-k+1, n+1)) / prod(q_int(j, p) for j in range(1, k+1))) else: return 0
def DuadicCodeOddPair(F,S1,S2): """ Constructs the "odd pair" of duadic codes associated to the "splitting" S1, S2 of n. .. warning:: Maybe the splitting should be associated to a sum of q-cyclotomic cosets mod n, where q is a *prime*. EXAMPLES:: sage: from sage.coding.code_constructions import is_a_splitting sage: n = 11; q = 3 sage: C = cyclotomic_cosets(q,n); C [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]] sage: S1 = C[1] sage: S2 = C[2] sage: is_a_splitting(S1,S2,11) (True, 2) sage: DuadicCodeOddPair(GF(q),S1,S2) (Linear code of length 11, dimension 6 over Finite Field of size 3, Linear code of length 11, dimension 6 over Finite Field of size 3) This is consistent with Theorem 6.1.3 in [HP]_. """ n = max(S1+S2)+1 if not(is_a_splitting(S1,S2,n)): raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") z = FF.gen() zeta = z**((q**k-1)/n) P1 = PolynomialRing(FF,"x") x = P1.gen() g1 = prod([x-zeta**i for i in S1+[0]]) g2 = prod([x-zeta**i for i in S2+[0]]) j = sum([x**i/n for i in range(n)]) P2 = PolynomialRing(F,"x") x = P2.gen() coeffs1 = [lift2smallest_field(c)[0] for c in (g1+j).coeffs()] coeffs2 = [lift2smallest_field(c)[0] for c in (g2+j).coeffs()] gg1 = P2(coeffs1) gg2 = P2(coeffs2) C1 = CyclicCodeFromGeneratingPolynomial(n,gg1) C2 = CyclicCodeFromGeneratingPolynomial(n,gg2) return C1,C2
def _gap_init_(self): r""" Return string that defines corresponding abelian group in GAP. EXAMPLES:: sage: G = AbelianGroup([2,3,9]) sage: G._gap_init_() 'AbelianGroup([2, 3, 9])' sage: gap(G) Group( [ f1, f2, f3 ] ) Only works for finite groups. :: sage: G = AbelianGroup(3,[0,3,4],names="abc"); G Multiplicative Abelian Group isomorphic to Z x C3 x C4 sage: G._gap_init_() Traceback (most recent call last): ... TypeError: abelian groups in GAP are finite, but self is infinite """ # TODO: Use the package polycyclic has AbelianPcpGroup, which can handle # the infinite case but it is a GAP package not GPL'd. # Use this when the group is infinite... if (False and prod(self.invariants())==0): # if False for now... return 'AbelianPcpGroup(%s)'%self.invariants() if not self.is_finite(): raise TypeError, "abelian groups in GAP are finite, but self is infinite" return 'AbelianGroup(%s)'%self.invariants()
def Ht(mu, q=None, t=None, pi=None): """ Returns the symmetric Macdonald polynomial using the Haiman, Haglund, and Loehr formula. Note that if both `q` and `t` are specified, then they must have the same parent. REFERENCE: - J. Haglund, M. Haiman, N. Loehr. *A combinatorial formula for non-symmetric Macdonald polynomials*. :arXiv:`math/0601693v3`. EXAMPLES:: sage: from sage.combinat.sf.ns_macdonald import Ht sage: HHt = SymmetricFunctions(QQ['q','t'].fraction_field()).macdonald().Ht() sage: Ht([0,0,1]) x0 + x1 + x2 sage: HHt([1]).expand(3) x0 + x1 + x2 sage: Ht([0,0,2]) x0^2 + (q + 1)*x0*x1 + x1^2 + (q + 1)*x0*x2 + (q + 1)*x1*x2 + x2^2 sage: HHt([2]).expand(3) x0^2 + (q + 1)*x0*x1 + x1^2 + (q + 1)*x0*x2 + (q + 1)*x1*x2 + x2^2 """ P, q, t, n, R, x = _check_muqt(mu, q, t, pi) res = 0 for a in n: weight = a.weight() res += q**a.maj()*t**a.inv()*prod( x[i]**weight[i] for i in range(len(weight)) ) return res
def exp(self, exponents): r""" Return unit with given exponents with respect to group generators. INPUT: - ``u`` -- Any object from which an element of the unit group's number field `K` may be constructed; an error is raised if an element of `K` cannot be constructed from u, or if the element constructed is not a unit. OUTPUT: a list of integers giving the exponents of ``u`` with respect to the unit group's basis. EXAMPLES:: sage: x = polygen(QQ) sage: K.<z> = CyclotomicField(13) sage: UK = UnitGroup(K) sage: [UK.log(u) for u in UK.gens()] [(1, 0, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0), (0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 1, 0), (0, 0, 0, 0, 0, 1)] sage: vec = [65,6,7,8,9,10] sage: unit = UK.exp(vec) sage: UK.log(unit) (13, 6, 7, 8, 9, 10) sage: UK.exp(UK.log(u)) == u.value() True """ return prod([u**e for u,e in zip(self.gens_values(),exponents)], self.number_field().one_element())
def q_factorial(n, p=None): """ Returns the `q`-analogue of the factorial `n!` If `p` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. EXAMPLES:: sage: from sage.combinat.q_analogues import q_factorial sage: q_factorial(3) q^3 + 2*q^2 + 2*q + 1 sage: p = ZZ['p'].0 sage: q_factorial(3, p) p^3 + 2*p^2 + 2*p + 1 The `q`-analogue of `n!` is only defined for `n` a nonnegative integer (:trac:`11411`):: sage: q_factorial(-2) Traceback (most recent call last): ... ValueError: Argument (-2) must be a nonnegative integer. """ if n in ZZ and n >= 0: return prod([q_int(i, p) for i in range(1, n+1)]) else: raise ValueError("Argument (%s) must be a nonnegative integer." %n)
def cardinality(self): """ Returns the number of Lyndon words with the evaluation e. EXAMPLES:: sage: LyndonWords([]).cardinality() 0 sage: LyndonWords([2,2]).cardinality() 1 sage: LyndonWords([2,3,2]).cardinality() 30 Check to make sure that the count matches up with the number of Lyndon words generated. :: sage: comps = [[],[2,2],[3,2,7],[4,2]]+Compositions(4).list() sage: lws = [ LyndonWords(comp) for comp in comps] sage: all( [ lw.cardinality() == len(lw.list()) for lw in lws] ) True """ evaluation = self.e le = __builtin__.list(evaluation) if len(evaluation) == 0: return 0 n = sum(evaluation) return sum([moebius(j)*factorial(n/j) / prod([factorial(ni/j) for ni in evaluation]) for j in divisors(gcd(le))])/n
def __pow__(self, n): """ requires that len(invs) = n """ if not isinstance(n, (int, long, Integer)): raise TypeError, "Argument n (= %s) must be an integer."%n n = int(n) M = self.parent() N = M.ngens() invs = M.invariants() if n < 0: L =[n*self.list()[i]%M.gen(i).order() for i in range(M.ngens())] return prod([M.gen(i)**L[i] for i in range(M.ngens())]) #m = LCM(invs) ## Not very efficient version #pw = (n)%m #x = self**pw #return x elif n == 0: return M(1) elif n == 1: return self elif n == 2: return self * self k = n//2 return self**k * self**(n-k)
def nu3(self): r""" Return the number of elliptic points of order 3 for this congruence subgroup `\Gamma_0(N)`. The number of these is given by a standard formula: 0 if `N` is divisible by 9 or any prime congruent to -1 mod 3, and otherwise `2^d` where d is the number of primes other than 3 dividing `N`. EXAMPLE:: sage: Gamma0(2).nu3() 0 sage: Gamma0(3).nu3() 1 sage: Gamma0(9).nu3() 0 sage: Gamma0(7).nu3() 2 sage: Gamma0(21).nu3() 2 sage: Gamma0(1729).nu3() 8 """ n = self.level() if (n % 9 == 0): return ZZ(0) return prod([ 1 + kronecker_symbol(-3, p) for p, _ in n.factor()])
def cardinality(self): r""" Return the cardinality of ``self``. The number of ordered set partitions of a set of length `k` with composition shape `\mu` is equal to .. MATH:: \frac{k!}{\prod_{\mu_i \neq 0} \mu_i!}. EXAMPLES:: sage: OrderedSetPartitions(5,[2,3]).cardinality() 10 sage: OrderedSetPartitions(0, []).cardinality() 1 sage: OrderedSetPartitions(0, [0]).cardinality() 1 sage: OrderedSetPartitions(0, [0,0]).cardinality() 1 sage: OrderedSetPartitions(5, [2,0,3]).cardinality() 10 """ return factorial(len(self._set))/prod([factorial(i) for i in self.c])
def psi(N): """ The index `[\Gamma : \Gamma_0(N)]`, where `\Gamma = GL(2, R)` for `R` the corresponding ring of integers, and `\Gamma_0(N)` standard congruence subgroup. EXAMPLES:: sage: from sage.modular.modsym.p1list_nf import psi sage: k.<a> = NumberField(x^2 + 23) sage: N = k.ideal(3, a - 1) sage: psi(N) 4 :: sage: k.<a> = NumberField(x^2 + 23) sage: N = k.ideal(5) sage: psi(N) 26 """ if not N.is_integral(): raise ValueError("psi only defined for integral ideals") from sage.misc.misc import prod return prod([(np+1)*np**(e-1) \ for np,e in [(p.absolute_norm(),e) \ for p,e in N.factor()]])
def cardinality(self): """ Returns the number of integer necklaces with the evaluation e. EXAMPLES:: sage: Necklaces([]).cardinality() 0 sage: Necklaces([2,2]).cardinality() 2 sage: Necklaces([2,3,2]).cardinality() 30 Check to make sure that the count matches up with the number of Lyndon words generated. :: sage: comps = [[],[2,2],[3,2,7],[4,2]]+Compositions(4).list() sage: ns = [ Necklaces(comp) for comp in comps] sage: all( [ n.cardinality() == len(n.list()) for n in ns] ) True """ evaluation = self.e le = list(evaluation) if len(le) == 0: return 0 n = sum(le) return sum([euler_phi(j)*factorial(n/j) / prod([factorial(ni/j) for ni in evaluation]) for j in divisors(gcd(le))])/n
def _kohnen_phi(self, a, t) : ## We use a modified power of a, namely for each prime factor p of a ## we use p**floor(v_p(a)/2). This is compensated for in the routine ## of \rho a_modif = 1 for (p,e) in a.factor() : a_modif = a_modif * p**(e // 2) res = 0 for dsq in filter(lambda d: d.is_square(), a.divisors()) : d = isqrt(dsq) for g_diag in itertools.ifilter( lambda diag: prod(diag) == d, itertools.product(*[d.divisors() for _ in xrange(t.nrows())]) ) : for subents in itertools.product(*[xrange(r) for (j,r) in enumerate(g_diag) for _ in xrange(j)]) : columns = [subents[(j * (j - 1)) // 2:(j * (j + 1)) // 2] for j in xrange(t.nrows())] g = diagonal_matrix(list(g_diag)) for j in xrange(t.nrows()) : for i in xrange(j) : g[i,j] = columns[j][i] ginv = g.inverse() tg = ginv.transpose() * t * ginv try : tg= matrix(ZZ, tg) except : continue if any(tg[i,i] % 2 == 1 for i in xrange(tg.nrows())) : continue tg.set_immutable() res = res + self._kohnen_rho(tg, a // dsq) return a_modif * res
def statistic(self, func, q=None): """ Return .. MATH:: prod_{(d, \lambda)\in \tau} n_\lambda(q^d) where `n_\lambda(q)` is the value returned by ``func`` on the input `\lambda`. INPUT: - ``func`` -- a function that takes a partition to a polynomial in ``q`` - ``q`` -- an integer or an indeterminate EXAMPLES:: sage: tau = SimilarityClassType([[1, [1]], [1, [2, 1]], [2, [1, 1]]]) sage: from sage.combinat.similarity_class_type import fq sage: tau.statistic(lambda la: prod([fq(m) for m in la.to_exp()])) (q^9 - 3*q^8 + 2*q^7 + 2*q^6 - 4*q^5 + 4*q^4 - 2*q^3 - 2*q^2 + 3*q - 1)/q^9 sage: q = ZZ['q'].gen() sage: tau.statistic(lambda la: q**la.size(), q = q) q^8 """ if q is None: q = FractionField(ZZ["q"]).gen() return prod([PT.statistic(func, q=q) for PT in self])
def _monomial_exponent_to_lower_factorial(me, x): r""" Converts a tuple of exponents to the monomial obtained by replacing each me[i] with `x_i*(x_i - 1)*\cdots*(x_i - a_i + 1)` EXAMPLES:: sage: from sage.combinat.misc import _monomial_exponent_to_lower_factorial sage: R.<x,y,z> = QQ[] sage: a = R.gens() sage: _monomial_exponent_to_lower_factorial(([1,0,0]),a) x sage: _monomial_exponent_to_lower_factorial(([2,0,0]),a) x^2 - x sage: _monomial_exponent_to_lower_factorial(([0,2,0]),a) y^2 - y sage: _monomial_exponent_to_lower_factorial(([1,1,0]),a) x*y sage: _monomial_exponent_to_lower_factorial(([1,1,2]),a) x*y*z^2 - x*y*z sage: _monomial_exponent_to_lower_factorial(([2,2,2]),a) x^2*y^2*z^2 - x^2*y^2*z - x^2*y*z^2 - x*y^2*z^2 + x^2*y*z + x*y^2*z + x*y*z^2 - x*y*z """ terms = [] for i in range(len(me)): for j in range(me[i]): terms.append(x[i] - j) return prod(terms)
def centralizer_group_cardinality(la, q=None): r""" Return the cardinality of the centralizer group in `GL_n(\mathbf{F}_q)` of a nilpotent matrix whose Jordan blocks are given by ``la``. INPUT: - ``lambda`` -- a partition - ``q`` -- an integer or an indeterminate OUTPUT: A polynomial function of ``q``. EXAMPLES:: sage: from sage.combinat.similarity_class_type import centralizer_group_cardinality sage: q = ZZ['q'].gen() sage: centralizer_group_cardinality(Partition([2, 1])) q^5 - 2*q^4 + q^3 """ if q is None: q = ZZ["q"].gen() return q ** centralizer_algebra_dim(la) * prod([fq(m, q=q) for m in la.to_exp()])
def __getitem__(self, support): r""" INPUT: - ``support`` - a proper subset of the index_set, as a list or set. Returns the cyclicaly decreasing element associated with ``support``. EXAMPLES:: : sage: W = WeylGroup(["A", 5, 1]) sage: W.pieri_factors()[[0,1,2,3,5]].reduced_word() [3, 2, 1, 0, 5] sage: W.pieri_factors()[[0,1,3,4,5]].reduced_word() [1, 0, 5, 4, 3] sage: W.pieri_factors()[[0,1,2,3,4]].reduced_word() [4, 3, 2, 1, 0] """ index_set = sorted(self.W.index_set()) support = sorted(support) assert set(support).issubset(set(index_set)) assert support != index_set if len(support) == 0: return self.W.one() s = self.W.simple_reflections() i = 0 while i < len(support) and support[i] == index_set[i]: i += 1 # This finds the first hole: either ley[i] is maximal or support[i] < support[i+1]+1 return prod((s[j] for j in list(reversed(support[0:i])) + list(reversed(support[i:]))), self.W.one())
def _Chow_group_free(self): r""" Return the relations coming from the free part of the Chow group OUTPUT: A tuple containing the elements of $Hom(A_{d-1,\text{free}}, F^\times)$, including the identity. EXAMPLES:: sage: fan = NormalFan(ReflexivePolytope(2, 0)) sage: X = ToricVariety(fan, base_field=GF(7)) sage: X.Chow_group().degree(1) C3 x Z sage: enum = X.point_set()._naive_enumerator() sage: enum._Chow_group_free() ((1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6)) """ units = self.units() result = [] rays = self.fan().rays() + self.fan().virtual_rays() ker = rays.matrix().integer_kernel().matrix() for phases in CartesianProduct(*([units] * ker.nrows())): phases = tuple(prod(mu**exponent for mu, exponent in zip(phases, column)) for column in ker.columns()) result.append(phases) return tuple(sorted(result))
def __call__( self, g ): """ Some python code for wrapping GAP's Images function but only for permutation groups. Returns an error if g is not in G. EXAMPLES:: sage: H = AbelianGroup(3, [2,3,4], names="abc") sage: a,b,c = H.gens() sage: G = AbelianGroup(2, [2,3], names="xy") sage: x,y = G.gens() sage: phi = AbelianGroupMorphism(G,H,[x,y],[a,b]) sage: phi(y*x) a*b sage: phi(y^2) b^2 """ G = g.parent() w = g.word_problem(self.domaingens) n = len(w) #print w,g.word_problem(self.domaingens) # g.word_problem is faster in general than word_problem(g) gens = self.codomaingens h = prod([gens[(self.domaingens).index(w[i][0])]**(w[i][1]) for i in range(n)]) return h
def units_mod_ideal(I): """ Returns integral elements of the number field representing the images of the global units modulo the ideal ``I``. INPUT: - ``I`` -- number field ideal. OUTPUT: A list of integral elements of the number field representing the images of the global units modulo the ideal ``I``. Elements of the list might be equivalent to each other mod ``I``. EXAMPLES:: sage: from sage.modular.cusps_nf import units_mod_ideal sage: k.<a> = NumberField(x^2 + 1) sage: I = k.ideal(a + 1) sage: units_mod_ideal(I) [1] sage: I = k.ideal(3) sage: units_mod_ideal(I) [1, a, -1, -a] :: sage: from sage.modular.cusps_nf import units_mod_ideal sage: k.<a> = NumberField(x^3 + 11) sage: k.unit_group() Unit group with structure C2 x Z of Number Field in a with defining polynomial x^3 + 11 sage: I = k.ideal(5, a + 1) sage: units_mod_ideal(I) [1, 2*a^2 + 4*a - 1, ...] :: sage: from sage.modular.cusps_nf import units_mod_ideal sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133) sage: k.unit_group() Unit group with structure C6 x Z of Number Field in a with defining polynomial x^4 - x^3 - 21*x^2 + 17*x + 133 sage: I = k.ideal(3) sage: U = units_mod_ideal(I) sage: all([U[j].is_unit() and not (U[j] in I) for j in range(len(U))]) True """ k = I.number_field() Uk = k.unit_group() Istar = I.idealstar(2) ulist = Uk.gens_values() elist = [Istar(I.ideallog(u)).order() for u in ulist] from sage.misc.mrange import xmrange from sage.misc.misc import prod return [prod([u**e for u,e in zip(ulist,ei)],k(1)) for ei in xmrange(elist)]
def cardinality(self): """ EXAMPLES:: sage: [ ContreTableaux(n).cardinality() for n in range(0, 11)] [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700] """ return prod( [ factorial(3*k+1)/factorial(self.n+k) for k in range(self.n)] )
def weyl_dimension(self, highest_weight): """ EXAMPLES:: sage: RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0]) 20 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) <type 'sage.rings.integer.Integer'> """ highest_weight = self(highest_weight) assert(highest_weight.is_dominant()) rho = self.rho() n = prod([(rho+highest_weight).dot_product(x) for x in self.positive_roots()]) d = prod([ rho.dot_product(x) for x in self.positive_roots()]) from sage.rings.integer import Integer return Integer(n/d)
def DuadicCodeEvenPair(F,S1,S2): r""" Constructs the "even pair" of duadic codes associated to the "splitting" (see the docstring for ``is_a_splitting`` for the definition) S1, S2 of n. .. warning:: Maybe the splitting should be associated to a sum of q-cyclotomic cosets mod n, where q is a *prime*. EXAMPLES:: sage: from sage.coding.code_constructions import is_a_splitting sage: n = 11; q = 3 sage: C = cyclotomic_cosets(q,n); C [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]] sage: S1 = C[1] sage: S2 = C[2] sage: is_a_splitting(S1,S2,11) (True, 2) sage: DuadicCodeEvenPair(GF(q),S1,S2) (Linear code of length 11, dimension 5 over Finite Field of size 3, Linear code of length 11, dimension 5 over Finite Field of size 3) """ n = max(S1+S2)+1 if not(is_a_splitting(S1,S2,n)): raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") z = FF.gen() zeta = z**((q**k-1)/n) P1 = PolynomialRing(FF,"x") x = P1.gen() g1 = prod([x-zeta**i for i in S1+[0]]) g2 = prod([x-zeta**i for i in S2+[0]]) P2 = PolynomialRing(F,"x") x = P2.gen() gg1 = P2([lift2smallest_field(c)[0] for c in g1.coeffs()]) gg2 = P2([lift2smallest_field(c)[0] for c in g2.coeffs()]) C1 = CyclicCodeFromGeneratingPolynomial(n,gg1) C2 = CyclicCodeFromGeneratingPolynomial(n,gg2) return C1,C2
def q_multinomial(seq, q=None, binomial_algorithm="auto"): r""" Return the `q`-multinomial coefficient. This is also known as the Gaussian multinomial coefficient, and is defined by .. MATH:: \binom{n}{k_1, k_2, \ldots, k_m}_q = \frac{[n]_q!} {[k_1]_q! [k_2]_q! \cdots [k_m]_q!} where `n = k_1 + k_2 + \cdots + k_m`. If `q` is unspecified, then the variable is the generator `q` for a univariate polynomial ring over the integers. INPUT: - ``seq`` -- an iterable of the values `k_1` to `k_m` defined above - ``q`` -- (default: ``None``) the variable `q`; if ``None``, then use a default variable in `\ZZ[q]` - ``binomial_algorithm`` -- (default: ``'auto'``) the algorithm to use in :meth:`~sage.combinat.q_analogues.q_binomial`; see possible values there ALGORITHM: We use the equivalent formula .. MATH:: \binom{k_1 + \cdots + k_m}{k_1, \ldots, k_m}_q = \prod_{i=1}^m \binom{\sum_{j=1}^i k_j}{k_i}_q. EXAMPLES:: sage: from sage.combinat.q_analogues import q_multinomial sage: q_multinomial([1,2,1]) q^5 + 2*q^4 + 3*q^3 + 3*q^2 + 2*q + 1 sage: q_multinomial([1,2,1], q=1) == multinomial([1,2,1]) True sage: q_multinomial((3,2)) == q_binomial(5,3) True sage: q_multinomial([]) 1 """ binomials = [] partial_sum = 0 for elem in seq: partial_sum += elem binomials.append(q_binomial(partial_sum, elem, q=q, algorithm=binomial_algorithm)) return prod(binomials)
def c1(part, t): """ EXAMPLES:: sage: from sage.combinat.sf.jack import c1 sage: t = QQ['t'].gen() sage: [c1(p,t) for p in Partitions(3)] [2*t^2 + 3*t + 1, t + 2, 6] """ return prod([1+t*part.arm_lengths(flat=True)[i]+part.leg_lengths(flat=True)[i] for i in range(sum(part))], t.parent()(1)) # FIXME: use .one()
def c2(part, t): """ EXAMPLES:: sage: from sage.combinat.sf.jack import c2 sage: t = QQ['t'].gen() sage: [c2(p,t) for p in Partitions(3)] [6*t^3, 2*t^3 + t^2, t^3 + 3*t^2 + 2*t] """ return prod([t+t*part.arm_lengths(flat=True)[i]+part.leg_lengths(flat=True)[i] for i in range(sum(part))], t.parent()(1)) # FIXME: use .one()
def egros_from_j(j,S=[]): r""" Given a rational j and a list of primes S, returns a list of elliptic curves over Q with j-invariant j and good reduction outside S, by checking all relevant quadratic twists. INPUT: - j - a rational number. - S - list of primes (default: empty list). .. note:: Primality of elements of S is not checked, and the output is undefined if S is not a list or contains non-primes. OUTPUT: A sorted list of all elliptic curves defined over `Q` with `j`-invariant equal to `j` and with good reduction at all primes outside the list ``S``. EXAMPLES:: sage: from sage.schemes.elliptic_curves.ell_egros import egros_from_j sage: [e.label() for e in egros_from_j(0,[3])] ['27a1', '27a3', '243a1', '243a2', '243b1', '243b2'] sage: [e.label() for e in egros_from_j(1728,[2])] ['32a1', '32a2', '64a1', '64a4', '256b1', '256b2', '256c1', '256c2'] sage: elist=egros_from_j(-4096/11,[11]) sage: [e.label() for e in elist] ['11a3', '121d1'] """ if j == 1728: return egros_from_j_1728(S) if j == 0: return egros_from_j_0(S) # Now j != 0, 1728 E = EllipticCurve_from_j(j) Elist=[] for ei in xmrange([2]*(1+len(S))): u = prod([p**e for p,e in zip(reversed([-1]+S),ei)],QQ(1)) Eu = E.quadratic_twist(u).minimal_model() if Eu.has_good_reduction_outside_S(S): Elist += [Eu] Elist.sort(cmp=curve_cmp) return Elist
def cardinality(self): """ EXAMPLES:: sage: OrderedSetPartitions(5,[2,3]).cardinality() 10 sage: OrderedSetPartitions(0, []).cardinality() 1 sage: OrderedSetPartitions(0, [0]).cardinality() 1 sage: OrderedSetPartitions(0, [0,0]).cardinality() 1 sage: OrderedSetPartitions(5, [2,0,3]).cardinality() 10 """ return factorial(len(self.s))/prod([factorial(i) for i in self.c])
def index(self): r""" Return the index of self in the full modular group. This is given by the formula .. math:: N^2 \prod_{\substack{p \mid N \\ \text{$p$ prime}}} \left( 1 - \frac{1}{p^2}\right). EXAMPLE:: sage: Gamma1(180).index() 20736 sage: [Gamma1(n).projective_index() for n in [1..16]] [1, 3, 4, 6, 12, 12, 24, 24, 36, 36, 60, 48, 84, 72, 96, 96] """ return prod([p**(2*e) - p**(2*e-2) for (p,e) in self.level().factor()])
def centralizer_group_card(self, q=None): """ Return the cardinality of the group of matrices in `GL_n(\mathbf{F}_q)` which commute with a matrix of type ``self``. INPUT: - ``q`` -- an integer or an indeterminate EXAMPLES:: sage: tau = SimilarityClassType([[1, [1]], [1, [1]]]) sage: tau.centralizer_group_card() q^2 - 2*q + 1 """ return prod([PT.centralizer_group_card(q=q) for PT in self])
def index(self): r""" Return the index of self in the full modular group. This is given by .. math:: \prod_{\substack{p \mid N \\ \text{$p$ prime}}}\left(p^{3e}-p^{3e-2}\right). EXAMPLE:: sage: [Gamma(n).index() for n in [1..19]] [1, 6, 24, 48, 120, 144, 336, 384, 648, 720, 1320, 1152, 2184, 2016, 2880, 3072, 4896, 3888, 6840] sage: Gamma(32041).index() 32893086819240 """ return prod( [p**(3 * e - 2) * (p * p - 1) for (p, e) in self.level().factor()])
def __call__(self, g): """ Evaluate ``self`` on a group element ``g``. OUTPUT: An element in :meth:`~sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class.base_ring`. EXAMPLES:: sage: F = AbelianGroup(5, [2,3,5,7,8], names="abcde") sage: a,b,c,d,e = F.gens() sage: Fd = F.dual_group(names="ABCDE") sage: A,B,C,D,E = Fd.gens() sage: A*B^2*D^7 A*B^2 sage: A(a) -1 sage: B(b) zeta840^140 - 1 sage: CC(B(b)) # abs tol 1e-8 -0.499999999999995 + 0.866025403784447*I sage: A(a*b) -1 """ F = self.parent().base_ring() expsX = self.exponents() expsg = g.exponents() order = self.parent().gens_orders() N = LCM(order) if is_ComplexField(F): from sage.symbolic.constants import pi I = F.gen() PI = F(pi) ans = prod([ exp(2 * PI * I * expsX[i] * expsg[i] / order[i]) for i in range(len(expsX)) ]) return ans ans = F(1) ## assumes F is the cyclotomic field zeta = F.gen() for i in range(len(expsX)): order_noti = N / order[i] ans = ans * zeta**(expsX[i] * expsg[i] * order_noti) return ans
def egros_from_j_0(S=[]): r""" Given a list of primes S, returns a list of elliptic curves over Q with j-invariant 0 and good reduction outside S, by checking all relevant sextic twists. INPUT: - S - list of primes (default: empty list). .. note:: Primality of elements of S is not checked, and the output is undefined if S is not a list or contains non-primes. OUTPUT: A sorted list of all elliptic curves defined over `Q` with `j`-invariant equal to `0` and with good reduction at all primes outside the list ``S``. EXAMPLES:: sage: from sage.schemes.elliptic_curves.ell_egros import egros_from_j_0 sage: egros_from_j_0([]) [] sage: egros_from_j_0([2]) [] sage: [e.label() for e in egros_from_j_0([3])] ['27a1', '27a3', '243a1', '243a2', '243b1', '243b2'] sage: len(egros_from_j_0([2,3,5])) 432 """ Elist = [] if not 3 in S: return Elist no2 = not 2 in S for ei in xmrange([2] + [6] * len(S)): u = prod([p**e for p, e in zip([-1] + S, ei)], QQ(1)) if no2: u *= 16 ## make sure 12|val(D,2) Eu = EllipticCurve([0, 0, 0, 0, u]).minimal_model() if Eu.has_good_reduction_outside_S(S): Elist += [Eu] Elist.sort(cmp=curve_cmp) return Elist
def exp(self, exponents): r""" Return unit with given exponents with respect to group generators. INPUT: - ``u`` -- Any object from which an element of the unit group's number field `K` may be constructed; an error is raised if an element of `K` cannot be constructed from u, or if the element constructed is not a unit. OUTPUT: a list of integers giving the exponents of ``u`` with respect to the unit group's basis. EXAMPLES:: sage: x = polygen(QQ) sage: K.<z> = CyclotomicField(13) sage: UK = UnitGroup(K) sage: [UK.log(u) for u in UK.gens()] [(1, 0, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0), (0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 1, 0), (0, 0, 0, 0, 0, 1)] sage: vec = [65,6,7,8,9,10] sage: unit = UK.exp(vec) sage: UK.log(unit) (13, 6, 7, 8, 9, 10) sage: UK.exp(UK.log(u)) == u.value() True An S-unit example:: sage: SUK = UnitGroup(K,S=2) sage: v = (3,1,4,1,5,9,2) sage: u = SUK.exp(v); u -997204*z^11 - 2419728*z^10 - 413812*z^9 - 413812*z^8 - 2419728*z^7 - 997204*z^6 - 2129888*z^4 - 1616524*z^3 + 149364*z^2 - 1616524*z - 2129888 sage: SUK.log(u) (3, 1, 4, 1, 5, 9, 2) sage: SUK.log(u) == v True """ return prod([u**e for u, e in zip(self.gens_values(), exponents)], self.number_field().one_element())
def omega_qt(self): """ Returns the image of self under the `\omega_{qt}` automorphism. EXAMPLES:: sage: H = MacdonaldPolynomialsH(QQ) sage: H([1,1]).omega_qt() ((2*q^2-2*q*t-2*q+2*t)/(t^3-t^2-t+1))*McdH[1, 1] + ((q-1)/(t-1))*McdH[2] """ P = self.parent() p = sfa.SFAPower(self.parent().base_ring()) p_self = p(self) f = lambda part: (-1)**(part.size() - part.length()) * prod( [(1 - P.q**i) / (1 - P.t**i) for i in part]) * p(part) return P(p._apply_module_morphism(p_self, f))
def cardinality(self): r""" Return the cardinality of ``self``. The number of `n \times n` alternating sign matrices is equal to .. MATH:: \prod_{k=0}^{n-1} \frac{(3k+1)!}{(n+k)!} = \frac{1! 4! 7! 10! \cdots (3n-2)!}{n! (n+1)! (n+2)! (n+3)! \cdots (2n-1)!} EXAMPLES:: sage: [AlternatingSignMatrices(n).cardinality() for n in range(0, 11)] [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700] """ return Integer(prod( [ factorial(3*k+1)/factorial(self._n+k) for k in range(self._n)] ))
def __pow__(self, n): """ EXAMPLES:: sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) # 1+x sage: g = f^3 sage: g.coefficients(4) [1, 3, 3, 1] :: sage: f^0 1 """ if not isinstance(n, (int, Integer)) or n < 0: raise ValueError("n must be a nonnegative integer") return prod([self] * n, self.parent().identity_element())
def E(mu, q=None, t=None, pi=None): """ Returns the non-symmetric Macdonald polynomial in type A corresponding to a shape ``mu``, with basement permuted according to ``pi``. Note that if both `q` and `t` are specified, then they must have the same parent. REFERENCE: - J. Haglund, M. Haiman, N. Loehr. *A combinatorial formula for non-symmetric Macdonald polynomials*. :arXiv:`math/0601693v3`. EXAMPLES:: sage: from sage.combinat.sf.ns_macdonald import E sage: E([0,0,0]) 1 sage: E([1,0,0]) x0 sage: E([0,1,0]) ((-t + 1)/(-q*t^2 + 1))*x0 + x1 sage: E([0,0,1]) ((-t + 1)/(-q*t + 1))*x0 + ((-t + 1)/(-q*t + 1))*x1 + x2 sage: E([1,1,0]) x0*x1 sage: E([1,0,1]) ((-t + 1)/(-q*t^2 + 1))*x0*x1 + x0*x2 sage: E([0,1,1]) ((-t + 1)/(-q*t + 1))*x0*x1 + ((-t + 1)/(-q*t + 1))*x0*x2 + x1*x2 sage: E([2,0,0]) x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + ((-q*t + q)/(-q*t + 1))*x0*x2 sage: E([0,2,0]) ((-t + 1)/(-q^2*t^2 + 1))*x0^2 + ((-q^2*t^3 + q^2*t^2 - q*t^2 + 2*q*t - q + t - 1)/(-q^3*t^3 + q^2*t^2 + q*t - 1))*x0*x1 + x1^2 + ((q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1))*x0*x2 + ((-q*t + q)/(-q*t + 1))*x1*x2 """ P, q, t, n, R, x = _check_muqt(mu, q, t, pi) res = 0 for a in n: weight = a.weight() res += q**a.maj() * t**a.coinv() * a.coeff(q, t) * prod( x[i]**weight[i] for i in range(len(weight))) return res
def Tokuyama_formula(self, name='t'): r""" Return the Tokuyama formula of ``self``. Following the exposition of [BBF]_, Tokuyama's formula asserts .. MATH:: \sum_{G} (t+1)^{s(G)} t^{l(G)} z_1^{d_{n+1}} z_2^{d_{n}-d_{n+1}} \cdots z_{n+1}^{d_1-d_2} = s_{\lambda} (z_1, \ldots, z_{n+1}) \prod_{i<j} (z_j+tz_i), where the sum is over all strict Gelfand-Tsetlin patterns with fixed top row `\lambda+\rho`, with `\lambda` a partition with at most `n+1` parts and `\rho = (n,n-1,\dots,1,0)`, and `s_{\lambda}` is a Schur function. INPUT: - ``name`` -- (Default: ``'t'``) An alternative name for the variable `t`. EXAMPLES:: sage: GT = GelfandTsetlinPatterns(top_row=[2,1,0],strict=True) sage: GT.Tokuyama_formula() t^3*x1^2*x2 + t^2*x1*x2^2 + t^2*x1^2*x3 + t^2*x1*x2*x3 + t*x1*x2*x3 + t*x2^2*x3 + t*x1*x3^2 + x2*x3^2 sage: GT = GelfandTsetlinPatterns(top_row=[3,2,1],strict=True) sage: GT.Tokuyama_formula() t^3*x1^3*x2^2*x3 + t^2*x1^2*x2^3*x3 + t^2*x1^3*x2*x3^2 + t^2*x1^2*x2^2*x3^2 + t*x1^2*x2^2*x3^2 + t*x1*x2^3*x3^2 + t*x1^2*x2*x3^3 + x1*x2^2*x3^3 sage: GT = GelfandTsetlinPatterns(top_row=[1,1,1],strict=True) sage: GT.Tokuyama_formula() 0 """ n = self._n variables = [name] + ["x%d" % i for i in range(1, n + 1)] R = PolynomialRing(ZZ, names=variables) t = R.gen(0) x = R.gens()[1:] GT = GelfandTsetlinPatterns(top_row=self._row, strict=True) return sum((t + 1)**(gt.number_of_special_entries()) * t**(gt.number_of_boxes()) * prod(x[i]**gt.weight()[i] for i in range(n)) for gt in GT)
def value(self): """ Return the value of the group element. OUTPUT: The value according to the values for generators, see :meth:`~AbelianGroupWithValues.gens_values`. EXAMPLES:: sage: G = AbelianGroupWithValues([5], 1) sage: G.0.value() 5 """ if self._value is None: values = self.parent().gens_values() self._value = prod(v**e for v, e in zip(values, self.exponents())) return self._value
def _kohnen_phi(self, a, t): ## We use a modified power of a, namely for each prime factor p of a ## we use p**floor(v_p(a)/2). This is compensated for in the routine ## of \rho a_modif = 1 for (p, e) in a.factor(): a_modif = a_modif * p**(e // 2) res = 0 for dsq in filter(lambda d: d.is_square(), a.divisors()): d = isqrt(dsq) for g_diag in itertools.ifilter( lambda diag: prod(diag) == d, itertools.product( *[d.divisors() for _ in xrange(t.nrows())])): for subents in itertools.product(*[ xrange(r) for (j, r) in enumerate(g_diag) for _ in xrange(j) ]): columns = [ subents[(j * (j - 1)) // 2:(j * (j + 1)) // 2] for j in xrange(t.nrows()) ] g = diagonal_matrix(list(g_diag)) for j in xrange(t.nrows()): for i in xrange(j): g[i, j] = columns[j][i] ginv = g.inverse() tg = ginv.transpose() * t * ginv try: tg = matrix(ZZ, tg) except: continue if any(tg[i, i] % 2 == 1 for i in xrange(tg.nrows())): continue tg.set_immutable() res = res + self._kohnen_rho(tg, a // dsq) return a_modif * res
def cardinality(self): r""" Cardinality of ``self``. The number of monotone triangles with `n` rows is equal to .. MATH:: \prod_{k=0}^{n-1} \frac{(3k+1)!}{(n+k)!} = \frac{1! 4! 7! 10! \cdots (3n-2)!}{n! (n+1)! (n+2)! (n+3)! \cdots (2n-1)!} EXAMPLES:: sage: M = MonotoneTriangles(4) sage: M.cardinality() 42 """ return Integer(prod( [ factorial(3*k+1)/factorial(self._n+k) for k in range(self._n)] ))
def E_integral(mu, q=None, t=None, pi=None): """ Returns the integral form for the non-symmetric Macdonald polynomial in type A corresponding to a shape mu. Note that if both q and t are specified, then they must have the same parent. REFERENCE: - J. Haglund, M. Haiman, N. Loehr. *A combinatorial formula for non-symmetric Macdonald polynomials*. :arXiv:`math/0601693v3`. EXAMPLES:: sage: from sage.combinat.sf.ns_macdonald import E_integral sage: E_integral([0,0,0]) 1 sage: E_integral([1,0,0]) (-t + 1)*x0 sage: E_integral([0,1,0]) (-q*t^2 + 1)*x0 + (-t + 1)*x1 sage: E_integral([0,0,1]) (-q*t + 1)*x0 + (-q*t + 1)*x1 + (-t + 1)*x2 sage: E_integral([1,1,0]) (t^2 - 2*t + 1)*x0*x1 sage: E_integral([1,0,1]) (q*t^3 - q*t^2 - t + 1)*x0*x1 + (t^2 - 2*t + 1)*x0*x2 sage: E_integral([0,1,1]) (q^2*t^3 + q*t^4 - q*t^3 - q*t^2 - q*t - t^2 + t + 1)*x0*x1 + (q*t^2 - q*t - t + 1)*x0*x2 + (t^2 - 2*t + 1)*x1*x2 sage: E_integral([2,0,0]) (t^2 - 2*t + 1)*x0^2 + (q^2*t^2 - q^2*t - q*t + q)*x0*x1 + (q^2*t^2 - q^2*t - q*t + q)*x0*x2 sage: E_integral([0,2,0]) (q^2*t^3 - q^2*t^2 - t + 1)*x0^2 + (q^4*t^3 - q^3*t^2 - q^2*t + q*t^2 - q*t + q - t + 1)*x0*x1 + (t^2 - 2*t + 1)*x1^2 + (q^4*t^3 - q^3*t^2 - q^2*t + q)*x0*x2 + (q^2*t^2 - q^2*t - q*t + q)*x1*x2 """ P, q, t, n, R, x = _check_muqt(mu, q, t, pi) res = 0 for a in n: weight = a.weight() res += q**a.maj() * t**a.coinv() * a.coeff_integral(q, t) * prod( x[i]**weight[i] for i in range(len(weight))) return res
def ncusps(self): r""" Return the number of cusps of this subgroup `\Gamma(N)`. EXAMPLES:: sage: [Gamma(n).ncusps() for n in [1..19]] [1, 3, 4, 6, 12, 12, 24, 24, 36, 36, 60, 48, 84, 72, 96, 96, 144, 108, 180] sage: Gamma(30030).ncusps() 278691840 sage: Gamma(2^30).ncusps() 432345564227567616 """ n = self.level() if n==1: return ZZ(1) if n==2: return ZZ(3) return prod([p**(2*e) - p**(2*e-2) for (p,e) in n.factor()])//2
def clifford_conductor(self): """ This is the product of all primes where the Clifford invariant is -1 Note: For ternary forms, this is the discriminant of the quaternion algebra associated to the quadratic space (i.e. the even Clifford algebra) EXAMPLES:: sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.clifford_invariant(2) 1 sage: Q.clifford_invariant(37) -1 sage: Q.clifford_conductor() 37 :: sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor() 2 sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor() 30 For hyperbolic spaces, the clifford conductor is 1:: sage: H = QuadraticForm(ZZ, 2, [0, 1, 0]) sage: H.clifford_conductor() 1 sage: (H + H).clifford_conductor() 1 sage: (H + H + H).clifford_conductor() 1 sage: (H + H + H + H).clifford_conductor() 1 """ D = self.disc() return prod( filter(lambda p: self.clifford_invariant(p) == -1, map(lambda x: x[0], factor(2 * self.level()))))
def order(self): """ Return the order (number of elements) of this finite subgroup. EXAMPLES:: sage: J = J0(42) sage: C = J.cuspidal_subgroup() sage: C.order() 2304 """ try: return self.__order except AttributeError: if self.__abvar.dimension() == 0: self.__order = ZZ(1) return self.__order o = prod(self.invariants()) self.__order = o return o
def __call__(self, g): """ Computes the value of a character self on a group element g (g must be an element of self.group()) EXAMPLES: sage: F = AbelianGroup(5, [2,3,5,7,8], names="abcde") sage: a,b,c,d,e = F.gens() sage: Fd = DualAbelianGroup(F, names="ABCDE") sage: A,B,C,D,E = Fd.gens() sage: A*B^2*D^7 A*B^2 sage: A(a) ## random last few digits -1.0000000000000000 + 0.00000000000000013834419720915037*I sage: B(b) ## random last few digits -0.49999999999999983 + 0.86602540378443871*I sage: A(a*b) ## random last few digits -1.0000000000000000 + 0.00000000000000013834419720915037*I """ F = self.parent().base_ring() expsX = list(self.list()) expsg = list(g.list()) invs = self.parent().invariants() N = LCM(invs) if is_ComplexField(F): from sage.symbolic.constants import pi I = F.gen() PI = F(pi) ans = prod([ exp(2 * PI * I * expsX[i] * expsg[i] / invs[i]) for i in range(len(expsX)) ]) return ans ans = F(1) ## assumes F is the cyclotomic field zeta = F.gen() #print F,zeta for i in range(len(expsX)): inv_noti = N / invs[i] ans = ans * zeta**(expsX[i] * expsg[i] * inv_noti) return ans
def order_of_general_linear_group(n, q=None): """ Return the cardinality of the group of `n \times n` invertible matrices with entries in a field of order ``q``. INPUT: - ``n`` -- a non-negative integer - ``q`` -- an integer or an indeterminate EXAMPLES:: sage: from sage.combinat.similarity_class_type import order_of_general_linear_group sage: order_of_general_linear_group(0) 1 sage: order_of_general_linear_group(2) q^4 - q^3 - q^2 + q """ if q is None: q = ZZ['q'].gen() return prod([q**n - q**i for i in range(n)])
def _to_s(self, part): """ Returns a function which gives the coefficient of a partition in the Schur expansion of self(part). EXAMPLES:: sage: S = MacdonaldPolynomialsS(QQ) sage: S2 = S._to_s(Partition([2])) sage: S2(Partition([2])) -t + 1 sage: S2(Partition([1,1])) t^2 - t """ #Covert to the power sum p = sfa.SFAPower(QQqt) s = sfa.SFASchur(QQqt) p_x = p(s(part)) t = self.t f = lambda m, c: (m, c * prod([(1 - t**k) for k in m])) res = s(p_x.map_item(f)) f = lambda part2: res.coefficient(part2) return f
def hasse_conductor(self): """ This is the product of all primes where the Hasse invariant equals -1 EXAMPLES:: sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5]) sage: Q.hasse_invariant(2) -1 sage: Q.hasse_invariant(37) -1 sage: Q.hasse_conductor() 74 :: sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor() 1 sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor() 10 """ D = self.disc() return prod([x[0] for x in factor(2 * self.level()) if self.hasse_invariant(x[0]) == -1])
def change_support(perm, support, change_perm=None): """ Changes the support of a permutation defined on [1, ..., n] to support. EXAMPLES:: sage: from sage.combinat.species.misc import change_support sage: p = PermutationGroupElement((1,2,3)); p (1,2,3) sage: change_support(p, [3,4,5]) (3,4,5) """ if change_perm is None: change_perm = prod([ PermutationGroupElement((i + 1, support[i])) for i in range(len(support)) if i + 1 != support[i] ], PermutationGroupElement([], SymmetricGroup(support))) if isinstance(perm, PermutationGroup_generic): return PermutationGroup( [change_support(g, support, change_perm) for g in perm.gens()]) return change_perm * perm * ~change_perm
def order(self): """ Return the order of this group. EXAMPLES:: sage: G = AbelianGroup(2,[2,3]) sage: G.order() 6 sage: G = AbelianGroup(3,[2,3,0]) sage: G.order() +Infinity """ try: return self.__len except AttributeError: from sage.rings.all import infinity, Integer if len(self.invariants()) < self.ngens(): self.__len = infinity else: self.__len = Integer(prod(self.invariants())) if self.__len == 0: self.__len = infinity return self.__len
def nu2(self): r""" Return the number of elliptic points of order 2 for this congruence subgroup `\Gamma_0(N)`. The number of these is given by a standard formula: 0 if `N` is divisible by 4 or any prime congruent to -1 mod 4, and otherwise `2^d` where d is the number of odd primes dividing `N`. EXAMPLE:: sage: Gamma0(2).nu2() 1 sage: Gamma0(4).nu2() 0 sage: Gamma0(21).nu2() 0 sage: Gamma0(1105).nu2() 8 sage: [Gamma0(n).nu2() for n in [1..19]] [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0] """ n = self.level() if n%4 == 0: return ZZ(0) return prod([ 1 + kronecker_symbol(-4, p) for p, _ in n.factor()])
def Kitaoka_mass_at_2(self): """ Returns the local mass of the quadratic form when `p=2`, according to Theorem 5.6.3 on pp108--9 of Kitaoka's Book "The Arithmetic of Quadratic Forms". INPUT: none OUTPUT: a rational number > 0 EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.Kitaoka_mass_at_2() ## WARNING: WE NEED TO CHECK THIS CAREFULLY! 1/2 """ ## Make a 0-dim'l quadratic form (for initialization purposes) Null_Form = copy.deepcopy(self) Null_Form.__init__(ZZ, 0) ## Step 0: Compute Jordan blocks and bounds of the scales to keep track of Jordan_Blocks = self.jordan_blocks_by_scale_and_unimodular(2) scale_list = [B[0] for B in Jordan_Blocks] s_min = min(scale_list) s_max = max(scale_list) ## Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale diag_dict = dict( (i, Null_Form) for i in range(s_min - 2, s_max + 4)) ## Initialize with the zero form dim2_dict = dict( (i, Null_Form) for i in range(s_min, s_max + 4)) ## Initialize with the zero form for (s, L) in Jordan_Blocks: i = 0 while (i < L.dim() - 1) and (L[i, i + 1] == 0): ## Find where the 2x2 blocks start i = i + 1 if i < (L.dim() - 1): diag_dict[s] = L.extract_variables(range(i)) ## Diagonal Form dim2_dict[s + 1] = L.extract_variables(range( i, L.dim())) ## Non-diagonal Form else: diag_dict[s] = L #print "diag_dict = ", diag_dict #print "dim2_dict = ", dim2_dict #print "Jordan_Blocks = ", Jordan_Blocks ################## START EDITING HERE ################## ## Compute q := sum of the q_j q = 0 for j in range(s_min, s_max + 1): if diag_dict[j].dim( ) > 0: ## Check that N_j is odd (i.e. rep'ns an odd #) if diag_dict[j + 1].dim() == 0: q += Jordan_Blocks[j][1].dim( ) ## When N_{j+1} is "even", add n_j else: q += Jordan_Blocks[j][1].dim( ) + 1 ## When N_{j+1} is "odd", add n_j + 1 ## Compute P = product of the P_j P = QQ(1) for j in range(s_min, s_max + 1): tmp_m = dim2_dict[j].dim() / 2 P *= prod([QQ(1) - QQ(4**(-k)) for j in range(1, tmp_m + 1)]) ## Compute the product E := prod_j (1 / E_j) E = QQ(1) for j in range(s_min - 1, s_max + 2): if (diag_dict[j-1].dim() == 0) and (diag_dict[j+1].dim() == 0) and \ ((diag_dict[j].dim() != 2) or (((diag_dict[j][0,0] - diag_dict[j][1,1]) % 4) != 0)): ## Deal with the complicated case: tmp_m = dim2_dict[j].dim() / 2 if dim2_dict[j].is_hyperbolic(2): E *= 2 / (1 + 2**(-tmp_m)) else: E *= 2 / (1 - 2**(-tmp_m)) else: E *= 2 ## DIAGNOSTIC #print "\nFinal Summary:" #print "nu =", nu #print "q = ", q #print "P = ", P #print "E = ", E ## Compute the exponent w w = QQ(0) for j in range(s_min, s_max + 1): n_j = Jordan_Blocks[j][1].dim() for k in range(j + 1, s_max + 1): n_k = Jordan_Blocks[k][1].dim() w += j * n_j * (n_k + QQ(n_j + 1) / 2) ## Step 5: Compute the local mass for the prime 2. mass_at_2 = (QQ(2)**(w - q)) * P * E return mass_at_2
def mass__by_Siegel_densities(self, odd_algorithm="Pall", even_algorithm="Watson"): """ Gives the mass of transformations (det 1 and -1). WARNING: THIS IS BROKEN RIGHT NOW... =( Optional Arguments: - When p > 2 -- odd_algorithm = "Pall" (only one choice for now) - When p = 2 -- even_algorithm = "Kitaoka" or "Watson" REFERENCES: - Nipp's Book "Tables of Quaternary Quadratic Forms". - Papers of Pall (only for p>2) and Watson (for `p=2` -- tricky!). - Siegel, Milnor-Hussemoller, Conway-Sloane Paper IV, Kitoaka (all of which have problems...) EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1]) sage: Q.mass__by_Siegel_densities() 1/384 sage: Q.mass__by_Siegel_densities() - (2^Q.dim() * factorial(Q.dim()))^(-1) 0 :: sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1]) sage: Q.mass__by_Siegel_densities() 1/48 sage: Q.mass__by_Siegel_densities() - (2^Q.dim() * factorial(Q.dim()))^(-1) 0 """ ## Setup n = self.dim() s = floor((n - 1) / 2) if n % 2 != 0: char_d = squarefree_part(2 * self.det()) ## Accounts for the det as a QF else: char_d = squarefree_part(self.det()) ## Form the generic zeta product generic_prod = ZZ(2) * (pi)**(-ZZ(n) * (n + 1) / 4) ########################################## generic_prod *= (self.det())**( ZZ(n + 1) / 2) ## ***** This uses the Hessian Determinant ******** ########################################## #print "gp1 = ", generic_prod generic_prod *= prod([gamma__exact(ZZ(j) / 2) for j in range(1, n + 1)]) #print "\n---", [(ZZ(j)/2, gamma__exact(ZZ(j)/2)) for j in range(1,n+1)] #print "\n---", prod([gamma__exact(ZZ(j)/2) for j in range(1,n+1)]) #print "gp2 = ", generic_prod generic_prod *= prod([zeta__exact(ZZ(j)) for j in range(2, 2 * s + 1, 2)]) #print "\n---", [zeta__exact(ZZ(j)) for j in range(2, 2*s+1, 2)] #print "\n---", prod([zeta__exact(ZZ(j)) for j in range(2, 2*s+1, 2)]) #print "gp3 = ", generic_prod if (n % 2 == 0): generic_prod *= ZZ(1) * quadratic_L_function__exact( n / 2, (-1)**(n / 2) * char_d) #print " NEW = ", ZZ(1) * quadratic_L_function__exact(n/2, (-1)**(n/2) * char_d) #print #print "gp4 = ", generic_prod #print "generic_prod =", generic_prod ## Determine the adjustment factors adj_prod = 1 for p in prime_divisors(2 * self.det()): ## Cancel out the generic factors p_adjustment = prod([1 - ZZ(p)**(-j) for j in range(2, 2 * s + 1, 2)]) if (n % 2 == 0): p_adjustment *= ZZ(1) * (1 - kronecker( (-1)**(n / 2) * char_d, p) * ZZ(p)**(-n / 2)) #print " EXTRA = ", ZZ(1) * (1 - kronecker((-1)**(n/2) * char_d, p) * ZZ(p)**(-n/2)) #print "Factor to cancel the generic one:", p_adjustment ## Insert the new mass factors if p == 2: if even_algorithm == "Kitaoka": p_adjustment = p_adjustment / self.Kitaoka_mass_at_2() elif even_algorithm == "Watson": p_adjustment = p_adjustment / self.Watson_mass_at_2() else: raise TypeError( "There is a problem -- your even_algorithm argument is invalid. Try again. =(" ) else: if odd_algorithm == "Pall": p_adjustment = p_adjustment / self.Pall_mass_density_at_odd_prime( p) else: raise TypeError( "There is a problem -- your optional arguments are invalid. Try again. =(" ) #print "p_adjustment for p =", p, "is", p_adjustment ## Put them together (cumulatively) adj_prod *= p_adjustment #print "Cumulative adj_prod =", adj_prod ## Extra adjustment for the case of a 2-dimensional form. #if (n == 2): # generic_prod *= 2 ## Return the mass mass = generic_prod * adj_prod return mass
def _span_of_forms_in_weight(forms, weight, prec, stop_dim=None, use_random=False): r""" Utility function. Given a nonempty list of pairs ``(k,f)``, where `k` is an integer and `f` is a power series, and a weight l, return all weight l forms obtained by multiplying together the given forms. INPUT: - ``forms`` -- list of pairs `(k, f)` with k an integer and f a power series (all over the same base ring) - ``weight`` -- an integer - ``prec`` -- an integer (less than or equal to the precision of all the forms in ``forms``) -- precision to use in power series computations. - ``stop_dim`` -- an integer: stop as soon as we have enough forms to span a submodule of this rank (a saturated one if the base ring is `\ZZ`). Ignored if ``use_random`` is False. - ``use_random`` -- which algorithm to use. If True, tries random products of the generators of the appropriate weight until a large enough submodule is found (determined by ``stop_dim``). If False, just tries everything. Note that if the given forms do generate the whole space, then ``use_random=True`` will often be quicker (particularly if the weight is large); but if the forms don't generate, the randomized algorithm is no help and will actually be substantially slower, because it needs to do repeated echelon form calls to check if vectors are in a submodule, while the non-randomized algorithm just echelonizes one enormous matrix at the end. EXAMPLES:: sage: import sage.modular.modform.find_generators as f sage: forms = [(4, 240*eisenstein_series_qexp(4,5)), (6,504*eisenstein_series_qexp(6,5))] sage: f._span_of_forms_in_weight(forms, 12, prec=5) Vector space of degree 5 and dimension 2 over Rational Field Basis matrix: [ 1 0 196560 16773120 398034000] [ 0 1 -24 252 -1472] sage: f._span_of_forms_in_weight(forms, 24, prec=5) Vector space of degree 5 and dimension 3 over Rational Field Basis matrix: [ 1 0 0 52416000 39007332000] [ 0 1 0 195660 12080128] [ 0 0 1 -48 1080] sage: ModularForms(1, 24).q_echelon_basis(prec=5) [ 1 + 52416000*q^3 + 39007332000*q^4 + O(q^5), q + 195660*q^3 + 12080128*q^4 + O(q^5), q^2 - 48*q^3 + 1080*q^4 + O(q^5) ] Test the alternative randomized algorithm:: sage: f._span_of_forms_in_weight(forms, 24, prec=5, use_random=True, stop_dim=3) Vector space of degree 5 and dimension 3 over Rational Field Basis matrix: [ 1 0 0 52416000 39007332000] [ 0 1 0 195660 12080128] [ 0 0 1 -48 1080] """ t = verbose('multiplying forms up to weight %s'%weight) # Algorithm: run through the monomials of the appropriate weight, and build # up the vector space they span. n = len(forms) R = forms[0][1].base_ring() V = R ** prec W = V.zero_submodule() shortforms = [f[1].truncate_powerseries(prec) for f in forms] # List of weights from sage.combinat.integer_vector_weighted import WeightedIntegerVectors wts = list(WeightedIntegerVectors(weight, [f[0] for f in forms])) t = verbose("calculated weight list", t) N = len(wts) if use_random: if stop_dim is None: raise ValueError("stop_dim must be provided if use_random is True") shuffle(wts) for c in xrange(N): w = V(prod(shortforms[i]**wts[c][i] for i in xrange(n)).padded_list(prec)) if w in W: continue W = V.span(list(W.gens()) + [w]) if stop_dim and W.rank() == stop_dim: if R != ZZ or W.index_in_saturation() == 1: verbose("Succeeded after %s of %s" % (c, N), t) return W verbose("Nothing worked", t) return W else: G = [V(prod(forms[i][1]**c[i] for i in xrange(n)).padded_list(prec)) for c in wts] t = verbose('found %s candidates' % N, t) W = V.span(G) verbose('span has dimension %s' % W.rank(), t) return W
def partial_fraction_decomposition(self): """ Decomposes fraction field element into a whole part and a list of fraction field elements over prime power denominators. The sum will be equal to the original fraction. AUTHORS: - Robert Bradshaw (2007-05-31) EXAMPLES:: sage: S.<t> = QQ[] sage: q = 1/(t+1) + 2/(t+2) + 3/(t-3); q (6*t^2 + 4*t - 6)/(t^3 - 7*t - 6) sage: whole, parts = q.partial_fraction_decomposition(); parts [3/(t - 3), 1/(t + 1), 2/(t + 2)] sage: sum(parts) == q True sage: q = 1/(t^3+1) + 2/(t^2+2) + 3/(t-3)^5 sage: whole, parts = q.partial_fraction_decomposition(); parts [1/3/(t + 1), 3/(t^5 - 15*t^4 + 90*t^3 - 270*t^2 + 405*t - 243), (-1/3*t + 2/3)/(t^2 - t + 1), 2/(t^2 + 2)] sage: sum(parts) == q True We do the best we can over inexact fields:: sage: R.<x> = RealField(20)[] sage: q = 1/(x^2 + x + 2)^2 + 1/(x-1); q (x^4 + 2.0000*x^3 + 5.0000*x^2 + 5.0000*x + 3.0000)/(x^5 + x^4 + 3.0000*x^3 - x^2 - 4.0000) sage: whole, parts = q.partial_fraction_decomposition(); parts [1.0000/(x - 1.0000), 1.0000/(x^4 + 2.0000*x^3 + 5.0000*x^2 + 4.0000*x + 4.0000)] sage: sum(parts) (x^4 + 2.0000*x^3 + 5.0000*x^2 + 5.0000*x + 3.0000)/(x^5 + x^4 + 3.0000*x^3 - x^2 - 4.0000) TESTS: We test partial fraction for irreducible denominators:: sage: R.<x> = ZZ[] sage: q = x^2/(x-1) sage: q.partial_fraction_decomposition() (x + 1, [1/(x - 1)]) sage: q = x^10/(x-1)^5 sage: whole, parts = q.partial_fraction_decomposition() sage: whole + sum(parts) == q True And also over finite fields (see trac #6052, #9945):: sage: R.<x> = GF(2)[] sage: q = (x+1)/(x^3+x+1) sage: q.partial_fraction_decomposition() (0, [(x + 1)/(x^3 + x + 1)]) sage: R.<x> = GF(11)[] sage: q = x + 1 + 1/(x+1) + x^2/(x^3 + 2*x + 9) sage: q.partial_fraction_decomposition() (x + 1, [1/(x + 1), x^2/(x^3 + 2*x + 9)]) And even the rationals:: sage: (26/15).partial_fraction_decomposition() (1, [1/3, 2/5]) """ from sage.misc.misc import prod denom = self.denominator() whole, numer = self.numerator().quo_rem(denom) factors = denom.factor() if factors.unit() != 1: numer *= ~factors.unit() if len(factors) == 1: return whole, [numer/r**e for r,e in factors] if not self.parent().is_exact(): # factors not grouped in this case all = {} for r in factors: all[r[0]] = 0 for r in factors: all[r[0]] += r[1] factors = all.items() factors.sort() # for doctest consistency factors = [r**e for r,e in factors] parts = [] for d in factors: # note that the product below is non-empty, since the case # of only one factor has been dealt with above n = numer * prod([r for r in factors if r != d]).inverse_mod(d) % d # we know the inverse exists as the two are relatively prime parts.append(n/d) return whole, parts