sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.47k stars 487 forks source link

Infrastructure for modelling full subcategories #16340

Closed nthiery closed 10 years ago

nthiery commented 10 years ago

It has been desired for a while to be able to test, when B is a subcategory of A, whether it is a full subcategory or not; equivalently this is whether any A-morphism is a B-morphism (up to forgetfull functor; note that the converse always holds).

The main application is for #10668, which will let B.homset_class inherit from A.homset_class in this case and only in this case.

References

Implementation proposal

For each category C, we encode the following data: is C is a full subcategory of the join of its super categories? Informally, the question is whether C introduces more structure or operations. For the sake of the discussion, I am going to call C a structure category in this case, but a better name is to be found.

Here are some of the main structure categories in Sage, and the structure or main operation they introduce:

Possible implementation: provide a method C.is_structure_category() (name to be found). The default implementation would return True for a plain category and False for a CategoryWithAxiom. This would cover most cases, and require to implement foo methods only in a few categories (e.g. the Unital axiom categories).

Once we have this data encoded, we can implement recursively a (cached) method such as:

    sage: Rings().structure_super_categories()
    {Magmas(), AdditiveMagmas()}

(just take the union of the structure super categories of the super categories of ``self``, and add ``self`` if relevant).

It is now trivial to check whether a subcategory B of A is actually a full subcategory: they just need to have the same structure super categories! Hence is_full_subcategory can be written as:

    def is_full_subcategory(self, other):
        return self.is_subcategory(other) and
           len(self.structure_super_categories()) == len(other.structure_super_categories())

Advantages of this proposal

This requires very little data to be encoded, and should be quite cheap to compute.

This is generally useful; in particular, for a user, the structure super categories together with the axioms would give an interesting overview of a category:

    sage: Rings().structure_super_categories()
    {Magmas(), AdditiveMagmas()}
    sage: Rings().axioms()
    frozenset({'AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse', 'AdditiveUnital', 'Associative', 'Distributive', 'Unital'})

In fact, we could hope/want to always have:

    C is Category.join(C.structure_super_categories()).with_axioms(C.axioms())

which could be used e.g. for pickling by construction while exposing very little implementation details.

Bonus

Each structure category could name the main additional operations, so that we could have something like:

    sage: Magmas().new_operation()
    "+"
    sage: Rings().operations()
    {"+", "0", "*", "1"}

or maybe:

    sage: Rings().operations()
    {Category of additive magmas: "+",
     Category of additive unital additive magmas: "0",
     Category of magmas: "*",
     Category of unital magmas: "1"}

Limitation

The current model forces the following assumption: C \subset B \subset A is a chain of categories and C is a full subcategory of A, then C is a full subcategory of B and B is a full subcategory of A. In particular, we can't model situations where, within the context of C, any A morphism is in fact a B morphism because the B structure is rigid.

Example: C=Groups, B=Monoids, A=Semigroups.

This is documented in details in the methods .is_fullsubcategory and .full_super_categories.

Questions

CC: @sagetrac-sage-combinat @hivert @simon-king-jena @darijgr @nbruin @pjbruin @vbraun

Component: categories

Keywords: full subcategories, homset

Author: Nicolas M. Thiéry

Branch: eb621c7

Reviewer: Darij Grinberg, Travis Scrimshaw, Simon King

Issue created by migration from https://trac.sagemath.org/ticket/16340

pjbruin commented 10 years ago
comment:40

Replying to @nthiery:

Replying to @pjbruin:

This actually strengthens my conviction that "structure category" is not a well-defined notion.

It's perfectly defined: C is a structure category if whenever A and B are in C and phi is a morphism between A and B for any strict super category of C, then phi is a C morphism. And it coincides with the intuition we have of it: does C define some additional structure (typically an operation) that has to be preserved by C-morphisms.

OK, but what I meant is that this notion depends on what supercategories of C have been defined, not just on C itself.

In this example, it depends on how you define Rings(): either as Rngs() & Semigroups().Unital(), in which case it is just a join of categories without new structure, _or_ as Rngs().Unital(), in which it does have extra structure (at least at first sight; you have to know that the category code magically rearranges the construction to turn Rngs().Unital() into a join of larger categories). In fact, Semigroups().Unital() (= Monoids()) is not a structure category either; it is the join of Magmas().Unital() and Semigroups().

