Ticket #10477: trac_10477-random-vector-constructor.patch

File trac_10477-random-vector-constructor.patch, 5.8 KB (added by rbeezer, 11 years ago)
  • sage/modules/all.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1292380286 28800
    # Node ID 8ef9265520be783fb0b1df51188b3a5fe8513856
    # Parent  800c70b1dfa3e31813ecd5ab8d54d1ca7f36b71b
    10477: random vector constructor
    
    diff -r 800c70b1dfa3 -r 8ef9265520be sage/modules/all.py
    a b  
    1717
    1818from free_quadratic_module import FreeQuadraticModule, QuadraticSpace, InnerProductSpace, is_FreeQuadraticModule
    1919
    20 from free_module_element import is_FreeModuleElement, vector, free_module_element, zero_vector
     20from free_module_element import is_FreeModuleElement, vector, free_module_element, zero_vector, random_vector
    2121
    2222from free_module_homspace import is_FreeModuleHomspace
    2323
  • sage/modules/free_module_element.pyx

    diff -r 800c70b1dfa3 -r 8ef9265520be sage/modules/free_module_element.pyx
    a b  
    529529        raise ValueError("elements of a zero vector belong in a ring, not %s" % arg0)
    530530    return vector(arg0, arg1)
    531531
     532def random_vector(ring, degree=None, *args, **kwds):
     533    r"""
     534    Returns a vector (or module element) with random entries.
     535
     536    INPUT:
     537
     538    - ring - default: ``ZZ`` - the base ring for the entries
     539    - degree - a non-negative integer for the number of entries in the vector
     540    - sparse - default: ``False`` - whether to use a sparse implementation
     541    - args, kwds - additional arguments and keywords are passed
     542      to the ``random_element()`` method of the ring
     543
     544    OUTPUT:
     545
     546    A vector, or free module element, with ``degree`` elements
     547    from ``ring``, chosen randomly from the ring according to
     548    the ring's ``random_element()`` method.
     549
     550    .. note::
     551        See below for examples of how random elements are
     552        generated by some common base rings.
     553
     554    EXAMPLES:
     555
     556    First, module elements over the integers.
     557    The default distribution is tightly clustered around -1, 0, 1.
     558    Uniform distributions can be specified by giving bounds, though
     559    the upper bound is never met.  See
     560    :meth:`sage.rings.integer_ring.IntegerRing_class.random_element`
     561    for several other variants. ::
     562
     563        sage: random_vector(10)
     564        (-8, 2, 0, 0, 1, -1, 2, 1, -95, -1)
     565
     566        sage: sorted(random_vector(20))
     567        [-12, -6, -4, -4, -2, -2, -2, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 4, 5]
     568
     569        sage: random_vector(ZZ, 20, x=4)
     570        (2, 0, 3, 0, 1, 0, 2, 0, 2, 3, 0, 3, 1, 2, 2, 2, 1, 3, 2, 3)
     571
     572        sage: random_vector(ZZ, 20, x=-20, y=100)
     573        (43, 47, 89, 31, 56, -20, 23, 52, 13, 53, 49, -12, -2, 94, -1, 95, 60, 83, 28, 63)
     574
     575        sage: random_vector(ZZ, 20, distribution="1/n")
     576        (0, -1, -2, 0, -1, -2, 0, 0, 27, -1, 1, 1, 0, 2, -1, 1, -1, -2, -1, 3)
     577
     578    Now over the rationals.  Note that bounds on the numerator and
     579    denominator may be specified.  See
     580    :meth:`sage.rings.rational_field.RationalField.random_element`
     581    for documentation. ::
     582
     583        sage: random_vector(QQ, 10)
     584        (-1, 1/4, 2, 2, -2, 1, -1, 0, 1, -1)
     585
     586        sage: random_vector(QQ, 10, num_bound = 15, den_bound = 5)
     587        (2, -12/5, -5/2, -4, -5/2, 4/5, 3/2, -1, -2, -12/5)
     588
     589    Inexact rings may be used as well.  The reals have
     590    uniform distributions, with the range `(-1,1)` as
     591    the default.  More at:
     592    :meth:`sage.rings.real_mpfr.RealField_class.random_element` ::
     593
     594        sage: random_vector(RR, 5)
     595        (0.8468..., -0.1538..., -0.8955..., 0.2241..., -0.9609...)
     596
     597        sage: random_vector(RR, 5, min = 8, max = 14)
     598        (11.4074..., 12.5127..., 11.6469..., 9.0442..., 13.6568...)
     599
     600    Any ring with a ``random_element()`` method may be used. ::
     601
     602        sage: F = FiniteField(23)
     603        sage: hasattr(F, 'random_element')
     604        True
     605        sage: random_vector(F, 10)
     606        (15, 9, 6, 18, 8, 12, 18, 21, 3, 13)
     607
     608    The default implementation is a dense representation, equivalent to
     609    setting ``sparse=False``. ::
     610
     611        sage: v = random_vector(10)
     612        sage: v.is_sparse()
     613        False
     614
     615        sage: w = random_vector(ZZ, 20, sparse=True)
     616        sage: w.is_sparse()
     617        True
     618
     619    Inputs get checked before constructing the vector. ::
     620
     621        sage: random_vector('junk')
     622        Traceback (most recent call last):
     623        ...
     624        TypeError: degree of a random vector must be an integer, not None
     625
     626        sage: random_vector('stuff', 5)
     627        Traceback (most recent call last):
     628        ...
     629        TypeError: elements of a vector, or module element, must come from a ring, not stuff
     630
     631        sage: random_vector(ZZ, -9)
     632        Traceback (most recent call last):
     633        ...
     634        ValueError: degree of a random vector must be non-negative, not -9
     635    """
     636    if sage.rings.integer.is_Integer(ring) or isinstance(ring,(int,long)):
     637        degree = ring
     638        ring = sage.rings.integer_ring.IntegerRing()
     639    if not (sage.rings.integer.is_Integer(degree) or isinstance(degree,(int,long))):
     640        raise TypeError("degree of a random vector must be an integer, not %s" % degree)
     641    if degree < 0:
     642        raise ValueError("degree of a random vector must be non-negative, not %s" % degree)
     643    if not is_Ring(ring):
     644        raise TypeError("elements of a vector, or module element, must come from a ring, not %s" % ring)
     645    if not hasattr(ring, "random_element"):
     646        raise AttributeError("cannot create a random vector since there is no random_element() method for %s" % ring )
     647    sparse = kwds.pop('sparse', False)
     648    entries = [ring.random_element(*args, **kwds) for _ in range(degree)]
     649    return vector(ring, degree, entries, sparse)
     650
    532651cdef class FreeModuleElement(element_Vector):   # abstract base class
    533652    """
    534653    An element of a generic free module.