Skip to content

Commit

Permalink
Set num_qubits kwarg when building UnitaryGate from Rust
Browse files Browse the repository at this point in the history
In the accelerate crate we currently have two places that are building
`UnitaryGate`, the quantum_volume() function that builds a quantum
volume model circuit and the Split2QUnitaries transpiler pass. Currently
this can only be done by calling Python (until Qiskit#13272 is implemented)
and there was a potential optimization we could make to specify the
number of qubits as an argument to the Python constructor. This skipss
the need for a few python operations to compute the number of qubits
from the size of the matrix. These operations are not exceedingly slow,
but as these Python space constructors are often the bottleneck so it
should help runtime performance of these two functions.
  • Loading branch information
mtreinish committed Oct 4, 2024
1 parent 492005e commit 7558c0e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
7 changes: 6 additions & 1 deletion crates/accelerate/src/circuit_library/quantum_volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

use pyo3::intern;
use pyo3::prelude::*;
use pyo3::types::PyDict;

use crate::getenv_use_multiple_threads;
use faer_ext::{IntoFaerComplex, IntoNdarrayComplex};
Expand Down Expand Up @@ -110,6 +112,8 @@ pub fn quantum_volume(
let num_unitaries = width * depth;
let mut permutation: Vec<Qubit> = (0..num_qubits).map(Qubit).collect();

let kwargs = PyDict::new_bound(py);
kwargs.set_item(intern!(py, "num_qubits"), 2)?;
let mut build_instruction = |(unitary_index, unitary_array): (usize, Array2<Complex64>),
rng: &mut Pcg64Mcg|
-> PyResult<Instruction> {
Expand All @@ -118,9 +122,10 @@ pub fn quantum_volume(
permutation.shuffle(rng);
}
let unitary = unitary_array.into_pyarray_bound(py);

let unitary_gate = UNITARY_GATE
.get_bound(py)
.call1((unitary.clone(), py.None(), false))?;
.call((unitary.clone(), py.None(), false), Some(&kwargs))?;
let instruction = PyInstruction {
qubits: 2,
clbits: 0,
Expand Down
9 changes: 7 additions & 2 deletions crates/accelerate/src/split_2q_unitaries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

use pyo3::intern;
use pyo3::prelude::*;
use pyo3::types::PyDict;
use rustworkx_core::petgraph::stable_graph::NodeIndex;

use qiskit_circuit::circuit_instruction::OperationFromPython;
Expand All @@ -27,6 +29,7 @@ pub fn split_2q_unitaries(
requested_fidelity: f64,
) -> PyResult<()> {
let nodes: Vec<NodeIndex> = dag.op_nodes(false).collect();

for node in nodes {
if let NodeType::Operation(inst) = &dag.dag()[node] {
let qubits = dag.get_qargs(inst.qubits).to_vec();
Expand All @@ -45,12 +48,14 @@ pub fn split_2q_unitaries(
if matches!(decomp.specialization, Specialization::IdEquiv) {
let k1r_arr = decomp.K1r(py);
let k1l_arr = decomp.K1l(py);
let kwargs = PyDict::new_bound(py);
kwargs.set_item(intern!(py, "num_qubits"), 1)?;
let k1r_gate = UNITARY_GATE
.get_bound(py)
.call1((k1r_arr, py.None(), false))?;
.call((k1r_arr, py.None(), false), Some(&kwargs))?;
let k1l_gate = UNITARY_GATE
.get_bound(py)
.call1((k1l_arr, py.None(), false))?;
.call((k1l_arr, py.None(), false), Some(&kwargs))?;
let insert_fn = |edge: &Wire| -> PyResult<OperationFromPython> {
if let Wire::Qubit(qubit) = edge {
if *qubit == qubits[0] {
Expand Down

0 comments on commit 7558c0e

Please sign in to comment.