diff --git a/src/execute.cc b/src/execute.cc index 73464d1cb..d5ef8af73 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -150,7 +150,7 @@ bool AUTOQ::Automata::execute(const char *filename, std::vector qub if (it == kRegexEnd) THROW_AUTOQ_ERROR("Expected measure assignment (var = measure ...[n]) in \"" + line + "\"."); std::string result = it->str(1); - int pos = 1 + atoi(it->str(2).c_str()); + int pos = 1 + qubit_permutation[atoi(it->str(2).c_str())]; // the automaton level of the qubit, as for gates var_is_measure_what_qubit[result] = pos; // TODO: Actually, we should split the automaton here into two separate copies which // are produced from the measurement outcome of 0 and 1, respectively. However, we do diff --git a/unit_tests/explicit_tree_aut_test.cc b/unit_tests/explicit_tree_aut_test.cc index 50124d9d0..2af06d837 100644 --- a/unit_tests/explicit_tree_aut_test.cc +++ b/unit_tests/explicit_tree_aut_test.cc @@ -324,6 +324,28 @@ BOOST_AUTO_TEST_CASE(for_loop_summarization_complex_amplitudes){ } } +// `r = measure q[k];` must guard on the same automaton level that gates use for +// q[k], also when the .hsl files reorder the qubits (#26). +BOOST_AUTO_TEST_CASE(measurement_guard_uses_qubit_permutation){ + std::string folder = test_dir_from_file(__FILE__, "testcase/MeasurePermutation/"); + // {|sts>} and {|s0s>} put the two `s` qubits next to each other, so q[1] and q[2] swap levels. + const std::vector> cases = { + {"if_reset.qasm", true}, + {"if_wrong_qubit.qasm", false}, + {"while_reset.qasm", true}, + }; + for (const auto& [circuit, expected] : cases) { + auto [autVec, qp] = AUTOQ::Parsing::TimbukParser::ReadTwoAutomata(folder + "pre.hsl", folder + "post.hsl", folder + circuit); + BOOST_REQUIRE_MESSAGE((qp == std::vector{0, 2, 1}), circuit + ": the qubits are not reordered"); + auto aut = autVec.at(0); + auto spec = autVec.at(1); + autVec.erase(autVec.begin(), autVec.begin() + 2); + bool verify = aut.execute(folder + circuit, qp, autVec); + verify &= (aut <<= spec); + BOOST_CHECK_MESSAGE(verify == expected, circuit + ": expected " + (expected ? "[OK]" : "[failed]")); + } +} + static void grover_oracle(AUTOQ::ConcreteAutomata& aut, unsigned ans, int n) { for (int i=1; i<=n; i++) { diff --git a/unit_tests/testcase/MeasurePermutation/if_reset.qasm b/unit_tests/testcase/MeasurePermutation/if_reset.qasm new file mode 100644 index 000000000..5f7132706 --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/if_reset.qasm @@ -0,0 +1,8 @@ +OPENQASM 3; +include "stdgates.inc"; +qubit[3] q; +bit r; +r = measure q[1]; +if (r) { + x q[1]; +} diff --git a/unit_tests/testcase/MeasurePermutation/if_wrong_qubit.qasm b/unit_tests/testcase/MeasurePermutation/if_wrong_qubit.qasm new file mode 100644 index 000000000..39e1bc676 --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/if_wrong_qubit.qasm @@ -0,0 +1,8 @@ +OPENQASM 3; +include "stdgates.inc"; +qubit[3] q; +bit r; +r = measure q[2]; +if (r) { + x q[1]; +} diff --git a/unit_tests/testcase/MeasurePermutation/inv.hsl b/unit_tests/testcase/MeasurePermutation/inv.hsl new file mode 100644 index 000000000..236ad7770 --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/inv.hsl @@ -0,0 +1,2 @@ +Extended Dirac +{|sts> : |s|=1, |t|=1} diff --git a/unit_tests/testcase/MeasurePermutation/post.hsl b/unit_tests/testcase/MeasurePermutation/post.hsl new file mode 100644 index 000000000..556f46cde --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/post.hsl @@ -0,0 +1,2 @@ +Extended Dirac +{|s0s> : |s|=1} diff --git a/unit_tests/testcase/MeasurePermutation/pre.hsl b/unit_tests/testcase/MeasurePermutation/pre.hsl new file mode 100644 index 000000000..236ad7770 --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/pre.hsl @@ -0,0 +1,2 @@ +Extended Dirac +{|sts> : |s|=1, |t|=1} diff --git a/unit_tests/testcase/MeasurePermutation/while_reset.qasm b/unit_tests/testcase/MeasurePermutation/while_reset.qasm new file mode 100644 index 000000000..08ac01674 --- /dev/null +++ b/unit_tests/testcase/MeasurePermutation/while_reset.qasm @@ -0,0 +1,9 @@ +OPENQASM 3; +include "stdgates.inc"; +qubit[3] q; +bit r; +r = measure q[1]; +while (r) { // inv.hsl + x q[1]; + r = measure q[1]; +}