#20515: Proper idiom for defining an axiom as the intersection of two axioms
defined in the same category.
-------------------------------+------------------------
       Reporter:  nthiery      |        Owner:
           Type:  enhancement  |       Status:  new
       Priority:  minor        |    Milestone:  sage-7.2
      Component:  categories   |   Resolution:
       Keywords:               |    Merged in:
        Authors:               |    Reviewers:
Report Upstream:  N/A          |  Work issues:
         Branch:               |       Commit:
   Dependencies:               |     Stopgaps:
-------------------------------+------------------------
Description changed by nthiery:

Old description:

> 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
> }}}
>
> A better idiom would be desirable, for cases where none of `A`, `A1`,
> `A2` make sense in a strict super category.
>
> See #18265 for a concrete instance where this workaround is currently
> used.

New description:

 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.

--

--
Ticket URL: <http://trac.sagemath.org/ticket/20515#comment:1>
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 https://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.

Reply via email to