Skip to content

Commit 4d196c1

Browse files
minestarksCopilot
andauthored
Circuit diagrams: classical wires should be rendered if grouped operation contains a measurement (#2799)
### BEFORE <img width="849" height="692" alt="image" src="https://github.com/user-attachments/assets/a12ae5f2-f2b9-4252-b7ec-2cb9a94f7fba" /> ### AFTER <img width="843" height="696" alt="image" src="https://github.com/user-attachments/assets/56f07ca4-cf94-479b-9a04-b2a7d0e9f895" /> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent f2824c1 commit 4d196c1

File tree

7 files changed

+3104
-80
lines changed

7 files changed

+3104
-80
lines changed

source/compiler/qsc_circuit/src/builder/tests.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,84 @@ fn qubit_labels_for_preallocated_qubits() {
405405
"#]]
406406
.assert_eq(&circuit.to_string());
407407
}
408+
409+
#[test]
410+
fn measurement_target_propagated_to_group() {
411+
let mut c = FakeCompilation::default();
412+
let mut builder = CircuitTracer::new(
413+
TracerConfig {
414+
max_operations: usize::MAX,
415+
source_locations: false,
416+
group_by_scope: true,
417+
},
418+
&FakeCompilation::user_package_ids(),
419+
);
420+
421+
builder.qubit_allocate(&[], 0);
422+
423+
builder.gate(&[c.user_code_frame("Main", 1)], "H", false, &[0], &[], None);
424+
425+
builder.measure(&[c.user_code_frame("Main", 2)], "M", 0, &0.into());
426+
427+
let circuit = builder.finish(&c);
428+
429+
// Verify that there's a grouped operation, with a measurement operation
430+
// inside it, and that the measurement target register is also propagated
431+
// to the group operation.
432+
433+
// Get the group
434+
435+
let mut group_ops = circuit.component_grid.iter().flat_map(|col| {
436+
col.components.iter().filter_map(|c| {
437+
if let Operation::Unitary(u) = c
438+
&& !u.children.is_empty()
439+
{
440+
Some(u)
441+
} else {
442+
None
443+
}
444+
})
445+
});
446+
447+
let group_op = group_ops
448+
.next()
449+
.expect("expected to find grouped operation");
450+
assert!(
451+
group_ops.next().is_none(),
452+
"expected only one grouped operation"
453+
);
454+
455+
// Get the measurement operation
456+
457+
let mut measurement_ops = group_op.children.iter().filter_map(|col| {
458+
col.components.iter().find_map(|c| {
459+
if let Operation::Measurement(m) = c {
460+
Some(m)
461+
} else {
462+
None
463+
}
464+
})
465+
});
466+
467+
let measurement_op = measurement_ops
468+
.next()
469+
.expect("expected to find measurement operation");
470+
assert!(
471+
measurement_ops.next().is_none(),
472+
"expected only one measurement operation"
473+
);
474+
475+
// Now verify that the measurement qubit and result registers exist in the parent
476+
// group operation's targets as well.
477+
group_op
478+
.targets
479+
.iter()
480+
.find(|reg| *reg == &measurement_op.qubits[0])
481+
.expect("expected measurement qubit in group operation's targets");
482+
483+
group_op
484+
.targets
485+
.iter()
486+
.find(|reg| *reg == &measurement_op.results[0])
487+
.expect("expected measurement result in group operation's targets");
488+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
operation Main() : Unit {
2+
use qs = Qubit[5];
3+
M(qs[0]);
4+
// Crossing a qubit wire
5+
Foo([qs[2], qs[4]]);
6+
// Crossing a classical wire
7+
Foo(qs[0..1]);
8+
// Crossing both qubit and classical wires
9+
Foo([qs[2], qs[0]]);
10+
// Spanning adjacent qubits
11+
Foo(qs[3..4]);
12+
// Crossing classical wire and adjacent qubits
13+
Foo(qs[0..2]);
14+
15+
// Some more classical wires to intersect
16+
M(qs[2]);
17+
M(qs[2]);
18+
19+
// Spanning all qubit wires, one classical wire extending
20+
// from the box, and crossing the other classical wires
21+
BoxWithMeasurements(qs);
22+
23+
use q1 = Qubit();
24+
use q2 = Qubit();
25+
Bar(q1);
26+
Bar(q2);
27+
Foo2(q1);
28+
Bar(q1);
29+
Foo2(q1);
30+
Foo2(q2);
31+
Bar(q2);
32+
Foo2(q2);
33+
}
34+
35+
operation Foo2(q : Qubit) : Unit {
36+
Bar(q);
37+
MResetZ(q);
38+
}
39+
40+
operation Bar(q : Qubit) : Unit {
41+
X(q);
42+
Y(q);
43+
}
44+
45+
operation BoxWithMeasurements(qs: Qubit[]) : Unit {
46+
M(qs[2]);
47+
Foo(qs);
48+
}
49+
50+
operation Foo(qs : Qubit[]) : Unit {
51+
body intrinsic;
52+
}

0 commit comments

Comments
 (0)