-
Notifications
You must be signed in to change notification settings - Fork 7
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
feat!: Infer extension deltas for Case, Cfg, Conditional, DataflowBlock, Dfg, TailLoop #1195
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1195 +/- ##
==========================================
+ Coverage 86.57% 86.66% +0.08%
==========================================
Files 94 94
Lines 17659 17806 +147
Branches 16797 16944 +147
==========================================
+ Hits 15289 15432 +143
+ Misses 1600 1598 -2
- Partials 770 776 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
self.validate_extensions()?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Leaving this here as in the future we plan for it to infer deltas | ||
/// of container nodes e.g. [OpType::DFG]. For the moment it does nothing. | ||
pub fn infer_extensions(&mut self) -> Result<(), ExtensionError> { | ||
pub fn infer_extensions(&mut self, remove: bool) -> Result<(), ExtensionError> { | ||
fn delta_mut(optype: &mut OpType) -> Option<&mut ExtensionSet> { |
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 guess this (+tests) might be better in a separate file, but this is 200 lines, a lot shorter than the old infer.rs
8cfbbd7
to
604b000
Compare
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.
The test simplifications and the brevity of the actual infer routine are very satisfying.
Thoughts on builder interface:
- Builders that infer extensions should be default, therefore they should have the short names (probably just the set of names we currently use with explicit deltas).
- Explicit delta versions, if necessary, can have some standard naming convention (e.g.
dfg_builder_delta
) - Could a potential simplification be just to require
FunctionType
inputs wherever possible (rather than in_types + out_types) and then make the default extension set inFunctionType
TO_BE_INFERRED
. Thenwith_extension_delta
onFunctionType
would overwrite the default set? Are there uses ofFunctionType
where having the default extension set be empty is important?
@@ -815,15 +816,5 @@ pub enum InterGraphEdgeError { | |||
}, | |||
} | |||
|
|||
#[derive(Debug, Clone, PartialEq, Error)] |
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.
breaking so needs mentioning in PR commit name + description
hugr-core/src/extension.rs
Outdated
@@ -406,6 +406,8 @@ pub enum ExtensionBuildError { | |||
pub struct ExtensionSet(BTreeSet<ExtensionId>); | |||
|
|||
impl ExtensionSet { | |||
pub const TO_BE_INFERRED: ExtensionId = ExtensionId::new_unchecked("TO_BE_INFERRED"); |
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 we want an even harder to hit name
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.
Made an "illegal" identifier i.e. you can only create it via new_unchecked
and not via new
hugr-core/src/hugr/validate.rs
Outdated
@@ -743,6 +747,9 @@ pub enum ValidationError { | |||
/// There are errors in the extension deltas. | |||
#[error(transparent)] | |||
ExtensionError(#[from] ExtensionError), | |||
/// A node claims to still be awaiting extension inference. Perhaps it is not acted upon by inference... |
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.
/// A node claims to still be awaiting extension inference. Perhaps it is not acted upon by inference... | |
/// A node claims to still be awaiting extension inference. Perhaps it is not acted upon by inference. |
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.
Fair, updated message too.
However, just to note - any Hugr-node that contains TO_BE_INFERRED in its delta is going to either be an error (if its parent doesn't) or result in a TLD that is basically unusable (because no runtime/environment/run_on_quantum_hw
node/etc. will support such extensions). So we could skip both the error and the check. Just a thought....
hugr-core/src/hugr.rs
Outdated
@@ -92,15 +91,63 @@ impl Hugr { | |||
self.validate_no_extensions(extension_registry)?; | |||
#[cfg(feature = "extension_inference")] | |||
{ | |||
self.infer_extensions()?; | |||
self.infer_extensions(false)?; | |||
self.validate_extensions()?; | |||
} | |||
Ok(()) | |||
} | |||
|
|||
/// Leaving this here as in the future we plan for it to infer deltas |
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.
update docstring (incl what "remove" means)
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.
Ooops, thanks
.map(|ch| Ok((ch, infer(h, ch, remove)?))) | ||
.collect::<Result<Vec<_>, _>>()?; | ||
|
||
let Some(es) = delta_mut(h.op_types.get_mut(node.pg_index())) else { |
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 we just add a get_optype_mut(Node)
to HugrMut
?
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, but
- This raises tricky questions of what to do for a Node that is not in the Hugr. What'll actually happen here is we'll fall back to DenseUnmanagedMap's behaviour of expanding to contain an OpType for that Node (index), which I suspect is not what we'd want on a (quasi-?)public method...so at the least, it's a bit more involved that it sounds
- If we do that, we should probably remove
replace_op
as having full&mut
access is clearly superior! (replace_op(idx, op)
isget_mut(idx) = op
). I guess that could follow, but obviously it's a breaking change, and I think better to do that all in another PR.
I think this is fine for inside crate::hugr
. (h
is just self
but we're in an inner-fn
)
hugr-core/src/hugr.rs
Outdated
assert_eq!(inf_res, Err(expected_err)); | ||
} | ||
|
||
fn build_ext_cfg(parent: ExtensionSet) -> (Hugr, Node) { |
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.
fn build_ext_cfg(parent: ExtensionSet) -> (Hugr, Node) { | |
fn build_ext_dfg(parent: ExtensionSet) -> (Hugr, Node) { |
?
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.
Erm, yes, oops, no idea how that happened
mid | ||
} | ||
|
||
#[rstest] |
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 these cases would benefit from comments next to each saying briefly why the result is expected
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.
Fair, done
hugr-core/src/hugr.rs
Outdated
..root_ty | ||
}; | ||
assert!(h.root_type() == &expected_gp.into()) | ||
// rest should be unchanged... |
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.
worth asserting?
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.
Done
604b000
to
f3a05c4
Compare
Ok, moved to #1219 |
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.
thanks!
hugr-core/src/hugr.rs
Outdated
#[case([XA], [TO_BE_INFERRED], true, [XA])] | ||
// Success: delta inferred for parent is subset of grandparent | ||
#[case([XA, XB], [TO_BE_INFERRED], true, [XA])] | ||
// Base case failure: infers [XA] for parent but grandparent has disjoint et |
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.
// Base case failure: infers [XA] for parent but grandparent has disjoint et | |
// Base case failure: infers [XA] for parent but grandparent has disjoint set |
…ck, Dfg, TailLoop (#1195) closes #640 * Add an ExtensionId TO_BE_INFERRED * On Case, Cfg, Conditional, DataflowBlock, Dfg, TailLoop, `Hugr::infer_extensions` replaces TO_BE_INFERRED with the smallest set of ExtensionIds that's correct wrt. its child nodes (i.e., the union of the child node deltas). If there are other ExtensionIds alongside TO_BE_INFERRED these will be kept (allowing a "lower bound" to be specified for individual nodes) * `Hugr::infer_extensions` also takes a `remove: bool` which, if true, modifies deltas of the same OpTypes that do *not* have TO_BE_INFERRED, by removing ExtensionIds. (Thus, non-inferred deltas act as upper bounds). BREAKING CHANGE: ExtensionError moved from hugr::validate to hugr; Hugr::infer_extensions takes bool parameter
## 🤖 New release * `hugr`: 0.5.1 -> 0.6.0 * `hugr-core`: 0.2.0 -> 0.3.0 * `hugr-passes`: 0.2.0 -> 0.3.0 * `hugr-cli`: 0.1.1 -> 0.1.2 <details><summary><i><b>Changelog</b></i></summary><p> ## `hugr` <blockquote> ## 0.6.0 (2024-06-28) ### Bug Fixes - SimpleReplacement panic on multiports ([#1191](#1191)) - Add some validation for const nodes ([#1222](#1222)) - Cfg not validating entry/exit types ([#1229](#1229)) - `extract_hugr` not removing root node ports ([#1239](#1239)) ### Documentation - Fix documentation of `ValidationError::ConstTypeError` ([#1227](#1227)) ### Features - CircuitBuilder::add_constant ([#1168](#1168)) - [**breaking**] Make the rewrite errors more useful ([#1174](#1174)) - [**breaking**] Validate Extensions using hierarchy, ignore input_extensions, RIP inference ([#1142](#1142)) - [**breaking**] Infer extension deltas for Case, Cfg, Conditional, DataflowBlock, Dfg, TailLoop ([#1195](#1195)) - Helper functions for requesting inference, use with builder in tests ([#1219](#1219)) ### Refactor - [**breaking**] FunctionBuilder takes impl Into<PolyFuncType> ([#1220](#1220)) - [**breaking**] Remove NodeType and input_extensions ([#1183](#1183)) </blockquote> ## `hugr-core` <blockquote> ## 0.3.0 (2024-06-28) ### Bug Fixes - SimpleReplacement panic on multiports ([#1191](#1191)) - Add some validation for const nodes ([#1222](#1222)) - Cfg not validating entry/exit types ([#1229](#1229)) - `extract_hugr` not removing root node ports ([#1239](#1239)) ### Documentation - Fix documentation of `ValidationError::ConstTypeError` ([#1227](#1227)) ### Features - CircuitBuilder::add_constant ([#1168](#1168)) - [**breaking**] Make the rewrite errors more useful ([#1174](#1174)) - [**breaking**] Validate Extensions using hierarchy, ignore input_extensions, RIP inference ([#1142](#1142)) - [**breaking**] Infer extension deltas for Case, Cfg, Conditional, DataflowBlock, Dfg, TailLoop ([#1195](#1195)) - Helper functions for requesting inference, use with builder in tests ([#1219](#1219)) ### Refactor - [**breaking**] Remove NodeType and input_extensions ([#1183](#1183)) - [**breaking**] FunctionBuilder takes impl Into<PolyFuncType> ([#1220](#1220)) </blockquote> ## `hugr-passes` <blockquote> ## 0.3.0 (2024-06-28) ### Features - [**breaking**] Validate Extensions using hierarchy, ignore input_extensions, RIP inference ([#1142](#1142)) - Helper functions for requesting inference, use with builder in tests ([#1219](#1219)) </blockquote> ## `hugr-cli` <blockquote> ## 0.1.1 (2024-06-07) ### Features - Reexport `clap::Parser` and `clap_verbosity_flag::Level` from hugr_cli ([#1146](#1146)) ### Refactor - Move binary to hugr-cli ([#1134](#1134)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/MarcoIeni/release-plz/). --------- Co-authored-by: Douglas Wilson <[email protected]>
Hugr::infer_extensions
replaces TO_BE_INFERRED with the smallest set of ExtensionIds that's correct wrt. its child nodes (i.e., the union of the child node deltas). If there are other ExtensionIds alongside TO_BE_INFERRED these will be kept (allowing a "lower bound" to be specified for individual nodes)Hugr::infer_extensions
also takes aremove: bool
which, if true, modifies deltas of the same OpTypes that do not have TO_BE_INFERRED, by removing ExtensionIds. (Thus, non-inferred deltas act as upper bounds).Relates to #640 but does not address the builder where this should be the default behaviour.
BREAKING CHANGE: ExtensionError moved from hugr::validate to hugr; Hugr::infer_extensions takes bool parameter