Ticket #1275: 7427-for-review.patch
| File 7427-for-review.patch, 178.1 kB (added by cwitty, 1 year ago) |
|---|
-
a/sage/calculus/calculus.py
old new 2830 2830 def _recursive_sub_over_ring(self, kwds, ring): 2831 2831 return ring(self) 2832 2832 2833 def _algebraic_(self, field): 2834 """ 2835 EXAMPLES: 2836 sage: a = SR(5/6) 2837 sage: AA(a) 2838 5/6 2839 sage: type(AA(a)) 2840 <class 'sage.rings.algebraic_real.AlgebraicReal'> 2841 sage: QQbar(a) 2842 5/6 2843 sage: type(QQbar(a)) 2844 <class 'sage.rings.algebraic_real.AlgebraicNumber'> 2845 sage: from sage.calculus.calculus import SymbolicConstant 2846 sage: i = SymbolicConstant(I) 2847 sage: AA(i) 2848 Traceback (most recent call last): 2849 ... 2850 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 2851 sage: QQbar(i) 2852 1*I 2853 sage: phi = SymbolicConstant(golden_ratio) 2854 sage: AA(phi) 2855 [1.6180339887498946 .. 1.6180339887498950] 2856 sage: QQbar(phi) 2857 [1.6180339887498946 .. 1.6180339887498950] 2858 """ 2859 2860 # Out of the many kinds of things that can be in a SymbolicConstant, 2861 # we accept only rational numbers (or things that can be coerced 2862 # to rational) and a few instances of Constant. 2863 2864 if isinstance(self._obj, sage.functions.constants.Constant) \ 2865 and hasattr(self._obj, '_algebraic_'): 2866 return self._obj._algebraic_(field) 2867 return field(Rational(self._obj)) 2833 2868 2834 2869 2835 2870 class SymbolicPolynomial(Symbolic_object): … … 3073 3108 rops = [op._real_rqdf_(field) for op in self._operands] 3074 3109 return self._operator(*rops) 3075 3110 3111 def _algebraic_(self, field): 3112 """ 3113 Convert a symbolic expression to an algebraic number. 3114 3115 EXAMPLES: 3116 sage: QQbar(sqrt(2) + sqrt(8)) 3117 [4.2426406871192847 .. 4.2426406871192857] 3118 sage: AA(sqrt(2) ^ 4) == 4 3119 True 3120 sage: AA(-golden_ratio) 3121 [-1.6180339887498950 .. -1.6180339887498946] 3122 sage: QQbar((2*I)^(1/2)) 3123 [1.0000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 1.0000000000000000]*I 3124 """ 3125 3126 # We try to avoid simplifying, because maxima's simplify command 3127 # can change the value of a radical expression (by changing which 3128 # root is selected). 3129 try: 3130 if self._operator is operator.pow: 3131 base = field(self._operands[0]) 3132 expt = Rational(self._operands[1]) 3133 return field(field(base) ** expt) 3134 else: 3135 rops = [field(op) for op in self._operands] 3136 return self._operator(*rops) 3137 except TypeError: 3138 if self.is_simplified(): 3139 raise 3140 else: 3141 return self.simplify()._algebraic_(field) 3142 3076 3143 def _is_atomic(self): 3077 3144 try: 3078 3145 return self._atomic … … 4011 4078 else: 4012 4079 return z 4013 4080 4081 def _algebraic_(self, field): 4082 """ 4083 Coerce to an algebraic number. 4084 4085 EXAMPLES: 4086 sage: QQbar(sqrt(2)) 4087 [1.4142135623730949 .. 1.4142135623730952] 4088 sage: AA(abs(1+I)) 4089 [1.4142135623730949 .. 1.4142135623730952] 4090 """ 4091 # We try to avoid simplifying, because maxima's simplify command 4092 # can change the value of a radical expression (by changing which 4093 # root is selected). 4094 f = self._operands[0] 4095 g = self._operands[1] 4096 try: 4097 return field(f(g._algebraic_(field))) 4098 except TypeError: 4099 if self.is_simplified(): 4100 raise 4101 else: 4102 return self.simplify()._algebraic_(field) 4103 4104 4014 4105 class PrimitiveFunction(SymbolicExpression): 4015 4106 def __init__(self, needs_braces=False): 4016 4107 SymbolicExpression.__init__(self) -
a/sage/functions/constants.py
old new 537 537 def _real_double_(self, R): 538 538 raise TypeError 539 539 540 def _algebraic_(self, field): 541 import sage.rings.algebraic_real 542 return field(sage.rings.algebraic_real.QQbar_I) 543 540 544 def __abs__(self): 541 545 return Integer(1) 542 546 … … 691 695 692 696 def _mpfr_(self,R): #is this OK for _mpfr_ ? 693 697 return (R(1)+R(5).sqrt())*R(0.5) 698 699 def _algebraic_(self, field): 700 import sage.rings.algebraic_real 701 return field(sage.rings.algebraic_real.get_AA_golden_ratio()) 694 702 695 703 golden_ratio = GoldenRatio() 696 704 -
a/sage/rings/algebraic_real.py
old new 1 1 """ 2 Field of Algebraic Reals2 Field of Algebraic Numbers 3 3 4 4 AUTHOR: 5 5 -- Carl Witty (2007-01-27): initial version 6 7 This is an implementation of the algebraic reals (the real numbers which 8 are the zero of a polynomial in ZZ[x]). All computations are exact. 9 10 As with many other implementations of the algebraic numbers, we avoid 11 computing a number field and working in the number field whenever possible. 6 -- Carl Witty (2007-10-29): massive rewrite to support complex 7 as well as real numbers 8 9 This is an implementation of the algebraic numbers (the complex 10 numbers which are the zero of a polynomial in ZZ[x]; in other words, 11 the algebraic closure of QQ, with an embedding into CC). All 12 computations are exact. We also include an implementation of the 13 algebraic reals (the intersection of the algebraic numbers with RR). 14 The field of algebraic numbers is available with abbreviation QQbar; 15 the field of algebraic reals has abbreviation AA. 16 17 As with many other implementations of the algebraic numbers, we try 18 hard to avoid computing a number field and working in the number 19 field; instead, we use floating-point interval arithmetic whenever 20 possible (basically whenever we need to prove disequalities), and 21 resort to symbolic computation only as needed (basically to prove 22 equalities). 12 23 13 24 Algebraic numbers exist in one of the following forms: 14 25 15 26 * a rational number 27 * the product of a rational number and an n'th root of unity 16 28 * the sum, difference, product, or quotient of algebraic numbers 29 * the negation, inverse, absolute value, norm, real part, 30 imaginary part, or complex conjugate of an algebraic number 17 31 * a particular root of a polynomial, given as a polynomial with 18 32 algebraic coefficients, an isolating interval (given as a 19 33 RealIntervalFieldElement) which encloses exactly one root, and … … 22 36 number given as the root of an irreducible polynomial with integral 23 37 coefficients and the polynomial is given as a NumberFieldElement 24 38 25 An algebraic number can be coerced into RealIntervalField; every algebraic 26 number has a cached interval of the highest precision yet calculated. 39 The multiplicative subgroup of the algebraic numbers generated 40 by the rational numbers and the roots of unity is handled particularly 41 efficiently, as long as these roots of unity come from the QQbar.zeta() 42 method. Cyclotomic fields in general are fairly efficient, again 43 as long as they are derived from QQbar.zeta(). 44 45 An algebraic number can be coerced into ComplexIntervalField (or 46 RealIntervalField, for algebraic reals); every algebraic number has a 47 cached interval of the highest precision yet calculated. 27 48 28 49 Everything is done with intervals except for comparisons. By default, 29 50 comparisons compute the two algebraic numbers with 128-bit precision … … 44 65 EXAMPLES: 45 66 sage: sqrt(AA(2)) > 0 46 67 True 47 sage: (sqrt(5 + 2*sqrt(AA(6))) - sqrt(AA(3)))**2 == 2 68 sage: (sqrt(5 + 2*sqrt(QQbar(6))) - sqrt(QQbar(3)))^2 == 2 69 True 70 sage: AA((sqrt(5 + 2*sqrt(6)) - sqrt(3))^2) == 2 48 71 True 49 72 50 73 For a monic cubic polynomial x^3 + b*x^2 + c*x + d with roots … … 82 105 sage: disc1(b, c, d) == disc2(s1, s2, s3) 83 106 True 84 107 108 We can coerce from symbolic expressions: 109 110 sage: QQbar(sqrt(-5)) 111 [2.2360679774997893 .. 2.2360679774997899]*I 112 sage: AA(sqrt(2) + sqrt(3)) 113 [3.1462643699419721 .. 3.1462643699419726] 114 sage: AA(sqrt(2)) + sqrt(3) 115 [3.1462643699419721 .. 3.1462643699419726] 116 sage: sqrt(2) + QQbar(sqrt(3)) 117 [3.1462643699419721 .. 3.1462643699419726] 118 sage: QQbar(I) 119 1*I 120 sage: AA(I) 121 Traceback (most recent call last): 122 ... 123 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 124 sage: QQbar(I * golden_ratio) 125 [1.6180339887498946 .. 1.6180339887498950]*I 126 sage: AA(golden_ratio)^2 - AA(golden_ratio) 127 1 128 sage: QQbar((-8)^(1/3)) 129 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 130 sage: AA((-8)^(1/3)) 131 -2 132 sage: QQbar((-4)^(1/4)) 133 [1.0000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 1.0000000000000000]*I 134 sage: AA((-4)^(1/4)) 135 Traceback (most recent call last): 136 ... 137 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 138 139 We can explicitly coerce from QQ[I]. (Technically, this is not quite 140 kosher, since QQ[I] doesn't come with an embedding; we don't know 141 whether the field generator is supposed to map to +I or -I. We assume 142 that for any quadratic field with polynomial x^2+1, the generator maps 143 to +I.) 144 145 sage: K.<im> = QQ[I] 146 sage: pythag = QQbar(3/5 + 4*im/5); pythag 147 4/5*I + 3/5 148 sage: pythag.abs() == 1 149 True 150 151 However, implicit coercion from QQ[I] is not allowed. 152 153 sage: QQbar(1) + im 154 Traceback (most recent call last): 155 ... 156 TypeError: unsupported operand parent(s) for '+': 'Algebraic Field' and 'Number Field in I with defining polynomial x^2 + 1' 157 158 We can implicitly coerce from algebraic reals to algebraic numbers: 159 160 sage: a = QQbar(1); print a, a.parent() 161 1 Algebraic Field 162 sage: b = AA(1); print b, b.parent() 163 1 Algebraic Real Field 164 sage: c = a + b; print c, c.parent() 165 2 Algebraic Field 166 85 167 Some computation with radicals: 86 168 87 169 sage: phi = (1 + sqrt(AA(5))) / 2 … … 101 183 sage: rt23 * rt35 == rt25 102 184 True 103 185 104 Algebraic reals which are known to be rational print as rationals; otherwise105 they print as intervals (with 53-bit precision).186 Algebraic numbers which are known to be rational print as rationals; 187 otherwise they print as intervals (with 53-bit precision). 106 188 107 189 sage: AA(2)/3 108 190 2/3 109 sage: AA(5/7)191 sage: QQbar(5/7) 110 192 5/7 111 sage: two = sqrt(AA(4)); two 193 sage: QQbar(1/3 - 1/4*I) 194 -1/4*I + 1/3 195 sage: two = QQbar(4).nth_root(4)^2; two 112 196 [1.9999999999999997 .. 2.0000000000000005] 113 197 sage: two == 2; two 114 198 True … … 116 200 sage: phi 117 201 [1.6180339887498946 .. 1.6180339887498950] 118 202 203 We can find the real and imaginary parts of an algebraic number (exactly). 204 205 sage: r = QQbar.polynomial_root(x^5 - x - 1, CIF(RIF(0.1, 0.2), RIF(1.0, 1.1))); r 206 [0.18123244446987538 .. 0.18123244446987541] + [1.0839541013177105 .. 1.0839541013177108]*I 207 sage: r.real() 208 [0.18123244446987538 .. 0.18123244446987541] 209 sage: r.imag() 210 [1.0839541013177105 .. 1.0839541013177108] 211 sage: r.minpoly() 212 x^5 - x - 1 213 sage: r.real().minpoly() 214 x^10 + 3/16*x^6 + 11/32*x^5 - 1/64*x^2 + 1/128*x - 1/1024 215 sage: r.imag().minpoly() # this takes a long time (143s on my laptop) 216 x^20 - 5/8*x^16 - 95/256*x^12 - 625/1024*x^10 - 5/512*x^8 - 1875/8192*x^6 + 25/4096*x^4 - 625/32768*x^2 + 2869/1048576 217 218 We can find the absolute value and norm of an algebraic number exactly. 219 (Note that we define the norm as the product of a number and its 220 complex conjugate; this is the algebraic definition of norm, if we 221 view QQbar as AA[I].) 222 223 sage: r = QQbar((-8)^(1/3)); r 224 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 225 sage: r.abs() == 2 226 True 227 sage: r.norm() == 4 228 True 229 sage: (r+I).norm().minpoly() 230 x^2 - 10*x + 13 231 sage: r = AA.polynomial_root(x^2 - x - 1, RIF(-1, 0)); r 232 [-0.61803398874989491 .. -0.61803398874989479] 233 sage: r.abs().minpoly() 234 x^2 + x - 1 235 236 We can compute the multiplicative order of an algebraic number. 237 238 sage: QQbar(-1/2 + I*sqrt(3)/2).multiplicative_order() 239 3 240 sage: QQbar(-sqrt(3)/2 + I/2).multiplicative_order() 241 12 242 sage: QQbar.zeta(12345).multiplicative_order() 243 12345 244 245 Cyclotomic fields are very fast as long as we only multiply and divide: 246 247 sage: z3_3 = QQbar.zeta(3) * 3 248 sage: z4_4 = QQbar.zeta(4) * 4 249 sage: z5_5 = QQbar.zeta(5) * 5 250 sage: z6_6 = QQbar.zeta(6) * 6 251 sage: z20_20 = QQbar.zeta(20) * 20 252 sage: z3_3 * z4_4 * z5_5 * z6_6 * z20_20 253 7200 254 255 And they're still pretty fast even if you add and subtract, and trigger 256 exact computation: 257 258 sage: (z3_3 + z4_4 + z5_5 + z6_6 + z20_20)._exact_value() 259 4*zeta60^15 + 5*zeta60^12 + 9*zeta60^10 + 20*zeta60^3 - 3 where a^16 + a^14 - a^10 - a^8 - a^6 + a^2 + 1 = 0 and a in [0.99452189536827328 .. 0.99452189536827341] + [0.10452846326765345 .. 0.10452846326765352]*I 260 119 261 The paper _ARPREC: An Arbitrary Precision Computation Package_ discusses 120 262 this result. Evidently it is difficult to find, but we can easily 121 263 verify it. 122 264 123 sage: alpha = AA.polynomial_root(x^10 + x^9 - x^7 - x^6 - x^5 - x^4 - x^3 + x + 1, RIF(1, 1.2))265 sage: alpha = QQbar.polynomial_root(x^10 + x^9 - x^7 - x^6 - x^5 - x^4 - x^3 + x + 1, RIF(1, 1.2)) 124 266 sage: lhs = alpha^630 - 1 125 267 sage: rhs_num = (alpha^315 - 1) * (alpha^210 - 1) * (alpha^126 - 1)^2 * (alpha^90 - 1) * (alpha^3 - 1)^3 * (alpha^2 - 1)^5 * (alpha - 1)^3 126 268 sage: rhs_den = (alpha^35 - 1) * (alpha^15 - 1)^2 * (alpha^14 - 1)^2 * (alpha^5 - 1)^6 * alpha^68 … … 128 270 sage: lhs 129 271 [2.6420403358193507e44 .. 2.6420403358193520e44] 130 272 sage: rhs 131 [2.642040335819350 7e44 .. 2.6420403358193520e44]273 [2.6420403358193503e44 .. 2.6420403358193520e44] 132 274 sage: lhs - rhs 133 [- 63347712947806569000000000000. .. 65804250213263496000000000000.]275 [-79344219392947342000000000000. .. 81800756658404269000000000000.] 134 276 sage: lhs == rhs 135 277 True 136 278 sage: lhs - rhs 137 [0.00000000000000000 .. 0.00000000000000000]279 0 138 280 sage: lhs._exact_value() 139 281 -242494609856316402264822833062350847769474540*a^9 + 862295472068289472491654837785947906234680703*a^8 - 829559238431038252116584538075753012193290520*a^7 - 125882239615006638366472766103700441555126185*a^6 + 1399067970863104691667276008776398309383579345*a^5 - 1561176687069361567616835847286958553574223422*a^4 + 761706318888840943058230840550737823821027895*a^3 + 580740464974951394762758666210754821723780266*a^2 - 954587496403409756503464154898858512440951323*a + 546081123623099782018260884934770383777092602 where a^10 - 4*a^9 + 5*a^8 - a^7 - 6*a^6 + 9*a^5 - 6*a^4 - a^3 + 5*a^2 - 4*a + 1 = 0 and a in [0.44406334400909258 .. 0.44406334400909265] 140 282 """ … … 143 285 from sage.structure.sage_object import SageObject 144 286 from sage.structure.parent_gens import ParentWithGens 145 287 from sage.rings.real_mpfr import RR 146 from sage.rings.real_mpfi import RealIntervalField, RIF, RealIntervalFieldElement 147 from sage.rings.polynomial.polynomial_ring import PolynomialRing 288 from sage.rings.real_mpfi import RealIntervalField, RIF, RealIntervalFieldElement, is_RealIntervalFieldElement 289 from sage.rings.complex_field import ComplexField 290 from sage.rings.complex_interval_field import ComplexIntervalField, is_ComplexIntervalField 291 from sage.rings.complex_interval import ComplexIntervalFieldElement, is_ComplexIntervalFieldElement 292 from sage.rings.polynomial.all import PolynomialRing, is_Polynomial 148 293 from sage.rings.integer_ring import ZZ 149 294 from sage.rings.rational_field import QQ 150 from sage.rings.number_field.number_field import NumberField 295 from sage.rings.number_field.number_field import NumberField, NumberField_quadratic, QuadraticField, CyclotomicField 151 296 from sage.rings.number_field.number_field_element import is_NumberFieldElement 297 from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_quadratic 152 298 from sage.rings.arith import factor 153 299 from sage.libs.pari.gen import pari 154 300 from sage.structure.element import generic_power 301 import infinity 302 from sage.misc.functional import cyclotomic_polynomial 303 304 CC = ComplexField() 305 CIF = ComplexIntervalField() 155 306 156 307 # Singleton object implementation copied from integer_ring.py 157 308 _obj = None … … 162 313 _obj = sage.rings.ring.Field.__new__(cls) 163 314 return _obj 164 315 165 class AlgebraicRealField(_uniq_alg, sage.rings.ring.Field): 316 _obj_r = None 317 class _uniq_alg_r(object): 318 def __new__(cls): 319 global _obj_r 320 if _obj_r is None: 321 _obj_r = sage.rings.ring.Field.__new__(cls) 322 return _obj_r 323 324 is_SymbolicExpressionRing = None 325 326 def late_import(): 327 global is_SymbolicExpressionRing 328 if is_SymbolicExpressionRing is None: 329 import sage.calculus.calculus 330 is_SymbolicExpressionRing = sage.calculus.calculus.is_SymbolicExpressionRing 331 332 class AlgebraicField_common(sage.rings.ring.Field): 333 def default_interval_prec(self): 334 return 64 335 336 def is_finite(self): 337 return False 338 339 def characteristic(self): 340 return sage.rings.integer.Integer(0) 341 342 def order(self): 343 return infinity.infinity 344 345 def common_polynomial(self, poly): 346 """ 347 Given a polynomial with algebraic coefficients, returns a 348 wrapper that caches high-precision calculations and 349 factorizations. This wrapper can be passed to polynomial_root 350 in place of the polynomial. 351 352 Using common_polynomial makes no semantic difference, but will 353 improve efficiency if you are dealing with multiple roots 354 of a single polynomial. 355 356 EXAMPLES: 357 sage: x = polygen(ZZ) 358 sage: p = AA.common_polynomial(x^2 - x - 1) 359 sage: phi = AA.polynomial_root(p, RIF(1, 2)) 360 sage: tau = AA.polynomial_root(p, RIF(-1, 0)) 361 sage: phi + tau == 1 362 True 363 sage: phi * tau == -1 364 True 365 366 sage: x = polygen(SR) 367 sage: p = (x - sqrt(-5)) * (x - sqrt(3)); p 368 x^2 + ((1 - sqrt(3))*(1 - sqrt(5)*I) - sqrt(3)*sqrt(5)*I - 1)*x + sqrt(3)*sqrt(5)*I 369 sage: p = QQbar.common_polynomial(p) 370 sage: a = QQbar.polynomial_root(p, CIF(RIF(-0.1, 0.1), RIF(2, 3))); a 371 [-6.1814409042940318e-19 .. 6.0853195377215860e-19] + [2.2360679774997893 .. 2.2360679774997899]*I 372 sage: b = QQbar.polynomial_root(p, RIF(1, 2)); b 373 [1.7320508075688771 .. 1.7320508075688775] 374 375 These "common polynomials" can be shared between real and 376 complex roots: 377 sage: p = AA.common_polynomial(x^3 - x - 1) 378 sage: r1 = AA.polynomial_root(p, RIF(1.3, 1.4)); r1 379 [1.3247179572447458 .. 1.3247179572447461] 380 sage: r2 = QQbar.polynomial_root(p, CIF(RIF(-0.7, -0.6), RIF(0.5, 0.6))); r2 381 [-0.66235897862237303 .. -0.66235897862237291] + [0.56227951206230120 .. 0.56227951206230132]*I 382 """ 383 return AlgebraicPolynomialTracker(poly) 384 385 class AlgebraicRealField(_uniq_alg_r, AlgebraicField_common): 166 386 r""" 167 387 The field of algebraic reals. 168 169 388 """ 170 389 171 390 def __init__(self): 172 391 ParentWithGens.__init__(self, self, ('x',), normalize=False) 173 self._default_interval_field = RealIntervalField(64) 174 175 def _repr_(self): 176 return "Algebraic Field" 392 393 def __call__(self, x): 394 """ 395 Coerce x into the field of algebraic real numbers. 396 397 """ 398 399 if isinstance(x, AlgebraicReal): 400 return x 401 elif isinstance(x, AlgebraicNumber): 402 if x.imag().is_zero(): 403 return x.real() 404 else: 405 raise TypeError, "Cannot coerce algebraic number with non-zero imaginary part to algebraic real" 406 elif hasattr(x, '_algebraic_'): 407 return x._algebraic_(AA) 408 return AlgebraicReal(x) 409 410 def _repr_(self): 411 return "Algebraic Real Field" 177 412 178 413 # Is there a standard representation for this? 179 414 def _latex_(self): 180 415 return "\\mathbf{A}" 181 182 def __call__(self, x):183 """184 Coerce x into the field of algebraic numbers.185 186 """187 188 if isinstance(x, AlgebraicRealNumber):189 return x190 return AlgebraicRealNumber(x)191 416 192 417 def _coerce_impl(self, x): 193 418 if isinstance(x, (int, long, sage.rings.integer.Integer, 194 419 sage.rings.rational.Rational)): 195 420 return self(x) 421 elif hasattr(x, '_algebraic_'): 422 return x._algebraic_(AA) 196 423 raise TypeError, 'no implicit coercion of element to the algebraic numbers' 424 425 def has_coerce_map_from_impl(self, from_par): 426 if from_par == ZZ or from_par == QQ or from_par == int or from_par == long: 427 return True 428 late_import() 429 if is_SymbolicExpressionRing(from_par): 430 return True 431 return False 197 432 198 433 def _is_valid_homomorphism_(self, codomain, im_gens): 199 434 try: … … 201 436 except TypeError: 202 437 return False 203 438 204 def default_interval_field(self):205 return self._default_interval_field206 207 439 def gens(self): 208 440 return (self(1), ) 209 441 … … 216 448 def ngens(self): 217 449 return 1 218 450 219 def is_finite(self):220 return False221 222 451 def is_atomic_repr(self): 223 452 return True 224 225 def characteristic(self):226 return sage.rings.integer.Integer(0)227 228 def order(self):229 return infinity.infinity230 453 231 454 def zeta(self, n=2): 232 455 if n == 1: … … 235 458 return self(-1) 236 459 else: 237 460 raise ValueError, "no n-th root of unity in algebraic reals" 238 239 def common_polynomial(self, poly):240 """241 Given a polynomial with algebraic coefficients, returns a242 wrapper that caches high-precision calculations and243 factorizations. This wrapper can be passed to polynomial_root244 in place of the polynomial.245 246 Using common_polynomial makes no semantic difference, but will247 improve efficiency if you are dealing with multiple roots248 of a single polynomial.249 250 EXAMPLES:251 sage: x = polygen(AA)252 sage: p = AA.common_polynomial(x^2 - x - 1)253 sage: phi = AA.polynomial_root(p, RIF(0, 2))254 sage: tau = AA.polynomial_root(p, RIF(-2, 0))255 sage: phi + tau == 1256 True257 sage: phi * tau == -1258 True259 """260 return AlgebraicPolynomialTracker(poly)261 461 262 462 def polynomial_root(self, poly, interval, multiplicity=1): 263 463 """ … … 279 479 or wrong answers may result. 280 480 281 481 Note that if you are constructing multiple roots of a single 282 polynomial, it is better to use AA.common_polynomial 283 to get a shared polynomial. 482 polynomial, it is better to use AA.common_polynomial (or 483 QQbar.common_polynomial; the two are equivalent) to get a 484 shared polynomial. 284 485 285 486 EXAMPLES: 286 487 sage: x = polygen(AA) 287 sage: phi = AA.polynomial_root(x^2 - x - 1, RIF( 0, 2)); phi488 sage: phi = AA.polynomial_root(x^2 - x - 1, RIF(1, 2)); phi 288 489 [1.6180339887498946 .. 1.6180339887498950] 289 490 sage: p = (x-1)^7 * (x-2) 290 491 sage: r = AA.polynomial_root(p, RIF(9/10, 11/10), multiplicity=7) … … 296 497 sage: r; r == sqrt(AA(2)) 297 498 [1.4142135623730949 .. 1.4142135623730952] 298 499 True 299 """ 300 return AlgebraicRealNumber(AlgebraicRealNumberRoot(poly, interval, multiplicity)) 500 501 We allow complex polynomials, as long as the particular root 502 in question is real. 503 sage: K.<im> = QQ[I] 504 sage: x = polygen(K) 505 sage: p = (im + 1) * (x^3 - 2); p 506 (I + 1)*x^3 - 2*I - 2 507 sage: r = AA.polynomial_root(p, RIF(1, 2)); r^3 508 [1.9999999999999997 .. 2.0000000000000005] 509 """ 510 if not is_RealIntervalFieldElement(interval): 511 raise ValueError, "interval argument of .polynomial_root on algebraic real field must be real" 512 513 return AlgebraicReal(ANRoot(poly, interval, multiplicity)) 301 514 302 515 def is_AlgebraicRealField(F): 303 516 return isinstance(F, AlgebraicRealField) 304 517 305 518 AA = AlgebraicRealField() 306 519 307 def rif_seq(): 520 class AlgebraicField(_uniq_alg, AlgebraicField_common): 521 """ 522 The field of algebraic numbers. 523 """ 524 525 def __init__(self): 526 ParentWithGens.__init__(self, AA, ('I',), normalize=False) 527 528 def __call__(self, x): 529 """ 530 Coerce x into the field of algebraic numbers. 531 532 """ 533 534 if isinstance(x, AlgebraicNumber): 535 return x 536 elif isinstance(x, AlgebraicReal): 537 return AlgebraicNumber(x._descr) 538 elif hasattr(x, '_algebraic_'): 539 return x._algebraic_(QQbar) 540 return AlgebraicNumber(x) 541 542 def _repr_(self): 543 return "Algebraic Field" 544 545 def _coerce_impl(self, x): 546 if isinstance(x, (int, long, sage.rings.integer.Integer, 547 sage.rings.rational.Rational)): 548 return self(x) 549 elif hasattr(x, '_algebraic_'): 550 return x._algebraic_(QQbar) 551 elif isinstance(x, AlgebraicReal): 552 return AlgebraicNumber(x._descr) 553 raise TypeError, 'no implicit coercion of element to the algebraic numbers' 554 555 def has_coerce_map_from_impl(self, from_par): 556 if from_par == ZZ or from_par == QQ or from_par == int or from_par == long: 557 return True 558 if from_par == AA: 559 return True 560 late_import() 561 if is_SymbolicExpressionRing(from_par): 562 return True 563 return False 564 565 def gens(self): 566 return(QQbar_I, ) 567 568 def gen(self, n=0): 569 if n == 0: 570 return QQbar_I 571 else: 572 raise IndexError, "n must be 0" 573 574 def ngens(self): 575 return 1 576 577 def is_atomic_repr(self): 578 return False 579 580 def zeta(self, n=4): 581 """ 582 Returns a primitive n'th root of unity. (In fact, returns 583 exp(2*pi*I/n).) 584 585 EXAMPLES: 586 sage: QQbar.zeta(1) 587 1 588 sage: QQbar.zeta(2) 589 -1 590 sage: QQbar.zeta(3) 591 [-0.50000000000000012 .. -0.49999999999999994] + [0.86602540378443859 .. 0.86602540378443871]*I 592 sage: QQbar.zeta(4) 593 1*I 594 sage: QQbar.zeta() 595 1*I 596 sage: QQbar.zeta(5) 597 [0.30901699437494739 .. 0.30901699437494746] + [0.95105651629515353 .. 0.95105651629515365]*I 598 sage: QQbar.zeta(314159) 599 [0.99999999979999965 .. 0.99999999979999977] + [0.000020000016891958231 .. 0.000020000016891958236]*I 600 """ 601 return AlgebraicNumber(ANRootOfUnity(QQ_1/n, QQ_1)) 602 603 def polynomial_root(self, poly, interval, multiplicity=1): 604 """ 605 Given a polynomial with algebraic coefficients and an interval 606 enclosing exactly one root of the polynomial, constructs 607 an algebraic real representation of that root. 608 609 The polynomial need not be irreducible, or even squarefree; but 610 if the given root is a multiple root, its multiplicity must be 611 specified. (IMPORTANT NOTE: Currently, multiplicity-k roots 612 are handled by taking the (k-1)th derivative of the polynomial. 613 This means that the interval must enclose exactly one root 614 of this derivative.) 615 616 The conditions on the arguments (that the interval encloses exactly 617 one root, and that multiple roots match the given multiplicity) 618 are not checked; if they are not satisfied, an error may be 619 thrown (possibly later, when the algebraic number is used), 620 or wrong answers may result. 621 622 Note that if you are constructing multiple roots of a single 623 polynomial, it is better to use QQbar.common_polynomial 624 to get a shared polynomial. 625 626 EXAMPLES: 627 sage: x = polygen(QQbar) 628 sage: phi = QQbar.polynomial_root(x^2 - x - 1, RIF(0, 2)); phi 629 [1.6180339887498946 .. 1.6180339887498950] 630 sage: p = (x-1)^7 * (x-2) 631 sage: r = QQbar.polynomial_root(p, RIF(9/10, 11/10), multiplicity=7) 632 sage: r; r == 1 633 [1.0000000000000000 .. 1.0000000000000000] 634 True 635 sage: p = (x-phi)*(x-sqrt(QQbar(2))) 636 sage: r = QQbar.polynomial_root(p, RIF(1, 3/2)) 637 sage: r; r == sqrt(QQbar(2)) 638 [1.4142135623730949 .. 1.4142135623730952] 639 True 640 """ 641 return AlgebraicNumber(ANRoot(poly, interval, multiplicity)) 642 643 def is_AlgebraicField(F): 644 return isinstance(F, AlgebraicField) 645 646 QQbar = AlgebraicField() 647 648 def prec_seq(): 308 649 # XXX Should do some testing to see where the efficiency breaks are 309 # in MPFR. 650 # in MPFR. We could also test variants like "bits = bits + bits // 2" 651 # (I think this is what MPFR uses internally). 310 652 bits = 64 311 653 while True: 312 yield RealIntervalField(bits)654 yield bits 313 655 bits = bits * 2 314 # # XXX temporary debugging: 315 # if bits > 1024: 316 # break 656 657 _short_prec_seq = (64, 128, None) 658 def short_prec_seq(): return _short_prec_seq 659 660 def tail_prec_seq(): 661 bits = 256 662 while True: 663 yield bits 664 bits = bits * 2 665 666 def rational_exact_root(r, d): 667 """ 668 Checks whether the rational r is an exact d'th power. If so, returns 669 the d'th root of r; otherwise, returns None. 670 671 EXAMPLES: 672 sage: from sage.rings.algebraic_real import rational_exact_root 673 sage: rational_exact_root(16/81, 4) 674 2/3 675 sage: rational_exact_root(8/81, 3) is None 676 True 677 """ 678 num = r.numerator() 679 den = r.denominator() 680 681 (num_rt, num_exact) = num.nth_root(d, report_exact=True) 682 if not num_exact: return None 683 (den_rt, den_exact) = den.nth_root(d, report_exact=True) 684 if not den_exact: return None 685 return (num_rt / den_rt) 317 686 318 687 def clear_denominators(poly): 319 688 """ … … 327 696 328 697 (Inspired by Pari's primitive_pol_to_monic().) 329 698 699 We assume that coefficient denominators are "small"; the algorithm 700 factors the denominators, to give the smallest possible scale factor. 701 330 702 EXAMPLES: 331 703 sage: from sage.rings.algebraic_real import clear_denominators 332 704 … … 337 709 (2, x^2 + x + 1) 338 710 339 711 """ 712 713 # This algorithm factors the polynomial denominators. 714 # We should check the size of the denominators and switch to 715 # an alternate, less precise algorithm if we decide factoring 716 # would be too slow. 340 717 341 718 d = poly.denominator() 342 719 if d == 1: … … 401 778 402 779 assert(best is not None) 403 780 parent = poly.parent() 404 return parent(best_elt), parent(best_elt.Mod(pari_poly).modreverse().lift()), parent(best) 781 rev = parent(best_elt.Mod(pari_poly).modreverse().lift()) 782 return parent(best_elt), rev, parent(best) 405 783 406 784 def isolating_interval(intv_fn, pol): 407 785 """ 408 intv_fn is a function that takes a RealIntervalFieldand returns an409 interval containing some particular root of pol. (It must return410 better approximations as the RealIntervalFieldprecision increases.)786 intv_fn is a function that takes a precision and returns an 787 interval of that precision containing some particular root of pol. 788 (It must return better approximations as the precision increases.) 411 789 pol is an irreducible polynomial with rational coefficients. 412 790 413 791 Returns an interval containing at most one root of pol. … … 416 794 sage: from sage.rings.algebraic_real import isolating_interval 417 795 418 796 sage: _.<x> = QQ['x'] 419 sage: isolating_interval(lambda rif: sqrt(rif(2)), x^2 - 2)797 sage: isolating_interval(lambda prec: sqrt(RealIntervalField(prec)(2)), x^2 - 2) 420 798 [1.41421356237309504876 .. 1.41421356237309504888] 421 799 422 800 And an example that requires more precision: 423 801 sage: delta = 10^(-70) 424 802 sage: p = (x - 1) * (x - 1 - delta) * (x - 1 + delta) 425 sage: isolating_interval(lambda rif: rif(1 + delta), p)803 sage: isolating_interval(lambda prec: RealIntervalField(prec)(1 + delta), p) 426 804 [1.00000000000000000000000000000000000000000000000000000000000000000000009999999999999999999999999999999999999999999999999999999999999999999999999999999999998 .. 1.00000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000014] 427 """ 428 for rif in rif_seq(): 429 intv = intv_fn(rif) 805 806 The function also works with complex intervals and complex roots: 807 sage: p = x^2 - x + 13/36 808 sage: isolating_interval(lambda prec: ComplexIntervalField(prec)(1/2, 1/3), p) 809 [0.500000000000000000000 .. 0.500000000000000000000] + [0.333333333333333333315 .. 0.333333333333333333343]*I 810 """ 811 dpol = pol.derivative() 812 813 for prec in prec_seq(): 814 intv = intv_fn(prec) 815 ifld = intv.parent() 430 816 431 817 # We need to verify that pol has exactly one root in the 432 818 # interval intv. We know (because it is a precondition of … … 434 820 # interval, so we only need to verify that it has at most one 435 821 # root (that the interval is sufficiently narrow). 436 822 437 # Call the root we want alpha, and the bounding interval 438 # [bot .. top]. By Budan's theorem, if pol(x+bot) 439 # has at most one more sign change than pol(x+top), 440 # then pol has at most one root in this interval. 441 # This is true if all coefficients in pol(x+bot) 442 # except for the constant coefficient have the same 443 # sign as the corresponding coefficients in pol(x+top). 444 445 # We can check this by computing pol(x+new_intv). 446 # This gives an "interval polynomial" which represents 447 # a set of polynomials, including pol(x+bot) and 448 # pol(x+top). If all coefficients except the constant 449 # coefficient of this interval polynomial are bounded away from 450 # zero, then pol has at most one root in intv. 451 452 # This is a sufficient condition, but not a necessary one. 453 # It is not obvious that there always exists a bounding 454 # interval for alpha with this property. Fortunately, 455 # in the current case with pol irreducible, such 456 # a bounding interval does exist. 457 458 # Consider the polynomial pol(x+alpha), where 459 # pol has degree n. The coefficient of x^k in this 460 # polynomial has an exact representation as a polynomial 461 # in QQ[alpha] of degree (n-k). If this coefficient is 462 # equal to zero, then that means that alpha is a zero 463 # of this degree (n-k) polynomial. But if k>0, then this 464 # is impossible, since alpha is a root of an irreducible 465 # degree n polynomial. 466 467 # Thus, all coefficients of pol(x+alpha) are nonzero, 468 # except for the constant coefficient, which is zero. We 469 # are guaranteed that if we select a sufficiently tight bounding 470 # interval around alpha, then pol(x+[bot..top]) 471 # will have coefficients bounded away from zero, which proves 472 # that there is only one root within that bounding interval. 473 474 zero = rif(0) 475 rif_poly_ring = rif['x'] 476 477 ip = pol(rif_poly_ring.gen() + intv) 478 coeffs = ip.list() 479 assert(zero in coeffs[0]) 480 481 ok = True 482 483 for c in coeffs[1:]: 484 if zero in c: 485 ok = False 486 break 487 if ok: 823 # We do this by computing the derivative of the polynomial 824 # over the interval. If the derivative is bounded away from zero, 825 # then we know there can be at most one root. 826 827 if not dpol(intv).contains_zero(): 488 828 return intv 489 829 490 830 def find_zero_result(fn, l): 491 831 """ 492 l is a list of some sort. 493 fn is a function which maps an element of l and a RealIntervalField494 into an interval, such that for a sufficiently precise RealIntervalField,495 e xactly one element of l results in an interval containing 0.496 Returns thatone element of l.832 l is a list of some sort. fn is a function which maps an element 833 of l and a precision into an interval (either real or complex) of 834 that precision, such that for sufficient precision, exactly one 835 element of l results in an interval containing 0. Returns that 836 one element of l. 497 837 498 838 EXAMPLES: 499 839 sage: from sage.rings.algebraic_real import find_zero_result … … 502 842 sage: p1 = x - 1 503 843 sage: p2 = x - 1 - delta 504 844 sage: p3 = x - 1 + delta 505 sage: p2 == find_zero_result(lambda p, rif: p(rif(1 + delta)), [p1, p2, p3])506 True 507 """ 508 for rif in rif_seq():845 sage: p2 == find_zero_result(lambda p, prec: p(RealIntervalField(prec)(1 + delta)), [p1, p2, p3]) 846 True 847 """ 848 for prec in prec_seq(): 509 849 result = None 510 850 ambig = False 511 851 for v in l: 512 intv = fn(v, rif)513 if 0 in intv:852 intv = fn(v, prec) 853 if intv.contains_zero(): 514 854 if result is not None: 515 855 ambig = True 516 856 break … … 520 860 if result is None: 521 861 raise ValueError, 'find_zero_result could not find any zeroes' 522 862 return result 863 864 def conjugate_expand(v): 865 """ 866 If the interval v (which may be real or complex) includes some 867 purely real numbers, return v' containing v such that 868 v' == v'.conjugate(). Otherwise return v unchanged. (Note that if 869 v' == v'.conjugate(), and v' includes one non-real root of a real 870 polynomial, then v' also includes the conjugate of that root. 871 Also note that the diameter of the return value is at most twice 872 the diameter of the input.) 873 874 EXAMPLES: 875 sage: from sage.rings.algebraic_real import conjugate_expand 876 sage: conjugate_expand(CIF(RIF(0, 1), RIF(1, 2))) 877 [0.00000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 2.0000000000000000]*I 878 sage: conjugate_expand(CIF(RIF(0, 1), RIF(0, 1))) 879 [0.00000000000000000 .. 1.0000000000000000] + [-1.0000000000000000 .. 1.0000000000000000]*I 880 sage: conjugate_expand(CIF(RIF(0, 1), RIF(-2, 1))) 881 [0.00000000000000000 .. 1.0000000000000000] + [-2.0000000000000000 .. 2.0000000000000000]*I 882 sage: conjugate_expand(RIF(1, 2)) 883 [1.0000000000000000 .. 2.0000000000000000] 884 """ 885 if is_RealIntervalFieldElement(v): 886 return v 887 im = v.imag() 888 if not im.contains_zero(): 889 return v 890 re = v.real() 891 fld = ComplexIntervalField(v.prec()) 892 return fld(re, im.union(-im)) 893 894 def conjugate_shrink(v): 895 """ 896 If the interval v includes some purely real numbers, return 897 a real interval containing only those real numbers. Otherwise 898 return v unchanged. 899 900 If v includes exactly one root of a real polynomial, and v was 901 returned by conjugate_expand(), then conjugate_shrink(v) still 902 includes that root, and is a RealIntervalFieldElement iff the root 903 in question is real. 904 905 EXAMPLES: 906 sage: from sage.rings.