Skip to content

Commit

Permalink
fix wire swap handling in the creation of a phase poly box [TKET-1653] (
Browse files Browse the repository at this point in the history
#146)

Fixes: [TKET-1653] No wireswap handling in the creation of a phase poly box #126

* add bugfix for wireswap in ppb creation

* try to fix mac

* try to fix mac II
  • Loading branch information
cqc-melf authored Jan 4, 2022
1 parent 9475e57 commit 61b2d75
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 4 deletions.
11 changes: 11 additions & 0 deletions tket/src/Circuit/Circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,17 @@ class Circuit {
*/
void replace_SWAPs();

/**
* this function replaces an implicit wire swap between the two given qubits
* with three CX operations
*
* @param first qubits to add the wireswap on
* @param second qubits to add the wireswap on
*
* O(c)
*/
void replace_implicit_wire_swap(const Qubit first, const Qubit second);

// O(E+V+q)
Circuit dagger() const;

Expand Down
12 changes: 12 additions & 0 deletions tket/src/Circuit/macro_manipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,18 @@ void Circuit::replace_SWAPs() {
remove_vertices(bin, GraphRewiring::No, VertexDeletion::Yes);
}

void Circuit::replace_implicit_wire_swap(
const Qubit first, const Qubit second) {
add_op<UnitID>(OpType::CX, {first, second});
add_op<UnitID>(OpType::CX, {second, first});
Vertex cxvertex = add_op<UnitID>(OpType::CX, {first, second});
EdgeVec outs = get_all_out_edges(cxvertex);
Edge out1 = outs[0];
dag[out1].ports.first = 1;
Edge out2 = outs[1];
dag[out2].ports.first = 0;
}

// helper functions for the dagger and transpose
void Circuit::_handle_boundaries(Circuit& circ, vertex_map_t& vmap) const {
// Handle boundaries
Expand Down
45 changes: 41 additions & 4 deletions tket/src/Converters/PhasePoly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,18 +147,55 @@ Circuit gray_synth(

PhasePolyBox::PhasePolyBox(const Circuit& circ)
: Box(OpType::PhasePolyBox), n_qubits_(circ.n_qubits()) {
if (circ.n_bits() != 0)
Circuit newcirc(circ);

// check for classical bits
if (newcirc.n_bits() != 0)
throw NotValid(
"Cannot construct phase polynomial from classical controlled "
"gates");

// check the gateset of the circuit
for (const Command& com : newcirc) {
OpType ot = com.get_op_ptr()->get_type();

switch (ot) {
case OpType::CX: {
break;
}
case OpType::Rz: {
break;
}
default: {
throw NotValid("Only CXs and Rzs allowed in Phase Polynomials");
}
}
}

// replace wireswaps with three CX
while (newcirc.has_implicit_wireswaps()) {
bool foundswap = false;

qubit_map_t perm = newcirc.implicit_qubit_permutation();
for (const std::pair<const Qubit, Qubit>& pair : perm) {
if (pair.first != pair.second) {
if (!foundswap) {
newcirc.replace_implicit_wire_swap(pair.first, pair.second);
foundswap = true;
}
}
}
}

// generate box
signature_ = op_signature_t(n_qubits_, EdgeType::Quantum);
unsigned i = 0;
for (const Qubit& qb : circ.all_qubits()) {
for (const Qubit& qb : newcirc.all_qubits()) {
qubit_indices_.insert({qb, i});
++i;
}
linear_transformation_ = MatrixXb::Identity(n_qubits_, n_qubits_);
for (const Command& com : circ) {
for (const Command& com : newcirc) {
OpType ot = com.get_op_ptr()->get_type();
unit_vector_t qbs = com.get_args();
if (ot == OpType::CX) {
Expand All @@ -180,7 +217,7 @@ PhasePolyBox::PhasePolyBox(const Circuit& circ)
else
pp_it->second += com.get_op_ptr()->get_params().at(0);
} else
throw NotImplemented("Only CXs and Rzs allowed in Phase Polynomials");
TKET_ASSERT(!"Only CXs and Rzs allowed in Phase Polynomials");
}
}

Expand Down
34 changes: 34 additions & 0 deletions tket/tests/test_PhasePolynomials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,40 @@ SCENARIO("Test conversion of circuit to circuit with phase poly boxes") {
REQUIRE(test_statevector_comparison(circ, result));
}
}
SCENARIO("Phase polynomial synthesis without architecture") {
GIVEN("single SWAP circuit") {
Circuit circ(2);
circ.add_op<unsigned>(OpType::SWAP, {0, 1});
circ.replace_SWAPs();
PhasePolyBox ppbox(circ);
std::shared_ptr<Circuit> circptr = ppbox.to_circuit();
Circuit circ2 = *circptr;
REQUIRE(test_unitary_comparison(circ, circ2));
}
GIVEN("more SWAP circuit") {
Circuit circ(5);
circ.add_op<unsigned>(OpType::SWAP, {0, 1});
circ.add_op<unsigned>(OpType::SWAP, {0, 2});
circ.add_op<unsigned>(OpType::SWAP, {0, 3});
circ.replace_SWAPs();
PhasePolyBox ppbox(circ);
std::shared_ptr<Circuit> circptr = ppbox.to_circuit();
Circuit circ2 = *circptr;
REQUIRE(test_unitary_comparison(circ, circ2));
}
GIVEN("more SWAP circuit II") {
Circuit circ(5);
circ.add_op<unsigned>(OpType::SWAP, {0, 1});
circ.add_op<unsigned>(OpType::SWAP, {1, 2});
circ.add_op<unsigned>(OpType::SWAP, {2, 3});
circ.add_op<unsigned>(OpType::SWAP, {3, 4});
circ.replace_SWAPs();
PhasePolyBox ppbox(circ);
std::shared_ptr<Circuit> circptr = ppbox.to_circuit();
Circuit circ2 = *circptr;
REQUIRE(test_unitary_comparison(circ, circ2));
}
}

} // namespace test_PhasePolynomials
} // namespace tket

0 comments on commit 61b2d75

Please sign in to comment.