I don't see why Rngs().Unital() should suggest it's a structure category. A.Unital() is never a structure category unless A is the category defining Unital. That is A=Magmas().

Certainly, but this relies on the the implementation choice of defining Magmas().Unital(). I admit this may be a slightly silly example, but I could imagine a different scenario where the person implementing these categories did not think anyone would need unital magmas, and hence chose to define Unital() relative to a more specific category, which in an extreme case could be Rngs(). In that case Rings() = Rngs().Unital() would have been a structure category, while being mathematically exactly the same as the actual Rings().

I don't see why this should necessarily be the case; we would just encode for each direct supercategory (of which there are usually just one or two) whether it is a full supercategory.

Well, I tried, and the code stunk with duplication, urging me to do it differently :-) Feel free to try for yourself.

I wish I had the time, but given that I don't, the best I can do is to just add my perspective as a non-developer but potential user of the category framework...

This makes computing all full supercategories not any slower (and probably faster) than computing all supercategories,

Yup.

or presumably all "structure supercategories" for that matter.

Possibly so. There are few structure supercategories so that's rather cheap too.

But to find them I assume one needs to traverse all supercategories and pick out the ones that are structure supercategories, so the time would still depend on the number of all supercategories, or am I mistaken?

pjbruin commented 10 years ago
comment:41

(cut out of previous comment since this is somewhat off topic)

Replying to @nthiery:

In particular, it becomes painful for categories with axioms or functorial construction categories where the super categories are computed automatically for you.

What is a functorial construction category? From the documentation it appears that the idea is that one first defines a construction in some "abstract" sense, and only then decides in which category it takes its values, or even to construct a completely new category for this. I realise that the code doesn't have to follow mathematical definitions exactly, but this seems to be quite the opposite of the usual pattern of doing things, where defining a function, functor or natural transformation presupposes that a domain and codomain have been fixed. In general this is essential because the function (etc.) that one defines, and its properties, depend on these choices. I am somewhat worried that the Sage implementation might rely (maybe just in subtle ways) on the intuition behind the cases where this advance choice of domain and codomain doesn't matter so much.

tscrim commented 10 years ago
comment:42

Replying to @pjbruin:

What is a functorial construction category? From the documentation it appears that the idea is that one first defines a construction in some "abstract" sense, and only then decides in which category it takes its values, or even to construct a completely new category for this. I realise that the code doesn't have to follow mathematical definitions exactly, but this seems to be quite the opposite of the usual pattern of doing things, where defining a function, functor or natural transformation presupposes that a domain and codomain have been fixed. In general this is essential because the function (etc.) that one defines, and its properties, depend on these choices. I am somewhat worried that the Sage implementation might rely (maybe just in subtle ways) on the intuition behind the cases where this advance choice of domain and codomain doesn't matter so much.

The examples are graded modules/algebras and WithRealizations. From those examples, I would say the categories that are actually used have a fixed (co)domain. I also think this is similar to morphisms, which also makes the assumption of a fixed (co)domain, but perhaps things are different in this case? I'm not sure I understand your concern here...

nthiery commented 10 years ago
comment:43

Replying to @tscrim:

After looking over the category, I agree with you that it is modeling a Coxeter system. However I think we should expand the documentation at the beginning of the category to emphasize this

+1, definitely (in a separate ticket of course)

