Skip to content

Commit

Permalink
Assert candidate swaps size (#108)
Browse files Browse the repository at this point in the history
* Add assertion that there are at least some swaps to trial

* Pseudo code for Yao

* Fix routing with measurements issue

* Add classically controlled gates to lexiroute test

Co-authored-by: sjdilkes <[email protected]>
  • Loading branch information
yao-cqc and sjdilkes authored Nov 9, 2021
1 parent 5b50029 commit 4c92d8d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
10 changes: 8 additions & 2 deletions tket/src/Mapping/LexiRoute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ void LexiRoute::solve(unsigned lookahead) {
}
swap_set_t candidate_swaps = this->get_candidate_swaps();
this->remove_swaps_decreasing(candidate_swaps);

TKET_ASSERT(candidate_swaps.size() != 0);
// Only want to substitute a single swap
// check next layer of interacting qubits and remove swaps until only one
// lexicographically superior swap is left
Expand All @@ -488,17 +490,18 @@ void LexiRoute::solve(unsigned lookahead) {
// architecture
this->set_interacting_uids(true);
}

// find best swap
auto it = candidate_swaps.end();
--it;

std::pair<Node, Node> chosen_swap = *it;
this->mapping_frontier_->set_quantum_boundary(copy);

this->set_interacting_uids();
std::pair<bool, bool> check = this->check_bridge(chosen_swap, lookahead);

// set for final time, to allow gates to be correctly inserted, but then leave
// as is
// insert gates
this->mapping_frontier_->set_quantum_boundary(copy);
if (!check.first && !check.second) {
// update circuit with new swap
Expand All @@ -522,8 +525,10 @@ void LexiRoute::solve(unsigned lookahead) {
this->mapping_frontier_->add_bridge(chosen_swap.second, central, target);
}
}

// TODO: Refactor the following to happen during add_swap and add_bridge
// methods
// add ancilla qubits if necessary
if (copy.size() < this->mapping_frontier_->quantum_boundary->size()) {
// implies ancilla qubit is added
// find ancilla qubit, find swap vertex and port by looking at boundary,
Expand Down Expand Up @@ -557,6 +562,7 @@ void LexiRoute::solve(unsigned lookahead) {
}
}
}

return;
}

Expand Down
19 changes: 16 additions & 3 deletions tket/src/Mapping/MappingFrontier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,23 @@ void MappingFrontier::advance_frontier_boundary(
// TODO: add optional skip function later to skip vertices that don't have
// physical requirements
boundary_updated = false;
CutFrontier next_cut = this->circuit_.next_cut(

std::shared_ptr<unit_frontier_t> frontier_edges =
frontier_convert_vertport_to_edge(
this->circuit_, this->quantum_boundary),
std::make_shared<b_frontier_t>());
this->circuit_, this->quantum_boundary);
// Add all classical edges that share the same target
unsigned dummy_bit_index = 0;
for (const std::pair<UnitID, Edge>& pair : frontier_edges->get<TagKey>()) {
Vertex vert = this->circuit_.target(pair.second);
for (const Edge& e :
this->circuit_.get_in_edges_of_type(vert, EdgeType::Classical)) {
frontier_edges->insert({Bit(dummy_bit_index), e});
dummy_bit_index++;
}
}

CutFrontier next_cut = this->circuit_.next_cut(
frontier_edges, std::make_shared<b_frontier_t>());

// For each vertex in a slice, if its physically permitted, update
// quantum_boundary with quantum out edges from vertex (i.e.
Expand Down
33 changes: 33 additions & 0 deletions tket/tests/test_LexiRoute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,39 @@ SCENARIO("Test LexiRoute::solve") {
LexiRoute lr1(shared_arc, mf);
lr1.solve(20);
}

GIVEN(
"Single best solution, with measurements and classically controlled "
"gates.") {
Circuit circ(6, 1);
std::vector<Qubit> qubits = circ.all_qubits();
circ.add_conditional_gate<unsigned>(OpType::CX, {}, {0, 2}, {0}, 1);
circ.add_op<UnitID>(OpType::CX, {qubits[1], qubits[3]});
circ.add_conditional_gate<unsigned>(OpType::X, {}, {0}, {0}, 1);
circ.add_op<UnitID>(OpType::Measure, {qubits[1], Bit(0)});
circ.add_op<UnitID>(OpType::CX, {qubits[4], qubits[5]});
circ.add_op<UnitID>(OpType::Measure, {qubits[3], Bit(0)});
// n0 -- n1 -- n2 -- n3 -- n4
// | |
// n5 n7
// |
// n6
std::map<UnitID, UnitID> rename_map = {
{qubits[0], nodes[0]}, {qubits[1], nodes[1]}, {qubits[2], nodes[2]},
{qubits[3], nodes[3]}, {qubits[4], nodes[6]}, {qubits[5], nodes[5]}};
circ.rename_units(rename_map);
std::shared_ptr<MappingFrontier> mf =
std::make_shared<MappingFrontier>(circ);
LexiRoute lr(shared_arc, mf);

lr.solve(4);
std::vector<Command> commands = mf->circuit_.get_commands();
REQUIRE(commands.size() == 7);
Command swap_c = commands[1];
unit_vector_t uids = {nodes[1], nodes[2]};
REQUIRE(swap_c.get_args() == uids);
REQUIRE(*swap_c.get_op_ptr() == *get_op_ptr(OpType::SWAP));
}
}
SCENARIO("Test LexiRouteRoutingMethod") {
std::vector<Node> nodes = {
Expand Down

0 comments on commit 4c92d8d

Please sign in to comment.