Ticket #8800: 8800_functor_pushout_doc_and_fixes.patch
File 8800_functor_pushout_doc_and_fixes.patch, 157.2 KB (added by , 12 years ago) |
---|
-
doc/en/reference/categories.rst
# HG changeset patch # User Simon King <simon.king@nuigalway.ie> # Date 1279718741 -3600 # Node ID 1a7c8feb901dd09ff8ee1d2fd34135c3e72665ad # Parent b4e473888eb985231e9429a532c937ce0040b073 #8800: Full doc test coverage of sage/categories/functor and sage/categories/pushout; fixing a multitude of bugs related with coercion. Putting it into the reference manual. diff -r b4e473888eb9 -r 1a7c8feb901d doc/en/reference/categories.rst
a b 13 13 sage/categories/homset 14 14 sage/categories/morphism 15 15 sage/categories/functor 16 sage/categories/pushout 16 17 17 18 Functorial constructions 18 19 ======================== -
doc/en/reference/coercion.rst
diff -r b4e473888eb9 -r 1a7c8feb901d doc/en/reference/coercion.rst
a b 586 586 sage: CC.construction() 587 587 (AlgebraicClosureFunctor, Real Field with 53 bits of precision) 588 588 sage: RR.construction() 589 (Completion Functor, Rational Field)589 (Completion[+Infinity], Rational Field) 590 590 sage: QQ.construction() 591 591 (FractionField, Integer Ring) 592 592 sage: ZZ.construction() # None 593 593 594 594 sage: Qp(5).construction() 595 (Completion Functor, Rational Field)596 sage: QQ.completion(5, 100 )595 (Completion[5], Rational Field) 596 sage: QQ.completion(5, 100, {}) 597 597 5-adic Field with capped relative precision 100 598 598 sage: c, R = RR.construction() 599 599 sage: a = CC.construction()[0] … … 608 608 (FractionField, Univariate Polynomial Ring in x over Complex Double Field), 609 609 (Poly[x], Complex Double Field), 610 610 (AlgebraicClosureFunctor, Real Double Field), 611 (Completion Functor, Rational Field),611 (Completion[+Infinity], Rational Field), 612 612 (FractionField, Integer Ring)] 613 613 614 614 Given Parents R and S, such that there is no coercion either from R to -
sage/categories/functor.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/categories/functor.pyx
a b 9 9 10 10 - Robert Bradshaw (2007-06-23): Pyrexify 11 11 12 - Simon King (2010-04-30): more examples, several bug fixes, re-implementation of the default call method, 12 - Simon King (2010-04-30): more examples, several bug fixes, 13 re-implementation of the default call method, 13 14 making functors applicable to morphisms (not only to objects) 14 15 15 16 """ … … 44 45 Instead, one should implement three methods, which are composed in the 45 46 default call method: 46 47 47 - ``_coerce_into_domain(self, x)``: Return an object of ``self``'s domain,48 corresponding to ``x``, or raise a ``TypeError``.48 - ``_coerce_into_domain(self, x)``: Return an object of ``self``'s 49 domain, corresponding to ``x``, or raise a ``TypeError``. 49 50 50 51 - Default: Raise ``TypeError`` if ``x`` is not in ``self``'s domain. 51 52 52 - ``_apply_functor(self, x)``: Apply ``self`` to an object ``x`` of ``self``'s domain. 53 - ``_apply_functor(self, x)``: Apply ``self`` to an object ``x`` of 54 ``self``'s domain. 53 55 54 56 - Default: Conversion into ``self``'s codomain. 55 57 56 - ``_apply_functor_to_morphism(self, f)``: Apply ``self`` to a morphism ``f`` in ``self``'s domain. 58 - ``_apply_functor_to_morphism(self, f)``: Apply ``self`` to a morphism 59 ``f`` in ``self``'s domain. 57 60 - Default: Return ``self(f.domain()).hom(f,self(f.codomain()))``. 58 61 59 62 EXAMPLES:: … … 76 79 sage: is_Functor(I) 77 80 True 78 81 79 Note that by default, an instance of the class Functor is coercion from the80 domain into the codomain. The above subclasses overloaded this behaviour. Here81 we illustrate the default::82 Note that by default, an instance of the class Functor is coercion 83 from the domain into the codomain. The above subclasses overloaded 84 this behaviour. Here we illustrate the default:: 82 85 83 86 sage: from sage.categories.functor import Functor 84 87 sage: F = Functor(Rings(),Fields()) … … 89 92 sage: F(GF(2)) 90 93 Finite Field of size 2 91 94 92 Functors are not only about the objects of a category, but also about their93 morphisms. We illustrate it, again, with the coercion functor from rings94 to fields.95 Functors are not only about the objects of a category, but also about 96 their morphisms. We illustrate it, again, with the coercion functor 97 from rings to fields. 95 98 96 99 :: 97 100 … … 108 111 From: Fraction Field of Univariate Polynomial Ring in x over Integer Ring 109 112 To: Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field 110 113 Defn: x |--> a + b 114 sage: F(f)(1/x) 115 1/(a + b) 116 117 We can also apply a polynomial ring construction functor to our homomorphism. The 118 result is a homomorphism that is defined on the base ring:: 119 120 sage: F = QQ['t'].construction()[0] 121 sage: F 122 Poly[t] 123 sage: F(f) 124 Ring morphism: 125 From: Univariate Polynomial Ring in t over Univariate Polynomial Ring in x over Integer Ring 126 To: Univariate Polynomial Ring in t over Multivariate Polynomial Ring in a, b over Rational Field 127 Defn: Induced from base ring by 128 Ring morphism: 129 From: Univariate Polynomial Ring in x over Integer Ring 130 To: Multivariate Polynomial Ring in a, b over Rational Field 131 Defn: x |--> a + b 132 sage: p = R1['t']('(-x^2 + x)*t^2 + (x^2 - x)*t - 4*x^2 - x + 1') 133 sage: F(f)(p) 134 (-a^2 - 2*a*b - b^2 + a + b)*t^2 + (a^2 + 2*a*b + b^2 - a - b)*t - 4*a^2 - 8*a*b - 4*b^2 - a - b + 1 111 135 112 136 """ 113 137 def __init__(self, domain, codomain): … … 133 157 134 158 def _apply_functor(self, x): 135 159 """ 136 Apply the functor to an object of ``self``'s domain 160 Apply the functor to an object of ``self``'s domain. 137 161 138 162 NOTE: 139 163 … … 153 177 154 178 def _apply_functor_to_morphism(self, f): 155 179 """ 156 Apply the functor to a morphism between two objects of ``self``'s domain 180 Apply the functor to a morphism between two objects of ``self``'s domain. 157 181 158 182 NOTE: 159 183 160 Each subclass of :class:`Functor` should overload this method. By default,161 this method coerces into the codomain, without checking whether the162 argument belongs to the domain.184 Each subclass of :class:`Functor` should overload this method. By 185 default, this method coerces into the codomain, without checking 186 whether the argument belongs to the domain. 163 187 164 188 TESTS:: 165 189 … … 169 193 sage: f = k.hom([-a-4]) 170 194 sage: R.<t> = k[] 171 195 sage: fR = R.hom(f,R) 172 sage: fF = F(fR); fF 196 sage: fF = F(fR) # indirect doctest 197 sage: fF 173 198 Ring endomorphism of Fraction Field of Univariate Polynomial Ring in t over Finite Field in a of size 5^2 174 199 Defn: Induced from base ring by 175 200 Ring endomorphism of Univariate Polynomial Ring in t over Finite Field in a of size 5^2 … … 187 212 188 213 def _coerce_into_domain(self, x): 189 214 """ 190 Interprete the argument as an object of self's domain 215 Interprete the argument as an object of self's domain. 191 216 192 217 NOTE: 193 218 194 Each subclass of :class:`Functor` should overload this method. It should return 195 an object of self's domain, and should raise a ``TypeError`` if this is impossible. 219 A subclass of :class:`Functor` may overload this method. It should 220 return an object of self's domain, and should raise a ``TypeError`` 221 if this is impossible. 196 222 197 By default, the argument will not be changed, but a ``TypeError`` will be raised if198 the argument does not belong to the domain.223 By default, the argument will not be changed, but a ``TypeError`` 224 will be raised if the argument does not belong to the domain. 199 225 200 226 TEST:: 201 227 … … 208 234 ... 209 235 TypeError: x (=Integer Ring) is not in Category of fields 210 236 211 212 237 """ 213 238 if not (x in self.__domain): 214 239 raise TypeError, "x (=%s) is not in %s"%(x, self.__domain) … … 229 254 """ 230 255 NOTE: 231 256 232 Implement _coerce_into_domain and _apply_functor when subclassing Functor. 257 Implement _coerce_into_domain, _apply_functor and 258 _apply_functor_to_morphism when subclassing Functor. 233 259 234 260 TESTS: 235 261 … … 397 423 """ 398 424 NOTE: 399 425 400 It is tested whether the second argument belongs to the class of forgetful functors 401 and has the same domain and codomain as self. If the second argument is a functor 402 of a different class but happens to be a forgetful functor, both arguments will 426 It is tested whether the second argument belongs to the class 427 of forgetful functors and has the same domain and codomain as 428 self. If the second argument is a functor of a different class 429 but happens to be a forgetful functor, both arguments will 403 430 still be considered as being *different*. 404 431 405 432 TEST:: 406 433 407 434 sage: F1 = ForgetfulFunctor(FiniteFields(),Fields()) 408 435 409 This is to test against a bug occuring in a previous version (see ticket 8800):: 436 This is to test against a bug occuring in a previous version 437 (see ticket 8800):: 410 438 411 439 sage: F1 == QQ #indirect doctest 412 440 False 413 441 414 We now compare with the fraction field functor, that has a different domain: 442 We now compare with the fraction field functor, that has a 443 different domain:: 415 444 416 445 sage: F2 = QQ.construction()[0] 417 446 sage: F1 == F2 #indirect doctest 418 447 False 419 448 420 449 """ 421 if not isinstance(other, self.__class__): 450 from sage.categories.pushout import IdentityConstructionFunctor 451 if not isinstance(other, (self.__class__,IdentityConstructionFunctor)): 422 452 return -1 423 453 if self.domain() == other.domain() and \ 424 454 self.codomain() == other.codomain(): … … 445 475 ... 446 476 TypeError: x (=Integer Ring) is not in Category of fields 447 477 478 TESTS:: 479 480 sage: R = IdentityFunctor(Rings()) 481 sage: P, _ = QQ['t'].construction() 482 sage: R == P 483 False 484 sage: P == R 485 False 486 sage: R == QQ 487 False 448 488 """ 449 489 def __init__(self, C): 450 490 """ … … 485 525 486 526 def _apply_functor(self, x): 487 527 """ 528 Apply the functor to an object of ``self``'s domain. 529 488 530 TESTS:: 489 531 490 532 sage: fields = Fields() … … 533 575 534 576 OUTPUT: 535 577 536 A functor that returns the corresponding object of ``D`` for any element of ``C``,537 by forgetting the extra structure.578 A functor that returns the corresponding object of ``D`` for 579 any element of ``C``, by forgetting the extra structure. 538 580 539 581 ASSUMPTION: 540 582 … … 567 609 if not domain.is_subcategory(codomain): 568 610 raise ValueError, "Forgetful functor not supported for domain %s"%domain 569 611 return ForgetfulFunctor_generic(domain, codomain) 570 571 612 -
sage/categories/pushout.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/categories/pushout.py
a b 1 from functor import Functor 1 """ 2 Coercion via Construction Functors. 3 """ 4 from functor import Functor, IdentityFunctor_generic 2 5 from basic import * 3 6 4 7 from sage.structure.parent import CoercionException … … 6 9 # TODO, think through the rankings, and override pushout where necessary. 7 10 8 11 class ConstructionFunctor(Functor): 9 12 """ 13 Base class for construction functors. 14 15 A construction functor is a functorial algebraic construction, 16 such as the construction of a matrix ring over a given ring 17 or the fraction field of a given ring. 18 19 In addition to the class :class:`~sage.categories.functor.Functor`, 20 construction functors provide rules for combining and merging 21 constructions. This is an important part of Sage's coercion model, 22 namely the pushout of two constructions: When a polynomial ``p`` in 23 a variable ``x`` with integer coefficients is added to a rational 24 number ``q``, then Sage finds that the parents ``ZZ['x']`` and 25 ``QQ`` are obtained from ``ZZ`` by applying a polynomial ring 26 construction respectively the fraction field construction. Each 27 construction functor has an attribute ``rank``, and the rank of 28 the polynomial ring construction is higher than the rank of the 29 fraction field construction. This means that the pushout of ``QQ`` 30 and ``ZZ['x']``, and thus a common parent in which ``p`` and ``q`` 31 can be added, is ``QQ['x']``, since the construction functor with 32 a lower rank is applied first. 33 34 :: 35 36 sage: F1, R = QQ.construction() 37 sage: F1 38 FractionField 39 sage: R 40 Integer Ring 41 sage: F2, R = (ZZ['x']).construction() 42 sage: F2 43 Poly[x] 44 sage: R 45 Integer Ring 46 sage: F3 = F2.pushout(F1) 47 sage: F3 48 Poly[x](FractionField(...)) 49 sage: F3(R) 50 Univariate Polynomial Ring in x over Rational Field 51 sage: from sage.categories.pushout import pushout 52 sage: P.<x> = ZZ[] 53 sage: pushout(QQ,P) 54 Univariate Polynomial Ring in x over Rational Field 55 sage: ((x+1) + 1/2).parent() 56 Univariate Polynomial Ring in x over Rational Field 57 58 When composing two construction functors, they are sometimes 59 merged into one, as is the case in the Quotient construction:: 60 61 sage: Q15, R = (ZZ.quo(15*ZZ)).construction() 62 sage: Q15 63 QuotientFunctor 64 sage: Q35, R = (ZZ.quo(35*ZZ)).construction() 65 sage: Q35 66 QuotientFunctor 67 sage: Q15.merge(Q35) 68 QuotientFunctor 69 sage: Q15.merge(Q35)(ZZ) 70 Ring of integers modulo 5 71 72 Functors can not only be applied to objects, but also to morphisms in the 73 respective categories. For example:: 74 75 sage: P.<x,y> = ZZ[] 76 sage: F = P.construction()[0]; F 77 MPoly[x,y] 78 sage: A.<a,b> = GF(5)[] 79 sage: f = A.hom([a+b,a-b],A) 80 sage: F(A) 81 Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 82 sage: F(f) 83 Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 84 Defn: Induced from base ring by 85 Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5 86 Defn: a |--> a + b 87 b |--> a - b 88 sage: F(f)(F(A)(x)*a) 89 (a + b)*x 90 91 """ 10 92 def __mul__(self, other): 93 """ 94 Compose construction functors to a composit construction functor, unless one of them is the identity. 95 96 NOTE: 97 98 The product is in functorial notation, i.e., when applying the product to an object 99 then the second factor is applied first. 100 101 TESTS:: 102 103 sage: from sage.categories.pushout import IdentityConstructionFunctor 104 sage: I = IdentityConstructionFunctor() 105 sage: F = QQ.construction()[0] 106 sage: P = ZZ['t'].construction()[0] 107 sage: F*P 108 FractionField(Poly[t](...)) 109 sage: P*F 110 Poly[t](FractionField(...)) 111 sage: (F*P)(ZZ) 112 Fraction Field of Univariate Polynomial Ring in t over Integer Ring 113 sage: I*P is P 114 True 115 sage: F*I is F 116 True 117 118 """ 11 119 if not isinstance(self, ConstructionFunctor) and not isinstance(other, ConstructionFunctor): 12 120 raise CoercionException, "Non-constructive product" 121 if isinstance(other,IdentityConstructionFunctor): 122 return self 123 if isinstance(self,IdentityConstructionFunctor): 124 return other 13 125 return CompositeConstructionFunctor(other, self) 14 126 15 127 def pushout(self, other): 128 """ 129 Composition of two construction functors, ordered by their ranks. 130 131 NOTE: 132 133 - This method seems not to be used in the coercion model. 134 135 - By default, the functor with smaller rank is applied first. 136 137 TESTS:: 138 139 sage: F = QQ.construction()[0] 140 sage: P = ZZ['t'].construction()[0] 141 sage: F.pushout(P) 142 Poly[t](FractionField(...)) 143 sage: P.pushout(F) 144 Poly[t](FractionField(...)) 145 146 """ 16 147 if self.rank > other.rank: 17 148 return self * other 18 149 else: … … 20 151 21 152 def __cmp__(self, other): 22 153 """ 23 Equality here means that they are mathematically equivalent, though they may have specific implementation data. 24 See the \code{merge} function. 154 Equality here means that they are mathematically equivalent, though they may have 155 specific implementation data. This method will usually be overloaded in subclasses. 156 by default, only the types of the functors are compared. Also see the \code{merge} 157 function. 158 159 TESTS:: 160 161 sage: from sage.categories.pushout import IdentityConstructionFunctor 162 sage: I = IdentityConstructionFunctor() 163 sage: F = QQ.construction()[0] 164 sage: P = ZZ['t'].construction()[0] 165 sage: I == F # indirect doctest 166 False 167 sage: I == I # indirect doctest 168 True 169 25 170 """ 26 171 return cmp(type(self), type(other)) 27 172 28 173 def __str__(self): 174 """ 175 NOTE: 176 177 By default, it returns the name of the construction functor's class. 178 Usually, this method will be overloaded. 179 180 TEST:: 181 182 sage: F = QQ.construction()[0] 183 sage: F # indirect doctest 184 FractionField 185 sage: Q = ZZ.quo(2).construction()[0] 186 sage: Q # indirect doctest 187 QuotientFunctor 188 189 """ 29 190 s = str(type(self)) 30 191 import re 31 192 return re.sub("<.*'.*\.([^.]*)'>", "\\1", s) 32 193 33 194 def __repr__(self): 195 """ 196 NOTE: 197 198 By default, it returns the name of the construction functor's class. 199 Usually, this method will be overloaded. 200 201 TEST:: 202 203 sage: F = QQ.construction()[0] 204 sage: F # indirect doctest 205 FractionField 206 sage: Q = ZZ.quo(2).construction()[0] 207 sage: Q # indirect doctest 208 QuotientFunctor 209 210 """ 34 211 return str(self) 35 212 36 213 def merge(self, other): 214 """ 215 Merge ``self`` with another construction functor, or return None. 216 217 NOTE: 218 219 The default is to merge only if the two functors coincide. But this 220 may be overloaded for subclasses, such as the quotient functor. 221 222 EXAMPLES:: 223 224 sage: F = QQ.construction()[0] 225 sage: P = ZZ['t'].construction()[0] 226 sage: F.merge(F) 227 FractionField 228 sage: F.merge(P) 229 sage: P.merge(F) 230 sage: P.merge(P) 231 Poly[t] 232 233 """ 37 234 if self == other: 38 235 return self 39 236 else: 40 237 return None 41 238 42 239 def commutes(self, other): 240 """ 241 Determine whether ``self`` commutes with another construction functor. 242 243 NOTE: 244 245 By default, ``False`` is returned in all cases (even if the two 246 functors are the same, since in this case :meth:`merge` will apply 247 anyway). So far there is no construction functor that overloads 248 this method. Anyway, this method only becomes relevant if two 249 construction functors have the same rank. 250 251 EXAMPLES:: 252 253 sage: F = QQ.construction()[0] 254 sage: P = ZZ['t'].construction()[0] 255 sage: F.commutes(P) 256 False 257 sage: P.commutes(F) 258 False 259 sage: F.commutes(F) 260 False 261 262 """ 43 263 return False 44 264 45 265 def expand(self): 266 """ 267 Decompose ``self`` into a list of construction functors. 268 269 NOTE: 270 271 The default is to return the list only containing ``self``. 272 273 EXAMPLE:: 274 275 sage: F = QQ.construction()[0] 276 sage: F.expand() 277 [FractionField] 278 sage: Q = ZZ.quo(2).construction()[0] 279 sage: Q.expand() 280 [QuotientFunctor] 281 sage: P = ZZ['t'].construction()[0] 282 sage: FP = F*P 283 sage: FP.expand() 284 [FractionField, Poly[t]] 285 286 """ 46 287 return [self] 47 288 48 289 49 290 class CompositeConstructionFunctor(ConstructionFunctor): 50 291 """ 51 A Construction Functor composed by other Construction Functors 292 A Construction Functor composed by other Construction Functors. 52 293 53 294 INPUT: 54 295 55 ``F1, F2,...``: A list of Construction Functors. The result is the296 ``F1, F2,...``: A list of Construction Functors. The result is the 56 297 composition ``F1`` followed by ``F2`` followed by ... 57 298 58 299 EXAMPLES:: … … 61 302 sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) 62 303 sage: F 63 304 Poly[y](FractionField(Poly[x](FractionField(...)))) 305 sage: F == loads(dumps(F)) 306 True 64 307 sage: F == CompositeConstructionFunctor(*F.all) 65 308 True 66 309 sage: F(GF(2)['t']) … … 92 335 93 336 def _apply_functor_to_morphism(self, f): 94 337 """ 338 Apply the functor to an object of ``self``'s domain. 339 95 340 TESTS:: 96 341 97 342 sage: from sage.categories.pushout import CompositeConstructionFunctor 98 343 sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) 99 344 sage: R.<a,b> = QQ[] 100 345 sage: f = R.hom([a+b, a-b]) 101 sage: F(f) # indirect doctest346 sage: F(f) # indirect doctest 102 347 Ring endomorphism of Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field 103 348 Defn: Induced from base ring by 104 349 Ring endomorphism of Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field … … 116 361 117 362 def _apply_functor(self, R): 118 363 """ 364 Apply the functor to an object of ``self``'s domain. 365 119 366 TESTS:: 120 367 121 368 sage: from sage.categories.pushout import CompositeConstructionFunctor 122 369 sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) 123 370 sage: R.<a,b> = QQ[] 124 sage: F(R) # indirect doctest371 sage: F(R) # indirect doctest 125 372 Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field 126 373 127 374 """ … … 146 393 147 394 def __mul__(self, other): 148 395 """ 149 Convention: ``(F1*F2)(X) == F1(F2(X))``. 396 Compose construction functors to a composit construction functor, unless one of them is the identity. 397 398 NOTE: 399 400 The product is in functorial notation, i.e., when applying the product to an object 401 then the second factor is applied first. 150 402 151 403 EXAMPLES:: 152 404 … … 159 411 """ 160 412 if isinstance(self, CompositeConstructionFunctor): 161 413 all = [other] + self.all 414 elif isinstance(other,IdentityConstructionFunctor): 415 return self 162 416 else: 163 417 all = other.all + [self] 164 418 return CompositeConstructionFunctor(*all) … … 201 455 202 456 203 457 class IdentityConstructionFunctor(ConstructionFunctor): 204 458 """ 459 A construction functor that is the identity functor. 460 461 TESTS:: 462 463 sage: from sage.categories.pushout import IdentityConstructionFunctor 464 sage: I = IdentityConstructionFunctor() 465 sage: I(RR) is RR 466 True 467 sage: I == loads(dumps(I)) 468 True 469 470 """ 205 471 rank = -100 206 472 207 473 def __init__(self): 208 Functor.__init__(self, Sets(), Sets()) 209 def _apply_functor(self, R): 210 return R 474 """ 475 TESTS:: 476 477 sage: from sage.categories.pushout import IdentityConstructionFunctor 478 sage: I = IdentityConstructionFunctor() 479 sage: IdentityFunctor(Sets()) == I 480 True 481 sage: I(RR) is RR 482 True 483 484 """ 485 ConstructionFunctor.__init__(self, Sets(), Sets()) 486 487 def _apply_functor(self, x): 488 """ 489 Return the argument unaltered. 490 491 TESTS:: 492 493 sage: from sage.categories.pushout import IdentityConstructionFunctor 494 sage: I = IdentityConstructionFunctor() 495 sage: I(RR) is RR # indirect doctest 496 True 497 """ 498 return x 499 500 def _apply_functor_to_morphism(self, f): 501 """ 502 Return the argument unaltered. 503 504 TESTS:: 505 506 sage: from sage.categories.pushout import IdentityConstructionFunctor 507 sage: I = IdentityConstructionFunctor() 508 sage: f = ZZ['t'].hom(['x'],QQ['x']) 509 sage: I(f) is f # indirect doctest 510 True 511 """ 512 return f 513 514 def __cmp__(self, other): 515 """ 516 TESTS:: 517 518 sage: from sage.categories.pushout import IdentityConstructionFunctor 519 sage: I = IdentityConstructionFunctor() 520 sage: I == IdentityFunctor(Sets()) # indirect doctest 521 True 522 sage: I == QQ.construction()[0] 523 False 524 525 """ 526 c = cmp(type(self),type(other)) 527 if c: 528 from sage.categories.functor import IdentityFunctor_generic 529 if isinstance(other,IdentityFunctor_generic): 530 return 0 531 return c 532 211 533 def __mul__(self, other): 534 """ 535 Compose construction functors to a composit construction functor, unless one of them is the identity. 536 537 NOTE: 538 539 The product is in functorial notation, i.e., when applying the product to an object 540 then the second factor is applied first. 541 542 TESTS:: 543 544 sage: from sage.categories.pushout import IdentityConstructionFunctor 545 sage: I = IdentityConstructionFunctor() 546 sage: F = QQ.construction()[0] 547 sage: P = ZZ['t'].construction()[0] 548 sage: I*F is F # indirect doctest 549 True 550 sage: F*I is F 551 True 552 sage: I*P is P 553 True 554 sage: P*I is P 555 True 556 557 """ 212 558 if isinstance(self, IdentityConstructionFunctor): 213 559 return other 214 560 else: 215 561 return self 216 562 217 563 218 219 220 564 class PolynomialFunctor(ConstructionFunctor): 221 565 """ 566 Construction functor for univariate polynomial rings. 567 568 EXAMPLE: 569 570 sage: P = ZZ['t'].construction()[0] 571 sage: P(GF(3)) 572 Univariate Polynomial Ring in t over Finite Field of size 3 573 sage: P == loads(dumps(P)) 574 True 575 sage: R.<x,y> = GF(5)[] 576 sage: f = R.hom([x+2*y,3*x-y],R) 577 sage: P(f)((x+y)*P(R).0) 578 (-x + y)*t 579 580 """ 222 581 rank = 9 223 582 224 583 def __init__(self, var, multi_variate=False): 584 """ 585 TESTS:: 586 587 sage: from sage.categories.pushout import PolynomialFunctor 588 sage: P = PolynomialFunctor('x') 589 sage: P(GF(3)) 590 Univariate Polynomial Ring in x over Finite Field of size 3 591 592 There is an optional parameter ``multi_variate``, but 593 apparently it is not used:: 594 595 sage: Q = PolynomialFunctor('x',multi_variate=True) 596 sage: Q(ZZ) 597 Univariate Polynomial Ring in x over Integer Ring 598 sage: Q == P 599 True 600 601 """ 225 602 from rings import Rings 226 603 Functor.__init__(self, Rings(), Rings()) 227 604 self.var = var 228 605 self.multi_variate = multi_variate 229 606 230 607 def _apply_functor(self, R): 608 """ 609 Apply the functor to an object of ``self``'s domain. 610 611 TEST:: 612 613 sage: P = ZZ['x'].construction()[0] 614 sage: P(GF(3)) # indirect doctest 615 Univariate Polynomial Ring in x over Finite Field of size 3 616 617 """ 231 618 from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing 232 619 return PolynomialRing(R, self.var) 233 620 234 621 def __cmp__(self, other): 622 """ 623 TESTS:: 624 625 sage: from sage.categories.pushout import MultiPolynomialFunctor 626 sage: Q = MultiPolynomialFunctor(('x',),'lex') 627 sage: P = ZZ['x'].construction()[0] 628 sage: P 629 Poly[x] 630 sage: Q 631 MPoly[x] 632 sage: P == Q 633 True 634 sage: P == loads(dumps(P)) 635 True 636 sage: P == QQ.construction()[0] 637 False 638 639 """ 235 640 c = cmp(type(self), type(other)) 236 641 if c == 0: 237 642 c = cmp(self.var, other.var) … … 240 645 return c 241 646 242 647 def merge(self, other): 648 """ 649 Merge ``self`` with another construction functor, or return None. 650 651 NOTE: 652 653 Internally, the merging is delegated to the merging of 654 multipolynomial construction functors. But in effect, 655 this does the same as the default implementation, that 656 returns ``None`` unless the to-be-merged functors coincide. 657 658 EXAMPLE:: 659 660 sage: P = ZZ['x'].construction()[0] 661 sage: Q = ZZ['y','x'].construction()[0] 662 sage: P.merge(Q) 663 sage: P.merge(P) is P 664 True 665 666 """ 243 667 if isinstance(other, MultiPolynomialFunctor): 244 668 return other.merge(self) 245 669 elif self == other: … … 248 672 return None 249 673 250 674 def __str__(self): 675 """ 676 TEST:: 677 678 sage: P = ZZ['x'].construction()[0] 679 sage: P # indirect doctest 680 Poly[x] 681 682 """ 251 683 return "Poly[%s]" % self.var 252 684 253 685 class MultiPolynomialFunctor(ConstructionFunctor): 254 686 """ 255 687 A constructor for multivariate polynomial rings. 688 689 EXAMPLES:: 690 691 sage: P.<x,y> = ZZ[] 692 sage: F = P.construction()[0]; F 693 MPoly[x,y] 694 sage: A.<a,b> = GF(5)[] 695 sage: F(A) 696 Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 697 sage: f = A.hom([a+b,a-b],A) 698 sage: F(f) 699 Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 700 Defn: Induced from base ring by 701 Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5 702 Defn: a |--> a + b 703 b |--> a - b 704 sage: F(f)(F(A)(x)*a) 705 (a + b)*x 706 256 707 """ 257 708 258 709 rank = 9 259 710 260 711 def __init__(self, vars, term_order): 261 712 """ 262 EXAMPLES: 713 EXAMPLES:: 714 263 715 sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) 264 716 sage: F 265 717 MPoly[x,y] … … 274 726 275 727 def _apply_functor(self, R): 276 728 """ 277 EXAMPLES: 729 Apply the functor to an object of ``self``'s domain. 730 731 EXAMPLES:: 732 278 733 sage: R.<x,y,z> = QQ[] 279 734 sage: F = R.construction()[0]; F 280 735 MPoly[x,y,z] 281 736 sage: type(F) 282 737 <class 'sage.categories.pushout.MultiPolynomialFunctor'> 283 sage: F(ZZ) 738 sage: F(ZZ) # indirect doctest 284 739 Multivariate Polynomial Ring in x, y, z over Integer Ring 285 sage: F(RR) 740 sage: F(RR) # indirect doctest 286 741 Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision 287 742 """ 288 743 from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing … … 290 745 291 746 def __cmp__(self, other): 292 747 """ 293 EXAMPLES: 748 EXAMPLES:: 749 294 750 sage: F = ZZ['x,y,z'].construction()[0] 295 751 sage: G = QQ['x,y,z'].construction()[0] 296 752 sage: F == G 297 753 True 754 sage: G == loads(dumps(G)) 755 True 298 756 sage: G = ZZ['x,y'].construction()[0] 299 757 sage: F == G 300 758 False … … 311 769 If two MPoly functors are given in a row, form a single MPoly functor 312 770 with all of the variables. 313 771 314 EXAMPLES: 772 EXAMPLES:: 773 315 774 sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) 316 775 sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None) 317 776 sage: G*F 318 777 MPoly[x,y,t] 319 778 """ 779 if isinstance(other,IdentityConstructionFunctor): 780 return self 320 781 if isinstance(other, MultiPolynomialFunctor): 321 782 if self.term_order != other.term_order: 322 783 raise CoercionException, "Incompatible term orders (%s,%s)." % (self.term_order, other.term_order) … … 331 792 332 793 def merge(self, other): 333 794 """ 334 EXAMPLES: 795 Merge ``self`` with another construction functor, or return None. 796 797 EXAMPLES:: 798 335 799 sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) 336 800 sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None) 337 801 sage: F.merge(G) is None … … 346 810 347 811 def expand(self): 348 812 """ 349 EXAMPLES: 813 Decompose ``self`` into a list of construction functors. 814 815 EXAMPLES:: 816 350 817 sage: F = QQ['x,y,z,t'].construction()[0]; F 351 818 MPoly[x,y,z,t] 352 819 sage: F.expand() 353 820 [MPoly[t], MPoly[z], MPoly[y], MPoly[x]] 354 821 355 Now an actual use case: 822 Now an actual use case:: 823 356 824 sage: R.<x,y,z> = ZZ[] 357 825 sage: S.<z,t> = QQ[] 358 826 sage: x+t … … 376 844 377 845 def __str__(self): 378 846 """ 379 EXAMPLES: 847 TEST:: 848 380 849 sage: QQ['x,y,z,t'].construction()[0] 381 850 MPoly[x,y,z,t] 382 851 """ … … 386 855 387 856 class InfinitePolynomialFunctor(ConstructionFunctor): 388 857 """ 389 A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`) 858 A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`). 390 859 391 860 AUTHOR: 392 -- Simon King 861 862 -- Simon King 393 863 394 864 This construction functor is used to provide uniqueness of infinite polynomial rings as parent structures. 395 865 As usual, the construction functor allows for constructing pushouts. … … 443 913 CoercionException: Overlapping variables (('a', 'b'),['a_3', 'a_1']) are incompatible 444 914 445 915 Since the construction functors are actually used to construct infinite polynomial rings, the following 446 result is no surprise: 916 result is no surprise:: 447 917 448 918 sage: C.<a,b> = InfinitePolynomialRing(B); C 449 919 Infinite polynomial ring in a, b over Multivariate Polynomial Ring in x, y over Rational Field … … 455 925 456 926 `X` and `Y` have an overlapping generators `x_\\ast, y_\\ast`. Since the default lexicographic order is 457 927 used in both rings, it gives rise to isomorphic sub-monoids in both `X` and `Y`. They are merged in the 458 pushout, which also yields a common parent for doing arithmetic .928 pushout, which also yields a common parent for doing arithmetic:: 459 929 460 930 sage: P = sage.categories.pushout.pushout(Y,X); P 461 931 Infinite polynomial ring in w, x, y, z over Rational Field … … 476 946 """ 477 947 TEST:: 478 948 479 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc 949 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest 480 950 InfPoly{[a,b,x], "degrevlex", "sparse"} 481 951 sage: F == loads(dumps(F)) 482 952 True … … 490 960 self._imple = implementation 491 961 492 962 def _apply_functor_to_morphism(self, f): 493 raise NotImplementedError 963 """ 964 Morphisms for inifinite polynomial rings are not implemented yet. 965 966 TEST:: 967 968 sage: P.<x,y> = QQ[] 969 sage: R.<alpha> = InfinitePolynomialRing(P) 970 sage: f = P.hom([x+y,x-y],P) 971 sage: R.construction()[0](f) # indirect doctest 972 Traceback (most recent call last): 973 ... 974 NotImplementedError: Morphisms for inifinite polynomial rings are not implemented yet. 975 976 """ 977 raise NotImplementedError, "Morphisms for inifinite polynomial rings are not implemented yet." 494 978 495 979 def _apply_functor(self, R): 496 980 """ 981 Apply the functor to an object of ``self``'s domain. 982 497 983 TEST:: 498 984 499 985 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F 500 986 InfPoly{[a,b,x], "degrevlex", "sparse"} 501 sage: F(QQ['t']) # indirect doc 987 sage: F(QQ['t']) # indirect doctest 502 988 Infinite polynomial ring in a, b, x over Univariate Polynomial Ring in t over Rational Field 503 989 504 990 """ … … 509 995 """ 510 996 TEST:: 511 997 512 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc 998 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest 513 999 InfPoly{[a,b,x], "degrevlex", "sparse"} 514 1000 515 1001 """ … … 519 1005 """ 520 1006 TEST:: 521 1007 522 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc 1008 sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest 523 1009 InfPoly{[a,b,x], "degrevlex", "sparse"} 524 sage: F == loads(dumps(F)) # indirect doc 1010 sage: F == loads(dumps(F)) # indirect doctest 525 1011 True 526 1012 sage: F == sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'deglex','sparse') 527 1013 False … … 534 1020 535 1021 def __mul__(self, other): 536 1022 """ 1023 Compose construction functors to a composit construction functor, unless one of them is the identity. 1024 1025 NOTE: 1026 1027 The product is in functorial notation, i.e., when applying the product to an object 1028 then the second factor is applied first. 1029 537 1030 TESTS:: 538 1031 539 1032 sage: F1 = QQ['a','x_2','x_1','y_3','y_2'].construction()[0]; F1 … … 551 1044 InfPoly{[x,y], "degrevlex", "dense"}(FractionField(...)) 552 1045 553 1046 """ 1047 if isinstance(other,IdentityConstructionFunctor): 1048 return self 554 1049 if isinstance(other, self.__class__): # 555 1050 INT = set(self._gens).intersection(other._gens) 556 1051 if INT: … … 684 1179 if self._imple != other._imple: 685 1180 return InfinitePolynomialFunctor(self._gens, self._order, 'dense') 686 1181 return self 687 ## if isinstance(other, PolynomialFunctor) or isinstance(other, MultiPolynomialFunctor):688 ## # For merging, we don't care about the orders689 ## ## if isinstance(other, MultiPolynomialFunctor) and self._order!=other.term_order.name():690 ## ## return None691 ## # We only merge if other's variables can all be interpreted in self.692 ## if isinstance(other, PolynomialFunctor):693 ## if other.var.count('_')!=1:694 ## return None695 ## g,n = other.var.split('_')696 ## if not ((g in self._gens) and n.isdigit()):697 ## return None698 ## # other merges into self!699 ## return self700 ## # Now, other is MultiPolynomial701 ## for v in other.vars:702 ## if v.count('_')!=1:703 ## return None704 ## g,n = v.split('_')705 ## if not ((g in self._gens) and n.isdigit()):706 ## return None707 ## # other merges into self!708 ## return self709 1182 return None 710 1183 711 1184 def expand(self): 712 1185 """ 713 Decompose the functor `F` into sub-functors, whose product returns `F` 1186 Decompose the functor `F` into sub-functors, whose product returns `F`. 714 1187 715 1188 EXAMPLES:: 716 1189 … … 735 1208 736 1209 737 1210 class MatrixFunctor(ConstructionFunctor): 738 1211 """ 1212 A construction functor for matrices over rings. 1213 1214 EXAMPLES:: 1215 1216 sage: MS = MatrixSpace(ZZ,2, 3) 1217 sage: F = MS.construction()[0]; F 1218 MatrixFunctor 1219 sage: MS = MatrixSpace(ZZ,2) 1220 sage: F = MS.construction()[0]; F 1221 MatrixFunctor 1222 sage: P.<x,y> = QQ[] 1223 sage: R = F(P); R 1224 Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field 1225 sage: f = P.hom([x+y,x-y],P); F(f) 1226 Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field 1227 Defn: Induced from base ring by 1228 Ring endomorphism of Multivariate Polynomial Ring in x, y over Rational Field 1229 Defn: x |--> x + y 1230 y |--> x - y 1231 sage: M = R([x,y,x*y,x+y]) 1232 sage: F(f)(M) 1233 [ x + y x - y] 1234 [x^2 - y^2 2*x] 1235 1236 """ 739 1237 rank = 10 740 1238 741 1239 def __init__(self, nrows, ncols, is_sparse=False): 742 # if nrows == ncols: 743 # Functor.__init__(self, Rings(), RingModules()) # takes a base ring 744 # else: 745 # Functor.__init__(self, Rings(), MatrixAlgebras()) # takes a base ring 746 # We must distinguish two cases: 747 # If nrows=ncols, the result is a ring. Otherwise, 748 # it is just a commutative additive group. 749 if nrows==ncols: 750 Functor.__init__(self, Rings(), Rings()) 1240 """ 1241 TEST:: 1242 1243 sage: from sage.categories.pushout import MatrixFunctor 1244 sage: F = MatrixFunctor(2,3) 1245 sage: F == MatrixSpace(ZZ,2,3).construction()[0] 1246 True 1247 sage: F.codomain() 1248 Category of commutative additive groups 1249 sage: R = MatrixSpace(ZZ,2,2).construction()[0] 1250 sage: R.codomain() 1251 Category of rings 1252 sage: F(ZZ) 1253 Full MatrixSpace of 2 by 3 dense matrices over Integer Ring 1254 sage: F(ZZ) in F.codomain() 1255 True 1256 sage: R(GF(2)) 1257 Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 1258 sage: R(GF(2)) in R.codomain() 1259 True 1260 """ 1261 if nrows == ncols: 1262 Functor.__init__(self, Rings(), Rings()) # Algebras() takes a base ring 751 1263 else: 752 Functor.__init__(self,Rings(), CommutativeAdditiveGroups()) 1264 # Functor.__init__(self, Rings(), MatrixAlgebras()) # takes a base ring 1265 Functor.__init__(self, Rings(), CommutativeAdditiveGroups()) # not a nice solution, but the best we can do. 753 1266 self.nrows = nrows 754 1267 self.ncols = ncols 755 1268 self.is_sparse = is_sparse 1269 756 1270 def _apply_functor(self, R): 1271 """ 1272 Apply the functor to an object of ``self``'s domain. 1273 1274 TEST: 1275 1276 The following is a test against a bug discussed at ticket #8800 1277 1278 sage: F = MatrixSpace(ZZ,2,3).construction()[0] 1279 sage: F(RR) # indirect doctest 1280 Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision 1281 sage: F(RR) in F.codomain() 1282 True 1283 1284 """ 757 1285 from sage.matrix.matrix_space import MatrixSpace 758 1286 return MatrixSpace(R, self.nrows, self.ncols, sparse=self.is_sparse) 1287 759 1288 def __cmp__(self, other): 1289 """ 1290 TEST:: 1291 1292 sage: F = MatrixSpace(ZZ,2,3).construction()[0] 1293 sage: F == loads(dumps(F)) 1294 True 1295 sage: F == MatrixSpace(ZZ,2,2).construction()[0] 1296 False 1297 1298 """ 760 1299 c = cmp(type(self), type(other)) 761 1300 if c == 0: 762 1301 c = cmp((self.nrows, self.ncols), (other.nrows, other.ncols)) 763 1302 return c 1303 764 1304 def merge(self, other): 1305 """ 1306 Merging is only happening if both functors are matrix functors of the same dimension. 1307 The result is sparse if and only if both given functors are sparse. 1308 1309 EXAMPLE:: 1310 1311 sage: F1 = MatrixSpace(ZZ,2,2).construction()[0] 1312 sage: F2 = MatrixSpace(ZZ,2,3).construction()[0] 1313 sage: F3 = MatrixSpace(ZZ,2,2,sparse=True).construction()[0] 1314 sage: F1.merge(F2) 1315 sage: F1.merge(F3) 1316 MatrixFunctor 1317 sage: F13 = F1.merge(F3) 1318 sage: F13.is_sparse 1319 False 1320 sage: F1.is_sparse 1321 False 1322 sage: F3.is_sparse 1323 True 1324 sage: F3.merge(F3).is_sparse 1325 True 1326 1327 """ 765 1328 if self != other: 766 1329 return None 767 1330 else: 768 1331 return MatrixFunctor(self.nrows, self.ncols, self.is_sparse and other.is_sparse) 769 1332 770 1333 class LaurentPolynomialFunctor(ConstructionFunctor): 771 1334 """ 1335 Construction functor for Laurent polynomial rings. 1336 1337 EXAMPLES:: 1338 1339 sage: L.<t> = LaurentPolynomialRing(ZZ) 1340 sage: F = L.construction()[0] 1341 sage: F 1342 LaurentPolynomialFunctor 1343 sage: F(QQ) 1344 Univariate Laurent Polynomial Ring in t over Rational Field 1345 sage: K.<x> = LaurentPolynomialRing(ZZ) 1346 sage: F(K) 1347 Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in x over Integer Ring 1348 sage: P.<x,y> = ZZ[] 1349 sage: f = P.hom([x+2*y,3*x-y],P) 1350 sage: F(f) 1351 Ring endomorphism of Univariate Laurent Polynomial Ring in t over Multivariate Polynomial Ring in x, y over Integer Ring 1352 Defn: Induced from base ring by 1353 Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring 1354 Defn: x |--> x + 2*y 1355 y |--> 3*x - y 1356 sage: F(f)(x*F(P).gen()^-2+y*F(P).gen()^3) 1357 (3*x - y)*t^3 + (x + 2*y)*t^-2 1358 1359 """ 772 1360 rank = 9 773 1361 774 1362 def __init__(self, var, multi_variate=False): 1363 """ 1364 INPUT: 1365 1366 - ``var``, a string or a list of strings 1367 - ``multi_variate``, optional bool, default ``False`` if ``var`` is a string 1368 and ``True`` otherwise: If ``True``, application to a Laurent polynomial 1369 ring yields a multivariate Laurent polynomial ring. 1370 1371 TESTS:: 1372 1373 sage: from sage.categories.pushout import LaurentPolynomialFunctor 1374 sage: F1 = LaurentPolynomialFunctor('t') 1375 sage: F2 = LaurentPolynomialFunctor('s', multi_variate=True) 1376 sage: F3 = LaurentPolynomialFunctor(['s','t']) 1377 sage: F1(F2(QQ)) 1378 Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field 1379 sage: F2(F1(QQ)) 1380 Multivariate Laurent Polynomial Ring in t, s over Rational Field 1381 sage: F3(QQ) 1382 Multivariate Laurent Polynomial Ring in s, t over Rational Field 1383 1384 """ 775 1385 Functor.__init__(self, Rings(), Rings()) 1386 if not isinstance(var, (basestring,tuple,list)): 1387 raise TypeError, "variable name or list of variable names expected" 776 1388 self.var = var 777 self.multi_variate = multi_variate 1389 self.multi_variate = multi_variate or not isinstance(var, basestring) 1390 778 1391 def _apply_functor(self, R): 1392 """ 1393 Apply the functor to an object of ``self``'s domain. 1394 1395 TESTS:: 1396 1397 sage: from sage.categories.pushout import LaurentPolynomialFunctor 1398 sage: F1 = LaurentPolynomialFunctor('t') 1399 sage: F2 = LaurentPolynomialFunctor('s', multi_variate=True) 1400 sage: F3 = LaurentPolynomialFunctor(['s','t']) 1401 sage: F1(F2(QQ)) # indirect doctest 1402 Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field 1403 sage: F2(F1(QQ)) 1404 Multivariate Laurent Polynomial Ring in t, s over Rational Field 1405 sage: F3(QQ) 1406 Multivariate Laurent Polynomial Ring in s, t over Rational Field 1407 1408 """ 779 1409 from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing, is_LaurentPolynomialRing 780 1410 if self.multi_variate and is_LaurentPolynomialRing(R): 781 1411 return LaurentPolynomialRing(R.base_ring(), (list(R.variable_names()) + [self.var])) 782 1412 else: 783 1413 from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing 784 1414 return LaurentPolynomialRing(R, self.var) 1415 785 1416 def __cmp__(self, other): 1417 """ 1418 TESTS:: 1419 1420 sage: from sage.categories.pushout import LaurentPolynomialFunctor 1421 sage: F1 = LaurentPolynomialFunctor('t') 1422 sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True) 1423 sage: F3 = LaurentPolynomialFunctor(['s','t']) 1424 sage: F1 == F2 1425 True 1426 sage: F1 == loads(dumps(F1)) 1427 True 1428 sage: F1 == F3 1429 False 1430 sage: F1 == QQ.construction()[0] 1431 False 1432 1433 """ 786 1434 c = cmp(type(self), type(other)) 787 1435 if c == 0: 788 1436 c = cmp(self.var, other.var) 789 1437 return c 1438 790 1439 def merge(self, other): 1440 """ 1441 Two Laurent polynomial construction functors merge if the variable names coincide. 1442 The result is multivariate if one of the arguments is multivariate. 1443 1444 EXAMPLE:: 1445 1446 sage: from sage.categories.pushout import LaurentPolynomialFunctor 1447 sage: F1 = LaurentPolynomialFunctor('t') 1448 sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True) 1449 sage: F1.merge(F2) 1450 LaurentPolynomialFunctor 1451 sage: F1.merge(F2)(LaurentPolynomialRing(GF(2),'a')) 1452 Multivariate Laurent Polynomial Ring in a, t over Finite Field of size 2 1453 sage: F1.merge(F1)(LaurentPolynomialRing(GF(2),'a')) 1454 Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in a over Finite Field of size 2 1455 1456 """ 791 1457 if self == other or isinstance(other, PolynomialFunctor) and self.var == other.var: 792 1458 return LaurentPolynomialFunctor(self.var, (self.multi_variate or other.multi_variate)) 793 1459 else: … … 795 1461 796 1462 797 1463 class VectorFunctor(ConstructionFunctor): 798 799 rank = 10 # ranking of functor, not rank of module 1464 """ 1465 A construction functor for free modules over commutative rings. 1466 1467 EXAMPLE:: 1468 1469 sage: F = (ZZ^3).construction()[0] 1470 sage: F 1471 VectorFunctor 1472 sage: F(GF(2)['t']) 1473 Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL) 1474 1475 1476 """ 1477 rank = 10 # ranking of functor, not rank of module. 1478 # This coincides with the rank of the matrix construction functor, but this is OK since they can not both be applied in any order 800 1479 801 1480 def __init__(self, n, is_sparse=False, inner_product_matrix=None): 802 # Functor.__init__(self, Rings(), FreeModules()) # takes a base ring 803 #This is a bad choice, since the input must be a commutative ring, and 804 #the output belongs to the category of commutative additive groups 805 #Functor.__init__(self, Objects(), Objects()) 806 Functor.__init__(self,CommutativeRings(),CommutativeAdditiveGroups()) 1481 """ 1482 INPUT: 1483 1484 - ``n``, the rank of the to-be-created modules (non-negative integer) 1485 - ``is_sparse`` (optional bool, default ``False``), create sparse implementation of modules 1486 - ``inner_product_matrix``: ``n`` by ``n`` matrix, used to compute inner products in the 1487 to-be-created modules 1488 1489 TEST:: 1490 1491 sage: from sage.categories.pushout import VectorFunctor 1492 sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9))) 1493 sage: F1.domain() 1494 Category of commutative rings 1495 sage: F1.codomain() 1496 Category of commutative additive groups 1497 sage: M1 = F1(ZZ) 1498 sage: M1.is_sparse() 1499 False 1500 sage: v = M1([3, 2, 1]) 1501 sage: v*Matrix(3,3,range(9))*v.column() 1502 (96) 1503 sage: v.inner_product(v) 1504 96 1505 sage: F2 = VectorFunctor(3, is_sparse=True) 1506 sage: M2 = F2(QQ); M2; M2.is_sparse() 1507 Sparse vector space of dimension 3 over Rational Field 1508 True 1509 1510 """ 1511 # Functor.__init__(self, Rings(), FreeModules()) # FreeModules() takes a base ring 1512 # Functor.__init__(self, Objects(), Objects()) # Object() makes no sence, since FreeModule raises an error, e.g., on Set(['a',1]). 1513 ## FreeModule requires a commutative ring. Thus, we have 1514 Functor.__init__(self, CommutativeRings(), CommutativeAdditiveGroups()) 807 1515 self.n = n 808 1516 self.is_sparse = is_sparse 809 1517 self.inner_product_matrix = inner_product_matrix 1518 810 1519 def _apply_functor(self, R): 1520 """ 1521 Apply the functor to an object of ``self``'s domain. 1522 1523 TESTS:: 1524 1525 sage: from sage.categories.pushout import VectorFunctor 1526 sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9))) 1527 sage: M1 = F1(ZZ) # indirect doctest 1528 sage: M1.is_sparse() 1529 False 1530 sage: v = M1([3, 2, 1]) 1531 sage: v*Matrix(3,3,range(9))*v.column() 1532 (96) 1533 sage: v.inner_product(v) 1534 96 1535 sage: F2 = VectorFunctor(3, is_sparse=True) 1536 sage: M2 = F2(QQ); M2; M2.is_sparse() 1537 Sparse vector space of dimension 3 over Rational Field 1538 True 1539 sage: v = M2([3, 2, 1]) 1540 sage: v.inner_product(v) 1541 14 1542 1543 """ 811 1544 from sage.modules.free_module import FreeModule 812 1545 return FreeModule(R, self.n, sparse=self.is_sparse, inner_product_matrix=self.inner_product_matrix) 1546 1547 def _apply_functor_to_morphism(self, f): 1548 """ 1549 This is not implemented yet. 1550 1551 TEST:: 1552 1553 sage: F = (ZZ^3).construction()[0] 1554 sage: P.<x,y> = ZZ[] 1555 sage: f = P.hom([x+2*y,3*x-y],P) 1556 sage: F(f) # indirect doctest 1557 Traceback (most recent call last): 1558 ... 1559 NotImplementedError: Can not create induced morphisms of free modules yet 1560 """ 1561 ## TODO: Implement this! 1562 raise NotImplementedError, "Can not create induced morphisms of free modules yet" 1563 813 1564 def __cmp__(self, other): 1565 """ 1566 Only the rank of the to-be-created modules is compared, *not* the inner product matrix. 1567 1568 TESTS:: 1569 1570 sage: from sage.categories.pushout import VectorFunctor 1571 sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9))) 1572 sage: F2 = (ZZ^3).construction()[0] 1573 sage: F1 == F2 1574 True 1575 sage: F1(QQ) == F2(QQ) 1576 True 1577 sage: F1(QQ).inner_product_matrix() == F2(QQ).inner_product_matrix() 1578 False 1579 sage: F1 == loads(dumps(F1)) 1580 True 1581 """ 814 1582 c = cmp(type(self), type(other)) 815 1583 if c == 0: 816 1584 c = cmp(self.n, other.n) 817 1585 return c 1586 818 1587 def merge(self, other): 1588 """ 1589 Two constructors of free modules merge, if the module ranks coincide. If both 1590 have explicitly given inner product matrices, they must coincide as well. 1591 1592 EXAMPLE: 1593 1594 Two modules without explicitly given inner product allow coercion:: 1595 1596 sage: M1 = QQ^3 1597 sage: P.<t> = ZZ[] 1598 sage: M2 = FreeModule(P,3) 1599 sage: M1([1,1/2,1/3]) + M2([t,t^2+t,3]) # indirect doctest 1600 (t + 1, t^2 + t + 1/2, 10/3) 1601 1602 If only one summand has an explicit inner product, the result will be provided 1603 with it:: 1604 1605 sage: M3 = FreeModule(P,3, inner_product_matrix = Matrix(3,3,range(9))) 1606 sage: M1([1,1/2,1/3]) + M3([t,t^2+t,3]) 1607 (t + 1, t^2 + t + 1/2, 10/3) 1608 sage: (M1([1,1/2,1/3]) + M3([t,t^2+t,3])).parent().inner_product_matrix() 1609 [0 1 2] 1610 [3 4 5] 1611 [6 7 8] 1612 1613 If both summands have an explicit inner product (even if it is the standard 1614 inner product), then the products must coincide. The only difference between 1615 ``M1`` and ``M4`` in the following example is the fact that the default 1616 inner product was *explicitly* requested for ``M4``. It is therefore not 1617 possible to coerce with a different inner product:: 1618 1619 sage: M4 = FreeModule(QQ,3, inner_product_matrix = Matrix(3,3,1)) 1620 sage: M4 == M1 1621 True 1622 sage: M4.inner_product_matrix() == M1.inner_product_matrix() 1623 True 1624 sage: M4([1,1/2,1/3]) + M3([t,t^2+t,3]) # indirect doctest 1625 Traceback (most recent call last): 1626 ... 1627 TypeError: unsupported operand parent(s) for '+': 'Ambient quadratic space of dimension 3 over Rational Field 1628 Inner product matrix: 1629 [1 0 0] 1630 [0 1 0] 1631 [0 0 1]' and 'Ambient free quadratic module of rank 3 over the integral domain Univariate Polynomial Ring in t over Integer Ring 1632 Inner product matrix: 1633 [0 1 2] 1634 [3 4 5] 1635 [6 7 8]' 1636 1637 """ 819 1638 if self != other: 820 1639 return None 1640 if self.inner_product_matrix is None: 1641 return VectorFunctor(self.n, self.is_sparse and other.is_sparse, other.inner_product_matrix) 1642 if other.inner_product_matrix is None: 1643 return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix) 1644 # At this point, we know that the user wants to take care of the inner product. 1645 # So, we only merge if both coincide: 1646 if self.inner_product_matrix != other.inner_product_matrix: 1647 return None 821 1648 else: 822 return VectorFunctor(self.n, self.is_sparse and other.is_sparse) 823 1649 return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix) 824 1650 825 1651 class SubspaceFunctor(ConstructionFunctor): 1652 """ 1653 Constructing a subspace of an ambient free module, given by a basis. 1654 1655 NOTE: 1656 1657 This construction functor keeps track of the basis. It can only be applied 1658 to free modules into which this basis coerces. 1659 1660 EXAMPLES:: 1661 1662 sage: M = ZZ^3 1663 sage: S = M.submodule([(1,2,3),(4,5,6)]); S 1664 Free module of degree 3 and rank 2 over Integer Ring 1665 Echelon basis matrix: 1666 [1 2 3] 1667 [0 3 6] 1668 sage: F = S.construction()[0] 1669 sage: F(GF(2)^3) 1670 Vector space of degree 3 and dimension 2 over Finite Field of size 2 1671 User basis matrix: 1672 [1 0 1] 1673 [0 1 0] 1674 1675 """ 826 1676 rank = 11 # ranking of functor, not rank of module 1677 827 1678 def __init__(self, basis): 828 # Functor.__init__(self, FreeModules(), FreeModules()) # takes a base ring 829 #Functor.__init__(self, Objects(), Objects()) 1679 """ 1680 INPUT: 1681 1682 ``basis``: a list of elements of a free module. 1683 1684 TEST:: 1685 1686 sage: from sage.categories.pushout import SubspaceFunctor 1687 sage: M = ZZ^3 1688 sage: F = SubspaceFunctor([M([1,2,3]),M([4,5,6])]) 1689 sage: F(GF(5)^3) 1690 Vector space of degree 3 and dimension 2 over Finite Field of size 5 1691 User basis matrix: 1692 [1 2 3] 1693 [4 0 1] 1694 """ 1695 ## Functor.__init__(self, FreeModules(), FreeModules()) # takes a base ring 1696 ## Functor.__init__(self, Objects(), Objects()) # is too general 830 1697 ## It seems that the category of commutative additive groups 831 1698 ## currently is the smallest base ring free category that 832 1699 ## contains in- and output 833 Functor.__init__(self, CommutativeAdditiveGroups(), CommutativeAdditiveGroups())1700 Functor.__init__(self, CommutativeAdditiveGroups(), CommutativeAdditiveGroups()) 834 1701 self.basis = basis 1702 835 1703 def _apply_functor(self, ambient): 1704 """ 1705 Apply the functor to an object of ``self``'s domain. 1706 1707 TESTS:: 1708 1709 sage: M = ZZ^3 1710 sage: S = M.submodule([(1,2,3),(4,5,6)]); S 1711 Free module of degree 3 and rank 2 over Integer Ring 1712 Echelon basis matrix: 1713 [1 2 3] 1714 [0 3 6] 1715 sage: F = S.construction()[0] 1716 sage: F(GF(2)^3) # indirect doctest 1717 Vector space of degree 3 and dimension 2 over Finite Field of size 2 1718 User basis matrix: 1719 [1 0 1] 1720 [0 1 0] 1721 """ 836 1722 return ambient.span_of_basis(self.basis) 1723 1724 def _apply_functor_to_morphism(self, f): 1725 """ 1726 This is not implemented yet. 1727 1728 TEST:: 1729 1730 sage: F = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0] 1731 sage: P.<x,y> = ZZ[] 1732 sage: f = P.hom([x+2*y,3*x-y],P) 1733 sage: F(f) # indirect doctest 1734 Traceback (most recent call last): 1735 ... 1736 NotImplementedError: Can not create morphisms of free sub-modules yet 1737 """ 1738 raise NotImplementedError, "Can not create morphisms of free sub-modules yet" 1739 837 1740 def __cmp__(self, other): 1741 """ 1742 TEST:: 1743 1744 sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0] 1745 sage: F2 = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0] 1746 sage: F3 = (QQ^3).span([(1,2,3),(4,5,6)]).construction()[0] 1747 sage: F4 = (ZZ^3).span([(1,0,-1),(0,1,2)]).construction()[0] 1748 sage: F1 == loads(dumps(F1)) 1749 True 1750 1751 The ``span`` method automatically transforms the given basis into 1752 echelon form. The bases look like that:: 1753 1754 sage: F1.basis 1755 [ 1756 (1, 0, 4), 1757 (0, 1, 2) 1758 ] 1759 sage: F2.basis 1760 [ 1761 (1, 2, 3), 1762 (0, 3, 6) 1763 ] 1764 sage: F3.basis 1765 [ 1766 (1, 0, -1), 1767 (0, 1, 2) 1768 ] 1769 sage: F4.basis 1770 [ 1771 (1, 0, -1), 1772 (0, 1, 2) 1773 ] 1774 1775 1776 The basis of ``F2`` is modulo 5 different from the other bases. 1777 So, we have:: 1778 1779 sage: F1 != F2 != F3 1780 True 1781 1782 The bases of ``F1``, ``F3`` and ``F4`` are the same modulo 5; however, 1783 there is no coercion from ``QQ^3`` to ``GF(5)^3``. Therefore, we have:: 1784 1785 sage: F1 == F3 1786 False 1787 1788 But there are coercions from ``ZZ^3`` to ``QQ^3`` and ``GF(5)^3``, thus:: 1789 1790 sage: F1 == F4 == F3 1791 True 1792 1793 """ 838 1794 c = cmp(type(self), type(other)) 839 1795 if c == 0: 840 1796 c = cmp(self.basis, other.basis) 841 1797 return c 1798 842 1799 def merge(self, other): 1800 """ 1801 Two Subspace Functors are merged into a construction functor of the sum of two subspaces. 1802 1803 EXAMPLE:: 1804 1805 sage: M = GF(5)^3 1806 sage: S1 = M.submodule([(1,2,3),(4,5,6)]) 1807 sage: S2 = M.submodule([(2,2,3)]) 1808 sage: F1 = S1.construction()[0] 1809 sage: F2 = S2.construction()[0] 1810 sage: F1.merge(F2) 1811 SubspaceFunctor 1812 sage: F1.merge(F2)(GF(5)^3) == S1+S2 1813 True 1814 sage: F1.merge(F2)(GF(5)['t']^3) 1815 Free module of degree 3 and rank 3 over Univariate Polynomial Ring in t over Finite Field of size 5 1816 User basis matrix: 1817 [1 0 0] 1818 [0 1 0] 1819 [0 0 1] 1820 1821 TEST:: 1822 1823 sage: P.<t> = ZZ[] 1824 sage: S1 = (ZZ^3).submodule([(1,2,3),(4,5,6)]) 1825 sage: S2 = (Frac(P)^3).submodule([(t,t^2,t^3+1),(4*t,0,1)]) 1826 sage: v = S1([0,3,6]) + S2([2,0,1/(2*t)]); v # indirect doctest 1827 (2, 3, (12*t + 1)/(2*t)) 1828 sage: v.parent() 1829 Vector space of degree 3 and dimension 3 over Fraction Field of Univariate Polynomial Ring in t over Integer Ring 1830 User basis matrix: 1831 [1 0 0] 1832 [0 1 0] 1833 [0 0 1] 1834 1835 """ 843 1836 if isinstance(other, SubspaceFunctor): 844 return SubspaceFunctor(self.basis + other.basis) # TODO: remove linear dependencies 1837 # in order to remove linear dependencies, and in 1838 # order to test compatibility of the base rings, 1839 # we try to construct a sample submodule 1840 if not other.basis: 1841 return self 1842 if not self.basis: 1843 return other 1844 try: 1845 P = pushout(self.basis[0].parent().ambient_module(),other.basis[0].parent().ambient_module()) 1846 except CoercionException: 1847 return None 1848 S = P.submodule(self.basis+other.basis).echelonized_basis() 1849 return SubspaceFunctor(S) 845 1850 else: 846 1851 return None 847 1852 848 849 1853 class FractionField(ConstructionFunctor): 850 1854 """ 1855 Construction functor for fraction fields. 1856 1857 EXAMPLE:: 1858 1859 sage: F = QQ.construction()[0] 1860 sage: F(GF(5)) is GF(5) 1861 True 1862 sage: F(ZZ['t']) 1863 Fraction Field of Univariate Polynomial Ring in t over Integer Ring 1864 sage: P.<x,y> = QQ[] 1865 sage: f = P.hom([x+2*y,3*x-y],P) 1866 sage: F(f) 1867 Ring endomorphism of Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field 1868 Defn: x |--> x + 2*y 1869 y |--> 3*x - y 1870 sage: F(f)(1/x) 1871 1/(x + 2*y) 1872 sage: F == loads(dumps(F)) 1873 True 1874 1875 """ 851 1876 rank = 5 852 1877 853 1878 def __init__(self): 1879 """ 1880 TEST:: 1881 1882 sage: from sage.categories.pushout import FractionField 1883 sage: F = FractionField() 1884 sage: F 1885 FractionField 1886 sage: F(ZZ['t']) 1887 Fraction Field of Univariate Polynomial Ring in t over Integer Ring 1888 """ 854 1889 Functor.__init__(self, Rings(), Fields()) 1890 855 1891 def _apply_functor(self, R): 1892 """ 1893 Apply the functor to an object of ``self``'s domain. 1894 1895 TEST:: 1896 1897 sage: F = QQ.construction()[0] 1898 sage: F(GF(5)['t']) # indirect doctest 1899 Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 1900 """ 856 1901 return R.fraction_field() 857 1902 858 859 class LocalizationFunctor(ConstructionFunctor): 860 861 rank = 6 862 863 def __init__(self, t): 864 Functor.__init__(self, Rings(), Rings()) 865 self.t = t 866 def _apply_functor(self, R): 867 return R.localize(t) 868 def __cmp__(self, other): 869 c = cmp(type(self), type(other)) 870 if c == 0: 871 c = cmp(self.t, other.t) 872 return c 873 1903 1904 # This isn't used anywhere in Sage, and so I remove it (Simon King, 2010-05) 1905 # 1906 #class LocalizationFunctor(ConstructionFunctor): 1907 # 1908 # rank = 6 1909 # 1910 # def __init__(self, t): 1911 # Functor.__init__(self, Rings(), Rings()) 1912 # self.t = t 1913 # def _apply_functor(self, R): 1914 # return R.localize(t) 1915 # def __cmp__(self, other): 1916 # c = cmp(type(self), type(other)) 1917 # if c == 0: 1918 # c = cmp(self.t, other.t) 1919 # return c 874 1920 875 1921 class CompletionFunctor(ConstructionFunctor): 876 1922 """ 1923 Completion of a ring with respect to a given prime (including infinity). 1924 1925 EXAMPLES:: 1926 1927 sage: R = Zp(5) 1928 sage: R 1929 5-adic Ring with capped relative precision 20 1930 sage: F1 = R.construction()[0] 1931 sage: F1 1932 Completion[5] 1933 sage: F1(ZZ) is R 1934 True 1935 sage: F1(QQ) 1936 5-adic Field with capped relative precision 20 1937 sage: F2 = RR.construction()[0] 1938 sage: F2 1939 Completion[+Infinity] 1940 sage: F2(QQ) is RR 1941 True 1942 sage: P.<x> = ZZ[] 1943 sage: Px = P.completion(x) # currently the only implemented completion of P 1944 sage: Px 1945 Power Series Ring in x over Integer Ring 1946 sage: F3 = Px.construction()[0] 1947 sage: F3(GF(3)['x']) 1948 Power Series Ring in x over Finite Field of size 3 1949 1950 TEST:: 1951 1952 sage: R1.<a> = Zp(5,prec=20)[] 1953 sage: R2 = Qp(5,prec=40) 1954 sage: R2(1) + a 1955 (1 + O(5^20))*a + (1 + O(5^40)) 1956 sage: 1/2 + a 1957 (1 + O(5^20))*a + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + 2*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 2*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 2*5^18 + 2*5^19 + O(5^20)) 1958 1959 """ 877 1960 rank = 4 878 1961 879 1962 def __init__(self, p, prec, extras=None): 1963 """ 1964 INPUT: 1965 1966 - ``p``: A prime number, the generator of a univariate polynomial ring, or ``+Infinity`` 1967 - ``prec``: an integer, yielding the precision in bits. Note that 1968 if ``p`` is prime then the ``prec`` is the *capped* precision, 1969 while it is the *set* precision if ``p`` is ``+Infinity``. 1970 - ``extras`` (optional dictionary): Information on how to print elements, etc. 1971 1972 TESTS:: 1973 1974 sage: from sage.categories.pushout import CompletionFunctor 1975 sage: F1 = CompletionFunctor(5,100) 1976 sage: F1(QQ) 1977 5-adic Field with capped relative precision 100 1978 sage: F1(ZZ) 1979 5-adic Ring with capped relative precision 100 1980 sage: F2 = RR.construction()[0] 1981 sage: F2 1982 Completion[+Infinity] 1983 sage: F2.extras 1984 {'sci_not': False, 'rnd': 'RNDN'} 1985 1986 """ 880 1987 Functor.__init__(self, Rings(), Rings()) 881 1988 self.p = p 882 1989 self.prec = prec 883 1990 self.extras = extras 1991 1992 def __str__(self): 1993 """ 1994 TEST:: 1995 1996 sage: Zp(7).construction() # indirect doctest 1997 (Completion[7], Integer Ring) 1998 """ 1999 return 'Completion[%s]'%repr(self.p) 2000 884 2001 def _apply_functor(self, R): 885 return R.completion(self.p, self.prec, self.extras) 2002 """ 2003 Apply the functor to an object of ``self``'s domain. 2004 2005 TEST:: 2006 2007 sage: R = Zp(5) 2008 sage: F1 = R.construction()[0] 2009 sage: F1(ZZ) is R # indirect doctest 2010 True 2011 sage: F1(QQ) 2012 5-adic Field with capped relative precision 20 2013 2014 """ 2015 try: 2016 if self.extras is None: 2017 try: 2018 return R.completion(self.p, self.prec) 2019 except TypeError: 2020 return R.completion(self.p, self.prec, {}) 2021 return R.completion(self.p, self.prec, self.extras) 2022 except (NotImplementedError,AttributeError): 2023 if R.construction() is None: 2024 raise NotImplementedError, "Completion is not implemented for %s"%R.__class__ 2025 F, BR = R.construction() 2026 M = self.merge(F) or F.merge(self) 2027 if M is not None: 2028 return M(BR) 2029 if self.commutes(F) or F.commutes(self): 2030 return F(self(BR)) 2031 raise NotImplementedError, "Don't know how to apply %s to %s"%(repr(self),repr(R)) 2032 886 2033 def __cmp__(self, other): 2034 """ 2035 NOTE: 2036 2037 Only the prime used in the completion is relevant to comparison 2038 of Completion functors, although the resulting rings also take 2039 the precision into account. 2040 2041 TEST:: 2042 2043 sage: R1 = Zp(5,prec=30) 2044 sage: R2 = Zp(5,prec=40) 2045 sage: F1 = R1.construction()[0] 2046 sage: F2 = R2.construction()[0] 2047 sage: F1 == loads(dumps(F1)) # indirect doctest 2048 True 2049 sage: F1==F2 2050 True 2051 sage: F1(QQ)==F2(QQ) 2052 False 2053 sage: R3 = Zp(7) 2054 sage: F3 = R3.construction()[0] 2055 sage: F1==F3 2056 False 2057 """ 887 2058 c = cmp(type(self), type(other)) 888 2059 if c == 0: 889 2060 c = cmp(self.p, other.p) 890 2061 return c 2062 891 2063 def merge(self, other): 2064 """ 2065 Two Completion functors are merged, if they are equal. If the precisions of 2066 both functors coincide, then a Completion functor is returned that results 2067 from updating the ``extras`` dictionary of ``self`` by ``other.extras``. 2068 Otherwise, if the completion is at infinity then merging does not increase 2069 the set precision, and if the completion is at a finite prime, merging 2070 does not decrease the capped precision. 2071 2072 EXAMPLE:: 2073 2074 sage: R1.<a> = Zp(5,prec=20)[] 2075 sage: R2 = Qp(5,prec=40) 2076 sage: R2(1)+a # indirect doctest 2077 (1 + O(5^20))*a + (1 + O(5^40)) 2078 sage: R3 = RealField(30) 2079 sage: R4 = RealField(50) 2080 sage: R3(1) + R4(1) # indirect doctest 2081 2.0000000 2082 sage: (R3(1) + R4(1)).parent() 2083 Real Field with 30 bits of precision 2084 2085 """ 2086 if self!=other: 2087 return None 892 2088 if self.p == other.p: 2089 from sage.all import Infinity 893 2090 if self.prec == other.prec: 894 2091 extras = self.extras.copy() 895 2092 extras.update(other.extras) 896 2093 return CompletionFunctor(self.p, self.prec, extras) 897 elif self.prec < other.prec:2094 elif (self.p==Infinity and self.prec<other.prec) or (self.p<Infinity and self.prec>other.prec): 898 2095 return self 899 2096 else: # self.prec > other.prec 900 2097 return other 901 2098 else: 902 2099 return None 903 2100 ## Completion has a lower rank than FractionField 2101 ## and is thus applied first. However, fact is that 2102 ## both commute. This is used in the call method, 2103 ## since some fraction fields have no completion method 2104 ## implemented. 2105 2106 def commutes(self,other): 2107 """ 2108 Completion commutes with fraction fields. 2109 2110 EXAMPLE:: 2111 2112 sage: F1 = Qp(5).construction()[0] 2113 sage: F2 = QQ.construction()[0] 2114 sage: F1.commutes(F2) 2115 True 2116 2117 TEST: 2118 2119 The fraction field ``R`` in the example below has no completion 2120 method. But completion commutes with the fraction field functor, 2121 and so it is tried internally whether applying the construction 2122 functors in opposite order works. It does:: 2123 2124 sage: P.<x> = ZZ[] 2125 sage: C = P.completion(x).construction()[0] 2126 sage: R = FractionField(P) 2127 sage: hasattr(R,'completion') 2128 False 2129 sage: C(R) is Frac(C(P)) 2130 True 2131 sage: F = R.construction()[0] 2132 sage: (C*F)(ZZ['x']) is (F*C)(ZZ['x']) 2133 True 2134 2135 """ 2136 return isinstance(other,(FractionField,CompletionFunctor)) 904 2137 905 2138 class QuotientFunctor(ConstructionFunctor): 906 2139 """ 2140 Construction functor for quotient rings. 2141 2142 NOTE: 2143 2144 The functor keeps track of variable names. 2145 2146 EXAMPLE:: 2147 2148 sage: P.<x,y> = ZZ[] 2149 sage: Q = P.quo([x^2+y^2]*P) 2150 sage: F = Q.construction()[0] 2151 sage: F(QQ['x','y']) 2152 Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2) 2153 sage: F(QQ['x','y']) == QQ['x','y'].quo([x^2+y^2]*QQ['x','y']) 2154 True 2155 sage: F(QQ['x','y','z']) 2156 Traceback (most recent call last): 2157 ... 2158 CoercionException: Can not apply this quotient functor to Multivariate Polynomial Ring in x, y, z over Rational Field 2159 sage: F(QQ['y','z']) 2160 Traceback (most recent call last): 2161 ... 2162 TypeError: not a constant polynomial 2163 """ 907 2164 rank = 7 908 2165 909 def __init__(self, I, as_field=False): 2166 def __init__(self, I, names=None, as_field=False): 2167 """ 2168 INPUT: 2169 2170 - ``I``, an ideal (the modulus) 2171 - ``names`` (optional string or list of strings), the names for the quotient ring generators 2172 - ``as_field`` (optional bool, default false), return the quotient ring as field (if available). 2173 2174 TESTS:: 2175 2176 sage: from sage.categories.pushout import QuotientFunctor 2177 sage: P.<t> = ZZ[] 2178 sage: F = QuotientFunctor([5+t^2]*P) 2179 sage: F(P) 2180 Univariate Quotient Polynomial Ring in tbar over Integer Ring with modulus t^2 + 5 2181 sage: F(QQ['t']) 2182 Univariate Quotient Polynomial Ring in tbar over Rational Field with modulus t^2 + 5 2183 sage: F = QuotientFunctor([5+t^2]*P,names='s') 2184 sage: F(P) 2185 Univariate Quotient Polynomial Ring in s over Integer Ring with modulus t^2 + 5 2186 sage: F(QQ['t']) 2187 Univariate Quotient Polynomial Ring in s over Rational Field with modulus t^2 + 5 2188 sage: F = QuotientFunctor([5]*ZZ,as_field=True) 2189 sage: F(ZZ) 2190 Finite Field of size 5 2191 sage: F = QuotientFunctor([5]*ZZ) 2192 sage: F(ZZ) 2193 Ring of integers modulo 5 2194 2195 """ 910 2196 Functor.__init__(self, Rings(), Rings()) # much more general... 911 2197 self.I = I 2198 if names is None: 2199 self.names = None 2200 elif isinstance(names, basestring): 2201 self.names = (names,) 2202 else: 2203 self.names = tuple(names) 912 2204 self.as_field = as_field 2205 913 2206 def _apply_functor(self, R): 2207 """ 2208 Apply the functor to an object of ``self``'s domain. 2209 2210 TESTS:: 2211 2212 sage: P.<x,y> = ZZ[] 2213 sage: Q = P.quo([2+x^2,3*x+y^2]) 2214 sage: F = Q.construction()[0]; F 2215 QuotientFunctor 2216 sage: F(QQ['x','y']) # indirect doctest 2217 Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + 2, y^2 + 3*x) 2218 2219 Note that the ``quo()`` method of a field returns the integer zero. 2220 The quotient construction functor, when applied to a field, returns 2221 the trivial ring:: 2222 2223 sage: F = ZZ.quo([5]*ZZ).construction()[0] 2224 sage: F(QQ) is Integers(1) 2225 True 2226 sage: QQ.quo(5) is int(0) 2227 True 2228 2229 """ 914 2230 I = self.I 2231 from sage.all import QQ 2232 if not I.is_zero(): 2233 from sage.rings.field import is_Field 2234 if is_Field(R): 2235 from sage.all import Integers 2236 return Integers(1) 915 2237 if I.ring() != R: 916 I.base_extend(R) 917 Q = R.quo(I) 2238 if I.ring().has_coerce_map_from(R): 2239 R = I.ring() 2240 else: 2241 R = pushout(R,I.ring().base_ring()) 2242 I = [R(1)*t for t in I.gens()]*R 2243 try: 2244 Q = R.quo(I,names=self.names) 2245 except IndexError: # That may happen! 2246 raise CoercionException, "Can not apply this quotient functor to %s"%R 918 2247 if self.as_field and hasattr(Q, 'field'): 919 2248 Q = Q.field() 920 2249 return Q 2250 921 2251 def __cmp__(self, other): 2252 """ 2253 The types, the names and the moduli are compared. 2254 2255 TESTS:: 2256 2257 sage: P.<x> = QQ[] 2258 sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] 2259 sage: F == loads(dumps(F)) 2260 True 2261 sage: P2.<x,y> = QQ[] 2262 sage: F == P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] 2263 False 2264 sage: P3.<x> = ZZ[] 2265 sage: F == P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0] 2266 True 2267 """ 922 2268 c = cmp(type(self), type(other)) 923 2269 if c == 0: 2270 c = cmp(self.names, other.names) 2271 if c == 0: 924 2272 c = cmp(self.I, other.I) 925 2273 return c 2274 926 2275 def merge(self, other): 2276 """ 2277 Two quotient functors with coinciding names are merged by taking the gcd of their moduli. 2278 2279 EXAMPLE:: 2280 2281 sage: P.<x> = QQ[] 2282 sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)]) 2283 sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)]) 2284 sage: from sage.categories.pushout import pushout 2285 sage: pushout(Q1,Q2) # indirect doctest 2286 Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^4 + 2*x^2 + 1 2287 2288 The following was fixed in trac ticket #8800:: 2289 2290 sage: pushout(GF(5), Integers(5)) 2291 Finite Field of size 5 2292 2293 """ 2294 if type(self)!=type(other): 2295 return None 2296 if self.names != other.names: 2297 return None 927 2298 if self == other: 928 return self 2299 if self.as_field == other.as_field: 2300 return self 2301 return QuotientFunctor(self.I, names=self.names, as_field=True) # one of them yields a field! 929 2302 try: 930 2303 gcd = self.I + other.I 931 2304 except (TypeError, NotImplementedError): 932 return None 2305 try: 2306 gcd = self.I.gcd(other.I) 2307 except (TypeError, NotImplementedError): 2308 return None 933 2309 if gcd.is_trivial() and not gcd.is_zero(): 934 2310 # quotient by gcd would result in the trivial ring/group/... 935 2311 # Rather than create the zero ring, we claim they can't be merged 936 2312 # TODO: Perhaps this should be detected at a higher level... 937 2313 raise TypeError, "Trivial quotient intersection." 938 return QuotientFunctor(gcd) 2314 # GF(p) has a coercion from Integers(p). Hence, merging should 2315 # yield a field if either self or other yields a field. 2316 return QuotientFunctor(gcd, names=self.names, as_field=self.as_field or other.as_field) 939 2317 940 2318 class AlgebraicExtensionFunctor(ConstructionFunctor): 941 2319 """ 2320 Algebraic extension (univariate polynomial ring modulo principal ideal). 2321 2322 EXAMPLE:: 2323 2324 sage: K.<a> = NumberField(x^3+x^2+1) 2325 sage: F = K.construction()[0] 2326 sage: F(ZZ['t']) 2327 Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1 2328 2329 Note that, even if a field is algebraically closed, the algebraic 2330 extension will be constructed as the quotient of a univariate 2331 polynomial ring:: 2332 2333 sage: F(CC) 2334 Univariate Quotient Polynomial Ring in a over Complex Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 2335 sage: F(RR) 2336 Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 2337 2338 Note that the construction functor of a number field applied to 2339 the integers returns an order (not necessarily maximal) of that 2340 field, similar to the behaviour of ``ZZ.extension(...)``:: 2341 2342 sage: F(ZZ) 2343 Order in Number Field in a with defining polynomial x^3 + x^2 + 1 2344 2345 This also holds for non-absolute number fields:: 2346 2347 sage: K.<a,b> = NumberField([x^3+x^2+1,x^2+x+1]) 2348 sage: F = K.construction()[0] 2349 sage: O = F(ZZ); O 2350 Relative Order in Number Field in a with defining polynomial x^3 + x^2 + 1 over its base field 2351 2352 Unfortunately, the relative number field is not a unique parent:: 2353 2354 sage: O.ambient() is K 2355 False 2356 sage: O.ambient() == K 2357 True 2358 2359 """ 942 2360 rank = 3 943 2361 944 def __init__(self, poly, name, elt=None, embedding=None): 2362 def __init__(self, polys, names, embeddings, cyclotomic=None): 2363 """ 2364 INPUT: 2365 2366 - ``polys``: a list of polynomials 2367 - ``names``: a list of strings of the same length as the 2368 list ``polys`` 2369 - ``embeddings``: a list of approximate complex values, 2370 determining an embedding of the generators into the 2371 complex field, or ``None`` for each generator whose 2372 embedding is not prescribed. 2373 - ``cyclotomic``: optional integer. If it is provided, 2374 application of the functor to the rational field yields 2375 a cyclotomic field, rather than just a number field. 2376 2377 REMARK: 2378 2379 Currently, an embedding can only be provided for the last 2380 generator, and only when the construction functor is applied 2381 to the rational field. There will be no error when constructing 2382 the functor, but when applying it. 2383 2384 TESTS:: 2385 2386 sage: from sage.categories.pushout import AlgebraicExtensionFunctor 2387 sage: P.<x> = ZZ[] 2388 sage: F1 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [None]) 2389 sage: F2 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [0]) 2390 sage: F1==F2 2391 False 2392 sage: F1(QQ) 2393 Number Field in a with defining polynomial x^3 - x^2 + 1 2394 sage: F1(QQ).coerce_embedding() 2395 sage: F2(QQ).coerce_embedding() 2396 Generic morphism: 2397 From: Number Field in a with defining polynomial x^3 - x^2 + 1 2398 To: Real Lazy Field 2399 Defn: a -> -0.7548776662466928? 2400 sage: F1(QQ)==F2(QQ) 2401 False 2402 sage: F1(GF(5)) 2403 Univariate Quotient Polynomial Ring in a over Finite Field of size 5 with modulus a^3 + 4*a^2 + 1 2404 sage: F2(GF(5)) 2405 Traceback (most recent call last): 2406 ... 2407 NotImplementedError: ring extension with prescripted embedding is not implemented 2408 2409 When applying a number field constructor to the ring of 2410 integers, an order (not necessarily maximal) of that field is 2411 returned, similar to the behaviour of ``ZZ.extension``:: 2412 2413 sage: F1(ZZ) 2414 Order in Number Field in a with defining polynomial x^3 - x^2 + 1 2415 2416 The cyclotomic fields form a special case of number fields 2417 with prescribed embeddings:: 2418 2419 sage: C = CyclotomicField(8) 2420 sage: F,R = C.construction() 2421 sage: F 2422 AlgebraicExtensionFunctor 2423 sage: R 2424 Rational Field 2425 sage: F(R) 2426 Cyclotomic Field of order 8 and degree 4 2427 sage: F(ZZ) 2428 Maximal Order in Cyclotomic Field of order 8 and degree 4 2429 2430 """ 945 2431 Functor.__init__(self, Rings(), Rings()) 946 self.poly = poly 947 self.name = name 948 self.elt = elt 949 self.embedding = embedding 2432 if not (isinstance(polys,(list,tuple)) and isinstance(names,(list,tuple)) and isinstance(embeddings,(list,tuple))): 2433 raise ValueError, "Arguments must be lists or tuples" 2434 if not (len(names)==len(polys)==len(embeddings)): 2435 raise ValueError, "The three arguments must be of the same length" 2436 self.polys = list(polys) 2437 self.names = list(names) 2438 self.embeddings = list(embeddings) 2439 self.cyclotomic = int(cyclotomic) if cyclotomic is not None else None 2440 950 2441 def _apply_functor(self, R): 951 return R.extension(self.poly, self.name, embedding=self.embedding) 2442 """ 2443 Apply the functor to an object of ``self``'s domain. 2444 2445 TESTS:: 2446 2447 sage: K.<a>=NumberField(x^3+x^2+1) 2448 sage: F = K.construction()[0] 2449 sage: F(ZZ) # indirect doctest 2450 Order in Number Field in a with defining polynomial x^3 + x^2 + 1 2451 sage: F(ZZ['t']) # indirect doctest 2452 Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1 2453 sage: F(RR) # indirect doctest 2454 Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 2455 """ 2456 from sage.all import QQ, ZZ, CyclotomicField 2457 if self.cyclotomic: 2458 if R==QQ: 2459 return CyclotomicField(self.cyclotomic) 2460 if R==ZZ: 2461 return CyclotomicField(self.cyclotomic).maximal_order() 2462 if len(self.polys) == 1: 2463 return R.extension(self.polys[0], self.names[0], embedding=self.embeddings[0]) 2464 return R.extension(self.polys, self.names, embedding=self.embeddings) 2465 952 2466 def __cmp__(self, other): 2467 """ 2468 TEST:: 2469 2470 sage: K.<a>=NumberField(x^3+x^2+1) 2471 sage: F = K.construction()[0] 2472 sage: F == loads(dumps(F)) 2473 True 2474 """ 953 2475 c = cmp(type(self), type(other)) 954 2476 if c == 0: 955 c = cmp(self.poly , other.poly)2477 c = cmp(self.polys, other.polys) 956 2478 if c == 0: 957 c = cmp(self.embedding , other.embedding)2479 c = cmp(self.embeddings, other.embeddings) 958 2480 return c 959 2481 2482 def merge(self,other): 2483 """ 2484 Merging with another :class:`AlgebraicExtensionFunctor`. 2485 2486 INPUT: 2487 2488 ``other`` -- Construction Functor. 2489 2490 OUTPUT: 2491 2492 - If ``self==other``, ``self`` is returned. 2493 - If ``self`` and ``other`` are simple extensions 2494 and both provide an embedding, then it is tested 2495 whether one of the number fields provided by 2496 the functors coerces into the other; the functor 2497 associated with the target of the coercion is 2498 returned. Otherwise, the construction functor 2499 associated with the pushout of the codomains 2500 of the two embeddings is returned, provided that 2501 it is a number field. 2502 - Otherwise, None is returned. 2503 2504 REMARK: 2505 2506 Algebraic extension with embeddings currently only 2507 works when applied to the rational field. This is 2508 why we use the admittedly strange rule above for 2509 merging. 2510 2511 TESTS:: 2512 2513 sage: P.<x> = QQ[] 2514 sage: L.<b> = NumberField(x^8-x^4+1, embedding=CDF.0) 2515 sage: M1.<c1> = NumberField(x^2+x+1, embedding=b^4-1) 2516 sage: M2.<c2> = NumberField(x^2+1, embedding=-b^6) 2517 sage: M1.coerce_map_from(M2) 2518 sage: M2.coerce_map_from(M1) 2519 sage: c1+c2; parent(c1+c2) #indirect doctest 2520 -b^6 + b^4 - 1 2521 Number Field in b with defining polynomial x^8 - x^4 + 1 2522 sage: from sage.categories.pushout import pushout 2523 sage: pushout(M1['x'],M2['x']) 2524 Univariate Polynomial Ring in x over Number Field in b with defining polynomial x^8 - x^4 + 1 2525 2526 In the previous example, the number field ``L`` becomes the pushout 2527 of ``M1`` and ``M2`` since both are provided with an embedding into 2528 ``L``, *and* since ``L`` is a number field. If two number fields 2529 are embedded into a field that is not a numberfield, no merging 2530 occurs:: 2531 2532 sage: K.<a> = NumberField(x^3-2, embedding=CDF(1/2*I*2^(1/3)*sqrt(3) - 1/2*2^(1/3))) 2533 sage: L.<b> = NumberField(x^6-2, embedding=1.1) 2534 sage: L.coerce_map_from(K) 2535 sage: K.coerce_map_from(L) 2536 sage: pushout(K,L) 2537 Traceback (most recent call last): 2538 ... 2539 CoercionException: ('Ambiguous Base Extension', Number Field in a with defining polynomial x^3 - 2, Number Field in b with defining polynomial x^6 - 2) 2540 2541 """ 2542 if not isinstance(other,AlgebraicExtensionFunctor): 2543 return None 2544 if self == other: 2545 return self 2546 # This method is supposed to be used in pushout(), 2547 # *after* expanding the functors. Hence, we can 2548 # assume that both functors have a single variable. 2549 # But for being on the safe side...: 2550 if len(self.names)!=1 or len(other.names)!=1: 2551 return None 2552 ## We don't accept a forgetful coercion, since, together 2553 ## with bidirectional coercions between two embedded 2554 ## number fields, it would yield to contradictions in 2555 ## the coercion system. 2556 # if self.polys==other.polys and self.names==other.names: 2557 # # We have a forgetful functor: 2558 # if self.embeddings==[None]: 2559 # return self 2560 # if other.embeddings==[None]: 2561 # return other 2562 # ... or we may use the given embeddings: 2563 if self.embeddings!=[None] and other.embeddings!=[None]: 2564 from sage.all import QQ 2565 KS = self(QQ) 2566 KO = other(QQ) 2567 if KS.has_coerce_map_from(KO): 2568 return self 2569 if KO.has_coerce_map_from(KS): 2570 return other 2571 # nothing else helps, hence, we move to the pushout of the codomains of the embeddings 2572 try: 2573 P = pushout(self.embeddings[0].parent(), other.embeddings[0].parent()) 2574 from sage.rings.number_field.number_field import is_NumberField 2575 if is_NumberField(P): 2576 return P.construction()[0] 2577 except CoercionException: 2578 return None 2579 2580 def __mul__(self, other): 2581 """ 2582 Compose construction functors to a composit construction functor, unless one of them is the identity. 2583 2584 NOTE: 2585 2586 The product is in functorial notation, i.e., when applying the product to an object 2587 then the second factor is applied first. 2588 2589 TESTS:: 2590 2591 sage: P.<x> = QQ[] 2592 sage: K.<a> = NumberField(x^3-5,embedding=0) 2593 sage: L.<b> = K.extension(x^2+a) 2594 sage: F,R = L.construction() 2595 sage: prod(F.expand())(R) == L #indirect doctest 2596 True 2597 2598 """ 2599 if isinstance(other,IdentityConstructionFunctor): 2600 return self 2601 if isinstance(other, AlgebraicExtensionFunctor): 2602 if set(self.names).intersection(other.names): 2603 raise CoercionException, "Overlapping names (%s,%s)" % (self.names, other.names) 2604 return AlgebraicExtensionFunctor(self.polys+other.polys, self.names+other.names, self.embeddings+other.embeddings) 2605 elif isinstance(other, CompositeConstructionFunctor) \ 2606 and isinstance(other.all[-1], AlgebraicExtensionFunctor): 2607 return CompositeConstructionFunctor(other.all[:-1], self * other.all[-1]) 2608 else: 2609 return CompositeConstructionFunctor(other, self) 2610 2611 def expand(self): 2612 """ 2613 Decompose the functor `F` into sub-functors, whose product returns `F`. 2614 2615 EXAMPLES:: 2616 2617 sage: P.<x> = QQ[] 2618 sage: K.<a> = NumberField(x^3-5,embedding=0) 2619 sage: L.<b> = K.extension(x^2+a) 2620 sage: F,R = L.construction() 2621 sage: prod(F.expand())(R) == L 2622 True 2623 sage: K = NumberField([x^2-2, x^2-3],'a') 2624 sage: F, R = K.construction() 2625 sage: F 2626 AlgebraicExtensionFunctor 2627 sage: L = F.expand(); L 2628 [AlgebraicExtensionFunctor, AlgebraicExtensionFunctor] 2629 sage: L[-1](QQ) 2630 Number Field in a1 with defining polynomial x^2 - 3 2631 """ 2632 if len(self.polys)==1: 2633 return [self] 2634 return [AlgebraicExtensionFunctor([self.polys[i]], [self.names[i]], [self.embeddings[i]]) for i in range(len(self.polys))] 2635 960 2636 class AlgebraicClosureFunctor(ConstructionFunctor): 961 2637 """ 2638 Algebraic Closure. 2639 2640 EXAMPLE:: 2641 2642 sage: F = CDF.construction()[0] 2643 sage: F(QQ) 2644 Algebraic Field 2645 sage: F(RR) 2646 Complex Field with 53 bits of precision 2647 sage: F(F(QQ)) is F(QQ) 2648 True 2649 2650 """ 962 2651 rank = 3 963 2652 964 2653 def __init__(self): 2654 """ 2655 TEST:: 2656 2657 sage: from sage.categories.pushout import AlgebraicClosureFunctor 2658 sage: F = AlgebraicClosureFunctor() 2659 sage: F(QQ) 2660 Algebraic Field 2661 sage: F(RR) 2662 Complex Field with 53 bits of precision 2663 sage: F == loads(dumps(F)) 2664 True 2665 2666 """ 965 2667 Functor.__init__(self, Rings(), Rings()) 2668 966 2669 def _apply_functor(self, R): 2670 """ 2671 Apply the functor to an object of ``self``'s domain. 2672 2673 TEST:: 2674 2675 sage: F = CDF.construction()[0] 2676 sage: F(QQ) # indirect doctest 2677 Algebraic Field 2678 """ 2679 if hasattr(R,'construction'): 2680 c = R.construction() 2681 if c is not None and c[0]==self: 2682 return R 967 2683 return R.algebraic_closure() 2684 968 2685 def merge(self, other): 969 # Algebraic Closure subsumes Algebraic Extension 970 return self 2686 """ 2687 Mathematically, Algebraic Closure subsumes Algebraic Extension. 2688 However, it seems that people do want to work with algebraic 2689 extensions of ``RR``. Therefore, we dont merge with algebraic extension. 2690 2691 TEST:: 2692 2693 sage: K.<a>=NumberField(x^3+x^2+1) 2694 sage: CDF.construction()[0].merge(K.construction()[0]) is None 2695 True 2696 sage: CDF.construction()[0].merge(CDF.construction()[0]) 2697 AlgebraicClosureFunctor 2698 2699 """ 2700 if self==other: 2701 return self 2702 return None 2703 # Mathematically, Algebraic Closure subsumes Algebraic Extension. 2704 # However, it seems that people do want to work with 2705 # algebraic extensions of RR (namely RR/poly*RR). So, we don't do: 2706 # if isinstance(other,AlgebraicExtensionFunctor): 2707 # return self 971 2708 972 2709 class PermutationGroupFunctor(ConstructionFunctor): 973 2710 … … 976 2713 def __init__(self, gens): 977 2714 """ 978 2715 EXAMPLES:: 979 2716 980 2717 sage: from sage.categories.pushout import PermutationGroupFunctor 981 2718 sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])]); PF 982 2719 PermutationGroupFunctor[(1,2)] … … 987 2724 def __repr__(self): 988 2725 """ 989 2726 EXAMPLES:: 990 2727 991 2728 sage: P1 = PermutationGroup([[(1,2)]]) 992 2729 sage: PF, P = P1.construction() 993 2730 sage: PF 994 PermutationGroupFunctor[(1,2)] 2731 PermutationGroupFunctor[(1,2)] 995 2732 """ 996 2733 return "PermutationGroupFunctor%s"%self.gens() 997 2734 998 def _ apply_functor(self, R):2735 def __call__(self, R): 999 2736 """ 1000 2737 EXAMPLES:: 1001 2738 … … 1017 2754 [(1,2)] 1018 2755 """ 1019 2756 return self._gens 1020 2757 1021 2758 def merge(self, other): 1022 2759 """ 2760 Merge ``self`` with another construction functor, or return None. 2761 1023 2762 EXAMPLES:: 1024 2763 1025 2764 sage: P1 = PermutationGroup([[(1,2)]]) 1026 2765 sage: PF1, P = P1.construction() 1027 2766 sage: P2 = PermutationGroup([[(1,3)]]) … … 1032 2771 if self.__class__ != other.__class__: 1033 2772 return None 1034 2773 return PermutationGroupFunctor(self.gens() + other.gens()) 1035 1036 def BlackBoxConstructionFunctor(ConstructionFunctor): 1037 2774 2775 class BlackBoxConstructionFunctor(ConstructionFunctor): 2776 """ 2777 Construction functor obtained from any callable object. 2778 2779 EXAMPLES:: 2780 2781 sage: from sage.categories.pushout import BlackBoxConstructionFunctor 2782 sage: FG = BlackBoxConstructionFunctor(gap) 2783 sage: FS = BlackBoxConstructionFunctor(singular) 2784 sage: FG 2785 BlackBoxConstructionFunctor 2786 sage: FG(ZZ) 2787 Integers 2788 sage: FG(ZZ).parent() 2789 Gap 2790 sage: FS(QQ['t']) 2791 // characteristic : 0 2792 // number of vars : 1 2793 // block 1 : ordering lp 2794 // : names t 2795 // block 2 : ordering C 2796 sage: FG == FS 2797 False 2798 sage: FG == loads(dumps(FG)) 2799 True 2800 """ 1038 2801 rank = 100 1039 2802 1040 2803 def __init__(self, box): 2804 """ 2805 TESTS:: 2806 sage: from sage.categories.pushout import BlackBoxConstructionFunctor 2807 sage: FG = BlackBoxConstructionFunctor(gap) 2808 sage: FM = BlackBoxConstructionFunctor(maxima) 2809 sage: FM == FG 2810 False 2811 sage: FM == loads(dumps(FM)) 2812 True 2813 """ 2814 ConstructionFunctor.__init__(self,Objects(),Objects()) 1041 2815 if not callable(box): 1042 2816 raise TypeError, "input must be callable" 1043 2817 self.box = box 2818 1044 2819 def _apply_functor(self, R): 1045 return box(R) 2820 """ 2821 Apply the functor to an object of ``self``'s domain. 2822 2823 TESTS:: 2824 2825 sage: from sage.categories.pushout import BlackBoxConstructionFunctor 2826 sage: f = lambda x: x^2 2827 sage: F = BlackBoxConstructionFunctor(f) 2828 sage: F(ZZ) # indirect doctest 2829 Ambient free module of rank 2 over the principal ideal domain Integer Ring 2830 2831 """ 2832 return self.box(R) 2833 1046 2834 def __cmp__(self, other): 1047 return self.box == other.box 1048 1049 2835 """ 2836 TESTS:: 2837 sage: from sage.categories.pushout import BlackBoxConstructionFunctor 2838 sage: FG = BlackBoxConstructionFunctor(gap) 2839 sage: FM = BlackBoxConstructionFunctor(maxima) 2840 sage: FM == FG # indirect doctest 2841 False 2842 sage: FM == loads(dumps(FM)) 2843 True 2844 """ 2845 c = cmp(type(self), type(other)) 2846 if c == 0: 2847 c = cmp(self.box, other.box) 2848 #return self.box == other.box 2849 return c 2850 1050 2851 def pushout(R, S): 1051 """2852 r""" 1052 2853 Given a pair of Objects R and S, try and construct a 1053 2854 reasonable object $Y$ and return maps such that 1054 2855 canonically $R \leftarrow Y \rightarrow S$. 1055 2856 1056 ALGORITHM: 1057 This incorporates the idea of functors discussed Sage Days 4. 1058 Every object $R$ can be viewed as an initial object and 1059 a series of functors (e.g. polynomial, quotient, extension, 1060 completion, vector/matrix, etc.). Call the series of 1061 increasingly-simple rings (with the associated functors) 1062 the "tower" of $R$. The \code{construction} method is used to 1063 create the tower. 1064 1065 Given two objects $R$ and $S$, try and find a common initial 1066 object $Z$. If the towers of $R$ and $S$ meet, let $Z$ be their 1067 join. Otherwise, see if the top of one coerces naturally into 1068 the other. 1069 1070 Now we have an initial object and two \emph{ordered} lists of 1071 functors to apply. We wish to merge these in an unambiguous order, 1072 popping elements off the top of one or the other tower as we 1073 apply them to $Z$. 1074 1075 - If the functors are distinct types, there is an absolute ordering 1076 given by the rank attribute. Use this. 1077 - Otherwise: 1078 - If the tops are equal, we (try to) merge them. 1079 - If \emph{exactly} one occurs lower in the other tower 1080 we may unambiguously apply the other (hoping for a later merge). 1081 - If the tops commute, we can apply either first. 1082 - Otherwise fail due to ambiguity. 2857 ALGORITHM: 2858 2859 This incorporates the idea of functors discussed Sage Days 4. 2860 Every object $R$ can be viewed as an initial object and 2861 a series of functors (e.g. polynomial, quotient, extension, 2862 completion, vector/matrix, etc.). Call the series of 2863 increasingly-simple rings (with the associated functors) 2864 the "tower" of $R$. The \code{construction} method is used to 2865 create the tower. 2866 2867 Given two objects $R$ and $S$, try and find a common initial 2868 object $Z$. If the towers of $R$ and $S$ meet, let $Z$ be their 2869 join. Otherwise, see if the top of one coerces naturally into 2870 the other. 2871 2872 Now we have an initial object and two \emph{ordered} lists of 2873 functors to apply. We wish to merge these in an unambiguous order, 2874 popping elements off the top of one or the other tower as we 2875 apply them to $Z$. 2876 2877 - If the functors are distinct types, there is an absolute ordering 2878 given by the rank attribute. Use this. 2879 2880 - Otherwise: 2881 2882 - If the tops are equal, we (try to) merge them. 2883 2884 - If \emph{exactly} one occurs lower in the other tower 2885 we may unambiguously apply the other (hoping for a later merge). 2886 2887 - If the tops commute, we can apply either first. 2888 2889 - Otherwise fail due to ambiguity. 1083 2890 1084 2891 EXAMPLES: 1085 Here our "towers" are $R = Complete_7(Frac(\Z)$ and $Frac(Poly_x(\Z))$, which give us $Frac(Poly_x(Complete_7(Frac(\Z)))$ 1086 sage: from sage.categories.pushout import pushout 1087 sage: pushout(Qp(7), Frac(ZZ['x'])) 1088 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 1089 1090 Note we get the same thing with 1091 sage: pushout(Zp(7), Frac(QQ['x'])) 1092 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 1093 sage: pushout(Zp(7)['x'], Frac(QQ['x'])) 1094 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 1095 1096 Note that polynomial variable ordering must be unambiguously determined. 1097 sage: pushout(ZZ['x,y,z'], QQ['w,z,t']) 1098 Traceback (most recent call last): 1099 ... 1100 CoercionException: ('Ambiguous Base Extension', Multivariate Polynomial Ring in x, y, z over Integer Ring, Multivariate Polynomial Ring in w, z, t over Rational Field) 1101 sage: pushout(ZZ['x,y,z'], QQ['w,x,z,t']) 1102 Multivariate Polynomial Ring in w, x, y, z, t over Rational Field 1103 1104 Some other examples 1105 sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z']) 1106 Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20 1107 sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y']) 1108 Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring 1109 sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x'])) 1110 Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field 1111 sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) 1112 Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring 1113 sage: pushout(QQ['x,y'], ZZ[['x']]) 1114 Univariate Polynomial Ring in y over Power Series Ring in x over Rational Field 1115 sage: pushout(Frac(ZZ['x']), QQ[['x']]) 1116 Laurent Series Ring in x over Rational Field 1117 1118 AUTHORS: 1119 -- Robert Bradshaw 2892 2893 Here our "towers" are $R = Complete_7(Frac(\ZZ)$ and $Frac(Poly_x(\ZZ))$, 2894 which give us $Frac(Poly_x(Complete_7(Frac(\ZZ)))$:: 2895 2896 sage: from sage.categories.pushout import pushout 2897 sage: pushout(Qp(7), Frac(ZZ['x'])) 2898 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 2899 2900 Note we get the same thing with 2901 :: 2902 2903 sage: pushout(Zp(7), Frac(QQ['x'])) 2904 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 2905 sage: pushout(Zp(7)['x'], Frac(QQ['x'])) 2906 Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20 2907 2908 Note that polynomial variable ordering must be unambiguously determined. 2909 :: 2910 2911 sage: pushout(ZZ['x,y,z'], QQ['w,z,t']) 2912 Traceback (most recent call last): 2913 ... 2914 CoercionException: ('Ambiguous Base Extension', Multivariate Polynomial Ring in x, y, z over Integer Ring, Multivariate Polynomial Ring in w, z, t over Rational Field) 2915 sage: pushout(ZZ['x,y,z'], QQ['w,x,z,t']) 2916 Multivariate Polynomial Ring in w, x, y, z, t over Rational Field 2917 2918 Some other examples:: 2919 2920 sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z']) 2921 Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20 2922 sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y']) 2923 Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring 2924 sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x'])) 2925 Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field 2926 sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3)) 2927 Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring 2928 sage: pushout(QQ['x,y'], ZZ[['x']]) 2929 Univariate Polynomial Ring in y over Power Series Ring in x over Rational Field 2930 sage: pushout(Frac(ZZ['x']), QQ[['x']]) 2931 Laurent Series Ring in x over Rational Field 2932 2933 AUTHORS: 2934 2935 -- Robert Bradshaw 1120 2936 """ 1121 2937 if R is S or R == S: 1122 2938 return R … … 1218 3034 elif Sc[-1] in Rc: 1219 3035 all = Rc.pop() * all 1220 3036 # If, perchance, the two functors commute, then we may do them in any order. 1221 elif Rc[-1].commutes(Sc[-1]) :3037 elif Rc[-1].commutes(Sc[-1]) or Sc[-1].commutes(Rc[-1]): 1222 3038 all = Sc.pop() * Rc.pop() * all 1223 3039 else: 1224 3040 # try and merge (default merge is failure for unequal functors) … … 1244 3060 1245 3061 1246 3062 def pushout_lattice(R, S): 1247 """1248 Given a pair of Objects R and S, try and construct a3063 r""" 3064 Given a pair of Objects $R$ and $S$, try and construct a 1249 3065 reasonable object $Y$ and return maps such that 1250 3066 canonically $R \leftarrow Y \rightarrow S$. 1251 3067 1252 ALGORITHM: 1253 This is based on the model that arose from much discussion at Sage Days 4. 1254 Going up the tower of constructions of $R$ and $S$ (e.g. the reals 1255 come from the rationals come from the integers) try and find a 1256 common parent, and then try and fill in a lattice with these 1257 two towers as sides with the top as the common ancestor and 1258 the bottom will be the desired ring. 3068 ALGORITHM: 3069 3070 This is based on the model that arose from much discussion at Sage Days 4. 3071 Going up the tower of constructions of $R$ and $S$ (e.g. the reals 3072 come from the rationals come from the integers) try and find a 3073 common parent, and then try and fill in a lattice with these 3074 two towers as sides with the top as the common ancestor and 3075 the bottom will be the desired ring. 3076 3077 See the code for a specific worked-out example. 1259 3078 1260 See the code for a specific worked-out example. 1261 1262 EXAMPLES: 3079 EXAMPLES:: 3080 1263 3081 sage: from sage.categories.pushout import pushout_lattice 1264 3082 sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) 1265 3083 sage: A.codomain() … … 1271 3089 Identity endomorphism of Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring 1272 3090 1273 3091 AUTHOR: 1274 -- Robert Bradshaw 3092 3093 - Robert Bradshaw 3094 1275 3095 """ 1276 3096 R_tower = construction_tower(R) 1277 3097 S_tower = construction_tower(S) … … 1357 3177 lattice[i+1,j+1] = Rc[i](lattice[i,j+1]) 1358 3178 Sc[j] = None # force us to use pre-applied Sc[i] 1359 3179 except (AttributeError, NameError): 1360 print i, j 1361 pp(lattice) 3180 # print i, j 3181 # pp(lattice) 3182 for i in range(100): 3183 for j in range(100): 3184 try: 3185 R = lattice[i,j] 3186 print i, j, R 3187 except KeyError: 3188 break 1362 3189 raise CoercionException, "%s does not support %s" % (lattice[i,j], 'F') 1363 3190 1364 3191 # If we are successful, we should have something that looks like this. … … 1397 3224 return R_map, S_map 1398 3225 1399 3226 1400 def pp(lattice): 3227 ## def pp(lattice): 3228 ## """ 3229 ## Used in debugging to print the current lattice. 3230 ## """ 3231 ## for i in range(100): 3232 ## for j in range(100): 3233 ## try: 3234 ## R = lattice[i,j] 3235 ## print i, j, R 3236 ## except KeyError: 3237 ## break 3238 3239 def construction_tower(R): 1401 3240 """ 1402 Used in debugging to print the current lattice. 3241 An auxiliary function that is used in :func:`pushout` and :func:`pushout_lattice`. 3242 3243 INPUT: 3244 3245 An object 3246 3247 OUTPUT: 3248 3249 A constructive description of the object from scratch, by a list of pairs 3250 of a construction functor and an object to which the construction functor 3251 is to be applied. The first pair is formed by ``None`` and the given object. 3252 3253 EXAMPLE:: 3254 3255 sage: from sage.categories.pushout import construction_tower 3256 sage: construction_tower(MatrixSpace(FractionField(QQ['t']),2)) 3257 [(None, Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in t over Rational Field), (MatrixFunctor, Fraction Field of Univariate Polynomial Ring in t over Rational Field), (FractionField, Univariate Polynomial Ring in t over Rational Field), (Poly[t], Rational Field), (FractionField, Integer Ring)] 3258 1403 3259 """ 1404 for i in range(100):1405 for j in range(100):1406 try:1407 R = lattice[i,j]1408 print i, j, R1409 except KeyError:1410 break1411 1412 def construction_tower(R):1413 3260 tower = [(None, R)] 1414 3261 c = R.construction() 1415 3262 while c is not None: … … 1423 3270 1424 3271 1425 3272 def type_to_parent(P): 3273 """ 3274 An auxiliary function that is used in :func:`pushout`. 3275 3276 INPUT: 3277 3278 A type 3279 3280 OUTPUT: 3281 3282 A Sage parent structure corresponding to the given type 3283 3284 TEST:: 3285 3286 sage: from sage.categories.pushout import type_to_parent 3287 sage: type_to_parent(int) 3288 Integer Ring 3289 sage: type_to_parent(float) 3290 Real Double Field 3291 sage: type_to_parent(complex) 3292 Complex Double Field 3293 sage: type_to_parent(list) 3294 Traceback (most recent call last): 3295 ... 3296 TypeError: Not a scalar type. 3297 """ 1426 3298 import sage.rings.all 1427 3299 if P in [int, long]: 1428 3300 return sage.rings.all.ZZ -
sage/groups/perm_gps/permgroup.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/groups/perm_gps/permgroup.py
a b 341 341 if gens is None: 342 342 self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group) 343 343 self._gens = self._gens_from_gap() 344 return 344 return None 345 345 346 346 gens = [self._element_class()(x, check=False).list() for x in gens] 347 347 self._deg = max([0]+[max(g) for g in gens]) … … 1111 1111 EXAMPLES:: 1112 1112 1113 1113 sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]]) 1114 sage: G.random_element() 1115 (1,2)(4,5) 1114 sage: a = G.random_element() 1115 sage: a in G 1116 True 1117 sage: a.parent() is G 1118 True 1119 sage: a^6 1120 () 1116 1121 """ 1117 1122 current_randstate().set_seed_gap() 1118 1123 -
sage/matrix/matrix0.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/matrix/matrix0.pyx
a b 3769 3769 [ 6 11] 3770 3770 sage: parent(d) 3771 3771 Full MatrixSpace of 2 by 2 dense matrices over Rational Field 3772 sage: d = b *c; d3772 sage: d = b+c 3773 3773 Traceback (most recent call last): 3774 3774 ... 3775 TypeError: unsupported operand parent(s) for ' *': 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field'3776 sage: d = b *c.change_ring(GF(7)); d3777 [ 2 3]3778 [ 6 4]3775 TypeError: unsupported operand parent(s) for '+': 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field' 3776 sage: d = b+c.change_ring(GF(7)); d 3777 [0 2] 3778 [4 6] 3779 3779 3780 3780 EXAMPLE of matrix times matrix where one matrix is sparse and the 3781 3781 other is dense (in such mixed cases, the result is always dense):: -
sage/modules/free_module.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/modules/free_module.py
a b 136 136 137 137 - Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``. 138 138 139 - Simon King (2010-12): Trac #8800: Fixing a bug in ``denominator()``. 140 139 141 """ 140 142 141 143 ########################################################################### … … 349 351 if not isinstance(sparse,bool): 350 352 raise TypeError, "Argument sparse (= %s) must be True or False" % sparse 351 353 352 if not base_ring.is_commutative():354 if not (hasattr(base_ring,'is_commutative') and base_ring.is_commutative()): 353 355 raise TypeError, "The base_ring must be a commutative ring." 354 356 355 357 if not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class): … … 596 598 (VectorFunctor, Multivariate Polynomial Ring in x0, x1, x2 over Rational Field) 597 599 """ 598 600 from sage.categories.pushout import VectorFunctor 601 if hasattr(self,'_inner_product_matrix'): 602 return VectorFunctor(self.rank(), self.is_sparse(),self.inner_product_matrix()), self.base_ring() 599 603 return VectorFunctor(self.rank(), self.is_sparse()), self.base_ring() 600 604 601 605 # FIXME: what's the level of generality of FreeModuleHomspace? … … 4891 4895 4892 4896 EXAMPLES:: 4893 4897 4894 sage: V = QQ^3 4895 sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ) 4896 sage: L 4897 Free module of degree 3 and rank 2 over Integer Ring 4898 Echelon basis matrix: 4899 [ 1/5 19/6 37/3] 4900 [ 0 23/6 46/3] 4898 sage: V = QQ^3 4899 sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ) 4900 sage: L 4901 Free module of degree 3 and rank 2 over Integer Ring 4902 Echelon basis matrix: 4903 [ 1/5 19/6 37/3] 4904 [ 0 23/6 46/3] 4901 4905 sage: L._denominator(L.echelonized_basis_matrix().list()) 4902 4906 30 4907 4903 4908 """ 4904 4909 if len(B) == 0: 4905 4910 return 1 4906 d = sage.rings.integer.Integer( B[0].denominator())4911 d = sage.rings.integer.Integer((hasattr(B[0],'denominator') and B[0].denominator()) or 1) 4907 4912 for x in B[1:]: 4908 d = d.lcm( x.denominator())4913 d = d.lcm((hasattr(x,'denominator') and x.denominator()) or 1) 4909 4914 return d 4910 4915 4911 4916 def _repr_(self): -
sage/modules/free_module_element.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/modules/free_module_element.pyx
a b 1498 1498 70 1499 1499 sage: 2*5*7 1500 1500 70 1501 1502 TESTS: 1503 1504 The following was fixed in trac ticket #8800:: 1505 1506 sage: M = GF(5)^3 1507 sage: v = M((4,0,2)) 1508 sage: v.denominator() 1509 1 1510 1501 1511 """ 1502 1512 R = self.base_ring() 1503 1513 if self.degree() == 0: return 1 1504 1514 x = self.list() 1505 d = x[0].denominator() 1515 # it may be that the marks do not have a denominator! 1516 d = x[0].denominator() if hasattr(x[0],'denominator') else 1 1506 1517 for y in x: 1507 d = d.lcm(y.denominator()) 1518 d = d.lcm(y.denominator()) if hasattr(y,'denominator') else d 1508 1519 return d 1509 1520 1510 1521 def dict(self, copy=True): -
sage/rings/integer_ring.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/integer_ring.pyx
a b 713 713 Relative Order in Number Field in a with defining polynomial x^2 + 1 over its base field 714 714 """ 715 715 if embedding is not None: 716 raise NotImplementedError 716 if embedding!=[None]*len(embedding): 717 raise NotImplementedError 717 718 from sage.rings.number_field.order import EquationOrder 718 719 return EquationOrder(poly, names) 719 720 -
sage/rings/number_field/number_field.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field.py
a b 369 369 To: Number Field in b with defining polynomial x^6 - x^2 + 1/10 370 370 Defn: a -> b^2 371 371 372 The ``QuadraticField`` and 373 ``CyclotomicField`` constructors create an embedding by 374 default unless otherwise specified. 372 The ``QuadraticField`` and ``CyclotomicField`` constructors 373 create an embedding by default unless otherwise specified. 375 374 376 375 :: 377 376 … … 419 418 sage: W.<a> = NumberField(x^2 + 1); W 420 419 Number Field in a with defining polynomial x^2 + 1 over its base field 421 420 421 The following has been fixed in trac ticket #8800:: 422 423 sage: P.<x> = QQ[] 424 sage: K.<a> = NumberField(x^3-5,embedding=0) 425 sage: L.<b> = K.extension(x^2+a) 426 sage: F, R = L.construction() 427 sage: F(R) == L # indirect doctest 428 True 429 422 430 """ 423 431 if name is None and names is None: 424 432 raise TypeError, "You must specify the name of the generator." … … 426 434 name = names 427 435 428 436 if isinstance(polynomial, (list, tuple)): 429 return NumberFieldTower(polynomial, name )437 return NumberFieldTower(polynomial, name, embeddings=embedding) 430 438 431 439 name = sage.structure.parent_gens.normalize_names(1, name) 432 440 … … 1024 1032 embedding = number_field_morphisms.create_embedding_from_approx(self, embedding) 1025 1033 self._populate_coercion_lists_(embedding=embedding) 1026 1034 1035 def construction(self): 1036 r""" 1037 Construction of self 1038 1039 EXAMPLE:: 1040 1041 sage: K.<a>=NumberField(x^3+x^2+1,embedding=CC.gen()) 1042 sage: F,R = K.construction() 1043 sage: F 1044 AlgebraicExtensionFunctor 1045 sage: R 1046 Rational Field 1047 sage: F(R) == K 1048 True 1049 1050 Note that, if a number field is provided with an embedding, 1051 the construction functor applied to the rationals is not 1052 necessarily identic with the number field. The reason is 1053 that the construction functor uses a value for the embedding 1054 that is equivalent, but not necessarily equal, to the one 1055 provided in the definition of the number field:: 1056 1057 sage: F(R) is K 1058 False 1059 sage: F.embeddings 1060 [0.2327856159383841? + 0.7925519925154479?*I] 1061 1062 TEST:: 1063 1064 sage: K.<a> = NumberField(x^3+x+1) 1065 sage: R.<t> = ZZ[] 1066 sage: a+t # indirect doctest 1067 t + a 1068 sage: (a+t).parent() 1069 Univariate Polynomial Ring in t over Number Field in a with defining polynomial x^3 + x + 1 1070 1071 The construction works for non-absolute number fields as well:: 1072 1073 sage: K.<a,b,c>=NumberField([x^3+x^2+1,x^2+1,x^7+x+1]) 1074 sage: F,R = K.construction() 1075 sage: F(R) == K 1076 True 1077 1078 :: 1079 1080 sage: P.<x> = QQ[] 1081 sage: K.<a> = NumberField(x^3-5,embedding=0) 1082 sage: L.<b> = K.extension(x^2+a) 1083 sage: a*b 1084 a*b 1085 1086 """ 1087 from sage.categories.pushout import AlgebraicExtensionFunctor 1088 from sage.all import QQ 1089 if self.is_absolute(): 1090 return (AlgebraicExtensionFunctor([self.polynomial()], [self.variable_name()], [None if self.coerce_embedding() is None else self.coerce_embedding()(self.gen())]), QQ) 1091 names = self.variable_names() 1092 polys = [] 1093 embeddings = [] 1094 K = self 1095 while (1): 1096 if K.is_absolute(): 1097 break 1098 polys.append(K.relative_polynomial()) 1099 embeddings.append(None if K.coerce_embedding() is None else K.coerce_embedding()(self.gen())) 1100 K = K.base_field() 1101 polys.append(K.relative_polynomial()) 1102 embeddings.append(None if K.coerce_embedding() is None else K.coerce_embedding()(K.gen())) 1103 return (AlgebraicExtensionFunctor(polys, names, embeddings), QQ) 1104 1027 1105 def _element_constructor_(self, x): 1028 1106 r""" 1029 1107 Make x into an element of this number field, possibly not canonically. … … 4422 4500 ... 4423 4501 ValueError: Fractional ideal (5) is not a prime ideal 4424 4502 """ 4503 from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal 4504 if is_NumberFieldIdeal(prime) and prime.number_field() is not self: 4505 raise ValueError, "%s is not an ideal of %s"%(prime,self) 4425 4506 # This allows principal ideals to be specified using a generator: 4426 4507 try: 4427 4508 prime = self.ideal(prime) 4428 4509 except TypeError: 4429 4510 pass 4430 4511 4431 from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal4432 4512 if not is_NumberFieldIdeal(prime) or prime.number_field() is not self: 4433 4513 raise ValueError, "%s is not an ideal of %s"%(prime,self) 4434 4514 if check and not prime.is_prime(): … … 4880 4960 """ 4881 4961 Coerce a number field element x into this number field. 4882 4962 4883 In most cases this currently doesn't work (since it is 4884 barely implemented) -- it only works for constants. 4963 REMARK: 4964 4965 The name of this method was chosen for historical reasons. 4966 In fact, what it does is not a coercion but a conversion. 4885 4967 4886 4968 INPUT: 4887 x -- an element of some number field 4888 4889 EXAMPLES: 4969 4970 ``x`` -- an element of some number field 4971 4972 ASSUMPTION: 4973 4974 ``x`` should be an element of a number field whose underlying 4975 polynomial ring allows conversion into the polynomial ring of 4976 ``self``. 4977 4978 Note that it is only tested that there is a method 4979 ``x.polynomial()`` yielding an output that can be converted 4980 into ``self.polynomial_ring()``. 4981 4982 OUTPUT: 4983 4984 An element of ``self`` corresponding to ``x``. 4985 4986 EXAMPLES:: 4987 4890 4988 sage: K.<a> = NumberField(x^3 + 2) 4891 4989 sage: L.<b> = NumberField(x^2 + 1) 4892 4990 sage: K._coerce_from_other_number_field(L(2/3)) 4893 2/3 4894 """ 4895 f = x.polynomial() 4896 if f.degree() <= 0: 4897 return self._element_class(self, f[0]) 4898 # todo: more general coercion if embedding have been asserted 4899 raise TypeError, "Cannot coerce element into this number field" 4991 2/3 4992 4993 TESTS: 4994 4995 The following was fixed in trac ticket #8800:: 4996 4997 sage: P.<x> = QQ[] 4998 sage: K.<a> = NumberField(x^3-5,embedding=0) 4999 sage: L.<b> = K.extension(x^2+a) 5000 sage: F,R = L.construction() 5001 sage: F(R) == L #indirect doctest 5002 True 5003 5004 """ 5005 f = self.polynomial_ring()(x.polynomial()) 5006 return self._element_class(self, f) 4900 5007 4901 5008 def _coerce_non_number_field_element_in(self, x): 4902 5009 """ … … 4985 5092 4986 5093 def _coerce_map_from_(self, R): 4987 5094 """ 4988 Canonical coercion of x into self. 4989 4990 Currently integers, rationals, and this field itself coerce 4991 canonically into this field. 5095 Canonical coercion of a ring R into self. 5096 5097 Currently any ring coercing into the base ring canonically coerces 5098 into this field, as well as orders in any number field coercing into 5099 this field, and of course the field itself as well. 5100 5101 Two embedded number fields may mutually coerce into each other, if 5102 the pushout of the two ambient fields exists and if it is possible 5103 to construct an :class:`~sage.rings.number_field.number_field_morphisms.EmbeddedNumberFieldMorphism`. 4992 5104 4993 5105 EXAMPLES:: 4994 5106 … … 5004 5116 sage: S.coerce(y) is y 5005 5117 True 5006 5118 5007 Fields with embeddings into an ambient field coerce naturally. 5119 Fields with embeddings into an ambient field coerce naturally by the given embedding:: 5120 5008 5121 sage: CyclotomicField(15).coerce(CyclotomicField(5).0 - 17/3) 5009 5122 zeta15^3 - 17/3 5010 5123 sage: K.<a> = CyclotomicField(16) … … 5016 5129 To: Number Field in a with defining polynomial x^2 + 3 5017 5130 Defn: zeta3 -> 1/2*a - 1/2 5018 5131 5019 There are situations for which one might imagine canonical 5020 coercion could make sense (at least after fixing choices), but 5021 which aren't yet implemented: 5132 Two embedded number fields with mutual coercions (testing against a 5133 bug that was fixed in trac ticket #8800):: 5134 5135 sage: K.<r4> = NumberField(x^4-2) 5136 sage: L1.<r2_1> = NumberField(x^2-2, embedding = r4**2) 5137 sage: L2.<r2_2> = NumberField(x^2-2, embedding = -r4**2) 5138 sage: r2_1+r2_2 # indirect doctest 5139 0 5140 sage: (r2_1+r2_2).parent() is L1 5141 True 5142 sage: (r2_2+r2_1).parent() is L2 5143 True 5144 5145 Coercion of an order (testing against a bug that was fixed in 5146 trac ticket #8800):: 5147 5148 sage: K.has_coerce_map_from(L1) 5149 True 5150 sage: L1.has_coerce_map_from(K) 5151 False 5152 sage: K.has_coerce_map_from(L1.maximal_order()) 5153 True 5154 sage: L1.has_coerce_map_from(K.maximal_order()) 5155 False 5156 5157 There are situations for which one might imagine conversion 5158 could make sense (at least after fixing choices), but of course 5159 there will be no coercion from the Symbolic Ring to a Number Field:: 5160 5022 5161 sage: K.<a> = QuadraticField(2) 5023 5162 sage: K.coerce(sqrt(2)) 5024 5163 Traceback (most recent call last): 5025 5164 ... 5026 5165 TypeError: no canonical coercion from Symbolic Ring to Number Field in a with defining polynomial x^2 - 2 5027 5166 5028 TESTS: 5167 TESTS:: 5168 5029 5169 sage: K.<a> = NumberField(polygen(QQ)^3-2) 5030 5170 sage: type(K.coerce_map_from(QQ)) 5031 5171 <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'> 5032 5172 5033 Make sure we still get our optimized morphisms for special fields: 5173 Make sure we still get our optimized morphisms for special fields:: 5174 5034 5175 sage: K.<a> = NumberField(polygen(QQ)^2-2) 5035 5176 sage: type(K.coerce_map_from(QQ)) 5036 5177 <type 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'> 5178 5037 5179 """ 5038 5180 if R in [int, long, ZZ, QQ, self.base()]: 5039 5181 return self._generic_convert_map(R) 5040 5182 from sage.rings.number_field.order import is_NumberFieldOrder 5041 if is_NumberFieldOrder(R) and R.number_field().has_coerce_map_from(self):5183 if is_NumberFieldOrder(R) and self.has_coerce_map_from(R.number_field()): 5042 5184 return self._generic_convert_map(R) 5043 5185 if is_NumberField(R) and R != QQ: 5044 5186 if R.coerce_embedding() is not None: … … 5047 5189 from sage.categories.pushout import pushout 5048 5190 ambient_field = pushout(R.coerce_embedding().codomain(), self.coerce_embedding().codomain()) 5049 5191 if ambient_field is not None: 5192 try: 5193 # the original ambient field 5194 return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self, ambient_field) 5195 except ValueError: # no embedding found 5196 # there might be one in the alg. completion 5197 return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self, ambient_field.algebraic_closure() if hasattr(ambient_field,'algebraic_closure') else ambient_field) 5198 except (ValueError, TypeError, sage.structure.coerce_exceptions.CoercionException),msg: 5199 # no success with the pushout 5200 try: 5050 5201 return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self) 5051 except (TypeError, ValueError): 5052 pass 5202 except (TypeError, ValueError): 5203 pass 5204 else: 5205 # R is embedded, self isn't. So, we could only have 5206 # the forgetful coercion. But this yields to non-commuting 5207 # coercions, as was pointed out at ticket #8800 5208 return None 5053 5209 5054 5210 def _magma_init_(self, magma): 5055 5211 """ … … 6540 6696 """ 6541 6697 return NumberField_cyclotomic_v1, (self.__n, self.variable_name(), self.gen_embedding()) 6542 6698 6699 def construction(self): 6700 F,R = NumberField_generic.construction(self) 6701 F.cyclotomic = self.__n 6702 return F,R 6703 6543 6704 def _magma_init_(self, magma): 6544 6705 """ 6545 6706 Function returning a string to create this cyclotomic field in -
sage/rings/number_field/number_field_element.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_element.pyx
a b 4315 4315 ... 4316 4316 TypeError: Cannot coerce element into this number field 4317 4317 """ 4318 from sage.all import parent 4319 if not self.__K.has_coerce_map_from(parent(x)): 4320 raise TypeError, "Cannot coerce element into this number field" 4318 4321 return self.__W.coordinates(self.__to_V(self.__K(x))) 4319 4322 4320 4323 def __cmp__(self, other): -
sage/rings/number_field/number_field_ideal.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_ideal.py
a b 241 241 '\\left(17\\right)' 242 242 """ 243 243 return '\\left(%s\\right)'%(", ".join(map(latex.latex, self._gens_repr()))) 244 244 245 245 def __cmp__(self, other): 246 246 """ 247 247 Compare an ideal of a number field to something else. 248 248 249 REMARK: 250 251 By default, comparing ideals is the same as comparing 252 their generator list. But of course, different generators 253 can give rise to the same ideal. And this can easily 254 be detected using Hermite normal form. 255 256 Unfortunately, there is a difference between "cmp" and 257 "==": In the first case, this method is directly called. 258 In the second case, it is only called *after coercion*. 259 However, we ensure that "cmp(I,J)==0" and "I==J" will 260 always give the same answer for number field ideals. 261 249 262 EXAMPLES:: 250 263 251 264 sage: K.<a> = NumberField(x^2 + 3); K … … 262 275 True 263 276 sage: f[1][0] == GF(7)(5) 264 277 False 278 279 TESTS:: 280 281 sage: L.<b> = NumberField(x^8-x^4+1) 282 sage: F_2 = L.fractional_ideal(b^2-1) 283 sage: F_4 = L.fractional_ideal(b^4-1) 284 sage: F_2 == F_4 285 True 286 265 287 """ 266 288 if not isinstance(other, NumberFieldIdeal): 289 # this can only occur with cmp(,) 267 290 return cmp(type(self), type(other)) 291 if self.parent()!=other.parent(): 292 # again, this can only occur if cmp(,) 293 # is called 294 if self==other: 295 return 0 296 c = cmp(self.pari_hnf(), other.pari_hnf()) 297 if c: return c 298 return cmp(self.parent(),other.parent()) 299 # We can now assume that both have the same parent, 300 # even if originally cmp(,) was called. 268 301 return cmp(self.pari_hnf(), other.pari_hnf()) 269 302 270 303 def coordinates(self, x): -
sage/rings/number_field/number_field_morphisms.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_morphisms.pyx
a b 109 109 This allows one to go from one number field in another consistently, 110 110 assuming they both have specified embeddings into an ambient field 111 111 (by default it looks for an embedding into `\CC`). 112 113 EXAMPLES:: 114 115 sage: K.<i> = NumberField(x^2+1,embedding=QQbar(I)) 116 sage: L.<i> = NumberField(x^2+1,embedding=-QQbar(I)) 117 sage: from sage.rings.number_field.number_field_morphisms import EmbeddedNumberFieldMorphism 118 sage: EmbeddedNumberFieldMorphism(K,L,CDF) 119 Generic morphism: 120 From: Number Field in i with defining polynomial x^2 + 1 121 To: Number Field in i with defining polynomial x^2 + 1 122 Defn: i -> -i 123 sage: EmbeddedNumberFieldMorphism(K,L,QQbar) 124 Generic morphism: 125 From: Number Field in i with defining polynomial x^2 + 1 126 To: Number Field in i with defining polynomial x^2 + 1 127 Defn: i -> -i 128 112 129 """ 113 130 cdef readonly ambient_field 114 131 … … 191 208 sage: from sage.rings.number_field.number_field_morphisms import EmbeddedNumberFieldConversion 192 209 sage: K.<a> = NumberField(x^2-17, embedding=4.1) 193 210 sage: L.<b> = NumberField(x^4-17, embedding=2.0) 194 sage: f = EmbeddedNumberFieldConversion( L, K)195 sage: f( b^2)196 a197 sage: f( L(a/2-11))198 1/2* a- 11211 sage: f = EmbeddedNumberFieldConversion(K, L) 212 sage: f(a) 213 b^2 214 sage: f(K(b^2/2-11)) 215 1/2*b^2 - 11 199 216 """ 200 217 if ambient_field is None: 201 218 from sage.rings.complex_double import CDF … … 269 286 return r 270 287 else: 271 288 # since things are inexact, try and pick the closest one 289 # -- unless the ambient field is inexact and has no prec(), 290 # which holds, e.g., for the symbolic ring 291 if not hasattr(ambient_field,'prec'): 292 return None 272 293 if max_prec is None: 273 294 max_prec = ambient_field.prec() * 32 274 295 while ambient_field.prec() < max_prec: -
sage/rings/polynomial/polynomial_quotient_ring.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/polynomial/polynomial_quotient_ring.py
a b 234 234 def __reduce__(self): 235 235 return PolynomialQuotientRing_generic, (self.__ring, self.__polynomial, self.variable_names()) 236 236 237 def _ _call__(self, x):237 def _element_constructor_(self, x): 238 238 """ 239 Co erce x into this quotient ring. Anything that can be coerced into240 the polynomial ring can be co erced into the quotient.239 Convert x into this quotient ring. Anything that can be converted into 240 the polynomial ring can be converted into the quotient. 241 241 242 242 INPUT: 243 243 244 244 245 - ``x`` - object to be co erced245 - ``x`` - object to be converted 246 246 247 247 248 OUTPUT: an element obtained by co ercing x into this ring.248 OUTPUT: an element obtained by converting x into this ring. 249 249 250 250 EXAMPLES:: 251 251 … … 263 263 alpha + 1 264 264 sage: S(S.gen()^10+1) 265 265 90*alpha^2 - 109*alpha + 28 266 267 TESTS: 268 269 Conversion should work even if there is no coercion. 270 This was fixed in trac ticket #8800:: 271 272 sage: P.<x> = QQ[] 273 sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)]) 274 sage: Q = P.quo([(x^2+1)^2]) 275 sage: Q1.has_coerce_map_from(Q) 276 False 277 sage: Q1(Q.gen()) 278 xbar 279 266 280 """ 267 281 if isinstance(x, PolynomialQuotientRingElement): 268 282 P = x.parent() 269 283 if P is self: 270 284 return x 271 elif P == self: 272 return PolynomialQuotientRingElement(self, self.__ring(x.lift()), check=False) 285 return PolynomialQuotientRingElement(self, self.__ring(x.lift()), check=False) 273 286 return PolynomialQuotientRingElement( 274 287 self, self.__ring(x) , check=True) 275 288 289 def _coerce_map_from_(self, R): 290 """ 291 Anything coercing into ``self``'s polynomial ring coerces into ``self``. 292 Any quotient polynomial ring whose polynomial ring coerces into 293 ``self``'s polynomial ring and whose modulus is divided by the modulus 294 of ``self`` coerces into ``self``. 295 296 AUTHOR: 297 298 - Simon King (2010-12): Trac ticket #8800 299 300 TESTS:: 301 302 sage: P5.<x> = GF(5)[] 303 sage: Q = P5.quo([(x^2+1)^2]) 304 sage: P.<x> = ZZ[] 305 sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)]) 306 sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)]) 307 sage: Q.has_coerce_map_from(Q1) #indirect doctest 308 True 309 sage: Q1.has_coerce_map_from(Q) 310 False 311 sage: Q1.has_coerce_map_from(Q2) 312 False 313 314 """ 315 if self.__ring.has_coerce_map_from(R): 316 return True 317 if isinstance(R, PolynomialQuotientRing_generic): 318 return self.__ring.has_coerce_map_from(R.polynomial_ring()) and self.__polynomial.divides(R.modulus()) 319 276 320 def _is_valid_homomorphism_(self, codomain, im_gens): 277 321 try: 278 322 # We need that elements of the base ring of the polynomial … … 367 411 return "Univariate Quotient Polynomial Ring in %s over %s with modulus %s"%( 368 412 self.variable_name(), self.base_ring(), self.modulus()) 369 413 414 def construction(self): 415 """ 416 Functorial construction of ``self`` 417 418 EXAMPLES:: 419 420 sage: P.<t>=ZZ[] 421 sage: Q = P.quo(5+t^2) 422 sage: F, R = Q.construction() 423 sage: F(R) == Q 424 True 425 sage: P.<t> = GF(3)[] 426 sage: Q = P.quo([2+t^2]) 427 sage: F, R = Q.construction() 428 sage: F(R) == Q 429 True 430 431 AUTHOR: 432 433 -- Simon King (2010-05) 434 """ 435 from sage.categories.pushout import QuotientFunctor 436 return QuotientFunctor([self.modulus()]*self.base(),self.variable_names(),self.is_field()), self.base() 370 437 371 438 def base_ring(self): 372 439 r""" -
sage/rings/qqbar.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/qqbar.py
a b 848 848 """ 849 849 return self 850 850 851 def construction(self): 852 """ 853 EXAMPLE:: 854 855 sage: QQbar.construction() 856 (AlgebraicClosureFunctor, Rational Field) 857 """ 858 from sage.categories.pushout import AlgebraicClosureFunctor 859 from sage.all import QQ 860 return (AlgebraicClosureFunctor(), QQ) 861 851 862 def gens(self): 852 863 return(QQbar_I, ) 853 864 -
sage/rings/quotient_ring.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/quotient_ring.py
a b 249 249 from sage.categories.pushout import QuotientFunctor 250 250 # Is there a better generic way to distinguish between things like Z/pZ as a field and Z/pZ as a ring? 251 251 from sage.rings.field import Field 252 return QuotientFunctor(self.__I, as_field=isinstance(self, Field)), self.__R 252 try: 253 names = self.variable_names() 254 except ValueError: 255 try: 256 names = self.cover_ring().variable_names() 257 except ValueError: 258 names = None 259 return QuotientFunctor(self.__I, names=names, as_field=isinstance(self, Field)), self.__R 253 260 254 261 def _repr_(self): 255 262 """ -
sage/rings/residue_field.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/residue_field.pyx
a b 160 160 class ResidueFieldFactory(UniqueFactory): 161 161 """ 162 162 A factory that returns the residue class field of a prime ideal p 163 of the ring of integers of a number field, or of a polynomial ring over a finite field. 163 of the ring of integers of a number field, or of a polynomial ring 164 over a finite field. 164 165 165 166 INPUT: 166 167 … … 296 297 297 298 def create_object(self, version, key, **kwds): 298 299 p, names, impl = key 300 pring = p.ring() 299 301 300 if p .ring()is ZZ:302 if pring is ZZ: 301 303 return ResidueFiniteField_prime_modn(p, names, p.gen(), None, None, None) 302 if is_PolynomialRing(p .ring()):303 K = p .ring().fraction_field()304 Kbase = p .ring().base_ring()304 if is_PolynomialRing(pring): 305 K = pring.fraction_field() 306 Kbase = pring.base_ring() 305 307 f = p.gen() 306 308 if f.degree() == 1 and Kbase.is_prime_field() and (impl is None or impl == 'modn'): 307 309 return ResidueFiniteField_prime_modn(p, None, Kbase.order(), None, None, None) … … 320 322 if is_NumberFieldIdeal(p): 321 323 characteristic = p.smallest_integer() 322 324 else: # ideal of a function field 323 characteristic = p .ring().base_ring().characteristic()325 characteristic = pring.base_ring().characteristic() 324 326 # Once we have function fields, we should probably have an if statement here. 325 K = p .ring().fraction_field()327 K = pring.fraction_field() 326 328 #OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields. 327 329 328 330 U, to_vs, to_order = p._p_quotient(characteristic) … … 454 456 455 457 def _element_constructor_(self, x): 456 458 """ 457 This is called after x fails to coerce into the finite field (without the convert map from the number field). 459 This is called after x fails to convert into ``self`` as 460 abstract finite field (without considering the underlying 461 number field). 458 462 459 So the strategy is to try to coerce into the number field, and then use the convert map. 463 So the strategy is to try to convert into the number field, 464 and then proceed to the residue field. 465 466 NOTE: 467 468 The behaviour of this method was changed in trac ticket #8800. 469 Before, an error was raised if there was no coercion. Now, 470 a conversion is possible even when there is no coercion. 471 This is like for different finite fields. 460 472 461 473 EXAMPLES:: 462 474 … … 467 479 sage: F = OK.residue_field(P) 468 480 sage: ResidueField_generic._element_constructor_(F, i) 469 481 8 482 483 With ticket #8800, we also have:: 484 470 485 sage: ResidueField_generic._element_constructor_(F, GF(13)(8)) 471 Traceback (most recent call last): 472 ... 473 TypeError: cannot coerce <type 'sage.rings.finite_rings.integer_mod.IntegerMod_int'> 486 8 474 487 475 #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7) 476 #sage: k.<a> = P.residue_field() 477 #sage: ResidueField_generic._element_constructor_(k, t) 478 #a 479 #sage: ResidueField_generic._element_constructor_(k, GF(17)(4)) 480 #4 488 Here is a test that was temporarily removed, but newly introduced 489 in ticket #8800:: 490 491 sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7) 492 sage: k.<a> = P.residue_field() 493 sage: k(t) 494 a 495 sage: k(GF(17)(4)) 496 4 497 498 In the remaining tests, we elaborate a bit more on the difference of 499 coercion and conversion:: 500 501 sage: K.<r4> = NumberField(x^4-2) 502 sage: L.<r4> = NumberField(x^4-2, embedding=CDF.0) 503 sage: FK = K.fractional_ideal(K.0) 504 sage: FL = L.fractional_ideal(L.0) 505 506 There is no coercion from the embedded to the unembedded 507 number field. Hence, the two fractional ideals are different. 508 By consequence, the resulting residue fields are different:: 509 510 sage: RL = ResidueField(FL) 511 sage: RK = ResidueField(FK) 512 sage: RK == RL 513 False 514 515 Since ``RL`` is defined with the embedded number field ``L``, there 516 is no coercion from the maximal order of ``K`` to ``RL``. However, 517 conversion is possible:: 518 519 sage: OK = K.maximal_order() 520 sage: RL.has_coerce_map_from(OK) 521 False 522 sage: RL(OK.1) 523 0 524 481 525 """ 482 526 K = OK = self.p.ring() 483 527 if OK.is_field(): … … 495 539 elif K.has_coerce_map_from(R): 496 540 x = K(x) 497 541 else: 498 raise TypeError, "cannot coerce %s"%type(x) 542 try: 543 x = K(x) 544 except (TypeError, ValueError): 545 raise TypeError, "cannot coerce %s"%type(x) 499 546 return self(x) 500 547 501 548 def _coerce_map_from_(self, R): -
sage/rings/ring.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/ring.pyx
a b 1245 1245 - ``poly`` -- A polynomial whose coefficients are coercible into self 1246 1246 - ``name`` -- (optional) name for the root of f 1247 1247 1248 NOTE: 1249 1250 Using this method on an algebraically complete field does *not* 1251 return this field; the construction self[x] / (f(x)) is done 1252 anyway. 1253 1248 1254 EXAMPLES:: 1249 1255 1250 1256 sage: R = QQ['x'] … … 1272 1278 if name is None: 1273 1279 name = str(poly.parent().gen(0)) 1274 1280 if embedding is not None: 1275 raise NotImplementedError 1281 raise NotImplementedError, "ring extension with prescripted embedding is not implemented" 1276 1282 R = self[name] 1277 1283 I = R.ideal(R(poly.list())) 1278 1284 return R.quotient(I, name) -
sage/schemes/elliptic_curves/ell_local_data.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/schemes/elliptic_curves/ell_local_data.py
a b 634 634 - ``cp`` (int) is the Tamagawa number 635 635 636 636 637 EXAMPLES (this raised a ntype error in sage prior to 4.4.4, see ticket #7930) ::637 EXAMPLES (this raised a type error in sage prior to 4.4.4, see ticket #7930) :: 638 638 639 639 sage: E = EllipticCurve('99d1') 640 640 … … 651 651 652 652 EXAMPLES: 653 653 654 The following example shows that the bug at #9324 is fixed: 654 The following example shows that the bug at #9324 is fixed:: 655 655 656 656 sage: K.<a> = NumberField(x^2-x+6) 657 657 sage: E = EllipticCurve([0,0,0,-53160*a-43995,-5067640*a+19402006]) 658 658 sage: E.conductor() # indirect doctest 659 659 Fractional ideal (18, 6*a) 660 660 661 662 663 661 """ 664 662 E = self._curve 665 663 P = self._prime … … 692 690 693 691 pval = lambda x: x.valuation(prime) 694 692 pdiv = lambda x: x.is_zero() or pval(x) > 0 695 pinv = lambda x: F.lift(~F(x)) 696 proot = lambda x,e: F.lift(F(x).nth_root(e, extend = False, all = True)[0]) 697 preduce = lambda x: F.lift(F(x)) 693 # Since ResidueField is cached in a way that 694 # does not care much about embeddings of number 695 # fields, it can happen that F.p.ring() is different 696 # from K. This is a problem: If F.p.ring() has no 697 # embedding but K has, then there is no coercion 698 # from F.p.ring().maximal_order() to K. But it is 699 # no problem to do an explicit conversion in that 700 # case (Simon King, trac ticket #8800). 701 702 from sage.categories.pushout import pushout, CoercionException 703 try: 704 if hasattr(F.p.ring(), 'maximal_order'): # it is not ZZ 705 _tmp_ = pushout(F.p.ring().maximal_order(),K) 706 pinv = lambda x: F.lift(~F(x)) 707 proot = lambda x,e: F.lift(F(x).nth_root(e, extend = False, all = True)[0]) 708 preduce = lambda x: F.lift(F(x)) 709 except CoercionException: # the pushout does not exist, we need conversion 710 pinv = lambda x: K(F.lift(~F(x))) 711 proot = lambda x,e: K(F.lift(F(x).nth_root(e, extend = False, all = True)[0])) 712 preduce = lambda x: K(F.lift(F(x))) 698 713 699 714 def _pquadroots(a, b, c): 700 715 r""" -
sage/schemes/elliptic_curves/ell_number_field.py
diff -r b4e473888eb9 -r 1a7c8feb901d sage/schemes/elliptic_curves/ell_number_field.py
a b 1908 1908 1909 1909 sage: K.<i> = QuadraticField(-1) 1910 1910 sage: E1 = EllipticCurve([i + 1, 0, 1, -240*i - 400, -2869*i - 2627]) 1911 sage: E1.conductor() 1911 sage: E1.conductor() 1912 1912 Fractional ideal (-7*i + 4) 1913 sage: E2 = EllipticCurve([1+i,0,1,0,0]) 1914 sage: E2.conductor() 1913 sage: E2 = EllipticCurve([1+i,0,1,0,0]) 1914 sage: E2.conductor() 1915 1915 Fractional ideal (-7*i + 4) 1916 1916 sage: E1.is_isogenous(E2) 1917 1917 Traceback (most recent call last): -
sage/structure/coerce.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/structure/coerce.pyx
a b 355 355 356 356 sage: import traceback 357 357 sage: cm.exception_stack() 358 [(< class 'sage.structure.coerce_exceptions.CoercionException'>, CoercionException(AttributeError("'IdealMonoid_c_with_category' object has no attribute 'base_extend'",),), <traceback object at ...>), (<type 'exceptions.TypeError'>, TypeError("no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'",), <traceback object at ...>)]358 [(<type 'exceptions.TypeError'>, TypeError('No coercion from Rational Field to pushout Ring of integers modulo 1',), <traceback object at ...>), (<type 'exceptions.TypeError'>, TypeError("no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'",), <traceback object at ...>)] 359 359 sage: print ''.join(sum([traceback.format_exception(*info) for info in cm.exception_stack()], [])) 360 360 Traceback (most recent call last): 361 361 ... -
sage/structure/parent.pyx
diff -r b4e473888eb9 -r 1a7c8feb901d sage/structure/parent.pyx
a b 909 909 mor = <map.Map>mor_ptr 910 910 else: 911 911 mor = <map.Map>self.convert_map_from(R) 912 912 913 913 if mor is not None: 914 914 if no_extra_args: 915 915 return mor._call_(x) … … 1649 1649 usually denotes a special relationship (e.g. sub-objects, choice of 1650 1650 completion, etc.) 1651 1651 1652 EXAMPLES: 1652 EXAMPLES:: 1653 1654 sage: K.<a>=NumberField(x^3+x^2+1,embedding=1) 1655 sage: K.coerce_embedding() 1656 Generic morphism: 1657 From: Number Field in a with defining polynomial x^3 + x^2 + 1 1658 To: Real Lazy Field 1659 Defn: a -> -1.465571231876768? 1660 sage: K.<a>=NumberField(x^3+x^2+1,embedding=CC.gen()) 1661 sage: K.coerce_embedding() 1662 Generic morphism: 1663 From: Number Field in a with defining polynomial x^3 + x^2 + 1 1664 To: Complex Lazy Field 1665 Defn: a -> 0.2327856159383841? + 0.7925519925154479?*I 1653 1666 """ 1654 1667 return self._embedding 1655 1668 … … 1808 1821 return self.coerce_map_from(S._type) 1809 1822 if self._coerce_from_hash is None: # this is because parent.__init__() does not always get called 1810 1823 self.init_coerce(False) 1811 cdef object ret1824 #cdef object ret 1812 1825 try: 1813 1826 return self._coerce_from_hash[S] 1814 1827 except KeyError: