Ticket #11725: trac_11725-random-algebraic-numbers3.patch

File trac_11725-random-algebraic-numbers3.patch, 5.3 KB (added by spice, 10 years ago)

Replaces previous patch

  • sage/rings/qqbar.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1314143349 25200
    # Node ID b1dc759dfe93ef3f5fb68124a2caf844563fceba
    # Parent  b2c0ed2e09a453751e4b2fe092667487f530eac3
    11725: random elements of QQbar
    
    diff --git a/sage/rings/qqbar.py b/sage/rings/qqbar.py
    a b  
    1 r"""
     1"""
    22Field of Algebraic Numbers
    33
    44AUTHOR:
     
    938938        """
    939939        return AlgebraicNumber(ANRoot(poly, interval, multiplicity))
    940940
     941    def random_element(self, poly_degree=2, *args, **kwds):
     942        r"""
     943        Returns a random algebraic number.
     944       
     945        INPUT:
     946       
     947        - ``poly_degree`` - default: 2 - degree of the random
     948          polynomial over the integers of which the returned
     949          algebraic number is a root.  This is not the degree of
     950          the minimal polynomial of the number. Increase this
     951          parameter to achieve a greater diversity of algebraic
     952          numbers, at a cost of greater computation time. You can
     953          also vary the distribution of the coefficients but that
     954          will not vary the degree of the extension containing
     955          the element.
     956         
     957        - ``args``, ``kwds`` - arguments and keywords passed to
     958          the random number generator for elements of ``ZZ``, the
     959          integers.  See
     960          :meth:`~sage.rings.integer_ring.IntegerRing_class.random_element`
     961          for details, or see example below.
     962         
     963        OUTPUT:
     964       
     965        An element of ``QQbar``, the field of algebraic
     966        numbers (see :mod:`sage.rings.qqbar`).
     967       
     968        ALGORITHM:
     969       
     970        A polynomial with degree between 1 and ``poly_degree``,
     971        with random integer coefficients is created.  A root of this
     972        polynomial is chosen at random.  The default degree is
     973        2 and the integer coefficients come from a distribution
     974        heavily weighted towards $0, \pm 1, \pm 2$.
     975       
     976        EXAMPLES::
     977       
     978            sage: a = QQbar.random_element()
     979            sage: a                         # random
     980            0.2626138748742799? + 0.8769062830975992?*I
     981            sage: a in QQbar
     982            True
     983       
     984            sage: b = QQbar.random_element(poly_degree=20)
     985            sage: b                         # random
     986            -0.8642649077479498? - 0.5995098147478391?*I
     987            sage: b in QQbar
     988            True
     989       
     990        Parameters for the distribution of the integer coefficients
     991        of the polynomials can be passed on to the random element method
     992        for integers.  For example, current default behavior of this method
     993        returns zero about 15% of the time; if we do not include zero as a
     994        possible coefficient, there will never be a zero constant term, and
     995        thus never a zero root. ::
     996       
     997            sage: z = [QQbar.random_element(x=1, y=10) for _ in range(20)]
     998            sage: QQbar(0) in z
     999            False
     1000           
     1001         If you just want real algebraic numbers you can filter them out. 
     1002         Using an odd degree for the polynomials will insure some degree of
     1003         success.  ::
     1004         
     1005            sage: r = []
     1006            sage: while len(r) < 3:
     1007            ...     x = QQbar.random_element(poly_degree=3)
     1008            ...     if x in AA:
     1009            ...       r.append(x)
     1010            sage: (len(r) == 3) and all([z in AA for z in r])
     1011            True
     1012           
     1013        TESTS:
     1014       
     1015            sage: QQbar.random_element('junk')
     1016            Traceback (most recent call last):
     1017            ...
     1018            TypeError: polynomial degree must be an integer, not junk
     1019            sage: QQbar.random_element(poly_degree=0)
     1020            Traceback (most recent call last):
     1021            ...
     1022            ValueError: polynomial degree must be greater than zero, not 0
     1023           
     1024        Random vectors already have a 'degree' keyword, so
     1025        we cannot use that for the polynomial's degree.  ::
     1026       
     1027            sage: v = random_vector(QQbar, degree=2, poly_degree=3)
     1028            sage: v                                 # random
     1029            (0.4694381338921299?, -0.500000000000000? + 0.866025403784439?*I)
     1030        """
     1031        import sage.rings.all
     1032        import sage.misc.prandom
     1033        try:
     1034            poly_degree = sage.rings.all.ZZ(poly_degree)
     1035        except TypeError:
     1036            msg = "polynomial degree must be an integer, not {0}"
     1037            raise TypeError(msg.format(poly_degree))
     1038        if poly_degree < 1:
     1039            msg = "polynomial degree must be greater than zero, not {0}"
     1040            raise ValueError(msg.format(poly_degree))
     1041        R = PolynomialRing(sage.rings.all.ZZ, 'x')
     1042        p = R.random_element(degree=poly_degree, *args, **kwds)
     1043        # degree zero polynomials have no roots
     1044        # totally zero poly has degree -1
     1045        # add a random leading term
     1046        if p.degree() < 1:   
     1047            g = R.gen(0)
     1048            m = sage.misc.prandom.randint(1, poly_degree)
     1049            p = p + g**m
     1050        roots = p.roots(ring=QQbar, multiplicities=False)
     1051       
     1052        # p will have at least one root; pick one at random
     1053        # could we instead just compute one root "randomly"?
     1054        m = sage.misc.prandom.randint(0, len(roots)-1)
     1055        return roots[m]
     1056
    9411057def is_AlgebraicField(F):
    9421058    return isinstance(F, AlgebraicField)
    9431059