Skip to content

Commit

Permalink
Add PhysicalQubit::from_bit and From<Qubit> impls.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinhartman committed Nov 11, 2024
1 parent 1a02579 commit 4909d59
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 17 deletions.
2 changes: 1 addition & 1 deletion crates/accelerate/src/euler_one_qubit_decomposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ pub(crate) fn optimize_1q_gates_decomposition(
None => raw_run.len() as f64,
};
let qubit: PhysicalQubit = if let NodeType::Operation(inst) = &dag.dag()[raw_run[0]] {
PhysicalQubit::new(dag.get_qargs(inst.qubits)[0].index().try_into().unwrap())
PhysicalQubit::from_bit(dag.get_qargs(inst.qubits)[0])
} else {
unreachable!("nodes in runs will always be op nodes")
};
Expand Down
11 changes: 2 additions & 9 deletions crates/accelerate/src/gate_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

use crate::nlayout::PhysicalQubit;
use crate::target_transpiler::exceptions::TranspilerError;
use crate::target_transpiler::Target;
use hashbrown::HashSet;
Expand Down Expand Up @@ -75,10 +74,7 @@ fn py_check_direction_coupling_map(
#[pyo3(name = "check_gate_direction_target")]
fn py_check_direction_target(py: Python, dag: &DAGCircuit, target: &Target) -> PyResult<bool> {
let target_check = |inst: &PackedInstruction, op_args: &[Qubit]| -> bool {
let qargs = smallvec![
PhysicalQubit::new(op_args[0].index().try_into().unwrap()),
PhysicalQubit::new(op_args[1].index().try_into().unwrap())
];
let qargs = smallvec![op_args[0].into(), op_args[1].into()];

target.instruction_supported(inst.op.name(), Some(&qargs))
};
Expand Down Expand Up @@ -205,10 +201,7 @@ fn py_fix_direction_target(
target: &Target,
) -> PyResult<DAGCircuit> {
let target_check = |inst: &PackedInstruction, op_args: &[Qubit]| -> bool {
let qargs = smallvec![
PhysicalQubit::new(op_args[0].index() as u32),
PhysicalQubit::new(op_args[1].index() as u32)
];
let qargs = smallvec![op_args[0].into(), op_args[1].into()];

// Take this path so Target can check for exact match of the parameterized gate's angle
if let OperationRef::Standard(std_gate) = inst.op.view() {
Expand Down
4 changes: 3 additions & 1 deletion crates/accelerate/src/gates_in_basis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ fn any_gate_missing_from_target(dag: &DAGCircuit, target: &Target) -> PyResult<b

// In the outer DAG, virtual and physical bits are the same thing.
let wire_map: HashMap<Qubit, PhysicalQubit> = HashMap::from_iter(
(0..dag.num_qubits()).map(|i| (Qubit::new(i), PhysicalQubit::new(i.try_into().unwrap()))),
(0..dag.num_qubits())
.map(Qubit::new)
.map(|q| (q, PhysicalQubit::from_bit(q))),
);

// Process the DAG.
Expand Down
14 changes: 14 additions & 0 deletions crates/accelerate/src/nlayout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use pyo3::types::PyList;

use hashbrown::HashMap;

use qiskit_circuit::Qubit;

/// A newtype for the different categories of qubits used within layouts. This is to enforce
/// significantly more type safety when dealing with mixtures of physical and virtual qubits, as we
/// typically are when dealing with layouts. In Rust space, `NLayout` only works in terms of the
Expand All @@ -32,11 +34,23 @@ macro_rules! qubit_newtype {
Self(val)
}
#[inline]
pub fn from_bit(val: Qubit) -> Self {
// TODO: move physical and virtual bit types to the circuit crate
// This will always work since Qubit is never bigger than a u32.
Self(val.index() as u32)
}
#[inline]
pub fn index(&self) -> usize {
self.0 as usize
}
}

impl From<Qubit> for $id {
fn from(value: Qubit) -> Self {
Self::from_bit(value)
}
}

impl pyo3::IntoPy<PyObject> for $id {
fn into_py(self, py: Python<'_>) -> PyObject {
self.0.into_py(py)
Expand Down
6 changes: 4 additions & 2 deletions crates/accelerate/src/remove_identity_equiv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ fn remove_identity_equiv(
let qargs: Vec<PhysicalQubit> = dag
.get_qargs(inst.qubits)
.iter()
.map(|x| PhysicalQubit::new(x.index() as u32))
.cloned()
.map(PhysicalQubit::from_bit)
.collect();
let error_rate = target.get_error(inst.op.name(), qargs.as_slice());
match error_rate {
Expand All @@ -61,7 +62,8 @@ fn remove_identity_equiv(
let qargs: Vec<PhysicalQubit> = dag
.get_qargs(inst.qubits)
.iter()
.map(|x| PhysicalQubit::new(x.index() as u32))
.cloned()
.map(PhysicalQubit::from_bit)
.collect();
let error_rate = target.get_error(inst.op.name(), qargs.as_slice());
match error_rate {
Expand Down
5 changes: 1 addition & 4 deletions crates/accelerate/src/unitary_synthesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,7 @@ fn py_run_main_loop(
// Run 1q synthesis
[2, 2] => {
let qubit = dag.get_qargs(packed_instr.qubits)[0];
let target_basis_set = get_target_basis_set(
target,
PhysicalQubit::new(qubit.index().try_into().unwrap()),
);
let target_basis_set = get_target_basis_set(target, PhysicalQubit::from_bit(qubit));
let sequence = unitary_to_gate_sequence_inner(
unitary.view(),
&target_basis_set,
Expand Down

0 comments on commit 4909d59

Please sign in to comment.