From a6dd9cc57b236d141c61b03cfa2f73ad5540c56b Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Sat, 15 Aug 2015 20:17:18 +0200 Subject: [PATCH] continue with graphs --- .../src/graph/shortestpath/BellmanFord.cpp | 20 ++---- .../src/graph/shortestpath/BellmanFord.h | 21 +++--- alib2algo/src/graph/shortestpath/Dijkstra.cpp | 20 ++---- alib2algo/src/graph/shortestpath/Dijkstra.h | 21 +++--- .../src/graph/shortestpath/FloydWarshall.cpp | 20 ++---- .../src/graph/shortestpath/FloydWarshall.h | 21 +++--- alib2algo/src/graph/sort/TopologicalSort.cpp | 34 ++-------- alib2algo/src/graph/sort/TopologicalSort.h | 21 +++--- .../src/graph/spanningtree/JarnikPrim.cpp | 46 +++---------- alib2algo/src/graph/spanningtree/JarnikPrim.h | 21 +++--- alib2algo/src/graph/traverse/Bfs.cpp | 67 ++++++------------- alib2algo/src/graph/traverse/Bfs.h | 22 +++--- alib2algo/src/graph/traverse/Dfs.cpp | 67 ++++++------------- alib2algo/src/graph/traverse/Dfs.h | 22 +++--- .../src/regexp/transform/RegExpIterate.h | 3 +- alib2algo/test-src/graph/traverse/BfsTest.cpp | 8 ++- alib2algo/test-src/graph/traverse/DfsTest.cpp | 8 ++- alib2data/src/common/multipleDispatch.hpp | 39 +++++++++++ 18 files changed, 181 insertions(+), 300 deletions(-) diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.cpp b/alib2algo/src/graph/shortestpath/BellmanFord.cpp index 85c3f35fc7..3e8c37be70 100644 --- a/alib2algo/src/graph/shortestpath/BellmanFord.cpp +++ b/alib2algo/src/graph/shortestpath/BellmanFord.cpp @@ -104,9 +104,7 @@ static BellmanFord::Result bellmanford_impl(const UndirectedGraph &graph, const BellmanFord::Result BellmanFord::bellmanford(const Graph &graph, const Node &start) { - Data data = {start, BellmanFord::Result {}}; - graph.getData().Accept(static_cast<void*>(&data), BELLMAN_FORD); - return data.out; + return getInstance().dispatch(graph.getData(), start); } BellmanFord::Result BellmanFord::bellmanford(const DirectedGraph &graph, const Node &start) @@ -114,24 +112,14 @@ BellmanFord::Result BellmanFord::bellmanford(const DirectedGraph &graph, const N return bellmanford_impl(graph, start); } +auto BellmanFordDirectedGraph = BellmanFord::RegistratorWrapper<BellmanFord::Result, graph::DirectedGraph>(BellmanFord::getInstance(), BellmanFord::bellmanford); + BellmanFord::Result BellmanFord::bellmanford(const UndirectedGraph &graph, const Node &start) { return bellmanford_impl(graph, start); } -void BellmanFord::Visit(void *data, const DirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - d.out = bellmanford(graph, d.start); -} - -void BellmanFord::Visit(void *data, const UndirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - d.out = bellmanford(graph, d.start); -} - -const BellmanFord BellmanFord::BELLMAN_FORD; +auto BellmanFordUndirectedGraph = BellmanFord::RegistratorWrapper<BellmanFord::Result, graph::UndirectedGraph>(BellmanFord::getInstance(), BellmanFord::bellmanford); } // namespace shortestpath diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.h b/alib2algo/src/graph/shortestpath/BellmanFord.h index 730175966d..9c5a07e2dd 100644 --- a/alib2algo/src/graph/shortestpath/BellmanFord.h +++ b/alib2algo/src/graph/shortestpath/BellmanFord.h @@ -1,28 +1,24 @@ #ifndef GRAPH_BELLMAN_FORD_H_ #define GRAPH_BELLMAN_FORD_H_ +#include <common/multipleDispatch.hpp> #include <unordered_map> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace shortestpath -{ +namespace shortestpath { // Bellman-Ford only works on graphs without negative-weight cycle // However it will detect the negative-weight cycle and throw exception // // note: negative-weight undirected edge = negative-weight cycle -class BellmanFord : public graph::VisitableGraphBase::const_visitor_type -{ +class BellmanFord : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> { public: - BellmanFord() {} - typedef std::unordered_map<Node, int> Result; static Result bellmanford(const Graph &graph, const Node &start); @@ -30,11 +26,10 @@ public: static Result bellmanford(const DirectedGraph &graph, const Node &start); static Result bellmanford(const UndirectedGraph &graph, const Node &start); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const BellmanFord BELLMAN_FORD; + static BellmanFord& getInstance() { + static BellmanFord res; + return res; + } }; } // namespace shortestpath diff --git a/alib2algo/src/graph/shortestpath/Dijkstra.cpp b/alib2algo/src/graph/shortestpath/Dijkstra.cpp index bb1ef7dc86..e4f59b4632 100644 --- a/alib2algo/src/graph/shortestpath/Dijkstra.cpp +++ b/alib2algo/src/graph/shortestpath/Dijkstra.cpp @@ -120,9 +120,7 @@ static Dijkstra::Result dijkstra_impl(const T &graph, const Node &start) Dijkstra::Result Dijkstra::dijkstra(const Graph &graph, const Node &start) { - Data data = {start, Dijkstra::Result {}}; - graph.getData().Accept(static_cast<void*>(&data), DIJKSTRA); - return data.out; + return getInstance().dispatch(graph.getData(), start); } Dijkstra::Result Dijkstra::dijkstra(const DirectedGraph &graph, const Node &start) @@ -130,24 +128,14 @@ Dijkstra::Result Dijkstra::dijkstra(const DirectedGraph &graph, const Node &star return dijkstra_impl(graph, start); } +auto DijkstraDirectedGraph = Dijkstra::RegistratorWrapper<Dijkstra::Result, graph::DirectedGraph>(Dijkstra::getInstance(), Dijkstra::dijkstra); + Dijkstra::Result Dijkstra::dijkstra(const UndirectedGraph &graph, const Node &start) { return dijkstra_impl(graph, start); } -void Dijkstra::Visit(void *data, const DirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - d.out = dijkstra(graph, d.start); -} - -void Dijkstra::Visit(void *data, const UndirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - d.out = dijkstra(graph, d.start); -} - -const Dijkstra Dijkstra::DIJKSTRA; +auto DijkstraUndirectedGraph = Dijkstra::RegistratorWrapper<Dijkstra::Result, graph::UndirectedGraph>(Dijkstra::getInstance(), Dijkstra::dijkstra); } // namespace shortestpath diff --git a/alib2algo/src/graph/shortestpath/Dijkstra.h b/alib2algo/src/graph/shortestpath/Dijkstra.h index 52cf36902b..d1fc6af8c6 100644 --- a/alib2algo/src/graph/shortestpath/Dijkstra.h +++ b/alib2algo/src/graph/shortestpath/Dijkstra.h @@ -1,25 +1,21 @@ #ifndef GRAPH_DIJKSTRA_H_ #define GRAPH_DIJKSTRA_H_ +#include <common/multipleDispatch.hpp> #include <unordered_map> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace shortestpath -{ +namespace shortestpath { // Dijkstra only works on graphs without negative-weight edges (>= 0) -class Dijkstra : public graph::VisitableGraphBase::const_visitor_type -{ +class Dijkstra : public std::SingleDispatchLastStaticParam<std::unordered_map<Node, int>, graph::GraphBase, const Node> { public: - Dijkstra() {} - typedef std::unordered_map<Node, int> Result; static Result dijkstra(const Graph &graph, const Node &start); @@ -27,11 +23,10 @@ public: static Result dijkstra(const DirectedGraph &graph, const Node &start); static Result dijkstra(const UndirectedGraph &graph, const Node &start); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const Dijkstra DIJKSTRA; + static Dijkstra& getInstance() { + static Dijkstra res; + return res; + } }; } // namespace shortestpath diff --git a/alib2algo/src/graph/shortestpath/FloydWarshall.cpp b/alib2algo/src/graph/shortestpath/FloydWarshall.cpp index ec9a40bef5..4cd4df7da2 100644 --- a/alib2algo/src/graph/shortestpath/FloydWarshall.cpp +++ b/alib2algo/src/graph/shortestpath/FloydWarshall.cpp @@ -59,9 +59,7 @@ static FloydWarshall::Result floydwarshall_impl(const T &graph) FloydWarshall::Result FloydWarshall::floydwarshall(const Graph &graph) { - Result res; - graph.getData().Accept(static_cast<void*>(&res), FLOYD_WARSHALL); - return res; + return getInstance().dispatch(graph.getData()); } FloydWarshall::Result FloydWarshall::floydwarshall(const DirectedGraph &graph) @@ -69,24 +67,14 @@ FloydWarshall::Result FloydWarshall::floydwarshall(const DirectedGraph &graph) return floydwarshall_impl(graph); } +auto FloydWarshallDirectedGraph = FloydWarshall::RegistratorWrapper<FloydWarshall::Result, graph::DirectedGraph>(FloydWarshall::getInstance(), FloydWarshall::floydwarshall); + FloydWarshall::Result FloydWarshall::floydwarshall(const UndirectedGraph &graph) { return floydwarshall_impl(graph); } -void FloydWarshall::Visit(void *data, const DirectedGraph &graph) const -{ - Result *r = static_cast<Result*>(data); - *r = floydwarshall(graph); -} - -void FloydWarshall::Visit(void *data, const UndirectedGraph &graph) const -{ - Result *r = static_cast<Result*>(data); - *r = floydwarshall(graph); -} - -const FloydWarshall FloydWarshall::FLOYD_WARSHALL; +auto FloydWarshallUndirectedGraph = FloydWarshall::RegistratorWrapper<FloydWarshall::Result, graph::UndirectedGraph>(FloydWarshall::getInstance(), FloydWarshall::floydwarshall); } // namespace shortestpath diff --git a/alib2algo/src/graph/shortestpath/FloydWarshall.h b/alib2algo/src/graph/shortestpath/FloydWarshall.h index bbc16ca708..367d62016f 100644 --- a/alib2algo/src/graph/shortestpath/FloydWarshall.h +++ b/alib2algo/src/graph/shortestpath/FloydWarshall.h @@ -1,17 +1,16 @@ #ifndef GRAPH_FLOYD_WARSHALL_FORD_H_ #define GRAPH_FLOYD_WARSHALL_FORD_H_ +#include <common/multipleDispatch.hpp> #include <unordered_map> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace shortestpath -{ +namespace shortestpath { // Floyd-Warshall only works on graphs without negative-weight cycle // However it will detect the negative-weight cycle and throw exception @@ -19,11 +18,8 @@ namespace shortestpath // note: negative-weight undirected edge = negative-weight cycle // note: std::numeric_limits<int>::max() is used as infinity -class FloydWarshall : public graph::VisitableGraphBase::const_visitor_type -{ +class FloydWarshall : public std::SingleDispatch<std::unordered_map<Node, std::unordered_map<Node, int>>, graph::GraphBase> { public: - FloydWarshall() {} - typedef std::unordered_map<Node, std::unordered_map<Node, int>> Result; static Result floydwarshall(const Graph &graph); @@ -31,11 +27,10 @@ public: static Result floydwarshall(const DirectedGraph &graph); static Result floydwarshall(const UndirectedGraph &graph); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const FloydWarshall FLOYD_WARSHALL; + static FloydWarshall& getInstance() { + static FloydWarshall res; + return res; + } }; } // namespace shortestpath diff --git a/alib2algo/src/graph/sort/TopologicalSort.cpp b/alib2algo/src/graph/sort/TopologicalSort.cpp index 6556074b1c..3ecbeadbd7 100644 --- a/alib2algo/src/graph/sort/TopologicalSort.cpp +++ b/alib2algo/src/graph/sort/TopologicalSort.cpp @@ -3,14 +3,11 @@ #include <exception/AlibException.h> -namespace graph -{ +namespace graph { -namespace sort -{ +namespace sort { -static TopologicalSort::Result topsort_impl(const DirectedGraph &graph) -{ +static TopologicalSort::Result topsort_impl(const DirectedGraph &graph) { TopologicalSort::Result s; std::unordered_map<Node, bool> visited; @@ -28,32 +25,15 @@ static TopologicalSort::Result topsort_impl(const DirectedGraph &graph) return s; } -TopologicalSort::Result TopologicalSort::topologicalsort(const Graph &graph) -{ - Result res; - graph.getData().Accept(static_cast<void*>(&res), TOPOLOGICAL_SORT); - return res; +TopologicalSort::Result TopologicalSort::topologicalsort(const Graph &graph) { + return getInstance().dispatch(graph.getData()); } -TopologicalSort::Result TopologicalSort::topologicalsort(const DirectedGraph &graph) -{ +TopologicalSort::Result TopologicalSort::topologicalsort(const DirectedGraph &graph) { return topsort_impl(graph); } -void TopologicalSort::Visit(void *data, const DirectedGraph &graph) const -{ - Result *r = static_cast<Result*>(data); - *r = topologicalsort(graph); -} - -void TopologicalSort::Visit(void *data, const UndirectedGraph &graph) const -{ - (void) data; - (void) graph; - throw exception::AlibException("Unsupported graph type UndirectedGraph"); -} - -const TopologicalSort TopologicalSort::TOPOLOGICAL_SORT; +auto TopologicalSortDirectedGraph = TopologicalSort::RegistratorWrapper<TopologicalSort::Result, graph::DirectedGraph>(TopologicalSort::getInstance(), TopologicalSort::topologicalsort); } // namespace sort diff --git a/alib2algo/src/graph/sort/TopologicalSort.h b/alib2algo/src/graph/sort/TopologicalSort.h index b746cb2bd5..e43fbd0d60 100644 --- a/alib2algo/src/graph/sort/TopologicalSort.h +++ b/alib2algo/src/graph/sort/TopologicalSort.h @@ -1,34 +1,29 @@ #ifndef GRAPH_TOPOLOGICAL_SORT_H_ #define GRAPH_TOPOLOGICAL_SORT_H_ +#include <common/multipleDispatch.hpp> #include <list> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace sort -{ +namespace sort { -class TopologicalSort : public graph::VisitableGraphBase::const_visitor_type -{ +class TopologicalSort : public std::SingleDispatch<std::list<Node>, graph::GraphBase> { public: - TopologicalSort() {} - typedef std::list<Node> Result; static Result topologicalsort(const Graph &graph); static Result topologicalsort(const DirectedGraph &graph); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const TopologicalSort TOPOLOGICAL_SORT; + static TopologicalSort& getInstance() { + static TopologicalSort res; + return res; + } }; } // namespace sort diff --git a/alib2algo/src/graph/spanningtree/JarnikPrim.cpp b/alib2algo/src/graph/spanningtree/JarnikPrim.cpp index 28f55bfbbe..5222d2a374 100644 --- a/alib2algo/src/graph/spanningtree/JarnikPrim.cpp +++ b/alib2algo/src/graph/spanningtree/JarnikPrim.cpp @@ -4,21 +4,17 @@ #include <limits> -namespace graph -{ +namespace graph { -namespace spanningtree -{ +namespace spanningtree { -class Data -{ +class Data { public: Node start; Graph *out; }; -class Value -{ +class Value { public: Value(const Node &node, int value) : node(node) @@ -40,8 +36,7 @@ public: typedef std::unordered_map<Node, std::unordered_map<Node, int>> weights_t; -static weights_t weights(const UndirectedGraph &g) -{ +static weights_t weights(const UndirectedGraph &g) { int val; weights_t w; @@ -63,8 +58,7 @@ static weights_t weights(const UndirectedGraph &g) return w; } -static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node &start) -{ +static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node &start) { UndirectedGraph res; // spanning tree std::set<Value> q; // priority queue weights_t w = weights(graph); // minimum weights @@ -101,35 +95,15 @@ static UndirectedGraph jarnikprim_impl(const UndirectedGraph &graph, const Node return res; } -Graph JarnikPrim::jarnikprim(const Graph &graph, const Node &start) -{ - Data out = { start, nullptr }; - graph.getData().Accept(static_cast<void*>(&out), JARNIK_PRIM); - Graph res = std::move(*out.out); - delete out.out; - return res; +Graph JarnikPrim::jarnikprim(const Graph &graph, const Node &start) { + return getInstance().dispatch(graph.getData(), start); } -UndirectedGraph JarnikPrim::jarnikprim(const UndirectedGraph &graph, const Node &start) -{ +UndirectedGraph JarnikPrim::jarnikprim(const UndirectedGraph &graph, const Node &start) { return jarnikprim_impl(graph, start); } -void JarnikPrim::Visit(void *data, const DirectedGraph &graph) const -{ - (void) data; - (void) graph; - throw exception::AlibException("Unsupported graph type DirectedGraph"); -} - -void JarnikPrim::Visit(void *data, const UndirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - d.out = new Graph(jarnikprim(graph, d.start)); - (void) d; -} - -const JarnikPrim JarnikPrim::JARNIK_PRIM; +auto JarnikPrimUndirectedGraph = JarnikPrim::RegistratorWrapper<graph::UndirectedGraph, graph::UndirectedGraph>(JarnikPrim::getInstance(), JarnikPrim::jarnikprim); } // namespace spanningtree diff --git a/alib2algo/src/graph/spanningtree/JarnikPrim.h b/alib2algo/src/graph/spanningtree/JarnikPrim.h index 8b8d11e24b..05d8054124 100644 --- a/alib2algo/src/graph/spanningtree/JarnikPrim.h +++ b/alib2algo/src/graph/spanningtree/JarnikPrim.h @@ -1,30 +1,25 @@ #ifndef GRAPH_JARNIK_PRIM_H_ #define GRAPH_JARNIK_PRIM_H_ +#include <common/multipleDispatch.hpp> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace spanningtree -{ +namespace spanningtree { -class JarnikPrim : public graph::VisitableGraphBase::const_visitor_type -{ +class JarnikPrim : public std::SingleDispatchLastStaticParam<graph::Graph, graph::GraphBase, const Node> { public: - JarnikPrim() {} - static Graph jarnikprim(const Graph &graph, const Node &start); static UndirectedGraph jarnikprim(const UndirectedGraph &graph, const Node &start); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const JarnikPrim JARNIK_PRIM; + static JarnikPrim& getInstance() { + static JarnikPrim res; + return res; + } }; } // namespace spanningtree diff --git a/alib2algo/src/graph/traverse/Bfs.cpp b/alib2algo/src/graph/traverse/Bfs.cpp index 19e60188d1..9b79beb56b 100644 --- a/alib2algo/src/graph/traverse/Bfs.cpp +++ b/alib2algo/src/graph/traverse/Bfs.cpp @@ -3,22 +3,18 @@ #include <queue> #include <unordered_map> -namespace graph -{ +namespace graph { -namespace traverse -{ +namespace traverse { -struct Data -{ +struct Data { Node start; Bfs::Function func; Bfs::FunctionExt func2; }; template <typename T> -static void bfs_impl(const T &graph, const Node &start, Bfs::Function func) -{ +static void bfs_impl(const T &graph, const Node &start, Bfs::Function func) { std::unordered_map<Node, bool> visited; std::queue<Node> q; @@ -42,8 +38,7 @@ static void bfs_impl(const T &graph, const Node &start, Bfs::Function func) } template <typename T> -static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func) -{ +static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func) { std::unordered_map<Node, int> distances; std::unordered_map<Node, Node> predecessors; std::queue<Node> q; @@ -69,59 +64,37 @@ static void bfs2_impl(const T &graph, const Node &start, Bfs::FunctionExt func) } } -void Bfs::bfs(const Graph &graph, const Node &start, Bfs::Function func) -{ - Data data = { start, func, nullptr }; - graph.getData().Accept(static_cast<void*>(&data), BFS); +void Bfs::bfs(const Graph &graph, const Node &start, Bfs::Function func) { + getInstance().dispatch(graph.getData(), start, func); } -void Bfs::bfs(const Graph &graph, const Node &start, Bfs::FunctionExt func) -{ - Data data = { start, nullptr, func }; - graph.getData().Accept(static_cast<void*>(&data), BFS); +void Bfs::bfs(const Graph &graph, const Node &start, Bfs::FunctionExt func) { + getInstance().dispatch(graph.getData(), start, func); } -void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func) -{ +void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::Function func) { bfs_impl(graph, start, func); } -void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func) -{ +auto BfsDirectedGraph1 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::getInstance(), Bfs::bfs); + +void Bfs::bfs(const DirectedGraph &graph, const Node &start, Bfs::FunctionExt func) { bfs2_impl(graph, start, func); } -void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func) -{ +auto BfsDirectedGraph2 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Bfs::getInstance(), Bfs::bfs); + +void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::Function func) { bfs_impl(graph, start, func); } -void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func) -{ - bfs2_impl(graph, start, func); -} +auto BfsUndirectedGraph1 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::getInstance(), Bfs::bfs); -void Bfs::Visit(void *data, const DirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - if (d.func) { - bfs(graph, d.start, d.func); - } else if (d.func2) { - bfs(graph, d.start, d.func2); - } -} - -void Bfs::Visit(void *data, const UndirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - if (d.func) { - bfs(graph, d.start, d.func); - } else if (d.func2) { - bfs(graph, d.start, d.func2); - } +void Bfs::bfs(const UndirectedGraph &graph, const Node &start, Bfs::FunctionExt func) { + bfs2_impl(graph, start, func); } -const Bfs Bfs::BFS; +auto BfsUndirectedGraph2 = Bfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Bfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Bfs::getInstance(), Bfs::bfs); } // namespace traverse diff --git a/alib2algo/src/graph/traverse/Bfs.h b/alib2algo/src/graph/traverse/Bfs.h index c180b1a323..2c207d1fee 100644 --- a/alib2algo/src/graph/traverse/Bfs.h +++ b/alib2algo/src/graph/traverse/Bfs.h @@ -1,25 +1,24 @@ #ifndef GRAPH_BFS_H_ #define GRAPH_BFS_H_ +#include <common/multipleDispatch.hpp> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace traverse -{ +namespace traverse { // func is called for each visited node, traversal stops when returning false // // bool Function(const Node &visitedNode); // bool FunctionExt(const Node &visitedNode, const Node &predecessor, int distanceFromStart); -class Bfs : public graph::VisitableGraphBase::const_visitor_type -{ +class Bfs : public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>, public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int)>> { public: - Bfs() {} + using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>::dispatch; + using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int)>>::dispatch; typedef std::function<bool(const Node&)> Function; typedef std::function<bool(const Node&, const Node&, int)> FunctionExt; @@ -32,11 +31,10 @@ public: static void bfs(const UndirectedGraph &graph, const Node &start, Function func); static void bfs(const UndirectedGraph &graph, const Node &start, FunctionExt func); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const Bfs BFS; + static Bfs& getInstance() { + static Bfs res; + return res; + } }; } // namespace traverse diff --git a/alib2algo/src/graph/traverse/Dfs.cpp b/alib2algo/src/graph/traverse/Dfs.cpp index 2aa7fe3100..e49863254e 100644 --- a/alib2algo/src/graph/traverse/Dfs.cpp +++ b/alib2algo/src/graph/traverse/Dfs.cpp @@ -3,22 +3,18 @@ #include <stack> #include <unordered_map> -namespace graph -{ +namespace graph { -namespace traverse -{ +namespace traverse { -struct Data -{ +struct Data { Node start; Dfs::Function func; Dfs::FunctionExt func2; }; template <typename T> -static void dfs_impl(const T &graph, const Node &start, Dfs::Function func) -{ +static void dfs_impl(const T &graph, const Node &start, Dfs::Function func) { std::unordered_map<Node, bool> visited; std::stack<Node> s; @@ -42,8 +38,7 @@ static void dfs_impl(const T &graph, const Node &start, Dfs::Function func) } template <typename T> -static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unordered_map<Node, bool> &visited, int &time, Dfs::FunctionExt func) -{ +static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unordered_map<Node, bool> &visited, int &time, Dfs::FunctionExt func) { int opened = ++time; visited[n] = true; @@ -58,63 +53,41 @@ static bool dfs2_impl(const T &graph, const Node &n, const Node &p, std::unorder return func(n, p, opened, ++time); } -void Dfs::dfs(const Graph &graph, const Node &start, Dfs::Function func) -{ - Data data = { start, func, nullptr }; - graph.getData().Accept(static_cast<void*>(&data), DFS); +void Dfs::dfs(const Graph &graph, const Node &start, Dfs::Function func) { + getInstance().dispatch(graph.getData(), start, func); } -void Dfs::dfs(const Graph &graph, const Node &start, Dfs::FunctionExt func) -{ - Data data = { start, nullptr, func }; - graph.getData().Accept(static_cast<void*>(&data), DFS); +void Dfs::dfs(const Graph &graph, const Node &start, Dfs::FunctionExt func) { + getInstance().dispatch(graph.getData(), start, func); } -void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func) -{ +void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::Function func) { dfs_impl(graph, start, func); } -void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func) -{ +auto DfsDirectedGraph1 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::getInstance(), Dfs::dfs); + +void Dfs::dfs(const DirectedGraph &graph, const Node &start, Dfs::FunctionExt func) { int time = 0; std::unordered_map<Node, bool> visited; dfs2_impl(graph, start, start, visited, time, func); } -void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func) -{ +auto DfsDirectedGraph2 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::DirectedGraph>(Dfs::getInstance(), Dfs::dfs); + +void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::Function func) { dfs_impl(graph, start, func); } -void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func) -{ +auto DfsUndirectedGraph1 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::Function>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::getInstance(), Dfs::dfs); + +void Dfs::dfs(const UndirectedGraph &graph, const Node &start, Dfs::FunctionExt func) { int time = 0; std::unordered_map<Node, bool> visited; dfs2_impl(graph, start, start, visited, time, func); } -void Dfs::Visit(void *data, const DirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - if (d.func) { - dfs(graph, d.start, d.func); - } else if (d.func2) { - dfs(graph, d.start, d.func2); - } -} - -void Dfs::Visit(void *data, const UndirectedGraph &graph) const -{ - Data d = *static_cast<Data*>(data); - if (d.func) { - dfs(graph, d.start, d.func); - } else if (d.func2) { - dfs(graph, d.start, d.func2); - } -} - -const Dfs Dfs::DFS; +auto DfsUndirectedGraph2 = Dfs::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, Dfs::FunctionExt>::RegistratorWrapper<void, graph::UndirectedGraph>(Dfs::getInstance(), Dfs::dfs); } // namespace traverse diff --git a/alib2algo/src/graph/traverse/Dfs.h b/alib2algo/src/graph/traverse/Dfs.h index 532b53ba9d..32d5467c51 100644 --- a/alib2algo/src/graph/traverse/Dfs.h +++ b/alib2algo/src/graph/traverse/Dfs.h @@ -1,25 +1,24 @@ #ifndef GRAPH_DFS_H_ #define GRAPH_DFS_H_ +#include <common/multipleDispatch.hpp> #include <graph/Graph.h> #include <graph/directed/DirectedGraph.h> #include <graph/undirected/UndirectedGraph.h> -namespace graph -{ +namespace graph { -namespace traverse -{ +namespace traverse { // func is called for each visited node, traversal stops when returning false // // bool Function(const Node &node); // bool FunctionExt(const Node &node, const Node &predecessor, int openTime, int closeTime); -class Dfs : public graph::VisitableGraphBase::const_visitor_type -{ +class Dfs : public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>, public std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int, int)>> { public: - Dfs() {} + using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&)>>::dispatch; + using std::SingleDispatch2LastStaticParams<void, graph::GraphBase, const Node&, std::function<bool(const Node&, const Node&, int, int)>>::dispatch; typedef std::function<bool(const Node&)> Function; typedef std::function<bool(const Node&, const Node&, int, int)> FunctionExt; @@ -32,11 +31,10 @@ public: static void dfs(const UndirectedGraph &graph, const Node &start, Function func); static void dfs(const UndirectedGraph &graph, const Node &start, FunctionExt func); -private: - void Visit(void *data, const DirectedGraph &graph) const; - void Visit(void *data, const UndirectedGraph &graph) const; - - static const Dfs DFS; + static Dfs& getInstance() { + static Dfs res; + return res; + } }; } // namespace traverse diff --git a/alib2algo/src/regexp/transform/RegExpIterate.h b/alib2algo/src/regexp/transform/RegExpIterate.h index 66e137d216..cb31310be5 100644 --- a/alib2algo/src/regexp/transform/RegExpIterate.h +++ b/alib2algo/src/regexp/transform/RegExpIterate.h @@ -14,8 +14,7 @@ #include <regexp/formal/FormalRegExp.h> #include <regexp/unbounded/UnboundedRegExp.h> -namespace regexp -{ +namespace regexp { /** * Iterates two regexpses diff --git a/alib2algo/test-src/graph/traverse/BfsTest.cpp b/alib2algo/test-src/graph/traverse/BfsTest.cpp index 4594c57fad..66abaf4184 100644 --- a/alib2algo/test-src/graph/traverse/BfsTest.cpp +++ b/alib2algo/test-src/graph/traverse/BfsTest.cpp @@ -182,7 +182,9 @@ void GraphBfsTest::testBfs2() distances.clear(); predecessors.clear(); - graph::traverse::Bfs::bfs(dg, n1, [&](const graph::Node &n, const graph::Node &p, int d) { + graph::Graph g(dg); + + graph::traverse::Bfs::bfs(g, n1, [&](const graph::Node &n, const graph::Node &p, int d) { distances[n] = d; predecessors.insert(std::make_pair(n, p)); return true; @@ -210,7 +212,9 @@ void GraphBfsTest::testBfs2() distances.clear(); predecessors.clear(); - graph::traverse::Bfs::bfs(ug, n1, [&](const graph::Node &n, const graph::Node &p, int d) { + graph::Graph g2(ug); + + graph::traverse::Bfs::bfs(g2, n1, [&](const graph::Node &n, const graph::Node &p, int d) { distances[n] = d; predecessors.insert(std::make_pair(n, p)); return true; diff --git a/alib2algo/test-src/graph/traverse/DfsTest.cpp b/alib2algo/test-src/graph/traverse/DfsTest.cpp index 90db9b35d9..54ce021370 100644 --- a/alib2algo/test-src/graph/traverse/DfsTest.cpp +++ b/alib2algo/test-src/graph/traverse/DfsTest.cpp @@ -184,7 +184,9 @@ void GraphDfsTest::testDfs2() closed.clear(); predecessors.clear(); - graph::traverse::Dfs::dfs(dg, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) { + graph::Graph g(dg); + + graph::traverse::Dfs::dfs(g, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) { counter++; opened[n] = o; closed[n] = c; @@ -213,7 +215,9 @@ void GraphDfsTest::testDfs2() closed.clear(); predecessors.clear(); - graph::traverse::Dfs::dfs(ug, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) { + graph::Graph g2(ug); + + graph::traverse::Dfs::dfs(g2, n1, [&](const graph::Node &n, const graph::Node &p, int o, int c) { counter++; opened[n] = o; closed[n] = c; diff --git a/alib2data/src/common/multipleDispatch.hpp b/alib2data/src/common/multipleDispatch.hpp index 6276f0c1d6..84a00a5978 100644 --- a/alib2data/src/common/multipleDispatch.hpp +++ b/alib2data/src/common/multipleDispatch.hpp @@ -134,6 +134,45 @@ public: }; +template<class ReturnType, class FirstParameterType, class FirstStaticParamType, class SecondStaticParamType> +class SingleDispatch2LastStaticParams { +public: + class RegistratorWrapperBase { + public: + virtual ReturnType eval(const FirstParameterType&, FirstStaticParamType, SecondStaticParamType) = 0; + + }; + +private: + typedef SingleDispatch2LastStaticParams<ReturnType, FirstParameterType, FirstStaticParamType, SecondStaticParamType> SelfType; + + std::map<long long, typename SelfType::RegistratorWrapperBase*> registeredFunctions; + +public: + template<class RealReturnType, class RealFirstParameterType> + class RegistratorWrapper : public RegistratorWrapperBase { + std::function<RealReturnType(const RealFirstParameterType&, FirstStaticParamType, SecondStaticParamType)> callback; + + public: + ReturnType eval(const FirstParameterType& first, FirstStaticParamType res, SecondStaticParamType res2) { + return ReturnType(callback((const RealFirstParameterType&) first, res, res2)); + } + + RegistratorWrapper(SelfType& pool, RealReturnType(*callback)(const RealFirstParameterType&, FirstStaticParamType, SecondStaticParamType)) : callback(callback) { + int a = 0; + if(! pool.registeredFunctions.insert(std::make_pair(RealFirstParameterType::typeId((const RealFirstParameterType&) a), this)). second) + throw std::logic_error("Callback alreary registered."); + } + }; + + ReturnType dispatch(const FirstParameterType& first, FirstStaticParamType res, SecondStaticParamType res2) { + typename std::map<long long, RegistratorWrapperBase*>::iterator callback = registeredFunctions.find(first.selfTypeId()); + if(callback == registeredFunctions.end()) throw std::bad_function_call(); + return callback->second->eval(first, res, res2); + } + +}; + // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- template<class ReturnType, class ParametersType> -- GitLab