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

Infra/use bimap for quantum boundary #185

Merged
merged 4 commits into from
Feb 4, 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
8 changes: 2 additions & 6 deletions tket/src/Mapping/MappingFrontier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ namespace tket {
UnitID get_unitid_from_unit_frontier(
const std::shared_ptr<unit_vertport_frontier_t>& u_frontier,
const VertPort& vp) {
for (auto it = u_frontier->get<TagKey>().begin();
it != u_frontier->get<TagKey>().end(); ++it) {
if (it->second == vp) {
return it->first;
}
}
auto it = u_frontier->get<TagValue>().find(vp);
if (it != u_frontier->get<TagValue>().end()) return it->first;
throw MappingFrontierError(
std::string("Edge provided not in unit_frontier_t object."));
}
Expand Down
50 changes: 17 additions & 33 deletions tket/src/Mapping/MultiGateReorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,25 @@ MultiGateReorder::MultiGateReorder(
_mapping_frontier->circuit_, _mapping_frontier->quantum_boundary));
}

// Traverse the DAG to the quantum frontier encoded in q_boundary_map
// Traverse the DAG to the quantum frontier
// to find the UnitID associated with an VertPort
UnitID get_unitid_from_vertex_port(
const Circuit &circ, const VertPort &vert_port,
const std::map<VertPort, UnitID> &q_boundary_map) {
const std::shared_ptr<MappingFrontier> &frontier,
const VertPort &vert_port) {
VertPort current_vert_port = vert_port;
while (true) {
auto it = q_boundary_map.find(current_vert_port);
if (it != q_boundary_map.end()) {
return it->second;
auto it =
frontier->quantum_boundary->get<TagValue>().find(current_vert_port);
if (it != frontier->quantum_boundary->get<TagValue>().end()) {
return it->first;
}
Edge current_e = circ.get_nth_out_edge(
Edge current_e = frontier->circuit_.get_nth_out_edge(
current_vert_port.first, current_vert_port.second);
Vertex prev_vert;
Edge prev_e;
std::tie(prev_vert, prev_e) =
circ.get_prev_pair(current_vert_port.first, current_e);
current_vert_port = {prev_vert, circ.get_source_port(prev_e)};
frontier->circuit_.get_prev_pair(current_vert_port.first, current_e);
current_vert_port = {prev_vert, frontier->circuit_.get_source_port(prev_e)};
}
}

Expand All @@ -46,12 +47,11 @@ bool is_multiq_quantum_gate(const Circuit &circ, const Vertex &vert) {
}

bool is_physically_permitted(
const Circuit &circ, const ArchitecturePtr &arc_ptr, const Vertex &vert,
const std::map<VertPort, UnitID> &q_boundary_map) {
const std::shared_ptr<MappingFrontier> &frontier,
const ArchitecturePtr &arc_ptr, const Vertex &vert) {
std::vector<Node> nodes;
for (port_t port = 0; port < circ.n_ports(vert); ++port) {
nodes.push_back(
Node(get_unitid_from_vertex_port(circ, {vert, port}, q_boundary_map)));
for (port_t port = 0; port < frontier->circuit_.n_ports(vert); ++port) {
nodes.push_back(Node(get_unitid_from_vertex_port(frontier, {vert, port})));
}

return arc_ptr->valid_operation(nodes);
Expand Down Expand Up @@ -176,14 +176,11 @@ void MultiGateReorder::solve(unsigned max_depth, unsigned max_size) {

// store a copy of the original this->mapping_frontier_->quantum_boundray
// this object will be updated and reset throughout the procedure
// so need to return it to original setting at end
// also create a map for getting UnitID from VertPort
std::map<VertPort, UnitID> q_boundary_map;
// so need to return it to original setting at end.
unit_vertport_frontier_t copy;
for (const std::pair<UnitID, VertPort> &pair :
this->mapping_frontier_->quantum_boundary->get<TagKey>()) {
copy.insert({pair.first, pair.second});
q_boundary_map.insert({pair.second, pair.first});
}
// Get a subcircuit only for iterating vertices
Subcircuit circ =
Expand All @@ -196,8 +193,7 @@ void MultiGateReorder::solve(unsigned max_depth, unsigned max_size) {
// 2. is a multi qubit quantum operation without classical controls
if (is_multiq_quantum_gate(this->mapping_frontier_->circuit_, vert) &&
is_physically_permitted(
this->mapping_frontier_->circuit_, this->architecture_, vert,
q_boundary_map)) {
this->mapping_frontier_, this->architecture_, vert)) {
std::optional<std::pair<EdgeVec, EdgeVec>> commute_pairs =
try_find_commute_edges(
this->mapping_frontier_->circuit_, this->u_frontier_edges_, vert);
Expand All @@ -212,12 +208,6 @@ void MultiGateReorder::solve(unsigned max_depth, unsigned max_size) {
convert_u_frontier_to_edges(*frontier_convert_vertport_to_edge(
this->mapping_frontier_->circuit_,
this->mapping_frontier_->quantum_boundary));
// Update the map
q_boundary_map.clear();
for (const std::pair<UnitID, VertPort> &pair :
this->mapping_frontier_->quantum_boundary->get<TagKey>()) {
q_boundary_map.insert({pair.second, pair.first});
}
}
}
}
Expand All @@ -235,20 +225,14 @@ bool MultiGateReorderRoutingMethod::check_method(
const EdgeVec u_frontier_edges =
convert_u_frontier_to_edges(*frontier_convert_vertport_to_edge(
mapping_frontier->circuit_, mapping_frontier->quantum_boundary));
std::map<VertPort, UnitID> q_boundary_map;
for (const std::pair<UnitID, VertPort> &pair :
mapping_frontier->quantum_boundary->get<TagKey>()) {
q_boundary_map.insert({pair.second, pair.first});
}

Subcircuit circ = mapping_frontier->get_frontier_subcircuit(
this->max_depth_, this->max_size_);
// since we assume that the frontier has been advanced
// we are certain that any multi-q vert lies after the frontier
for (const Vertex &vert : circ.verts) {
if (is_multiq_quantum_gate(mapping_frontier->circuit_, vert) &&
is_physically_permitted(
mapping_frontier->circuit_, architecture, vert, q_boundary_map)) {
is_physically_permitted(mapping_frontier, architecture, vert)) {
std::optional<std::pair<EdgeVec, EdgeVec>> commute_pairs =
try_find_commute_edges(
mapping_frontier->circuit_, u_frontier_edges, vert);
Expand Down
2 changes: 1 addition & 1 deletion tket/src/Mapping/include/Mapping/MappingFrontier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace tket {

typedef sequenced_map_t<UnitID, VertPort> unit_vertport_frontier_t;
typedef sequenced_bimap_t<UnitID, VertPort> unit_vertport_frontier_t;

// list of error types to throw out
class MappingFrontierError : public std::logic_error {
Expand Down
16 changes: 16 additions & 0 deletions tket/src/Utils/include/Utils/SequencedContainers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,23 @@
namespace tket {

struct TagKey {};
struct TagValue {};
struct TagSeq {};

template <typename A, typename B>
using sequenced_bimap_t = boost::multi_index::multi_index_container<
std::pair<A, B>,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::tag<TagKey>,
boost::multi_index::member<
std::pair<A, B>, A, &std::pair<A, B>::first>>,
boost::multi_index::ordered_unique<
boost::multi_index::tag<TagValue>,
boost::multi_index::member<
std::pair<A, B>, B, &std::pair<A, B>::second>>,
boost::multi_index::sequenced<boost::multi_index::tag<TagSeq>>>>;

template <typename A, typename B>
using sequenced_map_t = boost::multi_index::multi_index_container<
std::pair<A, B>,
Expand Down