-
Notifications
You must be signed in to change notification settings - Fork 6
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Inference Redux #639
Comments
Alternatively, if there really is only one variable, if we add to the (And/or: add an ExtensionId |
I'm not really sure that there should be only one "variable" in a hugr. What if the hugr is a Module containing 3 dataflow graphs - then the root of each of those graphs should be a variable? |
Yes, that's a fair question - seems like a reasonable thing to do - I note merely that it's not what we do at the moment: Lines 270 to 273 in b3062e9
So I think we can still handle items 1+2 first, without any consideration of variable(s), and then handle even multiple variables in stage 5 (e.g. passing an extra I'm still thinking I'd like to change handling of DFGs such that the |
So I think we can break this up into two themes: firstly, reordering steps in the algorithm; secondly, changing the approach to variables. The second is less certain and needs more thought, so on the first... Following #591 I think all the parts are pretty much there, but the current flow is
I think what we can do is
The last step raises questions (allows to address issues) like, what if my meta |
Wrt. variables, we should probably do #657 first. Then we can explicitly declare variables of kind TypeParam::Extensions, rather than the somewhat implicit "open with no constraints" that we use in inference now. This would allow returning an ExtensionSolution (that is complete, i.e. defined for all nodes) containing those variables, where necessary; and giving the highly-desirable property that instantiating the variables** and then performing inference, would produce the same answers as performing inference and then instantiating. ** via the normal mechanism for any other type variable, i.e. |
Note that if there are variables of kind We might allow more variables than in #692 here too, e.g. allowing a Dfg-rooted Hugr to be "parametric" in some variable (perhaps the input extensions to the root node). However, assuming the variable has no upper/lower bounds specified, again for the solution to be valid for all values of that variable, we'll just have to put that variable into extension sets everywhere - exactly as if the "extension variable" were just another extension (The neat trick might be to infer what upper/lower bounds for the variable would make the Hugr valid e.g. to fit in with existing annotations that don't mention it, but let's skip over this idea for now.) So we may not need to give any special treatment to "variables" (as extension inference does now), just treat them as either (1) their own identifiers, or (2) if we want to be able to |
This means variables are their own thing (rather than phase in the algorithm). We could nonetheless have three or four phases: Any remaining unsolved nodes require solving Plus constraints backwards, and so may have multiple possible solutions; there may be some element of policy as to which to pick. However the policy of "smallest-possible ExtensionSet" seems reasonable (!). Hence, we can (optionally?) continue: |
This might be enacted in stages as follows:
|
I'm in agreement. We just need to plan the order in which we do things. I think:
|
Splitting EdgeKind::Static into Const/Func is #695 or another? I'm not sure that's necessarily the right solution to the problem |
We probably also need to handle type-variables's in ExtensionSets even without using these for extension-inference's own notion of variables; I think this means (at the least?!) that inference mustn't propagate such a TV outside its binder. |
Agreed!
This is more of a head-scratcher. I think if we get to this point, it says there's something scarily non-parametric about the function! |
Yes!! ;-). So at the least, we should verify that any variables in any However, if we restrict the input-extensions to empty for FuncDefn/cl, then the output-extensions are necessarily empty too (as delta is zero), and I think that should prevent any leakage from functions; the Static edge has PolyFuncType that would bind the variable, and any Polymorphic lambdas/constants is another issue (#709), which we don't even have yet ;), but if it's a Const containing a lambda then that's empty delta, so we say the input-extensions and output-extensions of the const are empty, and again anything bound by / inside the PolyFuncType on the static edge should be fine. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
First a couple of notes:
main_loop
should not need to iterate more than once. It claimssolve_metas
can add new edges to the equality graph, but only if it findsConstraint::Equals
; a single iteration of merge_equal_metas should remove all Constraint::Equals and thus all edges from the equality graphSo, I propose removing/splitting main_loop, and the two calls to main_loop, as follows:
shunted
, new entries inconstraints
(i.e. keyed by the merged vars, but containing only Plus's), and a smaller set of variables (i.e.remaining
inmain_loop
- the new vars, and everything that wasn't shunted.)shunted
is a member ofUnificationContext
I suspect that remaining should be too. It'd be nice to useconstraints.keys()
but not sure whether that works(?)remaining
). Probably build that graph now. Variables on cycles can be shunted/merged; note they had no Equals constraints, but may still have Plus constraints pointing out of the cycle.tarjan_sccs
allows to return SCCs in an order (where cycle A depends upon cycle B, then B before A, say), we could solve the remaining constraints as we go here, but let's not.shunted
, make some more metas and move remaining non-cyclicconstraints
around, and build a new maplower_bound
(from merged meta to all Extensions on the cycle it was merged from).lower_bound
for existing meta, or "merge" the single meta into a new meta without the cycle, doesn't really matter).lower_bound
, or empty ExtensionSet otherwise.lower_bound
lower_bound
.Hugr-without-Lift-nodes ==> update validation to require extensions at source of edge are a subset of extensions of target of edge. Beyond change in step 5, I think that's all that's required.
The text was updated successfully, but these errors were encountered: