Skip to content

Commit a9b8f4a

Browse files
ElePTmtreinishraynelfss
authored
Oxidize UnitarySynthesis pass (#13141)
* Inital attempt at oxidizing unitary synthesis. * Add cacache pygates feature to accelerate * Use sabre target to speed up preferred_direction * Adapt code to changes in PackedInstruction * Use target in preferred_direction * Some cleanup * More cleanup * Apply inline suggestions from Matt's code review Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Apply remaining review suggestions: * Fix details after applying inline suggestions * Keep TwoQubitWeilDecomposition attributes private. Add getter. * Initialize new_blocks using size hint * Remove basis_set as it's not used if there is a target. * Use ref_qubits ([PhysicalQubit; 2]) instead of wire_map (IndexMap<Qubit, Physicalqubit>) * Define static GOODBYE_SET as suggested * Use ImportOnceCell for XXDecomposer and XXEmbodiments to avoid importing in a loop. * Set preferred_direction without making it mutable. * Fix check_goodbye * Privatize assets * Use the add_global_phase method instead of the private function. * Add qs_decomposition to imports * Simplify flip_bits * Use NormalOperation to pass around decomposer gate and params info * First attempt at attaching synth circuits directly * Second attempt at attaching synth circuits directly * Use edge set for coupling map * Avoid exposing internals from NullableIndexMap * Use unitary_to_gate_sequence_inner instead of optimize_1q_gates_decomposition. * Use concat! in long error message. * Use dag.apply_operation_back in 1q case. Additional cleanup. * Don't return ref to float in two qubit decomposer. * Use PyList as input type for coupling_edges (previous approach was innefficient) * Avoid using UnitarySynthesisReturn type, avoid intermediate dag creation in all cases except XXDecomposer. * Refactor appending to out_dag, remove unnecesary clones. * Cosmetic changes. Reduce indentation. * Squash bug * Fix clippy * Add qsd test * Avoid making unnecessary variables public * Use OperationRef instead of exposing discriminant * Rename DAGCircuit::substitue_node to py_substitute_node Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Restore name in Python world * Rewrite using flatten Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Apply suggestions from Ray's code review Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Adjust suggestions from code review. Apply remaining feedback: * Use circuit_to_dag from crates/circuit/converters.rs * Simplify iteration over coupling edges * Replace cumbersome call_method_bound with call_bound * Apply ownership suggestion from Ray Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Finish applying ownership suggestion from Ray * Changes to synth_error function: remove error that wasn't handled, deal with new panic calling operation_from_name * Undo flatten * Fix style * Add getters and setters for TwoQubitGateSequence, expose new, keep struct attributes private. * Apply Ray's suggestion to use unwrap_operation Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Use ExtraInstructionAttributes::default() * Apply suggestion to avoid intermediate collection * Use target::contains_key * Apply suggestion to use iter() instead of keys() Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Final touches * Final touches * Replace panics with unreachable * Format * Apply suggestions from Matt's code review Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Fix suggestions from Matt's code review * Apply remaining suggestions * Apply final suggestions from code review * Lint: Use `unwrap_or_default()`. --------- Co-authored-by: Matthew Treinish <mtreinish@kortar.org> Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
1 parent 68a1eca commit a9b8f4a

File tree

10 files changed

+1176
-12
lines changed

10 files changed

+1176
-12
lines changed

crates/accelerate/src/euler_one_qubit_decomposer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ pub fn generate_circuit(
581581

582582
const EULER_BASIS_SIZE: usize = 12;
583583

584-
static EULER_BASES: [&[&str]; EULER_BASIS_SIZE] = [
584+
pub static EULER_BASES: [&[&str]; EULER_BASIS_SIZE] = [
585585
&["u3"],
586586
&["u3", "u2", "u1"],
587587
&["u"],
@@ -595,7 +595,7 @@ static EULER_BASES: [&[&str]; EULER_BASIS_SIZE] = [
595595
&["rz", "sx", "x"],
596596
&["rz", "sx"],
597597
];
598-
static EULER_BASIS_NAMES: [EulerBasis; EULER_BASIS_SIZE] = [
598+
pub static EULER_BASIS_NAMES: [EulerBasis; EULER_BASIS_SIZE] = [
599599
EulerBasis::U3,
600600
EulerBasis::U321,
601601
EulerBasis::U,

crates/accelerate/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub mod synthesis;
4848
pub mod target_transpiler;
4949
pub mod two_qubit_decompose;
5050
pub mod uc_gate;
51+
pub mod unitary_synthesis;
5152
pub mod utils;
5253
pub mod vf2_layout;
5354

crates/accelerate/src/two_qubit_decompose.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,15 @@ pub struct TwoQubitWeylDecomposition {
510510
}
511511

512512
impl TwoQubitWeylDecomposition {
513+
pub fn a(&self) -> f64 {
514+
self.a
515+
}
516+
pub fn b(&self) -> f64 {
517+
self.b
518+
}
519+
pub fn c(&self) -> f64 {
520+
self.c
521+
}
513522
fn weyl_gate(
514523
&self,
515524
simplify: bool,
@@ -1231,17 +1240,39 @@ impl TwoQubitWeylDecomposition {
12311240

12321241
type TwoQubitSequenceVec = Vec<(Option<StandardGate>, SmallVec<[f64; 3]>, SmallVec<[u8; 2]>)>;
12331242

1243+
#[derive(Clone, Debug)]
12341244
#[pyclass(sequence)]
12351245
pub struct TwoQubitGateSequence {
12361246
gates: TwoQubitSequenceVec,
12371247
#[pyo3(get)]
12381248
global_phase: f64,
12391249
}
12401250

1251+
impl TwoQubitGateSequence {
1252+
pub fn gates(&self) -> &TwoQubitSequenceVec {
1253+
&self.gates
1254+
}
1255+
1256+
pub fn global_phase(&self) -> f64 {
1257+
self.global_phase
1258+
}
1259+
1260+
pub fn set_state(&mut self, state: (TwoQubitSequenceVec, f64)) {
1261+
self.gates = state.0;
1262+
self.global_phase = state.1;
1263+
}
1264+
}
1265+
1266+
impl Default for TwoQubitGateSequence {
1267+
fn default() -> Self {
1268+
Self::new()
1269+
}
1270+
}
1271+
12411272
#[pymethods]
12421273
impl TwoQubitGateSequence {
12431274
#[new]
1244-
fn new() -> Self {
1275+
pub fn new() -> Self {
12451276
TwoQubitGateSequence {
12461277
gates: Vec::new(),
12471278
global_phase: 0.,
@@ -1273,6 +1304,8 @@ impl TwoQubitGateSequence {
12731304
}
12741305
}
12751306
}
1307+
1308+
#[derive(Clone, Debug)]
12761309
#[allow(non_snake_case)]
12771310
#[pyclass(module = "qiskit._accelerate.two_qubit_decompose", subclass)]
12781311
pub struct TwoQubitBasisDecomposer {
@@ -1660,7 +1693,7 @@ impl TwoQubitBasisDecomposer {
16601693
Ok(res)
16611694
}
16621695

1663-
fn new_inner(
1696+
pub fn new_inner(
16641697
gate: String,
16651698
gate_matrix: ArrayView2<Complex64>,
16661699
basis_fidelity: f64,
@@ -1798,7 +1831,7 @@ impl TwoQubitBasisDecomposer {
17981831
})
17991832
}
18001833

1801-
fn call_inner(
1834+
pub fn call_inner(
18021835
&self,
18031836
unitary: ArrayView2<Complex64>,
18041837
basis_fidelity: Option<f64>,

0 commit comments

Comments
 (0)