From 8038d4957a4e82beebfbc97c852e9dbeda321099 Mon Sep 17 00:00:00 2001 From: Sarthak Jain <77235755+sarthak17jain@users.noreply.github.com> Date: Sat, 1 Oct 2022 10:33:49 +0530 Subject: [PATCH 1/2] Update Graph.hpp --- include/Graph/Graph.hpp | 110 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/include/Graph/Graph.hpp b/include/Graph/Graph.hpp index 2f867600c..b25cb5704 100644 --- a/include/Graph/Graph.hpp +++ b/include/Graph/Graph.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -355,6 +356,19 @@ namespace CXXGRAPH * @param start Node from where traversing starts * @return a vector of nodes that belong to C but not to M. */ + + virtual std::vector>> kosaraju() const; + /** + * \brief + * This function performs performs the kosaraju algorthm on the graph to find the strongly connected components. + * + * Mathematical definition of the problem: + * A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. + + * Note: No Thread Safe + * @return a vector of vector of strongly connected components. + */ + virtual const std::vector> graph_slicing(const Node &start) const; /** @@ -1948,6 +1962,102 @@ namespace CXXGRAPH } } + template + std::vector>> Graph::kosaraju() const + { + std::vector>> connectedComps; + + if (!isDirectedGraph()) + { + return connectedComps;//empty vector since for undirected graph strongly connected components do not exist + } + else + { + auto nodeSet = getNodeSet(); + auto adjMatrix = getAdjMatrix(); + // created visited map + std::unordered_map visited; + for (const auto &node : nodeSet) + { + visited[node->getId()] = false; + } + + std::stack *> st; + std::function *)> dfs_helper = [this, &adjMatrix, &visited, &dfs_helper, &st](const Node *source) + { + // mark the vertex visited + visited[source->getId()] = true; + + // travel the neighbors + for (int i = 0; i < adjMatrix[source].size(); i++) + { + const Node *neighbor = adjMatrix[source].at(i).first; + if (visited[neighbor->getId()] == false) + { + // make recursive call from neighbor + dfs_helper(neighbor); + } + } + + st.push(source); + }; + + for (const auto &node : nodeSet) + { + if (visited[node->getId()] == false) + { + dfs_helper(node); + } + } + + //construct the transpose of the given graph + AdjacencyMatrix rev; + auto addElementToAdjMatrix = [&rev](const Node *nodeFrom, const Node *nodeTo, const Edge *edge){ + std::pair *, const Edge *> elem = {nodeTo, edge}; + rev[nodeFrom].push_back(std::move(elem)); + }; + for (const auto &edgeSetIt : edgeSet) + { + const DirectedEdge *d_edge = dynamic_cast *>(edgeSetIt); + //Add the reverse edge to the reverse adjacency matrix + addElementToAdjMatrix(&(d_edge->getTo()), &(d_edge->getFrom()), d_edge); + } + + visited.clear(); + + std::function *, std::vector> &)> dfs_helper1 = [this, &rev, &visited, &dfs_helper1](const Node *source, std::vector> &comp) + { + // mark the vertex visited + visited[source->getId()] = true; + //Add the current vertex to the strongly connected component + comp.push_back(*source); + + // travel the neighbors + for (int i = 0; i < rev[source].size(); i++) + { + const Node *neighbor = rev[source].at(i).first; + if (visited[neighbor->getId()] == false) + { + // make recursive call from neighbor + dfs_helper1(neighbor, comp); + } + } + }; + + while(st.size()!=0){ + auto rem = st.top(); + st.pop(); + if(visited[rem->getId()] == false){ + std::vector> comp; + dfs_helper1(rem, comp); + connectedComps.push_back(comp); + } + } + + return connectedComps; + } + } + template const DialResult Graph::dial(const Node &source, int maxWeight) const { From bdb9d8a2c3fcc86751914f9471151f285f780e16 Mon Sep 17 00:00:00 2001 From: Sarthak Jain <77235755+sarthak17jain@users.noreply.github.com> Date: Mon, 3 Oct 2022 18:42:50 +0530 Subject: [PATCH 2/2] Update Graph.hpp Made the requested changes. Corrected the commenting. Moved the Doxygen documentation before the function declaration and corrected the documentation of the other function that I messed up earlier. --- include/Graph/Graph.hpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/include/Graph/Graph.hpp b/include/Graph/Graph.hpp index b25cb5704..18a766fd1 100644 --- a/include/Graph/Graph.hpp +++ b/include/Graph/Graph.hpp @@ -340,6 +340,18 @@ namespace CXXGRAPH */ virtual bool isStronglyConnectedGraph() const; + /** + * \brief + * This function performs performs the kosaraju algorthm on the graph to find the strongly connected components. + * + * Mathematical definition of the problem: + * A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. + + * Note: No Thread Safe + * @return a vector of vector of strongly connected components. + */ + virtual std::vector>> kosaraju() const; + /** * \brief * This function performs Graph Slicing based on connectivity @@ -356,19 +368,6 @@ namespace CXXGRAPH * @param start Node from where traversing starts * @return a vector of nodes that belong to C but not to M. */ - - virtual std::vector>> kosaraju() const; - /** - * \brief - * This function performs performs the kosaraju algorthm on the graph to find the strongly connected components. - * - * Mathematical definition of the problem: - * A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. - - * Note: No Thread Safe - * @return a vector of vector of strongly connected components. - */ - virtual const std::vector> graph_slicing(const Node &start) const; /**