Hi Bruce,

On 2018-05-18, Bruce <brucewestb...@gmail.com> wrote:
> As I understand it, in sage, the way to implement this is to have a 
> category.

Provided that what you are implementing does in fact form a mathematical
category (https://en.wikipedia.org/wiki/Category_(mathematics))

> However it seems there are two possibilities;
> I could put these methods in either ParentMethods or ElementMethods. I can 
> confused about which of these is preferable.

If you are talking about a method shared by all objects of the category:
It is ParentMethods. If you are talking about a method shared by
elements of objects of the category: It is ElementMethods.

> Let me be more specific. In mathematical terms I have things which I call 
> Tableaux.

When you say that *you* call it "Tableaux": Are you talking about a new
notion? Otherwise, you may find that what you want to implementing does
already exist in Sage. After all,

  sage: search_def("tableau")

gives plenty of things in Sage that have the word "tableau" in them.

> Then I can think of the set of Tableaux as the parent and lists of objects 
> as elements.

You say that you "think of the *set* of Tableaux" as the parent? That doesn't
sound promising at all. Although I don't know which notion you are using,
it seems likely to me that rather the *set* of all tableaux forms a category,
which means that each individual tableau is an object in that category.
And "parent" is just another word for "object of a sub-cateogory of the
category of sets". So, if there is a category of tableaux and if each
tableau has elements, then a tableau is a parent and its elements are,
well, its elements.

Is there a meaningful notion of a "morphism of tableaux" in your setting, so
that a morphism between two tableaux can be described as a mapping of
its elements? If there is, then it may certainly be reasonable to implement a
category of tableaux, with ParentMethods for generic implementations of
methods of tableaux and ElementMethods for generic implementations of
methods of elements of tableaux.

However, I think that this approach should really only be taken for
*generic* stuff that isn't time critical. The category framework should
not be used for specific implementations that depend on particular data
structures. These should rather be implemented in proper base classes.
And generic implementations tend to be slow, so if speed matters then it
should be implemented using special data structures and perhaps written
in Cython.

> The other problem I have is that I don't understand the Category, Parent, 
> Element structure. I have read the sage documentation
> and looked at the sage source code. The sage documentation seems more 
> focused on the needs of algebraic geometry than of combinatorics.

No surprise, since the mathematical notion of a category is intensely
used in algebra.

> I have struggled to find complete examples in the 
> combinat source code. As I understand it the key
> components are Parent.__init__  Element.__init__ _element_constructor_ but 
> I don't understand what these do or how they
> work together.

In a nutshell:

- If you implement a parent FOO, then FOO will be a subclass of
  sage.structure.parent.Parent, and at some point during FOO.__init__ the
  .__init__ methods of the base classes of FOO should of course be called.
  Hence, at some point, Parent.__init__(self, ...) will be called (maybe
  indirectly), and this is where the category of your new instance of FOO
  has to be declared.
- Similarly, if you are implementing the elements of FOO instance in a
  class BAR, then of course BAR will be a subclass of
  sage.structure.element.Element, and at some point during BAR.__init__
  also Element.__init__(self, P) has to be called (maybe indirectly),
  where P is the instance of FOO which `self` will be element of.
  Nothing more specific needs to be done in BAR.__init__ regarding the
  category framework.
- You did not mention another key component: Your class FOO has to have
  BAR assigned to a class attribute called "Element".
- FOO._element_constructor_ is a method that takes some arguments and
  returns an element of FOO. If P is an instance of FOO, then it ought
  to return an instance of P.element_class. Here, P.element_class is
  automatically created by Sage's category framework: It is a sub-class
  of both P.Element (i.e., BAR) and of P.category().parent_class (which
  is why FOO.__init__ needs to declare which category is to be used).
  It is in fact not always needed to implement FOO._element_constructor_
  explicitly: There is a default implementation, and having `FOO.Element=BAR`
  may be sufficient to make it work. But if there is particular input that
  BAR.__init__ won't handle then FOO._element_constructor_ is where you
  would implement a conversion.
  In that sense, _element_constructor_ is less of a key component than
  the `Element` attribute.
- Also, if your element class BAR implements arithmetic operations
  then you should be aware that some of Python's magic arithmetic
  methods such as __add__ or __mul__ have default implementations in
  Sage's base classe (sage.rings.ring.Ring etc), and these should *not*
  be overridden! Instead, you may implement the corresponding single
  underscore method (_add_, _mul_, _lmul_). The same holds for __repr__
  versus _repr_. Moreover, _add_ and _mul_ shouldn't just return instances
  of BAR, but of P.element_class (if P is the parent of the result of the
  arithmetic operation).
- Another key component: If there are canonical morphisms from other
  algebraic structures to your tableaux, then you may want to use them
  for automatic conversions (also known as "coercion map"). If a canonical
  morphism from `S` to `P` exists, then `P._coerce_map_from_(S)` should
  return True (it is also possible that it return the morphism to be used
  for automatic conversion). But be aware that this is only possible if
  the system of canonical morphisms is consistent: The identity map from
  P to P is a coercion map; there is at most one coercion map from S to
  P; and the composition of two coercion maps is a coercion map.

You can find a more detailed account on the category and coercion
framework including parents and elements in
http://doc.sagemath.org/html/en/thematic_tutorials/coercion_and_categories.html

> I am even confused about what the arguments are. It seems 
> that the arguments, or maybe just the order,
> are different for new style classes and old style classes.

I don't think old style classes are widely used in Sage. We talk here
about subclasses of sage.structure.parent.Parent and 
sage.structure.element.Element,
and these are of course new style classes.

Best regards,
Simon


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

Reply via email to