Skip to content

Commit db70f18

Browse files
authored
Tests & Thread safe dijkstra (#93)
* explicitly use Graph implementation instead of Graph_TS * add thread-safe tests for dijkstra * use graph instead of graph_ts in other algorithms as well * add tests for thread safe bellman-ford * add tests for thread safe bfs, floyd-warshall, graph slicing and prim algorithm
1 parent 2332352 commit db70f18

File tree

7 files changed

+258
-31
lines changed

7 files changed

+258
-31
lines changed

include/Graph/Graph.hpp

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ namespace CXXGRAPH
898898
result.success = false;
899899
result.errorMessage = "";
900900
result.result = INF_DOUBLE;
901-
auto nodeSet = getNodeSet();
901+
auto nodeSet = Graph<T>::getNodeSet();
902902
if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
903903
{
904904
// check if source node exist in the graph
@@ -911,7 +911,7 @@ namespace CXXGRAPH
911911
result.errorMessage = ERR_TARGET_NODE_NOT_IN_GRAPH;
912912
return result;
913913
}
914-
const AdjacencyMatrix<T> adj = getAdjMatrix();
914+
const AdjacencyMatrix<T> adj = Graph<T>::getAdjMatrix();
915915
// n denotes the number of vertices in graph
916916
int n = adj.size();
917917

@@ -1008,7 +1008,7 @@ namespace CXXGRAPH
10081008
result.success = false;
10091009
result.errorMessage = "";
10101010
result.result = INF_DOUBLE;
1011-
auto nodeSet = getNodeSet();
1011+
auto nodeSet = Graph<T>::getNodeSet();
10121012
if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
10131013
{
10141014
// check if source node exist in the graph
@@ -1039,7 +1039,7 @@ namespace CXXGRAPH
10391039
// outer loop for vertex relaxation
10401040
for (int i=0; i<n-1; i++)
10411041
{
1042-
auto edgeSet = this->getEdgeSet();
1042+
auto edgeSet = Graph<T>::getEdgeSet();
10431043
// inner loop for distance updates of
10441044
// each relaxation
10451045
for (auto edge : edgeSet)
@@ -1079,7 +1079,7 @@ namespace CXXGRAPH
10791079
// check if there exists a negative cycle
10801080
if (!earlyStopping)
10811081
{
1082-
auto edgeSet = this->getEdgeSet();
1082+
auto edgeSet = Graph<T>::getEdgeSet();
10831083
for (auto edge : edgeSet)
10841084
{
10851085
auto elem = edge->getNodePair();
@@ -1114,7 +1114,7 @@ namespace CXXGRAPH
11141114
result.success = false;
11151115
result.errorMessage = "";
11161116
std::map<std::pair<unsigned long, unsigned long>, double> pairwise_dist;
1117-
auto nodeSet = getNodeSet();
1117+
auto nodeSet = Graph<T>::getNodeSet();
11181118
// create a pairwise distance matrix with distance node distances
11191119
// set to inf. Distance of node to itself is set as 0.
11201120
for (auto elem1 : nodeSet)
@@ -1129,7 +1129,7 @@ namespace CXXGRAPH
11291129
}
11301130
}
11311131

1132-
auto edgeSet = this->getEdgeSet();
1132+
auto edgeSet = Graph<T>::getEdgeSet();
11331133
// update the weights of nodes
11341134
// connected by edges
11351135
for (auto edge : edgeSet)
@@ -1199,9 +1199,9 @@ namespace CXXGRAPH
11991199
result.errorMessage = ERR_DIR_GRAPH;
12001200
return result;
12011201
}
1202-
auto nodeSet = getNodeSet();
1202+
auto nodeSet = Graph<T>::getNodeSet();
12031203
auto n = nodeSet.size();
1204-
const AdjacencyMatrix<T> adj = getAdjMatrix();
1204+
const AdjacencyMatrix<T> adj = Graph<T>::getAdjMatrix();
12051205

12061206
// setting all the distances initially to INF_DOUBLE
12071207
std::map<const Node<T> *, double> dist;
@@ -1273,13 +1273,13 @@ namespace CXXGRAPH
12731273
{
12741274
// vector to keep track of visited nodes
12751275
std::vector<Node<T>> visited;
1276-
auto nodeSet = getNodeSet();
1276+
auto nodeSet = Graph<T>::getNodeSet();
12771277
//check is exist node in the graph
12781278
if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
12791279
{
12801280
return visited;
12811281
}
1282-
const AdjacencyMatrix<T> adj = getAdjMatrix();
1282+
const AdjacencyMatrix<T> adj = Graph<T>::getAdjMatrix();
12831283
// queue that stores vertices that need to be further explored
12841284
std::queue<const Node<T> *> tracker;
12851285

@@ -1313,13 +1313,13 @@ namespace CXXGRAPH
13131313
{
13141314
// vector to keep track of visited nodes
13151315
std::vector<Node<T>> visited;
1316-
auto nodeSet = getNodeSet();
1316+
auto nodeSet = Graph<T>::getNodeSet();
13171317
//check is exist node in the graph
13181318
if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
13191319
{
13201320
return visited;
13211321
}
1322-
const AdjacencyMatrix<T> adj = getAdjMatrix();
1322+
const AdjacencyMatrix<T> adj = Graph<T>::getAdjMatrix();
13231323
std::function<void(const AdjacencyMatrix<T> &, const Node<T> &, std::vector<Node<T>> &)> explore;
13241324
explore = [&explore](const AdjacencyMatrix<T> &adj, const Node<T> &node, std::vector<Node<T>> &visited) -> void
13251325
{
@@ -1353,8 +1353,8 @@ namespace CXXGRAPH
13531353
in_stack,
13541354
visited
13551355
};
1356-
auto nodeSet = this->getNodeSet();
1357-
auto adjMatrix = this->getAdjMatrix();
1356+
auto nodeSet = Graph<T>::getNodeSet();
1357+
auto adjMatrix = Graph<T>::getAdjMatrix();
13581358

13591359
/* State of the node.
13601360
*
@@ -1437,8 +1437,8 @@ namespace CXXGRAPH
14371437
{
14381438
return false;
14391439
}
1440-
auto adjMatrix = this->getAdjMatrix();
1441-
auto nodeSet = this->getNodeSet();
1440+
auto adjMatrix = Graph<T>::getAdjMatrix();
1441+
auto nodeSet = Graph<T>::getNodeSet();
14421442

14431443
std::map<unsigned long, unsigned int> indegree;
14441444
for (auto node : nodeSet)
@@ -1467,7 +1467,7 @@ namespace CXXGRAPH
14671467
}
14681468

14691469
// Vertices that need to be traversed.
1470-
auto remain = this->getNodeSet().size();
1470+
auto remain = Graph<T>::getNodeSet().size();
14711471
// While there are safe nodes that we can visit.
14721472
while (!can_be_solved.empty())
14731473
{
@@ -1502,7 +1502,7 @@ namespace CXXGRAPH
15021502
template <typename T>
15031503
bool Graph<T>::isDirectedGraph() const
15041504
{
1505-
auto edgeSet = this->getEdgeSet();
1505+
auto edgeSet = Graph<T>::getEdgeSet();
15061506
for (auto edge : edgeSet)
15071507
{
15081508
if (!(edge->isDirected().has_value() && edge->isDirected().value()))
@@ -1518,7 +1518,7 @@ namespace CXXGRAPH
15181518
template <typename T>
15191519
bool Graph<T>::isUndirectedGraph() const
15201520
{
1521-
auto edgeSet = this->getEdgeSet();
1521+
auto edgeSet = Graph<T>::getEdgeSet();
15221522
for (auto edge : edgeSet)
15231523
{
15241524
if ((edge->isDirected().has_value() && edge->isDirected().value()))
@@ -1537,8 +1537,8 @@ namespace CXXGRAPH
15371537
DialResult result;
15381538
result.success = false;
15391539

1540-
auto adj = getAdjMatrix();
1541-
auto nodeSet = getNodeSet();
1540+
auto adj = Graph<T>::getAdjMatrix();
1541+
auto nodeSet = Graph<T>::getNodeSet();
15421542

15431543
if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
15441544
{
@@ -1664,13 +1664,13 @@ namespace CXXGRAPH
16641664
{
16651665
std::vector<Node<T>> result;
16661666

1667-
std::list<const Node<T> *> nodeSet = getNodeSet();
1667+
std::list<const Node<T> *> nodeSet = Graph<T>::getNodeSet();
16681668
//check if start node in the graph
16691669
if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
16701670
{
16711671
return result;
16721672
}
1673-
std::vector<Node<T>> C = depth_first_search(start);
1673+
std::vector<Node<T>> C = Graph<T>::depth_first_search(start);
16741674
std::list<const Node<T> *> C1; //complement of C i.e. nodeSet - C
16751675
for (auto const node : nodeSet)
16761676
{
@@ -1685,7 +1685,7 @@ namespace CXXGRAPH
16851685
std::vector<Node<T>> M;
16861686
for (auto const node : C1)
16871687
{
1688-
std::vector<Node<T>> reachableNodes = depth_first_search(*node);
1688+
std::vector<Node<T>> reachableNodes = Graph<T>::depth_first_search(*node);
16891689
M.insert(M.end(),reachableNodes.begin(),reachableNodes.end());
16901690
}
16911691
// removes nodes from C that are reachable from M.

test/BFSTest.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ TEST(BFSTest, test_1)
2020
ASSERT_TRUE(std::find(res.begin(), res.end(), node1) != res.end());
2121
ASSERT_TRUE(std::find(res.begin(), res.end(), node2) != res.end());
2222
ASSERT_TRUE(std::find(res.begin(), res.end(), node3) != res.end());
23+
24+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
25+
std::vector<CXXGRAPH::Node<int>> res_ts = graph_ts.breadth_first_search(node1);
26+
ASSERT_EQ(res_ts.size(), 3);
27+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
28+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
29+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
2330
}
2431

2532
TEST(BFSTest, test_2)
@@ -41,6 +48,13 @@ TEST(BFSTest, test_2)
4148
ASSERT_FALSE(std::find(res.begin(), res.end(), node1) != res.end());
4249
ASSERT_TRUE(std::find(res.begin(), res.end(), node2) != res.end());
4350
ASSERT_TRUE(std::find(res.begin(), res.end(), node3) != res.end());
51+
52+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
53+
std::vector<CXXGRAPH::Node<int>> res_ts = graph_ts.breadth_first_search(node2);
54+
ASSERT_EQ(res_ts.size(), 2);
55+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
56+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
57+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
4458
}
4559

4660
TEST(BFSTest, test_3)
@@ -62,6 +76,13 @@ TEST(BFSTest, test_3)
6276
ASSERT_TRUE(std::find(res.begin(), res.end(), node1) != res.end());
6377
ASSERT_TRUE(std::find(res.begin(), res.end(), node2) != res.end());
6478
ASSERT_TRUE(std::find(res.begin(), res.end(), node3) != res.end());
79+
80+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
81+
std::vector<CXXGRAPH::Node<int>> res_ts = graph_ts.breadth_first_search(node2);
82+
ASSERT_EQ(res_ts.size(), 3);
83+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
84+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
85+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
6586
}
6687

6788
TEST(BFSTest, test_4)
@@ -83,6 +104,13 @@ TEST(BFSTest, test_4)
83104
ASSERT_TRUE(std::find(res.begin(), res.end(), node1) != res.end());
84105
ASSERT_TRUE(std::find(res.begin(), res.end(), node2) != res.end());
85106
ASSERT_TRUE(std::find(res.begin(), res.end(), node3) != res.end());
107+
108+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
109+
std::vector<CXXGRAPH::Node<int>> res_ts = graph.breadth_first_search(node3);
110+
ASSERT_EQ(res_ts.size(), 3);
111+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
112+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
113+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
86114
}
87115

88116
TEST(BFSTest, test_5)
@@ -104,6 +132,13 @@ TEST(BFSTest, test_5)
104132
ASSERT_FALSE(std::find(res.begin(), res.end(), node1) != res.end());
105133
ASSERT_FALSE(std::find(res.begin(), res.end(), node2) != res.end());
106134
ASSERT_TRUE(std::find(res.begin(), res.end(), node3) != res.end());
135+
136+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
137+
std::vector<CXXGRAPH::Node<int>> res_ts = graph_ts.breadth_first_search(node3);
138+
ASSERT_EQ(res_ts.size(), 1);
139+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
140+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
141+
ASSERT_TRUE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
107142
}
108143

109144
TEST(BFSTest, test_6)
@@ -127,4 +162,12 @@ TEST(BFSTest, test_6)
127162
ASSERT_FALSE(std::find(res.begin(), res.end(), node2) != res.end());
128163
ASSERT_FALSE(std::find(res.begin(), res.end(), node3) != res.end());
129164
ASSERT_FALSE(std::find(res.begin(), res.end(), node4) != res.end());
165+
166+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
167+
std::vector<CXXGRAPH::Node<int>> res_ts = graph_ts.breadth_first_search(node4);
168+
ASSERT_EQ(res_ts.size(), 0);
169+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node1) != res_ts.end());
170+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node2) != res_ts.end());
171+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node3) != res_ts.end());
172+
ASSERT_FALSE(std::find(res_ts.begin(), res_ts.end(), node4) != res_ts.end());
130173
}

test/BellmanFordTest.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ TEST(BellmanFordTest, test_1)
4343
ASSERT_FALSE(res.negativeCycle);
4444
ASSERT_EQ(res.errorMessage, "");
4545
ASSERT_EQ(res.result, -2);
46+
47+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
48+
CXXGRAPH::BellmanFordResult res_ts = graph_ts.bellmanford(node0, node3);
49+
ASSERT_TRUE(res_ts.success);
50+
ASSERT_FALSE(res_ts.negativeCycle);
51+
ASSERT_EQ(res_ts.errorMessage, "");
52+
ASSERT_EQ(res_ts.result, -2);
4653
}
4754

4855
// a graph with negative cycle
@@ -64,6 +71,13 @@ TEST(BellmanFordTest, test_2)
6471
ASSERT_TRUE(res.negativeCycle);
6572
ASSERT_EQ(res.errorMessage, "");
6673
ASSERT_EQ(res.result, CXXGRAPH::INF_DOUBLE);
74+
75+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
76+
CXXGRAPH::BellmanFordResult res_ts = graph_ts.bellmanford(node0, node2);
77+
ASSERT_TRUE(res_ts.success);
78+
ASSERT_TRUE(res_ts.negativeCycle);
79+
ASSERT_EQ(res_ts.errorMessage, "");
80+
ASSERT_EQ(res_ts.result, CXXGRAPH::INF_DOUBLE);
6781
}
6882

6983
// UndirectedWeightedEdge
@@ -86,6 +100,14 @@ TEST(BellmanFordTest, test_3)
86100
ASSERT_FALSE(res.negativeCycle);
87101
ASSERT_EQ(res.errorMessage, "");
88102
ASSERT_EQ(res.result, 2);
103+
104+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
105+
CXXGRAPH::BellmanFordResult res_ts = graph_ts.bellmanford(node1, node3);
106+
ASSERT_TRUE(res_ts.success);
107+
ASSERT_FALSE(res_ts.negativeCycle);
108+
ASSERT_EQ(res_ts.errorMessage, "");
109+
ASSERT_EQ(res_ts.result, 2);
110+
89111
}
90112

91113
// No weighted edge
@@ -108,6 +130,13 @@ TEST(BellmanFordTest, test_4)
108130
ASSERT_FALSE(res.negativeCycle);
109131
ASSERT_EQ(res.errorMessage, CXXGRAPH::ERR_NO_WEIGHTED_EDGE);
110132
ASSERT_EQ(res.result, CXXGRAPH::INF_DOUBLE);
133+
134+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
135+
CXXGRAPH::BellmanFordResult res_ts = graph_ts.bellmanford(node1, node3);
136+
ASSERT_FALSE(res_ts.success);
137+
ASSERT_FALSE(res_ts.negativeCycle);
138+
ASSERT_EQ(res_ts.errorMessage, CXXGRAPH::ERR_NO_WEIGHTED_EDGE);
139+
ASSERT_EQ(res_ts.result, CXXGRAPH::INF_DOUBLE);
111140
}
112141

113142

@@ -129,21 +158,41 @@ TEST(BellmanFordTest, test_5)
129158
ASSERT_EQ(res.errorMessage, CXXGRAPH::ERR_SOURCE_NODE_NOT_IN_GRAPH);
130159
ASSERT_EQ(res.result, CXXGRAPH::INF_DOUBLE);
131160

161+
CXXGRAPH::Graph_TS<int> graph_ts(edgeSet);
162+
CXXGRAPH::BellmanFordResult res_ts = graph.bellmanford(node3, node1);
163+
ASSERT_FALSE(res_ts.success);
164+
ASSERT_FALSE(res_ts.negativeCycle);
165+
ASSERT_EQ(res_ts.errorMessage, CXXGRAPH::ERR_SOURCE_NODE_NOT_IN_GRAPH);
166+
ASSERT_EQ(res_ts.result, CXXGRAPH::INF_DOUBLE);
167+
132168
res = graph.bellmanford(node1, node3);
133169
ASSERT_FALSE(res.success);
134170
ASSERT_FALSE(res.negativeCycle);
135171
ASSERT_EQ(res.errorMessage, CXXGRAPH::ERR_TARGET_NODE_NOT_IN_GRAPH);
136172
ASSERT_EQ(res.result, CXXGRAPH::INF_DOUBLE);
137173

174+
res_ts = graph_ts.bellmanford(node1, node3);
175+
ASSERT_FALSE(res_ts.success);
176+
ASSERT_FALSE(res_ts.negativeCycle);
177+
ASSERT_EQ(res_ts.errorMessage, CXXGRAPH::ERR_TARGET_NODE_NOT_IN_GRAPH);
178+
ASSERT_EQ(res_ts.result, CXXGRAPH::INF_DOUBLE);
179+
138180
CXXGRAPH::DirectedWeightedEdge<int> edge2(2, node3, node2, 1);
139181
edgeSet.push_back(&edge2);
140-
CXXGRAPH::Graph<int> graph1(edgeSet);
141-
142182

183+
CXXGRAPH::Graph<int> graph1(edgeSet);
143184
res = graph1.bellmanford(node1, node3);
144185
ASSERT_FALSE(res.success);
145186
ASSERT_FALSE(res.negativeCycle);
146187
ASSERT_EQ(res.errorMessage, CXXGRAPH::ERR_TARGET_NODE_NOT_REACHABLE);
147188
ASSERT_EQ(res.result, -1);
189+
190+
CXXGRAPH::Graph<int> graph1_ts(edgeSet);
191+
res_ts = graph1_ts.bellmanford(node1, node3);
192+
ASSERT_FALSE(res_ts.success);
193+
ASSERT_FALSE(res_ts.negativeCycle);
194+
ASSERT_EQ(res_ts.errorMessage, CXXGRAPH::ERR_TARGET_NODE_NOT_REACHABLE);
195+
ASSERT_EQ(res_ts.result, -1);
196+
148197
}
149198

0 commit comments

Comments
 (0)