Opened 7 years ago

Last modified 2 years ago

#20515 new enhancement

Proper idiom for defining an axiom as the intersection of two axioms defined in the same category.

Reported by: Nicolas M. Thiéry Owned by:
Priority: minor Milestone: sage-wishlist
Component: categories Keywords:
Cc: Merged in:
Authors: Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by Nicolas M. Thiéry)

Let Cs be a category, where three axioms are defined, A, A1, A2, with A being the intersection of A1 and A2. The natural implementation would look like:

    from sage.categories.category_with_axiom import CategoryWithAxiom, all_axioms

    all_axioms += ("A", "A1", "A2")

    class Cs(Category):
        def super_categories(self):
            return [Objects()]

        class SubcategoryMethods:
            def A1(self):
                return self._with_axiom("A1")
            def A2(self):
                return self._with_axiom("A2")
            def A(self):
                return self._with_axiom("A")

        class A1(CategoryWithAxiom):
            pass

        class A2(CategoryWithAxiom):
            def A1_extra_super_categories(self):
                return [Cs().A()]

        class A(CategoryWithAxiom):
            def extra_super_categories(self):
                return [Cs().A1(), Cs().A2()]

However this triggers an infinite recursion loop:

    sage: Cs().A()
    RuntimeError: maximum recursion depth exceeded while calling a Python object

This is because Cs().A2().A1_extra_super_categories() does not return a strict super category of the to-be-constructed category, which is forbidden by the current specifications:

http://doc.sagemath.org/html/en/reference/categories/sage/categories/category_with_axiom.html#id2

A workaround is to define A (or A1, or A2) in some super category:

    class C0(Category):
        def super_categories(self):
            return [Objects()]
        class SubcategoryMethods:
            def A(self):
                return self._with_axiom("A")
        class A(CategoryWithAxiom):
            pass

    class C1(Category):
        def super_categories(self):
            return [C0()]

        class SubcategoryMethods:
            def A1(self):
                return self._with_axiom("A1")
            def A2(self):
                return self._with_axiom("A2")

        class A1(CategoryWithAxiom):
            pass

        class A2(CategoryWithAxiom):
            def A1_extra_super_categories(self):
                return [C0.A()]

        class A(CategoryWithAxiom):
            def extra_super_categories(self):
                return [C1.A1(), C1.A2()]

Then,

    sage: C1().A1().A2() is C1().A()
    True
    sage: C1().A()
    Category of a1 a2 c1
    sage: C1().A().super_categories()
    [Category of a c0, Category of a2 c1, Category of a1 c1]
    sage: C1().A1().A2() is C1().A()
    True

See #18265 for a concrete instance where this workaround is currently used when none of A, A1, A2 make sense in a strict super category. A better idiom would be desirable if more use cases appear.

Change History (2)

comment:1 Changed 7 years ago by Nicolas M. Thiéry

Description: modified (diff)

comment:2 Changed 2 years ago by Matthias Köppe

Milestone: sage-7.2sage-wishlist
Note: See TracTickets for help on using tickets.