-
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
Implement RGate in Rust #12662
Implement RGate in Rust #12662
Conversation
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 9673800273Details
💛 - 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.
Thanks for the PR! it looks pretty good, I just left a couple of comments.
@@ -21,7 +21,7 @@ | |||
from qiskit.circuit import QuantumCircuit | |||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping | |||
|
|||
SKIP_LIST = {"rx", "ry", "ecr"} | |||
SKIP_LIST = {"rx", "ry", "ecr", "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.
Why add the r
gate to the SKIP_LIST? All others haven't been implemented yet, but r
has an implementation.
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. I added and removed several times while debugging. I'll recheck.
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.
Fixed in 7eef0f3
(#12662). It failed because the decomposition had an error.
crates/circuit/src/operations.rs
Outdated
let theta_expr = match ¶ms[0] { | ||
Param::Float(theta) => Param::Float(*theta), | ||
Param::ParameterExpression(theta) => { | ||
Param::ParameterExpression(theta.clone_ref(py)) | ||
} | ||
Param::Obj(_) => unreachable!(), | ||
}; | ||
let (phi_expr1, phi_expr2) = match ¶ms[0] { | ||
Param::Float(phi) => (Param::Float(*phi - 1.0), Param::Float(-*phi + 1.0)), | ||
Param::ParameterExpression(phi) => { | ||
let phiexpr1 = phi | ||
.call_method1(py, intern!(py, "__add__"), ((-PI / 2.0),)) | ||
.expect("Unexpected Qiskit python bug"); | ||
let phiexpr2 = phiexpr1 | ||
.call_method1(py, intern!(py, "__rmul__"), (-1.0,)) | ||
.expect("Unexpected Qiskit python bug"); | ||
( | ||
Param::ParameterExpression(phiexpr1), | ||
Param::ParameterExpression(phiexpr2), | ||
) | ||
} | ||
Param::Obj(_) => unreachable!(), | ||
}; | ||
let defparams = smallvec![theta_expr, phi_expr1, phi_expr2]; | ||
Some( | ||
CircuitData::from_standard_gates( | ||
py, | ||
1, | ||
[(Self::UGate, defparams, smallvec![Qubit(0)])], | ||
FLOAT_ZERO, | ||
) | ||
.expect("Unexpected Qiskit python bug"), | ||
) | ||
}), |
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 this could be more readable if we used helper functions like multiply_param
, and maybe add one for adding a scalar to a parameter in the same fashion. But I am fine merging the implementation as-is and beautifying it later.
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 first iteration did not fit with the helper function, nor one for add
. But it's changed a lot since I last tried. I'll revisit it; readability and encapsulation is important.
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 did something similar to your suggest in 49c8dcd
(#12662). This factors out cloning a Param
. This is only used once now, but can be used whenever a Param
needs to be cloned. I find the code much more readable at the call point.
Regarding factoring out add_param
: There are pros and cons to doing this. Disadvantages: The branch with -*phi + PI / 2.0
is more readable if it is not nested calls. In fact, this made it slightly easier for me to spot the error -*phi + 1.0
.
Another one is that it requires two match statements rather than one, so -*phi + PI / 2.0
won't be optimized. I'm not sure, but I doubt this will matter in the future for performance.
But, I'm on the fence. Currently, the second match arm would be much more readable with your suggestion. I can implement and use add_param
quickly if you prefer. I'm inclined to do it just to look at 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.
Implemented your suggestion in 07fec37
(#12662). I'm not 100% sure there isn't a non-negligible efficiency hit. But I think it's easier to read and will be easier to build on.
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 see your point, I think we could merge the code as-is and once all Rust standard gates are in place, maybe run the benchmarks with/without add_param
to see if there is indeed a significant performance hit.
Co-authored-by: Elena Peña Tapia <[email protected]>
Pull Request Test Coverage Report for Build 9681898421Warning: 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 |
There is an error in the expression for decomposition of the R gate in the port to Rust. This fixes the error and re-enables the skipped test that failed because of the incorrect expression.
To clone the enum, each variant must be handled separately. This is currently used once, but can be used each time a `Param` is cloned. In case more work needs to be done within match arms, one might choose not to use this function, but rather clone in each of these arms.
This handles `Float` and `ParameterExpression` variants uniformly.
Pull Request Test Coverage Report for Build 9688190770Details
💛 - 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.
* Implement RGate in Rust * Update crates/circuit/src/operations.rs Co-authored-by: Elena Peña Tapia <[email protected]> * Fix error in decomposition of RGate There is an error in the expression for decomposition of the R gate in the port to Rust. This fixes the error and re-enables the skipped test that failed because of the incorrect expression. * Factor cloning the Param enum in Rust To clone the enum, each variant must be handled separately. This is currently used once, but can be used each time a `Param` is cloned. In case more work needs to be done within match arms, one might choose not to use this function, but rather clone in each of these arms. * Run cargo fmt * Implement and use addition for enum Param This handles `Float` and `ParameterExpression` variants uniformly. --------- Co-authored-by: Elena Peña Tapia <[email protected]>
This completes all tasks of implementing
RGate
in Rust rather than Python.This replaces
#12507 has been modified and split into the present PR and #12651