Skip to content

Commit 7f38148

Browse files
authored
Dijkstra arbitrary weights (#269)
1 parent 6e8ab7a commit 7f38148

File tree

5 files changed

+64
-30
lines changed

5 files changed

+64
-30
lines changed

include/Architecture.hpp

+10-13
Original file line numberDiff line numberDiff line change
@@ -364,21 +364,18 @@ class Architecture {
364364
void createDistanceTable();
365365
void createFidelityTable();
366366

367-
static double costHeuristicBidirectional(const Dijkstra::Node& node) {
368-
auto length = node.cost - 1;
367+
static double dijkstraNodeToCost(const Dijkstra::Node& node) {
368+
// Dijkstra determines the minimal path cost from one physical qubit to
369+
// another. In the non-fidelity case we are only interested in swapping 2
370+
// logical qubits next to each other. Therefore the last swap cost has to
371+
// be ignored. That cost is stored in the field `node.prevCost` of each
372+
// node.
369373
if (node.containsCorrectEdge) {
370-
return length * COST_BIDIRECTIONAL_SWAP;
374+
return node.prevCost;
371375
}
372-
throw QMAPException("In a bidrectional architecture it should not happen "
373-
"that a node does not contain the right edge.");
374-
}
375-
376-
static double costHeuristicUnidirectional(const Dijkstra::Node& node) {
377-
auto length = node.cost - 1;
378-
if (node.containsCorrectEdge) {
379-
return length * COST_UNIDIRECTIONAL_SWAP;
380-
}
381-
return length * COST_UNIDIRECTIONAL_SWAP + COST_DIRECTION_REVERSE;
376+
// in case the last edge is a back-edge, we will need to reverse the CNOT,
377+
// executed on that edge
378+
return node.prevCost + COST_DIRECTION_REVERSE;
382379
}
383380

384381
// added for teleportation

include/utils.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,16 @@ class Dijkstra {
5858
bool visited = false;
5959
std::optional<std::uint16_t> pos = std::nullopt;
6060
double cost = -1.;
61+
double prevCost = -1.;
6162
};
6263

6364
static void buildTable(std::uint16_t n, const CouplingMap& couplingMap,
64-
Matrix& distanceTable,
65+
Matrix& distanceTable, const Matrix& edgeWeights,
6566
const std::function<double(const Node&)>& cost);
6667

6768
protected:
6869
static void dijkstra(const CouplingMap& couplingMap, std::vector<Node>& nodes,
69-
std::uint16_t start);
70+
std::uint16_t start, const Matrix& edgeWeights);
7071

7172
struct NodeComparator {
7273
bool operator()(const Node* x, const Node* y) {

src/Architecture.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,21 @@ Architecture::Architecture(const std::uint16_t nQ, const CouplingMap& cm,
185185
}
186186

187187
void Architecture::createDistanceTable() {
188+
isBidirectional = true;
189+
Matrix edgeWeights(nqubits, std::vector<double>(
190+
nqubits, std::numeric_limits<double>::max()));
188191
for (const auto& edge : couplingMap) {
189192
if (couplingMap.find({edge.second, edge.first}) == couplingMap.end()) {
190-
isBidirectional = false;
191-
break;
193+
isBidirectional = false;
194+
edgeWeights.at(edge.second).at(edge.first) = COST_UNIDIRECTIONAL_SWAP;
195+
edgeWeights.at(edge.first).at(edge.second) = COST_UNIDIRECTIONAL_SWAP;
196+
} else {
197+
edgeWeights.at(edge.first).at(edge.second) = COST_BIDIRECTIONAL_SWAP;
192198
}
193199
}
194200

195-
if (isBidirectional) {
196-
Dijkstra::buildTable(nqubits, couplingMap, distanceTable,
197-
Architecture::costHeuristicBidirectional);
198-
} else {
199-
Dijkstra::buildTable(nqubits, couplingMap, distanceTable,
200-
Architecture::costHeuristicUnidirectional);
201-
}
201+
Dijkstra::buildTable(nqubits, couplingMap, distanceTable, edgeWeights,
202+
Architecture::dijkstraNodeToCost);
202203
}
203204

204205
void Architecture::createFidelityTable() {

src/utils.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <cassert>
99

1010
void Dijkstra::buildTable(const std::uint16_t n, const CouplingMap& couplingMap,
11-
Matrix& distanceTable,
11+
Matrix& distanceTable, const Matrix& edgeWeights,
1212
const std::function<double(const Node&)>& cost) {
1313
distanceTable.clear();
1414
distanceTable.resize(n, std::vector<double>(n, -1.));
@@ -20,11 +20,13 @@ void Dijkstra::buildTable(const std::uint16_t n, const CouplingMap& couplingMap,
2020
nodes.at(j).visited = false;
2121
nodes.at(j).pos = j;
2222
nodes.at(j).cost = -1.;
23+
nodes.at(j).prevCost = -1.;
2324
}
2425

25-
nodes.at(i).cost = 0.;
26+
nodes.at(i).cost = 0.;
27+
nodes.at(i).prevCost = 0.;
2628

27-
dijkstra(couplingMap, nodes, i);
29+
dijkstra(couplingMap, nodes, i, edgeWeights);
2830

2931
for (std::uint16_t j = 0; j < n; ++j) {
3032
if (i == j) {
@@ -37,7 +39,8 @@ void Dijkstra::buildTable(const std::uint16_t n, const CouplingMap& couplingMap,
3739
}
3840

3941
void Dijkstra::dijkstra(const CouplingMap& couplingMap,
40-
std::vector<Node>& nodes, std::uint16_t start) {
42+
std::vector<Node>& nodes, std::uint16_t start,
43+
const Matrix& edgeWeights) {
4144
std::priority_queue<Node*, std::vector<Node*>, NodeComparator> queue{};
4245
queue.push(&nodes.at(start));
4346
while (!queue.empty()) {
@@ -61,8 +64,9 @@ void Dijkstra::dijkstra(const CouplingMap& couplingMap,
6164
}
6265

6366
Node newNode;
64-
newNode.cost = current->cost + 1.0;
65-
newNode.pos = to;
67+
newNode.cost = current->cost + edgeWeights.at(*pos).at(*to);
68+
newNode.prevCost = current->cost;
69+
newNode.pos = to;
6670
newNode.containsCorrectEdge = correctEdge;
6771
if (nodes.at(*to).cost < 0 || newNode < nodes.at(*to)) {
6872
nodes.at(*to) = newNode;

test/test_general.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//
55

66
#include "Architecture.hpp"
7+
#include "utils.hpp"
78

89
#include "gtest/gtest.h"
910
#include <iostream>
@@ -52,3 +53,33 @@ TEST(General, TestLineParsing) {
5253
EXPECT_EQ(data[1], "Entry2");
5354
EXPECT_EQ(data[2], "EscapedEntry1;EscapedEntry2");
5455
}
56+
57+
TEST(General, Dijkstra) {
58+
/*
59+
(6)
60+
.----------.
61+
\/ \/
62+
0 <-> 1 --> 2 <-> 3
63+
(1) (2) (3)
64+
*/
65+
66+
const CouplingMap cm = {{0, 1}, {1, 0}, {1, 2}, {2, 3},
67+
{3, 2}, {1, 3}, {3, 1}};
68+
69+
const Matrix edgeWeights = {
70+
{0, 1, 0, 0}, {1, 0, 2, 6}, {0, 15, 0, 3}, {0, 6, 3, 0}};
71+
72+
const Matrix targetTable1 = {
73+
{0, 1, 3, 6}, {1, 0, 2, 5}, {10, 9, 0, 3}, {7, 6, 3, 0}};
74+
Matrix distanceTable{};
75+
Dijkstra::buildTable(4, cm, distanceTable, edgeWeights,
76+
[](const Dijkstra::Node& n) { return n.cost; });
77+
EXPECT_EQ(distanceTable, targetTable1);
78+
79+
const Matrix targetTable2 = {
80+
{0, 0, 1, 3}, {0, 0, 0, 2}, {9, 3, 0, 0}, {6, 0, 0, 0}};
81+
distanceTable = {};
82+
Dijkstra::buildTable(4, cm, distanceTable, edgeWeights,
83+
[](const Dijkstra::Node& n) { return n.prevCost; });
84+
EXPECT_EQ(distanceTable, targetTable2);
85+
}

0 commit comments

Comments
 (0)