Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x in IntegralDomains() should refine category #15183

Closed
saraedum opened this issue Sep 10, 2013 · 27 comments
Closed

x in IntegralDomains() should refine category #15183

saraedum opened this issue Sep 10, 2013 · 27 comments

Comments

@saraedum
Copy link
Member

Currently, IntegerModRing refines its category if asked for membership in Fields():

sage: M = IntegerModRing(3)
sage: M.category()
Join of Category of commutative rings ...
sage: M in Fields()
True
sage: M.category()
Join of Category of fields ...

The same does not happen for IntegralDomains():

sage: M = IntegerModRing(5)
sage: M.category()
Join of Category of commutative rings ...
sage: M in IntegralDomains()
False
sage: M.category()
Join of Category of commutative rings ...

The changes on this ticket copy the logic from fields over to integral domains.

Depends on #14482

CC: @simon-king-jena @nthiery

Component: categories

Author: Julian Rueth

Branch/Commit: u/saraedum/ticket/15183 @ 2282a39

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

@saraedum saraedum added this to the sage-5.12 milestone Sep 10, 2013
@saraedum
Copy link
Member Author

Branch: u/saraedum/ticket/15183

@saraedum
Copy link
Member Author

Dependencies: #14482

@saraedum
Copy link
Member Author

Author: Julian Rueth

@saraedum saraedum modified the milestones: sage-5.12, sage-6.0 Sep 10, 2013
@saraedum
Copy link
Member Author

comment:5

Simon, I believe I mostly adapted your code from Fields. Do mind having a look at this?

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 10, 2013

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

[changeset:2554616]Added classes for discrete valuations
[changeset:5af8f0a]Merge branch 'u/saraedum/ticket/15171' of http://trac.sagemath.org/sage into ticket/15183
[changeset:2907216]Fixed a missing assignment in DiscreteValueGroup.
[changeset:2249b00]Added DiscreteValueGroup
[changeset:23db51b]Merge branch 'u/roed/ticket/14482' of ssh://trac.sagemath.org:2222/sage into ticket/15171

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 10, 2013

Commit: 2554616

@saraedum
Copy link
Member Author

Changed dependencies from #14482 to #14482, #15171

@saraedum
Copy link
Member Author

Changed dependencies from #14482, #15171 to #14482

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 10, 2013

Changed commit from 2554616 to 2282a39

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 10, 2013

Branch pushed to git repo; I updated commit sha1. This was a forced push. Recent commits:

[changeset:2282a39] Added refinement of categories for IntegralDomains.
[changeset:efa66ca] Merge branch 'u/saraedum/ticket/14482' of ssh://trac.sagemath.org:2222/sage into ticket/15183
[changeset:c2902bb] Improve diff() against 'dependencies'
[changeset:9e4a92c] Added _is_master_uptodate() to dev scripts
[changeset:cc0ba9f] Made remote_status() more usable.

@saraedum
Copy link
Member Author

comment:10

Sorry, I uploaded the wrong branch to this ticket. Should be fixed now.

@simon-king-jena
Copy link
Member

comment:11

The main problem for me is that it uses git, and as much as I know, the "master" branch in the trac-git version of Sage does not pass tests.

Hence, I currently have no version of Sage which I could use to test your changes. And besides, my knowledge of git is too little to really understand what has changed and what happened in a dependency.

In any case, are you really sure that IntegralDomains() needs the refinement? The reason for introducing the refinement in testing containment in Fields() was the fact that Fields.__contains__ does some pretty custom things, that are really slow, unless the objects's category is properly initialised. Hence, the idea was to "cache" the result of the slow test by refining the category, so that next time the slow test will be avoided.

But IntegralDomains has no custom implementation of __contains__. So, could you elaborate a bit more on the reason of your suggestion?

@nbruin
Copy link
Contributor

nbruin commented Sep 10, 2013

comment:12

Really, by the time you've established that Z/nZ is an integral domain, you can refine it to field anyway (which is an integral domain).

@saraedum
Copy link
Member Author

comment:13

Replying to @simon-king-jena:

The main problem for me is that it uses git, and as much as I know, the "master" branch in the trac-git version of Sage does not pass tests.

I see.

Hence, I currently have no version of Sage which I could use to test your changes. And besides, my knowledge of git is too little to really understand what has changed and what happened in a dependency.

