diff --git a/pytket/conanfile.py b/pytket/conanfile.py index 80e7e0b31c..3cc45a02ff 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.35@tket/stable") + self.requires("tket/1.3.36@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 143d5592c8..a092356c1d 100644 --- a/pytket/docs/changelog.rst +++ b/pytket/docs/changelog.rst @@ -1,6 +1,13 @@ Changelog ========= +Unreleased +---------- + +Fixes: + +* Fix `symbol_substitution` not preserving opgroups. + 1.34.0 (October 2024) --------------------- diff --git a/tket/conanfile.py b/tket/conanfile.py index 6439e45b7a..a131da11e2 100644 --- a/tket/conanfile.py +++ b/tket/conanfile.py @@ -23,7 +23,7 @@ class TketConan(ConanFile): name = "tket" - version = "1.3.35" + version = "1.3.36" package_type = "library" license = "Apache 2" homepage = "https://github.com/CQCL/tket" diff --git a/tket/src/Circuit/Circuit.cpp b/tket/src/Circuit/Circuit.cpp index e85292b2b6..115880b746 100644 --- a/tket/src/Circuit/Circuit.cpp +++ b/tket/src/Circuit/Circuit.cpp @@ -177,7 +177,7 @@ void Circuit::symbol_substitution(const SymEngine::map_basic_basic sub_map) { BGL_FORALL_VERTICES(v, dag, DAG) { Op_ptr new_op = get_Op_ptr_from_Vertex(v)->symbol_substitution(sub_map); if (new_op) { - dag[v] = {new_op}; + dag[v] = {new_op, dag[v].opgroup}; } } phase = phase.subs(sub_map); diff --git a/tket/test/src/Circuit/test_Circ.cpp b/tket/test/src/Circuit/test_Circ.cpp index 0575e382c7..e868668bd9 100644 --- a/tket/test/src/Circuit/test_Circ.cpp +++ b/tket/test/src/Circuit/test_Circ.cpp @@ -22,6 +22,7 @@ #include "../testutil.hpp" #include "tket/Circuit/Circuit.hpp" #include "tket/Circuit/DAGDefs.hpp" +#include "tket/Circuit/PauliExpBoxes.hpp" #include "tket/Circuit/Simulation/CircuitSimulator.hpp" #include "tket/Gate/GatePtr.hpp" #include "tket/Gate/OpPtrFunctions.hpp" @@ -1292,6 +1293,36 @@ SCENARIO("Functions with symbolic ops") { REQUIRE(test_equiv_val(op2->get_params()[0], 0.2)); REQUIRE(op3->get_type() == OpType::Barrier); } + GIVEN("A circuit with symbolic gates and boxes that belong to opgroups.") { + Sym asym = SymEngine::symbol("a"); + Expr alpha(asym); + Sym bsym = SymEngine::symbol("b"); + Expr beta(bsym); + Circuit circ(2); + circ.add_op(OpType::Rx, alpha, {0}, "Rx"); + Circuit inner_circ(2); + inner_circ.add_op(OpType::Rx, {alpha}, {0}); + inner_circ.add_op(OpType::Ry, {beta}, {0}); + auto cbox = CircBox(inner_circ); + circ.add_box(cbox, {0, 1}, "cbox"); + DensePauliMap paulis0{Pauli::X, Pauli::X}; + DensePauliMap paulis1{Pauli::Z, Pauli::X}; + auto ppbox = PauliExpPairBox( + SymPauliTensor(paulis0, alpha), SymPauliTensor(paulis1, beta)); + circ.add_box(ppbox, {0, 1}, "ppbox"); + symbol_map_t symbol_map; + symbol_map[asym] = Expr(0.2); + symbol_map[bsym] = Expr(0.3); + circ.symbol_substitution(symbol_map); + REQUIRE(!circ.is_symbolic()); + std::unordered_set opgroups({"Rx", "cbox", "ppbox"}); + REQUIRE(circ.get_opgroups() == opgroups); + std::vector cmds = circ.get_commands(); + REQUIRE(cmds.size() == 3); + REQUIRE(cmds[0].get_opgroup().value() == "Rx"); + REQUIRE(cmds[1].get_opgroup().value() == "cbox"); + REQUIRE(cmds[2].get_opgroup().value() == "ppbox"); + } } SCENARIO("Test depth_by_type method") {