(and I'd almost say we should rename the category to reflect this).

Possibly so; but then one has to do the same for Weyl groups, and WeylSystems does not look so compelling. In any cases, things will become easier when this will have been axiomatized, so that in theory there would be a single entry point (CoxeterGroups), with axioms Crystalographic, ...

So perhaps axiom categories could not be structure categories by default...more data is probably needed.

That felt like a reasonable default which is why I implemented this way; especially since anyway the only case where there can be additional structure for the axiom category is within the category defining the axiom.

Actually that brings up another question, should (regressive) functorial constructions be structure categories by default? Or again do you think more data needed?

At this point I'd be uncomfortable with it, since e.g. Graded is one such construction. So I guess it's best done construction by construction until we have more data. But it may well be that things should be as for axiom categories: except within the category defining the construction, there is no additional structure.

In fact, maybe the correct default would be to have, A.B().has_additional_structure() return True if and only if A is the category defining the axiom/regressive construction B.

We could actually get rid of "has_additional_structure" altogether, and instead have C.additional_structure() return C by default, with the possibility to override it to return None, or, in the future, something more meaningful than C.

However with doing things this way, how is it different than explicitly specifying the full subcategories (well, in reverse)?

Well, first it's more concise (just return None or self) and involves less duplication.

Also, it gives more information to the system: there are cases where a category defines no additional structure even though it's not a full subcategory of any of its direct super categories. Think of some full subcategory of Magmas() & AdditiveMagmas(). Granted, you could have full_super_categories return a join, but this would deviate from everywhere else (a category never has a join as super category), and thus probably be a source of problems.

Cheers, Nicolas

nthiery commented 10 years ago
comment:44

Hi Peter,

Sorry, still running behind. I'll just answer some easy points now.

Replying to @pjbruin:

I wish I had the time, but given that I don't, the best I can do is to just add my perspective as a non-developer but potential user of the category framework...

I know, and appreciate this. I guess I am just expressing the frustration when some things appear clearly after having manipulated the code for a while, yet are hard to convey convincingly.

But to find them I assume one needs to traverse all supercategories and pick out the ones that are structure supercategories, so the time would still depend on the number of all supercategories, or am I mistaken?

Yes and no: this is obtained by taking the union of the structures of the direct super categories, and cached. So yes, this can trigger a calculation for all the super categories if such information has never been computed before higher above in the category hierarchy. But otherwise, the cost is just that of the union, and that's essentially linear in the number of structure super categories.

Cheers, Nicolas

nthiery commented 10 years ago
comment:45

Dear Peter,

Replying to @pjbruin:

It seems to me that the first thing one has to do when defining a category (and maybe the only essential thing!) should be to decide how to encode its mathematical meaning. The distinction between adding a new axiom to the objects (thereby creating a full subcategory) and adding a new type of structure (thereby creating a relationship that I was thinking of as "category refinement" in earlier discussions) is really fundamental in my opinion.

I agree that clarifying what additional structure, if any, a category defines can be a fundamental guideline for the design. Now, from what I have seen in practice, new category writers usually start with plain structure categories, and they do intuitively the right thing (which typically shows up in the documentation: a XXX is a YYY endowed with an operation zzz).

Worst case, if XXX does not actually define new structure, the default behavior remains safe. They just won't get some feature that they most likely don't need anyway. Remember that the doc of "is_full_subcategory" specifies:

            A positive answer is guaranteed to be mathematically
            correct. A negative answer may mean that Sage has not been
            taught enough information to derive this information. See
            :meth:`full_super_categories` for a discussion.

Things are also safe when implementing an existing axiom or construction in a category where it was not yet there.

The above guideline becomes important when implementing new axioms, new constructions, or deciding which it should be; but there we can assume that the developer has gained enough experience.

Actually, that made me have a thought. How about instead of is_structure_category we have has_additional_structure, and then we could extend this to additional_structure (on a followup ticket).

On the contrary, I think it there is an essential distinction between just adding an axiom to the objects (hence creating a full subcategory) and adding "extra structure".

My point is that the two concepts of axioms and of categories adding structure are rather orthogonal.

Axioms are relevant when a bunch of categories have something to say about that axiom. An axiom by itself may or may not add structure. And there are non structure categories that need not be axioms.

Whether a given category is a structure category or not is the matter of a single method, and it's not worth the complexity of duplicating the category class hierarchy just for this.

(By the way, "over a base ring" is actually something that I am thinking of as another example of "extra structure".)

Here, it's really the category Modules that adds the structure. The class "Category_over_base_ring" is just a technical gadget to handle the base ring parameter that the categories over base rings takes. E.g. Algebras.FiniteDimensional is a category over a base ring which does not add structure, whereas Modules does.

Also: there is room for improvement in functorial constructions: in some cases, we could automatically deduce that the category is a structure category.

I am wondering how you could possibly detect such a thing. In the case of the Unital() structure (correct me if this is somehow an exception), how do you know that this does not just mean the existence of a unit element in the objects, but also the requirement that morphisms preserve this element? This seems to me precisely the type of information that has to be specified by the person implementing the Unital() structure.

Yes, this need to be specified explicitly by the person defining a new axiom. But if it's just about implementing an existing axiom for some category where it was not yet there, then the answer is clear: there is no new structure.

As we discussed with Travis, I believe something similar should hold for functorial constructions categories, at least in the covariant case, but I need to think more about it.

Cheers, Nicolas

nthiery commented 10 years ago
comment:46

Replying to @pjbruin:

OK, but what I meant is that this notion depends on what supercategories of C have been defined, not just on C itself.

Certainly, but this relies on the the implementation choice of defining Magmas().Unital(). I admit this may be a slightly silly example, but I could imagine a different scenario where the person implementing these categories did not think anyone would need unital magmas, and hence chose to define Unital() relative to a more specific category, which in an extreme case could be Rngs(). In that case Rings() = Rngs().Unital() would have been a structure category, while being mathematically exactly the same as the actual Rings().

Fair enough: this is indeed not something purely about the abstract (lattice of) mathematical categories, but about whatever subset has been actually modeled in Sage. It's not so bad though, since this does not depend on how the categories have been implemented (e.g. through axioms or not); just on which categories are implemented or not.

In the above scenario, Rings would at first be a structure category; and then, when the definition of the Unital axioms gets lifted up to some higher category like Magmas, Sage would learn that the structure actually comes from some higher category. That's fine given the specs about negative answers for "X.is_full_super_category(Y)".

In general, when adding new categories and "moving structure up", one indeed needs to update the "additional structure" methods of the lower categories accordingly. Though if one forgets to do it, it should just cause a lack of new feature, rather than bugs. So we are on the safe side.

Cheers, Nicolas

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

1e4418fMerge branch 'develop' into categories/full-subcategories-16340
708cc41Merge branch 'public/categories/full_subcategories-16340' of trac.sagemath.org:sage into categories/full-subcategories-16340
29a6c6716340: reverted change to CoxeterGroups.is_structure_category() + explanations in the doc
60aa12816340: fixed typos
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from d4c7a88 to 60aa128

nthiery commented 10 years ago
comment:48

Hi,

I just fixed some small typos, and reverted the change to CoxeterGroups.is_structure_category() as we discussed.

Time for a checkpoint on the current status.

Permutation groups

Looking back at Travis change, I would want to also revert the change to PermutationGroups(), to let it be a structure category. Indeed, permutation groups come with a distinguished action, and Wikipedia states that this action should be preserved by isomorphisms:

http://en.wikipedia.org/wiki/Permutation_group#Permutation_isomorphic_groups

Do you agree?

additional_structure w.r.t. full_super_categories

As discussed above, I believe that having the developer implement additional_structure rather than full_super_categories is more concise and involves less duplication. And also gives more information (which category define additional structure) which could be further refined (e.g. "Magmas()" defines "*"), if deemed useful in later iterations.

Is this acceptable for everyone?

additional_structure w.r.t is_structure_category

Do we have a consensus that the "additional_structure / structure" language is better than "is_structure_category / all_structure_super_categories"? And that for now we can specify that C.additional_structure() shall return C or None?

If yes, I can implement this change shortly.

Default for axioms

Currently, axiom categories define no additional structure by default. To be 100% foolproof even when defining new axioms, one could change that so an axiom category C().A() would by default define additional structure if and only if C is the category defining the axiom A.

It would be a relatively small change. The cost is that all but two of our current axioms would need to have an "additional_structure" method. I also need to check whether it's easy to detect if C is the category defining A.

Something similar could probably be done for functorial constructions, but we need more data and thinking to do it right and the current default is safe in the mean time.

Anything else?

Cheers, Nicolas

nthiery commented 10 years ago
comment:49

Replying to @pjbruin:

What is a functorial construction category?

Coming back to this side discussion ...

That's a good question. The documentation is certainly terse and could take some love. I haven't spent on it the two weeks of hard work I put on axioms!

From the documentation it appears that the idea is that one first defines a construction in some "abstract" sense, and only then decides in which category it takes its values, or even to construct a completely new category for this. I realise that the code doesn't have to follow mathematical definitions exactly, but this seems to be quite the opposite of the usual pattern of doing things, where defining a function, functor or natural transformation presupposes that a domain and codomain have been fixed. In general this is essential because the function (etc.) that one defines, and its properties, depend on these choices. I am somewhat worried that the Sage implementation might rely (maybe just in subtle ways) on the intuition behind the cases where this advance choice of domain and codomain doesn't matter so much.

Maybe the doc is misleading. But the starting point is really the functorial construction, that is the collection (F_C)_C of related functors (e.g. the collection of algebra functors: groups->group algebras, monoids->monoid algebras, finite groups->finite groups algebras, ...).

Then, the functorial construction category C.F() is meant to model the codomain of the functor F_C, which is well defined.

Of course the model might be incomplete. Categories in Sage are an approximation of the ideal mathematical categories; not all of them nor features thereof are implemented in Sage.

One possible source of confusion is that the functors F_C might not actually be modeled as a standalone objects in Sage. But that's just because we did not really need them at this point. In our example, we just need it was sufficient for now to have the construction implemented as G -> G.algebra(QQ). In general, at this point, the central feature really resides in the categories.

Another source of confusion is that some of the uses of the mechanism for "functorial construction categories" go beyond functorial constructions. E.g. for subobjects, quotients, ... there is not really a collection of functors behind the scene. Still the mechanism remains valid. It would be nice to come up with a better name and definition that would cover all cases. That's now #16991.

Cheers, Nicolas

tscrim commented 10 years ago
comment:50

I agree with reverting PermtutationGroup along with a warning or note about (iso)morphisms (although like Coxeter groups, it is not currently enforced AFAIK).

I don't have a strong opinion on what the method are named and the proposed interface is fine with me.

I'm okay with the default for axioms not being structure categories. However I'd rather have fuctorial construction categories being structure categories by default (I believe currently we only have two, graded and with-realizations, but the two I'd like to add, topological and metric, have additional structure).

pjbruin commented 10 years ago
comment:51

Replying to @nthiery:

Time for a checkpoint on the current status.

Permutation groups

Looking back at Travis change, I would want to also revert the change to PermutationGroups(), to let it be a structure category. Indeed, permutation groups come with a distinguished action, and Wikipedia states that this action should be preserved by isomorphisms:

http://en.wikipedia.org/wiki/Permutation_group#Permutation_isomorphic_groups

Do you agree?

Yes, the set that is acted upon does seem to qualify as extra structure.

additional_structure w.r.t. full_super_categories

As discussed above, I believe that having the developer implement additional_structure rather than full_super_categories is more concise and involves less duplication. And also gives more information (which category define additional structure) which could be further refined (e.g. "Magmas()" defines "*"), if deemed useful in later iterations.

Is this acceptable for everyone?

That sounds good to me.

additional_structure w.r.t is_structure_category

Do we have a consensus that the "additional_structure / structure" language is better than "is_structure_category / all_structure_super_categories"? And that for now we can specify that C.additional_structure() shall return C or None?

If yes, I can implement this change shortly.

I am in favour of this change.

Default for axioms

Currently, axiom categories define no additional structure by default. To be 100% foolproof even when defining new axioms, one could change that so an axiom category C().A() would by default define additional structure if and only if C is the category defining the axiom A.

I am not in favour of this, because it would conflate the notions of "axiom" and "extra structure" (which from my perspective are quite different) even more.

pjbruin commented 10 years ago
comment:52

Replying to @tscrim:

I'm okay with the default for axioms not being structure categories. However I'd rather have fuctorial construction categories being structure categories by default (I believe currently we only have two, graded and with-realizations, but the two I'd like to add, topological and metric, have additional structure).

It may be because I'm still misled by the terminology, but I'm afraid this only increases my confusion about what functorial construction categories are. In what sense do "topological" and "metric" have something to do with modelling codomains of a collection of functors? (Of course topological/metric spaces can be domains/codomains of functors, but I don't think this is what Nicolas meant in comment:49).

To me "topological" and "metric" are examples of "extra structure", in the sense that there are canonical functors (metric spaces) -> (topological spaces) -> (sets). In the current Sage implementation/parlance, I guess they would be regarded as examples of axioms.

tscrim commented 10 years ago
comment:53

Replying to @pjbruin:

It may be because I'm still misled by the terminology, but I'm afraid this only increases my confusion about what functorial construction categories are. In what sense do "topological" and "metric" have something to do with modelling codomains of a collection of functors? (Of course topological/metric spaces can be domains/codomains of functors, but I don't think this is what Nicolas meant in comment:49).

To me "topological" and "metric" are examples of "extra structure", in the sense that there are canonical functors (metric spaces) -> (topological spaces) -> (sets). In the current Sage implementation/parlance, I guess they would be regarded as examples of axioms.

This may not be the right way, but I think of these functional construction categories as additional data to some base category C in which every object of C has a natural way to construct this data that preserves the morphisms. For graded, make everything be in the 0-th graded part. For metric/topological, give it the discrete metric/topology.

Actually running with that example, an object in graded algebras would be the pair (A, deg), right? So if we consider the section of the forgetful function where deg(x) = 0 for all x in A, this would have algebras as a full subcategory of graded algebras, right? So I think we might need to be careful with how we are considering the base categories inside of the functorial construction category. On that, I reverse my position, functorial construction categories should not be structure categories because of the natural inclusion mentioned above (unless I'm wrong).

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 60aa128 to 950b039

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

950b03916340: Merge branch 'develop = 6.4 beta4' into categories/full-subcategories-16340
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 950b039 to b14ca6c

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

b14ca6c16340: revert change, and add documentation thereabout: the category of permutation groups defines additional structure
nthiery commented 10 years ago
comment:56

For info: Simon is sitting with me in Orsay, and we will be banging together on this ticket and follow ups in the next few days.

Expect some action :-) Finally!

Cheers, Nicolas

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from b14ca6c to 43b25d4

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

43b25d416340: is_structure_category -> additional_structure, all_super_structure_categories -> structure, default for functorial construction categories
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 43b25d4 to eb621c7

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

eb621c7Fixing some typos
simon-king-jena commented 10 years ago
comment:59

I went through all of the diff, fixed some typos, and I checked that with #10668 all tests pass. To be on the safe side, I will re-run certain tests with this branch, but it is close to a positive review.

simon-king-jena commented 10 years ago

Changed reviewer from Darij Grinberg, Travis Scrimshaw to Darij Grinberg, Travis Scrimshaw, Simon King

simon-king-jena commented 10 years ago
comment:60

Replying to @pjbruin:

Is it clear that the "structure category" terminology is the way to go? Personally I still don't like it very much (again, it pretends to be about categories but instead is about relations to their supercategories). I would prefer the proposals made by Nicolas in comment:9 and Simon in comment:10 to have an additional_structure() method that returns something meaningful about the additional structure, not just True or False.

This is not really addressed yet: There is additional_structure, but it returns self or None.

Anyway, I am still somewhat confident that I can make something out of the idea to use Gröbner bases in boolean polynomial rings to deal with deduction rules (à la Wedderburn Theorem) for axioms and structures. And then, it would be a matter of filling a dictionary with information about what structure corresponds to what operation.

simon-king-jena commented 10 years ago
comment:61

Replying to @tscrim:

Replying to @pjbruin:

It may be because I'm still misled by the terminology, but I'm afraid this only increases my confusion about what functorial construction categories are. In what sense do "topological" and "metric" have something to do with modelling codomains of a collection of functors? (Of course topological/metric spaces can be domains/codomains of functors, but I don't think this is what Nicolas meant in comment:49).

To me "topological" and "metric" are examples of "extra structure", in the sense that there are canonical functors (metric spaces) -> (topological spaces) -> (sets). In the current Sage implementation/parlance, I guess they would be regarded as examples of axioms.

This may not be the right way, but I think of these functional construction categories as additional data to some base category C in which every object of C has a natural way to construct this data that preserves the morphisms. For graded, make everything be in the 0-th graded part. For metric/topological, give it the discrete metric/topology.

Actually running with that example, an object in graded algebras would be the pair (A, deg), right? So if we consider the section of the forgetful function where deg(x) = 0 for all x in A, this would have algebras as a full subcategory of graded algebras, right? So I think we might need to be careful with how we are considering the base categories inside of the functorial construction category. On that, I reverse my position, functorial construction categories should not be structure categories because of the natural inclusion mentioned above (unless I'm wrong).

I am not very much confident about the functorial constructions either. I am (re-)reading the chapter on functorial constructions in the category primer right now.

Anyway, it seems to me that Nicolas has addressed the concerns expressed here (I was rereading all comments), the code is relatively clear (to me, the unclear parts concern things that existed before, like functorial constructions), and moreover all tests pass. So, if nobody objects, I am putting this to positive review, after reading the chapter in the primer...

simon-king-jena commented 10 years ago
comment:62

Hm. I did not find the category primer very helpful, as it only gives an example (cartesian product) on objects. But it does not tell what actually happens to the categories, and it does not tell how it is defined, nor how it is implemented. I somehow recall from reviewing it how it was implemented, but I would not easily be able to provide a mathematical definition.

Anyway. The new code that we are discussing here seems good to me.

vbraun commented 10 years ago

Changed branch from public/categories/full_subcategories-16340 to eb621c7

nthiery commented 10 years ago

Changed commit from eb621c7 to none

nthiery commented 10 years ago
comment:64

Yeah! Thanks everyone for the review!

6bdad4c1-1e26-4f2f-a442-a01a2292c181 commented 10 years ago
comment:65

O_o

Wasn't there a way to make all these classes inherit the additional_structure -> return None function ?..

Nathann

simon-king-jena commented 10 years ago
comment:66

Replying to @nathanncohen:

O_o

Wasn't there a way to make all these classes inherit the additional_structure -> return None function ?..

Probably not, if you talk about the case that return self is the default for categories that are not CategoryWithAxiom.

If you have a default (which here is chosen so that the test for a full subcategory will not give a false-positive answer by default), then you need to do something special for all cases that are special.

6bdad4c1-1e26-4f2f-a442-a01a2292c181 commented 10 years ago
comment:67

Yo !

Probably not, if you talk about the case that return self is the default for categories that are not CategoryWithAxiom.

If you have a default (which here is chosen so that the test for a full subcategory will not give a false-positive answer by default), then you need to do something special for all cases that are special.

Hmmmmm... Then perhaps only a flag when this infrastructure is initialized ? Doesn't matter much I guess, I it just unpleasant to see the same (empty) function being copy/pasted one thousand times.

Nathann

simon-king-jena commented 10 years ago
comment:68

Replying to @nathanncohen:

Hmmmmm... Then perhaps only a flag when this infrastructure is initialized ? Doesn't matter much I guess, I it just unpleasant to see the same (empty) function being copy/pasted one thousand times.

Or an attribute _adds_structure, and then define something like the following:

def additional_structure(self):
    if getattr(self._adds_structure, None):
        return self

In that way, the method additional_structure would be defined only in three places (default for categories, for categories with axiom, and for functorial constructions), and non-default behaviour could be requested more light-weight.

Nicolas, what do you think about it? To me, it sounds like a good idea.

6bdad4c1-1e26-4f2f-a442-a01a2292c181 commented 10 years ago
comment:69

Also, if I may say: the name "additional_structure" is like VERY vague. Perhaps this is the best you can do on the "mathematical side" of the feature, but it may be possible to give it a more informative name describing what exactly this parameter does, i.e. a more code-specific description.

But of course I have absolutely no idea of what I am talking about.

Nathann

nthiery commented 10 years ago
comment:70

Replying to @nathanncohen:

Wasn't there a way to make all these classes inherit the additional_structure -> return None function ?..

Yeah, I agree it's verbose looking. But I am actually quite happy that the design allowed us to explicitly insert so few additional information :-)

With this ticket, we are really adding a not so trivial mathematical information to almost 260+ categories (what shall, or not, be preserved by morphisms); thanks to the chosen defaults (which depend on whether we have a category with axiom, a construction category, or ...) we had to special case only about 20 categories. For each of them, there was a conscious design decision taken, some of which took a bit of discussion; each such decision has to be documented and tested. Hence we really want the doctests. In particular, having an attribute instead of a method would not save anything.

Cheers, Nicolas

nthiery commented 10 years ago
comment:71

Replying to @nathanncohen:

Also, if I may say: the name "additional_structure" is like VERY vague. Perhaps this is the best you can do on the "mathematical side" of the feature, but it may be possible to give it a more informative name describing what exactly this parameter does, i.e. a more code-specific description.

I am open to suggestions. This is completely local to categories and easy to change. That being said, since it's a method on categories, the context is rather well specified. And in this context, it's rather customary to say things like ``a ring is a set endowed with a structure of unital magma and unital additive magma satisfying the axioms xxx'':

sage: Rings().structure()
frozenset({Category of additive unital additive magmas,
           Category of additive magmas,
           Category of unital magmas,
           Category of magmas,
           Category of sets with partial maps,
           Category of sets})
sage: Rings().axioms()
frozenset({'AdditiveAssociative',
           'AdditiveCommutative',
           'AdditiveInverse',
           'AdditiveUnital',
           'Associative',
           'Distributive',
           'Unital'})

(btw: for that purpose, in the first example above, we might want to have a separate method that returns only the lowest categories, i.e. unital magmas and additive unital magmas).

Then, from "structure" to "additional structure", the leap is not too big.

Cheers, Nicolas