Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TKET-1598] fix ConnectivityPredicate fails after FullPeepholeOptimise and AASRouting #194

Merged
merged 3 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions tket/src/Predicates/PassGenerators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,18 @@ PassPtr gen_placement_pass_phase_poly(const Architecture& arc) {
};
Transform t = Transform(trans);

PredicatePtrMap precons{};
PredicatePtr no_wire_swap = std::make_shared<NoWireSwapsPredicate>();
PredicatePtrMap precons{CompilationUnit::make_type_pair(no_wire_swap)};

PredicatePtr placement_pred = std::make_shared<PlacementPredicate>(arc);
PredicatePtr n_qubit_pred =
std::make_shared<MaxNQubitsPredicate>(arc.n_nodes());

PredicatePtrMap s_postcons{
CompilationUnit::make_type_pair(placement_pred),
CompilationUnit::make_type_pair(n_qubit_pred)};
CompilationUnit::make_type_pair(n_qubit_pred),
CompilationUnit::make_type_pair(no_wire_swap)};

PostConditions pc{s_postcons, {}, Guarantee::Preserve};
// record pass config
nlohmann::json j;
Expand All @@ -297,6 +302,10 @@ PassPtr aas_routing_pass(
"Circuit has more qubits than the architecture has nodes.");
}

// this pass is not able to handle implicit wire swaps
// this is additionally assured by a precondition of this pass
TKET_ASSERT(!circ.has_implicit_wireswaps());

qubit_vector_t all_qu = circ.all_qubits();

Circuit input_circ = circ;
Expand Down Expand Up @@ -379,9 +388,12 @@ PassPtr aas_routing_pass(
PredicatePtr placedpred = std::make_shared<PlacementPredicate>(arc);
PredicatePtr n_qubit_pred =
std::make_shared<MaxNQubitsPredicate>(arc.n_nodes());
PredicatePtr no_wire_swap = std::make_shared<NoWireSwapsPredicate>();

PredicatePtrMap precons{
CompilationUnit::make_type_pair(placedpred),
CompilationUnit::make_type_pair(n_qubit_pred)};
CompilationUnit::make_type_pair(n_qubit_pred),
CompilationUnit::make_type_pair(no_wire_swap)};

