Skip to content
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
4d160bc
Add new multithreaded TwoQubitPeepholeOptimization pass
mtreinish Nov 10, 2024
decee9a
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Dec 1, 2024
746758f
Add support for running the TwoQubitControlledUDecomposer
mtreinish Dec 1, 2024
ee70e65
Suprress clippy warning about mismatch enum variant sizes
mtreinish Dec 1, 2024
4d4df68
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Dec 1, 2024
cb6b70f
Embed 2q gate count into score as tie breaker
mtreinish Dec 2, 2024
f06a070
Release GIL during parallel portion
mtreinish Dec 2, 2024
90b16e8
Merge branch 'main' into two-qubit-peephole-parallel-pass
mtreinish Jan 13, 2025
a175ee8
Fix lint
mtreinish Jan 13, 2025
af0c144
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Jan 26, 2025
79a46c5
Update ControlledUDecomposer to ensure we only run if the gate is con…
mtreinish Jan 26, 2025
839b4c9
Add reversed synthesis for two qubit basis decomposer
mtreinish Jan 26, 2025
d9399a6
Fix handling of single direction gates
mtreinish Jan 26, 2025
b4c4360
Fix import cycle
mtreinish Jan 26, 2025
aefdc90
Merge branch 'main' into two-qubit-peephole-parallel-pass
mtreinish Feb 4, 2025
746b953
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Feb 19, 2025
f2bb1fb
Flip scoring value to (2q gate count, predicted error)
mtreinish Feb 19, 2025
55b05c0
Add docstring to new pass
mtreinish Feb 19, 2025
7756d1e
Add release note
mtreinish Feb 19, 2025
6a01332
Run serially in multiprocessing context
mtreinish Feb 19, 2025
d83562b
Fix cache build
mtreinish Feb 20, 2025
5f73b93
Add tests
mtreinish Feb 26, 2025
5e6c4cb
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 11, 2025
8c7e67c
Rebase updates
mtreinish Apr 11, 2025
f41e855
Adjust tests
mtreinish Apr 11, 2025
3cdee4f
Clean-up test lint
mtreinish Apr 17, 2025
fd96145
Remove plugin method support from the new pass
mtreinish Apr 17, 2025
89931a4
Fix oversight in test code
mtreinish Apr 17, 2025
19368bb
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 17, 2025
14e421c
Fix test failures
mtreinish Apr 17, 2025
02785e1
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 17, 2025
c7ba671
Update target usage for recent changes
mtreinish Apr 17, 2025
089d3b6
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 18, 2025
9f820c1
Simplify argument typing on new dag builder
mtreinish Apr 18, 2025
bfdfe46
Use dag builder api
mtreinish Apr 18, 2025
f72df7d
Fix error handling for target lookup
mtreinish Apr 18, 2025
bb31eb5
Fix some bugs and expand tests
mtreinish Apr 18, 2025
1985ff4
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Jun 10, 2025
ed262ac
Deduplicate synthesis path between unitary synthesis and peephole
mtreinish Jun 14, 2025
817c2b1
Fix target handling in peephole pass
mtreinish Jun 14, 2025
24b3e44
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Jun 14, 2025
dbbcb37
Fix merge conflict
mtreinish Jun 14, 2025
439e1eb
Expand test coverage to check individual gate synthesis
mtreinish Jun 14, 2025
b24088a
Fix release note example
mtreinish Jun 14, 2025
117b793
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Jul 7, 2025
3b92602
Include single qubit gate count in the heuristic
mtreinish Jul 9, 2025
0374185
Fix approximate-by-default behaviour of `UnitarySynthesis`
jakelishman Mar 13, 2026
3fce976
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 15, 2026
8acceee
Merge remote-tracking branch 'jakelishman/correct-approximation-degre…
mtreinish Mar 16, 2026
a64f6c0
Update the pass to leverage unitary synthesis logic for decomposition
mtreinish Mar 16, 2026
785a02b
Fix directionality test
mtreinish Mar 17, 2026
437e900
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 17, 2026
2f682d5
Fix dag reconstruction bug on insertion too early
mtreinish Mar 17, 2026
79f2466
Remove smallvec usage for original sequence scoring
mtreinish Mar 17, 2026
1cdaa61
Fix original score creation
mtreinish Mar 17, 2026
4503c14
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 17, 2026
a7794ff
Fix comparison between original score and new score
mtreinish Mar 17, 2026
8bcc573
Use Dashmap<NodeIndex, usize> instead of Mutex<HashMap<NodeIndex, usi…
mtreinish Mar 17, 2026
4ecb01e
Use thread local storage for decomposer cache
mtreinish Mar 18, 2026
76b40ab
Fix doc indent
mtreinish Mar 18, 2026
76f5935
Appease the lint check changing http->https in the license header
mtreinish Mar 18, 2026
2d40a18
Fix release note
mtreinish Mar 18, 2026
b88de4a
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 18, 2026
ce3dddf
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 19, 2026
158725f
Return a user error from a decomposer build with an incorrect string …
mtreinish Mar 19, 2026
a8a3fe7
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 23, 2026
a1643a8
Fix scoring of single decomposition
mtreinish Mar 23, 2026
8c58c3a
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 25, 2026
dfbe65d
Performance tuning
mtreinish Mar 26, 2026
9356125
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Mar 31, 2026
9e3a651
Don't use a hashset for tracking processed runs
mtreinish Mar 31, 2026
500a964
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 2, 2026
a8dce96
Remove unnecessary empty check and use Mutex::into_inner() when no mo…
mtreinish Apr 2, 2026
2784217
Add atomic bool to tracking whether we've made a substitution
mtreinish Apr 2, 2026
469c06b
Merge remote-tracking branch 'origin/main' into two-qubit-peephole-pa…
mtreinish Apr 25, 2026
b9ce054
Add release note details to the pass docstring
mtreinish Apr 25, 2026
12b14ee
Update test module docstring
mtreinish Apr 25, 2026
f80db21
Update pass module docstring
mtreinish Apr 25, 2026
8c03af3
Fix typo in code comment
mtreinish Apr 25, 2026
819110d
Add docstrings for the new UnitarySynthesis helper methods
mtreinish Apr 25, 2026
56ea5aa
Expand 2q basis fore new tests
mtreinish Apr 25, 2026
31f616f
Use the peephole pass heuristic for best synthesis selection
mtreinish Apr 25, 2026
ddd8fdd
Add alt text to plot
mtreinish Apr 26, 2026
7c2f549
Add missing docs ref label
mtreinish Apr 26, 2026
5c6d650
Add xx +/- yy gates to test matrix
mtreinish Apr 26, 2026
66a90de
Assert a single 2q gate on controlled u decomposition
mtreinish Apr 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/accelerate/src/consolidate_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub(crate) fn consolidate_blocks(
dag.get_qargs(inst.qubits),
) {
all_block_gates.insert(inst_node);
let matrix = match get_matrix_from_inst(py, inst) {
let matrix = match get_matrix_from_inst(inst) {
Ok(mat) => mat,
Err(_) => continue,
};
Expand Down Expand Up @@ -215,7 +215,7 @@ pub(crate) fn consolidate_blocks(
*block_qargs.iter().min().unwrap(),
*block_qargs.iter().max().unwrap(),
];
let matrix = blocks_to_matrix(py, dag, &block, block_index_map).ok();
let matrix = blocks_to_matrix(dag, &block, block_index_map).ok();
if let Some(matrix) = matrix {
let num_basis_gates = match decomposer {
DecomposerType::TwoQubitBasis(ref decomp) => {
Expand Down Expand Up @@ -279,7 +279,7 @@ pub(crate) fn consolidate_blocks(
first_qubits,
)
{
let matrix = match get_matrix_from_inst(py, first_inst) {
let matrix = match get_matrix_from_inst(first_inst) {
Ok(mat) => mat,
Err(_) => continue,
};
Expand All @@ -303,7 +303,7 @@ pub(crate) fn consolidate_blocks(
already_in_block = true;
}
let gate = dag[*node].unwrap_operation();
let operator = match get_matrix_from_inst(py, gate) {
let operator = match get_matrix_from_inst(gate) {
Ok(mat) => mat,
Err(_) => {
// Set this to skip this run because we can't compute the matrix of the
Expand Down
21 changes: 11 additions & 10 deletions crates/accelerate/src/convert_2q_block_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ use crate::euler_one_qubit_decomposer::matmul_1q;
use crate::QiskitError;

#[inline]
pub fn get_matrix_from_inst(py: Python, inst: &PackedInstruction) -> PyResult<Array2<Complex64>> {
pub fn get_matrix_from_inst(inst: &PackedInstruction) -> PyResult<Array2<Complex64>> {
if let Some(mat) = inst.op.matrix(inst.params_view()) {
Ok(mat)
} else if inst.op.try_standard_gate().is_some() {
Err(QiskitError::new_err(
"Parameterized gates can't be consolidated",
))
} else if let OperationRef::Gate(gate) = inst.op.view() {
Ok(QI_OPERATOR
.get_bound(py)
.call1((gate.gate.clone_ref(py),))?
.getattr(intern!(py, "data"))?
.extract::<PyReadonlyArray2<Complex64>>()?
.as_array()
.to_owned())
Python::with_gil(|py| {
Ok(QI_OPERATOR
.get_bound(py)
.call1((gate.gate.clone_ref(py),))?
.getattr(intern!(py, "data"))?
.extract::<PyReadonlyArray2<Complex64>>()?
.as_array()
.to_owned())
})
} else {
Err(QiskitError::new_err(
"Can't compute matrix of non-unitary op",
Expand All @@ -55,7 +57,6 @@ pub fn get_matrix_from_inst(py: Python, inst: &PackedInstruction) -> PyResult<Ar

/// Return the matrix Operator resulting from a block of Instructions.
pub fn blocks_to_matrix(
py: Python,
dag: &DAGCircuit,
op_list: &[NodeIndex],
block_index_map: [Qubit; 2],
Expand All @@ -73,7 +74,7 @@ pub fn blocks_to_matrix(
let mut output_matrix: Option<Array2<Complex64>> = None;
for node in op_list {
let inst = dag[*node].unwrap_operation();
let op_matrix = get_matrix_from_inst(py, inst)?;
let op_matrix = get_matrix_from_inst(inst)?;
match dag
.get_qargs(inst.qubits)
.iter()
Expand Down
2 changes: 1 addition & 1 deletion crates/accelerate/src/high_level_synthesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ fn extract_definition(
"cx".to_string(),
aview2(&CX_GATE),
1.0,
"U",
EulerBasis::U,
None,
)?;
let two_qubit_sequence =
Expand Down
1 change: 1 addition & 0 deletions crates/accelerate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub mod synthesis;
pub mod target_transpiler;
pub mod twirling;
pub mod two_qubit_decompose;
pub mod two_qubit_peephole;
pub mod uc_gate;
pub mod unitary_synthesis;
pub mod vf2_layout;
Expand Down
27 changes: 19 additions & 8 deletions crates/accelerate/src/two_qubit_decompose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1273,9 +1273,9 @@ type TwoQubitSequenceVec = Vec<(Option<StandardGate>, SmallVec<[f64; 3]>, SmallV
#[derive(Clone, Debug)]
#[pyclass(sequence)]
pub struct TwoQubitGateSequence {
gates: TwoQubitSequenceVec,
pub gates: TwoQubitSequenceVec,
#[pyo3(get)]
global_phase: f64,
pub global_phase: f64,
}

impl TwoQubitGateSequence {
Expand Down Expand Up @@ -1383,6 +1383,12 @@ impl TwoQubitBasisDecomposer {
__num_basis_gates(self.basis_decomposer.b, self.basis_fidelity, u)
}

/// Is the gate super controlled
#[inline]
pub fn super_controlled(&self) -> bool {
self.super_controlled
}

fn decomp1_inner(
&self,
target: &TwoQubitWeylDecomposition,
Expand Down Expand Up @@ -1743,7 +1749,7 @@ impl TwoQubitBasisDecomposer {
gate: String,
gate_matrix: ArrayView2<Complex64>,
basis_fidelity: f64,
euler_basis: &str,
euler_basis: EulerBasis,
pulse_optimize: Option<bool>,
) -> PyResult<Self> {
let ipz: ArrayView2<Complex64> = aview2(&IPZ);
Expand Down Expand Up @@ -1851,7 +1857,7 @@ impl TwoQubitBasisDecomposer {
Ok(TwoQubitBasisDecomposer {
gate,
basis_fidelity,
euler_basis: EulerBasis::__new__(euler_basis)?,
euler_basis,
pulse_optimize,
basis_decomposer,
super_controlled,
Expand Down Expand Up @@ -2021,7 +2027,7 @@ impl TwoQubitBasisDecomposer {
gate,
gate_matrix.as_array(),
basis_fidelity,
euler_basis,
EulerBasis::__new__(euler_basis)?,
pulse_optimize,
)
}
Expand Down Expand Up @@ -2319,8 +2325,13 @@ fn two_qubit_decompose_up_to_diagonal(
let (su4, phase) = u4_to_su4(mat_arr);
let mut real_map = real_trace_transform(su4.view());
let mapped_su4 = real_map.dot(&su4.view());
let decomp =
TwoQubitBasisDecomposer::new_inner("cx".to_string(), aview2(&CX_GATE), 1.0, "U", None)?;
let decomp = TwoQubitBasisDecomposer::new_inner(
"cx".to_string(),
aview2(&CX_GATE),
1.0,
EulerBasis::__new__("U")?,
None,
)?;

let circ_seq = decomp.call_inner(mapped_su4.view(), None, true, None)?;
let circ = CircuitData::from_standard_gates(
Expand Down Expand Up @@ -2505,7 +2516,7 @@ impl<'py> IntoPyObject<'py> for RXXEquivalent {
#[derive(Clone, Debug)]
#[pyclass(module = "qiskit._accelerate.two_qubit_decompose", subclass)]
pub struct TwoQubitControlledUDecomposer {
rxx_equivalent_gate: RXXEquivalent,
pub rxx_equivalent_gate: RXXEquivalent,
euler_basis: EulerBasis,
#[pyo3(get)]
scale: f64,
Expand Down
Loading
Loading