# HG changeset patch
# Parent 74c911071a9a7ea5e77000bc00f3de2a9f0fdb07
diff -r 74c911071a9a 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 | ======================== |
diff -r 74c911071a9a sage/categories/functor.pyx
a
|
b
|
|
118 | 118 | result is a homomorphism that is defined on the base ring:: |
119 | 119 | |
120 | 120 | sage: F = QQ['t'].construction()[0] |
| 121 | sage: F |
| 122 | Poly[t] |
121 | 123 | sage: F(f) |
122 | 124 | Ring morphism: |
123 | 125 | From: Univariate Polynomial Ring in t over Univariate Polynomial Ring in x over Integer Ring |
… |
… |
|
155 | 157 | |
156 | 158 | def _apply_functor(self, x): |
157 | 159 | """ |
158 | | Apply the functor to an object of ``self``'s domain |
| 160 | Apply the functor to an object of ``self``'s domain. |
159 | 161 | |
160 | 162 | NOTE: |
161 | 163 | |
… |
… |
|
175 | 177 | |
176 | 178 | def _apply_functor_to_morphism(self, f): |
177 | 179 | """ |
178 | | 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. |
179 | 181 | |
180 | 182 | NOTE: |
181 | 183 | |
… |
… |
|
210 | 212 | |
211 | 213 | def _coerce_into_domain(self, x): |
212 | 214 | """ |
213 | | Interprete the argument as an object of self's domain |
| 215 | Interprete the argument as an object of self's domain. |
214 | 216 | |
215 | 217 | NOTE: |
216 | 218 | |
… |
… |
|
232 | 234 | ... |
233 | 235 | TypeError: x (=Integer Ring) is not in Category of fields |
234 | 236 | |
235 | | |
236 | 237 | """ |
237 | 238 | if not (x in self.__domain): |
238 | 239 | raise TypeError, "x (=%s) is not in %s"%(x, self.__domain) |
… |
… |
|
474 | 475 | ... |
475 | 476 | TypeError: x (=Integer Ring) is not in Category of fields |
476 | 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 |
477 | 488 | """ |
478 | 489 | def __init__(self, C): |
479 | 490 | """ |
… |
… |
|
514 | 525 | |
515 | 526 | def _apply_functor(self, x): |
516 | 527 | """ |
| 528 | Apply the functor to an object of ``self``'s domain. |
| 529 | |
517 | 530 | TESTS:: |
518 | 531 | |
519 | 532 | sage: fields = Fields() |
diff -r 74c911071a9a sage/categories/pushout.py
a
|
b
|
|
7 | 7 | |
8 | 8 | class ConstructionFunctor(Functor): |
9 | 9 | """ |
10 | | Base class for construction functors |
| 10 | Base class for construction functors. |
11 | 11 | |
12 | 12 | A construction functor is a functorial algebraic construction, |
13 | 13 | such as the construction of a matrix ring over a given ring |
… |
… |
|
30 | 30 | |
31 | 31 | :: |
32 | 32 | |
33 | | sage: F1,R = QQ.construction() |
| 33 | sage: F1, R = QQ.construction() |
34 | 34 | sage: F1 |
35 | 35 | FractionField |
36 | 36 | sage: R |
37 | 37 | Integer Ring |
38 | | sage: F2,R = (ZZ['x']).construction() |
| 38 | sage: F2, R = (ZZ['x']).construction() |
39 | 39 | sage: F2 |
40 | 40 | Poly[x] |
41 | 41 | sage: R |
… |
… |
|
53 | 53 | Univariate Polynomial Ring in x over Rational Field |
54 | 54 | |
55 | 55 | When composing two construction functors, they are sometimes |
56 | | merged into one, as is the case in the Quotient construction. |
57 | | |
58 | | :: |
59 | | |
60 | | sage: Q15,R = (ZZ.quo(15*ZZ)).construction() |
| 56 | merged into one, as is the case in the Quotient construction:: |
| 57 | |
| 58 | sage: Q15, R = (ZZ.quo(15*ZZ)).construction() |
61 | 59 | sage: Q15 |
62 | 60 | QuotientFunctor |
63 | | sage: Q35,R = (ZZ.quo(35*ZZ)).construction() |
| 61 | sage: Q35, R = (ZZ.quo(35*ZZ)).construction() |
64 | 62 | sage: Q35 |
65 | 63 | QuotientFunctor |
66 | 64 | sage: Q15.merge(Q35) |
… |
… |
|
125 | 123 | |
126 | 124 | def pushout(self, other): |
127 | 125 | """ |
128 | | Return the composition of two construction functors, in an order given by their ranks |
| 126 | Return the composition of two construction functors, in an order given by their ranks. |
129 | 127 | |
130 | 128 | NOTE: |
131 | 129 | |
132 | | - This method seems not to be used in the coercion model |
133 | | - By default, the functor with smaller rank is applied first |
| 130 | - This method seems not to be used in the coercion model. |
| 131 | - By default, the functor with smaller rank is applied first. |
134 | 132 | |
135 | 133 | TESTS:: |
136 | 134 | |
… |
… |
|
173 | 171 | NOTE: |
174 | 172 | |
175 | 173 | By default, it returns the name of the construction functor's class. |
176 | | Usually, this method will be overloaded |
| 174 | Usually, this method will be overloaded. |
177 | 175 | |
178 | 176 | TEST:: |
179 | 177 | |
… |
… |
|
194 | 192 | NOTE: |
195 | 193 | |
196 | 194 | By default, it returns the name of the construction functor's class. |
197 | | Usually, this method will be overloaded |
| 195 | Usually, this method will be overloaded. |
198 | 196 | |
199 | 197 | TEST:: |
200 | 198 | |
… |
… |
|
210 | 208 | |
211 | 209 | def merge(self, other): |
212 | 210 | """ |
213 | | Merge ``self`` with another construction functor, or return None |
| 211 | Merge ``self`` with another construction functor, or return None. |
214 | 212 | |
215 | 213 | NOTE: |
216 | 214 | |
… |
… |
|
236 | 234 | |
237 | 235 | def commutes(self, other): |
238 | 236 | """ |
239 | | Determine whether ``self`` commutes with another construction functor |
| 237 | Determine whether ``self`` commutes with another construction functor. |
240 | 238 | |
241 | 239 | NOTE: |
242 | 240 | |
… |
… |
|
262 | 260 | |
263 | 261 | def expand(self): |
264 | 262 | """ |
265 | | Decompose ``self`` into a list of construction functors |
| 263 | Decompose ``self`` into a list of construction functors. |
266 | 264 | |
267 | 265 | NOTE: |
268 | 266 | |
… |
… |
|
276 | 274 | sage: Q = ZZ.quo(2).construction()[0] |
277 | 275 | sage: Q.expand() |
278 | 276 | [QuotientFunctor] |
| 277 | sage: P = ZZ['t'].construction()[0] |
| 278 | sage: FP = F*P |
| 279 | sage: FP.expand() |
| 280 | [FractionField, Poly[t]] |
279 | 281 | |
280 | 282 | """ |
281 | 283 | return [self] |
… |
… |
|
283 | 285 | |
284 | 286 | class CompositeConstructionFunctor(ConstructionFunctor): |
285 | 287 | """ |
286 | | A Construction Functor composed by other Construction Functors |
| 288 | A Construction Functor composed by other Construction Functors. |
287 | 289 | |
288 | 290 | INPUT: |
289 | 291 | |
290 | | ``F1,F2,...``: A list of Construction Functors. The result is the |
| 292 | ``F1, F2,...``: A list of Construction Functors. The result is the |
291 | 293 | composition ``F1`` followed by ``F2`` followed by ... |
292 | 294 | |
293 | 295 | EXAMPLES:: |
… |
… |
|
329 | 331 | |
330 | 332 | def _apply_functor_to_morphism(self, f): |
331 | 333 | """ |
| 334 | Apply the functor to an object of ``self``'s domain. |
| 335 | |
332 | 336 | TESTS:: |
333 | 337 | |
334 | 338 | sage: from sage.categories.pushout import CompositeConstructionFunctor |
… |
… |
|
353 | 357 | |
354 | 358 | def _apply_functor(self, R): |
355 | 359 | """ |
| 360 | Apply the functor to an object of ``self``'s domain. |
| 361 | |
356 | 362 | TESTS:: |
357 | 363 | |
358 | 364 | sage: from sage.categories.pushout import CompositeConstructionFunctor |
… |
… |
|
383 | 389 | |
384 | 390 | def __mul__(self, other): |
385 | 391 | """ |
386 | | Convention: ``(F1*F2)(X) == F1(F2(X))``. |
| 392 | Compose construction functors to a composit construction functor, unless one of them is the identity. |
| 393 | |
| 394 | NOTE: |
| 395 | |
| 396 | The product is in functorial notation, i.e., when applying the product to an object |
| 397 | then the second factor is applied first. |
387 | 398 | |
388 | 399 | EXAMPLES:: |
389 | 400 | |
… |
… |
|
441 | 452 | |
442 | 453 | class IdentityConstructionFunctor(ConstructionFunctor): |
443 | 454 | """ |
444 | | A construction functor that is the identity functor |
| 455 | A construction functor that is the identity functor. |
445 | 456 | |
446 | 457 | TESTS:: |
447 | 458 | |
… |
… |
|
471 | 482 | |
472 | 483 | def _apply_functor(self, x): |
473 | 484 | """ |
474 | | Return the argument unaltered |
| 485 | Return the argument unaltered. |
475 | 486 | |
476 | 487 | TESTS:: |
477 | 488 | |
… |
… |
|
484 | 495 | |
485 | 496 | def _apply_functor_to_morphism(self, f): |
486 | 497 | """ |
487 | | Return the argument unaltered |
| 498 | Return the argument unaltered. |
488 | 499 | |
489 | 500 | TESTS:: |
490 | 501 | |
… |
… |
|
517 | 528 | |
518 | 529 | def __mul__(self, other): |
519 | 530 | """ |
| 531 | Compose construction functors to a composit construction functor, unless one of them is the identity. |
| 532 | |
| 533 | NOTE: |
| 534 | |
| 535 | The product is in functorial notation, i.e., when applying the product to an object |
| 536 | then the second factor is applied first. |
| 537 | |
520 | 538 | TESTS:: |
521 | 539 | |
522 | 540 | sage: from sage.categories.pushout import IdentityConstructionFunctor |
… |
… |
|
541 | 559 | |
542 | 560 | class PolynomialFunctor(ConstructionFunctor): |
543 | 561 | """ |
544 | | Construction functor for univariate polynomial rings |
| 562 | Construction functor for univariate polynomial rings. |
545 | 563 | |
546 | 564 | EXAMPLE: |
547 | 565 | |
… |
… |
|
584 | 602 | |
585 | 603 | def _apply_functor(self, R): |
586 | 604 | """ |
| 605 | Apply the functor to an object of ``self``'s domain. |
| 606 | |
587 | 607 | TEST:: |
588 | 608 | |
589 | 609 | sage: P = ZZ['x'].construction()[0] |
… |
… |
|
622 | 642 | |
623 | 643 | def merge(self, other): |
624 | 644 | """ |
| 645 | Merge ``self`` with another construction functor, or return None. |
| 646 | |
625 | 647 | NOTE: |
626 | 648 | |
627 | 649 | Internally, the merging is delegated to the merging of |
… |
… |
|
700 | 722 | |
701 | 723 | def _apply_functor(self, R): |
702 | 724 | """ |
| 725 | Apply the functor to an object of ``self``'s domain. |
| 726 | |
703 | 727 | EXAMPLES:: |
704 | 728 | |
705 | 729 | sage: R.<x,y,z> = QQ[] |
… |
… |
|
764 | 788 | |
765 | 789 | def merge(self, other): |
766 | 790 | """ |
| 791 | Merge ``self`` with another construction functor, or return None. |
| 792 | |
767 | 793 | EXAMPLES:: |
768 | 794 | |
769 | 795 | sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) |
… |
… |
|
780 | 806 | |
781 | 807 | def expand(self): |
782 | 808 | """ |
| 809 | Decompose ``self`` into a list of construction functors. |
| 810 | |
783 | 811 | EXAMPLES:: |
784 | 812 | |
785 | 813 | sage: F = QQ['x,y,z,t'].construction()[0]; F |
… |
… |
|
823 | 851 | |
824 | 852 | class InfinitePolynomialFunctor(ConstructionFunctor): |
825 | 853 | """ |
826 | | A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`) |
| 854 | A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`). |
827 | 855 | |
828 | 856 | AUTHOR: |
829 | 857 | |
… |
… |
|
881 | 909 | CoercionException: Overlapping variables (('a', 'b'),['a_3', 'a_1']) are incompatible |
882 | 910 | |
883 | 911 | Since the construction functors are actually used to construct infinite polynomial rings, the following |
884 | | result is no surprise: |
| 912 | result is no surprise:: |
885 | 913 | |
886 | 914 | sage: C.<a,b> = InfinitePolynomialRing(B); C |
887 | 915 | Infinite polynomial ring in a, b over Multivariate Polynomial Ring in x, y over Rational Field |
… |
… |
|
893 | 921 | |
894 | 922 | `X` and `Y` have an overlapping generators `x_\\ast, y_\\ast`. Since the default lexicographic order is |
895 | 923 | used in both rings, it gives rise to isomorphic sub-monoids in both `X` and `Y`. They are merged in the |
896 | | pushout, which also yields a common parent for doing arithmetic. |
| 924 | pushout, which also yields a common parent for doing arithmetic:: |
897 | 925 | |
898 | 926 | sage: P = sage.categories.pushout.pushout(Y,X); P |
899 | 927 | Infinite polynomial ring in w, x, y, z over Rational Field |
… |
… |
|
946 | 974 | |
947 | 975 | def _apply_functor(self, R): |
948 | 976 | """ |
| 977 | Apply the functor to an object of ``self``'s domain. |
| 978 | |
949 | 979 | TEST:: |
950 | 980 | |
951 | 981 | sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F |
… |
… |
|
986 | 1016 | |
987 | 1017 | def __mul__(self, other): |
988 | 1018 | """ |
| 1019 | Compose construction functors to a composit construction functor, unless one of them is the identity. |
| 1020 | |
| 1021 | NOTE: |
| 1022 | |
| 1023 | The product is in functorial notation, i.e., when applying the product to an object |
| 1024 | then the second factor is applied first. |
| 1025 | |
989 | 1026 | TESTS:: |
990 | 1027 | |
991 | 1028 | sage: F1 = QQ['a','x_2','x_1','y_3','y_2'].construction()[0]; F1 |
… |
… |
|
1142 | 1179 | |
1143 | 1180 | def expand(self): |
1144 | 1181 | """ |
1145 | | Decompose the functor `F` into sub-functors, whose product returns `F` |
| 1182 | Decompose the functor `F` into sub-functors, whose product returns `F`. |
1146 | 1183 | |
1147 | 1184 | EXAMPLES:: |
1148 | 1185 | |
… |
… |
|
1168 | 1205 | |
1169 | 1206 | class MatrixFunctor(ConstructionFunctor): |
1170 | 1207 | """ |
1171 | | A construction functor for matrices over rings |
| 1208 | A construction functor for matrices over rings. |
1172 | 1209 | |
1173 | 1210 | EXAMPLES:: |
1174 | 1211 | |
1175 | | sage: MS = MatrixSpace(ZZ,2) |
| 1212 | sage: MS = MatrixSpace(ZZ,2, 3) |
1176 | 1213 | sage: F = MS.construction()[0]; F |
1177 | 1214 | MatrixFunctor |
1178 | 1215 | sage: MS = MatrixSpace(ZZ,2) |
… |
… |
|
1205 | 1242 | True |
1206 | 1243 | sage: F.codomain() |
1207 | 1244 | Category of commutative additive groups |
1208 | | sage: MatrixSpace(ZZ,2,2).construction()[0].codomain() |
| 1245 | sage: R = MatrixSpace(ZZ,2,2).construction()[0] |
| 1246 | sage: R.codomain() |
1209 | 1247 | Category of rings |
1210 | | |
| 1248 | sage: F(ZZ) |
| 1249 | Full MatrixSpace of 2 by 3 dense matrices over Integer Ring |
| 1250 | sage: F(ZZ) in F.codomain() |
| 1251 | True |
| 1252 | sage: R(GF(2)) |
| 1253 | Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 |
| 1254 | sage: R(GF(2)) in R.codomain() |
| 1255 | True |
1211 | 1256 | """ |
1212 | 1257 | if nrows == ncols: |
1213 | 1258 | Functor.__init__(self, Rings(), Rings()) # Algebras() takes a base ring |
… |
… |
|
1217 | 1262 | self.nrows = nrows |
1218 | 1263 | self.ncols = ncols |
1219 | 1264 | self.is_sparse = is_sparse |
| 1265 | |
1220 | 1266 | def _apply_functor(self, R): |
1221 | 1267 | """ |
| 1268 | Apply the functor to an object of ``self``'s domain. |
| 1269 | |
1222 | 1270 | TEST: |
1223 | 1271 | |
1224 | 1272 | The following is a test against a bug discussed at ticket #8800 |
… |
… |
|
1232 | 1280 | """ |
1233 | 1281 | from sage.matrix.matrix_space import MatrixSpace |
1234 | 1282 | return MatrixSpace(R, self.nrows, self.ncols, sparse=self.is_sparse) |
| 1283 | |
1235 | 1284 | def __cmp__(self, other): |
1236 | 1285 | """ |
1237 | 1286 | TEST:: |
… |
… |
|
1247 | 1296 | if c == 0: |
1248 | 1297 | c = cmp((self.nrows, self.ncols), (other.nrows, other.ncols)) |
1249 | 1298 | return c |
| 1299 | |
1250 | 1300 | def merge(self, other): |
1251 | 1301 | """ |
1252 | 1302 | Merging is only happening if both functors are matrix functors of the same dimension. |
… |
… |
|
1278 | 1328 | |
1279 | 1329 | class LaurentPolynomialFunctor(ConstructionFunctor): |
1280 | 1330 | """ |
1281 | | Construction functor for Laurent polynomial rings |
| 1331 | Construction functor for Laurent polynomial rings. |
1282 | 1332 | |
1283 | 1333 | EXAMPLES:: |
1284 | 1334 | |
… |
… |
|
1332 | 1382 | if not isinstance(var, (basestring,tuple,list)): |
1333 | 1383 | raise TypeError, "variable name or list of variable names expected" |
1334 | 1384 | self.var = var |
1335 | | self.multi_variate = multi_variate or not isinstance(var,basestring) |
| 1385 | self.multi_variate = multi_variate or not isinstance(var, basestring) |
| 1386 | |
1336 | 1387 | def _apply_functor(self, R): |
1337 | 1388 | """ |
| 1389 | Apply the functor to an object of ``self``'s domain. |
| 1390 | |
1338 | 1391 | TESTS:: |
1339 | 1392 | |
1340 | 1393 | sage: from sage.categories.pushout import LaurentPolynomialFunctor |
… |
… |
|
1355 | 1408 | else: |
1356 | 1409 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing |
1357 | 1410 | return LaurentPolynomialRing(R, self.var) |
| 1411 | |
1358 | 1412 | def __cmp__(self, other): |
1359 | 1413 | """ |
1360 | 1414 | TESTS:: |
… |
… |
|
1377 | 1431 | if c == 0: |
1378 | 1432 | c = cmp(self.var, other.var) |
1379 | 1433 | return c |
| 1434 | |
1380 | 1435 | def merge(self, other): |
1381 | 1436 | """ |
1382 | 1437 | Two Laurent polynomial construction functors merge if the variable names coincide. |
… |
… |
|
1403 | 1458 | |
1404 | 1459 | class VectorFunctor(ConstructionFunctor): |
1405 | 1460 | """ |
1406 | | A construction functor for free modules over commutative rings |
| 1461 | A construction functor for free modules over commutative rings. |
1407 | 1462 | |
1408 | 1463 | EXAMPLE:: |
1409 | 1464 | |
… |
… |
|
1422 | 1477 | """ |
1423 | 1478 | INPUT: |
1424 | 1479 | |
1425 | | - ``n``, the rank of the to-be-created modules (non-neg. integer) |
| 1480 | - ``n``, the rank of the to-be-created modules (non-negative integer) |
1426 | 1481 | - ``is_sparse`` (optional bool, default ``False``), create sparse implementation of modules |
1427 | 1482 | - ``inner_product_matrix``: ``n`` by ``n`` matrix, used to compute inner products in the |
1428 | 1483 | to-be-created modules |
… |
… |
|
1431 | 1486 | |
1432 | 1487 | sage: from sage.categories.pushout import VectorFunctor |
1433 | 1488 | sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9))) |
| 1489 | sage: F1.domain() |
| 1490 | Category of commutative rings |
| 1491 | sage: F1.codomain() |
| 1492 | Category of commutative additive groups |
1434 | 1493 | sage: M1 = F1(ZZ) |
1435 | 1494 | sage: M1.is_sparse() |
1436 | 1495 | False |
… |
… |
|
1452 | 1511 | self.n = n |
1453 | 1512 | self.is_sparse = is_sparse |
1454 | 1513 | self.inner_product_matrix = inner_product_matrix |
| 1514 | |
1455 | 1515 | def _apply_functor(self, R): |
1456 | 1516 | """ |
| 1517 | Apply the functor to an object of ``self``'s domain. |
| 1518 | |
1457 | 1519 | TESTS:: |
1458 | 1520 | |
1459 | 1521 | sage: from sage.categories.pushout import VectorFunctor |
… |
… |
|
1477 | 1539 | """ |
1478 | 1540 | from sage.modules.free_module import FreeModule |
1479 | 1541 | return FreeModule(R, self.n, sparse=self.is_sparse, inner_product_matrix=self.inner_product_matrix) |
| 1542 | |
1480 | 1543 | def _apply_functor_to_morphism(self, f): |
1481 | 1544 | """ |
1482 | 1545 | This is not implemented yet. |
… |
… |
|
1493 | 1556 | """ |
1494 | 1557 | ## TODO: Implement this! |
1495 | 1558 | raise NotImplementedError, "Can not create induced morphisms of free modules yet" |
| 1559 | |
1496 | 1560 | def __cmp__(self, other): |
1497 | 1561 | """ |
1498 | | Only the rank of the to-be-created modules is compared, *not* the inner product matrix |
| 1562 | Only the rank of the to-be-created modules is compared, *not* the inner product matrix. |
1499 | 1563 | |
1500 | 1564 | TESTS:: |
1501 | 1565 | |
… |
… |
|
1515 | 1579 | if c == 0: |
1516 | 1580 | c = cmp(self.n, other.n) |
1517 | 1581 | return c |
| 1582 | |
1518 | 1583 | def merge(self, other): |
1519 | 1584 | """ |
1520 | 1585 | Two constructors of free modules merge, if the module ranks coincide. If both |
1521 | | have explicitly given inner product matrices, they must coincide as well |
| 1586 | have explicitly given inner product matrices, they must coincide as well. |
1522 | 1587 | |
1523 | 1588 | EXAMPLE: |
1524 | 1589 | |
… |
… |
|
1579 | 1644 | else: |
1580 | 1645 | return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix) |
1581 | 1646 | |
1582 | | |
1583 | 1647 | class SubspaceFunctor(ConstructionFunctor): |
1584 | 1648 | """ |
1585 | 1649 | Constructing a subspace of an ambient free module, given by a basis. |
… |
… |
|
1606 | 1670 | |
1607 | 1671 | """ |
1608 | 1672 | rank = 11 # ranking of functor, not rank of module |
| 1673 | |
1609 | 1674 | def __init__(self, basis): |
1610 | 1675 | """ |
1611 | 1676 | INPUT: |
1612 | 1677 | |
1613 | | ``basis``: a list of elements of a free module |
| 1678 | ``basis``: a list of elements of a free module. |
1614 | 1679 | |
1615 | 1680 | TEST:: |
1616 | 1681 | |
… |
… |
|
1630 | 1695 | ## contains in- and output |
1631 | 1696 | Functor.__init__(self, CommutativeAdditiveGroups(), CommutativeAdditiveGroups()) |
1632 | 1697 | self.basis = basis |
| 1698 | |
1633 | 1699 | def _apply_functor(self, ambient): |
1634 | 1700 | """ |
| 1701 | Apply the functor to an object of ``self``'s domain. |
| 1702 | |
1635 | 1703 | TESTS:: |
1636 | 1704 | |
1637 | 1705 | sage: M = ZZ^3 |
… |
… |
|
1648 | 1716 | [0 1 0] |
1649 | 1717 | """ |
1650 | 1718 | return ambient.span_of_basis(self.basis) |
| 1719 | |
1651 | 1720 | def _apply_functor_to_morphism(self, f): |
1652 | 1721 | """ |
1653 | 1722 | This is not implemented yet. |
… |
… |
|
1663 | 1732 | NotImplementedError: Can not create morphisms of free sub-modules yet |
1664 | 1733 | """ |
1665 | 1734 | raise NotImplementedError, "Can not create morphisms of free sub-modules yet" |
| 1735 | |
1666 | 1736 | def __cmp__(self, other): |
1667 | 1737 | """ |
1668 | 1738 | TEST:: |
… |
… |
|
1721 | 1791 | if c == 0: |
1722 | 1792 | c = cmp(self.basis, other.basis) |
1723 | 1793 | return c |
| 1794 | |
1724 | 1795 | def merge(self, other): |
1725 | 1796 | """ |
1726 | | Two Subspace Functors are merged into a construction functor of the sum of two subspaces |
| 1797 | Two Subspace Functors are merged into a construction functor of the sum of two subspaces. |
1727 | 1798 | |
1728 | 1799 | EXAMPLE:: |
1729 | 1800 | |
… |
… |
|
1775 | 1846 | else: |
1776 | 1847 | return None |
1777 | 1848 | |
1778 | | |
1779 | 1849 | class FractionField(ConstructionFunctor): |
1780 | 1850 | """ |
1781 | | Construction functor for fraction fields |
| 1851 | Construction functor for fraction fields. |
1782 | 1852 | |
1783 | 1853 | EXAMPLE:: |
1784 | 1854 | |
… |
… |
|
1813 | 1883 | Fraction Field of Univariate Polynomial Ring in t over Integer Ring |
1814 | 1884 | """ |
1815 | 1885 | Functor.__init__(self, Rings(), Fields()) |
| 1886 | |
1816 | 1887 | def _apply_functor(self, R): |
1817 | 1888 | """ |
| 1889 | Apply the functor to an object of ``self``'s domain. |
| 1890 | |
1818 | 1891 | TEST:: |
1819 | 1892 | |
1820 | 1893 | sage: F = QQ.construction()[0] |
… |
… |
|
1841 | 1914 | # c = cmp(self.t, other.t) |
1842 | 1915 | # return c |
1843 | 1916 | |
1844 | | |
1845 | 1917 | class CompletionFunctor(ConstructionFunctor): |
1846 | 1918 | """ |
1847 | | Completion of a ring with respect to a given prime (including infinity) |
| 1919 | Completion of a ring with respect to a given prime (including infinity). |
1848 | 1920 | |
1849 | 1921 | EXAMPLES:: |
1850 | 1922 | |
… |
… |
|
1882 | 1954 | |
1883 | 1955 | """ |
1884 | 1956 | rank = 4 |
1885 | | |
| 1957 | |
1886 | 1958 | def __init__(self, p, prec, extras=None): |
1887 | 1959 | """ |
1888 | 1960 | INPUT: |
… |
… |
|
1912 | 1984 | self.p = p |
1913 | 1985 | self.prec = prec |
1914 | 1986 | self.extras = extras |
| 1987 | |
1915 | 1988 | def __str__(self): |
1916 | 1989 | """ |
1917 | 1990 | TEST:: |
… |
… |
|
1920 | 1993 | (Completion[7], Integer Ring) |
1921 | 1994 | """ |
1922 | 1995 | return 'Completion[%s]'%repr(self.p) |
| 1996 | |
1923 | 1997 | def _apply_functor(self, R): |
1924 | 1998 | """ |
| 1999 | Apply the functor to an object of ``self``'s domain. |
| 2000 | |
1925 | 2001 | TEST:: |
1926 | 2002 | |
1927 | 2003 | sage: R = Zp(5) |
… |
… |
|
1979 | 2055 | if c == 0: |
1980 | 2056 | c = cmp(self.p, other.p) |
1981 | 2057 | return c |
| 2058 | |
1982 | 2059 | def merge(self, other): |
1983 | 2060 | """ |
1984 | 2061 | Two Completion functors are merged, if they are equal. If the precisions of |
… |
… |
|
2021 | 2098 | ## both commute. This is used in the call method, |
2022 | 2099 | ## since some fraction fields have no completion method |
2023 | 2100 | ## implemented. |
| 2101 | |
2024 | 2102 | def commutes(self,other): |
2025 | 2103 | """ |
2026 | | Completion commutes with fraction fields |
| 2104 | Completion commutes with fraction fields. |
2027 | 2105 | |
2028 | 2106 | EXAMPLE:: |
2029 | 2107 | |
… |
… |
|
2046 | 2124 | False |
2047 | 2125 | sage: C(R) is Frac(C(P)) |
2048 | 2126 | True |
| 2127 | sage: F = R.construction()[0] |
| 2128 | sage: (C*F)(ZZ['x']) is (F*C)(ZZ['x']) |
| 2129 | True |
2049 | 2130 | |
2050 | 2131 | """ |
2051 | 2132 | return isinstance(other,(FractionField,CompletionFunctor)) |
2052 | 2133 | |
2053 | 2134 | class QuotientFunctor(ConstructionFunctor): |
2054 | 2135 | """ |
2055 | | Construction functor for quotient rings |
| 2136 | Construction functor for quotient rings. |
2056 | 2137 | |
2057 | 2138 | NOTE: |
2058 | 2139 | |
… |
… |
|
2112 | 2193 | self.I = I |
2113 | 2194 | if names is None: |
2114 | 2195 | self.names = None |
2115 | | elif isinstance(names,basestring): |
| 2196 | elif isinstance(names, basestring): |
2116 | 2197 | self.names = (names,) |
2117 | 2198 | else: |
2118 | 2199 | self.names = tuple(names) |
2119 | 2200 | self.as_field = as_field |
| 2201 | |
2120 | 2202 | def _apply_functor(self, R): |
2121 | 2203 | """ |
| 2204 | Apply the functor to an object of ``self``'s domain. |
| 2205 | |
2122 | 2206 | TESTS:: |
2123 | 2207 | |
2124 | 2208 | sage: P.<x,y> = ZZ[] |
… |
… |
|
2159 | 2243 | if self.as_field and hasattr(Q, 'field'): |
2160 | 2244 | Q = Q.field() |
2161 | 2245 | return Q |
| 2246 | |
2162 | 2247 | def __cmp__(self, other): |
2163 | 2248 | """ |
2164 | 2249 | The types, the names and the moduli are compared. |
… |
… |
|
2182 | 2267 | if c == 0: |
2183 | 2268 | c = cmp(self.I, other.I) |
2184 | 2269 | return c |
| 2270 | |
2185 | 2271 | def merge(self, other): |
2186 | 2272 | """ |
2187 | | Two quotient functors with coinciding names are merged by taking the gcd of their moduli |
| 2273 | Two quotient functors with coinciding names are merged by taking the gcd of their moduli. |
2188 | 2274 | |
2189 | 2275 | EXAMPLE:: |
2190 | 2276 | |
… |
… |
|
2202 | 2288 | |
2203 | 2289 | """ |
2204 | 2290 | if type(self)!=type(other): |
2205 | | return |
| 2291 | return None |
2206 | 2292 | if self.names != other.names: |
2207 | | return |
| 2293 | return None |
2208 | 2294 | if self == other: |
2209 | 2295 | if self.as_field == other.as_field: |
2210 | 2296 | return self |
2211 | | return QuotientFunctor(self.I,names=self.names, as_field=True) # one of them yields a field! |
| 2297 | return QuotientFunctor(self.I, names=self.names, as_field=True) # one of them yields a field! |
2212 | 2298 | try: |
2213 | 2299 | gcd = self.I + other.I |
2214 | 2300 | except (TypeError, NotImplementedError): |
… |
… |
|
2223 | 2309 | raise TypeError, "Trivial quotient intersection." |
2224 | 2310 | # GF(p) has a coercion from Integers(p). Hence, merging should |
2225 | 2311 | # yield a field if either self or other yields a field. |
2226 | | return QuotientFunctor(gcd,names=self.names, as_field=self.as_field or other.as_field) |
| 2312 | return QuotientFunctor(gcd, names=self.names, as_field=self.as_field or other.as_field) |
2227 | 2313 | |
2228 | 2314 | class AlgebraicExtensionFunctor(ConstructionFunctor): |
2229 | 2315 | """ |
2230 | | Algebraic extension (univariate polynomial ring modulo principal ideal) |
| 2316 | Algebraic extension (univariate polynomial ring modulo principal ideal). |
2231 | 2317 | |
2232 | 2318 | EXAMPLE:: |
2233 | 2319 | |
… |
… |
|
2240 | 2326 | extension will be constructed as the quotient of a univariate |
2241 | 2327 | polynomial ring:: |
2242 | 2328 | |
| 2329 | sage: F(CC) |
| 2330 | Univariate Quotient Polynomial Ring in a over Complex Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 |
2243 | 2331 | sage: F(RR) |
2244 | 2332 | Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000 |
2245 | 2333 | |
… |
… |
|
2322 | 2410 | Order in Number Field in a with defining polynomial x^3 - x^2 + 1 |
2323 | 2411 | |
2324 | 2412 | The cyclotomic fields form a special case of number fields |
2325 | | with prescribed embeddings. |
2326 | | :: |
| 2413 | with prescribed embeddings:: |
2327 | 2414 | |
2328 | 2415 | sage: C = CyclotomicField(8) |
2329 | 2416 | sage: F,R = C.construction() |
… |
… |
|
2349 | 2436 | |
2350 | 2437 | def _apply_functor(self, R): |
2351 | 2438 | """ |
| 2439 | Apply the functor to an object of ``self``'s domain. |
| 2440 | |
2352 | 2441 | TESTS:: |
2353 | 2442 | |
2354 | 2443 | sage: K.<a>=NumberField(x^3+x^2+1) |
… |
… |
|
2388 | 2477 | |
2389 | 2478 | def merge(self,other): |
2390 | 2479 | """ |
2391 | | Merging two :class:`AlgebraicExtensionFunctor`s |
| 2480 | Merging two :class:`AlgebraicExtensionFunctor`s. |
2392 | 2481 | |
2393 | 2482 | INPUT: |
2394 | 2483 | |
2395 | | ``other`` -- Construction Functor |
| 2484 | ``other`` -- Construction Functor. |
2396 | 2485 | |
2397 | 2486 | OUTPUT: |
2398 | 2487 | |
… |
… |
|
2447 | 2536 | |
2448 | 2537 | """ |
2449 | 2538 | if not isinstance(other,AlgebraicExtensionFunctor): |
2450 | | return |
| 2539 | return None |
2451 | 2540 | if self == other: |
2452 | 2541 | return self |
2453 | 2542 | # This method is supposed to be used in pushout(), |
… |
… |
|
2455 | 2544 | # assume that both functors have a single variable. |
2456 | 2545 | # But for being on the safe side...: |
2457 | 2546 | if len(self.names)!=1 or len(other.names)!=1: |
2458 | | return |
| 2547 | return None |
2459 | 2548 | ## We don't accept a forgetful coercion, since, together |
2460 | 2549 | ## with bidirectional coercions between two embedded |
2461 | 2550 | ## number fields, it would yield to contradictions in |
… |
… |
|
2486 | 2575 | |
2487 | 2576 | def __mul__(self, other): |
2488 | 2577 | """ |
2489 | | Functor composition. |
2490 | | |
2491 | | The last factor is applied first. |
| 2578 | Compose construction functors to a composit construction functor, unless one of them is the identity. |
| 2579 | |
| 2580 | NOTE: |
| 2581 | |
| 2582 | The product is in functorial notation, i.e., when applying the product to an object |
| 2583 | then the second factor is applied first. |
2492 | 2584 | |
2493 | 2585 | TESTS:: |
2494 | 2586 | |
… |
… |
|
2514 | 2606 | |
2515 | 2607 | def expand(self): |
2516 | 2608 | """ |
2517 | | Decompose the functor `F` into sub-functors, whose product returns `F` |
| 2609 | Decompose the functor `F` into sub-functors, whose product returns `F`. |
2518 | 2610 | |
2519 | 2611 | EXAMPLES:: |
2520 | 2612 | |
… |
… |
|
2524 | 2616 | sage: F,R = L.construction() |
2525 | 2617 | sage: prod(F.expand())(R) == L |
2526 | 2618 | True |
2527 | | |
| 2619 | sage: K = NumberField([x^2-2, x^2-3],'a') |
| 2620 | sage: F, R = K.construction() |
| 2621 | sage: F |
| 2622 | AlgebraicExtensionFunctor |
| 2623 | sage: L = F.expand(); L |
| 2624 | [AlgebraicExtensionFunctor, AlgebraicExtensionFunctor] |
| 2625 | sage: L[-1](QQ) |
| 2626 | Number Field in a1 with defining polynomial x^2 - 3 |
2528 | 2627 | """ |
2529 | 2628 | if len(self.polys)==1: |
2530 | 2629 | return [self] |
… |
… |
|
2532 | 2631 | |
2533 | 2632 | class AlgebraicClosureFunctor(ConstructionFunctor): |
2534 | 2633 | """ |
2535 | | Algebraic Closure |
| 2634 | Algebraic Closure. |
2536 | 2635 | |
2537 | 2636 | EXAMPLE:: |
2538 | 2637 | |
… |
… |
|
2562 | 2661 | |
2563 | 2662 | """ |
2564 | 2663 | Functor.__init__(self, Rings(), Rings()) |
| 2664 | |
2565 | 2665 | def _apply_functor(self, R): |
2566 | 2666 | """ |
| 2667 | Apply the functor to an object of ``self``'s domain. |
| 2668 | |
2567 | 2669 | TEST:: |
2568 | 2670 | |
2569 | 2671 | sage: F = CDF.construction()[0] |
… |
… |
|
2575 | 2677 | if c is not None and c[0]==self: |
2576 | 2678 | return R |
2577 | 2679 | return R.algebraic_closure() |
| 2680 | |
2578 | 2681 | def merge(self, other): |
2579 | 2682 | """ |
2580 | 2683 | Mathematically, Algebraic Closure subsumes Algebraic Extension. |
… |
… |
|
2592 | 2695 | """ |
2593 | 2696 | if self==other: |
2594 | 2697 | return self |
| 2698 | return None |
2595 | 2699 | # Mathematically, Algebraic Closure subsumes Algebraic Extension. |
2596 | 2700 | # However, it seems that people do want to work with |
2597 | 2701 | # algebraic extensions of RR (namely RR/poly*RR). So, we don't do: |
… |
… |
|
2649 | 2753 | |
2650 | 2754 | def merge(self, other): |
2651 | 2755 | """ |
| 2756 | Merge ``self`` with another construction functor, or return None. |
| 2757 | |
2652 | 2758 | EXAMPLES:: |
2653 | 2759 | |
2654 | 2760 | sage: P1 = PermutationGroup([[(1,2)]]) |
… |
… |
|
2664 | 2770 | |
2665 | 2771 | class BlackBoxConstructionFunctor(ConstructionFunctor): |
2666 | 2772 | """ |
2667 | | Construction functor obtained from any callable object |
| 2773 | Construction functor obtained from any callable object. |
2668 | 2774 | |
2669 | 2775 | EXAMPLES:: |
2670 | 2776 | |
… |
… |
|
2705 | 2811 | if not callable(box): |
2706 | 2812 | raise TypeError, "input must be callable" |
2707 | 2813 | self.box = box |
| 2814 | |
2708 | 2815 | def _apply_functor(self, R): |
2709 | 2816 | """ |
| 2817 | Apply the functor to an object of ``self``'s domain. |
| 2818 | |
2710 | 2819 | TESTS:: |
2711 | 2820 | |
2712 | 2821 | sage: from sage.categories.pushout import BlackBoxConstructionFunctor |
… |
… |
|
2717 | 2826 | |
2718 | 2827 | """ |
2719 | 2828 | return self.box(R) |
| 2829 | |
2720 | 2830 | def __cmp__(self, other): |
2721 | 2831 | """ |
2722 | 2832 | TESTS:: |
… |
… |
|
2733 | 2843 | c = cmp(self.box, other.box) |
2734 | 2844 | #return self.box == other.box |
2735 | 2845 | return c |
2736 | | |
2737 | | |
| 2846 | |
2738 | 2847 | def pushout(R, S): |
2739 | 2848 | """ |
2740 | 2849 | Given a pair of Objects R and S, try and construct a |
diff -r 74c911071a9a sage/groups/perm_gps/permgroup.py
a
|
b
|
|
366 | 366 | if gens is None: |
367 | 367 | self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group) |
368 | 368 | self._gens = self._gens_from_gap() |
369 | | return |
| 369 | return None |
370 | 370 | |
371 | 371 | gens = [self._element_class()(x, check=False).list() for x in gens] |
372 | 372 | self._deg = max([0]+[max(g) for g in gens]) |
diff -r 74c911071a9a sage/rings/number_field/number_field.py
a
|
b
|
|
430 | 430 | sage: P.<x> = QQ[] |
431 | 431 | sage: K.<a> = NumberField(x^3-5,embedding=0) |
432 | 432 | sage: L.<b> = K.extension(x^2+a) |
433 | | sage: F,R = L.construction() |
| 433 | sage: F, R = L.construction() |
434 | 434 | sage: F(R) == L # indirect doctest |
435 | 435 | True |
436 | 436 | |
… |
… |
|
5086 | 5086 | sage: S.coerce(y) is y |
5087 | 5087 | True |
5088 | 5088 | |
5089 | | Fields with embeddings into an ambient field coerce naturally by the given embedding. |
5090 | | :: |
| 5089 | Fields with embeddings into an ambient field coerce naturally by the given embedding:: |
5091 | 5090 | |
5092 | 5091 | sage: CyclotomicField(15).coerce(CyclotomicField(5).0 - 17/3) |
5093 | 5092 | zeta15^3 - 17/3 |
… |
… |
|
5176 | 5175 | # R is embedded, self isn't. So, we could only have |
5177 | 5176 | # the forgetful coercion. But this yields to non-commuting |
5178 | 5177 | # coercions, as was pointed out at ticket #8800 |
5179 | | return |
| 5178 | return None |
5180 | 5179 | |
5181 | 5180 | def _magma_init_(self, magma): |
5182 | 5181 | """ |
diff -r 74c911071a9a sage/rings/number_field/number_field_ideal.py
a
|
b
|
|
281 | 281 | sage: L.<b> = NumberField(x^8-x^4+1) |
282 | 282 | sage: F_2 = L.fractional_ideal(b^2-1) |
283 | 283 | sage: F_4 = L.fractional_ideal(b^4-1) |
284 | | sage: F_2==F_4 |
| 284 | sage: F_2 == F_4 |
285 | 285 | True |
286 | 286 | |
287 | 287 | """ |
diff -r 74c911071a9a sage/rings/polynomial/polynomial_quotient_ring.py
a
|
b
|
|
419 | 419 | |
420 | 420 | sage: P.<t>=ZZ[] |
421 | 421 | sage: Q = P.quo(5+t^2) |
422 | | sage: F,R = Q.construction() |
| 422 | sage: F, R = Q.construction() |
423 | 423 | sage: F(R) == Q |
424 | 424 | True |
425 | 425 | sage: P.<t> = GF(3)[] |
426 | 426 | sage: Q = P.quo([2+t^2]) |
427 | | sage: F,R = Q.construction() |
| 427 | sage: F, R = Q.construction() |
428 | 428 | sage: F(R) == Q |
429 | 429 | True |
430 | 430 | |