Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow CircuitData construction from PackedOperations #12943

Merged
merged 3 commits into from
Aug 12, 2024
Merged
Changes from 2 commits
Commits
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
67 changes: 66 additions & 1 deletion crates/circuit/src/circuit_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::circuit_instruction::{CircuitInstruction, OperationFromPython};
use crate::imports::{ANNOTATED_OPERATION, CLBIT, QUANTUM_CIRCUIT, QUBIT};
use crate::interner::{IndexedInterner, Interner, InternerKey};
use crate::operations::{Operation, OperationRef, Param, StandardGate};
use crate::packed_instruction::PackedInstruction;
use crate::packed_instruction::{PackedInstruction, PackedOperation};
use crate::parameter_table::{ParameterTable, ParameterTableError, ParameterUse, ParameterUuid};
use crate::slice::{PySequenceIndex, SequenceIndex};
use crate::{Clbit, Qubit};
Expand Down Expand Up @@ -104,6 +104,71 @@ pub struct CircuitData {
}

impl CircuitData {
/// An alternate constructor to build a new `CircuitData` from an iterator
/// of packed operations. This can be used to build a circuit from a sequence
/// of `PackedOperation` without needing to involve Python.
///
/// This can be connected with the Python space
/// QuantumCircuit.from_circuit_data() constructor to build a full
/// QuantumCircuit from Rust.
///
/// # Arguments
///
/// * py: A GIL handle this is needed to instantiate Qubits in Python space
/// * num_qubits: The number of qubits in the circuit. These will be created
/// in Python as loose bits without a register.
/// * num_clbits: The number of classical bits in the circuit. These will be created
/// in Python as loose bits without a register.
/// * instructions: An iterator of the (packed operation, params, qubits, clbits) to
/// add to the circuit
/// * global_phase: The global phase to use for the circuit
Comment on lines +114 to +124
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's less common in Rust land to be this explicit about every individual argument - things like global_phase are pretty self explanatory, and if the comment is just explaining the type, it might not be offering too much.

We don't have any team policy on this yet, so no need to change anything, I'm just comparing to the Rust ecosystem at large.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good point, I followed what existed for from_standard_gates here 🙂

pub fn from_packed_operations<I>(
py: Python,
num_qubits: u32,
num_clbits: u32,
instructions: I,
global_phase: Param,
) -> PyResult<Self>
where
I: IntoIterator<
Item = (
PackedOperation,
SmallVec<[Param; 3]>,
Vec<Qubit>,
Vec<Clbit>,
),
>,
{
let instruction_iter = instructions.into_iter();
let mut res = Self::with_capacity(
py,
num_qubits,
num_clbits,
instruction_iter.size_hint().0,
global_phase,
)?;
for (operation, params, qargs, cargs) in instruction_iter {
let qubits = (&mut res.qargs_interner)
.intern(InternerKey::Value(qargs.to_vec()))?
.index;
let clbits = (&mut res.cargs_interner)
.intern(InternerKey::Value(cargs.to_vec()))?
.index;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the to_vec necessary here? I think qargs and cargs should already be owned, and already be the correct types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, my oversight 👍🏻 Fixed in d632427

let params = (!params.is_empty()).then(|| Box::new(params));
res.data.push(PackedInstruction {
op: operation,
qubits,
clbits,
params,
extra_attrs: None,
#[cfg(feature = "cache_pygates")]
py_op: RefCell::new(None),
});
res.track_instruction_parameters(py, res.data.len() - 1)?;
}
Ok(res)
}

/// An alternate constructor to build a new `CircuitData` from an iterator
/// of standard gates. This can be used to build a circuit from a sequence
/// of standard gates, such as for a `StandardGate` definition or circuit
Expand Down
Loading