Skip to main content

CoordCircuit

Struct CoordCircuit 

Source
pub struct CoordCircuit { /* private fields */ }
Expand description

A quantum circuit whose qubits are addressed by 2-D lattice coordinates rather than dense integer indices.

Operations live in CircuitBody blocks (the entry body plus any bodies referenced by Op::Repeat), stored flat and referenced by BodyId. Measurement records are allocated through an internal MeasRegistry, so every measurement has a stable id independent of qubit index. A coordinate-to-index layout for the Stim FFI boundary is derived on demand via Self::build_coord_to_index.

Implementations§

Source§

impl CoordCircuit

Source

pub fn new() -> CoordCircuit

Creates an empty circuit with one entry body.

Source

pub fn qubits(&self) -> HashSet<IVec2, FxBuildHasher>

The set of every qubit coordinate touched by any body or measurement record.

Source

pub const fn entry_body(&self) -> BodyId

The id of the top-level body operations are appended to.

Source

pub fn set_entry_body(&mut self, body: BodyId) -> Result<(), CircuitError>

Select an allocated body as the entry without renumbering body ids.

§Errors

Returns CircuitError::InvalidCircuitBody if body is not allocated.

Source

pub fn entry_top_level_repeats(&self) -> Vec<u32>

The repetition counts of the top-level Op::Repeats in the entry body, in order. Used to classify memory-padding templates: a one-round template has none, a looped template has exactly one.

Source

pub fn body_count(&self) -> usize

The number of circuit bodies, including repeat bodies.

Source

pub fn body(&self, id: BodyId) -> Option<&CircuitBody>

Borrows the body with the given id, or None if it is not allocated.

Source

pub fn body_mut(&mut self, id: BodyId) -> Option<&mut CircuitBody>

Mutably borrows the body with the given id, or None if it is not allocated.

Source

pub fn meas_registry(&self) -> &MeasRegistry

Borrows the measurement registry backing this circuit’s ids.

Source

pub fn reserve_measurement_id(&mut self, qubit: IVec2) -> u32

Allocates and returns a fresh measurement id for qubit.

Source

pub fn remap_measurement_ids( &mut self, remap: &HashMap<u32, u32, FxBuildHasher>, )

Rewrites every measurement id through remap, in both the registry and every op that references a measurement. Ids absent from remap are left unchanged.

Source

pub fn add_body(&mut self, body: CircuitBody) -> BodyId

Appends body and returns its newly assigned BodyId.

§Panics

Panics if the body-id space is exhausted.

Source

pub fn build_coord_to_index(&self) -> HashMap<IVec2, u32, FxBuildHasher>

Build a deterministic coord-to-index layout for the Stim FFI boundary. Indices are assigned by sorting coordinates by (x, y).

§Panics

Panics if the qubit-index space is exhausted.

Source

pub fn num_qubits(&self) -> u32

The number of distinct qubit coordinates in the circuit.

§Panics

Panics if the qubit count exceeds u32::MAX.

Source

pub fn num_measurements(&self) -> u32

The number of allocated measurement records.

Source

pub fn tick(&mut self)

Appends a Op::Tick moment barrier to the entry body.

Source

pub fn push_repeat(&mut self, body: BodyId, repetitions: u32)

Appends a Op::Repeat of body to the entry body.

Source

pub fn do_gate( &mut self, gate: GateType, targets: impl IntoIterator<Item = IVec2>, ) -> Result<(), CircuitError>

Appends a gate acting on targets to the entry body.

Empty targets is a no-op. Two-qubit gates consume targets pairwise.

§Errors

Returns CircuitError::InvalidGateTargetCount if a two-qubit gate is given an odd number of targets.

Source

pub fn measure( &mut self, basis: PauliBasis, targets: impl IntoIterator<Item = IVec2>, ) -> Vec<u32>

Appends a noiseless single-qubit measurement of each target in basis, returning one freshly allocated measurement id per target (in target order). crate::NoiseModel::noisy_circuit can add measurement noise.

Empty targets is a no-op returning an empty vector; duplicate targets each receive a distinct id.

Source

pub fn measure_pauli_products( &mut self, products: impl IntoIterator<Item = PauliMap>, ) -> Result<Vec<u32>, CircuitError>

Append a multi-Pauli-product measurement (Op::MPP): each product is measured jointly and produces one record, keyed by the product’s representative coordinate (see PauliMap::representative_coord) so records stay consistent across cloning. Empty products are rejected.

§Errors

Returns CircuitError::EmptyPauliProduct without modifying the circuit if any product is empty.

Source

pub fn expanded_measurement_columns( &self, ) -> Result<ExpandedMeasurementColumns, CircuitError>

The output column each measurement id lands in once every Op::Repeat is unrolled, together with the total number of records the unrolled circuit emits.

Backends address measurement records by position, but this circuit names them by id and hides repetition behind Repeat, so the two spaces only line up after unrolling. Self::flatten also unrolls, but it rewrites the circuit and mints fresh ids to do so; a caller that only wants “which record does this id land in” pays neither cost here.

A measurement inside a loop occurs once per iteration; the column reported is its last occurrence, matching the latest-occurrence rule both Self::flatten and the Stim emission frame use, so an id read from outside a loop resolves to the same record everywhere.

§Errors

Returns CircuitError::InvalidCircuitBody on a dangling or self-recursive body reference, and MeasurementFrameError::EmittedMeasurementCountOverflow when the unrolled circuit would emit more than u32::MAX records, or MeasurementFrameError::MeasurementCountOutOfRange if one operation already contains more than u32::MAX records.

