From bb325eba98d44de53705a8a0512be6f364d342f5 Mon Sep 17 00:00:00 2001 From: Miguel Raggi Date: Tue, 15 May 2018 08:56:49 -0500 Subject: [PATCH] Removed old files --- README.md | 3 +- graph/Bipartite.cpp | 92 ----- graph/Bipartite.hpp | 84 ----- graph/BipartiteMatching.cpp | 149 -------- graph/BipartiteMatching.hpp | 33 -- graph/Centrality.cpp | 125 ------- graph/Centrality.hpp | 12 - graph/Clustering.cpp | 66 ---- graph/Clustering.hpp | 8 - graph/CommonGraphs.cpp | 351 ------------------ graph/CommonGraphs.hpp | 38 -- graph/ConnectedComponents.cpp | 77 ---- graph/ConnectedComponents.hpp | 9 - graph/Graph.cpp | 204 ---------- graph/Graph.hpp | 147 -------- graph/IsSimple.cpp | 15 - graph/IsSimple.hpp | 5 - graph/LCA.cpp | 164 -------- graph/LCA.hpp | 73 ---- graph/MinSpanningTree.cpp | 100 ----- graph/MinSpanningTree.hpp | 7 - graph/PrintUtils.hpp | 41 -- graph/ShortestPaths.cpp | 33 -- graph/ShortestPaths.hpp | 269 -------------- graph/TreeAlgorithms.cpp | 66 ---- graph/TreeAlgorithms.hpp | 10 - graph/utils/Misc.hpp | 180 --------- graph/utils/NaturalNumber.hpp | 119 ------ graph/utils/Probability.hpp | 149 -------- graph/utils/RangeMinQuery.hpp | 87 ----- graph/utils/TimeHelpers.hpp | 73 ---- graph/utils/VectorHelpers.hpp | 127 ------- graph/utils/disjoint_sets.hpp | 73 ---- .../utils/experimental/RangeMinQueryIters.hpp | 97 ----- install_ubuntu1604.sh | 3 - install_ubuntu1710.sh | 3 - 36 files changed, 1 insertion(+), 3091 deletions(-) delete mode 100644 graph/Bipartite.cpp delete mode 100644 graph/Bipartite.hpp delete mode 100644 graph/BipartiteMatching.cpp delete mode 100644 graph/BipartiteMatching.hpp delete mode 100644 graph/Centrality.cpp delete mode 100644 graph/Centrality.hpp delete mode 100644 graph/Clustering.cpp delete mode 100644 graph/Clustering.hpp delete mode 100644 graph/CommonGraphs.cpp delete mode 100644 graph/CommonGraphs.hpp delete mode 100644 graph/ConnectedComponents.cpp delete mode 100644 graph/ConnectedComponents.hpp delete mode 100644 graph/Graph.cpp delete mode 100644 graph/Graph.hpp delete mode 100644 graph/IsSimple.cpp delete mode 100644 graph/IsSimple.hpp delete mode 100644 graph/LCA.cpp delete mode 100644 graph/LCA.hpp delete mode 100644 graph/MinSpanningTree.cpp delete mode 100644 graph/MinSpanningTree.hpp delete mode 100644 graph/PrintUtils.hpp delete mode 100644 graph/ShortestPaths.cpp delete mode 100644 graph/ShortestPaths.hpp delete mode 100644 graph/TreeAlgorithms.cpp delete mode 100644 graph/TreeAlgorithms.hpp delete mode 100644 graph/utils/Misc.hpp delete mode 100644 graph/utils/NaturalNumber.hpp delete mode 100644 graph/utils/Probability.hpp delete mode 100644 graph/utils/RangeMinQuery.hpp delete mode 100644 graph/utils/TimeHelpers.hpp delete mode 100644 graph/utils/VectorHelpers.hpp delete mode 100644 graph/utils/disjoint_sets.hpp delete mode 100644 graph/utils/experimental/RangeMinQueryIters.hpp diff --git a/README.md b/README.md index 7cab8c1..8ef9a69 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,8 @@ This is graph-algorithm-visualization software made for my students at ENES More git cmake clang or gcc - Google test + Google test # included! SFML - boost # Para ubuntu 16.04: diff --git a/graph/Bipartite.cpp b/graph/Bipartite.cpp deleted file mode 100644 index 586f4b3..0000000 --- a/graph/Bipartite.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "Bipartite.hpp" -#include -using Vertex = BipartiteGraph::Vertex; - -void BipartiteGraph::sort_neighbors() -{ - if (m_neighbors_sorted) - return; - - for (auto& x : m_X) - std::sort(std::begin(x), std::end(x)); - - for (auto& y : m_Y) - std::sort(std::begin(y), std::end(y)); - - m_neighbors_sorted = true; -} - -BipartiteGraph::BipartiteGraph(const Graph& G) -{ - // -1 means not set. 0 and 1 are the colors. - std::vector coloring(G.num_vertices(), -1); - - // map from vertices in G to vertices in (X,Y). - std::vector map(G.num_vertices(), -1); - - for (auto v : G.vertices()) - { - if (coloring[v] != -1) - continue; - std::stack frontier; - frontier.emplace(v); - coloring[v] = 0; - map[v] = m_X.size(); - m_X.emplace_back(); - - while (!frontier.empty()) - { - auto u = frontier.top(); - frontier.pop(); - - bool color = coloring[u]; - - for (auto w : G.neighbors(u)) - { - if (coloring[w] == -1) - { - coloring[w] = !color; - if (coloring[w]) - { - map[w] = m_Y.size(); - m_Y.emplace_back(); - } - else - { - map[w] = m_X.size(); - m_X.emplace_back(); - } - frontier.emplace(w); - } - } - } - - for (auto v : G.vertices()) - { - for (auto u : G.neighbors(v)) - { - if (u < v) - continue; - if (!coloring[u]) - add_edge(map[u], map[v]); - else - add_edge(map[v], map[u]); - } - } - } -} - -Graph BipartiteGraph::GetGraph() const -{ - Graph G(num_vertices()); - - for (Vertex v = 0; v < num_verticesX(); ++v) - { - for (auto u : neighborsX(v)) - { - G.add_edge(v, u + num_verticesX(), u.weight()); - } - } - - return G; -} diff --git a/graph/Bipartite.hpp b/graph/Bipartite.hpp deleted file mode 100644 index 5feeb9a..0000000 --- a/graph/Bipartite.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include "Graph.hpp" - -class BipartiteGraph -{ -public: - /****** BEGIN using definitions *****/ - using size_type = Graph::size_type; - - using Vertex = Graph::Vertex; - - using weight_t = Graph::weight_t; - - // something larger than weight_t, for when you have that weight_t doesn't - // properly hold a sum of weight_t (for example, if weight_t = char). - using sumweight_t = Graph::sumweight_t; - - using Neighbor = Graph::Neighbor; // Represents a half-edge (vertex,weight) - - using Edge = Graph::Edge; // (from,to,weight) - - using neighbor_list = std::vector; - using neighbor_const_iterator = neighbor_list::const_iterator; - using neighbor_iterator = neighbor_list::iterator; - /****** END using definitions *****/ - -public: - BipartiteGraph(size_type x, size_type y) : m_X(x), m_Y(y) {} - BipartiteGraph(const Graph& G); - - size_type degreeX(Vertex x) const { return m_X[x].size(); } - size_type degreeY(Vertex y) const { return m_Y[y].size(); } - - size_type num_verticesX() const { return m_X.size(); } - size_type num_verticesY() const { return m_Y.size(); } - - size_type num_vertices() const { return num_verticesX() + num_verticesY(); } - - using all_vertices = basic_natural_number; - auto verticesX() const { return all_vertices(num_verticesX()); } - auto verticesY() const { return all_vertices(num_verticesY()); } - - const auto& X() const { return m_X; } - const auto& Y() const { return m_Y; } - - const neighbor_list& neighborsX(Vertex a) const { return m_X[a]; } - const neighbor_list& neighborsY(Vertex a) const { return m_Y[a]; } - - void add_edge(Vertex x, Vertex y, weight_t w = 1) - { - m_X[x].emplace_back(y, w); - m_Y[y].emplace_back(x, w); - ++m_numedges; - m_neighbors_sorted = false; - } - - void add_edge(const Edge& E) { add_edge(E.from, E.to, E.weight()); } - - template - void add_edges(const EdgeContainer& edges) - { - for (auto& e : edges) - add_edge(e); - } - - void add_edges(const std::initializer_list& edges) - { - for (auto& e : edges) - add_edge(e); - } - - void FlipXandY() { std::swap(m_X, m_Y); } - - void sort_neighbors(); - - Graph GetGraph() const; - -private: - std::vector m_X{}; - std::vector m_Y{}; - size_type m_numedges{0}; - bool m_neighbors_sorted{false}; -}; diff --git a/graph/BipartiteMatching.cpp b/graph/BipartiteMatching.cpp deleted file mode 100644 index 9ccb9bf..0000000 --- a/graph/BipartiteMatching.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "BipartiteMatching.hpp" -#include "Probability.hpp" - -#include "PrintUtils.hpp" -#include "VectorHelpers.hpp" - -#include -#include -#include - -using Vertex = BipartiteGraph::Vertex; -using Edge = BipartiteGraph::Edge; - -BipartiteMatcher::BipartiteMatcher(const BipartiteGraph& G) - : m_Xmatches(G.num_verticesX(), -1), m_Ymatches(G.num_verticesY(), -1) -{ - CreateInitialMatching(G); // uncomment after testing!! - - // m_unmatched_in_X = G.verticesX(); // remove after testing!!! - - Augment(G); -} - -std::vector BipartiteMatcher::Edges() const -{ - std::vector matching; - matching.reserve(size()); - - for (auto x : indices(m_Xmatches)) - { - auto y = MatchX(x); - if (y >= 0) - matching.emplace_back(x, y); - } - - return matching; -} - -void BipartiteMatcher::CreateInitialMatching(const BipartiteGraph& G) -{ - m_unmatched_in_X.reserve(G.num_verticesX()); - - // std::vector W = G.verticesX(); - // std::sort(W.begin(), W.end(), [&G](auto a, auto b){ return G.degreeX(a) - // < G.degreeX(b); }); - - // for (auto x : W) - for (auto x : G.verticesX()) - { - // std::vector Z(G.neighborsX(x).begin(), - // G.neighborsX(x).end()); std::sort(Z.begin(), Z.end(), [&G](auto - // a, auto b){ return G.degreeY(a) < G.degreeY(b); - // }); - - // for (auto y : Z) - for (auto y : G.neighborsX(x)) - { - if (m_Ymatches[y] < 0) - { - m_Xmatches[x] = y; - m_Ymatches[y] = x; - ++m_size; - break; - } - } - if (m_Xmatches[x] < 0) - m_unmatched_in_X.emplace_back(x); - } -} - -void BipartiteMatcher::ApplyAugmentingPath(Vertex y, - const std::vector& parent) -{ - ++m_size; - - Vertex x = parent[y]; - do - { - auto new_y = m_Xmatches[x]; // save it because I'll erase it - - // new matches - m_Ymatches[y] = x; - m_Xmatches[x] = y; - - y = new_y; - x = parent[y]; - assert(x != -1); - } while (y != -1); -} - -bool BipartiteMatcher::FindAugmentingPath(const BipartiteGraph& G, Vertex x) -{ - const Vertex not_seen = -1; - // In order to reconstruct the augmenting path. - std::vector parent(G.num_verticesY(), -1); - - std::queue frontier; // BFS - frontier.emplace(x); - - while (!frontier.empty()) - { - auto current_x = frontier.front(); - frontier.pop(); - - for (Vertex y : G.neighborsX(current_x)) - { - if (parent[y] != not_seen) - continue; - - parent[y] = current_x; - - auto new_x = m_Ymatches[y]; - if (new_x == -1) - { - ApplyAugmentingPath(y, parent); - assert(m_Xmatches[x] != -1); - return true; - } - - frontier.emplace(new_x); - } - } - - return false; -} - -void BipartiteMatcher::Augment(const BipartiteGraph& G) -{ - size_t num_without_augment = 0; - auto it = m_unmatched_in_X.begin(); - - while (num_without_augment < m_unmatched_in_X.size()) - { - if (it == m_unmatched_in_X.end()) - it = m_unmatched_in_X.begin(); // Imagine this a circular buffer. - - if (FindAugmentingPath(G, *it)) - { - *it = m_unmatched_in_X.back(); - m_unmatched_in_X.pop_back(); - num_without_augment = 0; - } - else - { - ++it; - ++num_without_augment; - } - } -} diff --git a/graph/BipartiteMatching.hpp b/graph/BipartiteMatching.hpp deleted file mode 100644 index fb1b818..0000000 --- a/graph/BipartiteMatching.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "Bipartite.hpp" - -class BipartiteMatcher -{ -public: - using Vertex = BipartiteGraph::Vertex; - using Edge = Graph::Edge; - - BipartiteMatcher(const BipartiteGraph& G); - - Vertex MatchX(Vertex x) const { return m_Xmatches[x]; } - Vertex MatchY(Vertex y) const { return m_Ymatches[y]; } - - int size() const { return m_size; } - std::vector Edges() const; - -private: - void CreateInitialMatching(const BipartiteGraph& G); - - // returns false if no augmenting path was found - void Augment(const BipartiteGraph& G); - bool FindAugmentingPath(const BipartiteGraph& G, Vertex x); - - void ApplyAugmentingPath(Vertex y, const std::vector& parent); - - int m_size{0}; - std::vector m_Xmatches{}; // -1 if not matched - std::vector m_Ymatches{}; // -1 if not matched - - std::vector m_unmatched_in_X{}; -}; diff --git a/graph/Centrality.cpp b/graph/Centrality.cpp deleted file mode 100644 index b3f5b41..0000000 --- a/graph/Centrality.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "Centrality.hpp" -#include "ShortestPaths.hpp" -#include "VectorHelpers.hpp" - -namespace centrality -{ - -std::vector degree(const Graph& G) -{ - auto n = G.num_vertices(); - double e = n - 1.0; - std::vector C(n); - - for (auto v : G.vertices()) - C[v] = G.degree(v)/e; - - return C; -} -std::vector closeness(const Graph& G) -{ - auto n = G.num_vertices(); - - std::vector C(n,n-1); - - auto D = AllPairsShortestPaths(G); - - for (auto u : G.vertices()) - { - auto d = std::accumulate(D[u].begin(), D[u].end(),0.0); - C[u] /= d; - } - - return C; -} - -using namespace std; - -void betweenness_normalize(std::vector& B, Vertex n) -{ - double L = 2*n-1; - double R = n*n - n + 1; - - // Convert to nice, natural format - for (auto& x : B) - { - x = (x-L)/(R-L); - } -} - -std::vector betweenness_contrib(const Graph& G, Vertex s) -{ - auto n = G.num_vertices(); - std::vector ordered_vertices(1,s); - std::vector D(n,-1); - std::vector W(n,0); - std::vector X(n,1.0); - - D[s] = 0; - W[s] = 1; - - int d = 0; - - std::queue frontier; - frontier.emplace(s); - - //Step X - while (!frontier.empty()) - { - auto lastnode = frontier.front(); - frontier.pop(); - - d = D[lastnode]; - - for (auto v : G.neighbors(lastnode)) - { - if (D[v] == -1) - { - D[v] = d+1; - W[v] = W[lastnode]; - - frontier.emplace(v); - ordered_vertices.emplace_back(v); - } - else if (D[v] == D[lastnode] + 1) - { - W[v] += W[lastnode]; - } - } - } - - // Step W - for (auto vit = ordered_vertices.rbegin(); vit != ordered_vertices.rend(); ++vit) - { - auto v = *vit; - for (auto u : G.neighbors(v)) - { - if (D[u] == D[v] + 1) - { - X[v] += (X[u]*W[v])/W[u]; - } - } - } - - return X; -} - -std::vector betweenness(const Graph& G) -{ - auto n = G.num_vertices(); - std::vector B(n,0.0); - - for (auto s : G.vertices()) - { - auto X = betweenness_contrib(G,s); - for (auto i : G.vertices()) - B[i] += X[i]; - - } - - betweenness_normalize(B,n); - - return B; -} - -} diff --git a/graph/Centrality.hpp b/graph/Centrality.hpp deleted file mode 100644 index f92b1df..0000000 --- a/graph/Centrality.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "Graph.hpp" - - -namespace centrality -{ - -std::vector degree(const Graph& G); -std::vector closeness(const Graph& G); -std::vector betweenness(const Graph& G); - -} diff --git a/graph/Clustering.cpp b/graph/Clustering.cpp deleted file mode 100644 index 2ae2eb1..0000000 --- a/graph/Clustering.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "Clustering.hpp" -#include - -using Vertex = Graph::Vertex; - -std::int64_t num_triangles_of_neighbors(const Graph& G, Graph::Vertex v) -{ - std::int64_t result = 0; - - std::vector Neighbors(G.num_vertices(), 0); - - for (auto u : G.neighbors(v)) - Neighbors[u] = 1; - - for (auto u : G.neighbors(v)) - { - for (auto w : G.neighbors(u)) - { - if (w > u && Neighbors[w]) - ++result; - } - } - return result; -} - -std::int64_t num_triangles(const Graph& G) -{ - std::int64_t result = 0; - for (auto v : G.vertices()) - result += num_triangles_of_neighbors(G, v); - return result/3; -} - -std::int64_t sum_degrees_in_two(const Graph& G) -{ - std::int64_t result = 0; - for (auto v : G.vertices()) - { - auto d = G.degree(v); - result += (d*(d - 1))/2; - } - return result; -} - -std::vector clustering_local(const Graph& G) -{ - std::vector result(G.num_vertices(), 0.0); - - for (auto v : G.vertices()) - { - auto d = G.degree(v); - if (d >= 2) - result[v] = - (2.0*num_triangles_of_neighbors(G, v))/(d*(d - 1)); - } - - return result; -} - -double clustering_global(const Graph& G) -{ - double denominator = sum_degrees_in_two(G); - if (denominator == 0) - return 0; - return (3.0*num_triangles(G))/denominator; -} diff --git a/graph/Clustering.hpp b/graph/Clustering.hpp deleted file mode 100644 index 9ff8255..0000000 --- a/graph/Clustering.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "Graph.hpp" - -std::vector clustering_local(const Graph& G); -double clustering_global(const Graph& G); - -std::int64_t num_triangles(const Graph& G); -std::int64_t num_triangles_of_neighbors(const Graph& G, Graph::Vertex v); diff --git a/graph/CommonGraphs.cpp b/graph/CommonGraphs.cpp deleted file mode 100644 index b1cb57b..0000000 --- a/graph/CommonGraphs.cpp +++ /dev/null @@ -1,351 +0,0 @@ -#include "CommonGraphs.hpp" -#include "Probability.hpp" -#include - -namespace graphs -{ - -using Vertex = Graph::Vertex; - -Graph Petersen() -{ - Graph G(10); - - G.add_edges({{0, 1}, - {0, 4}, - {0, 5}, - {1, 2}, - {1, 6}, - {2, 3}, - {2, 7}, - {3, 4}, - {3, 8}, - {4, 9}, - {5, 7}, - {5, 8}, - {6, 8}, - {6, 9}, - {7, 9}}); - - return G; -} - -Graph Path(int n) -{ - Graph G(n + 1); - for (Vertex i = 0; i < n; ++i) - G.add_edge(i, i + 1); - return G; -} - -Graph Cycle(int n) -{ - Graph G = Path(n - 1); - if (n > 2) - { - G.add_edge(0, n - 1); - } - return G; -} - -Graph Complete(int n) -{ - Graph G(n); - - for (Vertex i = 0; i + 1 < n; ++i) - { - for (Vertex j = i + 1; j < n; ++j) - { - G.add_edge(i, j); - } - } - - return G; -} - -Graph Random(int n, double p) -{ - Graph G(n); - - for (auto i : G.vertices()) - { - for (int j = i + 1; j < G.num_vertices(); ++j) - { - if (probability_of_true(p)) - G.add_edge(i, j); - } - } - return G; -} - -Graph RandomWeighted(int n, double p) -{ - Graph G(n); - - for (auto u : G.vertices()) - { - for (Vertex v = u + 1; v < G.num_vertices(); ++v) - { - if (probability_of_true(p)) - { - G.add_edge(u, v, random_int(0, 100)); - } - } - } - return G; -} - -struct paircommutativehash -{ -public: - template - std::size_t operator()(const std::pair& x) const - { - return std::hash()(x.first) ^ std::hash()(x.second); - } -}; - -struct paircommutativeequal -{ -public: - template - bool operator()(const std::pair& A, const std::pair& B) const - { - return (A.first == B.first && A.second == B.second) || - (A.first == B.second && A.second == B.first); - } -}; - -Graph RandomWithSpecifiedNumEdges(int num_verts, int num_edges) -{ - Graph G(num_verts); - - std::int64_t total = std::int64_t(num_verts)*(num_verts - 1)/2; - - if (num_edges > total) - return G; // error!! - - if (num_edges < total/2) - { - std::unordered_set, - paircommutativehash, - paircommutativeequal> - AddedAlready; - while (G.num_edges() < num_edges) - { - auto u = random_int(0, num_verts); - auto v = random_int(0, num_verts); - if (u == v) - continue; - if (AddedAlready.emplace(u, v).second) - { - G.add_edge(u, v); - } - } - } - else - { - using edge = std::pair; - std::vector all; - all.reserve(total); - for (Vertex u = 0; u < num_verts; ++u) - { - for (Vertex v = u + 1; v < num_verts; ++v) - { - all.emplace_back(u, v); - } - } - - std::shuffle(all.begin(), all.end(), random_engine()); - for (int i = 0; i < num_edges; ++i) - G.add_edge(all[i].first, all[i].second); - } - - return G; -} - -Graph Grid(int n, int m) -{ - Graph G((n + 1)*(m + 1)); - - for (int i = 0; i < n; ++i) - { - for (int j = 0; j < m; ++j) - { - Vertex v = i*(m + 1) + j; - G.add_edge(v, v + 1); - G.add_edge(v, v + m + 1); - } - } - - for (int j = 0; j < m; ++j) - { - Vertex v = n*(m + 1) + j; - G.add_edge(v, v + 1); - } - - for (int i = 0; i < n; ++i) - { - Vertex v = i*(m + 1) + m; - G.add_edge(v, v + m + 1); - } - - return G; -} - -Graph WeightedGrid(int n, int m) -{ - Graph G((n + 1)*(m + 1)); - - for (int i = 0; i < n; ++i) - { - for (int j = 0; j < m; ++j) - { - Vertex v = i*(m + 1) + j; - G.add_edge(v, v + 1, random_int(0, 100)); - G.add_edge(v, v + m + 1, random_int(0, 100)); - } - } - - for (int j = 0; j < m; ++j) - { - Vertex v = n*(m + 1) + j; - G.add_edge(v, v + 1, random_int(0, 100)); - } - - for (int i = 0; i < n; ++i) - { - Vertex v = i*(m + 1) + m; - G.add_edge(v, v + m + 1, random_int(0, 100)); - } - - return G; -} - -Graph RandomTree(int n) -{ - Graph G(n); - - if (n < 2) - return G; - - G.add_edge(0, 1); - - for (Vertex v = 2; v < n; ++v) - { - auto u = random_int(0, v); - G.add_edge(u, v); - } - - return G; -} - -Graph CompleteBipartite(int n, int m) -{ - Graph G(n + m); - for (Vertex x = 0; x < n; ++x) - { - for (Vertex y = n; y < m + n; ++y) - { - G.add_edge(x, y); - } - } - return G; -} - -void ProduceRandomBinaryTreeEdges(Graph* G, Vertex start, Vertex end) -{ - if (end - start < 2) - return; - - Vertex mid = random_int(start + 1, end); - - // [start+1,mid)----- start ----- [mid,end) - - if (mid != start + 1) - { - G->add_edge(start, start + 1); - ProduceRandomBinaryTreeEdges(G, start + 1, mid); - } - - if (mid != end) - { - G->add_edge(start, mid); - ProduceRandomBinaryTreeEdges(G, mid, end); - } - // G->make_simple(); -} - -Graph RandomBinaryTree(int n) -{ - Graph G(n); - ProduceRandomBinaryTreeEdges(&G, 0, n); - return G; -} - -Graph AlbertBarabanasi(int n, int k) -{ - Graph G(n); - - // complete graph in [0,k) - for (int i = 0; i < k; ++i) - { - for (int j = i + 1; j < k; ++j) - { - G.add_edge(i, j); - } - } - - std::vector population(k); - population.reserve(n); - - std::iota(population.begin(), population.end(), 0); - - for (int i = k; i < n; ++i) - { - auto Neighs = random_sample(population, k); - - for (auto j : Neighs) - G.add_edge(i, j); - population.emplace_back(i); - } - - return G; -} - -Graph BalancedBinaryTree(int n) -{ - Graph G(n); - auto left_child = [](Vertex v) { return 2*v + 1; }; - auto right_child = [](Vertex v) { return 2*v + 2; }; - - for (auto v : G.vertices()) - { - auto L = left_child(v); - auto R = right_child(v); - if (L < G.num_vertices()) - G.add_edge(v, L); - if (R < G.num_vertices()) - G.add_edge(v, R); - } - - return G; -} - -BipartiteGraph RandomBipartite(int n, int m, double p) -{ - BipartiteGraph B(n, m); - - for (auto x : B.verticesX()) - { - for (auto y : B.verticesY()) - { - if (probability_of_true(p)) - B.add_edge(x, y); - } - } - - return B; -} - -} // namespace graphs diff --git a/graph/CommonGraphs.hpp b/graph/CommonGraphs.hpp deleted file mode 100644 index 1e58f8d..0000000 --- a/graph/CommonGraphs.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "Bipartite.hpp" -#include "Graph.hpp" - -namespace graphs -{ -Graph Petersen(); - -Graph Path(int n); - -Graph Cycle(int n); - -Graph Complete(int n); - -Graph CompleteBipartite(int n, int m); - -Graph BalancedBinaryTree(int n); - -Graph Random(int n, double p); - -Graph RandomWeighted(int n, double p); - -Graph RandomWithSpecifiedNumEdges(int num_verts, int num_edges); - -Graph RandomTree(int n); - -Graph RandomBinaryTree(int n); - -BipartiteGraph RandomBipartite(int n, int m, double p); - -Graph Grid(int n, int m); - -Graph WeightedGrid(int n, int m); - -Graph AlbertBarabanasi(int n, int k); - -} // namespace graphs diff --git a/graph/ConnectedComponents.cpp b/graph/ConnectedComponents.cpp deleted file mode 100644 index cd16c51..0000000 --- a/graph/ConnectedComponents.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "ConnectedComponents.hpp" -#include - -using Vertex = Graph::Vertex; - -std::vector connected_components(const Graph& G) -{ - auto n = G.num_vertices(); - std::vector components(n, -1); - int current_component = 0; - - for (auto v : G.vertices()) - { - if (components[v] != -1) - continue; - - std::stack frontier; - frontier.emplace(v); - while (!frontier.empty()) - { - auto p = frontier.top(); - frontier.pop(); - if (components[p] != -1) - continue; - components[p] = current_component; - for (auto u : G.neighbors(p)) - { - if (components[u] == -1) - frontier.emplace(u); - } - } - ++current_component; - } - - return components; -} - -bool is_connected(const Graph& G) -{ - auto n = G.num_vertices(); - if (n < 2) - return true; - - using Bool = char; - std::vector seen(n, false); - int num_seen = 0; - - std::stack frontier; - frontier.emplace(0); - - while (!frontier.empty()) - { - auto p = frontier.top(); - frontier.pop(); - if (seen[p]) - continue; - seen[p] = true; - ++num_seen; - for (auto u : G.neighbors(p)) - { - if (!seen[u]) - frontier.emplace(u); - } - } - - return num_seen == n; -} - -int num_connected_components(const Graph& G) -{ - if (G.num_vertices() == 0) - return 0; - - auto components = connected_components(G); - - return (*std::max_element(components.begin(), components.end())) + 1; -} diff --git a/graph/ConnectedComponents.hpp b/graph/ConnectedComponents.hpp deleted file mode 100644 index 0d32fff..0000000 --- a/graph/ConnectedComponents.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "Graph.hpp" - -std::vector connected_components(const Graph& G); - -bool is_connected(const Graph& G); - -int num_connected_components(const Graph& G); diff --git a/graph/Graph.cpp b/graph/Graph.cpp deleted file mode 100644 index 75e1626..0000000 --- a/graph/Graph.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include "Graph.hpp" -#include "VectorHelpers.hpp" - -using Vertex = Graph::Vertex; -using weight_t = Graph::weight_t; -using size_type = Graph::size_type; -using sumweight_t = Graph::sumweight_t; -using Neighbor = Graph::Neighbor; -using Edge = Graph::Edge; -using neighbor_iterator = Graph::neighbor_iterator; -using neighbor_const_iterator = Graph::neighbor_const_iterator; - -Graph::Graph(Vertex numberOfVertices) - : m_numvertices(std::max(0, numberOfVertices)) - , m_graph(m_numvertices) -{} - -// Graph modification functions -void Graph::add_edge(Vertex from, Vertex to, weight_t w) -{ - m_graph[from].emplace_back(to, w); - m_graph[to].emplace_back(from, w); - ++m_numedges; - m_neighbors_sorted = false; -} - -void Graph::add_edge(const Edge& e) { add_edge(e.from, e.to, e.weight()); } - -bool Graph::add_edge_no_repeat(Vertex from, Vertex to, weight_t w) -{ - if (is_neighbor(from, to)) - return false; - - add_edge(from, to, w); - return true; -} - -void Graph::add_edges(const std::initializer_list& edges) -{ - for (auto& e : edges) - add_edge(e); -} - -Vertex Graph::add_vertex() -{ - m_graph.emplace_back(); // empty vector - return m_numvertices++; -} - -std::vector Graph::edges() const -{ - std::vector total; - - for (auto u : vertices()) - { - for (auto v : m_graph[u]) - { - if (v > u) - total.emplace_back(u, v, v.weight()); - } - } - - return total; -} - -void Graph::sort_neighbors() -{ - if (m_neighbors_sorted) - return; - - for (auto& adj_list : m_graph) - sort(adj_list.begin(), adj_list.end()); - - m_neighbors_sorted = true; -} - -bool Graph::is_neighbor(Vertex from, Vertex to) const -{ - if (degree(from) > degree(to)) - std::swap(from, to); - - auto& NF = neighbors(from); - - if (m_neighbors_sorted) - return std::binary_search(NF.begin(), NF.end(), to); - - for (auto& a : NF) - { - if (a == to) - return true; - } - - return false; -} - -neighbor_iterator Graph::get_neighbor(Vertex from, Vertex to) -{ - auto first = m_graph[from].begin(); - auto last = m_graph[from].end(); - - if (m_neighbors_sorted) - return find_binary(first, last, to); - - return std::find(first, last, to); -} - -neighbor_const_iterator Graph::get_neighbor(Vertex from, Vertex to) const -{ - auto first = m_graph[from].begin(); - auto last = m_graph[from].end(); - - if (m_neighbors_sorted) - return find_binary(first, last, to); - - return std::find(first, last, to); -} - -weight_t Graph::edge_value(Vertex from, Vertex to) const -{ - if (degree(from) > degree(to)) - std::swap(from, to); - - auto neigh = get_neighbor(from, to); - - if (neigh == neighbors(from).end() || *neigh != to) - return 0; - - return neigh->weight(); -} - -void Graph::delete_loops() -{ - for (auto v : vertices()) - { - auto& NV = m_graph[v]; - auto newend = std::remove(NV.begin(), NV.end(), v); - m_numedges -= NV.end() - newend; - NV.erase(newend, NV.end()); - } -} - -void Graph::delete_repeated_edges() -{ - sort_neighbors(); - - for (auto& adj_list : m_graph) - { - auto newend = std::unique(adj_list.begin(), adj_list.end()); - m_numedges -= adj_list.end() - newend; - adj_list.erase(newend, adj_list.end()); - } -} - -void Graph::make_simple() -{ - delete_loops(); - delete_repeated_edges(); -} - -void Graph::remove_edge(Vertex v, Vertex u) -{ - m_neighbors_sorted = false; - - auto it = get_neighbor(v, u); - remove_unordered(m_graph[v], it); - - auto it2 = get_neighbor(u, v); - remove_unordered(m_graph[u], it2); - - --m_numedges; -} - -void Graph::remove_vertex(Vertex v) -{ - assert(v >= 0 && v < num_vertices()); - Vertex last_vertex = num_vertices() - 1; - - for (auto u : neighbors(v)) - { - auto& X = m_graph[u]; - auto it = std::remove(X.begin(), X.end(), v); - m_numedges -= X.end() - it; - X.erase(it, X.end()); - } - - if (v != last_vertex) - { - // Replace all occurrences of last_vertex to now be v - for (auto u : neighbors(last_vertex)) - { - for (auto& w : m_graph[u]) - { - if (w.vertex == last_vertex) - w.vertex = v; - } - } - - m_graph[v] = m_graph[last_vertex]; - } - - m_graph.pop_back(); - --m_numvertices; - m_neighbors_sorted = false; -} diff --git a/graph/Graph.hpp b/graph/Graph.hpp deleted file mode 100644 index 2bd6acf..0000000 --- a/graph/Graph.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include "Misc.hpp" -#include "NaturalNumber.hpp" -#include -#include - -// simple undirected graph -class Graph -{ -public: - using size_type = long long; // NOLINT - - using Vertex = std::int64_t; - - enum WORKAROUND_UNTIL_CPP17 - { - INVALID_VERTEX = -1 - }; - // inline static constexpr Vertex INVALID_VERTEX = -1; // Uncomment with - // c++17 - - using weight_t = std::int64_t; - - // something larger than weight_t, for when you have that weight_t doesn't - // properly hold a sum of weight_t (for example, if weight_t = char). - using sumweight_t = std::int64_t; - - struct Neighbor; // Represents a half-edge (vertex,weight) - - struct Edge; // (from,to,weight) - - using neighbor_list = std::vector; - using neighbor_const_iterator = neighbor_list::const_iterator; - using neighbor_iterator = neighbor_list::iterator; - - // Constructor - explicit Graph(Vertex numberOfVertices = 0); - - size_type degree(Vertex a) const { return m_graph[a].size(); } - - // Graph modification functions - Vertex add_vertex(); - void add_edge(Vertex from, Vertex to, weight_t w = 1); - void add_edge(const Edge& e); - - template - void add_edges(const EdgeContainer& edges) - { - for (auto& e : edges) - add_edge(e); - } - - void add_edges(const std::initializer_list& edges); - - bool add_edge_no_repeat(Vertex from, Vertex to, weight_t w = 1); - - void sort_neighbors(); - - void remove_vertex(Vertex v); - void remove_edge(Vertex v, Vertex u); - - void delete_loops(); - void delete_repeated_edges(); - void make_simple(); - - // Get Graph Info - Vertex num_vertices() const { return m_numvertices; } - size_type num_edges() const { return m_numedges; } - - inline const neighbor_list& neighbors(Vertex n) const { return m_graph[n]; } - inline const neighbor_list& outneighbors(Vertex n) const - { - return m_graph[n]; - } - inline const neighbor_list& inneighbors(Vertex n) const - { - return m_graph[n]; - } - - using all_vertices = basic_natural_number; - auto vertices() const { return all_vertices{num_vertices()}; } - - std::vector edges() const; // TODO(mraggi): make*this lazy - - bool is_neighbor(Vertex from, Vertex to) const; - - weight_t edge_value(Vertex from, Vertex to) const; - - neighbor_const_iterator get_neighbor(Vertex from, Vertex to) const; - neighbor_iterator get_neighbor(Vertex from, Vertex to); - - // Start class definitions - struct Neighbor - { - explicit Neighbor() : vertex(INVALID_VERTEX), m_weight(0) {} - - explicit Neighbor(Vertex v, weight_t w = 1) : vertex(v), m_weight(w) {} - - inline operator Vertex() const { return vertex; } - - weight_t weight() const { return m_weight; } - - void set_weight(weight_t w) { m_weight = w; } - - Vertex vertex{INVALID_VERTEX}; - - private: - // comment out if not needed, and make set_weight do nothing, and make - // weight() return 1 - weight_t m_weight{1}; - }; - - struct Edge - { - Vertex from{INVALID_VERTEX}; - Vertex to{INVALID_VERTEX}; - - Edge() : m_weight(0) {} - Edge(Vertex f, Vertex t, weight_t w = 1) : from(f), to(t), m_weight(w) - {} - - Vertex operator[](bool i) const { return i ? to : from; } - - // replace by "return 1" if weight doesn't exist - weight_t weight() const { return m_weight; } - void change_weight(weight_t w) { m_weight = w; } - - bool operator==(const Edge& E) const - { - return ((from == E.from && to == E.to) || - (from == E.to && to == E.from)) && - m_weight == E.m_weight; - } - - private: - weight_t m_weight{1}; - }; - -private: - // Graph member variables - size_type m_numvertices; - size_type m_numedges{0}; - - std::vector m_graph; - bool m_neighbors_sorted{false}; -}; diff --git a/graph/IsSimple.cpp b/graph/IsSimple.cpp deleted file mode 100644 index 4225257..0000000 --- a/graph/IsSimple.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "IsSimple.hpp" -#include -bool is_simple(const Graph& G) -{ - for (auto v : G.vertices()) - { - std::unordered_set US; - for (auto u : G.neighbors(v)) - { - if (!US.emplace(u).second) - return false; - } - } - return true; -} diff --git a/graph/IsSimple.hpp b/graph/IsSimple.hpp deleted file mode 100644 index 368703b..0000000 --- a/graph/IsSimple.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "Graph.hpp" - -bool is_simple(const Graph& G); diff --git a/graph/LCA.cpp b/graph/LCA.cpp deleted file mode 100644 index 1e8287a..0000000 --- a/graph/LCA.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "LCA.hpp" -#include "ConnectedComponents.hpp" -#include "TreeAlgorithms.hpp" -#include "VectorHelpers.hpp" -#include -#include -#include - -using Vertex = Graph::Vertex; - -Vertex lowest_common_ancestor_naive(const std::vector& parents, - Vertex u, - Vertex v) -{ - std::vector explored(parents.size(), false); - - Vertex root = find(parents.begin(), parents.end(), -1) - parents.begin(); - - while (u != root) - { - explored[u] = true; - u = parents[u]; - } - - while (v != root) - { - if (explored[v]) - return v; - v = parents[v]; - } - return root; -} - -LCAWithPowersOfTwo::LCAWithPowersOfTwo(const Graph& G, Vertex root) - : L(height_map(G, root)) - , A(G.num_vertices(), - std::vector( - std::log2(*std::max_element(L.begin(), L.end()) + 1) + 1, -1)) -{ - auto parents = set_root(G, root); - - // The 2^0-th ancestor of v is simply the parent of v - for (auto v : G.vertices()) - A[v][0] = parents[v]; - - for (int i = 1; i < log_height(); ++i) - { - for (auto v : G.vertices()) - { - // My 2^i-th ancestor is the 2^{i-1} ancestor of my 2^{i-1} - // ancestor! - if (A[v][i - 1] != -1) - A[v][i] = A[A[v][i - 1]][i - 1]; - } - } -} - -Vertex LCAWithPowersOfTwo::AncestorAtLevel(Vertex u, int lvl) const -{ - int d = L[u] - lvl; - assert(d >= 0); - - while (d > 0) - { - int h = std::log2(d); - u = A[u][h]; - d -= (1 << h); - } - - return u; -} - -Vertex LCAWithPowersOfTwo::FindLCA(Vertex u, Vertex v) const -{ - if (L[u] < L[v]) - std::swap(u, v); - - u = AncestorAtLevel(u, L[v]); - - if (u == v) - return u; - - for (int i = std::log2(L[u]); i >= 0; --i) - { - if (A[u][i] != -1 && A[u][i] != A[v][i]) - { - u = A[u][i]; - v = A[v][i]; - } - } - - return A[u][0]; // which is = A[v][0] -} - -std::vector LCAWithPowersOfTwo::GetParents() const -{ - std::vector parents(A.size()); - for (size_t v = 0; v < parents.size(); ++v) - parents[v] = A[v][0]; - return parents; -} - -void LCAWithRMQ::dfs_helper(const Graph& G, - Vertex parent, - Vertex current, - int current_height) -{ - m_first_and_last_index[current].first_occurrence = m_euler_tour.size(); - m_euler_tour.push_back(current); - m_height_map.push_back(current_height); - for (auto v : G.neighbors(current)) - { - if (v != parent) - { - dfs_helper(G, current, v, current_height + 1); - m_euler_tour.push_back(current); - m_height_map.push_back(current_height); - } - } - m_first_and_last_index[current].last_occurrence = m_euler_tour.size() - 1; -} - -LCAWithRMQ::LCAWithRMQ(const Graph& G, Vertex root) - : m_first_and_last_index(G.num_vertices()) - , m_initialized(initialize(G, root)) - , m_RMQ(m_height_map) -{} - -bool LCAWithRMQ::initialize(const Graph& G, Vertex root) -{ - auto n = G.num_vertices(); - m_euler_tour.reserve(2*n + 1); - m_height_map.reserve(2*n + 1); - - dfs_helper(G, Graph::INVALID_VERTEX, root, 0); - - return true; -} - -Vertex LCAWithRMQ::FindLCA(Vertex u, Vertex v) const -{ - if (u == v) - return u; - - auto FLU = m_first_and_last_index[u]; - auto FLV = m_first_and_last_index[v]; - - if (FLU.first_occurrence > FLV.first_occurrence) - { - std::swap(u, v); - std::swap(FLU, FLV); - } - - // Now u appears before v - - // If u is an ancestor of v: - if (FLU.last_occurrence > FLV.last_occurrence) - return u; - - // else - auto best_index = - m_RMQ.GetMinIndex(FLU.last_occurrence, FLV.first_occurrence); - return m_euler_tour[best_index]; -} diff --git a/graph/LCA.hpp b/graph/LCA.hpp deleted file mode 100644 index 550dec1..0000000 --- a/graph/LCA.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "Graph.hpp" -#include "RangeMinQuery.hpp" -#include "TreeAlgorithms.hpp" - -Graph::Vertex lowest_common_ancestor_naive( - const std::vector& parents, Graph::Vertex u, Graph::Vertex v); - -class LCAWithPowersOfTwo -{ -public: - using Vertex = Graph::Vertex; - - LCAWithPowersOfTwo(const Graph& G, Vertex root); - - Vertex FindLCA(Vertex u, Vertex v) const; - - const std::vector>& Ancestors() const { return A; } - const auto& Levels() const { return L; } - - std::vector GetParents() const; - -private: - // L[v] is the level (distance to root) of vertex v - std::vector L; - - // A[v][i] is the 2^i ancestor of vertex v - std::vector> A; - - int log_height() const { return A[0].size(); } - - Vertex AncestorAtLevel(Vertex u, int lvl) const; -}; - -class LCAWithRMQ -{ -public: - using Vertex = Graph::Vertex; - using index_t = std::make_signed_t; - - LCAWithRMQ(const Graph& G, Vertex root); - - Vertex FindLCA(Vertex u, Vertex v) const; - - auto& get_euler_tour() const { return m_euler_tour; } - auto& get_height_map() const { return m_height_map; } - - auto& get_first_and_last_occurrences() const - { - return m_first_and_last_index; - } - -private: - struct MyFirstMyLastMyEverything - { - index_t first_occurrence; - index_t last_occurrence; - }; - - void dfs_helper(const Graph& G, - Vertex parent, - Vertex current, - int current_height); - - bool initialize(const Graph& G, Vertex root); - - std::vector m_first_and_last_index; - std::vector m_euler_tour; - std::vector m_height_map; - bool m_initialized; - range_min_query m_RMQ; -}; diff --git a/graph/MinSpanningTree.cpp b/graph/MinSpanningTree.cpp deleted file mode 100644 index 6fd2e2c..0000000 --- a/graph/MinSpanningTree.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "MinSpanningTree.hpp" -#include "utils/disjoint_sets.hpp" -#include - -using Edge = Graph::Edge; -using Vertex = Graph::Vertex; - -struct by_reverse_weight -{ - template - bool operator()(const T& a, const T& b) - { - return a.weight() > b.weight(); - } -}; - -std::vector prim(const Graph& G) -{ - auto n = G.num_vertices(); - - std::vector T; - if (n < 2) - return T; - - Vertex num_tree_edges = n - 1; - - T.reserve(num_tree_edges); - - std::vector explored(n, false); - - std::priority_queue, by_reverse_weight> - EdgesToExplore; - - explored[0] = true; - for (auto v : G.neighbors(0)) - { - EdgesToExplore.emplace(0, v, v.weight()); - } - - while (!EdgesToExplore.empty()) - { - Edge s = EdgesToExplore.top(); - EdgesToExplore.pop(); - - if (explored[s.to]) - continue; - - T.emplace_back(s); - - --num_tree_edges; - if (num_tree_edges == 0) - return T; - - explored[s.to] = true; - for (auto v : G.neighbors(s.to)) - { - if (!explored[v]) - EdgesToExplore.emplace(s.to, v, v.weight()); - } - } - return T; -} - -std::vector kruskal(const Graph& G) -{ - auto n = G.num_vertices(); - Vertex num_tree_edges = n - 1; - - std::vector T; - T.reserve(num_tree_edges); - - auto E = G.edges(); - - std::sort(E.begin(), E.end(), [](const Edge& a, const Edge& b) { - if (a.weight() != b.weight()) - return a.weight() < b.weight(); - if (a.from != b.from) - return a.from < b.from; - return a.to < b.to; - }); - - disjoint_sets D(G.num_vertices()); - - for (auto& e : E) - { - Vertex a = e.from; - Vertex b = e.to; - - if (!D.are_in_same_connected_component(a, b)) - { - D.merge(a, b); - T.emplace_back(e); - --num_tree_edges; - if (num_tree_edges == 0) - return T; - } - } - - return T; -} diff --git a/graph/MinSpanningTree.hpp b/graph/MinSpanningTree.hpp deleted file mode 100644 index ed15e02..0000000 --- a/graph/MinSpanningTree.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "Graph.hpp" - -std::vector prim(const Graph& G); - -std::vector kruskal(const Graph& G); diff --git a/graph/PrintUtils.hpp b/graph/PrintUtils.hpp deleted file mode 100644 index 767674b..0000000 --- a/graph/PrintUtils.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "Graph.hpp" -#include - -inline std::ostream& operator<<(std::ostream& os, const Graph::Neighbor& N) -{ - os << '(' << N.vertex << ',' << N.weight() << ')'; - return os; -} - -inline std::ostream& operator<<(std::ostream& os, const Graph::Edge& E) -{ - os << '{' << E.from << '-' << E.to << ',' << E.weight() << '}'; - return os; -} - -inline std::string to_string(const Graph::Neighbor& N) -{ - std::stringstream ss; - ss << N; - return ss.str(); -} - -inline std::string to_string(const Graph::Edge& E) -{ - std::stringstream ss; - ss << E; - return ss.str(); -} - -inline void print_for_sage(const Graph& G) -{ - using std::cout; - using std::endl; - cout << "G = Graph(" << G.num_vertices() << ")" << endl; - for (auto e : G.edges()) - { - cout << "G.add_edge(" << e.from << "," << e.to << ")\n"; - } -} diff --git a/graph/ShortestPaths.cpp b/graph/ShortestPaths.cpp deleted file mode 100644 index 5c6c4e2..0000000 --- a/graph/ShortestPaths.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "ShortestPaths.hpp" - -// Dijkstra and Astar are now templates :) - -using Matrix = std::vector>; -Matrix AllPairsShortestPaths(const Graph& G) -{ - constexpr Distance oo = INF/2-1; - auto n = G.num_vertices(); - Matrix D(n,Row(n,oo)); - - for (auto u : G.vertices()) - { - D[u][u] = 0; - for (auto v : G.neighbors(u)) - D[u][v] = v.weight(); - } - - for (auto u : G.vertices()) - { - for (auto v : G.vertices()) - { - for (auto w : G.vertices()) - { - auto dvuw = D[v][u] + D[u][w]; - if (D[v][w] > dvuw) - D[v][w] = dvuw; - } - } - } - - return D; -} diff --git a/graph/ShortestPaths.hpp b/graph/ShortestPaths.hpp deleted file mode 100644 index 1c3e9e1..0000000 --- a/graph/ShortestPaths.hpp +++ /dev/null @@ -1,269 +0,0 @@ -#pragma once - -#include "Graph.hpp" -#include - -using Vertex = Graph::Vertex; -using Edge = Graph::Edge; -using Distance = Graph::sumweight_t; - -constexpr auto INF = std::numeric_limits::max(); - -// Used by both A* and Dijkstra -template > -inline Path PathFromParents(Vertex origin, - Vertex destination, - const std::vector& distance, - const std::vector& parent) -{ - Path P; - - if (origin == destination) - { - P.emplace_front(origin, 0); - return P; - } - - auto remaining = distance[destination]; - - if (remaining == INF) - return P; - - do - { - auto previous = destination; - destination = parent[destination]; - auto d = distance[previous] - distance[destination]; - P.emplace_front(previous, d); - } while (destination != origin); - - P.emplace_front(origin, 0); - - return P; -} - -//------------------ Start Dijsktra Searcher - -struct DummyPath -{ - DummyPath(Vertex v, Distance d) : last(v), length(d) {} - Vertex last; - Distance length; -}; - -inline bool operator<(const DummyPath& a, const DummyPath& b) -{ - return a.length > b.length; -} - -class DijkstraSearcher -{ -public: - // If destination is invalid, it constructs all single-source shortest - // paths. If destination is a specific vertex, the searcher stops when it - // finds it. - DijkstraSearcher(const Graph& G, - Vertex origin_, - Vertex destination_ = Graph::INVALID_VERTEX) - : origin(origin_) - , destination(destination_) - , distance(G.num_vertices(), INF) - , parent(G.num_vertices(), -1) - { - distance[origin] = 0; - - std::priority_queue frontier; - - frontier.emplace(origin, 0); - - while (!frontier.empty()) - { - auto P = frontier.top(); - frontier.pop(); - - if (P.length > distance[P.last]) - continue; - - if (P.last == destination) - break; - - for (auto& v : G.neighbors(P.last)) - { - auto d = P.length + v.weight(); - if (distance[v] > d) - { - distance[v] = d; - parent[v] = P.last; - frontier.emplace(v, d); - } - } - } - } - - // dest might be different from destination, if and only if, either - // destination is Graph::INVALID_VERTEX or distance from origin to dest is - // smaller than distance to destination. - template > - Path GetPath(Vertex dest = Graph::INVALID_VERTEX) const - { - if (dest == Graph::INVALID_VERTEX) - dest = destination; - - assert(dest != Graph::INVALID_VERTEX); - - return PathFromParents(origin, dest, distance, parent); - } - - Vertex Origin() const { return origin; } - Vertex Destination() const { return destination; } - - const std::vector& Distances() const { return distance; } - const std::vector& Parents() const { return parent; } - -private: - Vertex origin; - Vertex destination; - std::vector distance; - std::vector parent; -}; - -template > -Path Dijkstra(const Graph& G, Vertex origin, Vertex destination) -{ - return DijkstraSearcher(G, origin, destination).GetPath(); -} - -//------------------- START A* searcher - -struct DummyPathWithHeuristic -{ - DummyPathWithHeuristic(Vertex v, Distance c, Distance h) - : last(v), cost(c), heuristic(h) - {} - Vertex last; - Distance cost; - Distance heuristic; - - Distance cost_plus_heuristic() const { return cost + heuristic; } -}; - -inline bool operator<(const DummyPathWithHeuristic& A, - const DummyPathWithHeuristic& B) -{ - if (A.cost_plus_heuristic() != B.cost_plus_heuristic()) - return A.cost_plus_heuristic() > B.cost_plus_heuristic(); - - if (A.heuristic != B.heuristic) - return A.heuristic > B.heuristic; - - // if same cost plus heuristic, whatever. - return A.last > B.last; -} - -// Managed to make this not a template by having templated constructors. -class AstarSearcher -{ -public: - // Finds a path from origin to destination using heuristic h - template - AstarSearcher(const Graph& G, - Vertex origin_, - Vertex destination_, - Heuristic h) - : origin(origin_) - , destination(destination_) - , distance(G.num_vertices(), INF) - , parent(G.num_vertices(), Graph::INVALID_VERTEX) - { - auto objective = [destination_](Vertex v) { return v == destination_; }; - Init(G, objective, h); - } - - // Finds a path from origin to some destination that satisfies predicte - // objective, using heuristic h - template - AstarSearcher(const Graph& G, - Vertex origin_, - Objective objective, - Heuristic h) - : origin(origin_) - , destination(Graph::INVALID_VERTEX) - , distance(G.num_vertices(), INF) - , parent(G.num_vertices(), Graph::INVALID_VERTEX) - { - Init(G, objective, h); - } - - template > - Path GetPath() const - { - return PathFromParents(origin, destination, distance, parent); - } - - Vertex Origin() const { return origin; } - Vertex Destination() const { return destination; } - - Distance PathCost() const { return distance[destination]; } - - const std::vector& Distances() const { return distance; } - const std::vector& Parents() const { return parent; } - -private: - Vertex origin; - Vertex destination; - std::vector distance; - std::vector parent; - - template - void Init(const Graph& G, Objective objective, Heuristic h) - { - using std::cout; - using std::endl; - distance[origin] = 0; - - std::priority_queue frontier; - - frontier.emplace(origin, 0, h(origin)); - - while (!frontier.empty()) - { - auto P = frontier.top(); - frontier.pop(); - - if (P.cost > distance[P.last]) - continue; - - if (objective(P.last)) - { - destination = P.last; - return; - } - - for (auto& v : G.neighbors(P.last)) - { - auto d = P.cost + v.weight(); - if (distance[v] > d) - { - distance[v] = d; - parent[v] = P.last; - frontier.emplace(v, d, h(v)); - } - } - } - } -}; - -template > -Path Astar(const Graph& G, Vertex origin, Objective objective, Heuristic h) -{ - return AstarSearcher(G, origin, objective, h).GetPath(); -} - -using Row = std::vector; -using Matrix = std::vector; - - -// Warning: This algo is O(V^3)!! -Matrix AllPairsShortestPaths(const Graph& G); diff --git a/graph/TreeAlgorithms.cpp b/graph/TreeAlgorithms.cpp deleted file mode 100644 index 463c205..0000000 --- a/graph/TreeAlgorithms.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "TreeAlgorithms.hpp" -#include "ConnectedComponents.hpp" -#include "VectorHelpers.hpp" - -#include -#include -#include - -using Vertex = Graph::Vertex; - -bool is_tree(const Graph& G) -{ - return G.num_edges() + 1 == G.num_vertices() && is_connected(G); -} - -std::vector set_root(const Graph& G, Vertex root) -{ - std::vector parent(G.num_vertices()); - - parent[root] = Graph::INVALID_VERTEX; - - std::stack frontier; - frontier.emplace(root); - - while (!frontier.empty()) - { - auto p = frontier.top(); - frontier.pop(); - - for (auto u : G.neighbors(p)) - { - if (parent[p] == u) - continue; - parent[u] = p; - frontier.emplace(u); - } - } - return parent; -} - -std::vector height_map(const Graph& G, Vertex root) -{ - std::vector level(G.num_vertices(), -1); - - level[root] = 0; - - std::stack frontier; - frontier.emplace(root); - - while (!frontier.empty()) - { - auto p = frontier.top(); - frontier.pop(); - int current_level = level[p]; - - for (auto u : G.neighbors(p)) - { - if (level[u] != -1) - continue; - level[u] = current_level + 1; - frontier.emplace(u); - } - } - - return level; -} diff --git a/graph/TreeAlgorithms.hpp b/graph/TreeAlgorithms.hpp deleted file mode 100644 index 494b6cc..0000000 --- a/graph/TreeAlgorithms.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "Graph.hpp" -#include "RangeMinQuery.hpp" - -bool is_tree(const Graph& G); - -// calculate its parent (for each vertex) -std::vector set_root(const Graph& G, Graph::Vertex root); -std::vector height_map(const Graph& G, Graph::Vertex root); diff --git a/graph/utils/Misc.hpp b/graph/utils/Misc.hpp deleted file mode 100644 index cda22f9..0000000 --- a/graph/utils/Misc.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -////////////////////////////////////////// -/// \brief This is what operator%should be but isn't (!). -/// -/// C++ modulo operator%is dumb for negative integers: (-7)%3 returns -1, -/// instead of 2. This fixes it. \return an integer in [0,b) -////////////////////////////////////////// -template -inline IntType modulo(IntType a, IntType b) -{ - IntType r = a%b; - if (r < 0) - r += b; - return r; -} - -////////////////////////////////////////// -/// \brief This is what operator %= should be but isn't (!). -/// -/// C++ modulo operator %= is dumb for negative integers: (-7)%3 returns -1, -/// instead of 2. This fixes it. -////////////////////////////////////////// -template -inline void reduce_modulo(IntType& a, IntType b) -{ - a %= b; - if (a < 0) - a += b; -} - -template -inline T pow(T a, std::uint64_t n) -{ - T r = 1L; - - while (n > 0UL) - { - if (n & 1UL) // if odd - r *= a; - - n >>= 1; - a *= a; - } - - return r; -} - -// Deprecated in c++17. Here for use in c++14. -template -T gcd(T a, T b) -{ - while (b != 0) - { - T r = a%b; - a = b; - b = r; - } - return a; -} - -template -T reduce_fraction(Container Numerator, Container Denominator) -{ - for (auto& b : Denominator) - { - for (auto& a : Numerator) - { - auto d = gcd(a, b); - a /= d; - b /= d; - if (b == 1) - break; - } - } - - T result = 1; - for (auto a : Numerator) - result *= a; - return result; -} - -template , - class Map = std::unordered_map> -class map_with_default : public Map -{ - -public: - // using Base = typename Map; - explicit map_with_default(const Value& default_value) - : m_default(default_value) - {} - - Value operator()(const Key& key) const - { - auto it = Map::find(key); - if (it == Map::end()) - return m_default; - return it->second; - } - - Value& operator[](const Key& key) - { - auto it = Map::find(key); - if (it == Map::end()) - { - Map::operator[](key) = m_default; - return Map::operator[](key); - } - return it->second; - } - -private: - Value m_default; -}; - -template , - class Map = std::unordered_map> -class map_with_default_by_ref : public Map -{ - -public: - // using Base = typename Map; - explicit map_with_default_by_ref(const Value& default_value) - : m_default(default_value) - {} - - Value operator()(const Key& key) const - { - auto it = Map::find(key); - if (it == Map::end()) - return m_default; - return it->second; - } - - Value& operator[](const Key& key) - { - auto it = Map::find(key); - if (it == Map::end()) - { - it = Map::insert({key, m_default}).first; - // Map::operator[](key) = m_default; - } - return it->second; - } - - // void set_default(const Value& new_value) { m_default = new_value; } - -private: - const Value& m_default; -}; - -template -Iter find_binary(const Iter& first, const Iter& last, const T& t) -{ - auto it = std::lower_bound(first, last, t); - - if (it == last || *it != t) - return last; - - return it; -} - -template -class PriorityQueueWithReserve : public std::priority_queue -{ -public: - void reserve(size_t amount) { this->c.reserve(amount); } -}; \ No newline at end of file diff --git a/graph/utils/NaturalNumber.hpp b/graph/utils/NaturalNumber.hpp deleted file mode 100644 index 7b97a24..0000000 --- a/graph/utils/NaturalNumber.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once -#include "Misc.hpp" -#include -#include -#include - -////////////////////////////////////////// -/// \brief In set theory, a common way of defining a natural number is. n := -/// {0,1,2,...,n-1}, with 0 = {}. -////////////////////////////////////////// -template -class basic_natural_number -{ -public: - using difference_type = long long; // NOLINT - using size_type = long long; // NOLINT - using value_type = IntType; - class iterator; - using const_iterator = iterator; - -public: - basic_natural_number(IntType n) : m_n(n) { assert(n >= 0); } // NOLINT - - class iterator - { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = IntType; - using difference_type = std::int64_t; - using pointer = IntType const*; - using reference = const IntType&; - - explicit iterator(IntType t = 0) : m_ID(t) {} - - inline iterator& operator++() - { - ++m_ID; - return *this; - } - inline iterator& operator--() - { - --m_ID; - return *this; - } - inline const IntType& operator*() const { return m_ID; } - - inline iterator& operator+=(difference_type n) - { - m_ID += n; - return *this; - } - - inline iterator& operator-=(difference_type n) - { - return operator+=(-n); - } - - inline bool operator==(const iterator& it) { return *it == m_ID; } - - inline bool operator!=(const iterator& it) { return *it != m_ID; } - - inline difference_type operator-(const iterator& it) - { - return m_ID - *it; - } - - private: - IntType m_ID{0}; - - friend class basic_natural_number; - }; // end class iterator - - iterator begin() const { return iterator(0); } - iterator end() const { return iterator(m_n); } - - IntType operator[](size_type m) const { return m; } - size_type size() const { return m_n; } - - template - IntType partition_point(Pred p) - { - return *std::partition_point(begin(), end(), p); - } - - explicit operator std::vector() const - { - return std::vector(begin(), end()); - } - -private: - IntType m_n; -}; // end class basic_natural_number - -template -inline typename basic_natural_number::iterator -operator+(typename basic_natural_number::iterator it, - typename basic_natural_number::difference_type n) -{ - it += n; - return it; -} - -template -inline typename basic_natural_number::iterator -operator-(typename basic_natural_number::iterator it, - typename basic_natural_number::difference_type n) -{ - it -= n; - return it; -} - -using natural_number = basic_natural_number; -using big_natural_number = basic_natural_number; // NOLINT - -template -basic_natural_number indices(const Container& C) -{ - return basic_natural_number(C.size()); -} diff --git a/graph/utils/Probability.hpp b/graph/utils/Probability.hpp deleted file mode 100644 index b0d399d..0000000 --- a/graph/utils/Probability.hpp +++ /dev/null @@ -1,149 +0,0 @@ -#pragma once - -#include "Misc.hpp" -#include -#include -#include -// Who came up with the dumb C++11 way of getting random stuff? -// It's obviously missing some utility functions. Here they are. - -/** - *@brief Just a helper function to get the default random engine - */ -inline std::default_random_engine& random_engine() -{ - using RE = std::default_random_engine; - using result_type = RE::result_type; - static RE e(static_cast(time(nullptr))); - return e; -} - -/** - *@brief Returns true with probability p and false with probability 1-p - *@return true or false according to probability p, which must be a number - *between 0 and 1. - */ -inline bool probability_of_true(double p) -{ - std::bernoulli_distribution d(p); - return d(random_engine()); -} - -/** - *@brief "I just wanted a random integer! - *@return A random integer in the range [from,thru), with uniform probability - *distribution - */ -template -IntType random_int(IntType from, IntType thru) -{ - std::uniform_int_distribution d{}; - using parm_t = typename decltype(d)::param_type; - return d(random_engine(), parm_t{from, --thru}); -} - -/** - *@brief "I just wanted a random float! - *@return A random float number in the range [from,thru), with uniform - *probability distribution - */ -template -FloatType random_real(FloatType from, FloatType upto) -{ - std::uniform_real_distribution<> d{}; - using parm_t = decltype(d)::param_type; - return d(random_engine(), parm_t{from, upto}); -} - -template -auto random_sample_array(const RAContainer& population, int k) -{ - using T = typename RAContainer::value_type; - int n = population.size(); - std::vector sample; - sample.reserve(k); - std::vector explored(n, 0); - - while (k > 0) - { - auto i = random_int(0, n); - - if (explored[i] == 0) - { - explored[i] = 1; - sample.emplace_back(population[i]); - --k; - } - } - - return sample; -} - -template -auto random_sample_shuffle(const RAContainer& population, int k) -{ - using T = typename RAContainer::value_type; - - int n = population.size(); - - std::vector sample(population.begin(), population.end()); - for (int i = 0; i < k; ++i) - { - int j = random_int(i, n); - std::swap(sample[i], sample[j]); - } - - sample.erase(sample.begin() + k, sample.end()); - return sample; -} - -template -auto random_sample(const RAContainer& population, int k) -{ - using T = typename RAContainer::value_type; - int n = population.size(); - - if (k > n) - k = n; - - // double factor = linear_convert(sizeof(T), 0, 200, 0.0, 0.9); - // factor = std::min(factor,0.95); - double factor = 0.5; - if (std::is_trivially_copyable::value) - { - factor = 0.1; - } - - if (k < factor*n) - return random_sample_array(population, k); - - return random_sample_shuffle(population, k); -} - -template -auto random_choice(const RAContainer& population) -{ - auto n = population.size(); - return population[random_int(0, n)]; -} - -template -auto random_order(const RAContainer& C) -{ - using T = typename RAContainer::value_type; - std::vector X(C.begin(), C.end()); - - std::shuffle(X.begin(), X.end(), random_engine()); - - return X; -} - -template -auto random_order(const std::initializer_list& C) -{ - std::vector X(C.begin(), C.end()); - - std::shuffle(X.begin(), X.end(), random_engine()); - - return X; -} diff --git a/graph/utils/RangeMinQuery.hpp b/graph/utils/RangeMinQuery.hpp deleted file mode 100644 index 547d136..0000000 --- a/graph/utils/RangeMinQuery.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -template > -class range_min_query -{ - using index_type = std::make_signed_t; - using Row = std::vector; - using value_type = typename RAContainer::value_type; - -public: - range_min_query(const RAContainer& A, - Compare comp = std::less()) - : A_(A), T(A.size(), Row(std::log2(A.size()) + 1, -1)), comp_(comp) - { - index_type n = A.size(); - index_type max_h = T[0].size(); - - for (index_type x = 0; x < n; ++x) - { - T[x][0] = x; - } - - for (index_type h = 1; h < max_h; ++h) - { - for (index_type x = 0; x < n; ++x) - { - if (x + (1 << h) <= n) - { - index_type mid = x + (1 << (h - 1)); - T[x][h] = best(T[x][h - 1], T[mid][h - 1]); - } - } - } - } - - // Get min index in range [L,R) - index_type GetMinIndex(index_type L, index_type R) const - { - assert(0 <= L && L < R && R <= index_type(A_.size())); - index_type h = std::log2(R - L); - - index_type min_index_starting_at_L = T[L][h]; - index_type min_index_ending_at_R = BestEndingAt(R - 1, h); - - return best(min_index_starting_at_L, min_index_ending_at_R); - } - -private: - // A reference to the original container - const RAContainer& A_; - - // T[x][i] contains the index of the - // minimum of range [x,x+1,...,x+2^i) - std::vector T; - - Compare comp_; - - index_type best(index_type i, index_type j) const - { - if (comp_(A_[j], A_[i])) - return j; - return i; - } - - index_type BestEndingAt(index_type R, index_type h) const - { - return T[R - (1 << h) + 1][h]; - } -}; - -// This function is deprecated with C++17, but useful in c++14 and 11 -template > -range_min_query make_range_min_query( - const RAContainer& A, - Compare comp = std::less()) -{ - return range_min_query(A, comp); -} diff --git a/graph/utils/TimeHelpers.hpp b/graph/utils/TimeHelpers.hpp deleted file mode 100644 index 37f6e08..0000000 --- a/graph/utils/TimeHelpers.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include - -// You probably want something else, but whatever. -// TODO(mraggi): Use a better method of casting to double rather than measure in -// microseconds and the multiply by 1/1M, which is stupid. - -inline double diffclock(clock_t a, clock_t b) -{ - const double c = 1.0/CLOCKS_PER_SEC; - return double(a - b)*c; -} - -using clockt = std::chrono::time_point; - -inline double diffclockt(clockt a, clockt b) -{ - const double t = 0.000001; - return std::chrono::duration_cast(a - b) - .count() * - t; -} - -class RClock -{ -public: - static RClock& Instance() - { - static RClock A; - return A; - } - - std::chrono::time_point start_timer; - -private: - RClock() : start_timer(std::chrono::steady_clock::now()) {} -}; - -class Chronometer -{ -public: - Chronometer() : m_timer(std::chrono::steady_clock::now()) {} - - double Reset() - { - auto tlast = m_timer; - m_timer = std::chrono::steady_clock::now(); - - return std::chrono::duration_cast>( - m_timer - tlast) - .count(); - } - - double Peek() const - { - auto tnow = std::chrono::steady_clock::now(); - - return std::chrono::duration_cast>( - tnow - m_timer) - .count(); - } - - std::chrono::time_point m_timer; -}; - -inline double TimeFromStart() -{ - auto tnow = std::chrono::steady_clock::now(); - - return diffclockt(tnow, RClock::Instance().start_timer); -} diff --git a/graph/utils/VectorHelpers.hpp b/graph/utils/VectorHelpers.hpp deleted file mode 100644 index aefcc0f..0000000 --- a/graph/utils/VectorHelpers.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Misc.hpp" - -//////////////////////////////////// -/// \brief Converts a std::vector into a std::vector, provided U can be -/// converted to T -//////////////////////////////////// -template -std::vector Convert(const std::vector& G) -{ - auto n = G.size(); - std::vector toReturn(n); - - for (size_t i = 0; i < n; ++i) - { - toReturn[i] = static_cast(G[i]); - } - - return toReturn; -} - -//////////////////////////////////// -/// \brief prints out a space separated std::vector. -//////////////////////////////////// -template -std::ostream& operator<<(std::ostream& os, const std::vector& V) -{ - if (V.empty()) - return os; - auto it = V.begin(); - os << *it; - ++it; - for (; it != V.end(); ++it) - { - os << ' ' << *it; - } - - return os; -} - -//////////////////////////////////// -/// \brief prints out a matrix -//////////////////////////////////// -template -std::ostream& operator<<(std::ostream& os, const std::vector>& V) -{ - os << std::endl; - for (auto& v : V) - os << v << std::endl; - - return os; -} - -///////////////////////////// -/// \brief Specialization for std::vector printouts for std::vector so -/// that it doesn't print out spaces -///////////////////////////// -inline std::ostream& operator<<(std::ostream& os, const std::vector& V) -{ - for (bool v : V) - os << v; - - return os; -} - -/////////////////////////// -/// \brief Function composition -/// -/// \return f∘g -/////////////////////////// -template -vecT compose(const vecT& f, const std::vector& g) -{ - // typename vecT::value_type u(0); - vecT toReturn(g.size()); - - for (size_t i = 0; i < g.size(); ++i) - { - assert(g[i] < f.size()); - toReturn[i] = f[g[i]]; - } - - return toReturn; -} - -template -std::vector make_reserved_vector(size_t n) -{ - std::vector A; - A.reserve(n); - return A; -} - -template -inline void remove_unordered(std::vector& X, Iter it) -{ - *it = X.back(); - X.pop_back(); -} - -template -inline void remove_first(std::vector& X, const T& t) -{ - auto it = std::find(X.begin(), X.end(), t); - X.erase(it); -} - -template -inline void remove_first_unordered(std::vector& X, const T& t) -{ - auto it = std::find(X.begin(), X.end(), t); - remove_unordered(X, it); -} - -template -inline void remove_all_if(std::vector& X, Func f) -{ - auto it = std::remove_if(X.begin(), X.end(), f); - X.erase(it, X.end()); -} diff --git a/graph/utils/disjoint_sets.hpp b/graph/utils/disjoint_sets.hpp deleted file mode 100644 index ca32be7..0000000 --- a/graph/utils/disjoint_sets.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include - -class disjoint_sets -{ -public: - using size_type = std::int64_t; - using index_type = std::int64_t; - - explicit disjoint_sets(index_type n) : parent(n), m_num_components(n) - { - std::iota(parent.begin(), parent.end(), 0L); - } - - index_type find_root(index_type t) - { - std::vector branch; - branch.emplace_back(t); - while (t != parent[t]) - { - t = parent[t]; - branch.emplace_back(t); - } - for (auto u : branch) - parent[u] = t; - return t; - } - - void reset() - { - std::iota(parent.begin(), parent.end(), 0); - m_num_components = size(); - } - - void merge(index_type a, index_type b) - { - index_type ra = find_root(a); - index_type rb = set_parent(b, ra); - - if (ra != rb) - --m_num_components; - } - - bool are_in_same_connected_component(index_type a, index_type b) - { - return find_root(a) == find_root(b); - } - - size_type num_components() const { return m_num_components; } - - index_type size() const { return parent.size(); } - - auto& parents() const { return parent; } - -private: - // returns ORIGINAL parent of x - index_type set_parent(index_type x, index_type p) - { - while (x != parent[x]) - { - index_type t = parent[x]; - parent[x] = p; - x = t; - } - parent[x] = p; - return x; - } - - std::vector parent; - size_type m_num_components; -}; diff --git a/graph/utils/experimental/RangeMinQueryIters.hpp b/graph/utils/experimental/RangeMinQueryIters.hpp deleted file mode 100644 index f99cad9..0000000 --- a/graph/utils/experimental/RangeMinQueryIters.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include - -#include "VectorHelpers.hpp" -#include - -template ::value_type>> -class RangeMinQuery -{ - using index_type = std::int64_t; - using Row = std::vector; - using value_type = typename std::iterator_traits::value_type > ; - -public: - RangeMinQuery(Iter first, Iter last, Compare comp = std::less()) - : first_(first) - , last_(last) - , Start_(Initialize(last - first)) - , End_(Initialize(last - first)) - , comp_(comp) - { - index_type max_h = Start_[0].size(); - // Initialize Start_ and End_ - for (index_type x = 0; x < A.size(); ++x) - { - Start_[x][0] = x; - End_[x][0] = x; - } - - for (index_type h = 1; h < max_h; ++h) - { - for (index_type x = 0; x < A.size(); ++x) - { - if (x + (1 << h) <= A.size()) - { - index_type mid = x + (1 << (h - 1)); - Start_[x][h] = best(Start_[x][h - 1], Start_[mid][h - 1]); - } - - if (x - (1 << h) >= -1) - { - index_type mid = x - (1 << (h - 1)); - End_[x][h] = best(End_[x][h - 1], End_[mid][h - 1]); - } - } - } - - using namespace std; - cout << "A = " << A << endl; - cout << "Start_ = " << Start_ << endl; - cout << "End_ = " << End_ << endl; - } - - // Get min index in range [L,R) - index_type GetMinIndex(index_type L, index_type R) - { - index_type h = std::log2(R - L); - using namespace std; - cout << "h = " << h << endl; - index_type min_index_starting_at_L = Start_[L][h]; - cout << "mL = " << min_index_starting_at_L << endl; - index_type min_index_ending_at_R = End_[R - 1][h]; - cout << "mR = " << min_index_ending_at_R << endl; - - return best(min_index_starting_at_L, min_index_ending_at_R); - } - -private: - Iter first; - Iter last; - // Start_[x][i] contains the index of the minimum of range [x,x+1,...,x+2^i) - std::vector Start_; - // End_[x][i] contains the index of the minimum of range (x-2^i,...,x-1,x] - std::vector End_; - Compare comp_; - - index_type best(index_type i, index_type j) - { - if (comp_(A_[i], A_[j])) - return i; - return j; - } - - static std::vector Initialize(index_type diff) - { - return std::vector(diff, Row(std::log2(diff) + 1)); - } -}; - -template > -RangeMinQuery -make_range_min_query(const RAContainer& A, - Compare comp = std::less()) -{ - return RangeMinQuery(A, comp); -} \ No newline at end of file diff --git a/install_ubuntu1604.sh b/install_ubuntu1604.sh index ad38968..096672d 100644 --- a/install_ubuntu1604.sh +++ b/install_ubuntu1604.sh @@ -47,6 +47,3 @@ mkdir build cd build cmake .. make -./playground -./graph_tests -./visualizer diff --git a/install_ubuntu1710.sh b/install_ubuntu1710.sh index f6f92f4..51f1166 100644 --- a/install_ubuntu1710.sh +++ b/install_ubuntu1710.sh @@ -36,6 +36,3 @@ mkdir build cd build cmake .. make -./playground -./graph_tests -./visualizer