diff --git a/pytket/conanfile.py b/pytket/conanfile.py index 123ac8339a..86c6f590b0 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.13.0") self.requires("tkassert/0.3.4@tket/stable") - self.requires("tket/1.3.48@tket/stable") + self.requires("tket/1.3.49@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/tket/conanfile.py b/tket/conanfile.py index fa46ab76f8..01a68205a5 100644 --- a/tket/conanfile.py +++ b/tket/conanfile.py @@ -23,7 +23,7 @@ class TketConan(ConanFile): name = "tket" - version = "1.3.48" + version = "1.3.49" package_type = "library" license = "Apache 2" homepage = "https://github.com/CQCL/tket" diff --git a/tket/src/Converters/ZXConverters.cpp b/tket/src/Converters/ZXConverters.cpp index 2b07da47ae..b8e3e88527 100644 --- a/tket/src/Converters/ZXConverters.cpp +++ b/tket/src/Converters/ZXConverters.cpp @@ -585,7 +585,8 @@ std::pair circuit_to_zx(const Circuit& circ) { void clean_frontier( ZXDiagram& diag, ZXVertVec& frontier, Circuit& circ, - std::map& qubit_map) { + std::map& qubit_map, + std::map& input_qubits) { std::set frontier_lookup; std::list> czs; for (const ZXVert& f : frontier) { @@ -655,6 +656,8 @@ void clean_frontier( (nt0 == ZXType::Output && nt1 == ZXType::Input)) { diag.add_wire(ns.at(0), ns.at(1)); diag.remove_vertex(f); + auto input_found = input_qubits.find(f); + if (input_found != input_qubits.end()) input_qubits.erase(f); removed = true; } } @@ -852,10 +855,10 @@ Circuit zx_to_circuit(const ZXDiagram& d) { for (const ZXVert& i : ins) input_qubits.insert({diag.neighbours(i).at(0), i}); - clean_frontier(diag, frontier, circ, qubit_map); + clean_frontier(diag, frontier, circ, qubit_map, input_qubits); while (!frontier.empty()) { if (remove_all_gadgets(diag, frontier, input_qubits)) { - clean_frontier(diag, frontier, circ, qubit_map); + clean_frontier(diag, frontier, circ, qubit_map, input_qubits); } ZXVertSeqSet neighbours = neighbours_of_frontier(diag, frontier); boost::bimap correctors, preserve, ys; @@ -922,7 +925,7 @@ Circuit zx_to_circuit(const ZXDiagram& d) { } } - clean_frontier(diag, frontier, circ, qubit_map); + clean_frontier(diag, frontier, circ, qubit_map, input_qubits); } qubit_map_t qm; diff --git a/tket/test/src/ZX/test_ZXSimp.cpp b/tket/test/src/ZX/test_ZXSimp.cpp index cd006273b3..61dba660cc 100644 --- a/tket/test/src/ZX/test_ZXSimp.cpp +++ b/tket/test/src/ZX/test_ZXSimp.cpp @@ -15,6 +15,7 @@ #include #include "tket/Converters/Converters.hpp" +#include "tket/Predicates/PassLibrary.hpp" #include "tket/Transformations/Rebase.hpp" #include "tket/ZX/Rewrite.hpp" @@ -180,6 +181,53 @@ SCENARIO("Testing cases for internalising gadgets in MBQC") { } } +SCENARIO("Testing for vertex reuse bug") { + /** + * The following circuits were shown to hit errors non-deterministically, with + * the error likelihood varying with the device. + * + * At some point during extraction, a vertex would be removed from the graph, + * but some pointers to it lingered. Later, if an input extension occurred, + * new vertices would be added which may (depending on how boost was feeling + * with memory) reuse the same memory locations, so the old pointers now + * worked, meaning lookups in sets/functions would give false positives. + */ + GIVEN("Offender 1") { + Circuit circ(3); + circ.add_op(OpType::H, {1}); + circ.add_op(OpType::H, {2}); + circ.add_op(OpType::CX, {2, 1}); + circ.add_op(OpType::Rz, 1.1, {1}); + circ.add_op(OpType::H, {0}); + circ.add_op(OpType::CX, {2, 1}); + circ.add_op(OpType::H, {1}); + circ.add_op(OpType::H, {2}); + circ.add_op(OpType::Rz, 0.970644, {1}); + circ.add_op(OpType::Rz, 0.9, {2}); + circ.add_op(OpType::H, {1}); + circ.add_op(OpType::H, {2}); + + CompilationUnit cu(circ); + ZXGraphlikeOptimisation()->apply(cu); + } + GIVEN("Offender 2") { + Circuit circ(6); + circ.add_op(OpType::Rx, -0.78, {3}); + circ.add_op(OpType::Rx, 1.069, {5}); + circ.add_op(OpType::CX, {0, 3}); + circ.add_op(OpType::CX, {3, 5}); + circ.add_op(OpType::CX, {0, 5}); + circ.add_op(OpType::Rx, 1.069, {3}); + circ.add_op(OpType::Rx, -5.958, {4}); + circ.add_op(OpType::CX, {3, 4}); + circ.add_op(OpType::CX, {3, 5}); + circ.add_op(OpType::CX, {0, 3}); + + CompilationUnit cu(circ); + ZXGraphlikeOptimisation()->apply(cu); + } +} + } // namespace test_ZXSimp } // namespace zx } // namespace tket