-
Notifications
You must be signed in to change notification settings - Fork 231
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
Promote #3494
base: development
Are you sure you want to change the base?
Promote #3494
Conversation
M2/Macaulay2/m2/exports.m2
Outdated
@@ -871,7 +871,7 @@ export { | |||
"left", | |||
"length", | |||
"lift", | |||
"liftable", | |||
"isLiftable", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This list is sorted, so this line should be next to other "is" symbols.
M2/Macaulay2/m2/newring.m2
Outdated
@@ -11,6 +11,21 @@ needs "matrix2.m2" -- for lift | |||
-- new polynomial ring or quotient ring from old -- | |||
---------------------------------- | |||
|
|||
-- automate promotion | |||
promoteFromMap = method() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call this setupPromotionMethods
or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And perhaps commonEngineRingInitializations
should call it, similar to the lift
methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, that was part of the idea that it could replace some of the existing code. I haven't looked into it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about just setupPromote
? so it's not too long
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Up to you. My plan is to eventually allow the notation map(R, S) = f
.
if liftable(m,ZZ) then lift(m,ZZ) else 0)) | ||
lift(m,ZZ,Verify=>false) ?? 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I understand the motivation in this change. I like ??
and ??=
in certain situations (e.g. caching) but I'm concerned that in places like this it might make debugging more difficult. For instance, I imagine we would like to see an error if isLiftable
returned true but lift
failed here, because that would be a bug and an error would help us locate it, but ??
hides the error here and silently returns zero.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general I would agree with you but here's a pretty clear-cut case where we're basically calling lift
twice for no reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually a little confused about what's happening in this code, but sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, basically any time someone calls isLiftable, a potential call to lift is on the horizon, no?
M2/Macaulay2/m2/rationals.m2
Outdated
lift(QQ,QQ) := opts -> (r,QQ) -> r | ||
liftable(QQ,QQ) := (QQ,QQ) -> true | ||
isLiftable(QQ,QQ) := (QQ,QQ) -> true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this line even exist? We don't have isLiftable(ZZ,ZZ)
, etc.. Maybe there should be isLiftable(Ring, Ring) := (R, S) -> R === S
that is used as a last resort if R and S don't have an isLiftable
method installed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're right, this line is useless I believe.
right now for most (all?) rings we have lift(R,R):=o->(x,R)->x
so isLiftable(R,R)
will give true
without any need to override the default behaviour.
there is |
M2/Macaulay2/m2/newring.m2
Outdated
RS := AB/image fg; | ||
promoteFromMap map(RS,R,(vars AB)_{0 .. m-1}); | ||
if S =!= R then promoteFromMap map(RS,S,(vars AB)_{m .. m+n-1}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it natural that when R == S
we favor the first ring map over the second?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah this is annoying. no there isn't. in fact there are 3 choices here:
- favour the first
- favour the second
- decide that it's ambiguous and not call
promoteFromMap
at all.
I'm not sure what's best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there's a general lesson to be learned from the way NormalToricVarieties handles natural maps:
i1 : needsPackage "NormalToricVarieties";
i2 : X = toricProjectiveSpace 1;
i3 : Y = toricProjectiveSpace 2;
i4 : Z = X ** Y;
i5 : Z_[0]
o5 = | 1 |
| 0 |
| 0 |
o5 : ToricMap Z <--- X
i6 : Z_[1]
o6 = | 0 0 |
| 1 0 |
| 0 1 |
o6 : ToricMap Z <--- Y
i7 : Z^[1]
o7 = | 0 1 0 |
| 0 0 1 |
o7 : ToricMap Y <--- Z
i8 : Z^[0]
o8 = | 1 0 0 |
o8 : ToricMap X <--- Z
I wonder if we could have a notation for specific ring maps. In particular, if X === Y
then Z_[0]
and Z_[1]
are still clearly distinguished.
@@ -85,7 +83,7 @@ map(Ring, Ring, Matrix) := RingMap => opts -> (R, S, m) -> ( | |||
" into a degree of length ", toString degreeLength R); | |||
opts.DegreeMap | |||
) | |||
else if workable (() -> promote({},S,R)) then (d -> first promote({d},S,R)) | |||
else if (pr:=lookup(promote,List,S,R)) =!= null then (d -> first pr({d},S,R)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, I didn't know promote(List,S,R)
is for promoting the degree till now ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record I fixed this line because it could create infinite loops. It pretty much never occurred before because there were few promote
, but now with the added flexibility of promoteFromMap
(or whatever we're going to end up calling), it can easily happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would be in favor of deprecating promote(List, Ring, Ring)
and instead given a ring map f
make use of f.degreeMap
and f.degreeLift
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe just degreeGroup f
defined as degreeGroup RingMap := f -> f.degreeMap
, which is similar to how NormalToricVarieties supports picardGroup ToricMap
to give the map of Picard groups functorially.
Sure, you just need to remove |
A similar approach to your map(R, S) := map(R, S, { ... }, DegreeLift => ..., DegreeMap => ...) and have it cache that ring map (there is a syntax for allowing this), then lift(R, S) := ...
promote(S, R) := ... to define these methods in one place and have it be used throughout. The main motivation for this was having a better way to cache a ring map that specifically has a degree map or degree lift map that is then used here: Lines 200 to 203 in 1fd2382
In many situations map(R, S) is defined, but the degree map that M2 uses by default is incorrect, which causes all sorts of errors here.
|
I'm not sure if this is what you want but
|
a87434d
to
a7e9349
Compare
That seems to cause problems. I haven't looked in detail but the Core |
Okay, then either change the method type or don't rename it? |
not sure what you mean by either option. Do you want to change |
No, change the isLiftable in Core. For instance you could use hooks to check isLiftable(Number, Ring) :=
isLiftable(RingElement, Ring) := (r, R) -> ring r === R or tryHooks(
LiftabilityHooks, (r, R), (r, R) -> lift(r, R) =!= null)) Then you only need to install the special cases where there's legitimately a way to check liftability without actually lifting like this: addHook(LiftabilityHooks, (r, R) -> if ring r === QQ and R === ZZ then denominator r === 1) Actually, I would love to use hooks like this for i49 : #methods lift
o49 = 103
i50 : #methods promote
o50 = 124 |
I have to disagree with you here. I don't think hooks should be used as a replacement for the traditional method paradigm based on inheritance. And changing the definition of the Core |
Okay, then don't rename |
OK I can revert that part of the PR. Though at some point we'll want to do the rename, and then the problem will arise again. |
Well, I provided a way for that to happen, but you disagreed, and I don't see another option.
The problem with Besides, we use hooks in places where a function depends on the specifics of the ring of its inputs several places; look up |
I don't disagree that |
04b5a89
to
53983f1
Compare
Are you aiming for this PR to make it to the upcoming release, or the next one? |
I think it should be ready for this release. |
9ce1531
to
1ff3f83
Compare
--- author(s): PZJ | ||
--- notes: | ||
|
||
undocumented methods setupLift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you undocument these rather than just list the method keys as secondary keys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's because you get weird documentation errors, look at the Synopsis
keyword used in the documentation of preimage
, for instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly out of laziness. Also, some of the methods are really meant for internal use only, so I need to decide whether to document those or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I would vote to keep both of these methods unexported for now (of course you can do importFrom_Core "setupPromote"
in your own package to use it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I said "some of the methods are really meant for internal use only", I did not mean that setupPromote
and setupLift
were for internal use only. I meant some of their methods (as listed by say methods setupPromote
) are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well you've listed two things under Usage, so they should be listed as keys.
Key | ||
setupLift | ||
Headline | ||
automatic lift from one ring to another |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what sense is this "automatic"? Seems like the purpose of this function is to manually setup lifting method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops. copy-pasted too quickly the setupPromote
doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My complaint applies there, too. How is that automatic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is automatic in the sense that you don't need to invoke promote
explicitly, see the examples provided for setupPromote
-- promote(Matrix,R,S) := | ||
-- promote(MutableMatrix,R,S) := -- doesn't work, cf https://github.com/Macaulay2/M2/issues/2192 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused about these commented lines. Don't you have these exact methods implemented two lines below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but not as S ** M
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would it be? That wouldn't even work because Ring ** Matrix
calls Ring ** Module
which then calls promote(Matrix, Ring)
, so it would be a loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hash changed again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a pain, we should set up the emacs stuff differently so it doesn't occur...
Key | ||
setupPromote | ||
Headline | ||
automatic promotion from one ring to another |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your force push made my comment disappear, but still, I don't think this headline describes what this function does. If you don't want to remove "automatic", at least add "set up" to the beginning? Also:
- list at least one method key
- maybe link to this node from
promote
? (and similarly fromlift
tosetupLift
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will rewrite doc
@@ -466,6 +503,8 @@ swap = (x,y) -> (y,x) | |||
promoterightexact = swap @@ promoteleftexact @@ swap | |||
promoterightinexact = swap @@ promoteleftinexact @@ swap | |||
|
|||
isPromotable = (R,S) -> lookup(promote,R,S) =!= null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be defined next to promote
?
lift(R,S) := opts -> (a,S) -> if opts.Verify then f a else try f a; | ||
lift(List,R,S) := opts -> (m,R,S) -> apply(m,degmap); | ||
lift(Module,R,S) := opts -> (M,R,S) -> S ** M; | ||
lift(Matrix,R,S) := opts -> (m,R,S) -> map(lift(target m,S),lift(source m,S),applyTable(entries m,x->lift(x,S))); | ||
lift(MutableMatrix,R,S) := opts -> (m,R,S) -> mutableMatrix applyTable(entries m,x->lift(x,S)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have any lift
methods of matching e.g. lift(Module, R, S)
that isn't defined here automatically? Because if not, I think all of these should just be e.g. lift(Module, Ring, Ring)
, and we can rename lift(x,S)
to something else that is defined per ring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question. lift(Module,...)
only works for free modules anyway, it seems the definition I give could work universally. that being said it's not how it's done for the usual internal lift
, and I don't dare to change too much.
This PR addresses some of the issues raised in #3184.
before:
and
after:
and
In particular it introduces a new method
setupPromote
which makes it easy to (automatically) promote from A -> B given a map f: A -> B.