Skip to content

Commit 9cc3285

Browse files
authored
Fix bug in Unselect operation when selecting a single bit string (microsoft#2181)
When selecting a single bit string the number of address bits is 0, and we run into a problem splitting the address register in the optimized Unlookup implementation. This case is now handled without measurement based uncomputation.
1 parent 4192f29 commit 9cc3285

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

library/src/tests/table_lookup.rs

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ use qsc::interpret::Value;
88

99
const SELECT_TEST_LIB: &str = include_str!("resources/src/select.qs");
1010

11+
#[test]
12+
fn check_select_exhaustive_bitwidth_0() {
13+
test_expression_with_lib(
14+
"Test.TestSelect(0, 10)",
15+
SELECT_TEST_LIB,
16+
&Value::Tuple(vec![].into()),
17+
);
18+
}
19+
1120
#[test]
1221
fn check_select_exhaustive_bitwidth_1() {
1322
test_expression_with_lib(

library/std/src/Std/TableLookup.qs

+22-17
Original file line numberDiff line numberDiff line change
@@ -175,29 +175,34 @@ operation Unlookup(
175175
select : Qubit[],
176176
target : Qubit[]
177177
) : Unit {
178-
let numBits = Length(target);
179-
let numAddressBits = Length(select);
178+
// No measurement-based uncomputation when there is only one address
179+
if Length(data) == 1 {
180+
WriteMemoryContents(Head(data), target);
181+
} else {
182+
let numBits = Length(target);
183+
let numAddressBits = Length(select);
180184

181-
let l = MinI(Floor(Lg(IntAsDouble(numBits))), numAddressBits - 1);
182-
Fact(
183-
l < numAddressBits,
184-
$"l = {l} must be smaller than {numAddressBits}"
185-
);
185+
let l = MinI(Floor(Lg(IntAsDouble(numBits))), numAddressBits - 1);
186+
Fact(
187+
l < numAddressBits,
188+
$"l = {l} must be smaller than {numAddressBits}"
189+
);
186190

187-
let res = Mapped(r -> r == One, ForEach(MResetX, target));
191+
let res = Mapped(r -> r == One, ForEach(MResetX, target));
188192

189-
let dataFixup = Chunks(2^l, Padded(-2^numAddressBits, false, Mapped(MustBeFixed(res, _), data)));
193+
let dataFixup = Chunks(2^l, Padded(-2^numAddressBits, false, Mapped(MustBeFixed(res, _), data)));
190194

191-
let numAddressBitsFixup = numAddressBits - l;
195+
let numAddressBitsFixup = numAddressBits - l;
192196

193-
let selectParts = Partitioned([l], select);
194-
let targetFixup = target[...2^l - 1];
197+
let selectParts = Partitioned([l], select);
198+
let targetFixup = target[...2^l - 1];
195199

196-
within {
197-
EncodeUnary(selectParts[0], targetFixup);
198-
ApplyToEachA(H, targetFixup);
199-
} apply {
200-
lookup(dataFixup, selectParts[1], targetFixup);
200+
within {
201+
EncodeUnary(selectParts[0], targetFixup);
202+
ApplyToEachA(H, targetFixup);
203+
} apply {
204+
lookup(dataFixup, selectParts[1], targetFixup);
205+
}
201206
}
202207
}
203208

0 commit comments

Comments
 (0)