direct sums, products and other categorical constructions

186 views
Skip to first unread message

Simon Brandhorst

unread,
May 22, 2019, 5:19:08 AM5/22/19
to sage-devel
Right now I can do
sage: V = ZZ^2
sage
: D = V.direct_sum(V)
sage
: D
Free module of degree 4 and rank 4 over Integer Ring
Echelon basis matrix:
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]

But the result has forgotten that it is a direct sum.

Of a direct sum I expect, that it has a projection and a co-projection.
(this is how it is done in gap)
So I want to be able to type
sage: D.projection(0)
sage
: D.coprojection(0)

Then there could also be appropriate coercions.
The same holds for other direct sums in groups, vector spaces ....
Or for other constructions like a direct product, inverse limit ...

Maybe this is something for the category framework?
How would one implement it?

Vincent Delecroix

unread,
May 22, 2019, 9:23:37 AM5/22/19
to sage-...@googlegroups.com
I am not a big fan of bundling everything into a single
bigger object. What about returning a triple
(V, projections, coprojections)?

Simon King

unread,
May 22, 2019, 10:25:26 AM5/22/19
to sage-...@googlegroups.com
Hi Vincent,

On 2019-05-22, Vincent Delecroix <20100.d...@gmail.com> wrote:
> I am not a big fan of bundling everything into a single
> bigger object. What about returning a triple
> (V, projections, coprojections)?

I tend to argue that in the first place, SageMath is a maths software.
And mathematically, universal constructions do come "with batteries"
included. Hence, the projections and coprojections are part of the
construction and it makes sense to let them be part of the constructed
objects.

Here is a similar situation: When applying a construction functor, then
often a natural homomorphism is involved that is turned into a coercion
map and is thus part of the constructed object (a polynomial ring knows
the coercion map from its base ring).

I could imagine the following model:
- We do want unique parents. I.e., QQ^4 is unique.
- We want that the direct sum of QQ and QQ^3 yields different
coprojections than the direct sum of QQ^2 and QQ^2, even though the
constructed vector space is in both cases the same object, namely
QQ^4.
- Hence, a universal construction should be a wrapper. QQ^2+QQ^2 and
QQ+QQ^3 would be two different wrappers of the same object, each
providing different coprojections.

Perhaps the "Facade" framework can be used to implement it?

Best regards,
Simon

Nils Bruin

unread,
May 22, 2019, 12:36:20 PM5/22/19
to sage-devel
On Wednesday, May 22, 2019 at 7:25:26 AM UTC-7, Simon King wrote:

I tend to argue that in the first place, SageMath is a maths software.
And mathematically, universal constructions do come "with batteries"
included. Hence, the projections and coprojections are part of the
construction and it makes sense to let them be part of the constructed
objects.

I don't think you have to come to that conclusion. As the routine V.direct_sum says, it returns the direct sum as a free module, Of course the projections and coprojections should be available (either between the module and an explicit cartesian product, or as separate projections maps and section maps (possibly with the section stored on the projection), but if the direct sum is modelled as a free module (and for efficiency reasons you have to) then there is not really room to store these objects on that module itself. Plus, doing so opens up another can of memory leak problems.

Using the coercion framework to store the projections and coprojections is similarly problematic: there is no satisfactory answer to which object should keep which alive. Plus, with direct powers, it's not so clear where to project.

Returning the object as an element in an already implemented category together with the maps that follow naturally from the construction is definitely workable, and probably the most "basic" way of capturing the required datta. So I'd argue we should at least implement that basic interface. If someone wants to put some further sauce on that, it can be built on top.

Simon Brandhorst

unread,
May 23, 2019, 5:40:11 AM5/23/19
to sage-devel
I can live with (V, projections, coprojections)
but I dislike hiding everything in lists (or lists of lists, or lists of lists of lists..).
Being able to type VW.projections(1) would just be so much nicer.



Simon King

unread,
May 24, 2019, 8:14:04 AM5/24/19
to sage-...@googlegroups.com
Hi Simon,
+1.

But how? I think we do want unique parents. How do we want to
distinguish between "the same" object that was constructed in two different
universal ways?

There would be one possibility that would work without creating a
wrapper: An object X that was constructed by some construction functor F
applied to some more basic objects B1,...,Bn should be able to tell its
construction (there is X.construction()). So, if we want to distinguish,
say, $Q^4$ from $Q^3\oplus Q$, then we could simply use the pair
(CoproductFunctor, (Q^3,Q))
as key in the UniqueRepresentation cache.

Best regards,
Simon

Best regards,
Simon

Simon Brandhorst

unread,
May 27, 2019, 2:48:53 AM5/27/19
to sage-devel
Hi Simon,

I would agree that I want unique representation with simple "ambient" objects (usually constructed from an integer and maybe a ring). Then with complicated objects I am not so sure anymore. Say subgroups of a group and submodules of a module. There it might cause more trouble than benefit. Plus it is quite common to create
(hundred) thousands of subgroups/submodules during a computation.

Anyways that is a bit off topic.

In the example case of a direct sum of modules one could give the construction functor the input of
the two ambient spaces and the respective basis matrix of the modules.
If one calls projections/co projections it would create the objects again.
That could solve the memory leak issue? (but recreating the objects feels like a weird workaround.)

Simon King

unread,
May 29, 2019, 9:07:41 AM5/29/19
to sage-...@googlegroups.com
Hi Simon,

On 2019-05-27, Simon Brandhorst <sbran...@web.de> wrote:
> I would agree that I want unique representation with simple "ambient"
> objects (usually constructed from an integer and maybe a ring). Then with
> complicated objects I am not so sure anymore. Say subgroups of a group and
> submodules of a module. There it might cause more trouble than benefit.
> Plus it is quite common to create
> (hundred) thousands of subgroups/submodules during a computation.

If you do not keep a reference chain to said hundred thousands of
different subgroups, then they would be automatically removed from the
"UniqueRepresentation" cache. If not, it's a bug (admittedly we had
instances of that bug quite often).

So, at least at first, one could think that equipping the result of a
universal construction with (co)projections wouldn't interfere with
UniqueRepresentation's weak cache. That's where my original suggestion
came from.

However, each map such as a projection or coprojection does involve
references to domain or codomain. One of them can be weak (that's what we
do for coercion maps), but nonetheless adding the projections as attribute
to the constructed object X increases the likelyhood that X cannot be
garbage collected.

From that point of view, keeping the (co)projections or deleting them
should be in the decision of the user, they shouldn't be automatically
stored as attribute of the object X.

Best regards,
Simon

Reply all
Reply to author
Forward
0 new messages