def q_catalan_number(n, q=None): """ Returns the `q`-Catalan number of index `n`. If `q` 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, q) for j in range(n+2, 2*n+1)) / prod(q_int(j, q) for j in range(2,n+1)) else: raise ValueError("Argument (%s) must be a nonnegative integer." %n)
def rational_catalan_number(self, p, polynomial=False): r""" Return the ``p``-th rational Catalan number associated to ``self``. It is defined by .. MATH:: \prod_{i = 1}^n \frac{p + (p(d_i-1)) \mod h)}{d_i}, where `d_1, \ldots, d_n` are the degrees and `h` is the Coxeter number. See [STW2016]_ for this formula. INPUT: - ``polynomial`` -- optional boolean (default ``False``) if ``True``, return instead the `q`-analogue as a polynomial in `q` REFERENCES: .. [STW2016] C. Stump, H. Thomas, N. Williams. *Cataland II*, in preparation, 2016. EXAMPLES:: sage: W = ColoredPermutations(1,3) sage: [W.rational_catalan_number(p) for p in [5,7,8]] [7, 12, 15] sage: W = ColoredPermutations(2,2) sage: [W.rational_catalan_number(p) for p in [7,9,11]] [10, 15, 21] TESTS:: sage: W = ColoredPermutations(1,4) sage: W.rational_catalan_number(3, polynomial=True) q^6 + q^4 + q^3 + q^2 + 1 """ from sage.arith.all import gcd from sage.combinat.q_analogues import q_int h = self.coxeter_number() if not gcd(h, p) == 1: raise ValueError( "parameter p = %s is not coprime to the Coxeter number %s" % (p, h)) if polynomial: f = q_int else: f = lambda n: n num = prod( f(p + (p * (deg - 1)) % h) for deg in self.degrees()) den = prod(f(deg) for deg in self.degrees()) return num // den
def weyl_dimension(self, highest_weight): r""" Return the dimension of the highest weight representation of highest weight ``highest_weight``. EXAMPLES:: sage: RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0]) 20 sage: P = RootSystem(['C',2]).weight_lattice() sage: La = P.basis() sage: P.weyl_dimension(La[1]+La[2]) 16 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) <type 'sage.rings.integer.Integer'> """ highest_weight = self(highest_weight) if not highest_weight.is_dominant(): raise ValueError("the highest weight must be dominant") rho = self.rho() pr = self.coroot_lattice().positive_roots() from sage.rings.integer import Integer n = prod(((rho+highest_weight).scalar(x) for x in pr), Integer(1)) d = prod((rho.scalar(x) for x in pr), Integer(1)) return Integer(n/d)
def weyl_dimension(self, highest_weight): r""" Return the dimension of the highest weight representation of highest weight ``highest_weight``. EXAMPLES:: sage: RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0]) 20 sage: P = RootSystem(['C',2]).weight_lattice() sage: La = P.basis() sage: P.weyl_dimension(La[1]+La[2]) 16 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) <... 'sage.rings.integer.Integer'> """ highest_weight = self(highest_weight) if not highest_weight.is_dominant(): raise ValueError("the highest weight must be dominant") rho = self.rho() pr = self.coroot_lattice().positive_roots() from sage.rings.integer import Integer n = prod(((rho + highest_weight).scalar(x) for x in pr), Integer(1)) d = prod((rho.scalar(x) for x in pr), Integer(1)) return Integer(n / d)
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.DuadicCodeOddPair(GF(q),S1,S2) ([11, 6] Cyclic Code over GF(3), [11, 6] Cyclic Code over GF(3)) This is consistent with Theorem 6.1.3 in [HP2003]_. """ from sage.misc.stopgap import stopgap stopgap( "The function DuadicCodeOddPair has several issues which may cause wrong results", 25896) from .cyclic_code import CyclicCode n = len(S1) + len(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).coefficients(sparse=False) ] coeffs2 = [ _lift2smallest_field(c)[0] for c in (g2 + j).coefficients(sparse=False) ] gg1 = P2(coeffs1) gg2 = P2(coeffs2) gg1 = gcd(gg1, x**n - 1) gg2 = gcd(gg2, x**n - 1) C1 = CyclicCode(length=n, generator_pol=gg1) C2 = CyclicCode(length=n, generator_pol=gg2) return C1, C2
def weil_representation(self) : r""" OUTPUT: - A pair of matrices corresponding to T and S. """ disc_bilinear = lambda a, b: (self._dual_basis * vector(QQ, a.lift())) * self._L * (self._dual_basis * vector(QQ, b.lift())) disc_quadratic = lambda a: disc_bilinear(a, a) / ZZ(2) zeta_order = ZZ(lcm([8, 12, prod(self.invariants())] + map(lambda ed: 2 * ed, self.invariants()))) K = CyclotomicField(zeta_order); zeta = K.gen() R = PolynomialRing(K, 'x'); x = R.gen() # sqrt2s = (x**2 - 2).factor() # if sqrt2s[0][0][0].complex_embedding().real() > 0 : # sqrt2 = sqrt2s[0][0][0] # else : # sqrt2 = sqrt2s[0][1] Ldet_rts = (x**2 - prod(self.invariants())).factor() if Ldet_rts[0][0][0].complex_embedding().real() > 0 : Ldet_rt = Ldet_rts[0][0][0] else : Ldet_rt = Ldet_rts[0][0][0] Tmat = diagonal_matrix( K, [zeta**(zeta_order*disc_quadratic(a)) for a in self] ) Smat = zeta**(zeta_order / 8 * self._L.nrows()) / Ldet_rt \ * matrix( K, [ [ zeta**ZZ(-zeta_order * disc_bilinear(gamma,delta)) for delta in self ] for gamma in self ]) return (Tmat, Smat)
def rational_catalan_number(self, p, polynomial=False): r""" Return the ``p``-th rational Catalan number associated to ``self``. It is defined by .. MATH:: \prod_{i = 1}^n \frac{p + (p(d_i-1)) \mod h)}{d_i}, where `d_1, \ldots, d_n` are the degrees and `h` is the Coxeter number. See [STW2016]_ for this formula. INPUT: - ``polynomial`` -- optional boolean (default ``False``) if ``True``, return instead the `q`-analogue as a polynomial in `q` REFERENCES: .. [STW2016] C. Stump, H. Thomas, N. Williams. *Cataland II*, in preparation, 2016. EXAMPLES:: sage: W = ColoredPermutations(1,3) sage: [W.rational_catalan_number(p) for p in [5,7,8]] [7, 12, 15] sage: W = ColoredPermutations(2,2) sage: [W.rational_catalan_number(p) for p in [7,9,11]] [10, 15, 21] TESTS:: sage: W = ColoredPermutations(1,4) sage: W.rational_catalan_number(3, polynomial=True) q^6 + q^4 + q^3 + q^2 + 1 """ from sage.arith.all import gcd from sage.combinat.q_analogues import q_int h = self.coxeter_number() if not gcd(h,p) == 1: raise ValueError("parameter p = %s is not coprime to the Coxeter number %s" % (p, h)) if polynomial: f = q_int else: f = lambda n: n num = prod(f(p + (p * (deg - 1)) % h) for deg in self.degrees()) den = prod(f(deg) for deg in self.degrees()) return num // den
def good_primes(B): r""" Given the bound, returns the primes whose product is greater than ``B`` and which would take the least amount of time to run the main sieve algorithm Complexity of finding points modulo primes is assumed to be N^2 * P_max^{N}. Complexity of lifting points and the LLL() function is assumed to be close to (dim_max^5) * (alpha / P_max)^dim_scheme. where alpha is the product of all primes, P_max is the largest prime in the list, dim_max is the max dimension of all components, and N is the dimension of the ambient space. """ M = dict() # stores optimal list of primes, corresponding to list size small_primes = sufficient_primes(B) max_length = len(small_primes) M[max_length] = small_primes current_count = max_length - 1 dim = X.ambient_space().dimension() while current_count > 1: current_list = [] # stores prime which are bigger than least updated_list = [] best_list = [] least = (RR(B)**(1.00 / current_count)).floor() for i in range(current_count): current_list.append(next_prime(least)) least = current_list[-1] # improving list of primes by taking primes less than least # this part of algorithm is used to centralize primes around `least` prod_prime = prod(current_list) least = current_list[0] while least != 2 and prod_prime > B and len( updated_list) < current_count: best_list = updated_list + current_list[:current_count - len(updated_list)] updated_list.append(previous_prime(least)) least = updated_list[-1] removed_prime = current_list[current_count - len(updated_list)] prod_prime = (prod_prime * least) / removed_prime M[current_count] = sorted(best_list) current_count = current_count - 1 best_size = 2 best_time = (dim**2) * M[2][-1]**(dim) + ( dim_max**5 * (prod(M[2]) / M[2][-1])**dim_scheme) for i in range(2, max_length + 1): current_time = (dim**2) * M[i][-1]**(dim) + ( dim_max**5 * (prod(M[i]) / M[i][-1])**dim_scheme) if current_time < best_time: best_size = i best_time = current_time return M[best_size]
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.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 = len(S1) + len(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).coefficients(sparse=False) ] coeffs2 = [ lift2smallest_field(c)[0] for c in (g2 + j).coefficients(sparse=False) ] gg1 = P2(coeffs1) gg2 = P2(coeffs2) C1 = CyclicCodeFromGeneratingPolynomial(n, gg1) C2 = CyclicCodeFromGeneratingPolynomial(n, gg2) return C1, C2
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.DuadicCodeEvenPair(GF(q),S1,S2) ([11, 5] Cyclic Code over GF(3), [11, 5] Cyclic Code over GF(3)) """ from sage.misc.stopgap import stopgap stopgap( "The function DuadicCodeEvenPair has several issues which may cause wrong results", 25896) from .cyclic_code import CyclicCode n = len(S1) + len(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.coefficients(sparse=False)]) gg2 = P2( [_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)]) C1 = CyclicCode(length=n, generator_pol=gg1) C2 = CyclicCode(length=n, generator_pol=gg2) return C1, C2
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.DuadicCodeOddPair(GF(q),S1,S2) ([11, 6] Cyclic Code over GF(3), [11, 6] Cyclic Code over GF(3)) This is consistent with Theorem 6.1.3 in [HP2003]_. """ from .cyclic_code import CyclicCode n = len(S1) + len(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).coefficients(sparse=False)] coeffs2 = [_lift2smallest_field(c)[0] for c in (g2+j).coefficients(sparse=False)] gg1 = P2(coeffs1) gg2 = P2(coeffs2) gg1 = gcd(gg1, x**n - 1) gg2 = gcd(gg2, x**n - 1) C1 = CyclicCode(length = n, generator_pol = gg1) C2 = CyclicCode(length = n, generator_pol = gg2) return C1,C2
def f(partition): denom = prod((1 - q**part) for part in partition) try: ~denom rational = prod( (1 - q**(n * part)) for part in partition) / denom return q.parent()(rational) except (ZeroDivisionError, NotImplementedError, TypeError): # If denom is not invertible, we need to do the # computation with universal coefficients instead: quotient = ZZq( prod((1 - q_lim**(n * part)) / (1 - q_lim**part) for part in partition)) return quotient.subs({q_lim: q})
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 find_unique_orbit_lucas(k, G): ''' Lucas functions (Pell's conic) variant of Rains' algorithm. Only works with k = F_{p^n}, p ≠ 2, and G ⊂ ℤ/m*, where 1. <p> ⊂ ℤ/m* is of order r⋅2, 2. gcd(n, 2) = 1, 3. ℤ/m* = <p^2> × G. Return a Gaussian period of m-th roots of unity of k. ''' m = G[0][0].parent().order() q = k.cardinality() assert ((q + 1) % m == 0) cofactor = (q + 1) // m sqtest = (q - 1) // 2 fact = m.factor() # find an m-th root of unity zeta = 2 while any(lucas_pow(zeta, m // f[0]) == 2 for f in fact): a = k.random_element() if (a**2 - 4)**sqtest == 1: continue zeta = lucas_pow(a, cofactor) # return the Gaussian period # ... lovely combinatorial iterators! return sum( lucas_pow(zeta, prod(g**e for (g, _), e in zip(G, exps)).lift()) for exps in CProd(map(lambda (_, x): range(x), G))) / 2
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.all import prod return prod([(np+1)*np**(e-1) \ for np,e in [(p.absolute_norm(),e) \ for p,e in N.factor()]])
def c2(part, t): r""" Returns the t-Jack scalar product between ``J(part)`` and ``Q(part)``. INPUT: - ``self`` -- a Jack basis of the symmetric functions - ``part`` -- a partition - ``t`` -- an optional parameter (default: uses the parameter `t` from the Jack basis) OUTPUT: - a polynomial in the parameter ``t`` which is equal to the scalar product of ``J(part)`` and ``Q(part)`` 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().one(), )
def c1(part, t): r""" Returns the `t`-Jack scalar product between ``J(part)`` and ``P(part)``. INPUT: - ``part`` -- a partition - ``t`` -- an optional parameter (default: uses the parameter `t` from the Jack basis) OUTPUT: - a polynomial in the parameter ``t`` which is equal to the scalar product of ``J(part)`` and ``P(part)`` 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().one(), )
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 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 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 = builtins.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 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 = builtins.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 find_unique_orbit_lucas(k, G): ''' Lucas functions (Pell's conic) variant of Rains' algorithm. Only works with k = F_{p^n}, p ≠ 2, and G ⊂ ℤ/m*, where 1. <p> ⊂ ℤ/m* is of order r⋅2, 2. gcd(n, 2) = 1, 3. ℤ/m* = <p^2> × G. Return a Gaussian period of m-th roots of unity of k. ''' m = G[0][0].parent().order() q = k.cardinality() assert((q+1) % m == 0) cofactor = (q + 1) // m sqtest = (q - 1) // 2 fact = m.factor() # find an m-th root of unity zeta = 2 while any(lucas_pow(zeta, m // f[0]) == 2 for f in fact): a = k.random_element() if (a**2 - 4)**sqtest == 1: continue zeta = lucas_pow(a, cofactor) # return the Gaussian period # ... lovely combinatorial iterators! return sum(lucas_pow(zeta, prod(g**e for (g, _), e in zip(G, exps)).lift()) for exps in CProd(map(lambda (_,x): range(x), G)))/2
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 cardinality(self): r""" Return the cardinality of ``self``. The number of plane partitions inside an `a \times b \times c` box is equal to .. MATH:: \prod_{i=1}^{a} \prod_{j=1}^{b} \prod_{k=1}^{c} \frac{i+j+k-1}{i+j+k-2}. EXAMPLES:: sage: P = PlanePartitions((4,3,5)) sage: P.cardinality() 116424 """ A = self._box[0] B = self._box[1] C = self._box[2] return Integer( prod( Integer(i + j + k - 1) / Integer(i + j + k - 2) for i in range(1, A + 1) for j in range(1, B + 1) for k in range(1, C + 1)))
def _sage_(self): """ EXAMPLES:: sage: m = lie('[[1,0,3,3],[12,4,-4,7],[-1,9,8,0],[3,-5,-2,9]]') # optional - lie sage: m.sage() # optional - lie [ 1 0 3 3] [12 4 -4 7] [-1 9 8 0] [ 3 -5 -2 9] """ t = self.type() if t == "grp": raise ValueError("cannot convert Lie groups to native Sage objects") elif t == "mat": import sage.matrix.constructor return sage.matrix.constructor.matrix(eval(str(self).replace("\n", "").strip())) elif t == "pol": from sage.rings.all import PolynomialRing, QQ # Figure out the number of variables s = str(self) open_bracket = s.find("[") close_bracket = s.find("]") nvars = len(s[open_bracket:close_bracket].split(",")) # create the polynomial ring R = PolynomialRing(QQ, nvars, "x") x = R.gens() pol = R(0) # Split up the polynomials into terms terms = [] for termgrp in s.split(" - "): # The first entry in termgrp has # a negative coefficient termgrp = "-" + termgrp.strip() terms += termgrp.split("+") # Make sure we don't accidentally add a negative # sign to the first monomial if s[0] != "-": terms[0] = terms[0][1:] # go through all the terms in s for term in terms: xpos = term.find("X") coef = eval(term[:xpos].strip()) exps = eval(term[xpos + 1 :].strip()) monomial = prod([x[i] ** exps[i] for i in range(nvars)]) pol += coef * monomial return pol elif t == "tex": return repr(self) elif t == "vid": return None else: return ExpectElement._sage_(self)
def number_of_reflections_of_full_support(self): r""" Return the number of reflections with full support. EXAMPLES:: sage: W = Permutations(4) sage: W.number_of_reflections_of_full_support() 1 sage: W = ColoredPermutations(1,4) sage: W.number_of_reflections_of_full_support() 1 sage: W = CoxeterGroup("B3") sage: W.number_of_reflections_of_full_support() 3 sage: W = ColoredPermutations(3,3) sage: W.number_of_reflections_of_full_support() 3 """ n = self.rank() h = self.coxeter_number() l = self.cardinality() return (n * h * prod(d for d in self.codegrees() if d != 0)) // l
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_ring=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 = [] ker = self.rays().matrix().integer_kernel().matrix() for phases in itertools.product(units, repeat=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 selmer_group_iterator(self, S, m, proof=True): r""" Return an iterator through elements of the finite group `\QQ(S,m)`. INPUT: - ``S`` -- a set of primes - ``m`` -- a positive integer - ``proof`` -- ignored OUTPUT: An iterator yielding the distinct elements of `\QQ(S,m)`. See the docstring for :meth:`selmer_group` for more information. EXAMPLES:: sage: list(QQ.selmer_group_iterator((), 2)) [1, -1] sage: list(QQ.selmer_group_iterator((2,), 2)) [1, 2, -1, -2] sage: list(QQ.selmer_group_iterator((2,3), 2)) [1, 3, 2, 6, -1, -3, -2, -6] sage: list(QQ.selmer_group_iterator((5,), 2)) [1, 5, -1, -5] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) one = self.one() from sage.misc.all import prod from itertools import product for ev in product(*[range(o) for o in ords]): yield prod((p**e for p,e in zip(KSgens, ev)), one)
def q_factorial(n, q=None): """ Returns the `q`-analogue of the factorial `n!`. If `q` 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 non-negative 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, q) for i in range(1, n+1)]) else: raise ValueError("Argument (%s) must be a nonnegative integer." %n)
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 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 __getitem__(self, support): r""" Return the cyclically decreasing element associated with ``support``. INPUT: - ``support`` -- a proper subset of the index_set, as a list or set 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) if not set(support).issubset(set(index_set)) or support == index_set: raise ValueError( "the support must be a proper subset of the index set") if not support: 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 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 radical_value(self): """ Return the product of the prime factors in self. First, check that all exponents in the factorization are positive, raise ValueError otherwise. If all exponents are positive, return the product of the prime factors in self. This should be functionally equivalent to self.radical().value() EXAMPLES:: sage: F = factor(-100); F -1 * 2^2 * 5^2 sage: F.radical_value() 10 sage: factor(1/2).radical_value() Traceback (most recent call last): ... ValueError: All exponents in the factorization must be positive. """ if not all([e > 0 for p, e in self.__x]): raise ValueError( "All exponents in the factorization must be positive.") return prod([p for p, e in self.__x])
def __getitem__(self, support): r""" Return the cyclically decreasing element associated with ``support``. INPUT: - ``support`` -- a proper subset of the index_set, as a list or set 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) if not set(support).issubset(set(index_set)) or support == index_set: raise ValueError("the support must be a proper subset of the index set") if not support: 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 psi(N): r""" 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.all 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): 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 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 qexp(self, prec, verbose=False): """ The q-expansion of a monomial in Eisenstein series. INPUT: - prec -- positive integer - verbose -- bool (default: False) EXAMPLES:: sage: from psage.modform.rational.special import EisensteinMonomial sage: e = EisensteinMonomial([(5,4,2), (5,6,3)]) sage: e.qexp(11) -1/7374186086400 + 43/307257753600*q^5 - 671/102419251200*q^10 + O(q^11) sage: E4 = eisenstein_series_qexp(4,11); q = E4.parent().gen() sage: E6 = eisenstein_series_qexp(6,11) sage: (E4(q^5)^2 * E6(q^5)^3).add_bigoh(11) -1/7374186086400 + 43/307257753600*q^5 - 671/102419251200*q^10 + O(q^11) """ z = [eis_qexp(k, t, prec, verbose=verbose)**e for t, k, e in self._v] if verbose: print("Arithmetic to compute {0} +O(q^{1})".format(self, prec)) sys.stdout.flush() t = cputime() p = prod(z) if verbose: print("(time = {0:.2f} seconds)".format(cputime(t))) return p
def selmer_group_iterator(self, S, m, proof=True): r""" Return an iterator through elements of the finite group `\QQ(S,m)`. INPUT: - ``S`` -- a set of primes - ``m`` -- a positive integer - ``proof`` -- ignored OUTPUT: An iterator yielding the distinct elements of `\QQ(S,m)`. See the docstring for :meth:`selmer_group` for more information. EXAMPLES:: sage: list(QQ.selmer_group_iterator((), 2)) [1, -1] sage: list(QQ.selmer_group_iterator((2,), 2)) [1, 2, -1, -2] sage: list(QQ.selmer_group_iterator((2,3), 2)) [1, 3, 2, 6, -1, -3, -2, -6] sage: list(QQ.selmer_group_iterator((5,), 2)) [1, 5, -1, -5] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) one = self.one() from sage.misc.all import prod from itertools import product for ev in product(*[range(o) for o in ords]): yield prod((p**e for p, e in zip(KSgens, ev)), one)
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 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.all import prod return [prod([u**e for u,e in zip(ulist,ei)],k(1)) for ei in xmrange(elist)]
def _sage_(self): """ EXAMPLES:: sage: m = lie('[[1,0,3,3],[12,4,-4,7],[-1,9,8,0],[3,-5,-2,9]]') # optional - lie sage: m.sage() # optional - lie [ 1 0 3 3] [12 4 -4 7] [-1 9 8 0] [ 3 -5 -2 9] """ t = self.type() if t == 'grp': raise ValueError("cannot convert Lie groups to native Sage objects") elif t == 'mat': import sage.matrix.constructor return sage.matrix.constructor.matrix( eval( str(self).replace('\n','').strip()) ) elif t == 'pol': from sage.rings.all import PolynomialRing, QQ #Figure out the number of variables s = str(self) open_bracket = s.find('[') close_bracket = s.find(']') nvars = len(s[open_bracket:close_bracket].split(',')) #create the polynomial ring R = PolynomialRing(QQ, nvars, 'x') x = R.gens() pol = R(0) #Split up the polynomials into terms terms = [] for termgrp in s.split(' - '): #The first entry in termgrp has #a negative coefficient termgrp = "-"+termgrp.strip() terms += termgrp.split('+') #Make sure we don't accidentally add a negative #sign to the first monomial if s[0] != "-": terms[0] = terms[0][1:] #go through all the terms in s for term in terms: xpos = term.find('X') coef = eval(term[:xpos].strip()) exps = eval(term[xpos+1:].strip()) monomial = prod([x[i]**exps[i] for i in range(nvars)]) pol += coef * monomial return pol elif t == 'tex': return repr(self) elif t == 'vid': return None else: return ExpectElement._sage_(self)
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.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 = len(S1) + len(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.coefficients(sparse=False)]) gg2 = P2( [lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)]) C1 = CyclicCodeFromGeneratingPolynomial(n, gg1) C2 = CyclicCodeFromGeneratingPolynomial(n, gg2) return C1, C2
def _init_product_vectors(self, i): r""" Helper to build up ``self._vectors`` incrementally during the constructor. INPUT: - `i` -- list/tuple of integers. Multi-index of length equal to the number of constituent vector collections. The $j$-th entry $i[j]$ indexes a ray in the $j$-th vector collection. Hence, $i$ specifies one element in each vector collection. OUTPUT: This method mutates the :class:`TensorOperation` instance. In particular, the tensor product of the vectors of the vector collection is computed, and added to the elements of the tensor operation if it has not been encountered before. The index of this tensor product vector is returned as an integer. .. NOTE:: In a convenient choice of coordinates the tensor product of, say, two vectors $(a,b)$ and $(c,d)$, is $(ac, ad, bc, bd)$. EXAMPLES:: sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: S = VectorCollection([(1,), (-1,)], QQ, 1) sage: R_tensor_S = TensorOperation([R,S]) sage: R_tensor_S.index_map(1, 1) 3 sage: R_tensor_S.index_map(2, 0) 3 sage: R_tensor_S.vectors() # indirect doctest ((1, 0), (-1, 0), (1, 2), (-1, -2)) """ # Pick out the i[j]-th vector rays = [list(self._V[j].vectors()[k]) for j, k in enumerate(i)] v = [] # Note: convert to list, as cartesian_product of vectors is unrelated from sage.categories.cartesian_product import cartesian_product for r in cartesian_product(map(list, rays)): v.append(prod(r)) # build up the tensor product v = tuple(v) # Use index of pre-existing tensor product vector if there is one try: result = self._vectors.index(v) except ValueError: self._vectors.append(v) result = len(self._vectors) - 1 return result
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 = Zmod(n).cyclotomic_cosets(q); 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 sage: codes.DuadicCodeEvenPair(GF(q),S1,S2) ([11, 5] Cyclic Code over GF(3), [11, 5] Cyclic Code over GF(3)) """ from .cyclic_code import CyclicCode n = len(S1) + len(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.coefficients(sparse=False)]) gg2 = P2([_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)]) C1 = CyclicCode(length = n, generator_pol = gg1) C2 = CyclicCode(length = n, generator_pol = gg2) return C1,C2
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) if not highest_weight.is_dominant(): raise ValueError("the highest weight must be 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 __len__(self): sizes = self.sizes n = len(sizes) if n == 0: return 0 for i in sizes: if i <= 0: return 0 return prod(sizes, 1)
def eisenstein_basis(N, k, verbose=False): r""" Find spanning list of 'easy' generators for the subspace of `M_k(\Gamma_0(N))` generated by level 1 Eisenstein series and their images of even integer weights up to `k`. INPUT: - N -- positive integer - k -- positive integer - ``verbose`` -- bool (default: False) OUTPUT: - list of monomials in images of level 1 Eisenstein series - prec of q-expansions needed to determine element of `M_k(\Gamma_0(N))`. EXAMPLES:: sage: from psage.modform.rational.special import eisenstein_basis sage: eisenstein_basis(5,4) ([E4(q^5)^1, E4(q^1)^1, E2^*(q^5)^2], 3) sage: eisenstein_basis(11,2,verbose=True) # warning below because of verbose Warning -- not enough series. ([E2^*(q^11)^1], 2) sage: eisenstein_basis(11,2,verbose=False) ([E2^*(q^11)^1], 2) """ assert N > 1 if k % 2 != 0: return [] # Make list E of Eisenstein series, to enough precision to # determine them, until we span space. M = ModularForms(N, k) prec = M.echelon_basis()[-1].valuation() + 1 gens = eisenstein_gens(N, k, prec) R = PolynomialRing(ZZ, len(gens), ['E%sq%s'%(g[1],g[0]) for g in gens]) z = [(R.gen(i), g[1]) for i, g in enumerate(gens)] m = monomials(z, k) A = QQ**prec V = A.zero_subspace() E = [] for i, z in enumerate(m): d = z.degrees() f = prod(g[2]**d[i] for i, g in enumerate(gens) if d[i]) v = A(f.padded_list(prec)) if v not in V: V = V + A.span([v]) w = [(gens[i][0],gens[i][1],d[i]) for i in range(len(d)) if d[i]] E.append(EisensteinMonomial(w)) if V.dimension() == M.dimension(): return E, prec if verbose: print "Warning -- not enough series." return E, prec
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 Newton_polytope_vars_coeffs(polynomial, variables): """ Return the Newton polytope in the given variables. INPUT: See :func:`WeierstrassForm` for how to specify the input polynomial and variables. OUTPUT: A tuple containing of the affine span of the Netwton polytope and a dictionary with keys the integral values of the Newton polytope and values the corresponding coefficient of ``polynomial``. EXAMPLES:: sage: from sage.schemes.toric.weierstrass import Newton_polytope_vars_coeffs sage: R.<x,y,z,a30,a21,a12,a03,a20,a11,a02,a10,a01,a00> = QQ[] sage: p = (a30*x^3 + a21*x^2*y + a12*x*y^2 + a03*y^3 + a20*x^2*z + ....: a11*x*y*z + a02*y^2*z + a10*x*z^2 + a01*y*z^2 + a00*z^3) sage: p_data = Newton_polytope_vars_coeffs(p, [x,y,z]); p_data {(0, 0, 3): a00, (0, 1, 2): a01, (0, 2, 1): a02, (0, 3, 0): a03, (1, 0, 2): a10, (1, 1, 1): a11, (1, 2, 0): a12, (2, 0, 1): a20, (2, 1, 0): a21, (3, 0, 0): a30} sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: polytope = LatticePolytope_PPL(p_data.keys()); polytope A 2-dimensional lattice polytope in ZZ^3 with 3 vertices sage: polytope.vertices() ((0, 0, 3), (3, 0, 0), (0, 3, 0)) sage: polytope.embed_in_reflexive_polytope() The map A*x+b with A= [-1 -1] [ 0 1] [ 1 0] b = (3, 0, 0) """ R = polynomial.parent() var_indices = [R.gens().index(x) for x in variables] result = dict() for c, m in polynomial: e = m.exponents()[0] v = tuple([e[i] for i in var_indices]) m_red = m // prod(x**i for x, i in zip(variables, v)) result[v] = result.get(v, R.zero()) + c*m_red return result