diff --git a/alib2algo/src/graph/shortestpath/BellmanFord.cpp b/alib2algo/src/graph/shortestpath/BellmanFord.cpp index 85c3f35fc797ca656e78852f6b7382742aa7f1b3..3e8c37be7054d68ac3538b9739dead0e3b686c75 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 730175966d90b4b39eae277514898ab3dfd7bf93..9c5a07e2dd8d6a889b8b9f1e1cc0fef6b045b6b2 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 bb1ef7dc86737cb945b4a859186f8013f16fc25e..e4f59b4632d259a6a12146d2d928267b3fb90b90 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 52cf36902b1945420a6160b60bce1ecb57a6f020..d1fc6af8c6ce9f6fe904141bf02e7c2b94bc4beb 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 ec9a40bef55708cc73890ce3a0c4fb3cc13cfb1f..4cd4df7da223f694f33613ee263d70e147a96377 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 bbc16ca70802693ef9d4165de691eef55dcd1b4b..367d62016fca34f7a4313505ae8dc5e64c5c2493 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 6556074b1c0d1274823f433e917749df83ea56ba..3ecbeadbd790910579da6748dffb7b924be35cc9 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 b746cb2bd5f12d6ff0e53cd0a8a8758e062df8db..e43fbd0d60c8071223b92a9fe45618f7f4ab7e97 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 28f55bfbbe5c6b13763ba5ea54762ef02b02df59..5222d2a374db648ed6b09a10fde120cd501d1251 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 8b8d11e24b7fab00d35d4272c529189ff1b97d1c..05d80541248961547d7e8e6daab7bc938c849687 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 19e60188d13ac79303fea67ff733351b2e0e6ec3..9b79beb56b44cdb954574897ad5bc48cadb72c4b 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 c180b1a3230dae0d44b7e95788ff64f907755438..2c207d1fee435478e1864ff9cdf7456184769f33 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 2aa7fe3100ddcdc338b98495ffcefd10203ecce4..e49863254e8227e33711591be3c4751e8066c40a 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 532b53ba9d4548132cfa28d6a602581735319b70..32d5467c51abaa22132844019535a853e0cc48fc 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 66e137d2160ce55f1294f966f49f7d6253edbe19..cb31310be5c794ebd1f26c7e4a88699bb2b7820a 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 4594c57fad4e3d397747f00d3451ae5e5f367544..66abaf41847e31bad83db5c85f82c7951c4a1475 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 90db9b35d90efb47dfa80e585d7e804833d869bb..54ce021370fe0876e7925d405eec22e5c91834ff 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 6276f0c1d6a3224fa96ee1fbe3932d07f023b1f1..84a00a59782b7e5adf4b8139dcfad16a1ae31e13 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>