Skip to content

Commit 1f5ca91

Browse files
fajlipFSB
and
FSB
authored
Adds deterministic version for boruvka and dijkstra algorithm. (#398)
* Adds deterministic version for boruvka and dijkstra algorithm. * Add unit tests for deterministic boruvka and dijkstra. --------- Co-authored-by: FSB <f.brezna@era.aero>
1 parent ae58ab4 commit 1f5ca91

File tree

5 files changed

+1438
-0
lines changed

5 files changed

+1438
-0
lines changed

include/CXXGraph/Graph/Algorithm/Boruvka_impl.hpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,104 @@ const MstResult Graph<T>::boruvka() const {
123123
return result;
124124
}
125125

126+
template <typename T>
127+
const MstResult Graph<T>::boruvka_deterministic() const {
128+
MstResult result;
129+
result.success = false;
130+
result.errorMessage = "";
131+
result.mstCost = INF_DOUBLE;
132+
if (!isUndirectedGraph()) {
133+
result.errorMessage = ERR_DIR_GRAPH;
134+
return result;
135+
}
136+
const auto nodeSet = Graph<T>::getNodeSet();
137+
const auto n = nodeSet.size();
138+
139+
// Use std map for storing n subsets.
140+
auto subsets = make_shared<std::unordered_map<CXXGraph::id_t, Subset>>();
141+
142+
// Initially there are n different trees.
143+
// Finally there will be one tree that will be MST
144+
auto numTrees = n;
145+
146+
// check if all edges are weighted and store the weights
147+
// in a map whose keys are the edge ids and values are the edge weights
148+
const auto edgeSet = Graph<T>::getEdgeSet();
149+
std::unordered_map<CXXGraph::id_t, double> edgeWeight;
150+
for (const auto &edge : edgeSet) {
151+
if (edge->isWeighted().has_value() && edge->isWeighted().value())
152+
edgeWeight[edge->getId()] =
153+
(std::dynamic_pointer_cast<const Weighted>(edge))->getWeight();
154+
else {
155+
// No Weighted Edge
156+
result.errorMessage = ERR_NO_WEIGHTED_EDGE;
157+
return result;
158+
}
159+
}
160+
161+
for (const auto &node : nodeSet) {
162+
Subset set{node->getId(), 0};
163+
(*subsets)[node->getId()] = set;
164+
}
165+
166+
result.mstCost = 0; // we will store the cost here
167+
// exit when only 1 tree i.e. mst
168+
while (numTrees > 1) {
169+
// Everytime initialize cheapest map
170+
// It stores index of the cheapest edge of subset.
171+
std::unordered_map<CXXGraph::id_t, CXXGraph::id_t> cheapest;
172+
for (const auto &node : nodeSet) cheapest[node->getId()] = INT_MAX;
173+
174+
// Traverse through all edges and update
175+
// cheapest of every component
176+
for (const auto &edge : edgeSet) {
177+
auto elem = edge->getNodePair();
178+
auto edgeId = edge->getId();
179+
// Find sets of two corners of current edge
180+
auto set1 = Graph<T>::setFind(subsets, elem.first->getId());
181+
auto set2 = Graph<T>::setFind(subsets, elem.second->getId());
182+
183+
// If two corners of current edge belong to
184+
// same set, ignore current edge
185+
if (set1 == set2) continue;
186+
187+
// Else check if current edge is closer to previous
188+
// cheapest edges of set1 and set2
189+
if (cheapest[set1] == INT_MAX ||
190+
(edgeWeight[cheapest[set1]] > edgeWeight[edgeId]) ||
191+
(edgeWeight[cheapest[set1]] == edgeWeight[edgeId] && cheapest[set1] > edgeId)
192+
)
193+
cheapest[set1] = edgeId;
194+
195+
if (cheapest[set2] == INT_MAX ||
196+
(edgeWeight[cheapest[set2]] > edgeWeight[edgeId]) ||
197+
(edgeWeight[cheapest[set2]] == edgeWeight[edgeId] && cheapest[set2] > edgeId)
198+
)
199+
cheapest[set2] = edgeId;
200+
}
201+
202+
// iterate over all the vertices and add picked
203+
// cheapest edges to MST
204+
for (const auto &[nodeId, edgeId] : cheapest) {
205+
// Check if cheapest for current set exists
206+
if (edgeId != INT_MAX) {
207+
auto cheapestNode = Graph<T>::getEdge(edgeId).value()->getNodePair();
208+
auto set1 = Graph<T>::setFind(subsets, cheapestNode.first->getId());
209+
auto set2 = Graph<T>::setFind(subsets, cheapestNode.second->getId());
210+
if (set1 == set2) continue;
211+
result.mstCost += edgeWeight[edgeId];
212+
auto newEdgeMST = std::make_pair(cheapestNode.first->getUserId(),
213+
cheapestNode.second->getUserId());
214+
result.mst.push_back(newEdgeMST);
215+
// take union of set1 and set2 and decrease number of trees
216+
Graph<T>::setUnion(subsets, set1, set2);
217+
numTrees--;
218+
}
219+
}
220+
}
221+
result.success = true;
222+
return result;
223+
}
224+
126225
} // namespace CXXGraph
127226
#endif // __CXXGRAPH_BORUVKA_IMPL_H__

0 commit comments

Comments
 (0)