Skip to content

Commit 355689e

Browse files
authored
Add reset broadcast (#2404)
Implements broadcast for resetting qubits. Any qubit registers are passed to `ResetAll` so that we don't have to generate many reset calls in the AST.
1 parent 95933e1 commit 355689e

File tree

5 files changed

+226
-4
lines changed

5 files changed

+226
-4
lines changed

compiler/qsc_qasm/src/ast_builder.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,14 @@ pub(crate) fn build_reset_call(expr: ast::Expr, name_span: Span, operand_span: S
753753
build_global_call_with_one_param("Reset", expr, name_span, operand_span)
754754
}
755755

756+
pub(crate) fn build_reset_all_call(
757+
expr: ast::Expr,
758+
name_span: Span,
759+
operand_span: Span,
760+
) -> ast::Expr {
761+
build_global_call_with_one_param("ResetAll", expr, name_span, operand_span)
762+
}
763+
756764
pub(crate) fn build_global_call_with_one_param<S: AsRef<str>>(
757765
name: S,
758766
expr: ast::Expr,

compiler/qsc_qasm/src/compiler.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use crate::{
2929
build_math_call_no_params, build_measure_call, build_operation_with_stmts,
3030
build_path_ident_expr, build_path_ident_ty, build_qasm_import_decl,
3131
build_qasm_import_items, build_qasmstd_convert_call_with_two_params, build_range_expr,
32-
build_reset_call, build_return_expr, build_return_unit, build_stmt_semi_from_expr,
33-
build_stmt_semi_from_expr_with_span, build_ternary_update_expr,
32+
build_reset_all_call, build_reset_call, build_return_expr, build_return_unit,
33+
build_stmt_semi_from_expr, build_stmt_semi_from_expr_with_span, build_ternary_update_expr,
3434
build_top_level_ns_with_items, build_tuple_expr, build_unary_op_expr,
3535
build_unmanaged_qubit_alloc, build_unmanaged_qubit_alloc_array, build_while_stmt,
3636
build_wrapped_block_expr, managed_qubit_alloc_array, map_qsharp_type_to_ast_ty,
@@ -1037,9 +1037,15 @@ impl QasmCompiler {
10371037
}
10381038

10391039
fn compile_reset_stmt(&mut self, stmt: &semast::ResetStmt) -> Option<qsast::Stmt> {
1040+
let is_register = matches!(stmt.operand.kind, crate::semantic::ast::GateOperandKind::Expr(ref expr) if matches!(expr.ty, Type::QubitArray(..)));
1041+
10401042
let operand = self.compile_gate_operand(&stmt.operand);
10411043
let operand_span = operand.span;
1042-
let expr = build_reset_call(operand, stmt.reset_token_span, operand_span);
1044+
let expr = if is_register {
1045+
build_reset_all_call(operand, stmt.reset_token_span, operand_span)
1046+
} else {
1047+
build_reset_call(operand, stmt.reset_token_span, operand_span)
1048+
};
10431049
Some(build_stmt_semi_from_expr(expr))
10441050
}
10451051

compiler/qsc_qasm/src/semantic/tests/statements.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ mod break_stmt;
66
mod continue_stmt;
77
mod for_stmt;
88
mod if_stmt;
9+
mod reset_stmt;
910
mod switch_stmt;
1011
mod while_stmt;
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::semantic::tests::check_stmt_kinds;
5+
use expect_test::expect;
6+
7+
#[test]
8+
fn on_a_single_qubit() {
9+
check_stmt_kinds(
10+
"qubit q;
11+
reset q;",
12+
&expect![[r#"
13+
QubitDeclaration [0-8]:
14+
symbol_id: 8
15+
ResetStmt [17-25]:
16+
reset_token_span: [17-22]
17+
operand: GateOperand [23-24]:
18+
kind: Expr [23-24]:
19+
ty: Qubit
20+
kind: SymbolId(8)
21+
"#]],
22+
);
23+
}
24+
25+
#[test]
26+
fn on_an_indexed_qubit_register() {
27+
check_stmt_kinds(
28+
"qubit[5] q;
29+
reset q[2];",
30+
&expect![[r#"
31+
QubitArrayDeclaration [0-11]:
32+
symbol_id: 8
33+
size: 5
34+
size_span: [6-7]
35+
ResetStmt [20-31]:
36+
reset_token_span: [20-25]
37+
operand: GateOperand [26-30]:
38+
kind: Expr [26-30]:
39+
ty: Qubit
40+
kind: IndexedIdent [26-30]:
41+
symbol_id: 8
42+
name_span: [26-27]
43+
index_span: [27-30]
44+
indices:
45+
Expr [28-29]:
46+
ty: Int(None, true)
47+
kind: Lit: Int(2)
48+
"#]],
49+
);
50+
}
51+
52+
#[test]
53+
fn on_a_span_indexed_qubit_register() {
54+
check_stmt_kinds(
55+
"qubit[5] q;
56+
reset q[1:3];",
57+
&expect![[r#"
58+
QubitArrayDeclaration [0-11]:
59+
symbol_id: 8
60+
size: 5
61+
size_span: [6-7]
62+
ResetStmt [20-33]:
63+
reset_token_span: [20-25]
64+
operand: GateOperand [26-32]:
65+
kind: Expr [26-32]:
66+
ty: QubitArray(3)
67+
kind: IndexedIdent [26-32]:
68+
symbol_id: 8
69+
name_span: [26-27]
70+
index_span: [27-32]
71+
indices:
72+
Range [28-31]:
73+
start: Expr [28-29]:
74+
ty: Int(None, true)
75+
kind: Lit: Int(1)
76+
step: <none>
77+
end: Expr [30-31]:
78+
ty: Int(None, true)
79+
kind: Lit: Int(3)
80+
"#]],
81+
);
82+
}
83+
84+
#[test]
85+
fn on_a_zero_len_qubit_register() {
86+
check_stmt_kinds(
87+
"qubit[0] q;
88+
reset q;",
89+
&expect![[r#"
90+
QubitArrayDeclaration [0-11]:
91+
symbol_id: 8
92+
size: 0
93+
size_span: [6-7]
94+
ResetStmt [20-28]:
95+
reset_token_span: [20-25]
96+
operand: GateOperand [26-27]:
97+
kind: Expr [26-27]:
98+
ty: QubitArray(0)
99+
kind: SymbolId(8)
100+
"#]],
101+
);
102+
}
103+
104+
#[test]
105+
fn on_an_unindexed_qubit_register() {
106+
check_stmt_kinds(
107+
"qubit[5] q;
108+
reset q;",
109+
&expect![[r#"
110+
QubitArrayDeclaration [0-11]:
111+
symbol_id: 8
112+
size: 5
113+
size_span: [6-7]
114+
ResetStmt [20-28]:
115+
reset_token_span: [20-25]
116+
operand: GateOperand [26-27]:
117+
kind: Expr [26-27]:
118+
ty: QubitArray(5)
119+
kind: SymbolId(8)
120+
"#]],
121+
);
122+
}

compiler/qsc_qasm/src/tests/statement/reset.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
use crate::{
5-
tests::{compile_with_config, fail_on_compilation_errors, gen_qsharp},
5+
tests::{compile_qasm_to_qsharp, compile_with_config, fail_on_compilation_errors, gen_qsharp},
66
CompilerConfig, OutputSemantics, ProgramType, QubitSemantics,
77
};
88
use expect_test::expect;
@@ -160,3 +160,88 @@ fn reset_with_adaptive_ri_profile_generates_reset_qir() -> miette::Result<(), Ve
160160

161161
Ok(())
162162
}
163+
164+
#[test]
165+
fn on_a_single_qubit() -> miette::Result<(), Vec<Report>> {
166+
let source = r#"
167+
qubit q;
168+
reset q;
169+
"#;
170+
171+
let qsharp = compile_qasm_to_qsharp(source)?;
172+
expect![[r#"
173+
import Std.OpenQASM.Intrinsic.*;
174+
let q = QIR.Runtime.__quantum__rt__qubit_allocate();
175+
Reset(q);
176+
"#]]
177+
.assert_eq(&qsharp);
178+
Ok(())
179+
}
180+
181+
#[test]
182+
fn on_an_indexed_qubit_register() -> miette::Result<(), Vec<Report>> {
183+
let source = r#"
184+
qubit[5] q;
185+
reset q[2];
186+
"#;
187+
188+
let qsharp = compile_qasm_to_qsharp(source)?;
189+
expect![[r#"
190+
import Std.OpenQASM.Intrinsic.*;
191+
let q = QIR.Runtime.AllocateQubitArray(5);
192+
Reset(q[2]);
193+
"#]]
194+
.assert_eq(&qsharp);
195+
Ok(())
196+
}
197+
198+
#[test]
199+
fn on_a_span_indexed_qubit_register() -> miette::Result<(), Vec<Report>> {
200+
let source = r#"
201+
qubit[5] q;
202+
reset q[1:3];
203+
"#;
204+
205+
let qsharp = compile_qasm_to_qsharp(source)?;
206+
expect![[r#"
207+
import Std.OpenQASM.Intrinsic.*;
208+
let q = QIR.Runtime.AllocateQubitArray(5);
209+
ResetAll(q[1..3]);
210+
"#]]
211+
.assert_eq(&qsharp);
212+
Ok(())
213+
}
214+
215+
#[test]
216+
fn on_a_zero_len_qubit_register() -> miette::Result<(), Vec<Report>> {
217+
let source = r#"
218+
qubit[0] q;
219+
reset q;
220+
"#;
221+
222+
let qsharp = compile_qasm_to_qsharp(source)?;
223+
expect![[r#"
224+
import Std.OpenQASM.Intrinsic.*;
225+
let q = QIR.Runtime.AllocateQubitArray(0);
226+
ResetAll(q);
227+
"#]]
228+
.assert_eq(&qsharp);
229+
Ok(())
230+
}
231+
232+
#[test]
233+
fn on_an_unindexed_qubit_register() -> miette::Result<(), Vec<Report>> {
234+
let source = r#"
235+
qubit[5] q;
236+
reset q;
237+
"#;
238+
239+
let qsharp = compile_qasm_to_qsharp(source)?;
240+
expect![[r#"
241+
import Std.OpenQASM.Intrinsic.*;
242+
let q = QIR.Runtime.AllocateQubitArray(5);
243+
ResetAll(q);
244+
"#]]
245+
.assert_eq(&qsharp);
246+
Ok(())
247+
}

0 commit comments

Comments
 (0)