Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 1707ed7

Browse files
authored
Adjacency matrix (#48)
* Add definition of Mat2. * Made access to Vertices and Edges in Diagrams const. * Added method to get all vertices connected to set of vertices. * Added method to check if vertex is in vector of vertices. * Added Test new methods.
1 parent b01ba5e commit 1707ed7

File tree

7 files changed

+113
-38
lines changed

7 files changed

+113
-38
lines changed

include/Definitions.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ namespace zx {
3636
return msg.c_str();
3737
}
3838
};
39+
40+
using gf2Mat = std::vector<std::vector<bool>>;
41+
using gf2Vec = std::vector<bool>;
3942
} // namespace zx

include/Utils.hpp

+26-26
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,23 @@ namespace zx {
3737
class Vertices {
3838
public:
3939
explicit Vertices(
40-
std::vector<std::optional<VertexData>>& vertices):
40+
const std::vector<std::optional<VertexData>>& vertices):
4141
vertices(vertices){};
4242

4343
class VertexIterator {
4444
public:
4545
using iterator_category = std::forward_iterator_tag;
4646
using difference_type = std::int32_t;
47-
using value_type = std::pair<Vertex, VertexData&>;
47+
using value_type = std::pair<Vertex, const VertexData&>;
4848
using pointer = value_type*;
4949
using reference = value_type&;
5050

51-
explicit VertexIterator(std::vector<std::optional<VertexData>>& vertices):
51+
explicit VertexIterator(const std::vector<std::optional<VertexData>>& vertices):
5252
currentPos(vertices.begin()), vertices(vertices) {
5353
nextValidVertex();
5454
}
55-
VertexIterator(std::vector<std::optional<VertexData>>& vertices,
56-
Vertex v);
55+
VertexIterator(const std::vector<std::optional<VertexData>>& vertices,
56+
Vertex v);
5757

5858
value_type operator*() const { return {v, currentPos->value()}; }
5959
// pointer operator->() { return ptr; }
@@ -70,26 +70,26 @@ namespace zx {
7070
const VertexIterator& b);
7171

7272
private:
73-
Vertex v = 0;
74-
std::vector<std::optional<VertexData>>::iterator currentPos;
75-
std::vector<std::optional<VertexData>>& vertices;
73+
Vertex v = 0;
74+
std::vector<std::optional<VertexData>>::const_iterator currentPos;
75+
const std::vector<std::optional<VertexData>>& vertices;
7676

7777
void nextValidVertex();
7878
};
7979

8080
using iterator = VertexIterator;
8181

82-
iterator begin() { return VertexIterator(vertices); }
83-
iterator end() { return {vertices, vertices.size()}; }
82+
const iterator begin() { return VertexIterator(vertices); }
83+
const iterator end() { return {vertices, vertices.size()}; }
8484

8585
private:
86-
std::vector<std::optional<VertexData>>& vertices;
86+
const std::vector<std::optional<VertexData>>& vertices;
8787
};
8888