PredicatePtr postcon1 = std::make_shared<ConnectivityPredicate>(arc);
std::pair<const std::type_index, PredicatePtr> pair1 =
Expand Down
10 changes: 9 additions & 1 deletion tket/src/Predicates/PassLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ const PassPtr &ComposePhasePolyBoxes() {
* converts a circuit containing all possible gates to a circuit
* containing only phase poly boxes + H gates (and measure + reset + collapse
* + barrier)
* this pass will replace all wire swaps in the given circuit and they will be
* included in the last or an additional phase poly boxes
*/
static const PassPtr pp([]() {
Transform t =
Expand All @@ -293,7 +295,13 @@ const PassPtr &ComposePhasePolyBoxes() {

PredicatePtrMap precons{CompilationUnit::make_type_pair(noclas)};

PostConditions postcon = {precons, {}, Guarantee::Clear};
PredicatePtr no_wire_swap = std::make_shared<NoWireSwapsPredicate>();

PredicatePtrMap s_postcons{
CompilationUnit::make_type_pair(noclas),
CompilationUnit::make_type_pair(no_wire_swap)};
PostConditions postcon{s_postcons, {}, Guarantee::Preserve};

nlohmann::json j;
j["name"] = "ComposePhasePolyBoxes";
return std::make_shared<StandardPass>(precons, t, postcon, j);
Expand Down
1 change: 1 addition & 0 deletions tket/src/Predicates/include/Predicates/PassGenerators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ PassPtr gen_directed_cx_routing_pass(
/**
* execute architecture aware synthesis on a given architecture for an allready
* place circuit, only for circuit which contains Cx+Rz+H gates
* this pass is not able to handle implicit wire swaps
* @param arc architecture to route on
* @param lookahead parameter for the recursion depth in the algorithm, the
* value should be > 0
Expand Down
11 changes: 11 additions & 0 deletions tket/src/Transformations/Decomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,17 @@ Transform decomp_boxes() {

Transform compose_phase_poly_boxes() {
return Transform([](Circuit &circ) {
// replace wireswaps with three CX
while (circ.has_implicit_wireswaps()) {
qubit_map_t perm = circ.implicit_qubit_permutation();
for (const std::pair<const Qubit, Qubit> &pair : perm) {
if (pair.first != pair.second) {
circ.replace_implicit_wire_swap(pair.first, pair.second);
break;
}
}
}

CircToPhasePolyConversion conv = CircToPhasePolyConversion(circ);
conv.convert();
circ = conv.get_circuit();
Expand Down
70 changes: 68 additions & 2 deletions tket/tests/test_CompilerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ SCENARIO("rebase and decompose PhasePolyBox test") {
Circuit result = cu.get_circ_ref();

REQUIRE(test_unitary_comparison(result, circ));
REQUIRE(!NoWireSwapsPredicate().verify(result));
REQUIRE(NoWireSwapsPredicate().verify(result));
}
GIVEN("NoWireSwapsPredicate for ComposePhasePolyBoxes II") {
Circuit circ(5);
Expand All @@ -817,7 +817,73 @@ SCENARIO("rebase and decompose PhasePolyBox test") {
Circuit result = cu.get_circ_ref();

REQUIRE(test_unitary_comparison(result, circ));
REQUIRE(!NoWireSwapsPredicate().verify(result));
REQUIRE(NoWireSwapsPredicate().verify(result));
}
GIVEN("NoWireSwapsPredicate for ComposePhasePolyBoxes III") {
Circuit circ(5);
add_2qb_gates(circ, OpType::CX, {{0, 3}, {1, 4}});
circ.add_op<unsigned>(OpType::SWAP, {3, 4});
circ.add_op<unsigned>(OpType::CX, {2, 3});
circ.add_op<unsigned>(OpType::Z, {3});
circ.add_op<unsigned>(OpType::CX, {2, 3});
circ.add_op<unsigned>(OpType::SWAP, {0, 1});
circ.add_op<unsigned>(OpType::CX, {1, 4});
circ.add_op<unsigned>(OpType::Z, {4});
circ.add_op<unsigned>(OpType::CX, {1, 4});
circ.add_op<unsigned>(OpType::SWAP, {1, 2});
circ.add_op<unsigned>(OpType::SWAP, {2, 3});
circ.add_op<unsigned>(OpType::CX, {0, 1});
circ.add_op<unsigned>(OpType::CX, {1, 2});
circ.add_op<unsigned>(OpType::CX, {2, 3});

REQUIRE(NoWireSwapsPredicate().verify(circ));
circ.replace_SWAPs();
REQUIRE(!NoWireSwapsPredicate().verify(circ));

CompilationUnit cu(circ);
REQUIRE(ComposePhasePolyBoxes()->apply(cu));
Circuit result = cu.get_circ_ref();

REQUIRE(test_unitary_comparison(result, circ));
REQUIRE(NoWireSwapsPredicate().verify(result));
}
GIVEN("NoWireSwapsPredicate for aas I") {
std::vector<Node> nodes = {Node(0), Node(1), Node(2), Node(3), Node(4)};
Architecture architecture(
{{nodes[0], nodes[1]},
{nodes[1], nodes[2]},
{nodes[2], nodes[3]},
{nodes[3], nodes[4]}});

Circuit circ(5);
add_2qb_gates(circ, OpType::CX, {{0, 3}, {1, 4}});
circ.add_op<unsigned>(OpType::SWAP, {3, 4});
circ.add_op<unsigned>(OpType::CX, {2, 3});
circ.add_op<unsigned>(OpType::Z, {3});
circ.add_op<unsigned>(OpType::CX, {2, 3});
circ.add_op<unsigned>(OpType::SWAP, {0, 1});
circ.add_op<unsigned>(OpType::CX, {1, 4});
circ.add_op<unsigned>(OpType::Z, {4});
circ.add_op<unsigned>(OpType::CX, {1, 4});
circ.add_op<unsigned>(OpType::SWAP, {1, 2});
circ.add_op<unsigned>(OpType::SWAP, {2, 3});
circ.add_op<unsigned>(OpType::CX, {0, 1});
circ.add_op<unsigned>(OpType::CX, {1, 2});
circ.add_op<unsigned>(OpType::CX, {2, 3});

REQUIRE(NoWireSwapsPredicate().verify(circ));
circ.replace_SWAPs();
REQUIRE(!NoWireSwapsPredicate().verify(circ));

CompilationUnit cu(circ);

REQUIRE(gen_full_mapping_pass_phase_poly(
architecture, 1, aas::CNotSynthType::Rec)
->apply(cu));
Circuit result = cu.get_circ_ref();

REQUIRE(test_unitary_comparison(result, circ));
REQUIRE(NoWireSwapsPredicate().verify(result));
}
}

Expand Down