Skip to content

Commit

Permalink
Add rust-native apply_operation methods (#13143)
Browse files Browse the repository at this point in the history
* Initial: Add rust-native `apply_operation_front` and `apply_operation_back methods.
- These methods allow rust users to add an operation to either the front or the back of the circuit without needing to have valid interned indices for the Qargs/Qargs of said operations.
- Leverage the new methods in the existing python variants of them.

* Fix: Remove extra blank space

* Fix: Revert changes to python `apply_op` methods.
- To avoid an ownership issue, usage of the new methods from the Python variants has been removed.
- As requested, the insertion check in the rust `apply_op` has been removed.

* Fix: Adapt to new `ExtraInstructionProperties` infrastructure.

* Format: Change redundant iteration statement for params
  • Loading branch information
raynelfss authored Sep 17, 2024
1 parent 8783641 commit c68e803
Showing 1 changed file with 110 additions and 1 deletion.
111 changes: 110 additions & 1 deletion crates/circuit/src/dag_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use std::hash::{Hash, Hasher};

use ahash::RandomState;
use smallvec::SmallVec;

use crate::bit_data::BitData;
use crate::circuit_data::CircuitData;
Expand All @@ -26,7 +27,7 @@ use crate::error::DAGCircuitError;
use crate::imports;
use crate::interner::{Interned, Interner};
use crate::operations::{Operation, OperationRef, Param, PyInstruction, StandardGate};
use crate::packed_instruction::PackedInstruction;
use crate::packed_instruction::{PackedInstruction, PackedOperation};
use crate::rustworkx_core_vnext::isomorphism;
use crate::{BitType, Clbit, Qubit, TupleLikeArg};

Expand Down Expand Up @@ -5192,6 +5193,114 @@ impl DAGCircuit {
Ok(new_node)
}

/// Apply a [PackedOperation] to the back of the circuit.
pub fn apply_operation_back(
&mut self,
py: Python,
op: PackedOperation,
qargs: &[Qubit],
cargs: &[Clbit],
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: ExtraInstructionAttributes,
#[cfg(feature = "cache_pygates")] py_op: Option<PyObject>,
) -> PyResult<NodeIndex> {
self.inner_apply_op(
py,
op,
qargs,
cargs,
params,
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
false,
)
}

/// Apply a [PackedOperation] to the front of the circuit.
pub fn apply_operation_front(
&mut self,
py: Python,
op: PackedOperation,
qargs: &[Qubit],
cargs: &[Clbit],
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: ExtraInstructionAttributes,
#[cfg(feature = "cache_pygates")] py_op: Option<PyObject>,
) -> PyResult<NodeIndex> {
self.inner_apply_op(
py,
op,
qargs,
cargs,
params,
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
true,
)
}

#[inline]
#[allow(clippy::too_many_arguments)]
fn inner_apply_op(
&mut self,
py: Python,
op: PackedOperation,
qargs: &[Qubit],
cargs: &[Clbit],
params: Option<SmallVec<[Param; 3]>>,
extra_attrs: ExtraInstructionAttributes,
#[cfg(feature = "cache_pygates")] py_op: Option<PyObject>,
front: bool,
) -> PyResult<NodeIndex> {
// Check that all qargs are within an acceptable range
qargs.iter().try_for_each(|qarg| {
if qarg.0 as usize >= self.num_qubits() {
return Err(PyValueError::new_err(format!(
"Qubit index {} is out of range. This DAGCircuit currently has only {} qubits.",
qarg.0,
self.num_qubits()
)));
}
Ok(())
})?;

// Check that all cargs are within an acceptable range
cargs.iter().try_for_each(|carg| {
if carg.0 as usize >= self.num_clbits() {
return Err(PyValueError::new_err(format!(
"Clbit index {} is out of range. This DAGCircuit currently has only {} clbits.",
carg.0,
self.num_clbits()
)));
}
Ok(())
})?;

#[cfg(feature = "cache_pygates")]
let py_op = if let Some(py_op) = py_op {
py_op.into()
} else {
OnceCell::new()
};
let packed_instruction = PackedInstruction {
op,
qubits: self.qargs_interner.insert(qargs),
clbits: self.cargs_interner.insert(cargs),
params: params.map(Box::new),
extra_attrs,
#[cfg(feature = "cache_pygates")]
py_op,
};

if front {
self.push_front(py, packed_instruction)
} else {
self.push_back(py, packed_instruction)
}
}

fn sort_key(&self, node: NodeIndex) -> SortKeyType {
match &self.dag[node] {
NodeType::Operation(packed) => (
Expand Down

0 comments on commit c68e803

Please sign in to comment.