Skip to content

Commit

Permalink
Fix bug preventing display of circuits where same qubit measured more…
Browse files Browse the repository at this point in the history
… than once

The logic for returning the count of measurements incorrectly reported every qubit as being measured only once no matter how many times it was measured. This was breaking circuit display for non-base profile programs.
  • Loading branch information
swernli committed Sep 26, 2024
1 parent 6c3ab39 commit 40b658f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 22 deletions.
30 changes: 30 additions & 0 deletions compiler/qsc/src/interpret/circuit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,36 @@ fn one_gate() {
.assert_eq(&circ.to_string());
}

#[test]
fn measure_same_qubit_twice() {
let mut interpreter = interpreter(
r"
namespace Test {
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
H(q);
let r1 = M(q);
let r2 = M(q);
[r1, r2]
}
}
",
Profile::Unrestricted,
);

let circ = interpreter
.circuit(CircuitEntryPoint::EntryPoint, false)
.expect("circuit generation should succeed");

expect![[r#"
q_0 ── H ──── M ──── M ──
╘══════╪═══
╘═══
"#]]
.assert_eq(&circ.to_string());
}

#[test]
fn toffoli() {
let mut interpreter = interpreter(
Expand Down
25 changes: 3 additions & 22 deletions compiler/qsc_circuit/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ impl Backend for Builder {
let mapped_q = self.map(q);
// In the Circuit schema, result id is per-qubit
let res_id = self.num_measurements_for_qubit(mapped_q);
// We don't actually need the Remapper since we're not
// remapping any qubits, but it's handy for keeping track of measurements
let id = self.remapper.m(q);

self.push_gate(measurement_gate(mapped_q.0, res_id));
Expand Down Expand Up @@ -249,21 +247,6 @@ impl Builder {
self.circuit.operations.push(gate);
}

fn num_measurements_by_qubit(&self) -> IndexMap<usize, usize> {
self.remapper.qubit_measurement_counts.iter().fold(
IndexMap::default(),
|mut map: IndexMap<usize, usize>, (q, _)| {
match map.get_mut(q.0) {
Some(rs) => *rs += 1,
None => {
map.insert(q.0, 1);
}
}
map
},
)
}

fn num_measurements_for_qubit(&self, qubit: WireId) -> usize {
self.remapper
.qubit_measurement_counts
Expand All @@ -273,19 +256,17 @@ impl Builder {
}

fn finish_circuit(&self, mut circuit: Circuit) -> Circuit {
let by_qubit = self.num_measurements_by_qubit();

// add deferred measurements
if self.config.base_profile {
for (qubit, _) in &by_qubit {
for (qubit, _) in &self.remapper.qubit_measurement_counts {
// guaranteed one measurement per qubit, so result is always 0
circuit.operations.push(measurement_gate(qubit, 0));
circuit.operations.push(measurement_gate(qubit.0, 0));
}
}

// add qubit declarations
for i in 0..self.remapper.num_qubits() {
let num_measurements = by_qubit.get(i).map_or(0, |c| *c);
let num_measurements = self.num_measurements_for_qubit(WireId(i));
circuit.qubits.push(crate::circuit::Qubit {
id: i,
num_children: num_measurements,
Expand Down

0 comments on commit 40b658f

Please sign in to comment.