You could use ./sage --dev diff --base=dependencies to see the changes introduced on the ticket itself. (with a recent version of #14482, like the one on this ticket, i.e., do sage -b before using this command)

In any case, are you really sure that IntegralDomains() needs the refinement? The reason for introducing the refinement in testing containment in Fields() was the fact that Fields.__contains__ does some pretty custom things, that are really slow, unless the objects's category is properly initialised. Hence, the idea was to "cache" the result of the slow test by refining the category, so that next time the slow test will be avoided.

What does Fields.__contains__ do? It calls .is_field() which might be expensive (e.g. in the case Z/nZ). Integral domains should do the same, call .is_integral_domain() which is as expensive.

But IntegralDomains has no custom implementation of __contains__. So, could you elaborate a bit more on the reason of your suggestion?

I believe that's why the check IntegerModRing(2) in IntegralDomains() failed, right?

@saraedum
Copy link
Member Author

comment:14

Replying to @nbruin:

Really, by the time you've established that Z/nZ is an integral domain, you can refine it to field anyway (which is an integral domain).

Sure, in the case of Z/nZ this is true. However, I tried to implement this on the level of categories, and I don't think that IntegralDomains() should try to refine to Fields(). One could of course implement this in IntegerModRing but I believe it is cleaner like this.

@simon-king-jena
Copy link
Member

comment:15

Replying to @saraedum:

What does Fields.__contains__ do? It calls .is_field()

No, it calls sage.rings.ring._is_Field, and this is where .is_field() might be called and the refinement might happen.

Integral domains should do the same, call .is_integral_domain() which is as expensive.

But IntegralDomains has no custom implementation of __contains__. So, could you elaborate a bit more on the reason of your suggestion?

I believe that's why the check IntegerModRing(2) in IntegralDomains() failed, right?

Do you suggest to introduce a custom IntegralDomains.__contains__?

@saraedum
Copy link
Member Author

comment:16

Replying to @simon-king-jena:

Replying to @saraedum:

What does Fields.__contains__ do? It calls .is_field()

No, it calls sage.rings.ring._is_Field, and this is where .is_field() might be called and the refinement might happen.

Sorry, that's what I meant.

Integral domains should do the same, call .is_integral_domain() which is as expensive.

But IntegralDomains has no custom implementation of __contains__. So, could you elaborate a bit more on the reason of your suggestion?

I believe that's why the check IntegerModRing(2) in IntegralDomains() failed, right?

Do you suggest to introduce a custom IntegralDomains.__contains__?

Yes. This is what my patch does. Here is the diff: changeset:2282a39

@simon-king-jena
Copy link
Member

comment:17

Can you tell me why the patchbot only found errors in TWO files, namely

sage -t --long src/sage/dev/sagedev.py  # 1 doctest failed
sage -t --long src/sage/dev/patch.py  # 2 doctests failed

??

On my machine, I got many more errors. Or perhaps I am on the wrong branch. I currently have

$ git branch
* master
  public/sage-git/master
  ticket/15120

where #15120 is supposed to fix some remaining tests. But I am not sure, perhaps one of the two branches above is not the sage-trac master. How can I find out whether my current branch pulls from github or from trac?

@saraedum
Copy link
Member Author

comment:18

Replying to @simon-king-jena:

Can you tell me why the patchbot only found errors in TWO files, namely

sage -t --long src/sage/dev/sagedev.py  # 1 doctest failed
sage -t --long src/sage/dev/patch.py  # 2 doctests failed

??

I'm not sure what the patchbot does. It might merge in a few changes for the doctests but I don't know.

On my machine, I got many more errors. Or perhaps I am on the wrong branch. I currently have

$ git branch
* master
  public/sage-git/master
  ticket/15120

where #15120 is supposed to fix some remaining tests. But I am not sure, perhaps one of the two branches above is not the sage-trac master. How can I find out whether my current branch pulls from github or from trac?

git branch -vv shows where the branches pull from. You can of course also pull explicitely: git pull http://trac.sagemath.org/sage.git public/sage-git/master.

@simon-king-jena
Copy link
Member

comment:19

Replying to @saraedum:

git branch -vv shows where the branches pull from.

Not really.

$ git branch -vv
* master                 b890215 [origin/public/sage-git/master] Merge branch 'ticket/14482' into public/sage-git/master
  public/sage-git/master cf14c84 [origin/public/sage-git/master: behind 562] Merge branch 'ticket/14482' into public/sage-git/master
  ticket/15120           6912669 Fix --new option for doctests.

Neither trac nor github are mentioned...

You can of course also pull explicitely: git pull http://trac.sagemath.org/sage.git public/sage-git/master.

Am I correct that this would pull into my "public/sage-git/master" branch, but would not affect the other branch called "master"?

I am sure that one branch was obtained from github and the other from trac, and it is a shame that it can't clearly (at least to my understanding) tell which is which.

@saraedum
Copy link
Member Author

comment:20

Replying to @simon-king-jena:

Replying to @saraedum:

git branch -vv shows where the branches pull from.

Not really.

$ git branch -vv
* master                 b890215 [origin/public/sage-git/master] Merge branch 'ticket/14482' into public/sage-git/master
  public/sage-git/master cf14c84 [origin/public/sage-git/master: behind 562] Merge branch 'ticket/14482' into public/sage-git/master
  ticket/15120           6912669 Fix --new option for doctests.

So, master and public/sage-git/master pull from origin. To find out what is origin, type git remote -v.

You can of course also pull explicitely: git pull http://trac.sagemath.org/sage.git public/sage-git/master.

Am I correct that this would pull into my "public/sage-git/master" branch, but would not affect the other branch called "master"?

This would pull into the current branch, the one with the asterisk in git branch.

I am sure that one branch was obtained from github and the other from trac, and it is a shame that it can't clearly (at least to my understanding) tell which is which.

It seems that they both came from trac. At least their latest version does. It does not really matter where they originally came from.

@simon-king-jena
Copy link
Member

comment:21

Replying to @saraedum:

So, master and public/sage-git/master pull from origin. To find out what is origin, type git remote -v.

git remote -v
origin  ssh://git@trac.sagemath.org:2222/sage.git (fetch)
origin  ssh://git@trac.sagemath.org:2222/sage.git (push)

So, to my surprise, there is no github in it.

@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin removed this from the sage-6.0 milestone Dec 17, 2013
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin added this to the sage-6.1 milestone Dec 17, 2013
@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Dec 26, 2013

comment:23

Okay guys, it looks like Nicolas says that category containment should not refine the category, and on the other hand Fields already do it. What do you decide ?

Nathann

@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Dec 26, 2013

comment:24

Just in case...

Nathann

@simon-king-jena
Copy link
Member

comment:25

Replying to @nathanncohen:

Okay guys, it looks like Nicolas says that category containment should not refine the category,

For good reason! Category refinement involves changing the class of an object after creation, and actually after usage! Python lets you do those things, but really it is a dangerous hack.

We have seen cases in which the hash of a parent depends on the class of the parent. Hence, if a category refinement happens after (or while) using a parent P as key of a dictionary, it used to be possible that P was put in the wrong hash bucket of the dictionary. Fortunately, someone (I think it was Volker) added a security layer, so that now changing the class results in an error if it changes the hash.

But apart from hash, one often sees the following in __cmp__ methods:

def __cmp__(self, other):
    c = cmp(type(self),type(other))
    if c:
        return c
    return cmp(<data for self>,<data for other>)

Hence, if you add category refinement, comparison could break: Imagine you originally had cmp(self,other)==0 and then did self in IntegralDomains() (triggering a category refinement) but didn't other in IntegralDomains(). Now, ask cmp(self,other): The result will not be zero any more!

Mathematically, a category refinement should be fine, and one may think that the category framework is designed to be stable against category refinement ("if you refine the category of P, then P may inherit different methods from the category framework than before, but these new methods will fit better."). However, some of these methods do caching. Hence, if P originally belongs to category C1 and it got some method meth() which did some caching, and then you refine P's category to be C2, so that P now inherits a different version of meth() that uses a different cache, then you have a mess.

One could argue that it is a bug if you do get a mess upon category refinement. But perhaps it is wise to not consciously ask for trouble...

and on the other hand Fields already do it.

Yes, I know, I have to take the full blame...

But the situation was different than the situation here!

When I introduced category refinement for fields, Fields.__contains__ used to be custom since a long time. This custom method was very very slow, but the default __contains__ method couldn't be used unless all parents' categories were fully initialised. But then, the initialisation took too much time. Hence, I went for a compromise: Keep initialisation fast, and accept that the first Fields() containment test is slow; but in case of success, make sure that all further containment test will be quick.

I was motivated by a concrete example that was important to a "powerful" Sage sub-community (you know, elliptic curves and so on): This example became way too slow after implementing the category framework for all rings. Reason: Initialisation of these rings took way too long, since for each ring it was needed to test whether the modulus is a prime number. Guided by this example (and a similar example for matrix spaces) I found that a "lazy" category initialisation can avoid certain severe regressions.

However, here, things are different: As much as I understand, the suggestion is to let IntegralDomains() have a custom __contains__ method, just because Fields() has a custom __contains__ method too. But since Category_singleton.__contains__ is very very fast, it should not be overridden by a custom __contains__ without a very very good and compelling reason. It could actually be that some examples will become slower when the containment test will regress.

Put differently: I haven't seen any concrete "real world" example that shows that we need lazy category initialisation for (some) integral domains. Without such example, I'd say we should better not open Pandora's box again.

@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.1, sage-6.2 Jan 30, 2014
@mezzarobba
Copy link
Member

comment:27

So, does this ticket still need review? Should it be closed as wontfix?

@saraedum
Copy link
Member Author

comment:28

Simon made a good point. I did this for consistency with Fields. I see now that it is better not to introduce this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants