Skip to content

Commit

Permalink
Update Noise Aware Placement for Circuits with only single qubit gates (
Browse files Browse the repository at this point in the history
#1165)

* Add catch for empty pattern graph

* Update test_NoiseAwarePlacement.cpp

* bump

* Add further comments

* Update changelog.rst

* Update pytket/docs/changelog.rst

Co-authored-by: Alec Edgington <[email protected]>

---------

Co-authored-by: Alec Edgington <[email protected]>
  • Loading branch information
sjdilkes and cqc-alec authored Dec 8, 2023
1 parent 3f67a56 commit ef9fbbb
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def package(self):
cmake.install()

def requirements(self):
self.requires("tket/1.2.71@tket/stable")
self.requires("tket/1.2.72@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")
Expand Down
7 changes: 3 additions & 4 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ Deprecations:

Fixes:

* Fix `PauliFrameRandomisation.sample_circuits`.

Fixes:

* Ensure that squashing long sequences of gates via unitary multiplication does
not produce non-unitary results due to rounding errors.
* Fix `PauliFrameRandomisation.sample_circuits`.
* For `Circuit` with no 2-qubit gates, `NoiseAwarePlacement` now assigns `Qubit` to `Node` in `Architecture`
with lowest reported error rates.


1.22.0 (November 2023)
Expand Down
2 changes: 1 addition & 1 deletion tket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TketConan(ConanFile):
name = "tket"
version = "1.2.71"
version = "1.2.72"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
29 changes: 29 additions & 0 deletions tket/src/Placement/NoiseAwarePlacement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,35 @@ std::vector<std::map<Qubit, Node>> NoiseAwarePlacement::get_all_placement_maps(
const Circuit& circ_, unsigned matches) const {
std::vector<WeightedEdge> weighted_pattern_edges =
this->default_pattern_weighting(circ_);

if (weighted_pattern_edges.empty()) {
// => there are no two-qubit gates in the input circuit
// in this case, as this method is "noise-aware", assign
// qubits in the circuit to the lowest-error architecture nodes
std::vector<std::pair<gate_error_t, Node>> all_node_errors;
for (const Node& node : this->architecture_.nodes()) {
all_node_errors.push_back(
{this->characterisation_.get_error(node), node});
}
// make sure all_node_errors goes from best->worst error rates
// N.B. `get_error` returns "0", i.e. no error, if the `Node` passed
// is not held in the characterisation
std::sort(
all_node_errors.begin(), all_node_errors.end(),
[](const auto& lhs, const auto& rhs) {
// Compare based on the float values in descending order
return lhs.first < rhs.first;
});
std::vector<Qubit> circ_qubits = circ_.all_qubits();
TKET_ASSERT(all_node_errors.size() >= circ_qubits.size());
std::map<Qubit, Node> placement_map;
// assign circuit qubits to Node with best error rate
for (std::size_t i = 0; i < circ_qubits.size(); i++) {
placement_map.insert({circ_qubits[i], all_node_errors[i].second});
}
return {placement_map};
}

std::vector<boost::bimap<Qubit, Node>> placement_maps =
this->get_all_weighted_subgraph_monomorphisms(
circ_, weighted_pattern_edges, true);
Expand Down
40 changes: 33 additions & 7 deletions tket/test/src/Placement/test_NoiseAwarePlacement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ SCENARIO("Base NoiseAwarePlacement class") {
Circuit circuit(1);
NoiseAwarePlacement placement(architecture);
placement.place(circuit);
REQUIRE(circuit.all_qubits()[0] == Qubit(Placement::unplaced_reg(), 0));
REQUIRE(circuit.all_qubits()[0] == Node(0));
}
GIVEN(
"Two qubit unconnected circuit, two qubit Architecture, "
Expand All @@ -51,8 +51,8 @@ SCENARIO("Base NoiseAwarePlacement class") {
Circuit circuit(2);
NoiseAwarePlacement placement(architecture);
placement.place(circuit);
REQUIRE(circuit.all_qubits()[0] == Qubit(Placement::unplaced_reg(), 0));
REQUIRE(circuit.all_qubits()[1] == Qubit(Placement::unplaced_reg(), 1));
REQUIRE(circuit.all_qubits()[0] == Node(0));
REQUIRE(circuit.all_qubits()[1] == Node(1));
}
GIVEN(
"Three qubit unconnected circuit, two qubit Architecture, "
Expand Down Expand Up @@ -231,8 +231,8 @@ SCENARIO("Base NoiseAwarePlacement class") {
circuit.add_op<unsigned>(OpType::CX, {1, 2});
circuit.add_op<unsigned>(OpType::CX, {2, 3});
circuit.add_op<unsigned>(OpType::CX, {0, 3});
// In this case there are many valid placements, it happens to return this
// one
// In this case there are many valid placements, it happens to return
// this one
NoiseAwarePlacement placement(architecture);
std::map<Qubit, Node> map = placement.get_placement_map(circuit);
REQUIRE(map[Qubit(0)] == Node(3));
Expand Down Expand Up @@ -276,8 +276,8 @@ SCENARIO("Base NoiseAwarePlacement class") {
DeviceCharacterisation characterisation_link_node(
op_node_errors, op_link_errors);

// Here the difference in single qubit error rates makes this placement (or
// a rotation of) best
// Here the difference in single qubit error rates makes this placement
// (or a rotation of) best
placement.set_characterisation(characterisation_link_node);
map = placement.get_placement_map(circuit);

Expand Down Expand Up @@ -408,5 +408,31 @@ SCENARIO("Base NoiseAwarePlacement class") {
REQUIRE(map[Qubit(4)] == Node(1));
REQUIRE(map[Qubit(5)] == Node(2));
}
GIVEN(
"A circuit with only single-qubit gates, assigns Qubits to Nodes with "
"lowest single qubit error rates.") {
std::vector<std::pair<unsigned, unsigned>> edges = {
{0, 1}, {1, 2}, {0, 2}, {2, 3}};
Architecture architecture(edges);
Circuit circuit(3);
circuit.add_op<unsigned>(OpType::H, {0});
circuit.add_op<unsigned>(OpType::H, {1});
circuit.add_op<unsigned>(OpType::H, {2});

avg_node_errors_t op_node_errors;
op_node_errors[Node(0)] = 0.25;
op_node_errors[Node(1)] = 0.01;
op_node_errors[Node(2)] = 0.01;
op_node_errors[Node(3)] = 0.05;

DeviceCharacterisation characterisation(op_node_errors, {}, {});
NoiseAwarePlacement placement(architecture);
placement.set_characterisation(characterisation);

std::map<Qubit, Node> placement_map = placement.get_placement_map(circuit);
REQUIRE(placement_map[Qubit(0)] == Node(1));
REQUIRE(placement_map[Qubit(1)] == Node(2));
REQUIRE(placement_map[Qubit(2)] == Node(3));
}
}
} // namespace tket

0 comments on commit ef9fbbb

Please sign in to comment.