Skip to content

Commit

Permalink
Fix bug in Unselect operation when selecting a single bit string (#2181)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
msoeken authored Feb 13, 2025
1 parent 4192f29 commit 9cc3285
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 17 deletions.
9 changes: 9 additions & 0 deletions library/src/tests/table_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ use qsc::interpret::Value;

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

#[test]
fn check_select_exhaustive_bitwidth_0() {
test_expression_with_lib(
"Test.TestSelect(0, 10)",
SELECT_TEST_LIB,
&Value::Tuple(vec![].into()),
);
}

#[test]
fn check_select_exhaustive_bitwidth_1() {
test_expression_with_lib(
Expand Down
39 changes: 22 additions & 17 deletions library/std/src/Std/TableLookup.qs
Original file line number Diff line number Diff line change
Expand Up @@ -175,29 +175,34 @@ operation Unlookup(
select : Qubit[],
target : Qubit[]
) : Unit {
let numBits = Length(target);
let numAddressBits = Length(select);
// No measurement-based uncomputation when there is only one address
if Length(data) == 1 {
WriteMemoryContents(Head(data), target);
} else {
let numBits = Length(target);
let numAddressBits = Length(select);

let l = MinI(Floor(Lg(IntAsDouble(numBits))), numAddressBits - 1);
Fact(
l < numAddressBits,
$"l = {l} must be smaller than {numAddressBits}"
);
let l = MinI(Floor(Lg(IntAsDouble(numBits))), numAddressBits - 1);
Fact(
l < numAddressBits,
$"l = {l} must be smaller than {numAddressBits}"
);

let res = Mapped(r -> r == One, ForEach(MResetX, target));
let res = Mapped(r -> r == One, ForEach(MResetX, target));

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

let numAddressBitsFixup = numAddressBits - l;
let numAddressBitsFixup = numAddressBits - l;

let selectParts = Partitioned([l], select);
let targetFixup = target[...2^l - 1];
let selectParts = Partitioned([l], select);
let targetFixup = target[...2^l - 1];

within {
EncodeUnary(selectParts[0], targetFixup);
ApplyToEachA(H, targetFixup);
} apply {
lookup(dataFixup, selectParts[1], targetFixup);
within {
EncodeUnary(selectParts[0], targetFixup);
ApplyToEachA(H, targetFixup);
} apply {
lookup(dataFixup, selectParts[1], targetFixup);
}
}
}

Expand Down

0 comments on commit 9cc3285

Please sign in to comment.