Add base paper and tarjan's SCC algorithm
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -24,6 +24,3 @@ x86/
|
|||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
*.vcxproj.filters
|
*.vcxproj.filters
|
||||||
|
|
||||||
*.pdf
|
|
||||||
*.pptx
|
|
||||||
74
algorithm/tarjan.h
Normal file
74
algorithm/tarjan.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#ifndef TARJAN_H_
|
||||||
|
#define TARJAN_H_
|
||||||
|
|
||||||
|
#include "graph/graph.h"
|
||||||
|
using namespace graph;
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ranges>
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace algorithm {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Tarjan {
|
||||||
|
public:
|
||||||
|
Tarjan(Graph<T> G) : G(G) {}
|
||||||
|
|
||||||
|
void findSCC();
|
||||||
|
|
||||||
|
void strongConnect(Vertex<T>& v);
|
||||||
|
|
||||||
|
std::uint16_t index = 0;
|
||||||
|
std::stack<Vertex<T>> S;
|
||||||
|
private:
|
||||||
|
Graph<T> G;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Tarjan<T>::strongConnect(Vertex<T>& v) {
|
||||||
|
v.index, v.lowlink = index++;
|
||||||
|
v.onStack = true;
|
||||||
|
S.push(v);
|
||||||
|
|
||||||
|
for (auto& w : v.edges) {
|
||||||
|
if (w.index == -1) {
|
||||||
|
// successor w has not yet been visited, recurse on it
|
||||||
|
strongConnect(w);
|
||||||
|
v.lowlink = std::min(v.lowlink, w.lowlink);
|
||||||
|
} else if (w.onStack) {
|
||||||
|
// successor w is in stack S and hence in the current SCC
|
||||||
|
// if w is not on stack, then (v, w) is an edge pointing to an SCC
|
||||||
|
// already found and must be ignored
|
||||||
|
v.lowlink = std::min(v.lowlink, w.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if v is a root node, pop the stack and generate an SCC
|
||||||
|
if (v.lowlink = v.index) {
|
||||||
|
// start a new SCC
|
||||||
|
Vertex<T> w;
|
||||||
|
do {
|
||||||
|
w = S.top();
|
||||||
|
S.pop();
|
||||||
|
// add w to current SCC
|
||||||
|
|
||||||
|
} while (w != v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Tarjan<T>::findSCC() {
|
||||||
|
|
||||||
|
for (auto& vertex : G.vertices) {
|
||||||
|
if (vertex.index == -1) {
|
||||||
|
strongConnect(vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace algorithm
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
doc/IMPROVED DYNAMIC REACHABILITY ALGORITHMS.pdf
Normal file
BIN
doc/IMPROVED DYNAMIC REACHABILITY ALGORITHMS.pdf
Normal file
Binary file not shown.
65
graph/graph.h
Normal file
65
graph/graph.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef GRAPH_H_
|
||||||
|
#define GRAPH_H_
|
||||||
|
|
||||||
|
#include "vertex.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace graph {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Graph {
|
||||||
|
public:
|
||||||
|
Graph() = default;
|
||||||
|
|
||||||
|
// Add vertex v
|
||||||
|
void insert(Vertex<T>& v);
|
||||||
|
|
||||||
|
// Add edge between v and u
|
||||||
|
void insert(Vertex<T> v, Vertex<T> u);
|
||||||
|
|
||||||
|
// Delete vertex v
|
||||||
|
void erase(Vertex<T>& v);
|
||||||
|
|
||||||
|
// Delete edge between v and u
|
||||||
|
void erase(Vertex<T>& v, Vertex<T>& u);
|
||||||
|
|
||||||
|
// Return true if v and u are connected
|
||||||
|
bool connected(const Vertex<T>& v, const Vertex<T>& u) const;
|
||||||
|
|
||||||
|
// Adjacency matrix representation
|
||||||
|
std::vector<Vertex<T>> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void Graph<T>::insert(Vertex<T>& v) {
|
||||||
|
vertices.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void Graph<T>::insert(Vertex<T> v, Vertex<T> u) {
|
||||||
|
v.edges.push_back(u);
|
||||||
|
vertices.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void Graph<T>::erase(Vertex<T>& v) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void Graph<T>::erase(Vertex<T>& v, Vertex<T>& u) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool Graph<T>::connected(const Vertex<T>& v, const Vertex<T>& u) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace graph
|
||||||
|
|
||||||
|
#endif
|
||||||
36
graph/vertex.h
Normal file
36
graph/vertex.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef VERTEX_H_
|
||||||
|
#define VERTEX_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <compare>
|
||||||
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace graph {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Vertex {
|
||||||
|
public:
|
||||||
|
Vertex() = default;
|
||||||
|
Vertex(T v) : v(v) {}
|
||||||
|
|
||||||
|
T v;
|
||||||
|
std::uint16_t index = -1;
|
||||||
|
std::uint16_t lowlink = -1;
|
||||||
|
bool onStack = false;
|
||||||
|
std::vector<Vertex<T>> edges;
|
||||||
|
|
||||||
|
auto operator<=>(const Vertex&) const = default;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
friend inline std::ostream& operator<<(std::ostream& os, const Vertex<T>& v);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Vertex<T>& vout) {
|
||||||
|
return os << vout.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace graph
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#ifndef GRAPH_H_
|
|
||||||
#define GRAPH_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace graph {
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
class Graph {
|
|
||||||
public:
|
|
||||||
Graph() = default;
|
|
||||||
|
|
||||||
// Add vertex v
|
|
||||||
void insert(const V& v);
|
|
||||||
|
|
||||||
// Add edge between v and u
|
|
||||||
void insert(const V& v, const V& u);
|
|
||||||
|
|
||||||
// Delete vertex v
|
|
||||||
void erase(const V& v);
|
|
||||||
|
|
||||||
// Delete edge between v and u
|
|
||||||
void erase(const V& v, const V& u);
|
|
||||||
|
|
||||||
// Return true if v and u are connected
|
|
||||||
bool connected(const V& v, const V& u);
|
|
||||||
private:
|
|
||||||
std::map<V, std::set<V>> adjacency;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
inline void Graph<V>::insert(const V& v) {
|
|
||||||
adjacency[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
inline void Graph<V>::insert(const V& v, const V& u) {
|
|
||||||
adjacency[v].insert(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
inline void Graph<V>::erase(const V& v) {
|
|
||||||
adjacency.erase(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
inline void Graph<V>::erase(const V& v, const V& u) {
|
|
||||||
adjacency[v].erase(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
inline bool Graph<V>::connected(const V& v, const V& u) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace graph
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include "graph/graph.h"
|
||||||
|
using namespace graph;
|
||||||
|
#include "algorithm/tarjan.h"
|
||||||
|
|
||||||
#include "include/graph.h"
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
TEST_SUITE("Testing Graph.") {
|
TEST_SUITE("Testing Graph.") {
|
||||||
using namespace graph;
|
|
||||||
|
|
||||||
TEST_CASE("Insert vertices/edges.") {
|
TEST_CASE("Insert vertices/edges.") {
|
||||||
Graph<std::uint16_t> G;
|
Graph<std::uint16_t> G;
|
||||||
@@ -20,6 +22,12 @@ TEST_SUITE("Testing Graph.") {
|
|||||||
G.insert(4, 6);
|
G.insert(4, 6);
|
||||||
G.insert(5, 6);
|
G.insert(5, 6);
|
||||||
|
|
||||||
|
Vertex<std::uint16_t> v1(1);
|
||||||
|
Vertex<std::uint16_t> v2(3);
|
||||||
|
Vertex<std::uint16_t> v3(5);
|
||||||
|
algorithm::Tarjan<std::uint16_t> tarjan(G);
|
||||||
|
tarjan.findSCC();
|
||||||
|
|
||||||
// CHECK_EQ(G.connected(1, 5), true);
|
// CHECK_EQ(G.connected(1, 5), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user