Changeset 7504:5908f80abccc


Ignore:
Timestamp:
12/01/07 21:17:45 (5 years ago)
Author:
Carl Witty <cwitty@…>
Branch:
default
Message:

Add more cases for polynomial .roots() (most importantly, ring=QQbar)

Location:
sage/rings
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sage/rings/polynomial/complex_roots.py

    r7471 r7504  
    2525from copy import copy 
    2626 
     27from sage.rings.real_mpfi import RealIntervalField 
    2728from sage.rings.complex_field import ComplexField 
    2829from sage.rings.complex_interval_field import ComplexIntervalField 
     30from sage.rings.qqbar import AA, QQbar 
    2931 
    3032def refine_root(ip, ipd, irt, fld): 
     
    111113 
    112114        nirt = center - val / slope 
    113         if nirt in irt and nirt.diameter() >= irt.diameter() >> 1: 
     115        if nirt in irt and nirt.diameter() >= irt.diameter() >> 3: 
    114116            # If the new diameter is much less than the original diameter, 
    115117            # then we have not yet converged.  (Perhaps we were asked 
     
    122124        else: 
    123125            irt = irt.union(nirt) 
     126            # If we don't find a root after a while, try (approximately) 
     127            # tripling the size of the region. 
     128            if i >= 6: 
     129                rd = irt.real().absolute_diameter() 
     130                id = irt.imag().absolute_diameter() 
     131                md = max(rd, id) 
     132                md_intv = RealIntervalField(rd.prec())(-md, md) 
     133                md_cintv = ComplexIntervalField(rd.prec())(md_intv, md_intv) 
     134                irt = irt + md_cintv 
    124135 
    125136        if not smashed_real and irt.real().contains_zero(): 
    126137            irt = irt.parent()(0, irt.imag()) 
     138            smashed_real = True 
    127139        if not smashed_imag and irt.imag().contains_zero(): 
    128140            irt = irt.parent()(irt.real(), 0) 
     141            smashed_imag = True 
    129142 
    130143    return None 
     
    244257    has a repeated root, then the algorithm will loop forever!) 
    245258 
     259    You can specify retval='interval' (the default) to get roots as 
     260    complex intervals.  The other options are retval='algebraic' to 
     261    get elements of QQbar, or retval='algebraic_real' to get only 
     262    the real roots, and to get them as elements of AA. 
     263 
    246264    EXAMPLES: 
    247265        sage: from sage.rings.polynomial.complex_roots import complex_roots 
     
    257275    This polynomial actually has all-real coefficients, and is very, very 
    258276    close to (x-1)^5: 
    259         sage: [RR(QQ(x)) for x in list(p - (x-1)^5)] 
     277        sage: [RR(QQ(a)) for a in list(p - (x-1)^5)] 
    260278        [3.87259191484932e-121, -3.87259191484932e-121] 
    261279        sage: rts = complex_roots(p) 
    262280        sage: [ComplexIntervalField(10)(rt[0] - 1) for rt in rts] 
    263281        [0, [7.8886e-31 .. 7.8887e-31]*I, [7.8886e-31 .. 7.8887e-31], [-7.8887e-31 .. -7.8886e-31]*I, [-7.8887e-31 .. -7.8886e-31]] 
     282 
     283    We can get roots either as intervals, or as elements of QQbar or AA. 
     284        sage: p = (x^2 + x - 1) 
     285        sage: p = p * p(x*im) 
     286        sage: p 
     287        (-1)*x^4 + (im - 1)*x^3 + im*x^2 + (-im - 1)*x + 1 
     288        sage: rts = complex_roots(p); type(rts[0][0]), rts 
     289        (<type 'sage.rings.complex_interval.ComplexIntervalFieldElement'>, [([-0.000000000000000085405681994008930 .. 0.00000000000000018852810564551411] + [1.6180339887498944 .. 1.6180339887498952]*I, 1), ([-1.6180339887498952 .. -1.6180339887498944] + [-0.00000000000000018852810564551411 .. 0.000000000000000085405681994008930]*I, 1), ([0.61803398874989468 .. 0.61803398874989502] + [-0.00000000000000011497311295586537 .. 0.000000000000000052767663576832497]*I, 1), ([-0.000000000000000054022849329007172 .. 0.00000000000000011371792720369062] - [0.61803398874989468 .. 0.61803398874989502]*I, 1)]) 
     290        sage: rts = complex_roots(p, retval='algebraic'); type(rts[0][0]), rts 
     291        (<class 'sage.rings.qqbar.AlgebraicNumber'>, [([-3.7249532943328317e-20 .. 3.7095114777437122e-20] + [1.6180339887498946 .. 1.6180339887498950]*I, 1), ([-1.6180339887498950 .. -1.6180339887498946] + [-3.7095114777437122e-20 .. 3.7249532943328317e-20]*I, 1), ([0.61803398874989479 .. 0.61803398874989491] + [-1.8145161579843782e-20 .. 3.1750950176743468e-20]*I, 1), ([-2.5399597786669076e-20 .. 2.0313092838036301e-20] - [0.61803398874989479 .. 0.61803398874989491]*I, 1)]) 
     292        sage: rts = complex_roots(p, retval='algebraic_real'); type(rts[0][0]), rts 
     293        (<class 'sage.rings.qqbar.AlgebraicReal'>, [([-1.6180339887498950 .. -1.6180339887498946], 1), ([0.61803398874989479 .. 0.61803398874989491], 1)]) 
    264294    """ 
    265295 
     
    284314                ok = False 
    285315                break 
     316            if retval != 'interval': 
     317                factor = QQbar.common_polynomial(factor) 
    286318            for irt in irts: 
    287                 all_rts.append((irt, exp)) 
    288  
    289         if ok and intervals_disjoint([rt for (rt, mult) in all_rts]): 
    290             return all_rts 
     319                all_rts.append((irt, factor, exp)) 
     320 
     321        if ok and intervals_disjoint([rt for (rt, fac, mult) in all_rts]): 
     322            if retval == 'interval': 
     323                return [(rt, mult) for (rt, fac, mult) in all_rts] 
     324            elif retval == 'algebraic': 
     325                return [(QQbar.polynomial_root(fac, rt), mult) for (rt, fac, mult) in all_rts] 
     326            elif retval == 'algebraic_real': 
     327                rts = [] 
     328                for (rt, fac, mult) in all_rts: 
     329                    qqbar_rt = QQbar.polynomial_root(fac, rt) 
     330                    if qqbar_rt.imag().is_zero(): 
     331                        rts.append((AA(qqbar_rt), mult)) 
     332                return rts 
    291333 
    292334        prec = prec * 2 
  • sage/rings/polynomial/polynomial_element.pyx

    r7486 r7504  
    7474 
    7575cdef object is_AlgebraicRealField 
     76cdef object is_AlgebraicField 
     77cdef object is_AlgebraicField_common 
    7678cdef object NumberField_quadratic 
    7779cdef object is_ComplexIntervalField 
     
    8082    # A hack to avoid circular imports. 
    8183    global is_AlgebraicRealField 
     84    global is_AlgebraicField 
     85    global is_AlgebraicField_common 
    8286    global NumberField_quadratic 
    8387    global is_ComplexIntervalField 
     
    8892    import sage.rings.qqbar 
    8993    is_AlgebraicRealField = sage.rings.qqbar.is_AlgebraicRealField 
     94    is_AlgebraicField = sage.rings.qqbar.is_AlgebraicField 
     95    is_AlgebraicField_common = sage.rings.qqbar.is_AlgebraicField_common 
    9096    import sage.rings.number_field.number_field 
    9197    NumberField_quadratic = sage.rings.number_field.number_field.NumberField_quadratic 
     
    25072513            sage: p.roots(ring=ComplexIntervalField(200)) 
    25082514            [([1.1673039782614186842560458998548421807205603715254890391400816 .. 1.1673039782614186842560458998548421807205603715254890391400829], 1), ([0.18123244446987538390180023778112063996871646618462304743773153 .. 0.18123244446987538390180023778112063996871646618462304743773341] + [1.0839541013177106684303444929807665742736402431551156543011306 .. 1.0839541013177106684303444929807665742736402431551156543011344]*I, 1), ([0.18123244446987538390180023778112063996871646618462304743773153 .. 0.18123244446987538390180023778112063996871646618462304743773341] - [1.0839541013177106684303444929807665742736402431551156543011306 .. 1.0839541013177106684303444929807665742736402431551156543011344]*I, 1), ([-0.76488443360058472602982318770854173032899665194736756700777454 .. -0.76488443360058472602982318770854173032899665194736756700777...] + [0.35247154603172624931794709140258105439420648082424733283769... .. 0.35247154603172624931794709140258105439420648082424733283769...]*I, 1), ([-0.76488443360058472602982318770854173032899665194736756700777454 .. -0.76488443360058472602982318770854173032899665194736756700777204] - [0.35247154603172624931794709140258105439420648082424733283769122 .. 0.35247154603172624931794709140258105439420648082424733283769341]*I, 1)] 
     2515            sage: rts = p.roots(ring=QQbar); rts 
     2516            [([1.1673039782614185 .. 1.1673039782614188], 1), ([0.18123244446987538 .. 0.18123244446987541] + [1.0839541013177105 .. 1.0839541013177108]*I, 1), ([0.18123244446987538 .. 0.18123244446987541] - [1.0839541013177105 .. 1.0839541013177108]*I, 1), ([-0.76488443360058478 .. -0.76488443360058466] + [0.35247154603172620 .. 0.35247154603172626]*I, 1), ([-0.76488443360058478 .. -0.76488443360058466] - [0.35247154603172620 .. 0.35247154603172626]*I, 1)] 
     2517            sage: p.roots(ring=AA) 
     2518            [([1.1673039782614185 .. 1.1673039782614188], 1)] 
     2519            sage: p = (x - rts[1][0])^2 * (x^2 + x + 1) 
     2520            sage: p.roots(ring=QQbar) 
     2521            [([-0.50000000000000012 .. -0.49999999999999994] + [0.86602540378443859 .. 0.86602540378443871]*I, 1), ([-0.50000000000000000 .. -0.50000000000000000] - [0.86602540378443859 .. 0.86602540378443871]*I, 1), ([0.18123244446987538 .. 0.18123244446987541] + [1.0839541013177105 .. 1.0839541013177108]*I, 2)] 
     2522            sage: p.roots(ring=CIF) 
     2523            [([-0.50000000000000012 .. -0.49999999999999994] + [0.86602540378443859 .. 0.86602540378443871]*I, 1), ([-0.50000000000000000 .. -0.50000000000000000] - [0.86602540378443859 .. 0.86602540378443871]*I, 1), ([0.18123244446987538 .. 0.18123244446987541] + [1.0839541013177105 .. 1.0839541013177108]*I, 2)] 
    25092524 
    25102525        Note that coefficients in a number field with defining polynomial 
     
    25512566 
    25522567        Note that we can find the roots of a polynomial with 
    2553         algebraic real coefficients: 
     2568        algebraic coefficients: 
    25542569         
    25552570            sage: rt2 = sqrt(AA(2)) 
     
    25912606        this method gives.) 
    25922607 
    2593         If L is CIF, and K is ZZ, QQ, AA, or the Gaussian rationals, 
    2594         then the root isolation algorithm 
     2608        If L is QQbar or CIF, and K is ZZ, QQ, AA, QQbar, or the 
     2609        Gaussian rationals, then the root isolation algorithm 
    25952610        sage.rings.polynomial.complex_roots.complex_roots() is used. 
    2596         (You can call complex_roots() directly to get more control than 
    2597         this method gives.) 
     2611        (You can call complex_roots() directly to get more control 
     2612        than this method gives.) 
     2613 
     2614        If L is AA and K is QQbar or the Gaussian rationals, then 
     2615        complex_roots() is used (as above) to find roots in QQbar, 
     2616        then these roots are filtered to select only the real roots. 
    25982617 
    25992618        If L is floating-point and K is not, then we attempt to change 
     
    27142733                return rts 
    27152734 
    2716         if L != K or is_AlgebraicRealField(L): 
     2735        if L != K or is_AlgebraicField_common(L): 
    27172736            # So far, the only "special" implementations are for real 
    27182737            # and complex root isolation. 
     
    27482767 
    27492768            if (is_IntegerRing(K) or is_RationalField(K) 
    2750                 or is_AlgebraicRealField(K) or input_gaussian) and \ 
    2751                 (is_ComplexIntervalField(L)): 
     2769                or is_AlgebraicField_common(K) or input_gaussian) and \ 
     2770                (is_ComplexIntervalField(L) or is_AlgebraicField_common(L)): 
    27522771 
    27532772                from sage.rings.polynomial.complex_roots import complex_roots 
    27542773 
    2755                 rts = complex_roots(self, min_prec=L.prec()) 
     2774                if is_ComplexIntervalField(L): 
     2775                    rts = complex_roots(self, min_prec=L.prec()) 
     2776                elif is_AlgebraicField(L): 
     2777                    rts = complex_roots(self, retval='algebraic') 
     2778                else: 
     2779                    rts = complex_roots(self, retval='algebraic_real') 
    27562780 
    27572781                if multiplicities: 
  • sage/rings/qqbar.py

    r7503 r7504  
    645645 
    646646QQbar = AlgebraicField() 
     647 
     648def is_AlgebraicField_common(F): 
     649    return isinstance(F, AlgebraicField_common) 
    647650 
    648651def prec_seq(): 
     
    16281631                 isinstance(x, NumberFieldElement_quadratic) and \ 
    16291632                 list(x.parent().polynomial()) == [1, 0, 1]: 
    1630             self._descr = ANExtensionElement(QQbar_I_generator, QQbar_I_nf(x)) 
     1633            self._descr = ANExtensionElement(QQbar_I_generator, QQbar_I_nf(x.list())) 
    16311634        else: 
    16321635            raise TypeError, "Illegal initializer for algebraic number" 
Note: See TracChangeset for help on using the changeset viewer.