def symmetrizer(self): """ Return the symmetrizer of ``self``. EXAMPLES:: sage: cm = CartanMatrix([[2,-5],[-2,2]]) sage: cm.symmetrizer() Finite family {0: 2, 1: 5} TESTS: Check that the symmetrizer computed from the Cartan matrix agrees with the values given by the Cartan type:: sage: ct = CartanType(['B',4,1]) sage: ct.symmetrizer() Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1} sage: ct.cartan_matrix().symmetrizer() Finite family {0: 2, 1: 2, 2: 2, 3: 2, 4: 1} """ sym = self.is_symmetrizable(True) if not sym: raise ValueError("the Cartan matrix is not symmetrizable") iset = self.index_set() # The result from is_symmetrizable needs to be scaled # to integer coefficients from sage.arith.all import LCM from sage.rings.all import QQ scalar = LCM([QQ(x).denominator() for x in sym]) return Family({iset[i]: ZZ(val * scalar) for i, val in enumerate(sym)})
def padic_height(self, prec=20): r""" Return the canonical `p`-adic height function on the original curve. INPUT: - ``prec`` -- the `p`-adic precision, default is 20. OUTPUT: - A function that can be evaluated on rational points of `E`. EXAMPLES:: sage: e = EllipticCurve('130a1') sage: eq = e.tate_curve(5) sage: h = eq.padic_height(prec=10) sage: P = e.gens()[0] sage: h(P) 2*5^-1 + 1 + 2*5 + 2*5^2 + 3*5^3 + 3*5^6 + 5^7 + O(5^9) Check that it is a quadratic function:: sage: h(3*P)-3^2*h(P) O(5^9) """ if not self.is_split(): raise NotImplementedError( "The p-adic height is not implemented for non-split multiplicative reduction." ) p = self._p # we will have to do it properly with David Harvey's _multiply_point(E, R, Q) n = LCM(self._E.tamagawa_numbers()) * (p - 1) # this function is a closure, I don't see how to doctest it (PZ) def _height(P, check=True): if check: assert P.curve( ) == self._E, "the point P must lie on the curve from which the height function was created" Q = n * P cQ = denominator(Q[0]) q = self.parameter(prec=prec) nn = q.valuation() precp = prec + nn + 2 uQ = self.lift(Q, prec=precp) si = self.__padic_sigma_square(uQ, prec=precp) q = self.parameter(prec=precp) nn = q.valuation() qEu = q / p**nn res = -(log(si * self._Csquare(prec=precp) / cQ) + log(uQ)**2 / log(qEu)) / n**2 R = Qp(self._p, prec) return R(res) return _height
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 TESTS:: sage: F = AbelianGroup(1, [7], names="a") sage: a, = F.gens() sage: Fd = F.dual_group(names="A", base_ring=GF(29)) sage: A, = Fd.gens() sage: A(a) 16 """ F = self.parent().base_ring() expsX = self.exponents() expsg = g.exponents() order = self.parent().gens_orders() N = LCM(order) order_not = [N / o for o in order] zeta = F.zeta(N) return F.prod(zeta**(expsX[i] * expsg[i] * order_not[i]) for i in range(len(expsX)))
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([(2 * PI * I * expsX[i] * expsg[i] / order[i]).exp() 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 spol(f,g): """ Computes the S-polynomial of f and g. INPUT: - ``f,g`` - polynomials OUTPUT: - The S-polynomial of f and g. EXAMPLES:: sage: R.<x,y,z> = PolynomialRing(QQ,3) sage: from sage.rings.polynomial.toy_buchberger import spol sage: spol(x^2 - z - 1, z^2 - y - 1) x^2*y - z^3 + x^2 - z^2 """ fg_lcm = LCM(LM(f),LM(g)) return fg_lcm//LT(f)*f - fg_lcm//LT(g)*g
def select(P): """ The normal selection strategy INPUT: - ``P`` - a list of critical pairs OUTPUT: an element of P EXAMPLES:: sage: from sage.rings.polynomial.toy_buchberger import select sage: R.<x,y,z> = PolynomialRing(QQ,3, order='lex') sage: ps = [x^3 - z -1, z^3 - y - 1, x^5 - y - 2] sage: pairs = [[ps[i],ps[j]] for i in range(3) for j in range(i+1,3)] sage: select(pairs) [x^3 - z - 1, -y + z^3 - 1] """ return min(P, key=lambda fi_fj: LCM(LM(fi_fj[0]), LM(fi_fj[1])).total_degree())
def order(self): """ Return the order of this element. OUTPUT: An integer or ``infinity``. EXAMPLES:: sage: F = AbelianGroup(3,[7,8,9]) sage: Fd = F.dual_group() sage: A,B,C = Fd.gens() sage: (B*C).order() 72 sage: F = AbelianGroup(3,[7,8,9]); F Multiplicative Abelian group isomorphic to C7 x C8 x C9 sage: F.gens()[2].order() 9 sage: a,b,c = F.gens() sage: (b*c).order() 72 sage: G = AbelianGroup(3,[7,8,9]) sage: type((G.0 * G.1).order())==Integer True """ M = self.parent() order = M.gens_orders() L = self.exponents() N = LCM([ order[i] / GCD(order[i], L[i]) for i in range(len(order)) if L[i] != 0 ]) if N == 0: return infinity else: return ZZ(N)
def level(self): r""" Determines the level of the quadratic form over a PID, which is a generator for the smallest ideal `N` of `R` such that N * (the matrix of 2*Q)^(-1) is in R with diagonal in 2*R. Over `\ZZ` this returns a non-negative number. (Caveat: This always returns the unit ideal when working over a field!) EXAMPLES:: sage: Q = QuadraticForm(ZZ, 2, range(1,4)) sage: Q.level() 8 sage: Q1 = QuadraticForm(QQ, 2, range(1,4)) sage: Q1.level() # random UserWarning: Warning -- The level of a quadratic form over a field is always 1. Do you really want to do this?!? 1 sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.level() 420 """ ## Try to return the cached level try: return self.__level except AttributeError: ## Check that the base ring is a PID if not isinstance(self.base_ring(), PrincipalIdealDomain): raise TypeError("Oops! The level (as a number) is only defined over a Principal Ideal Domain. Try using level_ideal().") ## Warn the user if the form is defined over a field! if self.base_ring().is_field(): warn("Warning -- The level of a quadratic form over a field is always 1. Do you really want to do this?!?") #raise RuntimeError, "Warning -- The level of a quadratic form over a field is always 1. Do you really want to do this?!?" ## Check invertibility and find the inverse try: mat_inv = self.matrix()**(-1) except ZeroDivisionError: raise TypeError("Oops! The quadratic form is degenerate (i.e. det = 0). =(") ## Compute the level inv_denoms = [] for i in range(self.dim()): for j in range(i, self.dim()): if (i == j): inv_denoms += [denominator(mat_inv[i,j] / 2)] else: inv_denoms += [denominator(mat_inv[i,j])] lvl = LCM(inv_denoms) lvl = Ideal(self.base_ring()(lvl)).gen() ############################################################## ## To do this properly, the level should be the inverse of the ## fractional ideal (over R) generated by the entries whose ## denominators we take above. =) ############################################################## ## Normalize the result over ZZ if self.base_ring() == IntegerRing(): lvl = abs(lvl) ## Cache and return the level self.__level = lvl return lvl
def update(G,B,h): """ Update ``G`` using the list of critical pairs ``B`` and the polynomial ``h`` as presented in [BW93]_, page 230. For this, Buchberger's first and second criterion are tested. This function implements the Gebauer-Moeller Installation. INPUT: - ``G`` - an intermediate Groebner basis - ``B`` - a list of critical pairs - ``h`` - a polynomial OUTPUT: a tuple of an intermediate Groebner basis and a list of critical pairs EXAMPLES:: sage: from sage.rings.polynomial.toy_buchberger import update sage: R.<x,y,z> = PolynomialRing(QQ,3) sage: set_verbose(0) sage: update(set(),set(),x*y*z) ({x*y*z}, set()) sage: G,B = update(set(),set(),x*y*z-1) sage: G,B = update(G,B,x*y^2-1) sage: G,B ({x*y*z - 1, x*y^2 - 1}, {(x*y^2 - 1, x*y*z - 1)}) """ R = h.parent() C = set([(h,g) for g in G]) D = set() while C != set(): (h,g) = C.pop() lcm_divides = lambda rhs: R.monomial_divides( LCM(LM(h),LM(rhs[1])), LCM(LM(h),LM(g))) if R.monomial_pairwise_prime(LM(h),LM(g)) or \ (\ not any( lcm_divides(f) for f in C ) \ and not any( lcm_divides(f) for f in D ) \ ): D.add( (h,g) ) E = set() while D != set(): (h,g) = D.pop() if not R.monomial_pairwise_prime(LM(h),LM(g)): E.add( (h,g) ) B_new = set() while B != set(): g1,g2 = B.pop() if not R.monomial_divides( LM(h), LCM(LM(g1),LM(g2)) ) or \ R.monomial_lcm(LM(g1),LM( h)) == LCM(LM(g1),LM(g2)) or \ R.monomial_lcm(LM( h),LM(g2)) == LCM(LM(g1),LM(g2)) : B_new.add( (g1,g2) ) B_new = B_new.union( E ) G_new = set() while G != set(): g = G.pop() if not R.monomial_divides(LM(h), LM(g)): G_new.add(g) G_new.add(h) return G_new,B_new
def BCHCode(n, delta, F, b=0): r""" A 'Bose-Chaudhuri-Hockenghem code' (or BCH code for short) is the largest possible cyclic code of length n over field F=GF(q), whose generator polynomial has zeros (which contain the set) `Z = \{a^{b},a^{b+1}, ..., a^{b+delta-2}\}`, where a is a primitive `n^{th}` root of unity in the splitting field `GF(q^m)`, b is an integer `0\leq b\leq n-delta+1` and m is the multiplicative order of q modulo n. (The integers `b,...,b+delta-2` typically lie in the range `1,...,n-1`.) The integer `delta \geq 1` is called the "designed distance". The length n of the code and the size q of the base field must be relatively prime. The generator polynomial is equal to the least common multiple of the minimal polynomials of the elements of the set `Z` above. Special cases are b=1 (resulting codes are called 'narrow-sense' BCH codes), and `n=q^m-1` (known as 'primitive' BCH codes). It may happen that several values of delta give rise to the same BCH code. The largest one is called the Bose distance of the code. The true minimum distance, d, of the code is greater than or equal to the Bose distance, so `d\geq delta`. EXAMPLES:: sage: FF.<a> = GF(3^2,"a") sage: x = PolynomialRing(FF,"x").gen() sage: L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L) sage: f = x^(8)-1 sage: g.divides(f) True sage: C = codes.CyclicCode(8,g); C Linear code of length 8, dimension 4 over Finite Field of size 3 sage: C.minimum_distance() 4 sage: C = codes.BCHCode(8,3,GF(3),1); C Linear code of length 8, dimension 4 over Finite Field of size 3 sage: C.minimum_distance() 4 sage: C = codes.BCHCode(8,3,GF(3)); C Linear code of length 8, dimension 5 over Finite Field of size 3 sage: C.minimum_distance() 3 sage: C = codes.BCHCode(26, 5, GF(5), b=1); C Linear code of length 26, dimension 10 over Finite Field of size 5 """ q = F.order() R = IntegerModRing(n) m = R(q).multiplicative_order() FF = GF(q**m, "z") z = FF.gen() e = z.multiplicative_order() / n a = z**e # order n P = PolynomialRing(F, "x") x = P.gen() L1 = [] for coset in R.cyclotomic_cosets(q, range(b, b + delta - 1)): L1.extend(P((a**j).minpoly()) for j in coset) g = P(LCM(L1)) if not (g.divides(x**n - 1)): raise ValueError("BCH codes does not exist with the given input.") return CyclicCodeFromGeneratingPolynomial(n, g)