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.user
|
||||
*.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 <cstdint>
|
||||
#include "graph/graph.h"
|
||||
using namespace graph;
|
||||
#include "algorithm/tarjan.h"
|
||||
|
||||
#include "include/graph.h"
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
TEST_SUITE("Testing Graph.") {
|
||||
using namespace graph;
|
||||
|
||||
TEST_CASE("Insert vertices/edges.") {
|
||||
Graph<std::uint16_t> G;
|
||||
@@ -20,6 +22,12 @@ TEST_SUITE("Testing Graph.") {
|
||||
G.insert(4, 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);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user