§Examples
let qubit = ivec2(0, 0);
let mut circuit = CoordCircuit::new();
let looped = circuit.reserve_measurement_id(qubit);
let body = circuit.add_body(CircuitBody::from_ops(vec![Op::Measure {
    basis: PauliBasis::Z,
    qubits: vec![qubit],
    measurements: vec![looped],
    flip_probability: 0.0,
}]));
circuit.push_repeat(body, 3);

let columns = circuit.expanded_measurement_columns()?;
assert_eq!(columns.count(), 3);
assert_eq!(columns.column(looped), Some(2), "the last of three occurrences");
Source

pub fn has_repeats(&self) -> bool

Whether any body contains an Op::Repeat.

Source

pub fn flatten(&mut self) -> Result<Vec<FlattenEvent>, CircuitError>

Unroll every Op::Repeat into a single straight-line entry body, returning the replay trace side-table owners need to translate loop-relative annotations (see FlattenEvent).

Measurement-id semantics mirror the emission frame’s latest-occurrence rule: every unrolled occurrence of a measurement gets a fresh id except the last, which keeps the original id, so references from outside the loop (which always meant “the latest occurrence”) stay valid without any remap. ConditionalPauli measurement controls are rewritten to the occurrence emitted most recently before them. Zero-repetition repeats are dropped.

A circuit without repeats is returned untouched with an empty trace.

§Errors

CircuitError::InvalidCircuitBody on a dangling or self-recursive body reference, CircuitError::FlattenMeasurementIdOverflow when the unrolled circuit would need more than u32::MAX measurement ids, or CircuitError::FlattenResourceLimit when expansion exceeds the default FlattenLimits.

Source

pub fn flatten_with_limits( &mut self, limits: FlattenLimits, ) -> Result<Vec<FlattenEvent>, CircuitError>

Self::flatten with an explicit allowance for expanded work.

The shared body DAG is counted before the circuit is changed. Rejected expansions leave both operations and measurement identities untouched.

§Errors

Returns the same body, id-space, and resource errors as Self::flatten.

Source

pub fn check_flatten_limits( &self, limits: FlattenLimits, ) -> Result<usize, CircuitError>

Check expansion without changing the circuit and return its work cost. A caller flattening several circuits can charge the returned cost to one shared allowance before materializing any of them.

§Errors

Returns the same body, id-space, and resource errors as Self::flatten.

Source

pub fn has_moments_conflict(&self) -> bool

Checks if there are any operations that act on the same qubit within the same moment. A repeat does not imply a tick, including between its iterations.

Trait Implementations§

Source§

impl Clone for CoordCircuit

Source§

fn clone(&self) -> CoordCircuit

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CoordCircuit

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for CoordCircuit

Source§

fn default() -> CoordCircuit

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for CoordCircuit

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<CoordCircuit, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for CoordCircuit

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for CoordCircuit

Source§

fn eq(&self, other: &CoordCircuit) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for CoordCircuit

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for CoordCircuit

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T, BorrowedSelf> BitwiseMutViaBorrow<BorrowedSelf> for T
where T: BorrowMut<BorrowedSelf>, BorrowedSelf: BitwiseMut + ?Sized,

§

fn assign_index(&mut self, index: usize, to: bool)

§

fn negate_index(&mut self, index: usize)

§

fn clear_bits(&mut self)

§

fn assign_random( &mut self, bit_count: usize, random_number_generator: &mut impl RngExt, )
where BorrowedSelf: BitLength,

§

impl<Bits, Other, BorrowedSelf, BorrowedOther> BitwisePairMutViaBorrow<Other, BorrowedSelf, BorrowedOther> for Bits
where Bits: BorrowMut<BorrowedSelf> + ?Sized, Other: Borrow<BorrowedOther> + ?Sized, BorrowedSelf: Bitwise + BitwisePairMut<BorrowedOther> + ?Sized, BorrowedOther: Bitwise + ?Sized,

§

fn assign(&mut self, other: &Other)

§

fn bitxor_assign(&mut self, other: &Other)

§

fn bitand_assign(&mut self, other: &Other)

§

fn bitor_assign(&mut self, other: &Other)

§

impl<T, Other, BorrowedSelf, BorrowedOther> BitwisePairViaBorrow<Other, BorrowedSelf, BorrowedOther> for T
where T: Borrow<BorrowedSelf> + ?Sized, Other: Borrow<BorrowedOther> + ?Sized, BorrowedSelf: Bitwise + BitwisePair<BorrowedOther> + ?Sized, BorrowedOther: Bitwise + ?Sized,

§

fn dot(&self, other: &Other) -> bool

§

fn and_weight(&self, other: &Other) -> usize

§

fn or_weight(&self, other: &Other) -> usize

§

fn xor_weight(&self, other: &Other) -> usize

§

impl<T, BorrowedSelf> BitwiseViaBorrow<BorrowedSelf> for T
where T: Borrow<BorrowedSelf>, BorrowedSelf: Bitwise + ?Sized,

§

fn index(&self, index: usize) -> bool

§

fn weight(&self) -> usize

§

fn parity(&self) -> bool

§

fn is_zero(&self) -> bool

§

fn is_unit(&self, index: usize) -> bool

§

fn support<'a>(&'a self) -> impl SortedIterator
where BorrowedSelf: 'a,

§

fn max_support(&self) -> Option<usize>

§

fn min_support(&self) -> Option<usize>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.