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
Beispiel #2
0
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
Beispiel #3
0
        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)))
Beispiel #4
0
        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)))
Beispiel #5
0
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
Beispiel #7
0
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)
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
    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
Beispiel #12
0
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)
Beispiel #13
0
    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
Beispiel #14
0
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
Beispiel #15
0
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
Beispiel #16
0
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 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)
Beispiel #18
0
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)
Beispiel #21
0
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)
        ])
Beispiel #22
0
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
Beispiel #23
0
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)])