#20896: calling GF(2)**2 breaks CyclicPermutationGroup(10).algebra(GF(5))
------------------------------+------------------------
       Reporter:  dimpase     |        Owner:
           Type:  defect      |       Status:  new
       Priority:  major       |    Milestone:  sage-7.3
      Component:  categories  |   Resolution:
       Keywords:              |    Merged in:
        Authors:              |    Reviewers:
Report Upstream:  N/A         |  Work issues:
         Branch:              |       Commit:
   Dependencies:              |     Stopgaps:
------------------------------+------------------------

Comment (by nthiery):

 == Issue analysis ==

 Scratching this itch and similar ones we have been getting, I have
 been pondering these last days about the handling of "over base ring"
 categories in Sage.

 The issue is that, by design, `A3=Algebras(GF(3))` and
 `A5=Algebras(GF(5))` share the same element/parent/... classes.
 However the MRO for such classes is built to be consistent with a
 total order on categories, and that total order is built dynamically
 using little context; so hard to keep consistent. Hence the order we
 get for `A3` and `A5` need not be the same, and the MRO basically depends
 on which one has been built first. If one builds alternatively larger
 and larger hierarchies for `GF(5)` and `GF(3)` we are likely to hit an
 inconsistency at some point.

 == Aim: toward singleton categories ==

 This, together with other stuff I do (e.g. [1]) with colleagues from
 other systems (GAP, MMT, ...), finished to convince me that most of
 our categories should really be singleton categories, and not be
 parametrized.

 Let's see what this means for categories over a ring like
 `Algebras`. I originally followed the tradition of Axiom and MuPAD by
 having them be systematically parametrized by the base ring. However
 the series of issues we faced and are still facing shows that this
 does not scale.

 Instead, to provide generic code, tests, ... we want a collection of
 singleton categories like:

 - modules over rings
 - vector spaces (e.g. modules over fields)
 - polyonials over PIDs

 After all, the code provided in e.g. `ParentMethods` will always be
 the same, regardless of the parameters of the category (well, that's
 not perfectly true; there were idioms for this in Axiom and MuPAD
 which we could try to port over).

 Of course, there can be cases, e.g. for typechecking, where it's handy
 to model some finer category like `Algebras(GF(3))`. However such
 categories should really be implemented as thin wrappers on top of the
 previous ones.

 We had already discussed approaches in this direction, in particular
 with Simon. #15801 was a first step, but remaing issues show that this
 is not enough.

 == Proposition of design ==

 We keep our current `Category_over_base_ring`'s (`Modules`,
 `Algebras`, `HopfAlgebras`, ...). However they now are all singleton
 categories, meant to be called as:

      `Modules()`      ->     Modules over rings
      `Algebras()`     ->     Algebras over rings

 Whenever some of the above category needs to be refined depending on
 the properties on the base ring, we define some appropriate axiom.
 E.g. `VectorSpaces()` would be `Modules().OverFields()`. And we could
 eventually have categories like `Modules().OverPIDs()`,
 `Polynomials().OverPIDs()`.


 Now what happens if one calls `Algebras(QQ)`?

 As a syntactical sugar, this returns the join `Algebras() &
 Modules().Over(QQ)`.

 Fine, now what's this latter gadget? It's merely a place holder with two
 roles:

 - Store the information that the base ring is `QQ`

 - Investigate, upon construction, the properties of the base ring and
   set axioms appropriately (e.g. in this case `OverFields`).

 == Implementation details ==

 - In effect, `Modules().Over(QQ)` is pretty similar to a category with
   axiom. First in terms of syntax; also the handling of pretty
   printing will be of the same nature (we want the join
   `Algebras() & Modules().Over(QQ)`
   to be printed as `algebras over QQ`).

 - However, at this stage, we can't implement it directly using axioms
   since those are not parametrized. One option would be to generalize
   our axiom infrastructure to support parameters; however it's far
   from clear that we actually want to have this feature, and how it
   should be implemented. So I am inclined to not overengineer for now.

 - Some care will be needed for subcategory and containment testing.

 == Pros, cons, points to be discussed ==

 Pros:

 - Constructing `Algebras(QQ)` does not require constructing any of the
   super categories `Modules(QQ)` and such. Instead, this just requires
   `Modules()`, and the like which most likely have already been
   constructed.

 - There is no more need to fiddle with class creation as we used to
   do, and to have this special hack which causes `Modules(QQ)` to
   return `VectorSpaces(QQ)`. This just uses the standard
   infrastructure for axioms, joins, etc.

 - It's more explicit about the level of generality of the
   code. `Algebras().OverFields()` provide codes valid for any algebra
   over a field.

 - This makes it easier for buiding static documentation: there is a
   canonical instance for `Algebras()` which Sphinx could inspect.

 Cons:

 - The hierarchy of axioms OverFields, OverPIDs, ... will somewhat
   duplicate the existing hierarchy of axioms about rings. If we start
   having many of them, that could become cumbersome.

 - In a join like `Algebras() & ModulesOver(QQ)`, there is little
   control about whether the parent class for the former or the latter
   comes first. But that's no different than what happens for other
   axioms.

 - `C=Algebras().Over(QQ)` should definitely be a full subcategory of
   `Algebras()`. But this means that `Modules().Over(QQ)` won't appear
   in `C.structure()`. The base field won't appear either in
   `C.axioms()`. Therefore `C` cannot be reconstructed from its
   structure and axioms as we are generally aiming for. Maybe this is
   really calling for `Over(QQ)` to be an axiom.

 - This should be relatively quick and straightforward to implement and
   fully backward compatible. And we have a lot of tests.

 Points to be debated:

 - At some point, we will want to support semirings. Should we support
   them right away by having `Modules()` be the category of modules
   over a semiring? Same thing for `Algebras()`, ... It feels like
   overkill for now, but might be annoying to change later. Also where
   does the road end? We may want to support even weaker structures at
   some point.

 - What name for the axioms? `OverField`, or `OverFields`?

 - We want some syntax that, given e.g. `QQ` as input, returns
   `Algebras().OverFields()`. The typical use case is within the
   constructor of a parent that takes a base ring `K` as input, and
   wants to use the richest category possible based on the properties
   of `K`, but does not specifically care that `K` be stored in the
   category.

   Maybe something like `Algebras().Over(QQ, store_base_ring=False)`.

   We want this syntax to be as simple as possible, to encourage using
   it whenever there is no specific reason to do otherwise.


 [1] https://github.com/nthiery/sage-gap-semantic-interface

--
Ticket URL: <https://trac.sagemath.org/ticket/20896#comment:3>
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