Ticket #11943: trac11943_mro_for_all_super_categories_lazy_hook.patch
File trac11943_mro_for_all_super_categories_lazy_hook.patch, 84.2 KB (added by , 10 years ago) |
---|
-
doc/en/reference/misc.rst
# HG changeset patch # User Simon King <simon.king@uni-jena.de> # Date 1319403311 -7200 # Node ID 67948c416f8b9ef23a0c97fda5f76772678f05aa # Parent 9c42ea6598c003a4f88b1ae727a0f5436650fd59 #11943: Order the super categories of a category according to Python's method resolution order Introduce lazy-attribute versions of super_categories and all_super_categories, for getting a speed-up. Allow to use a shortpath in is_subcategory, by using _subcategory_hook_. Use subclass check on parent classes to determine subcategories. diff --git a/doc/en/reference/misc.rst b/doc/en/reference/misc.rst
a b Miscellaneous 8 8 9 9 sage/misc/abstract_method 10 10 sage/misc/cachefunc 11 sage/misc/c3 11 12 sage/misc/decorators 12 13 sage/misc/classgraph 13 14 sage/misc/dev_tools -
module_list.py
diff --git a/module_list.py b/module_list.py
a b ext_modules = [ 1058 1058 Extension('sage.misc.cython_c', 1059 1059 sources = ['sage/misc/cython_c.pyx']), 1060 1060 1061 Extension('sage.misc.c3', 1062 sources = ['sage/misc/c3.pyx']), 1063 1061 1064 Extension('sage.misc.derivative', 1062 1065 sources = ['sage/misc/derivative.pyx']), 1063 1066 -
sage/categories/additive_magmas.py
diff --git a/sage/categories/additive_magmas.py b/sage/categories/additive_magmas.py
a b class AdditiveMagmas(Category_singleton) 35 35 36 36 """ 37 37 38 @cached_method39 38 def super_categories(self): 40 39 """ 41 40 EXAMPLES:: -
sage/categories/affine_weyl_groups.py
diff --git a/sage/categories/affine_weyl_groups.py b/sage/categories/affine_weyl_groups.py
a b class AffineWeylGroups(Category_singleto 44 44 sage: TestSuite(C).run() 45 45 """ 46 46 47 @cached_method48 47 def super_categories(self): 49 48 r""" 50 49 EXAMPLES:: -
sage/categories/algebra_ideals.py
diff --git a/sage/categories/algebra_ideals.py b/sage/categories/algebra_ideals.py
a b AlgebraIdeals 12 12 13 13 from sage.misc.cachefunc import cached_method 14 14 from category_types import Category_ideal 15 from algebra_modules import AlgebraModules 16 from commutative_algebras import CommutativeAlgebras 15 17 16 18 class AlgebraIdeals(Category_ideal): 17 19 """ … … class AlgebraIdeals(Category_ideal): 58 60 """ 59 61 return self.ambient() 60 62 61 @cached_method62 63 def super_categories(self): 63 64 """ 65 The category of algebra modules should be a super category of this category. 66 67 However, since algebra modules are currently only available over commutative rings, 68 we have to omit it if our ring is non-commutative. 69 64 70 EXAMPLES:: 65 71 66 72 sage: AlgebraIdeals(QQ[x]).super_categories() 67 73 [Category of algebra modules over Univariate Polynomial Ring in x over Rational Field] 74 sage: C = AlgebraIdeals(FreeAlgebra(QQ,2,'a,b')) 75 sage: C.super_categories() 76 [] 77 68 78 """ 69 from algebra_modules import AlgebraModules70 79 R = self.algebra() 71 return [AlgebraModules(R)] 80 try: 81 if R.is_commutative(): 82 return [AlgebraModules(R)] 83 except (AttributeError,NotImplementedError): 84 pass 85 return [] -
sage/categories/algebra_modules.py
diff --git a/sage/categories/algebra_modules.py b/sage/categories/algebra_modules.py
a b Algebra modules 12 12 13 13 from sage.misc.cachefunc import cached_method 14 14 from category_types import Category_module 15 from modules import Modules 15 16 16 17 class AlgebraModules(Category_module): 17 18 """ … … class AlgebraModules(Category_module): 77 78 """ 78 79 return self.base_ring() 79 80 80 @cached_method81 81 def super_categories(self): 82 82 """ 83 83 EXAMPLES:: … … class AlgebraModules(Category_module): 86 86 [Category of modules over Univariate Polynomial Ring in x over Rational Field] 87 87 """ 88 88 R = self.algebra() 89 from modules import Modules90 89 return [Modules(R)] -
sage/categories/algebras.py
diff --git a/sage/categories/algebras.py b/sage/categories/algebras.py
a b from sage.categories.dual import DualObj 23 23 from sage.categories.tensor import TensorProductsCategory, tensor 24 24 from sage.categories.morphism import SetMorphism 25 25 from sage.categories.rings import Rings 26 from sage.categories.modules import Modules 26 27 from sage.misc.cachefunc import cached_method 27 28 from sage.structure.sage_object import have_same_parent 28 29 … … class Algebras(Category_over_base_ring): 66 67 from sage.rings.ring import Algebra 67 68 return isinstance(x, Algebra) and x.base_ring() == self.base_ring() 68 69 69 @cached_method70 70 def super_categories(self): 71 71 """ 72 72 EXAMPLES:: … … class Algebras(Category_over_base_ring): 75 75 [Category of rings, Category of modules over Integer Ring] 76 76 """ 77 77 R = self.base_ring() 78 from sage.categories.rings import Rings79 from sage.categories.modules import Modules80 78 return [Rings(), Modules(R)] 81 79 82 80 class ParentMethods: # (Algebra): # Eventually, the content of Algebra should be moved here -
sage/categories/bialgebras.py
diff --git a/sage/categories/bialgebras.py b/sage/categories/bialgebras.py
a b class Bialgebras(Category_over_base_ring 29 29 sage: TestSuite(Bialgebras(ZZ)).run() 30 30 """ 31 31 32 @cached_method33 32 def super_categories(self): 34 33 """ 35 34 EXAMPLES:: -
sage/categories/bimodules.py
diff --git a/sage/categories/bimodules.py b/sage/categories/bimodules.py
a b Bimodules 13 13 14 14 from sage.categories.category import Category 15 15 from sage.misc.cachefunc import cached_method 16 from sage.categories.left_modules import LeftModules 17 from sage.categories.right_modules import RightModules 18 16 19 from sage.categories.rings import Rings 17 20 _Rings = Rings() 18 21 … … class Bimodules(Category): 103 106 from sage.misc.latex import latex 104 107 return "{%s}_{%s}_{%s}"%(Category._latex_(self), latex(self._left_base_ring), latex(self._right_base_ring)) 105 108 106 @cached_method107 109 def super_categories(self): 108 110 """ 109 111 EXAMPLES:: … … class Bimodules(Category): 113 115 """ 114 116 R = self.left_base_ring() 115 117 S = self.right_base_ring() 116 from sage.categories.left_modules import LeftModules117 from sage.categories.right_modules import RightModules118 118 return [LeftModules(R), RightModules(S)] 119 119 120 120 class ParentMethods: -
sage/categories/cartesian_product.py
diff --git a/sage/categories/cartesian_product.py b/sage/categories/cartesian_product.py
a b class CartesianProductsCategory(Covarian 145 145 """ 146 146 return self 147 147 148 def base (self):148 def base_ring(self): 149 149 """ 150 The base of a cartesian product is the base (usually a ring)of the underlying category.150 The base ring of a cartesian product is the base ring of the underlying category. 151 151 152 152 EXAMPLES:: 153 153 154 sage: Algebras(ZZ).CartesianProducts().base ()154 sage: Algebras(ZZ).CartesianProducts().base_ring() 155 155 Integer Ring 156 156 """ 157 return self.base_category().base ()157 return self.base_category().base_ring() 158 158 159 159 # This is Category.CartesianProducts 160 160 def CartesianProducts(self): -
sage/categories/category.py
diff --git a/sage/categories/category.py b/sage/categories/category.py
a b A parent ``P`` is in a category ``C`` if 98 98 from sage.misc.abstract_method import abstract_method, abstract_methods_of_class 99 99 from sage.misc.lazy_attribute import lazy_attribute 100 100 from sage.misc.cachefunc import cached_method, cached_function 101 from sage.misc.c3 import C3_algorithm, C3_algorithm_set 101 102 #from sage.misc.misc import attrcall 102 103 103 104 from sage.structure.sage_object import SageObject … … def _join(categories, as_list): 135 136 136 137 # Ensure associativity by flattening JoinCategory's 137 138 # Invariant: the super categories of a JoinCategory are not JoinCategories themselves 138 categories = sum( (tuple(category. super_categories()) if isinstance(category, JoinCategory) else (category,)139 categories = sum( (tuple(category._super_categories) if isinstance(category, JoinCategory) else (category,) 139 140 for category in categories), ()) 140 141 141 142 # remove redundant categories which are super categories of others … … class Category(UniqueRepresentation, Sag 228 229 sage: from sage.categories.all import Category 229 230 sage: from sage.misc.lazy_attribute import lazy_attribute 230 231 sage: class As (Category): 231 ... @cached_method232 232 ... def super_categories(self): 233 233 ... return [] 234 234 ... … … class Category(UniqueRepresentation, Sag 238 238 ... f = fA 239 239 ... 240 240 sage: class Bs (Category): 241 ... @cached_method242 241 ... def super_categories(self): 243 242 ... return [As()] 244 243 ... … … class Category(UniqueRepresentation, Sag 247 246 ... return "B" 248 247 ... 249 248 sage: class Cs (Category): 250 ... @cached_method251 249 ... def super_categories(self): 252 250 ... return [As()] 253 251 ... … … class Category(UniqueRepresentation, Sag 257 255 ... f = fC 258 256 ... 259 257 sage: class Ds (Category): 260 ... @cached_method261 258 ... def super_categories(self): 262 259 ... return [Bs(),Cs()] 263 260 ... … … class Category(UniqueRepresentation, Sag 275 272 True 276 273 277 274 We construct a parent in the category Ds() (that is an instance of 278 Ds().parent_class , and check that it has access to all the275 Ds().parent_class), and check that it has access to all the 279 276 methods provided by all the categories, with the appropriate 280 277 inheritance order. 281 278 :: … … class Category(UniqueRepresentation, Sag 426 423 EXAMPLES:: 427 424 428 425 sage: class SemiprimitiveRings(Category): 429 ... @cached_method430 426 ... def super_categories(self): 431 427 ... return [Rings()] 432 428 ... … … class Category(UniqueRepresentation, Sag 610 606 # """ 611 607 # return hash(self.__category) # Any reason not to use id? 612 608 609 def _subcategory_hook_(self, C): 610 """ 611 Quick subcategory check. 612 613 INPUT: 614 615 ``C`` - a category 616 617 OUTPUT: 618 619 - True, if ``C`` is a subcategory of ``self``. 620 - False, if ``C`` is not a subcategory of ``self``. 621 - ``NotImplemented``, if a quick check was not enough to determine 622 whether ``C`` is a subcategory of ``self`` or not. 623 624 NOTE: 625 626 This default implementation tests whether the parent class 627 of ``C`` is a subclass of the parent class of ``self``. 628 Currently (as of trac ticket #11900) this is a complete 629 subcategory test. But this will change with trac ticket #11935. 630 631 The aim of this method is to offer a framework to add 632 a cheap test for subcategories. When doing 633 ``C.is_subcategory(self)`` (note the reverse order of 634 ``self`` and ``C``), this method is usually called first. 635 Only if it returns ``NotImplemented``, 636 :meth:`is_subcategory` will determine the list of super 637 categories of ``C``. 638 639 It is not needed to deal with the case that ``C`` is 640 ``self``, because this is the first test that is done 641 in :meth:`is_subcategory`. 642 643 OUTPUT: 644 645 - ``True``, if it is certain that ``C`` is a subcategory 646 of self. 647 - ``False``, if it is certain that ``C`` is no subcategory 648 of self. 649 - ``NotImplemented``, if the question whether ``C`` is 650 a subcategory of self shall be answered by studying the 651 list of super-categories of ``C``. 652 653 EXAMPLE:: 654 655 sage: Rings()._subcategory_hook_(Rings()) 656 True 657 """ 658 # return True if C is a proper sub-category of self; 659 # It is not needed to consider the case "C is self". 660 # return False if C is clearly not a sub-category 661 # of self. 662 # return NotImplemented otherwise. 663 return issubclass(C.parent_class, self.parent_class) 664 613 665 def __contains__(self, x): 614 666 """ 615 667 Membership testing … … class Category(UniqueRepresentation, Sag 807 859 Category of sets with partial maps, 808 860 Category of objects] 809 861 """ 810 done = set() 811 linear_extension = [] 812 for cat in reversed(self._all_super_categories_raw()): 813 if not cat in done: 814 done.add(cat) 815 linear_extension.append(cat) 816 linear_extension.reverse() 862 return C3_algorithm(self,'_super_categories','_all_super_categories',False) 863 864 @lazy_attribute 865 def _all_super_categories_proper(self): 866 r""" 867 All proper super categories of this category. 868 869 NOTE: 870 871 By trac ticket #11943, the order of super categories 872 is determined by the C3 algorithm. 873 874 EXAMPLES:: 875 876 sage: C = GradedHopfAlgebrasWithBasis(QQ).abstract_category(); C 877 Category of abstract graded hopf algebras with basis over Rational Field 878 sage: C._all_super_categories_proper 879 [Category of graded hopf algebras over Rational Field, 880 Category of graded bialgebras over Rational Field, 881 Category of graded algebras over Rational Field, 882 Category of graded coalgebras over Rational Field, 883 Category of graded modules over Rational Field, 884 Category of hopf algebras over Rational Field, 885 Category of bialgebras over Rational Field, 886 Category of algebras over Rational Field, 887 ...] 888 """ 889 return C3_algorithm(self,'_super_categories','_all_super_categories',True) 890 891 @lazy_attribute 892 def _set_of_super_categories(self): 893 """ 894 The frozen set of all proper super categories of this category. 895 896 NOTE: 897 898 This is used for a speed-up in category containment tests. 899 900 TEST:: 901 902 sage: C = HopfAlgebrasWithBasis(GF(7)) 903 sage: C._set_of_super_categories == frozenset(C._all_super_categories_proper) 904 True 905 """ 906 try: 907 return frozenset(self.__dict__['_all_super_categories_proper']) 908 except KeyError: 909 return frozenset(C3_algorithm_set(self,'_super_categories','_all_super_categories',True)) 910 911 def all_super_categories(self, proper=False): 912 """ 913 Returns the list of all super categories of this category. 914 915 NOTE: 916 917 By trac ticket #11943, the order of super categories 918 is determined by the :func:`~sage.misc.c3.C3_algorithm`. 919 920 INPUT: 921 922 - ``proper``: a boolean; defaults to False. Whether to exclude this category. 923 924 NOTE: 925 926 This method exists for convenience. However, the developers 927 are advised to use the lazy attribute ``_all_super_categories`` 928 or ``_all_super_categories_proper`` when asking for the super 929 categories - simply because a lazy attribute is much faster 930 than any method. 931 932 EXAMPLE:: 933 934 sage: Sets().all_super_categories() 935 [Category of sets, Category of sets with partial maps, Category of objects] 936 sage: Sets().all_super_categories(proper=True) 937 [Category of sets with partial maps, Category of objects] 938 sage: Sets().all_super_categories() is Sets()._all_super_categories 939 True 940 sage: Sets().all_super_categories(proper=True) is Sets()._all_super_categories_proper 941 True 942 943 """ 817 944 if proper: 818 return linear_extension 819 else: 820 return [self] + linear_extension 945 return self._all_super_categories_proper 946 return self._all_super_categories 947 948 @lazy_attribute 949 def _super_categories(self): 950 """ 951 Returns the immediate super categories of this category. 952 953 NOTE: 954 955 For implementing this lazy attribute, you must provide 956 a method :meth:`super_categories`. However, the developers 957 are advised to use the lazy attribute ``_super_categories`` 958 when asking for the super categories - simply because a 959 lazy attribute is much faster than any method. 960 """ 961 return self.super_categories() 962 963 def super_categories(self): 964 """ 965 Implement this method to provide the *immediate* super categories. 966 967 NOTE: 968 969 The order of immediate super categories matters in exactly the 970 same way as the order of base classes of a Python class 971 matters. In fact, by trac ticket #11943, the category 972 framework of Sage uses the same algorithm for determining the 973 order on the list of *all* super categories that Python is 974 using for the method resolution order of new style classes. 975 976 NOTE: 977 978 In order to avoid overhead, the developers are advised to use 979 the lazy attribute ``_super_categories``. While 980 ``super_categories()`` must be provided, but it should not be 981 called, for the sake of speed. 982 """ 983 raise NotImplementedError 984 985 def _test_category_graph(self, **options): 986 """ 987 Verify that Python's method resolution coincides with the category graph. 988 989 NOTE: 990 991 By trac ticket #11943, the list of categories returned by :meth:`all_super_categories` 992 is supposed to correspond to the method resolution order of the parent or element 993 classes. This method verifies it. 994 995 TODO: 996 997 Currently, it won't work for hom categories. 998 999 EXAMPLE:: 1000 1001 sage: C = HopfAlgebrasWithBasis(QQ) 1002 sage: C.parent_class.mro() == [X.parent_class for X in C._all_super_categories] + [object] 1003 True 1004 sage: C.element_class.mro() == [X.element_class for X in C._all_super_categories] + [object] 1005 True 1006 sage: TestSuite(C).run() # indirect doctest 1007 1008 """ 1009 tester = self._tester(**options) 1010 tester.assert_(self.parent_class.mro() == [C.parent_class for C in self._all_super_categories] + [object]) 1011 tester.assert_(self.element_class.mro() == [C.element_class for C in self._all_super_categories] + [object]) 821 1012 822 1013 # def construction(self): 823 1014 # return (self.__class__,) … … class Category(UniqueRepresentation, Sag 861 1052 # super categories, but not on the base (except when the super categories depend 862 1053 # on the base). When that is done, calling the cached function will be needed again. 863 1054 #return dynamic_class("%s.parent_class"%self.__class__.__name__, 864 # tuple(cat.parent_class for cat in self.super_categories ()),1055 # tuple(cat.parent_class for cat in self.super_categories), 865 1056 # self.ParentMethods, 866 1057 # reduction = (getattr, (self, "parent_class"))) 867 1058 return dynamic_class_internal.f("%s.parent_class"%self.__class__.__name__, 868 tuple(cat.parent_class for cat in self. super_categories()),1059 tuple(cat.parent_class for cat in self._super_categories), 869 1060 self.ParentMethods, 870 1061 reduction = (getattr, (self, "parent_class"))) 871 1062 … … class Category(UniqueRepresentation, Sag 892 1083 # super categories, but not on the base (except when the super categories depend 893 1084 # on the base). When that is done, calling the cached function will be needed again. 894 1085 #return dynamic_class("%s.element_class"%self.__class__.__name__, 895 # (cat.element_class for cat in self.super_categories ()),1086 # (cat.element_class for cat in self.super_categories), 896 1087 # self.ElementMethods, 897 1088 # reduction = (getattr, (self, "element_class")) 898 1089 # ) 899 1090 return dynamic_class_internal.f("%s.element_class"%self.__class__.__name__, 900 tuple(cat.element_class for cat in self. super_categories()),1091 tuple(cat.element_class for cat in self._super_categories), 901 1092 self.ElementMethods, 902 1093 reduction = (getattr, (self, "element_class"))) 903 1094 … … class Category(UniqueRepresentation, Sag 916 1107 917 1108 918 1109 # Operations on the lattice of categories 919 @cached_method920 1110 def is_subcategory(self, c): 921 1111 """ 922 1112 Returns True if self is naturally embedded as a subcategory of c. … … class Category(UniqueRepresentation, Sag 961 1151 """ 962 1152 if c is self: 963 1153 return True 964 assert(isinstance(c, Category)) 965 if isinstance(c, JoinCategory): 966 return all(self.is_subcategory(x) for x in c.super_categories()) 967 if isinstance(self, JoinCategory): 968 for cat in self.super_categories(): 969 if cat.is_subcategory(c): 970 return True 971 return False 972 try: 973 cbase = c.base() 974 except (AttributeError, TypeError, NotImplementedError): 975 cbase = None 976 if cbase is not None: 977 try: 978 selfbase = self.base() 979 except (AttributeError, TypeError, NotImplementedError): 980 selfbase = None 981 if selfbase is not cbase: 982 return False 983 return c in self.all_super_categories() 1154 subcat_hook = c._subcategory_hook_(self) 1155 if subcat_hook is NotImplemented: 1156 return c in self._set_of_super_categories 1157 return subcat_hook 984 1158 985 1159 def or_subcategory(self, category = None): 986 1160 """ … … class Category(UniqueRepresentation, Sag 1040 1214 if isinstance(c, Category): 1041 1215 return self.is_subcategory(c) 1042 1216 else: 1043 return any(isinstance(cat, c) for cat in self. all_super_categories())1217 return any(isinstance(cat, c) for cat in self._all_super_categories) 1044 1218 1045 1219 @cached_method 1046 1220 def _meet_(self, other): … … class Category(UniqueRepresentation, Sag 1097 1271 # %time L = EllipticCurve('960d1').prove_BSD() 1098 1272 return self 1099 1273 else: 1100 return Category.join(self._meet_(sup) for sup in other. super_categories())1274 return Category.join(self._meet_(sup) for sup in other._super_categories) 1101 1275 1102 1276 @staticmethod 1103 1277 def meet(categories): … … class Category(UniqueRepresentation, Sag 1145 1319 Join of Category of groups and Category of commutative additive monoids 1146 1320 sage: J.super_categories() 1147 1321 [Category of groups, Category of commutative additive monoids] 1148 sage: J.all_super_categories(proper =True)1322 sage: J.all_super_categories(proper=True) 1149 1323 [Category of groups, 1150 1324 Category of monoids, 1151 1325 Category of semigroups, … … class Category(UniqueRepresentation, Sag 1234 1408 try: #if hasattr(self, "HomCategory"): 1235 1409 return self.HomCategory(self) 1236 1410 except AttributeError: 1237 return Category.join((category.hom_category() for category in self. super_categories()))1411 return Category.join((category.hom_category() for category in self._super_categories)) 1238 1412 1239 1413 def example(self, *args, **keywords): 1240 1414 """ … … def category_graph(categories = None): 1344 1518 categories = [ cat.an_instance() for cat in sage.categories.all.__dict__.values() if isinstance(cat, type) and issubclass(cat, Category) and cat not in abstract_classes_for_categories ] 1345 1519 cats = set() 1346 1520 for category in categories: 1347 for cat in category. all_super_categories():1521 for cat in category._all_super_categories: 1348 1522 cats.add(cat) 1349 1523 1350 1524 categories = cats … … def category_graph(categories = None): 1352 1526 for cat in categories: 1353 1527 g.add_vertex(cat._repr_object_names()) 1354 1528 for source in categories: 1355 for target in source. super_categories():1529 for target in source._super_categories: 1356 1530 g.add_edge([source._repr_object_names(), target._repr_object_names()]) 1357 1531 return g 1358 1532 … … class HomCategory(Category): 1364 1538 """ 1365 1539 An abstract base class for all categories of homsets 1366 1540 1367 The hierarchy of homset categories is built in parallel to that of 1368 their base categories (which is plain wrong!!!) 1541 .. todo:: 1542 1543 Get a consistent hierarchy of homset categories. Currently, it 1544 is built in parallel to that of their base categories (which 1545 is plain wrong!!!) 1369 1546 1370 1547 """ 1371 1548 def __init__(self, category, name=None): … … class HomCategory(Category): 1376 1553 - ``category`` -- the category whose Homsets are the objects of this category. 1377 1554 - ``name`` -- An optional name for this category. 1378 1555 1379 EXAMPLES:: 1556 EXAMPLES: 1557 1558 We need to skip one test, since the hierarchy of hom categories isn't 1559 consistent yet:: 1380 1560 1381 1561 sage: C = sage.categories.category.HomCategory(Rings()); C 1382 1562 Category of hom sets in Category of rings 1383 sage: TestSuite(C).run( )1563 sage: TestSuite(C).run(skip=['_test_category_graph']) 1384 1564 """ 1385 1565 Category.__init__(self, name) 1386 1566 self.base_category = category … … class HomCategory(Category): 1408 1588 1409 1589 """ 1410 1590 from sage.categories.category_types import Category_over_base 1411 for C in self. all_super_categories():1591 for C in self._all_super_categories_proper: 1412 1592 if isinstance(C,Category_over_base): 1413 1593 return C.base() 1414 1594 raise AttributeError, "This hom category has no base" 1415 1595 1416 @cached_method1417 1596 def super_categories(self): 1418 1597 """ 1419 1598 Returns the immediate super categories, as per :meth:`Category.super_categories`. … … class HomCategory(Category): 1425 1604 """ 1426 1605 return Category.join(self.extra_super_categories() + 1427 1606 [category.hom_category() 1428 for category in self.base_category. super_categories()],1607 for category in self.base_category._super_categories], 1429 1608 as_list=True) 1430 1609 @cached_method 1431 1610 def extra_super_categories(self): … … class JoinCategory(Category): 1457 1636 Join of Category of groups and Category of commutative additive monoids 1458 1637 sage: J.super_categories() 1459 1638 [Category of groups, Category of commutative additive monoids] 1460 sage: J.all_super_categories(proper =True)1639 sage: J.all_super_categories(proper=True) 1461 1640 [Category of groups, Category of monoids, Category of semigroups, Category of magmas, Category of commutative additive monoids, Category of commutative additive semigroups, Category of additive magmas, Category of sets, Category of sets with partial maps, Category of objects] 1462 1641 """ 1463 1642 … … class JoinCategory(Category): 1479 1658 sage: C = JoinCategory((Groups(), CommutativeAdditiveMonoids())); C 1480 1659 Join of Category of groups and Category of commutative additive monoids 1481 1660 sage: TestSuite(C).run() 1661 1482 1662 """ 1483 1663 assert(len(super_categories) >= 2) 1484 1664 assert(all(not isinstance(category, JoinCategory) for category in super_categories)) … … class JoinCategory(Category): 1500 1680 """ 1501 1681 return self._super_categories 1502 1682 1683 def _subcategory_hook_(self, C): 1684 """ 1685 Tells whether this join category contains another category as a subcategory. 1686 1687 INPUT: 1688 1689 ``C`` -- a category. 1690 1691 OUTPUT: 1692 1693 Whether ``C`` is sub-category of self or not. 1694 1695 NOTE: 1696 1697 ``C`` is sub-category of this join category if and only if it is sub-category 1698 for all super categories of this join category. 1699 1700 EXAMPLE:: 1701 1702 sage: QQ['x'].category().is_subcategory(Category.join([Rings(), VectorSpaces(QQ)])) # indirect doctest 1703 True 1704 1705 """ 1706 for X in self._super_categories: 1707 if not C.is_subcategory(X): 1708 return False 1709 return True 1710 1503 1711 def _repr_(self): 1504 1712 """ 1505 1713 Print representation. … … class JoinCategory(Category): 1516 1724 sage: Category.join((Sets().Facades(), Groups())) 1517 1725 Category of facade groups 1518 1726 """ 1519 categories = self. super_categories()1727 categories = self._super_categories 1520 1728 from sets_cat import Sets 1521 1729 if len(categories) == 2 and Sets().Facades() in categories: 1522 1730 categories = list(categories) 1523 1731 categories.remove(Sets().Facades()) 1524 1732 return "Category of facade %s"%(categories[0]._repr_object_names()) 1525 return "Join of %s"%(" and ".join(str(cat) for cat in self.super_categories()))1733 return "Join of %s"%(" and ".join(str(cat) for cat in categories)) -
sage/categories/category_types.py
diff --git a/sage/categories/category_types.py b/sage/categories/category_types.py
a b This is placed in a separate file from c 17 17 from sage.misc.cachefunc import cached_method 18 18 from sage.misc.latex import latex 19 19 from category import Category 20 from sage.categories.rings import Rings 21 _Rings = Rings() 20 from objects import Objects 22 21 23 22 #################################################################### 24 23 # Different types of categories … … class Elements(Category): 76 75 """ 77 76 return self.__object(x) 78 77 79 @cached_method80 78 def super_categories(self): 81 79 """ 82 80 EXAMPLES:: … … class Elements(Category): 88 86 89 87 check that this is what we want. 90 88 """ 91 from objects import Objects92 89 return [Objects()] 93 90 94 91 def object(self): … … class Sequences(Category): 153 150 from sage.rings.rational_field import QQ 154 151 return cls(QQ) 155 152 156 @cached_method157 153 def super_categories(self): 158 154 """ 159 155 EXAMPLES:: … … class Sequences(Category): 161 157 sage: Sequences(ZZ).super_categories() 162 158 [Category of objects] 163 159 """ 164 from objects import Objects165 160 return [Objects()] # Almost FiniteEnumeratedSets() except for possible repetitions 166 161 167 162 def _call_(self, x): … … class Category_over_base(Category): 208 203 Category.__init__(self, name) 209 204 self.__base = base 210 205 211 212 206 @classmethod 213 207 def an_instance(cls): 214 208 """ … … class Category_over_base(Category): 260 254 ############################################################# 261 255 # Category of objects over some base ring 262 256 ############################################################# 257 class AbelianCategory(Category): 258 def is_abelian(self): 259 return True 260 263 261 class Category_over_base_ring(Category_over_base): 264 262 def __init__(self, base, name=None): 265 assert base in _Rings, "base must be a ring" 263 from sage.categories.rings import Rings 264 assert base in Rings(), "base must be a ring" 266 265 Category_over_base.__init__(self, base, name) 267 266 self.__base = base 268 267 … … class Category_over_base_ring(Category_o 273 272 """ 274 273 return self.base() 275 274 276 class AbelianCategory(Category):277 def is_abelian(self):278 return True279 280 275 ############################################################# 281 276 # Category of objects in some ambient object 282 277 ############################################################# … … class SimplicialComplexes(Category): 358 353 sage: TestSuite(SimplicialComplexes()).run() 359 354 """ 360 355 361 @cached_method362 356 def super_categories(self): 363 357 """ 364 358 EXAMPLES:: … … class SimplicialComplexes(Category): 366 360 sage: SimplicialComplexes().super_categories() 367 361 [Category of objects] 368 362 """ 369 from objects import Objects370 363 return [Objects()] # anything better? 371 364 372 365 ############################################################# … … class ChainComplexes(Category_module): 389 382 sage: TestSuite(ChainComplexes(RationalField())).run() 390 383 """ 391 384 392 @cached_method393 385 def super_categories(self): 394 386 """ 395 387 EXAMPLES:: … … class ChainComplexes(Category_module): 397 389 sage: ChainComplexes(Integers(9)).super_categories() 398 390 [Category of objects] 399 391 """ 400 from objects import Objects401 392 return [Objects()] # anything better? -
sage/categories/classical_crystals.py
diff --git a/sage/categories/classical_crystals.py b/sage/categories/classical_crystals.py
a b class ClassicalCrystals(Category_singlet 55 55 running ._test_stembridge_local_axioms() . . . pass 56 56 """ 57 57 58 @cached_method59 58 def super_categories(self): 60 59 r""" 61 60 EXAMPLES:: -
sage/categories/coalgebras.py
diff --git a/sage/categories/coalgebras.py b/sage/categories/coalgebras.py
a b class Coalgebras(Category_over_base_ring 45 45 46 46 sage: TestSuite(Coalgebras(ZZ)).run() 47 47 """ 48 @cached_method49 48 def super_categories(self): 50 49 """ 51 50 EXAMPLES:: -
sage/categories/commutative_additive_groups.py
diff --git a/sage/categories/commutative_additive_groups.py b/sage/categories/commutative_additive_groups.py
a b class CommutativeAdditiveGroups(AbelianC 32 32 sage: TestSuite(CommutativeAdditiveGroups()).run() 33 33 """ 34 34 35 @cached_method36 35 def super_categories(self): 37 36 """ 38 37 EXAMPLES:: -
sage/categories/commutative_additive_monoids.py
diff --git a/sage/categories/commutative_additive_monoids.py b/sage/categories/commutative_additive_monoids.py
a b class CommutativeAdditiveMonoids(Categor 35 35 sage: TestSuite(CommutativeAdditiveMonoids()).run() 36 36 """ 37 37 38 @cached_method39 38 def super_categories(self): 40 39 """ 41 40 EXAMPLES:: -
sage/categories/commutative_additive_semigroups.py
diff --git a/sage/categories/commutative_additive_semigroups.py b/sage/categories/commutative_additive_semigroups.py
a b class CommutativeAdditiveSemigroups(Cate 36 36 37 37 """ 38 38 39 @cached_method40 39 def super_categories(self): 41 40 """ 42 41 EXAMPLES:: -
sage/categories/commutative_algebra_ideals.py
diff --git a/sage/categories/commutative_algebra_ideals.py b/sage/categories/commutative_algebra_ideals.py
a b Commutative algebra ideals 12 12 13 13 from sage.misc.cachefunc import cached_method 14 14 from category_types import Category_ideal, Category_in_ambient 15 from algebra_ideals import AlgebraIdeals 15 16 16 17 class CommutativeAlgebraIdeals(Category_ideal): 17 18 """ … … class CommutativeAlgebraIdeals(Category_ 66 67 """ 67 68 return self.ambient() 68 69 69 @cached_method70 70 def super_categories(self): 71 71 """ 72 72 EXAMPLES:: … … class CommutativeAlgebraIdeals(Category_ 74 74 sage: CommutativeAlgebraIdeals(QQ[x]).super_categories() 75 75 [Category of algebra ideals in Univariate Polynomial Ring in x over Rational Field] 76 76 """ 77 from algebra_ideals import AlgebraIdeals78 77 R = self.algebra() 79 78 return [AlgebraIdeals(R)] -
sage/categories/commutative_ring_ideals.py
diff --git a/sage/categories/commutative_ring_ideals.py b/sage/categories/commutative_ring_ideals.py
a b Commutative ring ideals 13 13 from sage.misc.cachefunc import cached_method 14 14 from category_types import Category_ideal 15 15 from sage.categories.commutative_rings import CommutativeRings 16 from ring_ideals import RingIdeals 16 17 17 18 class CommutativeRingIdeals(Category_ideal): 18 19 """ … … class CommutativeRingIdeals(Category_ide 45 46 raise TypeError, "R (=%s) must be a commutative ring"%R 46 47 Category_ideal.__init__(self, R) 47 48 48 @cached_method49 49 def super_categories(self): 50 50 """ 51 51 EXAMPLES:: … … class CommutativeRingIdeals(Category_ide 53 53 sage: CommutativeRingIdeals(ZZ).super_categories() 54 54 [Category of ring ideals in Integer Ring] 55 55 """ 56 from ring_ideals import RingIdeals57 56 R = self.ring() 58 57 return [RingIdeals(R)] -
sage/categories/covariant_functorial_construction.py
diff --git a/sage/categories/covariant_functorial_construction.py b/sage/categories/covariant_functorial_construction.py
a b class CovariantConstructionCategory(Cate 354 354 sage: sage.categories.algebra_functor.AlgebrasCategory.default_super_categories(FiniteMonoids(), QQ) 355 355 Category of monoid algebras over Rational Field 356 356 """ 357 return Category.join([getattr(cat, cls._functor_category)(*args) for cat in category. super_categories()])357 return Category.join([getattr(cat, cls._functor_category)(*args) for cat in category._super_categories]) 358 358 359 def is_subcategory(self, C): 360 if C is self: 361 return True 362 for X in self._super_categories: 363 if X.is_subcategory(C): 364 return True 365 return False 359 366 360 367 def __init__(self, category, *args): 361 368 """ … … class CovariantConstructionCategory(Cate 409 416 """ 410 417 return [] 411 418 412 @cached_method413 419 def super_categories(self): 414 420 """ 415 421 Returns the super categories of a construction category -
sage/categories/coxeter_groups.py
diff --git a/sage/categories/coxeter_groups.py b/sage/categories/coxeter_groups.py
a b class CoxeterGroups(Category_singleton): 97 97 running ._test_some_elements() . . . pass 98 98 """ 99 99 100 @cached_method101 100 def super_categories(self): 102 101 """ 103 102 EXAMPLES:: -
sage/categories/crystals.py
diff --git a/sage/categories/crystals.py b/sage/categories/crystals.py
a b class Crystals(Category_singleton): 82 82 running ._test_stembridge_local_axioms() . . . pass 83 83 """ 84 84 85 @cached_method86 85 def super_categories(self): 87 86 r""" 88 87 EXAMPLES:: -
sage/categories/division_rings.py
diff --git a/sage/categories/division_rings.py b/sage/categories/division_rings.py
a b class DivisionRings(Category_singleton): 31 31 sage: TestSuite(DivisionRings()).run() 32 32 """ 33 33 34 @cached_method35 34 def super_categories(self): 36 35 """ 37 36 EXAMPLES:: -
sage/categories/domains.py
diff --git a/sage/categories/domains.py b/sage/categories/domains.py
a b class Domains(Category_singleton): 32 32 sage: TestSuite(Domains()).run() 33 33 """ 34 34 35 @cached_method36 35 def super_categories(self): 37 36 """ 38 37 EXAMPLES:: -
sage/categories/enumerated_sets.py
diff --git a/sage/categories/enumerated_sets.py b/sage/categories/enumerated_sets.py
a b class EnumeratedSets(Category_singleton) 85 85 sage: TestSuite(C).run() 86 86 """ 87 87 88 @cached_method89 88 def super_categories(self): 90 89 """ 91 90 EXAMPLES:: -
sage/categories/euclidean_domains.py
diff --git a/sage/categories/euclidean_domains.py b/sage/categories/euclidean_domains.py
a b class EuclideanDomains(Category_singleto 31 31 sage: TestSuite(EuclideanDomains()).run() 32 32 """ 33 33 34 @cached_method35 34 def super_categories(self): 36 35 """ 37 36 EXAMPLES:: -
sage/categories/fields.py
diff --git a/sage/categories/fields.py b/sage/categories/fields.py
a b Fields 13 13 14 14 from sage.categories.category import Category 15 15 from sage.categories.category_singleton import Category_singleton, Category_contains_method_by_parent_class 16 from sage.categories.euclidean_domains import EuclideanDomains 17 from sage.categories.unique_factorization_domains import UniqueFactorizationDomains 18 from sage.categories.division_rings import DivisionRings 19 16 20 from sage.misc.cachefunc import cached_method 17 21 from sage.misc.lazy_attribute import lazy_class_attribute 18 22 from sage.rings.field import is_Field … … class Fields(Category_singleton): 43 47 sage: TestSuite(Fields()).run() 44 48 """ 45 49 46 @cached_method47 50 def super_categories(self): 48 51 """ 49 52 EXAMPLES:: … … class Fields(Category_singleton): 52 55 [Category of euclidean domains, Category of unique factorization domains, Category of division rings] 53 56 54 57 """ 55 from sage.categories.basic import EuclideanDomains, UniqueFactorizationDomains, DivisionRings56 58 return [EuclideanDomains(), UniqueFactorizationDomains(), DivisionRings()] 57 59 58 60 def __contains__(self, x): -
sage/categories/finite_groups.py
diff --git a/sage/categories/finite_groups.py b/sage/categories/finite_groups.py
a b class FiniteGroups(Category): 31 31 sage: C = FiniteGroups() 32 32 sage: TestSuite(C).run(verbose = True) 33 33 running ._test_category() . . . pass 34 running ._test_category_graph() . . . pass 34 35 running ._test_not_implemented_methods() . . . pass 35 36 running ._test_pickling() . . . pass 36 37 -
sage/categories/finite_permutation_groups.py
diff --git a/sage/categories/finite_permutation_groups.py b/sage/categories/finite_permutation_groups.py
a b class FinitePermutationGroups(Category): 33 33 sage: C = FinitePermutationGroups() 34 34 sage: TestSuite(C).run(verbose = True) 35 35 running ._test_category() . . . pass 36 running ._test_category_graph() . . . pass 36 37 running ._test_not_implemented_methods() . . . pass 37 38 running ._test_pickling() . . . pass 38 39 -
sage/categories/finite_semigroups.py
diff --git a/sage/categories/finite_semigroups.py b/sage/categories/finite_semigroups.py
a b class FiniteSemigroups(Category): 44 44 sage: C = FiniteSemigroups() 45 45 sage: TestSuite(C).run(verbose = True) 46 46 running ._test_category() . . . pass 47 running ._test_category_graph() . . . pass 47 48 running ._test_not_implemented_methods() . . . pass 48 49 running ._test_pickling() . . . pass 49 50 -
sage/categories/g_sets.py
diff --git a/sage/categories/g_sets.py b/sage/categories/g_sets.py
a b G-Sets 12 12 13 13 from sage.categories.category import Category 14 14 from sage.misc.cachefunc import cached_method 15 from sets_cat import Sets 15 16 16 17 ############################################################# 17 18 # GSets … … class GSets(Category): 51 52 #def construction(self): 52 53 # return (self.__class__, self.__G) 53 54 54 @cached_method55 55 def super_categories(self): 56 56 """ 57 57 EXAMPLES:: … … class GSets(Category): 59 59 sage: GSets(SymmetricGroup(8)).super_categories() 60 60 [Category of sets] 61 61 """ 62 from sets_cat import Sets63 62 return [Sets()] 64 63 65 64 @classmethod -
sage/categories/gcd_domains.py
diff --git a/sage/categories/gcd_domains.py b/sage/categories/gcd_domains.py
a b Gcd domains 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 from sage.categories.integral_domains import IntegralDomains 14 15 15 16 class GcdDomains(Category_singleton): 16 17 """ … … class GcdDomains(Category_singleton): 30 31 sage: TestSuite(GcdDomains()).run() 31 32 """ 32 33 33 @cached_method34 34 def super_categories(self): 35 35 """ 36 36 EXAMPLES:: … … class GcdDomains(Category_singleton): 38 38 sage: GcdDomains().super_categories() 39 39 [Category of integral domains] 40 40 """ 41 from sage.categories.integral_domains import IntegralDomains42 41 return [IntegralDomains()] 43 42 44 43 class ParentMethods: -
sage/categories/groupoid.py
diff --git a/sage/categories/groupoid.py b/sage/categories/groupoid.py
a b Groupoid 12 12 13 13 from sage.categories.category import Category 14 14 from sage.misc.cachefunc import cached_method 15 from sets_cat import Sets 15 16 16 17 class Groupoid(Category): 17 18 """ … … class Groupoid(Category): 57 58 #def construction(self): 58 59 # return (self.__class__, self.__G) 59 60 60 @cached_method61 61 def super_categories(self): 62 62 """ 63 63 EXAMPLES:: … … class Groupoid(Category): 65 65 sage: Groupoid(DihedralGroup(3)).super_categories() 66 66 [Category of sets] 67 67 """ 68 from sets_cat import Sets69 68 return [Sets()] # ??? 70 69 71 70 @classmethod -
sage/categories/groups.py
diff --git a/sage/categories/groups.py b/sage/categories/groups.py
a b class Groups(Category_singleton): 34 34 sage: TestSuite(Groups()).run() 35 35 """ 36 36 37 @cached_method38 37 def super_categories(self): 39 38 """ 40 39 EXAMPLES:: … … class Groups(Category_singleton): 344 343 [Category of hopf algebras with basis over Rational Field, Category of monoid algebras over Rational Field] 345 344 346 345 sage: Groups().example().algebra(ZZ).categories() 347 [Category of group algebras over Integer Ring, Category of hopf algebras with basis over Integer Ring, Category of bialgebras with basis over Integer Ring, Category of coalgebras with basis over Integer Ring, Category of hopf algebras over Integer Ring, Category of bialgebras over Integer Ring, Category of coalgebras over Integer Ring, Category of monoid algebras over Integer Ring, Category of semigroup algebras over Integer Ring, Category of algebras with basis over Integer Ring, Category of algebras over Integer Ring, Category of rings, Category of rngs, Category of semirings, Category of monoids, Category of semigroups, Category of magmas, Category of set algebras over Integer Ring, Category of modules with basis over Integer Ring, Category of modules over Integer Ring, Category of bimodules over Integer Ring on the left and Integer Ring on the right, Category of left modules over Integer Ring, Category of right modules over Integer Ring, Category of commutative additive groups, Category of commutative additive monoids, Category of commutative additive semigroups, Category of additive magmas, Category of sets, Category of sets with partial maps, Category of objects] 346 [Category of group algebras over Integer Ring, 347 Category of hopf algebras with basis over Integer Ring, 348 Category of bialgebras with basis over Integer Ring, 349 Category of monoid algebras over Integer Ring, 350 Category of semigroup algebras over Integer Ring, 351 Category of algebras with basis over Integer Ring, 352 Category of coalgebras with basis over Integer Ring, 353 Category of set algebras over Integer Ring, 354 Category of modules with basis over Integer Ring, 355 Category of hopf algebras over Integer Ring, 356 Category of bialgebras over Integer Ring, 357 Category of algebras over Integer Ring, 358 Category of rings, 359 Category of rngs, 360 Category of coalgebras over Integer Ring, 361 Category of modules over Integer Ring, 362 Category of bimodules over Integer Ring on the left and Integer Ring on the right, 363 Category of left modules over Integer Ring, 364 Category of right modules over Integer Ring, 365 Category of commutative additive groups, 366 Category of semirings, 367 Category of commutative additive monoids, 368 Category of commutative additive semigroups, 369 Category of additive magmas, 370 Category of monoids, 371 Category of semigroups, 372 Category of magmas, 373 Category of sets, 374 Category of sets with partial maps, 375 Category of objects] 348 376 """ 349 377 from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis 350 378 return [HopfAlgebrasWithBasis(self.base_ring())] -
sage/categories/hecke_modules.py
diff --git a/sage/categories/hecke_modules.py b/sage/categories/hecke_modules.py
a b Hecke modules 13 13 from sage.categories.category_types import Category_module 14 14 from sage.misc.cachefunc import cached_method 15 15 from sage.categories.category import HomCategory 16 from sage.categories.all import ModulesWithBasis 16 17 17 18 class HeckeModules(Category_module): 18 19 r""" … … class HeckeModules(Category_module): 73 74 raise TypeError, "R (=%s) must be a commutative ring"%R 74 75 Category_module.__init__(self, R, "Hecke modules") 75 76 76 @cached_method77 77 def super_categories(self): 78 78 """ 79 79 EXAMPLES:: … … class HeckeModules(Category_module): 81 81 sage: HeckeModules(QQ).super_categories() 82 82 [Category of modules with basis over Rational Field] 83 83 """ 84 from sage.categories.all import ModulesWithBasis85 84 R = self.base_ring() 86 85 return [ModulesWithBasis(R)] 87 86 -
sage/categories/highest_weight_crystals.py
diff --git a/sage/categories/highest_weight_crystals.py b/sage/categories/highest_weight_crystals.py
a b class HighestWeightCrystals(Category_sin 58 58 running ._test_stembridge_local_axioms() . . . pass 59 59 """ 60 60 61 @cached_method62 61 def super_categories(self): 63 62 r""" 64 63 EXAMPLES:: -
sage/categories/hopf_algebras.py
diff --git a/sage/categories/hopf_algebras.py b/sage/categories/hopf_algebras.py
a b class HopfAlgebras(Category_over_base_ri 32 32 sage: TestSuite(HopfAlgebras(ZZ)).run() 33 33 """ 34 34 35 @cached_method36 35 def super_categories(self): 37 36 """ 38 37 EXAMPLES:: -
sage/categories/integral_domains.py
diff --git a/sage/categories/integral_domains.py b/sage/categories/integral_domains.py
a b Integral domains 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 from sage.categories.commutative_rings import CommutativeRings 15 from sage.categories.domains import Domains 14 16 15 17 class IntegralDomains(Category_singleton): 16 18 """ … … class IntegralDomains(Category_singleton 29 31 sage: TestSuite(IntegralDomains()).run() 30 32 """ 31 33 32 @cached_method33 34 def super_categories(self): 34 35 """ 35 36 EXAMPLES:: … … class IntegralDomains(Category_singleton 37 38 sage: IntegralDomains().super_categories() 38 39 [Category of commutative rings, Category of domains] 39 40 """ 40 from sage.categories.basic import CommutativeRings, Domains41 41 return [CommutativeRings(), Domains()] 42 42 43 43 class ParentMethods: -
sage/categories/left_modules.py
diff --git a/sage/categories/left_modules.py b/sage/categories/left_modules.py
a b Left modules 10 10 11 11 from category_types import Category_over_base_ring 12 12 from sage.misc.cachefunc import cached_method 13 from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups 13 14 14 15 #?class LeftModules(Category_over_base_rng): 15 16 class LeftModules(Category_over_base_ring): … … class LeftModules(Category_over_base_rin 30 31 sage: TestSuite(LeftModules(ZZ)).run() 31 32 """ 32 33 33 @cached_method34 34 def super_categories(self): 35 35 """ 36 36 EXAMPLES:: … … class LeftModules(Category_over_base_rin 38 38 sage: LeftModules(QQ).super_categories() 39 39 [Category of commutative additive groups] 40 40 """ 41 from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups42 41 return [CommutativeAdditiveGroups()] 43 42 44 43 class ParentMethods: -
sage/categories/magmas.py
diff --git a/sage/categories/magmas.py b/sage/categories/magmas.py
a b class Magmas(Category_singleton): 36 36 sage: C = Magmas() 37 37 sage: TestSuite(C).run(verbose=True) 38 38 running ._test_category() . . . pass 39 running ._test_category_graph() . . . pass 39 40 running ._test_not_implemented_methods() . . . pass 40 41 running ._test_pickling() . . . pass 41 42 42 43 """ 43 @cached_method44 44 def super_categories(self): 45 45 """ 46 46 EXAMPLES:: -
sage/categories/matrix_algebras.py
diff --git a/sage/categories/matrix_algebras.py b/sage/categories/matrix_algebras.py
a b Matrix algebras 12 12 13 13 from category_types import Category_over_base_ring 14 14 from sage.misc.cachefunc import cached_method 15 from algebras import Algebras 15 16 16 17 class MatrixAlgebras(Category_over_base_ring): 17 18 """ … … class MatrixAlgebras(Category_over_base_ 27 28 sage: TestSuite(MatrixAlgebras(ZZ)).run() 28 29 """ 29 30 30 @cached_method31 31 def super_categories(self): 32 32 """ 33 33 EXAMPLES:: … … class MatrixAlgebras(Category_over_base_ 35 35 sage: MatrixAlgebras(QQ).super_categories() 36 36 [Category of algebras over Rational Field] 37 37 """ 38 from algebras import Algebras39 38 R = self.base_ring() 40 39 return [Algebras(R)] -
sage/categories/modular_abelian_varieties.py
diff --git a/sage/categories/modular_abelian_varieties.py b/sage/categories/modular_abelian_varieties.py
a b Modular abelian varieties 12 12 13 13 from category_types import Category_over_base 14 14 from sage.misc.cachefunc import cached_method 15 from sets_cat import Sets 15 16 16 17 class ModularAbelianVarieties(Category_over_base): 17 18 """ … … class ModularAbelianVarieties(Category_o 49 50 """ 50 51 return self.base() 51 52 52 @cached_method53 53 def super_categories(self): 54 54 """ 55 55 EXAMPLES:: … … class ModularAbelianVarieties(Category_o 57 57 sage: ModularAbelianVarieties(QQ).super_categories() 58 58 [Category of sets] 59 59 """ 60 from sets_cat import Sets61 60 return [Sets()] # FIXME -
sage/categories/modules.py
diff --git a/sage/categories/modules.py b/sage/categories/modules.py
a b Modules 14 14 from sage.categories.category import HomCategory 15 15 from category_types import Category_module 16 16 from sage.misc.cachefunc import cached_method 17 from sage.categories.bimodules import Bimodules 17 18 from sage.categories.fields import Fields 18 19 _Fields = Fields() 19 20 from vector_spaces import VectorSpaces … … class Modules(Category_module): 120 121 result._reduction[2]['dispatch'] = False 121 122 return result 122 123 123 @cached_method124 124 def super_categories(self): 125 125 """ 126 126 EXAMPLES:: … … class Modules(Category_module): 136 136 [Category of modules over Rational Field] 137 137 """ 138 138 R = self.base_ring() 139 from sage.categories.bimodules import Bimodules140 139 return [Bimodules(R,R)] 141 140 142 141 class ParentMethods: -
sage/categories/monoids.py
diff --git a/sage/categories/monoids.py b/sage/categories/monoids.py
a b class Monoids(Category_singleton): 46 46 sage: TestSuite(C).run() 47 47 48 48 """ 49 @cached_method50 49 def super_categories(self): 51 50 """ 52 51 Returns a list of the immediate super categories of ``self``. -
sage/categories/number_fields.py
diff --git a/sage/categories/number_fields.py b/sage/categories/number_fields.py
a b class NumberFields(Category_singleton): 55 55 sage: TestSuite(NumberFields()).run() 56 56 """ 57 57 58 @cached_method59 58 def super_categories(self): 60 59 """ 61 60 EXAMPLES:: -
sage/categories/objects.py
diff --git a/sage/categories/objects.py b/sage/categories/objects.py
a b class Objects(Category): 38 38 sage: TestSuite(Objects()).run() 39 39 """ 40 40 41 @cached_method42 41 def super_categories(self): 43 42 """ 44 43 EXAMPLES:: -
sage/categories/partially_ordered_monoids.py
diff --git a/sage/categories/partially_ordered_monoids.py b/sage/categories/partially_ordered_monoids.py
a b class PartiallyOrderedMonoids(Category_s 33 33 sage: TestSuite(PartiallyOrderedMonoids()).run() 34 34 """ 35 35 36 @cached_method37 36 def super_categories(self): 38 37 """ 39 38 EXAMPLES:: -
sage/categories/pointed_sets.py
diff --git a/sage/categories/pointed_sets.py b/sage/categories/pointed_sets.py
a b Pointed sets 13 13 from sage.categories.category import Category 14 14 from sage.categories.category_singleton import Category_singleton 15 15 from sage.misc.cachefunc import cached_method 16 from sets_cat import Sets 16 17 17 18 class PointedSets(Category_singleton): 18 19 """ … … class PointedSets(Category_singleton): 31 32 # import sage.sets.all 32 33 # return sage.sets.all.Set(X, pt) 33 34 34 @cached_method35 35 def super_categories(self): 36 36 """ 37 37 EXAMPLES:: … … class PointedSets(Category_singleton): 39 39 sage: PointedSets().super_categories() 40 40 [Category of sets] 41 41 """ 42 from sets_cat import Sets43 42 return [Sets()] # ??? -
sage/categories/primer.py
diff --git a/sage/categories/primer.py b/sage/categories/primer.py
a b Functorial constructions 546 546 Category of algebras over Rational Field, 547 547 Category of rings, 548 548 Category of rngs, 549 Category of semirings,550 549 Category of vector spaces over Rational Field, 551 550 Category of modules over Rational Field, 552 551 Category of bimodules over Rational Field on the left and Rational Field on the right, 553 552 Category of left modules over Rational Field, 554 553 Category of right modules over Rational Field, 555 554 Category of commutative additive groups, 555 Category of semirings, 556 556 Category of commutative additive monoids, 557 557 Category of commutative additive semigroups, 558 558 Category of additive magmas, … … Wrapup: 613 613 Writing a new category 614 614 ---------------------- 615 615 616 Each category should come with a good example, in sage.categories.examples. 616 Each category `C` **must** be provided with a method ``C.super_categories()`` 617 and *can* be provided with a method ``C._subcategory_hook_(D)``. Also, it 618 may be needed to insert `C` into the output of the ``super_categories()`` method 619 of some other category. This determines the position of `C` in the category graph. 617 620 618 The order between super categories should not be mathematically 619 relevant (otherwise this usually means the category hierarchy is 620 wrong). On the other hand, it should be consistent, to help Python 621 build the method resolution order for the generated classes (it always 622 respects inheritance, and tries to respect the order of the bases). 621 A category *may* provide methods that can be used by all its objects, 622 respectively by all elements of its objects. 623 623 624 The current convention is to order them lexicographically w.r.t. the 625 following criterions: 624 Each category *should* come with a good example, in sage.categories.examples. 625 626 Inserting the new category into the category graph 627 .................................................. 628 629 ``C.super_categories()`` must return a list of categories, namely 630 the *immediate* super categories of `C`. The generic method 631 ``C.all_super_categories()`` will recursively determine the list 632 of *all* super categories of `C`, by using the so-called C3 algorithm, 633 that is also used for the method resolution order of new-style classes 634 in Python (see trac ticket #11943). 635 636 Of course, if you know that your new category `C` is immediate 637 super category of an existing category `D`, then you should modify 638 `D`'s ``super_categories`` method so that `C` is included. 639 640 Although the order between super categories should not be mathematically 641 relevant, the order *is* relevant for inheritance of methods. Namely, 642 a category can provide methods for all its objects and for the elements 643 for all its objects. If `P` is an object in the category `C` and if 644 `C_1` and `C_2` are both super categories of `C` defining some method 645 ``foo``, then `P` will use `C_1`'s version of ``foo`` only if `C_1` 646 appears in ``C.all_super_categories()`` before `C_2`. 647 648 Also, the C3 algorithm will only be able to determine a consistent order 649 on the list of all super categories if the orders on the different lists 650 of *immediate* super categories is sane. See :func:`sage.misc.c3.C3_algorithm` 651 and :meth:`sage.categories.category.Category.all_super_categories` for examples. 652 653 It is thus useful to follow certain conventions when ordering the 654 immediate super categories. The current convention is to order them 655 lexicographically w.r.t. the following criteria: 626 656 627 657 - Graded... or Finite dimensional... first 628 658 - ...WithBasis first … … This gives the following order:: 652 682 Category of algebras over Rational Field, 653 683 Category of rings, 654 684 Category of rngs, 655 Category of semirings,656 Category of monoids,657 Category of semigroups,658 Category of magmas,659 685 Category of coalgebras over Rational Field, 660 686 Category of vector spaces over Rational Field, 661 687 Category of modules over Rational Field, … … This gives the following order:: 663 689 Category of left modules over Rational Field, 664 690 Category of right modules over Rational Field, 665 691 Category of commutative additive groups, 692 Category of semirings, 666 693 Category of commutative additive monoids, 667 694 Category of commutative additive semigroups, 668 695 Category of additive magmas, 696 Category of monoids, 697 Category of semigroups, 698 Category of magmas, 669 699 Category of sets, 670 700 Category of sets with partial maps, 671 701 Category of objects] 672 702 673 Todo: any better convention? Maybe we should further specify that subcategories of Modules() go first? 703 When in doubt, ``C.is_subcategory(D)`` returns True if and only 704 if `D` appears in ``C.all_super_categories()``. However, 705 creating the list of all super categories is an expensive 706 operation that can sometimes be avoided. For example, if 707 both `C` and `D` are categories defined over a base, but the 708 bases differ, then they can not be subcategories of each other. 709 710 If such a short-path is known, one can implement a method 711 ``_subcategory_hook_``. ``C.is_subcategory(D)`` first calls 712 ``D._subcategory_hook_(C)``. If this returns ``NotImplemented``, then 713 ``C.is_subcategory(D)`` tries to find ``D`` in 714 ``C.all_super_categories()``. Otherwise, ``C.is_subcategory(D)`` 715 returns the result of ``D._subcategory_hook_(C)``. 716 717 By default, ``D._subcategory_hook_(C)`` tests 718 ``issubclass(C.parent_class,D.parent_class)``, which is very often 719 giving the right answer:: 720 721 sage: Rings()._subcategory_hook_(Algebras(QQ)) 722 True 723 sage: HopfAlgebras(QQ)._subcategory_hook_(Algebras(QQ)) 724 False 725 sage: Algebras(QQ)._subcategory_hook_(HopfAlgebras(QQ)) 726 True 727 728 Methods for objects and elements 729 ................................ 730 731 Different objects of the same category share some algebraic features, and 732 very often these features can be encoded in a method, in a generic way. 733 For example, for every commutative additive monoid, it makes sense to ask 734 for the sum of a list of elements. Sage's category framework allows to 735 provide a generic implementation for all objects of a category. 736 737 If you want to provide your new category with generic methods for objects 738 (or elements of objects), then you simply add an attribute called 739 ``ParentMethods`` (or ``ElementMethods``) carrying a class. The methods 740 of that class will automatically become methods of the objects (or the 741 elements). For instance:: 742 743 sage: P.<x,y> = ZZ[] 744 sage: P.sum([x,y,1]) 745 x + y + 1 746 sage: P.sum.__module__ 747 'sage.categories.commutative_additive_monoids' 748 sage: P.sum.__func__ is CommutativeAdditiveMonoids().ParentMethods.sum.__func__ 749 True 750 751 We recommend to study the code of one example:: 752 753 sage: C = CommutativeAdditiveMonoids() 754 sage: C?? # not tested 674 755 675 756 Caveats 676 757 ------- -
sage/categories/principal_ideal_domains.py
diff --git a/sage/categories/principal_ideal_domains.py b/sage/categories/principal_ideal_domains.py
a b Principal ideal domains 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 from sage.categories.unique_factorization_domains import UniqueFactorizationDomains 14 15 15 16 class PrincipalIdealDomains(Category_singleton): 16 17 """ … … class PrincipalIdealDomains(Category_sin 36 37 sage: TestSuite(PrincipalIdealDomains()).run() 37 38 """ 38 39 39 @cached_method40 40 def super_categories(self): 41 41 """ 42 42 EXAMPLES:: … … class PrincipalIdealDomains(Category_sin 44 44 sage: PrincipalIdealDomains().super_categories() 45 45 [Category of unique factorization domains] 46 46 """ 47 from sage.categories.basic import UniqueFactorizationDomains48 47 return [UniqueFactorizationDomains()] 49 48 50 49 class ParentMethods: -
sage/categories/quotient_fields.py
diff --git a/sage/categories/quotient_fields.py b/sage/categories/quotient_fields.py
a b from sage.categories.category import Cat 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 14 from sage.misc.abstract_method import abstract_method 15 from sage.categories.fields import Fields 15 16 16 17 class QuotientFields(Category_singleton): 17 18 """ … … class QuotientFields(Category_singleton) 29 30 sage: TestSuite(QuotientFields()).run() 30 31 """ 31 32 32 @cached_method33 33 def super_categories(self): 34 34 """ 35 35 EXAMPLES:: … … class QuotientFields(Category_singleton) 37 37 sage: QuotientFields().super_categories() 38 38 [Category of fields] 39 39 """ 40 from sage.categories.fields import Fields41 40 return [Fields()] 42 41 43 42 class ParentMethods: -
sage/categories/right_modules.py
diff --git a/sage/categories/right_modules.py b/sage/categories/right_modules.py
a b Right modules 10 10 11 11 from category_types import Category_over_base_ring 12 12 from sage.misc.cachefunc import cached_method 13 from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups 13 14 14 15 ##?class RightModules(Category_over_base_rng): 15 16 class RightModules(Category_over_base_ring): … … class RightModules(Category_over_base_ri 30 31 sage: TestSuite(RightModules(ZZ)).run() 31 32 """ 32 33 33 @cached_method34 34 def super_categories(self): 35 35 """ 36 36 EXAMPLES:: … … class RightModules(Category_over_base_ri 38 38 sage: RightModules(QQ).super_categories() 39 39 [Category of commutative additive groups] 40 40 """ 41 from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups42 41 return [CommutativeAdditiveGroups()] 43 42 44 43 class ParentMethods: -
sage/categories/ring_ideals.py
diff --git a/sage/categories/ring_ideals.py b/sage/categories/ring_ideals.py
a b Ring ideals 12 12 13 13 from category_types import Category_ideal 14 14 from sage.misc.cachefunc import cached_method 15 from modules import Modules 15 16 from sage.categories.rings import Rings 16 17 _Rings = Rings() 17 18 … … class RingIdeals(Category_ideal): 57 58 raise TypeError, "R (=%s) must be a ring"%R 58 59 Category_ideal.__init__(self, R) 59 60 60 @cached_method61 61 def super_categories(self): 62 62 """ 63 63 EXAMPLES:: … … class RingIdeals(Category_ideal): 67 67 sage: RingIdeals(QQ).super_categories() 68 68 [Category of vector spaces over Rational Field] 69 69 """ 70 from modules import Modules71 70 R = self.ring() 72 71 return [Modules(R)] -
sage/categories/rings.py
diff --git a/sage/categories/rings.py b/sage/categories/rings.py
a b Rings 11 11 # http://www.gnu.org/licenses/ 12 12 #****************************************************************************** 13 13 14 from sage.categories.rngs import Rngs 15 from sage.categories.semirings import Semirings 14 16 from sage.categories.category import Category 15 17 from sage.categories.category_singleton import Category_singleton 16 18 from category import HomCategory … … class Rings(Category_singleton): 42 44 in the category ``Algebras(P)``. 43 45 """ 44 46 45 @cached_method46 47 def super_categories(self): 47 48 """ 48 49 EXAMPLES:: … … class Rings(Category_singleton): 50 51 sage: Rings().super_categories() 51 52 [Category of rngs, Category of semirings] 52 53 """ 53 from sage.categories.rngs import Rngs54 from sage.categories.semirings import Semirings55 54 return [Rngs(), Semirings()] 56 55 57 56 class ParentMethods: -
sage/categories/rngs.py
diff --git a/sage/categories/rngs.py b/sage/categories/rngs.py
a b Rngs 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 from commutative_additive_groups import CommutativeAdditiveGroups 15 from semigroups import Semigroups 14 16 15 17 class Rngs(Category_singleton): 16 18 """ … … class Rngs(Category_singleton): 31 33 sage: TestSuite(Rngs()).run() 32 34 """ 33 35 34 @cached_method35 36 def super_categories(self): 36 37 """ 37 38 EXAMPLES:: … … class Rngs(Category_singleton): 39 40 sage: Rngs().super_categories() 40 41 [Category of commutative additive groups, Category of semigroups] 41 42 """ 42 from commutative_additive_groups import CommutativeAdditiveGroups43 from semigroups import Semigroups44 43 return [CommutativeAdditiveGroups(), Semigroups()] 45 44 46 45 class ParentMethods: -
sage/categories/schemes.py
diff --git a/sage/categories/schemes.py b/sage/categories/schemes.py
a b Schemes 13 13 from sage.categories.category import Category, HomCategory 14 14 from sage.categories.category_types import Category_over_base 15 15 from sage.misc.cachefunc import cached_method 16 from sets_cat import Sets 16 17 17 18 def Schemes(X=None): 18 19 """ … … class Schemes_abstract(Category): 57 58 """ 58 59 Category.__init__(self, "Schemes") 59 60 60 @cached_method61 61 def super_categories(self): 62 62 """ 63 63 EXAMPLES:: … … class Schemes_abstract(Category): 65 65 sage: Schemes().super_categories() 66 66 [Category of sets] 67 67 """ 68 from sets_cat import Sets69 68 return [Sets()] 70 69 71 70 def _call_(self, x): … … class Schemes_over_base(Category_over_ba 203 202 """ 204 203 return self.base() 205 204 206 @cached_method207 205 def super_categories(self): 208 206 """ 209 207 EXAMPLES:: -
sage/categories/semigroups.py
diff --git a/sage/categories/semigroups.py b/sage/categories/semigroups.py
a b class Semigroups(Category_singleton): 42 42 sage: C = Semigroups() 43 43 sage: TestSuite(C).run(verbose=True) 44 44 running ._test_category() . . . pass 45 running ._test_category_graph() . . . pass 45 46 running ._test_not_implemented_methods() . . . pass 46 47 running ._test_pickling() . . . pass 47 48 48 49 """ 49 @cached_method50 50 def super_categories(self): 51 51 """ 52 52 EXAMPLES:: -
sage/categories/semirings.py
diff --git a/sage/categories/semirings.py b/sage/categories/semirings.py
a b Semirings 10 10 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 from sage.categories.commutative_additive_monoids import CommutativeAdditiveMonoids 14 from sage.categories.monoids import Monoids 13 15 from sage.misc.cachefunc import cached_method 14 16 15 17 class Semirings(Category_singleton): … … class Semirings(Category_singleton): 36 38 sage: TestSuite(Semirings()).run() 37 39 """ 38 40 39 @cached_method40 41 def super_categories(self): 41 42 """ 42 43 EXAMPLES:: … … class Semirings(Category_singleton): 44 45 sage: Semirings().super_categories() 45 46 [Category of commutative additive monoids, Category of monoids] 46 47 """ 47 from sage.categories.commutative_additive_monoids import CommutativeAdditiveMonoids48 from sage.categories.monoids import Monoids49 48 return [CommutativeAdditiveMonoids(), Monoids()] 50 49 51 50 class ParentMethods: -
sage/categories/sets_cat.py
diff --git a/sage/categories/sets_cat.py b/sage/categories/sets_cat.py
a b class Sets(Category_singleton): 157 157 158 158 """ 159 159 160 @cached_method161 160 def super_categories(self): 162 161 r""" 163 162 We include SetsWithPartialMaps between Sets and Objects so that we -
sage/categories/sets_with_partial_maps.py
diff --git a/sage/categories/sets_with_partial_maps.py b/sage/categories/sets_with_partial_maps.py
a b SetsWithPartialMaps 13 13 from sage.categories.category import Category, HomCategory 14 14 from sage.categories.category_singleton import Category_singleton 15 15 from sage.misc.cachefunc import cached_method 16 from objects import Objects 16 17 17 18 class SetsWithPartialMaps(Category_singleton): 18 19 """ … … class SetsWithPartialMaps(Category_singl 41 42 # import sage.sets.all 42 43 # return sage.sets.all.Set(X, pt) 43 44 44 @cached_method45 45 def super_categories(self): 46 46 """ 47 47 EXAMPLES:: … … class SetsWithPartialMaps(Category_singl 49 49 sage: SetsWithPartialMaps().super_categories() 50 50 [Category of objects] 51 51 """ 52 from objects import Objects53 52 return [Objects()] 54 53 55 54 class HomCategory(HomCategory): -
sage/categories/unique_factorization_domains.py
diff --git a/sage/categories/unique_factorization_domains.py b/sage/categories/unique_factorization_domains.py
a b Unique factorization domains 11 11 from sage.categories.category import Category 12 12 from sage.categories.category_singleton import Category_singleton 13 13 from sage.misc.cachefunc import cached_method 14 from sage.categories.gcd_domains import GcdDomains 14 15 15 16 class UniqueFactorizationDomains(Category_singleton): 16 17 """ … … class UniqueFactorizationDomains(Categor 30 31 sage: TestSuite(UniqueFactorizationDomains()).run() 31 32 """ 32 33 33 @cached_method34 34 def super_categories(self): 35 35 """ 36 36 EXAMPLES:: … … class UniqueFactorizationDomains(Categor 38 38 sage: UniqueFactorizationDomains().super_categories() 39 39 [Category of gcd domains] 40 40 """ 41 from sage.categories.gcd_domains import GcdDomains42 41 return [GcdDomains()] 43 42 44 43 class ParentMethods: -
sage/categories/vector_spaces.py
diff --git a/sage/categories/vector_spaces.py b/sage/categories/vector_spaces.py
a b class VectorSpaces(Category_module): 110 110 """ 111 111 return self.base_ring() 112 112 113 @cached_method114 113 def super_categories(self): 115 114 """ 116 115 EXAMPLES:: -
sage/categories/weyl_groups.py
diff --git a/sage/categories/weyl_groups.py b/sage/categories/weyl_groups.py
a b class WeylGroups(Category_singleton): 49 49 sage: TestSuite(C).run() 50 50 """ 51 51 52 @cached_method53 52 def super_categories(self): 54 53 r""" 55 54 EXAMPLES:: -
new file sage/misc/c3.pyx
diff --git a/sage/misc/c3.pyx b/sage/misc/c3.pyx new file mode 100644
- + 1 """ 2 The C3 algorithm 3 4 The C3 algorithm is used as method resolution order for new style 5 classes in Python. The implementation here is used to order the list 6 of super categories of a category. 7 8 AUTHOR: 9 10 - Simon King (2011-11): initial version. 11 """ 12 13 include "../ext/python.pxi" 14 15 cpdef list C3_algorithm(object start, str bases, str attribute, bint proper): 16 """ 17 The C3 algorithm. 18 19 NOTE: 20 21 This implementation is used to order the list of super categories of a 22 category; see :meth:`~sage.categories.category.Category.all_super_categories`. 23 By consequence, the list of super categories exactly corresponds to the 24 method resolution order of the parent or element class of a category. 25 This is because Python uses the same algorithm (of course in a different 26 implementation) as method resolution order for new style classes. 27 28 INPUT: 29 30 - ``start`` (object): The returned list is built upon data 31 provided by certain attributes of ``start``. 32 - ``bases`` (string): The name of an attribute of ``start`` 33 providing a list of objects. 34 - ``attribute`` (string): The name of an attribute of the 35 objects provided in ``getattr(start,bases)``. That attribute 36 is supposed to provide a list. 37 38 ASSUMPTIONS: 39 40 Our implementation of the algorithm only works on lists of 41 objects that compare equal if and only if they are identical. 42 43 OUTPUT: 44 45 A list, the result of the C3 algorithm applied to the list 46 ``[getattr(X,attribute) for X in getattr(start,bases)]``. 47 48 EXAMPLES: 49 50 We start with an example of categories with an inconsistent 51 base classes of a new class:: 52 53 sage: class X(Category): 54 ... def super_categories(self): 55 ... return [Objects()] 56 sage: class X(Category): 57 ... def super_categories(self): 58 ... return [Objects()] 59 sage: class Y(Category): 60 ... def super_categories(self): 61 ... return [Objects()] 62 sage: class A(Category): 63 ... def super_categories(self): 64 ... return [X(),Y()] 65 sage: class B(Category): 66 ... def super_categories(self): 67 ... return [Y(),X()] 68 sage: class Foo(Category): 69 ... def super_categories(self): 70 ... return [A(),B()] 71 sage: F = Foo() 72 73 Python is not able to create a consistent method resolution order 74 for the parent class:: 75 76 sage: F.parent_class 77 Traceback (most recent call last): 78 ... 79 TypeError: Cannot create a consistent method resolution 80 order (MRO) for bases X.parent_class, Y.parent_class 81 82 Since the C3 algorithm is used for determining the list of 83 all super categories (by trac ticket #11943), a similar error 84 arises here:: 85 86 sage: F.all_super_categories() 87 Traceback (most recent call last): 88 ... 89 ValueError: Can not merge the items Category of x, Category of y. 90 91 Next, we demonstrate how our implementation of the C3 algorithm 92 is used to compute the list of all super categories:: 93 94 sage: C = Category.join([HopfAlgebrasWithBasis(QQ), FiniteEnumeratedSets()]) 95 sage: from sage.misc.c3 import C3_algorithm 96 sage: C3_algorithm(C,'_super_categories','_all_super_categories',True)==C._all_super_categories_proper 97 True 98 sage: C3_algorithm(C,'_super_categories','_all_super_categories',False)==C._all_super_categories 99 True 100 101 By trac ticket #11943, the following consistency tests are part 102 of the test suites of categories (except for hom categories):: 103 104 sage: C.parent_class.mro() == [x.parent_class for x in C.all_super_categories()]+[object] 105 True 106 sage: C.element_class.mro() == [x.element_class for x in C.all_super_categories()]+[object] 107 True 108 109 """ 110 # The lists in the arguments are reverted, 111 # so that we can do pop() in lieue of pop(0). 112 # In addition, containedness in the tail is tested using lists. 113 cdef list out 114 if proper: 115 out = [] 116 else: 117 out = [start] 118 cdef list args = getattr(start,bases) 119 if not args: 120 return out 121 cdef list curr_tail, tmp_tail 122 cdef set curr_set, tmp_set 123 cdef object curr_obj 124 cdef bint next_item_found 125 cdef list heads = [] 126 cdef list tails = [] 127 cdef list tailsets = [] 128 for curr_obj in args: 129 curr_tail = getattr(curr_obj, attribute) 130 heads.append(curr_tail[0]) 131 tmp_tail = PyList_GetSlice(curr_tail,1,PyList_GET_SIZE(curr_tail)) 132 PyList_Reverse(tmp_tail) 133 tails.append(tmp_tail) 134 tailsets.append(set(tmp_tail)) 135 cdef int i,j, lenargs 136 lenargs = len(heads) 137 for i from 0<=i<lenargs: 138 curr_tail = <list>PyList_GET_ITEM(tails,i) 139 if curr_tail is None: 140 continue 141 curr_set = <set>PyList_GET_ITEM(tailsets,i) 142 O = <object>PyList_GET_ITEM(heads,i) 143 next_item_found=True 144 for j from 0<=j<i: 145 tmp_tail = <list>PyList_GET_ITEM(tails,j) 146 if tmp_tail is None: 147 continue 148 tmp_set = <set>PyList_GET_ITEM(tailsets,j) 149 X = <object>PyList_GET_ITEM(heads,j) 150 if X is O: 151 try: 152 X = tmp_tail.pop() 153 heads[j] = X 154 tmp_set.remove(X) 155 except IndexError: 156 tails[j] = None 157 elif O in tmp_set: 158 next_item_found=False 159 break 160 if next_item_found: 161 for j from i<j<lenargs: 162 tmp_tail = <list>PyList_GET_ITEM(tails,j) 163 if tmp_tail is None: 164 continue 165 tmp_set = <set>PyList_GET_ITEM(tailsets,j) 166 X = <object>PyList_GET_ITEM(heads,j) 167 if X is O: 168 try: 169 X = tmp_tail.pop() 170 heads[j] = X 171 tmp_set.remove(X) 172 except IndexError: 173 tails[j] = None 174 elif O in tmp_set: 175 next_item_found=False 176 break 177 if next_item_found: 178 out.append(O) 179 try: 180 O = curr_tail.pop() 181 heads[i] = O 182 curr_set.remove(O) 183 except IndexError: 184 tails[i] = None 185 186 i = -1 187 # Either we need to raise an error, or the list is done. 188 if tails.count(None)<lenargs: 189 raise ValueError, "Can not merge the items %s."%', '.join([repr(heads[i]) for i,t in enumerate(tails) if t is not None]) 190 return out 191 192 cpdef frozenset C3_algorithm_set(object start, str bases, str attribute, bint proper): 193 """ 194 Return the result of :func:`C3_algorithm` as a frozen set. 195 196 EXAMPLE: 197 198 This function is used internally for creating the set of all 199 super categories of a category. Since a containment test is 200 much faster for sets than for lists, this provides some 201 speed-up for the category framework. See trac ticket #11943:: 202 203 sage: Rings()._set_of_super_categories 204 frozenset([...]) 205 sage: Rings()._set_of_super_categories == frozenset(Rings().all_super_categories(proper=True)) 206 True 207 208 """ 209 return frozenset(C3_algorithm(start,bases,attribute,proper))