diff --git a/pytket/conanfile.py b/pytket/conanfile.py index d070bc36fa..e75f704d46 100644 --- a/pytket/conanfile.py +++ b/pytket/conanfile.py @@ -32,7 +32,7 @@ def package(self): cmake.install() def requirements(self): - self.requires("tket/1.2.66@tket/stable") + self.requires("tket/1.2.67@tket/stable") self.requires("tklog/0.3.3@tket/stable") self.requires("tkrng/0.3.3@tket/stable") self.requires("tkassert/0.3.4@tket/stable") diff --git a/pytket/docs/changelog.rst b/pytket/docs/changelog.rst index 97187302c3..71cba0ff00 100644 --- a/pytket/docs/changelog.rst +++ b/pytket/docs/changelog.rst @@ -16,6 +16,7 @@ Fixes: of the bits in the expression in the resulting ``cmd.args`` * Fix incorrect serialisation of ``PauliExpPairBox`` when the Pauli strings are of length 2. +* Fix incorrect controlled ``ConjugationBox`` handling. 1.21.0 (October 2023) --------------------- diff --git a/tket/conanfile.py b/tket/conanfile.py index fd7918b995..7cf1e667ab 100644 --- a/tket/conanfile.py +++ b/tket/conanfile.py @@ -23,7 +23,7 @@ class TketConan(ConanFile): name = "tket" - version = "1.2.66" + version = "1.2.67" package_type = "library" license = "Apache 2" homepage = "https://github.com/CQCL/tket" diff --git a/tket/src/Circuit/CircUtils.cpp b/tket/src/Circuit/CircUtils.cpp index 17b0deb998..379882104b 100644 --- a/tket/src/Circuit/CircUtils.cpp +++ b/tket/src/Circuit/CircUtils.cpp @@ -596,7 +596,10 @@ static Circuit controlled_conjugation_box( all_args[n_controls + i] = Qubit(n_controls + args[i].index()[0]); target_args[i] = Qubit(n_controls + args[i].index()[0]); } - Circuit circ(n_controls + n_targets); + Circuit circ; + for (const Qubit &q : all_args) { + circ.add_qubit(q); + } circ.add_op(compute, target_args); QControlBox controlled_action(action, n_controls); circ.add_box(controlled_action, all_args); @@ -801,6 +804,9 @@ static Eigen::Matrix2cd get_target_op_matrix(const Op_ptr &op) { // A gate block containing Cn* gates that can be merged as a single CnU gate // a block can also contain a single Barrier, which will be left in place +// TODO: conjugation boxs are accepted as well; however they don't fit the +// semantics. control_qubits and target_qubit don't mean anything for a +// conjugation box. struct CnGateBlock { enum class MergeMode { append, prepend }; CnGateBlock(const Command &command) { diff --git a/tket/test/src/Circuit/test_Boxes.cpp b/tket/test/src/Circuit/test_Boxes.cpp index e2c8afd1ac..c6fee206d2 100644 --- a/tket/test/src/Circuit/test_Boxes.cpp +++ b/tket/test/src/Circuit/test_Boxes.cpp @@ -873,6 +873,18 @@ SCENARIO("QControlBox", "[boxes]") { d.add_op(OpType::CX, {2, 1}); REQUIRE(*c == d); } + WHEN("Wrapped in a CircBox") { + Circuit inner_circ(4); + inner_circ.add_op(cj_op, {1, 3}); + Op_ptr circbox_op = std::make_shared(inner_circ); + QControlBox qbox(circbox_op); + std::shared_ptr c = qbox.to_circuit(); + Circuit d(5); + d.add_op(OpType::CX, {4, 2}); + d.add_op(OpType::CZ, {0, 2}); + d.add_op(OpType::CX, {4, 2}); + REQUIRE(*c == d); + } WHEN("Nested") { Circuit compute_outer(3); compute_outer.add_op(OpType::CX, {2, 1}); @@ -929,6 +941,20 @@ SCENARIO("QControlBox", "[boxes]") { std::shared_ptr c = qbox.to_circuit(); REQUIRE(c->count_gates(OpType::CX) == 4); } + GIVEN("controlled PauliExpBox") { + // https://github.com/CQCL/tket/issues/1109 + PauliExpBox pbox( + SymPauliTensor({Pauli::I, Pauli::Z, Pauli::I, Pauli::I}, 0.7)); + Op_ptr op = std::make_shared(pbox); + QControlBox qbox(op); + std::shared_ptr c = qbox.to_circuit(); + // construct the expected circuit + Circuit correct_inner(4); + correct_inner.add_op(OpType::Rz, 0.7, {1}); + QControlBox correct_qbox(std::make_shared(correct_inner)); + std::shared_ptr d = correct_qbox.to_circuit(); + REQUIRE(*c == *d); + } } SCENARIO("Unitary3qBox", "[boxes]") {