-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Add Rust matrix support for PauliProductRotation #15879
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
Changes from 8 commits
7d3f417
97b1fb6
bb1dad9
0d8e92f
5435705
c163201
2dec214
b20e4f0
ef5a9e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,6 @@ | |
| // Any modifications or derivative works of this code must retain this | ||
| // copyright notice, and modified files need to carry a notice indicating | ||
| // that they have been altered from the originals. | ||
|
|
||
| use approx::relative_eq; | ||
| use std::f64::consts::PI; | ||
| use std::fmt::Debug; | ||
|
|
@@ -3262,24 +3261,6 @@ impl PyInstruction { | |
| }) | ||
| } | ||
|
|
||
| pub fn matrix(&self) -> Option<Array2<Complex64>> { | ||
| Python::attach(|py| -> Option<Array2<Complex64>> { | ||
| match self.instruction.getattr(py, intern!(py, "to_matrix")) { | ||
| Ok(to_matrix) => { | ||
| let res: Option<Py<PyAny>> = to_matrix.call0(py).ok()?.extract(py).ok(); | ||
| match res { | ||
| Some(x) => { | ||
| let array: PyReadonlyArray2<Complex64> = x.extract(py).ok()?; | ||
| Some(array.as_array().to_owned()) | ||
| } | ||
| None => None, | ||
| } | ||
| } | ||
| Err(_) => None, | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| pub fn definition(&self) -> Option<CircuitData> { | ||
| Python::attach(|py| -> Option<CircuitData> { | ||
| match self.instruction.getattr(py, intern!(py, "definition")) { | ||
|
|
@@ -3311,6 +3292,24 @@ impl PyInstruction { | |
| }) | ||
| } | ||
|
|
||
| pub fn matrix(&self) -> Option<Array2<Complex64>> { | ||
| Python::attach(|py| -> Option<Array2<Complex64>> { | ||
| match self.instruction.getattr(py, intern!(py, "to_matrix")) { | ||
| Ok(to_matrix) => { | ||
| let res: Option<Py<PyAny>> = to_matrix.call0(py).ok()?.extract(py).ok(); | ||
| match res { | ||
| Some(x) => { | ||
| let array: PyReadonlyArray2<Complex64> = x.extract(py).ok()?; | ||
| Some(array.as_array().to_owned()) | ||
| } | ||
| None => None, | ||
| } | ||
| } | ||
| Err(_) => None, | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| pub fn matrix_as_static_2q(&self) -> Option<[[Complex64; 4]; 4]> { | ||
| if self.num_qubits() != 2 { | ||
| return None; | ||
|
|
@@ -3550,24 +3549,6 @@ pub struct PauliProductRotation { | |
| pub angle: Param, | ||
| } | ||
|
|
||
| impl Operation for PauliProductRotation { | ||
| fn name(&self) -> &str { | ||
| "pauli_product_rotation" | ||
| } | ||
| fn num_qubits(&self) -> u32 { | ||
| self.z.len() as u32 | ||
| } | ||
| fn num_clbits(&self) -> u32 { | ||
| 0 | ||
| } | ||
| fn num_params(&self) -> u32 { | ||
| 1 | ||
| } | ||
| fn directive(&self) -> bool { | ||
| false | ||
| } | ||
| } | ||
|
|
||
| impl PauliProductRotation { | ||
| pub fn create_py_op(&self, py: Python, label: Option<&str>) -> PyResult<Py<PyAny>> { | ||
| let z = self.z.to_pyarray(py); | ||
|
|
@@ -3587,6 +3568,43 @@ impl PauliProductRotation { | |
| )?; | ||
| Ok(gate.unbind()) | ||
| } | ||
| pub fn matrix(&self) -> Option<Array2<Complex64>> { | ||
| let angle = match self.angle { | ||
| Param::Float(f) => f, | ||
| _ => return None, | ||
| }; | ||
| let pauli_mat = gate_matrix::pauli_zx_to_dense_matrix(&self.z, &self.x); | ||
| let cos_val = (angle / 2.0).cos(); | ||
| let sin_val = (angle / 2.0).sin(); | ||
| let dim = pauli_mat.shape()[0]; | ||
| let identity = Array2::<Complex64>::eye(dim); | ||
| Some( | ||
| identity.mapv(|v| Complex64::new(v.re * cos_val, 0.)) | ||
| + pauli_mat.mapv(|v| Complex64::new(0., -sin_val) * v), | ||
| ) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the current identity.mapv(...) tells Rust to: Iterate over every single one of the 256 elements (even the 240 zeros as it's identity). Instead we can think of doing This may avoid unnecessary memory copies.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion — that makes sense. I’ve updated the implementation to construct the result directly from the Pauli matrix and add the cosine term to the diagonal in-place, avoiding the extra allocation from Please let me know if this looks good now. |
||
| } | ||
| } | ||
|
|
||
| impl Operation for PauliProductRotation { | ||
| fn name(&self) -> &str { | ||
| "pauli_product_rotation" | ||
| } | ||
|
|
||
| fn num_qubits(&self) -> u32 { | ||
| self.z.len() as u32 | ||
| } | ||
|
|
||
| fn num_clbits(&self) -> u32 { | ||
| 0 | ||
| } | ||
|
|
||
| fn num_params(&self) -> u32 { | ||
| 1 | ||
| } | ||
|
|
||
| fn directive(&self) -> bool { | ||
| false | ||
| } | ||
| } | ||
|
|
||
| impl PartialEq for PauliProductRotation { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| features: | ||
| - | | ||
| Added Rust-side matrix support for ``PauliProductRotationGate`` by reusing | ||
| the existing Pauli matrix construction logic from the Rust | ||
| ``SparsePauliOp`` 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.
You are calling
gate_matrix::pauli_zx_to_dense_matrix, but the function you added insparse_pauli_op.rsis namedpauli_zx_to_matrixThere 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 catch, thanks for pointing that out.
I’ve updated the call to use
pauli_zx_to_matrixand ensured it is correctly defined and used withingate_matrixto avoid cross-crate dependency issues. The naming and usage are now aligned.Please let me know if anything else needs refinement.