-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Move the circuit library's entanglement logic to Rust #12950
Conversation
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 10510704837Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
thanks @alexanderivrii for the hint!
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 @Cryoris - I only have some minor comments.
BTW, does porting this code to rust improves its performance ?
if let Ok(strategy) = entanglement.downcast::<PyString>() { | ||
let as_str = strategy.to_string(); | ||
return Ok(Box::new( | ||
get_entanglement_from_str(num_qubits, block_size, as_str.as_str(), offset)?.map(Ok), | ||
)); | ||
} else if let Ok(list) = entanglement.downcast::<PyList>() { | ||
let entanglement_iter = list.iter().map(move |el| { | ||
let connections = el | ||
.downcast::<PyTuple>() | ||
.expect("Entanglement must be list of tuples") // clearer error message than `?` | ||
.iter()? | ||
.map(|index| index?.downcast::<PyInt>()?.extract()) | ||
.collect::<Result<Vec<u32>, _>>()?; | ||
|
||
if connections.len() != block_size as usize { | ||
return Err(QiskitError::new_err(format!( | ||
"Entanglement {:?} does not match block size {}", | ||
connections, block_size | ||
))); | ||
} | ||
Ok(connections) | ||
}); | ||
return Ok(Box::new(entanglement_iter)); | ||
} | ||
Err(QiskitError::new_err( | ||
"Entanglement must be a string or list of qubit indices.", | ||
)) |
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.
To me this looks good, however I would appreciate if someone with more knowledge of Rust/Pyo3 would take a look as well (maybe @raynelfss)? In particular, is there a more ergonomic way to convert python lists of integers into a rust vector (avoiding some of the downcasting/extracting)?
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 there's a way I'd be glad to know it -- the NLocal
refactoring (on my local branch, not here) currently has quadruple nested lists which need casting to PyList
😅
if entanglement == "pairwise" && block_size > 2 { | ||
return Err(QiskitError::new_err(format!( | ||
"block_size ({}) can be at most 2 for pairwise entanglement", | ||
block_size | ||
))); | ||
} |
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.
Could we add this to the match
code below (by including ("pairwise", _)
after handling the other "pairwise" cases)?
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 idea 👍🏻
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.
LGTM, thanks for this development!
Summary
Move the entanglement logic used in the circuit library's
NLocal
circuits & friends to Rust. This PR is also the basis to move frequently used circuits, such asEfficientSU2
,TwoLocal
orZZFeatureMap
to Rust.This also fixes a bug in the
circular
entanglement which missed some entanglement blocks for entangling gates with 3+ qubits.Details and comments
NLocal
will directly use this function, but there's also a series of tests to check the different errors and possible input types.The attentive reader might notice that handling elaborate constructs such as
list[list[list[int]]]
are not handled, which does not affect the current code, but will change what we accept once the circuit library is moved to Rust. That's an intentional change as these types were used to allow different entanglements for different circuit layers (controlled byoffset
), but this was redundantly covered by passing a callable. Moving forward, the suggestion is to only allow a callable in these cases to have only 1 method of doing 1 thing 🙂