From e13ed2634e8ce9e3f72c62fe461b971157be7e43 Mon Sep 17 00:00:00 2001 From: Silas Dilkes <36165522+sjdilkes@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:52:30 +0000 Subject: [PATCH] Timeout on `GPGraph` construction in `GreedyPauliSimp` (#1706) * Timeout on graph construction * Update GreedyPauliConverters.cpp * Update test_GreedyPauli.cpp * bump * Update test_GreedyPauli.cpp * Update test_GreedyPauli.cpp * Update test_GreedyPauli.cpp * Update test_GreedyPauli.cpp * Update test_GreedyPauli.cpp * remove circuit constructor unneeded * Update tket/include/tket/Transformations/GreedyPauliOptimisation.hpp Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> * Update test_GreedyPauli.cpp * Update GreedyPauliOptimisation.hpp --------- Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> --- pytket/conanfile.py | 2 +- pytket/docs/changelog.rst | 4 + tket/conanfile.py | 2 +- .../GreedyPauliOptimisation.hpp | 8 +- .../Transformations/GreedyPauliConverters.cpp | 14 +-- .../GreedyPauliOptimisation.cpp | 11 +- tket/test/src/test_GreedyPauli.cpp | 108 +++++++++--------- 7 files changed, 80 insertions(+), 69 deletions(-) diff --git a/pytket/conanfile.py b/pytket/conanfile.py index c50c6c9909..bc553d5788 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.53@tket/stable") + self.requires("tket/1.3.54@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 ab87fb34a7..3fcc3ac78d 100644 --- a/pytket/docs/changelog.rst +++ b/pytket/docs/changelog.rst @@ -8,6 +8,10 @@ Fixes: * Fix circuit iteration giving invalid slices in some cases. +Performance: + +* Update `GreedyPauliSimp` `thread_timeout` to hit timeout when constructing Pauli Graph. + 1.36.0 (November 2024) ---------------------- diff --git a/tket/conanfile.py b/tket/conanfile.py index 2602d319f1..dcc80f7bb7 100644 --- a/tket/conanfile.py +++ b/tket/conanfile.py @@ -23,7 +23,7 @@ class TketConan(ConanFile): name = "tket" - version = "1.3.53" + version = "1.3.54" package_type = "library" license = "Apache 2" homepage = "https://github.com/CQCL/tket" diff --git a/tket/include/tket/Transformations/GreedyPauliOptimisation.hpp b/tket/include/tket/Transformations/GreedyPauliOptimisation.hpp index 8f53b08bde..513dba640d 100644 --- a/tket/include/tket/Transformations/GreedyPauliOptimisation.hpp +++ b/tket/include/tket/Transformations/GreedyPauliOptimisation.hpp @@ -525,8 +525,8 @@ typedef boost::adj_list_vertex_property_map< */ class GPGraph { public: - /** Construct an GPGraph from a circuit */ - GPGraph(const Circuit& circ); + /** Construct an GPGraph from the qubits and bits */ + GPGraph(qubit_vector_t qubits, bit_vector_t bits); GPVertSet get_successors(const GPVert& vert) const; @@ -544,9 +544,8 @@ class GPGraph { std::tuple< std::vector>, std::vector, boost::bimap> - get_sequence(); + get_sequence(std::shared_ptr> stop_flag); - private: /** * Applies the given gate to the end of the graph. * Clifford gates transform the tableau. @@ -558,6 +557,7 @@ class GPGraph { const Command& cmd, bool conditional = false, std::vector cond_bits = {}, unsigned cond_value = 0); + private: /** * Add a Pauli rotation to the graph * If the angle is non-Clifford or if conditional is true then add to the DAG diff --git a/tket/src/Transformations/GreedyPauliConverters.cpp b/tket/src/Transformations/GreedyPauliConverters.cpp index 86cbdc56db..d3756d6fc3 100644 --- a/tket/src/Transformations/GreedyPauliConverters.cpp +++ b/tket/src/Transformations/GreedyPauliConverters.cpp @@ -111,10 +111,8 @@ static bool nodes_commute(const PauliNode_ptr& n1, const PauliNode_ptr& n2) { return true; } -GPGraph::GPGraph(const Circuit& circ) - : n_qubits_(circ.n_qubits()), n_bits_(circ.n_bits()) { - qubit_vector_t qubits = circ.all_qubits(); - bit_vector_t bits = circ.all_bits(); +GPGraph::GPGraph(qubit_vector_t qubits, bit_vector_t bits) + : n_qubits_(qubits.size()), n_bits_(bits.size()) { for (const Qubit& q : qubits) { TKET_ASSERT(q.reg_name() == q_default_reg()); TKET_ASSERT(q.index().at(0) < qubits.size()); @@ -124,9 +122,6 @@ GPGraph::GPGraph(const Circuit& circ) TKET_ASSERT(b.index().at(0) < bits.size()); } cliff_ = UnitaryRevTableau(n_qubits_); - for (const Command& cmd : circ.get_commands()) { - apply_gate_at_end(cmd); - } } GPVertSet GPGraph::get_successors(const GPVert& vert) const { @@ -487,11 +482,14 @@ std::vector GPGraph::vertices_in_order() const { std::tuple< std::vector>, std::vector, boost::bimap> -GPGraph::get_sequence() { +GPGraph::get_sequence(std::shared_ptr> stop_flag) { std::vector vertices = vertices_in_order(); auto it = vertices.begin(); std::vector> interior_nodes; while (it != vertices.end()) { + if (stop_flag.get()->load()) { + return {}; + } const PauliNode_ptr& node = graph_[*it]; std::vector commuting_set; commuting_set.push_back(node); diff --git a/tket/src/Transformations/GreedyPauliOptimisation.cpp b/tket/src/Transformations/GreedyPauliOptimisation.cpp index 3c80ee1eed..9f6b0956a4 100644 --- a/tket/src/Transformations/GreedyPauliOptimisation.cpp +++ b/tket/src/Transformations/GreedyPauliOptimisation.cpp @@ -772,14 +772,21 @@ Circuit greedy_pauli_graph_synthesis_flag( for (const auto& pair : unit_map) { rev_unit_map.insert({pair.second, pair.first}); } - GPGraph gpg(circ_flat); + + GPGraph gpg(circ_flat.all_qubits(), circ_flat.all_bits()); + for (const Command& cmd : circ_flat.get_commands()) { + if (stop_flag.get()->load()) { + return Circuit(); + } + gpg.apply_gate_at_end(cmd); + } // We regularly check whether the timeout has ocurred if (stop_flag.get()->load()) { return Circuit(); } - auto [rotation_sets, rows, measures] = gpg.get_sequence(); + auto [rotation_sets, rows, measures] = gpg.get_sequence(stop_flag); if (stop_flag.get()->load()) { return Circuit(); diff --git a/tket/test/src/test_GreedyPauli.cpp b/tket/test/src/test_GreedyPauli.cpp index 76e0c0cfc6..268cf6bcef 100644 --- a/tket/test/src/test_GreedyPauli.cpp +++ b/tket/test/src/test_GreedyPauli.cpp @@ -764,70 +764,72 @@ SCENARIO("Test GreedyPauliSimp pass construction") { SCENARIO("Test GreedyPauliSimp with multiple trials and threads") { GIVEN("Large circuit with ZZPhase") { Circuit circ(6); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::X, Pauli::X}, 0.3)), {0, 1}); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Y, Pauli::X}, 0.2)), - {0, 1, 2}); - circ.add_box( - PauliExpCommutingSetBox({ - {{Pauli::I, Pauli::Y, Pauli::I, Pauli::Z}, 1.2}, - {{Pauli::X, Pauli::Y, Pauli::Z, Pauli::I}, 0.8}, - {{Pauli::I, Pauli::I, Pauli::I, Pauli::Z}, 1.25}, - }), - {1, 2, 3, 4}); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::Y, Pauli::X}, 0.1)), {2, 3}); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Y, Pauli::X}, 0.11)), - {1, 3, 4}); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::Y, Pauli::Y}, 0.2)), {4, 5}); - circ.add_box( - PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Z, Pauli::X}, 0.15)), - {2, 4, 5}); - circ.add_box( - PauliExpBox( - SymPauliTensor({Pauli::X, Pauli::X, Pauli::X, Pauli::X}, 0.25)), - {2, 4, 5, 0}); - circ.add_box( - PauliExpBox( - SymPauliTensor({Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, 0.125)), - {1, 3, 5, 0}); + for (unsigned i = 0; i < 1000; i++) { + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::X, Pauli::X}, 0.3)), {0, 1}); + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Y, Pauli::X}, 0.2)), + {0, 1, 2}); + circ.add_box( + PauliExpCommutingSetBox({ + {{Pauli::I, Pauli::Y, Pauli::I, Pauli::Z}, 1.2}, + {{Pauli::X, Pauli::Y, Pauli::Z, Pauli::I}, 0.8}, + {{Pauli::I, Pauli::I, Pauli::I, Pauli::Z}, 1.25}, + }), + {1, 2, 3, 4}); + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::Y, Pauli::X}, 0.1)), {2, 3}); + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Y, Pauli::X}, 0.11)), + {1, 3, 4}); + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::Y, Pauli::Y}, 0.2)), {4, 5}); + circ.add_box( + PauliExpBox(SymPauliTensor({Pauli::Z, Pauli::Z, Pauli::X}, 0.15)), + {2, 4, 5}); + circ.add_box( + PauliExpBox( + SymPauliTensor({Pauli::X, Pauli::X, Pauli::X, Pauli::X}, 0.25)), + {2, 4, 5, 0}); + circ.add_box( + PauliExpBox( + SymPauliTensor({Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, 0.125)), + {1, 3, 5, 0}); - circ.add_box( - PauliExpBox(SymPauliTensor( - {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::X}, - 0.125)), - {1, 3, 5, 0, 2, 4}); - - circ.add_box( - PauliExpBox(SymPauliTensor( - {Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, - 0.125)), - {0, 1, 2, 3, 4, 5}); + circ.add_box( + PauliExpBox(SymPauliTensor( + {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::X}, + 0.125)), + {1, 3, 5, 0, 2, 4}); - circ.add_box( - PauliExpBox(SymPauliTensor( - {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, - 0.125)), - {5, 2, 4, 1, 3, 0}); + circ.add_box( + PauliExpBox(SymPauliTensor( + {Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, + 0.125)), + {0, 1, 2, 3, 4, 5}); - circ.add_box( - PauliExpBox(SymPauliTensor( - {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::X}, - 0.125)), - {0, 5, 1, 4, 3, 2}); + circ.add_box( + PauliExpBox(SymPauliTensor( + {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Z, Pauli::Z, Pauli::X}, + 0.125)), + {5, 2, 4, 1, 3, 0}); + circ.add_box( + PauliExpBox(SymPauliTensor( + {Pauli::X, Pauli::Z, Pauli::Y, Pauli::Y, Pauli::Z, Pauli::X}, + 0.125)), + {0, 5, 1, 4, 3, 2}); + } Circuit d(circ); REQUIRE(!Transforms::greedy_pauli_optimisation( - 0.7, 0.3, 500, 500, 0, true, 0, 10) + 0.7, 0.3, 500, 500, 0, true, 1, 10) .apply(d)); REQUIRE(Transforms::greedy_pauli_optimisation( - 0.7, 0.3, 500, 500, 0, true, 10, 10) + 0.7, 0.3, 500, 500, 0, true, 100, 10) .apply(d)); REQUIRE(test_unitary_comparison(circ, d, true)); } } + } // namespace test_GreedyPauliSimp } // namespace tket