8989
class Edges {
9090
public:
91-
Edges(std::vector<std::vector<Edge>>& edges,
92-
std::vector<std::optional<VertexData>>& vertices):
91+
Edges(const std::vector<std::vector<Edge>>& edges,
92+
const std::vector<std::optional<VertexData>>& vertices):
9393
edges(edges),
9494
vertices(vertices){};
9595

@@ -101,11 +101,11 @@ namespace zx {
101101
using pointer = value_type*;
102102
using reference = value_type&;
103103

104-
EdgeIterator(std::vector<std::vector<Edge>>& edges,
105-
std::vector<std::optional<VertexData>>& vertices);
104+
EdgeIterator(const std::vector<std::vector<Edge>>& edges,
105+
const std::vector<std::optional<VertexData>>& vertices);
106106

107-
EdgeIterator(std::vector<std::vector<Edge>>& edges,
108-
std::vector<std::optional<VertexData>>& vertices, Vertex v);
107+
EdgeIterator(const std::vector<std::vector<Edge>>& edges,
108+
const std::vector<std::optional<VertexData>>& vertices, Vertex v);
109109

110110
value_type operator*() const { return {v, currentPos->to}; }
111111
// pointer operator->() { return ptr; }
@@ -120,23 +120,23 @@ namespace zx {
120120
friend bool operator!=(const EdgeIterator& a, const EdgeIterator& b);
121121

122122
private:
123-
Vertex v;
124-
std::vector<Edge>::iterator currentPos;
125-
std::vector<std::vector<Edge>>::iterator edgesPos;
126-
std::vector<std::vector<Edge>>& edges;
127-
std::vector<std::optional<VertexData>>& vertices;
123+
Vertex v;
124+
std::vector<Edge>::const_iterator currentPos;
125+
std::vector<std::vector<Edge>>::const_iterator edgesPos;
126+
const std::vector<std::vector<Edge>>& edges;
127+
const std::vector<std::optional<VertexData>>& vertices;
128128

129129
void checkNextVertex();
130130
};
131131

132132
using iterator = EdgeIterator;
133133

134-
iterator begin() { return {edges, vertices}; }
135-
iterator end() { return {edges, vertices, edges.size()}; }
134+
const iterator begin() { return {edges, vertices}; }
135+
const iterator end() { return {edges, vertices, edges.size()}; }
136136

137137
private:
138-
std::vector<std::vector<Edge>>& edges;
139-
std::vector<std::optional<VertexData>>& vertices;
138+
const std::vector<std::vector<Edge>>& edges;
139+
const std::vector<std::optional<VertexData>>& vertices;
140140
};
141141

142142
bool isPauli(const PiExpression& expr);

include/ZXDiagram.hpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ namespace zx {
6161
return vertices[v];
6262
}
6363

64-
[[nodiscard]] std::vector<std::pair<Vertex, VertexData&>> getVertices();
65-
[[nodiscard]] std::vector<std::pair<Vertex, Vertex>> getEdges();
64+
[[nodiscard]] std::vector<std::pair<Vertex, const VertexData&>> getVertices() const;
65+
[[nodiscard]] std::vector<std::pair<Vertex, Vertex>> getEdges() const;
6666

6767
[[nodiscard]] const std::vector<Vertex>& getInputs() const {
6868
return inputs;
@@ -123,6 +123,9 @@ namespace zx {
123123
[[nodiscard]] bool globalPhaseIsZero() const {
124124
return globalPhase.isZero();
125125
}
126+
gf2Mat getAdjMat() const;
127+
std::vector<Vertex> getConnectedSet(const std::vector<Vertex>& s, const std::vector<Vertex>& exclude = {}) const;
128+
static bool isIn(const Vertex& v, const std::vector<Vertex>& vertices);
126129

127130
private:
128131
std::vector<std::vector<Edge>> edges;

src/Utils.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace zx {
66
Vertices::VertexIterator::VertexIterator(
7-
std::vector<std::optional<VertexData>>& vertices, const Vertex v):
7+
const std::vector<std::optional<VertexData>>& vertices, const Vertex v):
88
v(v),
99
currentPos(vertices.begin()), vertices(vertices) {
1010
if (v >= vertices.size()) {
@@ -49,8 +49,8 @@ namespace zx {
4949
}
5050

5151
Edges::EdgeIterator::EdgeIterator(
52-
std::vector<std::vector<Edge>>& edges,
53-
std::vector<std::optional<VertexData>>& vertices):
52+
const std::vector<std::vector<Edge>>& edges,
53+
const std::vector<std::optional<VertexData>>& vertices):
5454
v(0),
5555
currentPos(edges[0].begin()), edgesPos(edges.begin()), edges(edges), vertices(vertices) {
5656
if (!vertices.empty()) {
@@ -68,8 +68,8 @@ namespace zx {
6868
}
6969

7070
Edges::EdgeIterator::EdgeIterator(
71-
std::vector<std::vector<Edge>>& edges,
72-
std::vector<std::optional<VertexData>>& vertices, const Vertex v):
71+
const std::vector<std::vector<Edge>>& edges,
72+
const std::vector<std::optional<VertexData>>& vertices, const Vertex v):
7373
v(v),
7474
edges(edges), vertices(vertices) {
7575
if (v >= edges.size()) {

src/ZXDiagram.cpp

+39-3
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,14 @@ namespace zx {
162162
return edge;
163163
}
164164

165-
[[nodiscard]] std::vector<std::pair<Vertex, VertexData&>>
166-
ZXDiagram::getVertices() {
165+
[[nodiscard]] std::vector<std::pair<Vertex, const VertexData&>>
166+
ZXDiagram::getVertices() const {
167167
Vertices verts(vertices);
168+
168169
return {verts.begin(), verts.end()};
169170
}
170171

171-
[[nodiscard]] std::vector<std::pair<Vertex, Vertex>> ZXDiagram::getEdges() {
172+
[[nodiscard]] std::vector<std::pair<Vertex, Vertex>> ZXDiagram::getEdges() const {
172173
Edges es(edges, vertices);
173174
return {es.begin(), es.end()};
174175
}
@@ -369,4 +370,39 @@ namespace zx {
369370
globalPhase += phase;
370371
}
371372

373+
gf2Mat ZXDiagram::getAdjMat() const {
374+
gf2Mat adjMat{nvertices, gf2Vec(nvertices, false)};
375+
for (const auto& [from, to]: getEdges()) {
376+
adjMat[from][to] = true;
377+
adjMat[to][from] = true;
378+
}
379+
for (std::size_t i = 0; i < adjMat.size(); ++i) {
380+
adjMat[i][i] = true;
381+
}
382+
return adjMat;
383+
}
384+
385+
std::vector<Vertex> ZXDiagram::getConnectedSet(const std::vector<Vertex>& s, const std::vector<Vertex>& exclude) const {
386+
std::vector<Vertex> connected;
387+
for (const auto v: s) {
388+
for (const auto& [to, _]: edges[v]) {
389+
if (isIn(to, exclude))
390+
continue;
391+
392+
const auto& p = std::lower_bound(connected.begin(), connected.end(), to);
393+
if (p == connected.end()) {
394+
connected.emplace_back(to);
395+
continue;
396+
}
397+
if (*p != to) {
398+
connected.insert(p, to);
399+
}
400+
}
401+
}
402+
return connected;
403+
}
404+
405+
bool ZXDiagram::isIn(const Vertex& v, const std::vector<Vertex>& vertices) {
406+
return std::find(vertices.begin(), vertices.end(), v) != vertices.end();
407+
}
372408
} // namespace zx

test/test_expression.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,6 @@ TEST_F(ExpressionTest, Instantiation) {
193193
EXPECT_PRED_FORMAT2(testing::FloatLE, e.evaluate(assignment), 5.0);
194194

195195
e += z;
196-
197-
EXPECT_THROW(e.evaluate(assignment), sym::SymbolicException);
196+
[[maybe_unused]] double h;
197+
EXPECT_THROW(h = e.evaluate(assignment), sym::SymbolicException);
198198
}

test/test_zx.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,36 @@ TEST_F(ZXDiagramTest, RemoveScalarSubDiagram) {
217217
EXPECT_TRUE(idWithScal.isDeleted(v));
218218
EXPECT_TRUE(idWithScal.isDeleted(w));
219219
}
220+
221+
TEST_F(ZXDiagramTest, AdjMat) {
222+
zx::ZXDiagram diag(3);
223+
224+
const auto& adj = diag.getAdjMat();
225+
226+
for (const auto& [v, _]: diag.getVertices()) {
227+
for (const auto& [w, _]: diag.getVertices()) {
228+
if (diag.connected(v, w) || v == w) {
229+
EXPECT_TRUE(adj[v][w]);
230+
EXPECT_TRUE(adj[w][v]);
231+
} else {
232+
EXPECT_FALSE(adj[v][w]);
233+
EXPECT_FALSE(adj[w][v]);
234+
}
235+
}
236+
}
237+
}
238+
239+
TEST_F(ZXDiagramTest, ConnectedSet) {
240+
zx::ZXDiagram diag(3);
241+
auto connected = diag.getConnectedSet(diag.getInputs());
242+
243+
for (const auto& v: connected) {
244+
EXPECT_TRUE(diag.isIn(v, diag.getOutputs()));
245+
}
246+
247+
connected = diag.getConnectedSet(diag.getInputs(), {4});
248+
249+
EXPECT_TRUE(diag.isIn(3, connected));
250+
EXPECT_FALSE(diag.isIn(4, connected));
251+
EXPECT_TRUE(diag.isIn(5, connected));
252+
}

0 commit comments

Comments
 (0)