-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Oxidize VariableMapper
and uses.
#14361
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
Conversation
...and add very unpleasant error handling code.
cf2fe19
to
a420113
Compare
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 15690052436Details
💛 - Coveralls |
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.
Overall this looks really good thanks for doing that. I have a couple inline comments but nothing major.
The other question I have is there a reason to keep the python space mapper class around anymore? I'm guessing the answer is QuantumCircuit.compose()
as that's the only usage I can find of it. That's probably blocked on #14299 so we might want to open a tracking issue for that.
fn may_have_additional_wires(&self, op: OperationRef) -> bool { | ||
let OperationRef::Instruction(inst) = op 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.
Not that this is a big deal, but was there a reason for this change. It's probably better like this, but I'm just wondering if there was a motivation on this?
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 don't actually recall why I'd done this originally. FWIW, I believe this changes again in the control flow oxidation PR.
|
||
pub(crate) struct VariableMapper { | ||
target_cregs: Vec<ClassicalRegister>, | ||
register_map: RefCell<HashMap<String, ClassicalRegister>>, |
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 curious why does this need interior mutability? Are we returning references to registers and need to mutate it as well?
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 reason is just that this is functionally a cache, only. Without the interior mutability, I'd need to make all of these map functions take a &mut self
, and that had less than ideal implications when working with this struct. IIRC, caching is the official Rust docs example for interior mutability, so I feel good about the use of it here lol
Thanks for the initial review! Yeah, you're spot on—we need to port |
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 LGTM! Just a minor nitpick and some appreciation :)
let qargs_list: Vec<&ShareableQubit> = self | ||
.qubits | ||
.map_indices(self.qargs_interner.get(node.qubits)) | ||
.collect(); | ||
let mut cargs_list: Vec<&ShareableClbit> = self | ||
.clbits | ||
.map_indices(self.cargs_interner.get(node.clbits)) | ||
.collect(); | ||
let cargs_set: HashSet<&ShareableClbit> = | ||
HashSet::from_iter(cargs_list.iter().cloned()); |
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.
Thank you for this 😄
} | ||
// This is maintaining the legacy behavior of `DAGCircuit.compose`. We don't | ||
// attempt to speed-up this lookup with a cache, since that would just make the more | ||
// standard cases more annoying to deal with. |
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 maintaining the legacy behavior of `DAGCircuit.compose`. We don't | |
// attempt to speed-up this lookup with a cache, since that would just make the more | |
// standard cases more annoying to deal with. | |
} | |
// This is maintaining the legacy behavior of `DAGCircuit.compose`. We don't | |
// attempt to speed-up this lookup with a cache, since that would just make the | |
// standard cases more annoying to deal with. |
Saying "more" twice here seems a bit redundant.
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 will defer this since the comment is just ported from the Python version 🙂
Summary
Ports the private Python-space helper class
VariableMapper
to Rust.Also introduces Rust-side iteration methods for classical expressions (
Expr
).Details and comments
Note that we still will need the
Python
token inDAGCircuit::{py_substitute_node_with_dag, compose}
until we (I) finish porting control flow.To-do
DAGCircuit::compose
to use newVariableMapper
.Make the existing Python-space variable mapper use the new one internally (we still need the Python interface forEdit: I'm going to defer this to whoever portsQuantumCircuit
.QuantumCircuit.compose
to Rust, rather than introducing some kind ofPyVariableMapper
wrapper that would go away during that process anyhow.Stretch
is being mapped properly byDAGCircuit::py_substitute_node_with_dag
Edit: onlytarget
andcondition
get mapped, and they'd never containStretch
so this is all set.