Skip to content

Commit

Permalink
adding Disjoint2qBlocks layering (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
EliasLF authored Feb 26, 2023
1 parent e30f48e commit 3f59866
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
11 changes: 8 additions & 3 deletions include/Mapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ class Mapper {
*
* Layering::IndividualGates/Layering::None -> each gate on separate layer
* Layering::DisjointQubits -> each layer contains gates only acting on a
* disjoint set of qubits Layering::OddGates -> always 2 gates per layer
* disjoint set of qubits
* Layering::OddGates -> always 2 gates per layer
* (assigned by order of original gate index in the circuit)
* Layering::QubitTriangle -> intended for architectures which contain
* triangles of physical qubits, each layer only contains gates acting on 3
* distinct qubits
* Layering::Disjoint2qBlocks -> each layer contains 2Q-Blocks only acting on
* a disjoint set of qubits
*/
virtual void createLayers();

Expand All @@ -117,12 +120,14 @@ class Mapper {
* @param lastLayer the array storing the last layer each qubit is used in
* @param control the (potential) control qubit of the gate
* @param target the target qubit of the gate
* @param gate the gate to be added to the layerh
* @param gate the gate to be added to the layer
* @param collect2qBlocks if true, gates are collected in 2Q-blocks, and
* layering is performed on these blocks
*/
void processDisjointQubitLayer(
std::array<std::optional<std::size_t>, MAX_DEVICE_QUBITS>& lastLayer,
const std::optional<std::uint16_t>& control, std::uint16_t target,
qc::Operation* gate);
qc::Operation* gate, bool collect2qBlocks);

/**
* @brief Get the index of the next layer after the given index containing a
Expand Down
8 changes: 7 additions & 1 deletion include/configuration/Layering.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ enum class Layering {
IndividualGates,
DisjointQubits,
OddGates,
QubitTriangle
QubitTriangle,
Disjoint2qBlocks
};

[[maybe_unused]] static inline std::string toString(const Layering strategy) {
Expand All @@ -25,6 +26,8 @@ enum class Layering {
return "odd_gates";
case Layering::QubitTriangle:
return "qubit_triangle";
case Layering::Disjoint2qBlocks:
return "disjoint_2q_blocks";
case Layering::None:
return "none";
}
Expand All @@ -48,5 +51,8 @@ layeringFromString(const std::string& layering) {
if (layering == "qubit_triangle" || layering == "4") {
return Layering::QubitTriangle;
}
if (layering == "disjoint_2q_blocks" || layering == "5") {
return Layering::Disjoint2qBlocks;
}
throw std::invalid_argument("Invalid layering value: " + layering);
}
1 change: 1 addition & 0 deletions mqt/qmap/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ PYBIND11_MODULE(pyqmap, m) {
.value("disjoint_qubits", Layering::DisjointQubits)
.value("odd_gates", Layering::OddGates)
.value("qubit_triangle", Layering::QubitTriangle)
.value("disjoint_2q_blocks", Layering::Disjoint2qBlocks)
.export_values()
// allow construction from string
.def(py::init([](const std::string& str) -> Layering {
Expand Down
1 change: 1 addition & 0 deletions mqt/qmap/pyqmap.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class Layering:
individual_gates: ClassVar[Layering] = ...
odd_gates: ClassVar[Layering] = ...
qubit_triangle: ClassVar[Layering] = ...
disjoint_2q_blocks: ClassVar[Layering] = ...
@overload
def __init__(self, value: int) -> None: ...
@overload
Expand Down
33 changes: 27 additions & 6 deletions src/Mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ Mapper::Mapper(const qc::QuantumComputation& quantumComputation,
void Mapper::processDisjointQubitLayer(
std::array<std::optional<std::size_t>, MAX_DEVICE_QUBITS>& lastLayer,
const std::optional<std::uint16_t>& control, const std::uint16_t target,
qc::Operation* gate) {
qc::Operation* gate, bool collect2qBlocks) {
std::size_t layer = 0;
if (!control.has_value()) {
if (!lastLayer.at(target).has_value()) {
layer = 0;
} else {
layer = *lastLayer.at(target) + 1;
if (lastLayer.at(target).has_value()) {
layer = *lastLayer.at(target);
// single qubit gates can always be added to the last 2Q block
if (!collect2qBlocks) {
layer++;
}
}
if (!collect2qBlocks) {
lastLayer.at(target) = layer;
}
lastLayer.at(target) = layer;
} else {
Expand All @@ -53,6 +58,19 @@ void Mapper::processDisjointQubitLayer(
layer = *lastLayer.at(*control) + 1;
} else {
layer = std::max(*lastLayer.at(*control), *lastLayer.at(target)) + 1;

if (collect2qBlocks &&
(*lastLayer.at(*control) == *lastLayer.at(target))) {
for (auto& g : layers.at(layer - 1)) {
if ((g.control == *control && g.target == target) ||
(g.control == target && g.target == *control)) {
// if last layer contained gate with equivalent qubit set, use that
// layer
layer--;
break;
}
}
}
}
lastLayer.at(*control) = layer;
lastLayer.at(target) = layer;
Expand Down Expand Up @@ -116,7 +134,10 @@ void Mapper::createLayers() {
}
break;
case Layering::DisjointQubits:
processDisjointQubitLayer(lastLayer, control, target, gate.get());
processDisjointQubitLayer(lastLayer, control, target, gate.get(), false);
break;
case Layering::Disjoint2qBlocks:
processDisjointQubitLayer(lastLayer, control, target, gate.get(), true);
break;
case Layering::OddGates:
// every other gate is put in a new layer
Expand Down
14 changes: 14 additions & 0 deletions test/test_exact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ TEST_P(ExactTest, DisjointQubits) {
SUCCEED() << "Mapping successful";
}

TEST_P(ExactTest, Disjoint2qBlocks) {
settings.layering = Layering::Disjoint2qBlocks;
ibmqYorktownMapper->map(settings);
ibmqYorktownMapper->dumpResult(GetParam() +
"_exact_yorktown_disjoint_2q.qasm");
ibmqYorktownMapper->printResult(std::cout);

ibmqLondonMapper->map(settings);
ibmqLondonMapper->dumpResult(GetParam() + "_exact_london_disjoint_2q.qasm");
ibmqLondonMapper->printResult(std::cout);
SUCCEED() << "Mapping successful";
}

TEST_P(ExactTest, OddGates) {
settings.layering = Layering::OddGates;
ibmqYorktownMapper->map(settings);
Expand Down Expand Up @@ -353,6 +366,7 @@ TEST_P(ExactTest, toStringMethods) {

EXPECT_EQ(toString(Layering::IndividualGates), "individual_gates");
EXPECT_EQ(toString(Layering::DisjointQubits), "disjoint_qubits");
EXPECT_EQ(toString(Layering::Disjoint2qBlocks), "disjoint_2q_blocks");
EXPECT_EQ(toString(Layering::OddGates), "odd_gates");
EXPECT_EQ(toString(Layering::QubitTriangle), "qubit_triangle");
EXPECT_EQ(toString(Layering::None), "none");
Expand Down
11 changes: 10 additions & 1 deletion test/test_heuristic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,16 @@ TEST_P(HeuristicTest16Q, Disjoint) {
Configuration settings{};
settings.layering = Layering::DisjointQubits;
ibmQX5Mapper->map(settings);
ibmQX5Mapper->dumpResult(GetParam() + "_heuristic_qx5_dynamic.qasm");
ibmQX5Mapper->dumpResult(GetParam() + "_heuristic_qx5_disjoint.qasm");
ibmQX5Mapper->printResult(std::cout);
SUCCEED() << "Mapping successful";
}

TEST_P(HeuristicTest16Q, Disjoint2qBlocks) {
Configuration settings{};
settings.layering = Layering::Disjoint2qBlocks;
ibmQX5Mapper->map(settings);
ibmQX5Mapper->dumpResult(GetParam() + "_heuristic_qx5_disjoint_2q.qasm");
ibmQX5Mapper->printResult(std::cout);
SUCCEED() << "Mapping successful";
}
Expand Down

0 comments on commit 3f59866

Please sign in to comment.