-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Support commutation check between Pauli-based gates and standard gates (After reverting #15488) #15925
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
Merged
Merged
Support commutation check between Pauli-based gates and standard gates (After reverting #15488) #15925
Changes from 53 commits
Commits
Show all changes
62 commits
Select commit
Hold shift + click to select a range
b7ac6b4
Transpiler: implement exact Pauli generators for LightCone in Rust
debasmita2102 75c3d1f
Lint: apply cargo fmt and fix clippy::map_clone in split_2q_unitaries.rs
debasmita2102 1ba26a7
Expose generator_observable to Python
debasmita2102 ab5ebad
Refactor generator logic to use qiskit_circuit::StandardGate
debasmita2102 b45d2ab
Update generator_observable with expansions for CCX/CCZ/CSwap
debasmita2102 307486f
Fix generator fallback for unsupported gates and update docs
debasmita2102 f36974a
Narrow PR scope: remove split_2q_unitaries and pyext python wrapper
debasmita2102 331a972
Add generator support for CS, CSdg, CSX, CCX, CCZ; add commutation tests
debasmita2102 c1c6474
style: run black on test_commutation_checker.py
debasmita2102 8b6ad0d
style: run rustfmt on standard_generators.rs
debasmita2102 d46faa9
lint: fix license headers and pylint warnings
debasmita2102 b379cab
style: remove decorative unicode lines and add operator equivalence t…
debasmita2102 8eca98f
fix: ensure strict Operator equivalence for all supported generators
debasmita2102 82d06c3
style: fix pylint reimport and missing variables in test_commutation_…
debasmita2102 ba51fa3
Add generic generator equivalence test, fix matrix conversion, and op…
debasmita2102 5a598f4
Format python tests
debasmita2102 479cb55
Update copyright year in standard_generators.rs
debasmita2102 6e49f7d
Clarify docstring for multi-qubit generators context
debasmita2102 41e6822
Fix XXPlusYY and XXMinusYY generator validation and test cases
debasmita2102 14d8260
Move test imports to top of file
debasmita2102 b42479c
Use ddt data parameterization for gate generator testing tests
debasmita2102 4bd721d
Refactor test_clifford_gates_have_generators to use ddt
debasmita2102 ea2f559
Add CPhase, CRX, CRY, CRZ to generator tests
debasmita2102 4f1b312
Update test_all_gates_operator_equivalence_ddt docstring to be more a…
debasmita2102 b783d6b
Move all inline imports to the top of the file
debasmita2102 9785156
Reorganize test data to group related gates logically
debasmita2102 2604588
Add tests for unsupported gates and parameters in generator logic
debasmita2102 800bbdf
Rename test helper to _commute to reflect that it uses either generat…
debasmita2102 246fa63
Clarify parameter handling in generator_observable docstring
debasmita2102 6ea2944
Comprehensive audit: Add Identity support and register all missing ga…
debasmita2102 7f37313
Fix: Correct gate generator expansions and resolve UnsortedIndices la…
debasmita2102 ee303f8
pose generator engine, restore overflow logic, expand tests, and cent…
debasmita2102 30903a9
Update crates/circuit/src/util.rs
debasmita2102 a221780
Update releasenotes/notes/pauli-evolution-commutation-8f7caab8.yaml
debasmita2102 56ddaf6
Update releasenotes/notes/pauli-evolution-commutation-8f7caab8.yaml
debasmita2102 bc07ec1
added missing gate, added test, copyright year, doc explaining
debasmita2102 b490441
restore negative constants to util.rs for generator expansions
debasmita2102 33effd8
fix lint errors in regression test and move imports to top
debasmita2102 c5e07f0
Final PR fixes: address remaining lint issues and update copyright he…
debasmita2102 b7329c7
Remove accidental temporary files from PR
debasmita2102 edc9c6b
Restore original copyright years for existing files (only PR-created …
debasmita2102 de6b82e
Permanently delete bicycle-architecture-compiler from branch
debasmita2102 6aededd
resolved merge conflicts
debasmita2102 514c166
removed redundant constants blocking branch conflict
debasmita2102 dfc6a45
fix lint and formatting issues
debasmita2102 37dd7fd
docstring edits
debasmita2102 267c106
docstring formatting
debasmita2102 fbd90d5
fixing formatting
debasmita2102 fbd68b4
revert docstring changes to fix lint failure
debasmita2102 34c2795
Reverted changes in max_entries_per_row
debasmita2102 70d1602
renaming tests
debasmita2102 16c88e6
readded the comments in cargo test
debasmita2102 f96a972
Cleanup and reword method
Cryoris 9fb660d
Merge branch 'main' into lightcone-fix
Cryoris 10c28cb
Reno and rm duplicated block
Cryoris 3b70253
Sasha's review comments
Cryoris 5cd398c
Remove some unused imports
Cryoris 5e01660
Merge branch 'main' into lightcone-fix
Cryoris 71cdd06
Move pickle import back to where it was
Cryoris b07f90d
Merge branch 'lightcone-fix' of github.com:debasmita2102/qiskit into …
Cryoris e5d15fd
Fix circuit crate dependency
Cryoris f78b306
Rm incorrect sentence on commutation
Cryoris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,350 @@ | ||
| // This code is part of Qiskit. | ||
| // | ||
| // (C) Copyright IBM 2026 | ||
| // | ||
| // This code is licensed under the Apache License, Version 2.0. You may | ||
| // obtain a copy of this license in the LICENSE.txt file in the root directory | ||
| // of this source tree or at https://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // 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. | ||
|
|
||
| // AI Attribution: | ||
| // This module was developed with assistance from GitHub Copilot integrated in VS Code. | ||
| // The underlying model : Claude Haiku 4.5. | ||
| // Portions of the Pauli generator mapping logic and SoA layout were generated | ||
| // and then manually verified for mathematical correctness against the commutation logic. | ||
| // | ||
| // This module maps standard quantum gates to their Hamiltonian generators H_gate such that: | ||
| // | ||
| // gate = exp(-i * H_gate) (up to global phase) | ||
| // | ||
| // The generator is returned as a SparseObservable (a sum of Pauli tensor products). | ||
| // | ||
| // For single-qubit gates: X = exp(-i*(pi/2)*X), H = exp(-i*(pi/2)*(X+Z)/sqrt(2)), etc. | ||
| // For multi-qubit controlled gates: CX = exp(-i*(pi/4)*(ZX - ZI - IX)), etc. | ||
| // For rotation gates: RX(t) = exp(-i*(t/2)*X), RY(t) = exp(-i*(t/2)*Y), etc. | ||
| // | ||
| // The SoA (Struct-of-Arrays) layout is used: `bit_terms`, `indices`, and `boundaries` are | ||
| // flattened arrays. Term `i` uses bit_terms[boundaries[i]..boundaries[i+1]] and | ||
| // indices[boundaries[i]..boundaries[i+1]] for its Pauli operators and qubit targets. | ||
|
|
||
| use crate::sparse_observable::SparseObservable; | ||
| use pyo3::prelude::*; | ||
| use pyo3::wrap_pyfunction; | ||
|
|
||
| use num_complex::Complex64; | ||
| use qiskit_circuit::operations::{Operation, Param, StandardGate}; | ||
| use qiskit_util::complex::{C_ZERO, c64}; | ||
| use std::f64::consts::{FRAC_PI_2, FRAC_PI_4, FRAC_PI_8, SQRT_2}; | ||
|
|
||
| const C_FRAC_PI_2: Complex64 = c64(FRAC_PI_2, 0.0); | ||
| const C_FRAC_PI_4: Complex64 = c64(FRAC_PI_4, 0.0); | ||
| const C_FRAC_PI_8: Complex64 = c64(FRAC_PI_8, 0.0); | ||
| const C_FRAC_PI_2_SQRT_2: Complex64 = c64(FRAC_PI_2 / SQRT_2, 0.0); | ||
| const C_M_FRAC_PI_4: Complex64 = c64(-FRAC_PI_4, 0.0); | ||
| const C_M_FRAC_PI_8: Complex64 = c64(-FRAC_PI_8, 0.0); | ||
| const C_M_FRAC_PI_2_SQRT_2: Complex64 = c64(-FRAC_PI_2 / SQRT_2, 0.0); | ||
|
|
||
| const BETA_TOLERANCE: f64 = 1e-10; | ||
|
|
||
| /// For parametric gates (e.g., `RX(theta)`), the generator $H$ depends on the | ||
| /// gate parameters (e.g., $H = (\theta/2)X$). This function extracts parameter values | ||
| /// from the `params` slice to compute the concrete coefficients for the returned | ||
| /// `SparseObservable`. | ||
| /// | ||
| /// If parameters are missing or symbolic (non-`Float`), it defaults to a coefficient | ||
|
Cryoris marked this conversation as resolved.
Outdated
|
||
| /// of 1.0. This allows the commutation checker to still prove commutation in cases | ||
| /// where the generator's Pauli structure alone is sufficient (e.g., `[theta*X, X] = 0` | ||
| /// for any `theta`), but it avoids attempting to store parametric expressions, which | ||
| /// `SparseObservable` does not currently support. | ||
|
Cryoris marked this conversation as resolved.
Outdated
|
||
| pub fn standard_gate_exponent(gate: StandardGate, params: &[Param]) -> Option<SparseObservable> { | ||
| // let _params = params; | ||
| let fixed_params = params | ||
| .iter() | ||
| .map(|p| match p { | ||
| Param::Float(f) => *f, | ||
| Param::ParameterExpression(_) => 1.0, | ||
| Param::Obj(_) => panic!("StandardGate's don't have Param::Obj"), | ||
|
Cryoris marked this conversation as resolved.
Outdated
|
||
| }) | ||
| .collect::<Vec<f64>>(); | ||
|
|
||
| let num_qubits = gate.num_qubits(); | ||
|
|
||
| use crate::sparse_observable::BitTerm::*; | ||
|
|
||
| let (coeffs, bit_terms, indices, boundaries) = match gate { | ||
| StandardGate::GlobalPhase => (vec![c64(-fixed_params[0], 0.)], vec![], vec![], vec![0, 0]), | ||
| // H = exp(-i pi/sqrt(8) (X + Z)) | ||
| StandardGate::H => ( | ||
| vec![C_FRAC_PI_2_SQRT_2, C_FRAC_PI_2_SQRT_2], | ||
| vec![X, Z], | ||
| vec![0, 0], | ||
| vec![0, 1, 2], | ||
| ), | ||
| // X = exp(-i pi/2 X), Y = exp(-i pi/2 Y), Z = exp(-i pi/2 Z) | ||
| StandardGate::X => (vec![C_FRAC_PI_2], vec![X], vec![0], vec![0, 1]), | ||
| StandardGate::Y => (vec![C_FRAC_PI_2], vec![Y], vec![0], vec![0, 1]), | ||
| StandardGate::Z => (vec![C_FRAC_PI_2], vec![Z], vec![0], vec![0, 1]), | ||
| // Identity: exp(-i 0) = I. | ||
| StandardGate::I => (vec![C_ZERO], vec![], vec![], vec![0, 0]), | ||
| // S = exp(-i pi/4 Z), Sdg = exp(-i (-pi/4) Z) | ||
| StandardGate::S => (vec![C_FRAC_PI_4], vec![Z], vec![0], vec![0, 1]), | ||
| StandardGate::Sdg => (vec![C_M_FRAC_PI_4], vec![Z], vec![0], vec![0, 1]), | ||
| // T = exp(-i pi/8 Z), Tdg = exp(-i (-pi/8) Z) | ||
| StandardGate::T => (vec![C_FRAC_PI_8], vec![Z], vec![0], vec![0, 1]), | ||
| StandardGate::Tdg => (vec![C_M_FRAC_PI_8], vec![Z], vec![0], vec![0, 1]), | ||
| // SX = exp(-i pi/4 X), SXdg = exp(-i (-pi/4) X) | ||
| StandardGate::SX => (vec![C_FRAC_PI_4], vec![X], vec![0], vec![0, 1]), | ||
| StandardGate::SXdg => (vec![C_M_FRAC_PI_4], vec![X], vec![0], vec![0, 1]), | ||
| // RX(t) = exp(-i t/2 X), RY, RZ=Phase, equivalently | ||
| StandardGate::RX => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![X], | ||
| vec![0], | ||
| vec![0, 1], | ||
| ), | ||
| StandardGate::RY => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![Y], | ||
| vec![0], | ||
| vec![0, 1], | ||
| ), | ||
| StandardGate::RZ | StandardGate::Phase | StandardGate::U1 => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![Z], | ||
| vec![0], | ||
| vec![0, 1], | ||
| ), | ||
| // CX = exp(-i pi/4 (ZX - ZI - IX)) | ||
| StandardGate::CX => ( | ||
| vec![C_M_FRAC_PI_4, C_FRAC_PI_4, C_FRAC_PI_4], | ||
| vec![Z, X, Z, X], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 3, 4], | ||
| ), | ||
| // CY = exp(-i pi/4 (ZY - ZI - IY)) | ||
| StandardGate::CY => ( | ||
| vec![C_M_FRAC_PI_4, C_FRAC_PI_4, C_FRAC_PI_4], | ||
| vec![Z, Y, Z, Y], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 3, 4], | ||
| ), | ||
| // CZ = exp(-i pi/4 (ZZ - ZI - IZ)) | ||
| StandardGate::CZ => ( | ||
| vec![C_M_FRAC_PI_4, C_FRAC_PI_4, C_FRAC_PI_4], | ||
| vec![Z, Z, Z, Z], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 3, 4], | ||
| ), | ||
| // CS = exp(-i (-pi/8) (ZZ - ZI - IZ)) | ||
| StandardGate::CS => ( | ||
| vec![C_FRAC_PI_8, C_FRAC_PI_8, C_M_FRAC_PI_8], | ||
| vec![Z, Z, Z, Z], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 1, 2, 4], | ||
| ), | ||
| // CSdg (inv sqrt(CZ)): factor +pi/8 | ||
| StandardGate::CSdg => ( | ||
| vec![C_M_FRAC_PI_8, C_M_FRAC_PI_8, C_FRAC_PI_8], | ||
| vec![Z, Z, Z, Z], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 1, 2, 4], | ||
| ), | ||
| // CSX (sqrt(CX)/controlled-SX): factor -pi/8 | ||
| StandardGate::CSX => ( | ||
| vec![C_FRAC_PI_8, C_FRAC_PI_8, C_M_FRAC_PI_8], | ||
| vec![Z, X, Z, X], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 1, 2, 4], | ||
| ), | ||
| // CRX(t) = exp(-i t/4 (-ZX + IX)) | ||
| StandardGate::CRX => ( | ||
| vec![ | ||
| c64(-fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![Z, X, X], | ||
| vec![0, 1, 1], | ||
| vec![0, 2, 3], | ||
| ), | ||
| // CRY(t) = exp(-i t/4 (-ZY + IY)) | ||
| StandardGate::CRY => ( | ||
| vec![ | ||
| c64(-fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![Z, Y, Y], | ||
| vec![0, 1, 1], | ||
| vec![0, 2, 3], | ||
| ), | ||
| // CRZ(t) = exp(-i t/4 (-ZZ + IZ)) | ||
| StandardGate::CRZ => ( | ||
| vec![ | ||
| c64(-fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![Z, Z, Z], | ||
| vec![0, 1, 1], | ||
| vec![0, 2, 3], | ||
| ), | ||
| // CPhase(t) = exp(-i t/4 (-ZZ + ZI + IZ)) | ||
| // (same as CRZ but shifts both Z0 and Z1, not just Z1) | ||
| StandardGate::CPhase => ( | ||
| vec![ | ||
| c64(-fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![Z, Z, Z, Z], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 3, 4], | ||
| ), | ||
| // Swap = exp(-i pi/4 (XX + YY + ZZ)) | ||
| StandardGate::Swap => ( | ||
| vec![C_FRAC_PI_4, C_FRAC_PI_4, C_FRAC_PI_4], | ||
| vec![X, X, Y, Y, Z, Z], | ||
| vec![0, 1, 0, 1, 0, 1], | ||
| vec![0, 2, 4, 6], | ||
| ), | ||
| // ISwap = exp(-i (-pi/4) (XX + YY)) | ||
| StandardGate::ISwap => ( | ||
| vec![C_M_FRAC_PI_4, C_M_FRAC_PI_4], | ||
| vec![X, X, Y, Y], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 4], | ||
| ), | ||
| // RXX(t) = exp(-i t/2 XX) | ||
| StandardGate::RXX => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![X, X], | ||
| vec![0, 1], | ||
| vec![0, 2], | ||
| ), | ||
| // RYY(t) = exp(-i t/2 YY) | ||
| StandardGate::RYY => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![Y, Y], | ||
| vec![0, 1], | ||
| vec![0, 2], | ||
| ), | ||
| // RZZ(t) = exp(-i t/2 ZZ) | ||
| StandardGate::RZZ => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![Z, Z], | ||
| vec![0, 1], | ||
| vec![0, 2], | ||
| ), | ||
| // RZX(t) = exp(-i t/2 ZX) | ||
| StandardGate::RZX => ( | ||
| vec![c64(fixed_params[0] / 2.0, 0.0)], | ||
| vec![Z, X], | ||
| vec![0, 1], | ||
| vec![0, 2], | ||
| ), | ||
| // XX+YY and XX-YY are just handled if the beta parameter is 0, in which case | ||
| // the generator is XX +- YY. | ||
| StandardGate::XXPlusYY | StandardGate::XXMinusYY => { | ||
| // This covers both parametric ``beta`` and if they are above tolerance | ||
| if fixed_params[1].abs() > BETA_TOLERANCE { | ||
| return None; | ||
| } | ||
|
|
||
| match gate { | ||
| StandardGate::XXPlusYY => ( | ||
| vec![ | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![X, X, Y, Y], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 4], | ||
| ), | ||
| StandardGate::XXMinusYY => ( | ||
| vec![ | ||
| c64(fixed_params[0] / 4.0, 0.0), | ||
| c64(-fixed_params[0] / 4.0, 0.0), | ||
| ], | ||
| vec![X, X, Y, Y], | ||
| vec![0, 1, 0, 1], | ||
| vec![0, 2, 4], | ||
| ), | ||
| _ => unreachable!(), | ||
| } | ||
| } | ||
| // CCX = exp(-i pi/8 (ZZX - ZIX - IZX - ZZI + ZII + IZI + IIX)) | ||
| StandardGate::CCX => ( | ||
| vec![ | ||
| C_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| ], | ||
| vec![Z, Z, X, Z, X, Z, X, Z, Z, Z, Z, X], | ||
| vec![0, 1, 2, 0, 2, 1, 2, 0, 1, 0, 1, 2], | ||
| vec![0, 3, 5, 7, 9, 10, 11, 12], | ||
| ), | ||
| // Same as CCX but with Z on the target | ||
| StandardGate::CCZ => ( | ||
| vec![ | ||
| C_M_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| ], | ||
| vec![Z, Z, Z, Z, Z, Z, Z, Z, Z, Z, Z, Z], | ||
| vec![0, 1, 2, 0, 2, 1, 2, 0, 1, 0, 1, 2], | ||
| vec![0, 3, 5, 7, 9, 10, 11, 12], | ||
| ), | ||
| // CSwap = exp(-i pi/8 (ZII - ZXX - ZYY - ZZZ + IXX + IYY + IZZ)) | ||
| StandardGate::CSwap => ( | ||
| vec![ | ||
| C_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_M_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| C_FRAC_PI_8, | ||
| ], | ||
| vec![Z, Z, X, X, Z, Y, Y, Z, Z, Z, X, X, Y, Y, Z, Z], | ||
| vec![0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 1, 2, 1, 2, 1, 2], | ||
| vec![0, 1, 4, 7, 10, 12, 14, 16], | ||
| ), | ||
| // ECR = exp(-i pi/sqrt(8) (IX - XY)) | ||
| StandardGate::ECR => ( | ||
| vec![C_FRAC_PI_2_SQRT_2, C_M_FRAC_PI_2_SQRT_2], | ||
| vec![X, Y, X], | ||
| vec![0, 0, 1], | ||
| vec![0, 1, 3], | ||
| ), | ||
| _ => return None, | ||
| }; | ||
|
|
||
| // SAFETY: The internal data was constructed manually and is consistent. | ||
| Some(unsafe { | ||
| SparseObservable::new_unchecked(num_qubits, coeffs, bit_terms, indices, boundaries) | ||
| }) | ||
| } | ||
|
|
||
| #[pyfunction(name = "_standard_gate_exponent")] | ||
| #[pyo3(signature = (gate, params=None))] | ||
| pub fn py_standard_gate_exponent( | ||
| gate: StandardGate, | ||
| params: Option<Vec<Param>>, | ||
| ) -> Option<SparseObservable> { | ||
| let params = params.unwrap_or_default(); | ||
| standard_gate_exponent(gate, ¶ms) | ||
| } | ||
|
|
||
| pub fn standard_generators(m: &Bound<PyModule>) -> PyResult<()> { | ||
| m.add_function(wrap_pyfunction!(py_standard_gate_exponent, m)?)?; | ||
| Ok(()) | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.