def isogenyclasstable(Nmin,Nmax): iso_dict = {} from sage.schemes.elliptic_curves.ell_rational_field import cremona_curves from sage.misc.misc import srange for E in cremona_curves(srange(Nmin,Nmax)): cond = int(cremona_label_regex.match(E.label()).groups()[0]) iso_dict[cond] = [] for E in cremona_curves(srange(Nmin,Nmax)): cond = int(cremona_label_regex.match(E.label()).groups()[0]) id = cremona_label_regex.match(E.label()).groups()[1] iso_dict[cond].append(str(cond)+id) for cond in iso_dict: iso_dict[cond] = set(iso_dict[cond]) return iso_dict
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds): r""" This function is used internally by the ``parametric_plot3d`` command. """ from sage.plot.misc import setup_for_eval_on_grid g, ranges = setup_for_eval_on_grid(f, [urange,vrange], plot_points) urange = srange(*ranges[0], include_endpoint=True) vrange = srange(*ranges[1], include_endpoint=True) G = ParametricSurface(g, (urange, vrange), **kwds) if boundary_style is not None: for u in (urange[0], urange[-1]): G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style) for v in (vrange[0], vrange[-1]): G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style) return G
def an_element(self): r""" Return an element of ``self``. EXAMPLES:: sage: SymmetricFunctions(QQ['t']).kschur(3).an_element() 2*ks3[] + 2*ks3[1] + 3*ks3[2] """ return self( Partition(srange(self.k,0,-1)))
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds): r""" This function is used internally by the ``parametric_plot3d`` command. """ from sage.plot.misc import setup_for_eval_on_grid g, ranges = setup_for_eval_on_grid(f, [urange, vrange], plot_points) urange = srange(*ranges[0], include_endpoint=True) vrange = srange(*ranges[1], include_endpoint=True) G = ParametricSurface(g, (urange, vrange), **kwds) if boundary_style is not None: for u in (urange[0], urange[-1]): G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for v in vrange], **boundary_style) for v in (vrange[0], vrange[-1]): G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for u in urange], **boundary_style) return G
def dirichlet_coefficients(self, ncoeffs=20): from sage.rings.power_series_ring import PowerSeriesRing from sage.misc.misc import srange #from sage.misc.mrange import mrange ncoeffs = ZZ(ncoeffs) ps = prime_range(ncoeffs + 1) num_ps = len(ps) exps = [ncoeffs.exact_log(p) + 1 for p in ps] M = ncoeffs.exact_log(2) + 1 #print ps, exps, M PS = PowerSeriesRing(QQ, 'x', M) euler_factors = dict([[ps[i], ~PS(self.euler_factor(ps[i]), exps[i] + 1)] for i in range(num_ps)]) ans = [] for n in srange(1, ncoeffs + 1): ans.append(prod([euler_factors[p][e] for p, e in n.factor()])) #ans = [0] * ncoeffs #is_zeroes = True #for e in mrange(exps): # if is_zeroes: # is_zeroes = False # ans[0] = QQ.one() # continue # n = 1 # an = QQ.one() # breaker = False # for i in range(num_ps): # if exps[i] == 0: # continue # n *= ps[i] ** e[i] # if n > ncoeffs: # breaker = True # break # an *= euler_factors[i][e[i]] # #print n, an, e # if breaker: # continue # ans[n-1] = an return ans
def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): r""" Totally generic discrete baby-step giant-step function. Solves `na=b` (or `a^n=b`) with `lb\le n\le ub` where ``bounds==(lb,ub)``, raising an error if no such `n` exists. `a` and `b` must be elements of some group with given identity, inverse of ``x`` given by ``inverse(x)``, and group operation on ``x``, ``y`` by ``op(x,y)``. If operation is '*' or '+' then the other arguments are provided automatically; otherwise they must be provided by the caller. INPUT: - ``a`` - group element - ``b`` - group element - ``bounds`` - a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper`` - ``operation`` - string: '*', '+', 'other' - ``identity`` - the identity element of the group - ``inverse()`` - function of 1 argument ``x`` returning inverse of ``x`` - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in group OUTPUT: An integer `n` such that `a^n = b` (or `na = b`). If no such `n` exists, this function raises a ValueError exception. NOTE: This is a generalization of discrete logarithm. One situation where this version is useful is to find the order of an element in a group where we only have bounds on the group order (see the elliptic curve example below). ALGORITHM: Baby step giant step. Time and space are soft `O(\sqrt{n})` where `n` is the difference between upper and lower bounds. EXAMPLES:: sage: b = Mod(2,37); a = b^20 sage: bsgs(b, a, (0,36)) 20 sage: p=next_prime(10^20) sage: a=Mod(2,p); b=a^(10^25) sage: bsgs(a, b, (10^25-10^6,10^25+10^6)) == 10^25 True sage: K = GF(3^6,'b') sage: a = K.gen() sage: b = a^210 sage: bsgs(a, b, (0,K.order()-1)) 210 sage: K.<z>=CyclotomicField(230) sage: w=z^500 sage: bsgs(z,w,(0,229)) 40 An additive example in an elliptic curve group:: sage: F.<a>=GF(37^5,'a') sage: E=EllipticCurve(F,[1,1]) sage: P=E.lift_x(a); P (a : 9*a^4 + 22*a^3 + 23*a^2 + 30 : 1) This will return a multiple of the order of P: sage: bsgs(P,P.parent()(0),Hasse_bounds(F.order()),operation='+') 69327408 AUTHOR: - John Cremona (2008-03-15) """ Z = integer_ring.ZZ from operator import inv, mul, neg, add if operation in multiplication_names: identity = a.parent()(1) inverse = inv op = mul elif operation in addition_names: identity = a.parent()(0) inverse = neg op = add else: if identity==None or inverse==None or op==None: raise ValueError, "identity, inverse and operation must be given" lb, ub = bounds if lb<0 or ub<lb: raise ValueError, "bsgs() requires 0<=lb<=ub" if a.is_zero() and not b.is_zero(): raise ValueError, "No solution in bsgs()" ran = 1 + ub - lb # the length of the interval c = op(inverse(b),multiple(a,lb,operation=operation)) if ran < 30: # use simple search for small ranges i = lb d = c # for i,d in multiples(a,ran,c,indexed=True,operation=operation): for i0 in range(ran): i = lb + i0 if identity == d: # identity == b^(-1)*a^i, so return i return Z(i) d = op(a,d) raise ValueError, "No solution in bsgs()" m = ran.isqrt()+1 # we need sqrt(ran) rounded up table = dict() # will hold pairs (a^(lb+i),lb+i) for i in range(m) d=c for i0 in misc.srange(m): i = lb + i0 if identity==d: # identity == b^(-1)*a^i, so return i return Z(i) table[d] = i d=op(d,a) c = op(c,inverse(d)) # this is now a**(-m) d=identity for i in misc.srange(m): j = table.get(d) if not j==None: # then d == b*a**(-i*m) == a**j return Z(i*m + j) d=op(c,d) raise ValueError, "Log of %s to the base %s does not exist in %s."%(b,a,bounds)
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 """ from sage.misc.misc import srange 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() cosets = Set([]) for i in srange(b,b+delta-1): cosets = cosets.union(Set(cyclotomic_cosets(q, n, i))) L0 = [a**j for j in cosets] L1 = [P(ai.minpoly()) for ai in L0] g = P(LCM(L1)) #print cosets, "\n", g, "\n", (x**n-1).factor(), "\n", L1, "\n", g.divides(x**n-1) if not(g.divides(x**n-1)): raise ValueError, "BCH codes does not exist with the given input." return CyclicCodeFromGeneratingPolynomial(n,g)
def cyclotomic_cosets(q, n, t = None): r""" INPUT: q,n,t positive integers (or t=None) Some type-checking of inputs is performed. OUTPUT: q-cyclotomic cosets mod n (or, if t is not None, the q-cyclotomic coset mod n containing t) Let q, n be relatively print positive integers and let `A = q^{ZZ}`. The group A acts on ZZ/nZZ by multiplication. The orbits of this action are "cyclotomic cosets", or more precisely "q-cyclotomic cosets mod n". Sometimes the smallest element of the coset is called the "coset leader". The algorithm will always return the cosets as sorted lists of lists, so the coset leader will always be the first element in the list. These cosets arise in the theory of duadic codes and minimal polynomials of finite fields. Fix a primitive element `z` of `GF(q^k)`. The minimal polynomial of `z^s` over `GF(q)` is given by .. math:: M_s(x) = \prod_{i \in C_s} (x-z^i), where `C_s` is the q-cyclotomic coset mod n containing s, `n = q^k - 1`. EXAMPLES:: sage: cyclotomic_cosets(2,11) [[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] sage: cyclotomic_cosets(2,15) [[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]] sage: cyclotomic_cosets(2,15,5) [5, 10] sage: cyclotomic_cosets(3,16) [[0], [1, 3, 9, 11], [2, 6], [4, 12], [5, 7, 13, 15], [8], [10, 14]] sage: F.<z> = GF(2^4, "z") sage: P.<x> = PolynomialRing(F,"x") sage: a = z^5 sage: a.minimal_polynomial() x^2 + x + 1 sage: prod([x-z^i for i in [5, 10]]) x^2 + x + 1 sage: cyclotomic_cosets(3,2,0) [0] sage: cyclotomic_cosets(3,2,1) [1] sage: cyclotomic_cosets(3,2,2) [0] This last output looks strange but is correct, since the elements of the cosets are in ZZ/nZZ and 2 = 0 in ZZ/2ZZ. """ from sage.misc.misc import srange if not(t==None) and type(t)<>Integer: raise TypeError, "Optional input %s must None or an integer."%t if q<2 or n<2: raise TypeError, "Inputs %s and %s must be > 1."%(q,n) if GCD(q,n) <> 1: raise TypeError, "Inputs %s and %s must be relative prime."%(q,n) if t<>None and type(t)==Integer: S = Set([t*q**i%n for i in srange(n)]) L = list(S) L.sort() return L ccs = Set([]) ccs_list = [[0]] for s in range(1,n): if not(s in ccs): S = Set([s*q**i%n for i in srange(n)]) L = list(S) L.sort() ccs = ccs.union(S) ccs_list.append(L) return ccs_list
def Krawtchouk(n,q,l,x,check=True): """ Compute ``K^{n,q}_l(x)``, the Krawtchouk polynomial. See :wikipedia:`Kravchuk_polynomials`; It is defined by the generating function `(1+(q-1)z)^{n-x}(1-z)^x=\sum_{l} K^{n,q}_l(x)z^l` and is equal to .. math:: K^{n,q}_l(x)=\sum_{j=0}^l (-1)^j(q-1)^{(l-j)}{x \choose j}{n-x \choose l-j}, INPUT: - ``n, q, x`` -- arbitrary numbers - ``l`` -- a nonnegative integer - ``check`` -- check the input for correctness. ``True`` by default. Otherwise, pass it as it is. Use ``check=False`` at your own risk. EXAMPLES:: sage: Krawtchouk(24,2,5,4) 2224 sage: Krawtchouk(12300,4,5,6) 567785569973042442072 TESTS: check that the bug reported on :trac:`19561` is fixed:: sage: Krawtchouk(3,2,3,3) -1 sage: Krawtchouk(int(3),int(2),int(3),int(3)) -1 sage: Krawtchouk(int(3),int(2),int(3),int(3),check=False) -5 other unusual inputs :: sage: Krawtchouk(sqrt(5),1-I*sqrt(3),3,55.3).n() 211295.892797... + 1186.42763...*I sage: Krawtchouk(-5/2,7*I,3,-1/10) 480053/250*I - 357231/400 sage: Krawtchouk(1,1,-1,1) Traceback (most recent call last): ... ValueError: l must be a nonnegative integer sage: Krawtchouk(1,1,3/2,1) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer """ from sage.arith.all import binomial from sage.misc.misc import srange # Use the expression in equation (55) of MacWilliams & Sloane, pg 151 # We write jth term = some_factor * (j-1)th term if check: from sage.rings.integer_ring import ZZ l0 = ZZ(l) if l0 != l or l0<0: raise ValueError('l must be a nonnegative integer') l = l0 kraw = jth_term = (q-1)**l * binomial(n, l) # j=0 for j in srange(1,l+1): jth_term *= -q*(l-j+1)*(x-j+1)/((q-1)*j*(n-j+1)) kraw += jth_term return kraw
def _coeffs_from_height(self, height_tuple): """ Returns a list of tuples of a-invariants of all curves described by height_tuple. INPUT: - ``height_tuple`` -- A tuple of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. OUTPUT: - A list of 2-tuples, each consisting of the given height, followed by a tuple of a-invariants of a curve of that height. EXAMPLES: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: B = C.next_height(4); B (4, [1, 2], [1]) sage: L = C._coeffs_from_height(B) sage: for ell in L: print ell ...: (4, [0, 0, 0, -1, -2]) (4, [0, 0, 0, -1, 2]) (4, [0, 0, 0, 0, -2]) (4, [0, 0, 0, 0, 2]) (4, [0, 0, 0, 1, -2]) (4, [0, 0, 0, 1, 2]) """ height = height_tuple[0] coeffs = height_tuple[1] index = height_tuple[2] # Produce list of all coefficient tuples with given height L = [] for S in list(powerset(index))[1:]: B = [] for j in range(len(coeffs)): if j in S: B.append([-coeffs[j], coeffs[j]]) elif j in index: B.append(srange(-coeffs[j] + 1, coeffs[j])) else: B.append(srange(-coeffs[j], coeffs[j] + 1)) C = CartesianProduct(*B).list() for c in C: L.append(c) # Convert coefficient tuples to a-invariants L2 = [] for c in L: C = self._coeffs_to_a_invariants(c) if not self._is_singular(C): L2.append((height, C)) return L2
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 = CyclicCode(8,g); C Linear code of length 8, dimension 4 over Finite Field of size 3 sage: C.minimum_distance() 4 sage: C = 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 = 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 = BCHCode(26, 5, GF(5), b=1); C Linear code of length 26, dimension 10 over Finite Field of size 5 """ from sage.misc.misc import srange 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() cosets = Set([]) for i in srange(b,b+delta-1): cosets = cosets.union(Set(cyclotomic_cosets(q, n, i))) L0 = [a**j for j in cosets] L1 = [P(ai.minpoly()) for ai in L0] g = P(LCM(L1)) #print cosets, "\n", g, "\n", (x**n-1).factor(), "\n", L1, "\n", g.divides(x**n-1) if not(g.divides(x**n-1)): raise ValueError, "BCH codes does not exist with the given input." return CyclicCodeFromGeneratingPolynomial(n,g)
def _coeffs_from_height(self,height_tuple): """ Returns a list of tuples of a-invariants of all curves described by height_tuple. INPUT: - ``height_tuple`` -- A tuple of the form (H, C, I) such that H: The smallest height >= N C: A list of coefficients for curves of this height I: A list of indices indicating which of the above coefficients achieve this height. The remaining values in C indicate the max absolute value those coefficients are allowed to obtain without altering the height. For example, the tuple (4, [1, 2], [1]) for the short Weierstrass case denotes set of curves with height 4; these are all of the form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1. OUTPUT: - A list of 2-tuples, each consisting of the given height, followed by a tuple of a-invariants of a curve of that height. EXAMPLES: sage: from sage.schemes.elliptic_curves.curve_enumerator import * sage: C = CurveEnumerator(family="short_weierstrass") sage: B = C.next_height(4); B (4, [1, 2], [1]) sage: L = C._coeffs_from_height(B) sage: for ell in L: print ell ...: (4, [0, 0, 0, -1, -2]) (4, [0, 0, 0, -1, 2]) (4, [0, 0, 0, 0, -2]) (4, [0, 0, 0, 0, 2]) (4, [0, 0, 0, 1, -2]) (4, [0, 0, 0, 1, 2]) """ height = height_tuple[0] coeffs = height_tuple[1] index = height_tuple[2] # Produce list of all coefficient tuples with given height L = [] for S in list(powerset(index))[1:]: B = [] for j in range(len(coeffs)): if j in S: B.append([-coeffs[j],coeffs[j]]) elif j in index: B.append(srange(-coeffs[j]+1,coeffs[j])) else: B.append(srange(-coeffs[j],coeffs[j]+1)) C = CartesianProduct(*B).list() for c in C: L.append(c) # Convert coefficient tuples to a-invariants L2 = [] for c in L: C = self._coeffs_to_a_invariants(c) if not self._is_singular(C): L2.append((height,C)) return L2
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds): r""" Return a parametric three-dimensional space surface. This function is used internally by the :func:`parametric_plot3d` command. There are two ways this function is invoked by :func:`parametric_plot3d`. - ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max), (v_min, v_max))``: `f_x, f_y, f_z` are each functions of two variables - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min, u_max), (v, v_min, v_max))``: `f_x, f_y, f_z` can be viewed as functions of `u` and `v` INPUT: - ``f`` - a 3-tuple of functions or expressions, or vector of size 3 - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple (u, u_min, u_max) - ``vrange`` - a 2-tuple (v_min, v_max) or a 3-tuple (v, v_min, v_max) - ``plot_points`` - (default: "automatic", which is [40,40] for surfaces) initial number of sample points in each parameter; a pair of integers. - ``boundary_style`` - (default: None, no boundary) a dict that describes how to draw the boundaries of regions by giving options that are passed to the line3d command. EXAMPLES: We demonstrate each of the two ways of calling this. See :func:`parametric_plot3d` for many more examples. We do the first one with lambda functions:: sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v)) sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) # indirect doctest Now we do the same thing with symbolic expressions:: sage: u, v = var('u,v') sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True) """ from sage.plot.misc import setup_for_eval_on_grid g, ranges = setup_for_eval_on_grid(f, [urange,vrange], plot_points) urange = srange(*ranges[0], include_endpoint=True) vrange = srange(*ranges[1], include_endpoint=True) G = ParametricSurface(g, (urange, vrange), **kwds) if boundary_style is not None: for u in (urange[0], urange[-1]): G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style) for v in (vrange[0], vrange[-1]): G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style) return G
def Krawtchouk(n, q, l, x, check=True): """ Compute ``K^{n,q}_l(x)``, the Krawtchouk polynomial. See :wikipedia:`Kravchuk_polynomials`; It is defined by the generating function `(1+(q-1)z)^{n-x}(1-z)^x=\sum_{l} K^{n,q}_l(x)z^l` and is equal to .. math:: K^{n,q}_l(x)=\sum_{j=0}^l (-1)^j(q-1)^{(l-j)}{x \choose j}{n-x \choose l-j}, INPUT: - ``n, q, x`` -- arbitrary numbers - ``l`` -- a nonnegative integer - ``check`` -- check the input for correctness. ``True`` by default. Otherwise, pass it as it is. Use ``check=False`` at your own risk. EXAMPLES:: sage: Krawtchouk(24,2,5,4) 2224 sage: Krawtchouk(12300,4,5,6) 567785569973042442072 TESTS: check that the bug reported on :trac:`19561` is fixed:: sage: Krawtchouk(3,2,3,3) -1 sage: Krawtchouk(int(3),int(2),int(3),int(3)) -1 sage: Krawtchouk(int(3),int(2),int(3),int(3),check=False) -5 other unusual inputs :: sage: Krawtchouk(sqrt(5),1-I*sqrt(3),3,55.3).n() 211295.892797... + 1186.42763...*I sage: Krawtchouk(-5/2,7*I,3,-1/10) 480053/250*I - 357231/400 sage: Krawtchouk(1,1,-1,1) Traceback (most recent call last): ... ValueError: l must be a nonnegative integer sage: Krawtchouk(1,1,3/2,1) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer """ from sage.arith.all import binomial from sage.misc.misc import srange # Use the expression in equation (55) of MacWilliams & Sloane, pg 151 # We write jth term = some_factor * (j-1)th term if check: from sage.rings.integer_ring import ZZ l0 = ZZ(l) if l0 != l or l0 < 0: raise ValueError('l must be a nonnegative integer') l = l0 kraw = jth_term = (q - 1)**l * binomial(n, l) # j=0 for j in srange(1, l + 1): jth_term *= -q * (l - j + 1) * (x - j + 1) / ((q - 1) * j * (n - j + 1)) kraw += jth_term return kraw
def QuadraticResidueCodeOddPair(n, F): """ Quadratic residue codes of a given odd prime length and base ring either don't exist at all or occur as 4-tuples - a pair of "odd-like" codes and a pair of "even-like" codes. If n 2 is prime then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a quadratic residue mod n. They are constructed as "odd-like" duadic codes associated the splitting (Q,N) mod n, where Q is the set of non-zero quadratic residues and N is the non-residues. EXAMPLES:: sage: codes.QuadraticResidueCodeOddPair(17,GF(13)) (Linear code of length 17, dimension 9 over Finite Field of size 13, Linear code of length 17, dimension 9 over Finite Field of size 13) sage: codes.QuadraticResidueCodeOddPair(17,GF(2)) (Linear code of length 17, dimension 9 over Finite Field of size 2, Linear code of length 17, dimension 9 over Finite Field of size 2) sage: codes.QuadraticResidueCodeOddPair(13,GF(9,"z")) (Linear code of length 13, dimension 7 over Finite Field in z of size 3^2, Linear code of length 13, dimension 7 over Finite Field in z of size 3^2) sage: C1 = codes.QuadraticResidueCodeOddPair(17,GF(2))[1] sage: C1x = C1.extended_code() sage: C2 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0] sage: C2x = C2.extended_code() sage: C2x.spectrum(); C1x.spectrum() [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1] [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1] sage: C2x == C1x.dual_code() True sage: C3 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0] sage: C3x = C3.extended_code() sage: C3x.spectrum() [1, 0, 0, 0, 14, 0, 0, 0, 1] sage: C3x.is_self_dual() True This is consistent with Theorem 6.6.14 in [HP]_. TESTS:: sage: codes.QuadraticResidueCodeOddPair(9,GF(2)) Traceback (most recent call last): ... ValueError: the argument n must be an odd prime """ from sage.misc.misc import srange from sage.categories.finite_fields import FiniteFields if F not in FiniteFields(): raise ValueError("the argument F must be a finite field") q = F.order() n = Integer(n) if n <= 2 or not n.is_prime(): raise ValueError("the argument n must be an odd prime") Q = quadratic_residues(n) Q.remove(0) # non-zero quad residues N = [x for x in srange(1, n) if x not in Q] # non-zero quad non-residues if q not in Q: raise ValueError( "the order of the finite field must be a quadratic residue modulo n" ) return DuadicCodeOddPair(F, Q, N)
def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None): r""" Totally generic discrete baby-step giant-step function. Solves `na=b` (or `a^n=b`) with `lb\le n\le ub` where ``bounds==(lb,ub)``, raising an error if no such `n` exists. `a` and `b` must be elements of some group with given identity, inverse of ``x`` given by ``inverse(x)``, and group operation on ``x``, ``y`` by ``op(x,y)``. If operation is '*' or '+' then the other arguments are provided automatically; otherwise they must be provided by the caller. INPUT: - ``a`` - group element - ``b`` - group element - ``bounds`` - a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper`` - ``operation`` - string: '*', '+', 'other' - ``identity`` - the identity element of the group - ``inverse()`` - function of 1 argument ``x`` returning inverse of ``x`` - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in group OUTPUT: An integer `n` such that `a^n = b` (or `na = b`). If no such `n` exists, this function raises a ValueError exception. NOTE: This is a generalization of discrete logarithm. One situation where this version is useful is to find the order of an element in a group where we only have bounds on the group order (see the elliptic curve example below). ALGORITHM: Baby step giant step. Time and space are soft `O(\sqrt{n})` where `n` is the difference between upper and lower bounds. EXAMPLES:: sage: b = Mod(2,37); a = b^20 sage: bsgs(b, a, (0,36)) 20 sage: p=next_prime(10^20) sage: a=Mod(2,p); b=a^(10^25) sage: bsgs(a, b, (10^25-10^6,10^25+10^6)) == 10^25 True sage: K = GF(3^6,'b') sage: a = K.gen() sage: b = a^210 sage: bsgs(a, b, (0,K.order()-1)) 210 sage: K.<z>=CyclotomicField(230) sage: w=z^500 sage: bsgs(z,w,(0,229)) 40 An additive example in an elliptic curve group:: sage: F.<a> = GF(37^5) sage: E = EllipticCurve(F, [1,1]) sage: P = E.lift_x(a); P (a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1) This will return a multiple of the order of P:: sage: bsgs(P,P.parent()(0),Hasse_bounds(F.order()),operation='+') 69327408 AUTHOR: - John Cremona (2008-03-15) """ Z = integer_ring.ZZ from operator import inv, mul, neg, add if operation in multiplication_names: identity = a.parent()(1) inverse = inv op = mul elif operation in addition_names: identity = a.parent()(0) inverse = neg op = add else: if identity is None or inverse is None or op is None: raise ValueError("identity, inverse and operation must be given") lb, ub = bounds if lb < 0 or ub < lb: raise ValueError("bsgs() requires 0<=lb<=ub") if a.is_zero() and not b.is_zero(): raise ValueError("No solution in bsgs()") ran = 1 + ub - lb # the length of the interval c = op(inverse(b), multiple(a, lb, operation=operation)) if ran < 30: # use simple search for small ranges i = lb d = c # for i,d in multiples(a,ran,c,indexed=True,operation=operation): for i0 in range(ran): i = lb + i0 if identity == d: # identity == b^(-1)*a^i, so return i return Z(i) d = op(a, d) raise ValueError("No solution in bsgs()") m = ran.isqrt() + 1 # we need sqrt(ran) rounded up table = dict() # will hold pairs (a^(lb+i),lb+i) for i in range(m) d = c for i0 in misc.srange(m): i = lb + i0 if identity == d: # identity == b^(-1)*a^i, so return i return Z(i) table[d] = i d = op(d, a) c = op(c, inverse(d)) # this is now a**(-m) d = identity for i in misc.srange(m): j = table.get(d) if j is not None: # then d == b*a**(-i*m) == a**j return Z(i * m + j) d = op(c, d) raise ValueError("Log of %s to the base %s does not exist in %s." % (b, a, bounds))
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds): r""" Return a parametric three-dimensional space surface. This function is used internally by the :func:`parametric_plot3d` command. There are two ways this function is invoked by :func:`parametric_plot3d`. - ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max), (v_min, v_max))``: `f_x, f_y, f_z` are each functions of two variables - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min, u_max), (v, v_min, v_max))``: `f_x, f_y, f_z` can be viewed as functions of `u` and `v` INPUT: - ``f`` - a 3-tuple of functions or expressions, or vector of size 3 - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple (u, u_min, u_max) - ``vrange`` - a 2-tuple (v_min, v_max) or a 3-tuple (v, v_min, v_max) - ``plot_points`` - (default: "automatic", which is [40,40] for surfaces) initial number of sample points in each parameter; a pair of integers. - ``boundary_style`` - (default: None, no boundary) a dict that describes how to draw the boundaries of regions by giving options that are passed to the line3d command. EXAMPLES: We demonstrate each of the two ways of calling this. See :func:`parametric_plot3d` for many more examples. We do the first one with lambda functions:: sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v)) sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) # indirect doctest Now we do the same thing with symbolic expressions:: sage: u, v = var('u,v') sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True) """ from sage.plot.misc import setup_for_eval_on_grid g, ranges = setup_for_eval_on_grid(f, [urange, vrange], plot_points) urange = srange(*ranges[0], include_endpoint=True) vrange = srange(*ranges[1], include_endpoint=True) G = ParametricSurface(g, (urange, vrange), **kwds) if boundary_style is not None: for u in (urange[0], urange[-1]): G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for v in vrange], **boundary_style) for v in (vrange[0], vrange[-1]): G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for u in urange], **boundary_style) return G
def QuadraticResidueCodeOddPair(n,F): """ Quadratic residue codes of a given odd prime length and base ring either don't exist at all or occur as 4-tuples - a pair of "odd-like" codes and a pair of "even-like" codes. If n 2 is prime then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a quadratic residue mod n. They are constructed as "odd-like" duadic codes associated the splitting (Q,N) mod n, where Q is the set of non-zero quadratic residues and N is the non-residues. EXAMPLES:: sage: codes.QuadraticResidueCodeOddPair(17,GF(13)) (Linear code of length 17, dimension 9 over Finite Field of size 13, Linear code of length 17, dimension 9 over Finite Field of size 13) sage: codes.QuadraticResidueCodeOddPair(17,GF(2)) (Linear code of length 17, dimension 9 over Finite Field of size 2, Linear code of length 17, dimension 9 over Finite Field of size 2) sage: codes.QuadraticResidueCodeOddPair(13,GF(9,"z")) (Linear code of length 13, dimension 7 over Finite Field in z of size 3^2, Linear code of length 13, dimension 7 over Finite Field in z of size 3^2) sage: C1 = codes.QuadraticResidueCodeOddPair(17,GF(2))[1] sage: C1x = C1.extended_code() sage: C2 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0] sage: C2x = C2.extended_code() sage: C2x.spectrum(); C1x.spectrum() [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1] [1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1] sage: C2x == C1x.dual_code() True sage: C3 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0] sage: C3x = C3.extended_code() sage: C3x.spectrum() [1, 0, 0, 0, 14, 0, 0, 0, 1] sage: C3x.is_self_dual() True This is consistent with Theorem 6.6.14 in [HP]_. TESTS:: sage: codes.QuadraticResidueCodeOddPair(9,GF(2)) Traceback (most recent call last): ... ValueError: the argument n must be an odd prime """ from sage.misc.misc import srange from sage.categories.finite_fields import FiniteFields if F not in FiniteFields(): raise ValueError("the argument F must be a finite field") q = F.order() n = Integer(n) if n <= 2 or not n.is_prime(): raise ValueError("the argument n must be an odd prime") Q = quadratic_residues(n); Q.remove(0) # non-zero quad residues N = [x for x in srange(1,n) if x not in Q] # non-zero quad non-residues if q not in Q: raise ValueError("the order of the finite field must be a quadratic residue modulo n") return DuadicCodeOddPair(F,Q,N)
def plot_vector_field3d(functions, xrange, yrange, zrange, plot_points=5, colors='jet', center_arrows=False, **kwds): r""" Plot a 3d vector field INPUT: - ``functions`` - a list of three functions, representing the x-, y-, and z-coordinates of a vector - ``xrange``, ``yrange``, and ``zrange`` - three tuples of the form (var, start, stop), giving the variables and ranges for each axis - ``plot_points`` (default 5) - either a number or list of three numbers, specifying how many points to plot for each axis - ``colors`` (default 'jet') - a color, list of colors (which are interpolated between), or matplotlib colormap name, giving the coloring of the arrows. If a list of colors or a colormap is given, coloring is done as a function of length of the vector - ``center_arrows`` (default False) - If True, draw the arrows centered on the points; otherwise, draw the arrows with the tail at the point - any other keywords are passed on to the plot command for each arrow EXAMPLES:: sage: x,y,z=var('x y z') sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi)) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors=['red','green','blue']) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors='red') sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=4) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=[3,5,7]) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True) TESTS: This tests that Trac # 2100 is fixed in a way compatible with this command:: sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True,aspect_ratio=(1,2,1)) """ (ff, gg, hh), ranges = setup_for_eval_on_grid(functions, [xrange, yrange, zrange], plot_points) xpoints, ypoints, zpoints = [ srange(*r, include_endpoint=True) for r in ranges ] points = [ vector((i, j, k)) for i in xpoints for j in ypoints for k in zpoints ] vectors = [ vector((ff(*point), gg(*point), hh(*point))) for point in points ] try: from matplotlib.cm import get_cmap cm = get_cmap(colors) assert (cm is not None) except (TypeError, AssertionError): if isinstance(colors, (list, tuple)): from matplotlib.colors import LinearSegmentedColormap cm = LinearSegmentedColormap.from_list('mymap', colors) else: cm = lambda x: colors max_len = max(v.norm() for v in vectors) scaled_vectors = [v / max_len for v in vectors] if center_arrows: return sum([ plot(v, color=cm(v.norm()), **kwds).translate(p - v / 2) for v, p in zip(scaled_vectors, points) ]) else: return sum([ plot(v, color=cm(v.norm()), **kwds).translate(p) for v, p in zip(scaled_vectors, points) ])
def ruler(start, end, ticks=4, sub_ticks=4, absolute=False, snap=False, **kwds): """ Draw a ruler in 3-D, with major and minor ticks. INPUT: - ``start`` - the beginning of the ruler, as a list, tuple, or vector. - ``end`` - the end of the ruler, as a list, tuple, or vector. - ``ticks`` - (default: 4) the number of major ticks shown on the ruler. - ``sub_ticks`` - (default: 4) the number of shown subdivisions between each major tick. - ``absolute`` - (default: ``False``) if ``True``, makes a huge ruler in the direction of an axis. - ``snap`` - (default: ``False``) if ``True``, snaps to an implied grid. Type ``line3d.options`` for a dictionary of the default options for lines, which are also available. EXAMPLES: A ruler:: sage: from sage.plot.plot3d.shapes2 import ruler sage: R = ruler([1,2,3],vector([2,3,4])); R A ruler with some options:: sage: R = ruler([1,2,3],vector([2,3,4]),ticks=6, sub_ticks=2, color='red'); R The keyword ``snap`` makes the ticks not necessarily coincide with the ruler:: sage: ruler([1,2,3],vector([1,2,4]),snap=True) The keyword ``absolute`` makes a huge ruler in one of the axis directions:: sage: ruler([1,2,3],vector([1,2,4]),absolute=True) TESTS:: sage: ruler([1,2,3],vector([1,3,4]),absolute=True) Traceback (most recent call last): ... ValueError: Absolute rulers only valid for axis-aligned paths """ start = vector(RDF, start) end = vector(RDF, end) dir = end - start dist = math.sqrt(dir.dot_product(dir)) dir /= dist one_tick = dist/ticks * 1.414 unit = 10 ** math.floor(math.log(dist/ticks, 10)) if unit * 5 < one_tick: unit *= 5 elif unit * 2 < one_tick: unit *= 2 if dir[0]: tick = dir.cross_product(vector(RDF, (0,0,-dist/30))) elif dir[1]: tick = dir.cross_product(vector(RDF, (0,0,dist/30))) else: tick = vector(RDF, (dist/30,0,0)) if snap: for i in range(3): start[i] = unit * math.floor(start[i]/unit + 1e-5) end[i] = unit * math.ceil(end[i]/unit - 1e-5) if absolute: if dir[0]*dir[1] or dir[1]*dir[2] or dir[0]*dir[2]: raise ValueError, "Absolute rulers only valid for axis-aligned paths" m = max(dir[0], dir[1], dir[2]) if dir[0] == m: off = start[0] elif dir[1] == m: off = start[1] else: off = start[2] first_tick = unit * math.ceil(off/unit - 1e-5) - off else: off = 0 first_tick = 0 ruler = shapes.LineSegment(start, end, **kwds) for k in range(1, int(sub_ticks * first_tick/unit)): P = start + dir*(k*unit/sub_ticks) ruler += shapes.LineSegment(P, P + tick/2, **kwds) for d in srange(first_tick, dist + unit/(sub_ticks+1), unit): P = start + dir*d ruler += shapes.LineSegment(P, P + tick, **kwds) ruler += shapes.Text(str(d+off), **kwds).translate(P - tick) if dist - d < unit: sub_ticks = int(sub_ticks * (dist - d)/unit) for k in range(1, sub_ticks): P += dir * (unit/sub_ticks) ruler += shapes.LineSegment(P, P + tick/2, **kwds) return ruler
def plot_vector_field3d(functions, xrange, yrange, zrange, plot_points=5, colors="jet", center_arrows=False, **kwds): r""" Plot a 3d vector field INPUT: - ``functions`` - a list of three functions, representing the x-, y-, and z-coordinates of a vector - ``xrange``, ``yrange``, and ``zrange`` - three tuples of the form (var, start, stop), giving the variables and ranges for each axis - ``plot_points`` (default 5) - either a number or list of three numbers, specifying how many points to plot for each axis - ``colors`` (default 'jet') - a color, list of colors (which are interpolated between), or matplotlib colormap name, giving the coloring of the arrows. If a list of colors or a colormap is given, coloring is done as a function of length of the vector - ``center_arrows`` (default False) - If True, draw the arrows centered on the points; otherwise, draw the arrows with the tail at the point - any other keywords are passed on to the plot command for each arrow EXAMPLES:: sage: x,y,z=var('x y z') sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi)) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors=['red','green','blue']) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors='red') sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=4) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=[3,5,7]) sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True) TESTS: This tests that :trac:`2100` is fixed in a way compatible with this command:: sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True,aspect_ratio=(1,2,1)) """ (ff, gg, hh), ranges = setup_for_eval_on_grid(functions, [xrange, yrange, zrange], plot_points) xpoints, ypoints, zpoints = [srange(*r, include_endpoint=True) for r in ranges] points = [vector((i, j, k)) for i in xpoints for j in ypoints for k in zpoints] vectors = [vector((ff(*point), gg(*point), hh(*point))) for point in points] try: from matplotlib.cm import get_cmap cm = get_cmap(colors) except (TypeError, ValueError): cm = None if cm is None: if isinstance(colors, (list, tuple)): from matplotlib.colors import LinearSegmentedColormap cm = LinearSegmentedColormap.from_list("mymap", colors) else: cm = lambda x: colors max_len = max(v.norm() for v in vectors) scaled_vectors = [v / max_len for v in vectors] if center_arrows: return sum([plot(v, color=cm(v.norm()), **kwds).translate(p - v / 2) for v, p in zip(scaled_vectors, points)]) else: return sum([plot(v, color=cm(v.norm()), **kwds).translate(p) for v, p in zip(scaled_vectors, points)])