From 3395993d41e1eeb251742ec1659c284dd6df324c Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:38:24 +0000 Subject: [PATCH] Implement dagger() and transpose() for CustomGate (#1671) --- pytket/conanfile.py | 2 +- pytket/docs/changelog.rst | 1 + pytket/tests/circuit_test.py | 12 ++++++++++++ tket/conanfile.py | 2 +- tket/include/tket/Circuit/Boxes.hpp | 4 ++++ tket/src/Circuit/Boxes.cpp | 16 ++++++++++++++++ tket/src/OpType/OpTypeFunctions.cpp | 7 +++---- 7 files changed, 38 insertions(+), 6 deletions(-) diff --git a/pytket/conanfile.py b/pytket/conanfile.py index 623627832f..3df72b2788 100644 --- a/pytket/conanfile.py +++ b/pytket/conanfile.py @@ -38,7 +38,7 @@ def requirements(self): self.requires("pybind11_json/0.2.14") self.requires("symengine/0.12.0") self.requires("tkassert/0.3.4@tket/stable") - self.requires("tket/1.3.43@tket/stable") + self.requires("tket/1.3.44@tket/stable") self.requires("tklog/0.3.3@tket/stable") self.requires("tkrng/0.3.3@tket/stable") self.requires("tktokenswap/0.3.9@tket/stable") diff --git a/pytket/docs/changelog.rst b/pytket/docs/changelog.rst index aea2310369..04a6373000 100644 --- a/pytket/docs/changelog.rst +++ b/pytket/docs/changelog.rst @@ -16,6 +16,7 @@ Features: * Add `only_reduce` argument to `GreedyPauliSimp`. * Add option to not relabel `ClassicalExpBox` when calling `rename_units` and `flatten_registers` +* Implement `dagger()` and `transpose()` for `CustomGate`. Fixes: diff --git a/pytket/tests/circuit_test.py b/pytket/tests/circuit_test.py index 4903e5b387..861e043640 100644 --- a/pytket/tests/circuit_test.py +++ b/pytket/tests/circuit_test.py @@ -783,11 +783,23 @@ def test_custom_gates() -> None: op0 = cmd0.op assert gate.type == op0.type assert gate.params == op0.params + c_d = c.dagger() + c_t = c.transpose() Transform.DecomposeBoxes().apply(c) coms = c.get_commands() assert str(coms[0]) == "CX q[0], q[3];" assert str(coms[1]) == "Rz(0.7) q[1];" assert str(coms[2]) == "CRz(1.3) q[0], q[1];" + Transform.DecomposeBoxes().apply(c_d) + coms_d = c_d.get_commands() + assert str(coms_d[0]) == "CRz(2.7) q[0], q[1];" + assert str(coms_d[1]) == "CX q[0], q[3];" + assert str(coms_d[2]) == "Rz(3.3) q[1];" + Transform.DecomposeBoxes().apply(c_t) + coms_t = c_t.get_commands() + assert str(coms_t[0]) == "CRz(1.3) q[0], q[1];" + assert str(coms_t[1]) == "CX q[0], q[3];" + assert str(coms_t[2]) == "Rz(0.7) q[1];" def test_errors() -> None: diff --git a/tket/conanfile.py b/tket/conanfile.py index 7d7d74a9fd..dc0b961750 100644 --- a/tket/conanfile.py +++ b/tket/conanfile.py @@ -23,7 +23,7 @@ class TketConan(ConanFile): name = "tket" - version = "1.3.43" + version = "1.3.44" package_type = "library" license = "Apache 2" homepage = "https://github.com/CQCL/tket" diff --git a/tket/include/tket/Circuit/Boxes.hpp b/tket/include/tket/Circuit/Boxes.hpp index af2d6a859a..68a4b874b8 100644 --- a/tket/include/tket/Circuit/Boxes.hpp +++ b/tket/include/tket/Circuit/Boxes.hpp @@ -494,6 +494,10 @@ class CustomGate : public Box { bool is_clifford() const override; + Op_ptr dagger() const override; + + Op_ptr transpose() const override; + protected: void generate_circuit() const override; CustomGate() : Box(OpType::CustomGate), gate_(), params_() {} diff --git a/tket/src/Circuit/Boxes.cpp b/tket/src/Circuit/Boxes.cpp index 40d00fb6b8..4679fc79c7 100644 --- a/tket/src/Circuit/Boxes.cpp +++ b/tket/src/Circuit/Boxes.cpp @@ -372,6 +372,22 @@ bool CustomGate::is_clifford() const { return true; } +Op_ptr CustomGate::dagger() const { + Circuit inner_c_dag = gate_->get_def()->dagger(); + composite_def_ptr_t dag_def_ptr = std::make_shared( + gate_->get_name() + "_dagger", gate_->get_def()->dagger(), + gate_->get_args()); + return std::make_shared(dag_def_ptr, params_); +} + +Op_ptr CustomGate::transpose() const { + Circuit inner_c_dag = gate_->get_def()->transpose(); + composite_def_ptr_t dag_def_ptr = std::make_shared( + gate_->get_name() + "_transpose", gate_->get_def()->transpose(), + gate_->get_args()); + return std::make_shared(dag_def_ptr, params_); +} + QControlBox::QControlBox( const Op_ptr &op, unsigned n_controls, const std::vector &control_state) diff --git a/tket/src/OpType/OpTypeFunctions.cpp b/tket/src/OpType/OpTypeFunctions.cpp index 0c2a0c98a6..1b6cdadf44 100644 --- a/tket/src/OpType/OpTypeFunctions.cpp +++ b/tket/src/OpType/OpTypeFunctions.cpp @@ -254,10 +254,9 @@ bool is_oneway_type(OpType optype) { // or we do not yet have the dagger gate as an OpType. // If the gate can have an dagger, define it in the dagger() method. static const OpTypeSet no_defined_inverse = { - OpType::Input, OpType::Output, OpType::Measure, - OpType::ClInput, OpType::ClOutput, OpType::Barrier, - OpType::Reset, OpType::Collapse, OpType::CustomGate, - OpType::PhasePolyBox, OpType::Create, OpType::Discard}; + OpType::Input, OpType::Output, OpType::Measure, OpType::ClInput, + OpType::ClOutput, OpType::Barrier, OpType::Reset, OpType::Collapse, + OpType::PhasePolyBox, OpType::Create, OpType::Discard}; return find_in_set(optype, no_defined_inverse); }