On Tue, Apr 29, 2014 at 08:17:44PM +0200, Nathann Cohen wrote:
> Why did you have to move the code around, though ?
> What is the difference between sets.cartesian_product and
> categories.cartesian_product ?

<disclaimer>
My answer is most likely going to be a bit broad and include stuff you
already know; I am just taking the occasion to write a blurb that
could possibly end up somewhere in the documentation (typically as a
complement of cartesian_product?), if someone finds it useful.
</disclaimer>

There can be several ways to represent an element of a cartesian
product. The natural implementation is using a tuple (well, a wrapped
tuple). That's what the concrete class in
sets.cartesian_product.CartesianProduct does::

    sage: C = cartesian_product([GF(3), GF(5)])
    sage: type(C)
    <class 'sage.sets.cartesian_product.CartesianProduct_with_category'>
    sage: C.an_element()
    (0, 0)

But if you start from vector spaces it's natural to think of the
cartesian product as a direct sum, and therefore represent the
cartesian product by a vector space:

        sage: X = CombinatorialFreeModule(QQ, ['a','b']); X.rename("X")
        sage: Y = CombinatorialFreeModule(QQ, ['c','d']); Y.rename("Y")
        sage: C = cartesian_product([X,Y])
        sage: C
        X (+) Y
        sage: type(C)
        <class ...CombinatorialFreeModule...>

This vector space has a basis indexed by the disjoint unions of that
of X and of Y::

        sage: C.basis().keys()
        Disjoint union of Family ({'a', 'b'}, {'c', 'd'})
        sage: C.an_element()
        2*B[(0, 'a')] + 2*B[(0, 'b')] + 3*B[(1, 'c')]

So that's a second concrete implementation of a cartesian
product. There could be others (e.g. one could represent the cartesian
product of two permutation groups as a permutation group).

That's for the concrete classes. Then, you have generic code that
works in all cases (say an_element, one). This code goes in the
relevant abstract classes in the category. For example the code for
`an_element` is something about parents that are cartesian products of
sets; so it goes in the abstract class
Sets.CartesianProducts.ParentMethods. On the other hand `one` is about
monoids (in fact unital magmas), so it goes in
Monoids.CartesianProducts.ParentMethods (in
Magmas.Unital.CartesianProducts.ParentMethods after #10963).

The last player in the game is the `cartesian_product` object, as in
`cartesian_product([A,B,...])`. Its role is to look at the properties
of A,B,..., and decide on an appropriate concrete implementation and a
category. Technically, this object is a "covariant functorial
construction" and it's implemented in
sage.categories.cartesian_product. In practice, unless one wants to
use it as an example to create a new construction, there is no reason
to fiddle with it.

> Cool. I am trying to clean the CartesianProduct stuff of additive
> groups and it does not look good. The methods are not inherited from
> where they should -_-
> 
> Right now, my problem is that the __add__ method from a
> CombinatorialFreeModule is taken from my CommutativeAdditiveGroup.
> And I thought I could expect all those objects to have a .value
> argument, but apparently I can t >_<

The three points you probably are hitting here are:

- It's best to implement _add_ rather than __add__ (__add__ builds on
  _add_ and takes care of coercion for you). Equivalently you can
  implement the method 'summation' in the parent (that's what done for
  the product).

- Vector spaces are already endowed with their addition. Sounds like
  you accidently overrode it.

- Using .value directly breaks encapsulation and is thus
  implementation dependent. Instead, have a look at some generic
  method that manipulates an element of a cartesian product and see
  how its pieces are recovered there. E.g.:

        sage: C = cartesian_product([GF(3), GF(5)])
        sage: C.product??

Let me know if you would want me to have a look at the code.

> Okay, so I will try to see if I can guarantee correctness when you can't.....

I just meant the usual caveat "not tested=likely to be broken".

> > I am hesitant on whether _element_constructor should always directly
> > coerce the elements, or first check if they are already in the right
> > parent and if not call coercion.
> 
> Well, your pick. I barely understand what the dilemma is about :-P

Just about the "if" line I commented out in your code. Maybe it should
really be there. Or we should do a separate `if` for each set.

Cheers,
                                Nicolas
--
Nicolas M. ThiƩry "Isil" <nthi...@users.sf.net>
http://Nicolas.Thiery.name/

-- 
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 http://groups.google.com/group/sage-combinat-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to