Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 4 additions & 8 deletions quon_qec/src/experiment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,11 @@ fn emit_stim_single_block_memory(expanded: &ExpandedWorkload) -> Result<String,
}

// Prepare |0…0⟩ then optional data H for X-init / X-memory (|+⟩^n).
out.push('R');
let mut reset_ids = Vec::with_capacity(block.atoms.len());
for atom in &block.atoms {
out.push_str(&format!(" {}", atom.0));
reset_ids.push(atom.0);
}
out.push_str("\nTICK\n");
stim_emit::emit_reset_tick(&mut out, &reset_ids);

let z_check_indices: Vec<usize> = block
.stabilizers
Expand Down Expand Up @@ -673,11 +673,7 @@ fn emit_stim_lattice_surgery_cx(expanded: &ExpandedWorkload) -> Result<String, E
.collect();
all_atoms.sort_unstable();
all_atoms.dedup();
out.push('R');
for id in &all_atoms {
out.push_str(&format!(" {id}"));
}
out.push_str("\nTICK\n");
stim_emit::emit_reset_tick(&mut out, &all_atoms);

// Round kinds append through [`stim_emit::StimRoundEmitter`]. Byproduct
// handles and deferred measure-logical rounds come back out for observable
Expand Down
25 changes: 25 additions & 0 deletions quon_qec/src/experiment/stim_emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
//! Lattice surgery calls [`StimRoundEmitter::emit`]. Single-block memory calls
//! [`StimRoundEmitter::emit_single_block`] on the same registry. A new round
//! kind is a new impl plus one arm in [`lattice_round_emitter`].
//!
//! Both builders share [`emit_reset_tick`] for the prepare-`R` / `TICK` line.
//! Headers and observable assembly stay in the builders.

use std::collections::HashMap;

Expand All @@ -19,6 +22,18 @@ use crate::workload::LogicalBasis;

use super::{ExperimentError, emit_local_ops, emit_round_body, logical_observable_atoms};

/// Write `R <ids>\nTICK\n` in caller order.
///
/// Single-block memory passes layout order. Lattice surgery passes the sorted
/// unique id list. This function does not reorder.
pub(crate) fn emit_reset_tick(out: &mut String, atom_ids: &[u32]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approve. I would merge this slice.

Both builders call emit_reset_tick for the prepare-R / TICK line. The helper writes ids in caller order and does not sort or dedup. Single-block memory still passes block.atoms in layout order. Lattice surgery still sorts and dedups before the call. An empty list still writes R then TICK, and reset_tick_keeps_caller_order locks [4, 0, 4] so a hidden reorder would fail.

The diff does not touch the checked-in Stim gold, so repetition d=3, surface d=3 Z/X, and lattice-surgery CX stay byte-identical. This function has no unwrap or expect. The PR body and commit say issue 473 stays open; there is no Fixes/Closes/Resolves keyword.

Headers and observable assembly stay in the builders, on the open issue.

out.push('R');
for id in atom_ids {
out.push_str(&format!(" {id}"));
}
out.push_str("\nTICK\n");
}

/// Shared Stim state for one lattice-surgery circuit.
///
/// Round impls append instructions and record byproduct handles. Observable
Expand Down Expand Up @@ -671,4 +686,14 @@ mod tests {
assert!(ctx.measure_logical.is_none());
assert_eq!(ctx.memory_round_i, 0);
}

#[test]
fn reset_tick_keeps_caller_order() {
let mut out = String::new();
emit_reset_tick(&mut out, &[4, 0, 4]);
assert_eq!(out, "R 4 0 4\nTICK\n");
let mut empty = String::new();
emit_reset_tick(&mut empty, &[]);
assert_eq!(empty, "R\nTICK\n");
}
}
Loading