#15927: What are the requirements on super_categories?
--------------------------+----------------------------------
   Reporter:  darij       |            Owner:
       Type:  defect      |           Status:  new
   Priority:  major       |        Milestone:  sage-6.2
  Component:  categories  |         Keywords:  C3, categories
  Merged in:              |          Authors:
  Reviewers:              |  Report Upstream:  N/A
Work issues:              |           Branch:
     Commit:              |     Dependencies:
   Stopgaps:              |
--------------------------+----------------------------------
 I've started this discussion on #10963 and that's also where the fix
 should probably be done (if only to avoid some ugly mergery), but since
 it's a separate issue I'm opening a new ticket for it.

 The Sage categories primer (`src/sage/categories/primer.py`) says that,
 when you specify a category,
 {{{
 ``C.super_categories()`` *must* return a list of categories, namely
 the *immediate* super categories of `C`.
 }}}

 I asked whether this means that it is FORBIDDEN to provide non-immediate
 supercategories (i.e., categories which are redundant because they are
 forced by transitivity using the rest of the list). If so, it means that
 creating a category is harder than the tutorial implies, because not only
 does one have to ensure that one has added all new relations to the poset
 of categories, but one also must get rid of all the old relations that
 have become redundant through the new relations created.

 I have done some tests. Apparently there *is* some need for irredundancy:

 {{{
 sage: class Gggps(Category):
     def super_categories(self):
         return [Groups(), Groups(), Groups()]
 ....:
 sage: Gggps()
 ---------------------------------------------------------------------------
 KeyError                                  Traceback (most recent call
 last)
 <ipython-input-38-ef76ba7c6662> in <module>()
 ----> 1 Gggps()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/classcall_metaclass.so in
 sage.misc.classcall_metaclass.ClasscallMetaclass.__call__
 (sage/misc/classcall_metaclass.c:1282)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in __classcall__(cls, *args,
 **options)
     463         if isinstance(cls, DynamicMetaclass):
     464             cls = cls.__base__
 --> 465         return super(Category, cls).__classcall__(cls, *args,
 **options)
     466
     467     def __init__(self, s=None):

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/cachefunc.so in
 sage.misc.cachefunc.WeakCachedFunction.__call__
 (sage/misc/cachefunc.c:6182)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/structure/unique_representation.pyc in __classcall__(cls,
 *args, **options)
    1019             True
    1020         """
 -> 1021         instance = typecall(cls, *args, **options)
    1022         assert isinstance( instance, cls )
    1023         if instance.__class__.__reduce__ ==
 CachedRepresentation.__reduce__:

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/classcall_metaclass.so in
 sage.misc.classcall_metaclass.typecall
 (sage/misc/classcall_metaclass.c:1665)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in __init__(self, s)
     502                 raise TypeError, "Argument string must be a
 string."
     503         self.__class__ =
 dynamic_class("%s_with_category"%self.__class__.__name__,
 --> 504                                        (self.__class__,
 self.subcategory_class, ),
     505                                        cache = False, reduction =
 None,
     506                                        doccls=self.__class__)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in subcategory_class(self)
    1288         """
    1289         return self._make_named_class('subcategory_class',
 'SubcategoryMethods',
 -> 1290                                       cache=False,
 picklable=False)
    1291
    1292     @lazy_attribute

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in _make_named_class(self, name,
 method_provider, cache, picklable)
    1244             reduction = None
    1245         return dynamic_class(class_name,
 -> 1246                              tuple(getattr(cat,name) for cat in
 self._super_categories_for_classes),
    1247                              method_provider_cls,
 prepend_cls_bases = False, doccls = doccls,
    1248                              reduction = reduction, cache = cache)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in
 _super_categories_for_classes(self)
    1038             [Category of rngs, Category of semirings]
    1039         """
 -> 1040         self._all_super_categories
    1041         return self._super_categories_for_classes
    1042

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in _all_super_categories(self)
     885                                            for cat in
 self._super_categories] +
     886
 [self._super_categories],
 --> 887                                           category_sort_key)
     888         if not sorted(result, key = category_sort_key,
 reverse=True) == result:
     889             warn("Inconsistent sorting results for all super
 categories of %s"%self.__class__)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/c3_controlled.so in
 sage.misc.c3_controlled.C3_sorted_merge (sage/misc/c3_controlled.c:4459)()

 KeyError: (28672, 99)
 }}}
 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/classcall_metaclass.so in
 sage.misc.classcall_metaclass.ClasscallMetaclass.__call__
 (sage/misc/classcall_metaclass.c:1282)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in __classcall__(cls, *args,
 **options)
     463         if isinstance(cls, DynamicMetaclass):
     464             cls = cls.__base__
 --> 465         return super(Category, cls).__classcall__(cls, *args,
 **options)
     466
     467     def __init__(self, s=None):

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/cachefunc.so in
 sage.misc.cachefunc.WeakCachedFunction.__call__
 (sage/misc/cachefunc.c:6182)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/structure/unique_representation.pyc in __classcall__(cls,
 *args, **options)
    1019             True
    1020         """
 -> 1021         instance = typecall(cls, *args, **options)
    1022         assert isinstance( instance, cls )
    1023         if instance.__class__.__reduce__ ==
 CachedRepresentation.__reduce__:

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/classcall_metaclass.so in
 sage.misc.classcall_metaclass.typecall
 (sage/misc/classcall_metaclass.c:1665)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in __init__(self, s)
     502                 raise TypeError, "Argument string must be a
 string."
     503         self.__class__ =
 dynamic_class("%s_with_category"%self.__class__.__name__,
 --> 504                                        (self.__class__,
 self.subcategory_class, ),
     505                                        cache = False, reduction =
 None,
     506                                        doccls=self.__class__)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in subcategory_class(self)
    1288         """
    1289         return self._make_named_class('subcategory_class',
 'SubcategoryMethods',
 -> 1290                                       cache=False,
 picklable=False)
    1291
    1292     @lazy_attribute

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in _make_named_class(self, name,
 method_provider, cache, picklable)
    1244             reduction = None
    1245         return dynamic_class(class_name,
 -> 1246                              tuple(getattr(cat,name) for cat in
 self._super_categories_for_classes),
    1247                              method_provider_cls,
 prepend_cls_bases = False, doccls = doccls,
    1248                              reduction = reduction, cache = cache)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in
 _super_categories_for_classes(self)
    1038             [Category of rngs, Category of semirings]
    1039         """
 -> 1040         self._all_super_categories
    1041         return self._super_categories_for_classes
    1042

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/lazy_attribute.so in
 sage.misc.lazy_attribute._lazy_attribute.__get__
 (sage/misc/lazy_attribute.c:1357)()

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/categories/category.pyc in _all_super_categories(self)
     885                                            for cat in
 self._super_categories] +
     886
 [self._super_categories],
 --> 887                                           category_sort_key)
     888         if not sorted(result, key = category_sort_key,
 reverse=True) == result:
     889             warn("Inconsistent sorting results for all super
 categories of %s"%self.__class__)

 /home/darij/gitsage/sage-5.13.beta1/local/lib/python2.7/site-
 packages/sage/misc/c3_controlled.so in
 sage.misc.c3_controlled.C3_sorted_merge (sage/misc/c3_controlled.c:4459)()

 KeyError: (28672, 99)
 }}}

 With only two `Groups()` it works. Now I'm wondering if this is a
 consequence of the algorithm not being intended for redundant input, or
 some unrelated C3 bug just showing up here. Either way, I'd prefer to see
 it fixed because ensuring irredundancy seems to be a pain not many
 category authors will want to inflict upon themselves.

--
Ticket URL: <http://trac.sagemath.org/ticket/15927>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.

Reply via email to