From e450287c0a948ecb7fbebb9eda39edd6243634f5 Mon Sep 17 00:00:00 2001 From: Benjamin Bigey Date: Wed, 24 Jan 2018 08:54:50 +0100 Subject: [PATCH 1/4] Implementation of .DOT generation + update search algorithms --- doc/examples/route_finding.cpp | 28 +-- single_include/graph.hpp | 299 +++++++++++++++++++++++---------- src/Graph.cpp | 72 +++++++- src/Graph.h | 17 +- src/GraphSearch.cpp | 106 ++++++------ src/GraphSearch.h | 247 +++++++++++++++++++++++---- test/src/unit-search.cpp | 7 +- test/src/unit-text.cpp | 45 +++++ 8 files changed, 620 insertions(+), 201 deletions(-) diff --git a/doc/examples/route_finding.cpp b/doc/examples/route_finding.cpp index 305198b..a757515 100644 --- a/doc/examples/route_finding.cpp +++ b/doc/examples/route_finding.cpp @@ -62,28 +62,28 @@ int main() { const string BEGIN{"Arad"}; - auto DFS = search::make_DFS(map); - auto pDFS = DFS.run (map.find(BEGIN), map.find("Bucharest")); + auto DFS = search::make_DFS(map, map.find("Bucharest")); + auto pDFS = DFS.run (map.find(BEGIN)); - auto BFS = search::make_BFS(map); - auto pBFS = BFS.run (map.find(BEGIN), map.find("Bucharest")); + auto BFS = search::make_BFS(map, map.find("Bucharest")); + auto pBFS = BFS.run (map.find(BEGIN)); - auto DLS = search::make_DLS(map); - auto pDLS = DLS.run (map.find(BEGIN), map.find("Bucharest"), 5); + auto DLS = search::make_DLS(map, map.find("Bucharest")); + auto pDLS = DLS.run (map.find(BEGIN), 5); - auto IDDFS = search::make_IDDFS(map); - auto pIDDFS = IDDFS.run(map.find(BEGIN), map.find("Bucharest")); + auto IDDFS = search::make_IDDFS(map, map.find("Bucharest")); + auto pIDDFS = IDDFS.run(map.find(BEGIN)); - auto UCS = search::make_UCS(map); - auto pUCS = UCS.run (map.find(BEGIN), map.find("Bucharest")); + auto UCS = search::make_UCS(map, map.find("Bucharest")); + auto pUCS = UCS.run (map.find(BEGIN)); - auto aStar = search::make_AStar(map); - auto heuristic = [&straight_line_Bucharest](const graph_undirected::const_iterator & it, const graph_undirected::const_iterator & target) -> double { - if (target->first == "Bucharest") { + auto aStar = search::make_AStar(map, map.find("Bucharest")); + auto heuristic = [&straight_line_Bucharest](const graph_undirected::const_iterator & it) -> double { + if (it->first == "Bucharest") { return straight_line_Bucharest[it->first]; } }; - auto pAStar = aStar.run(map.find(BEGIN), map.find("Bucharest"), heuristic); + auto pAStar = aStar.run(map.find(BEGIN), heuristic); const size_t nr_digits_IDDFS{static_cast(pIDDFS.empty() ? 0 : log10(pIDDFS.get_nr_steps()) + 1)}; cout << "\nCalculation of the shortest path from '" << BEGIN << "' to 'Bucharest' with several search algorithms:\n" diff --git a/single_include/graph.hpp b/single_include/graph.hpp index 53bb3da..378557f 100644 --- a/single_include/graph.hpp +++ b/single_include/graph.hpp @@ -4,7 +4,7 @@ * ╚═╝╩╚═╩ ╩╩ ╩ ╩ https://github.com/Terae/Structure * * - * Single header-file generated by terae on 2018-01-17 + * Single header-file generated by terae on 2018-01-24 * * * Licensed under the MIT License . @@ -709,18 +709,26 @@ class graph { template ::value>> inline std::vector get_edges (const key_type &) const; + // TODO + bool is_cyclic() const; + + // TODO + bool is_isomorphic() const; + /// @section Text functions - template friend std::ostream &operator<<(std::ostream &os, const graph &g); - template friend std::istream &operator>>(std::istream &is, graph &g); + template friend std::ostream &operator<<(std::ostream &, const graph &); + template friend std::istream &operator>>(std::istream &, graph &); void save(const char* filepath) const; graph &load(const char* filepath); + std::ostream &generate_dot(std::ostream &, const std::string &name = "") const; + /// @section Bool operators - template bool operator==(const graph &other) const noexcept; - template bool operator!=(const graph &other) const noexcept; + template bool operator==(const graph &) const noexcept; + template bool operator!=(const graph &) const noexcept; class node : public basic_node { public: @@ -750,11 +758,11 @@ namespace search { template class path { template friend class pathComparator; - template friend class abstractSearch; template friend class abstractFirstSearch; template friend class DLS; template friend class UCS; template friend class AStar; + template friend class Dijkstra; public: path(); @@ -782,90 +790,128 @@ namespace search { template class pathComparator { private: - stateType _target; - std::function _heuristic; + std::function _heuristic; public: - pathComparator(stateType target, std::function heuristic); + pathComparator(std::function heuristic); bool operator() (const path &, const path &); }; template class abstractSearch { + public: + using state = typename graph::const_iterator; + + explicit abstractSearch(const graph &, std::function is_goal); + protected: const graph &g; - abstractSearch(const graph &); + + std::function _is_goal; }; - template - class abstractFirstSearch : public abstractSearch { + template + class abstractTargetedSearch : public abstractSearch { public: + using abstractSearch::abstractSearch; + using state = typename graph::const_iterator; - abstractFirstSearch(const graph &); - path run(state begin, state target); + explicit abstractTargetedSearch(const graph &, state target); + explicit abstractTargetedSearch(const graph &, const std::list &list_target); + + protected: + std::list _targets; + }; + + template + class abstractFirstSearch : public abstractTargetedSearch { + public: + using abstractTargetedSearch::abstractTargetedSearch; + + using state = typename abstractTargetedSearch::state; + + path run(state begin) const; }; template using BFS = abstractFirstSearch; - template - constexpr BFS make_BFS(const graph &); + template + constexpr BFS make_BFS(const graph &, Args &&...); template using DFS = abstractFirstSearch; - template - constexpr DFS make_DFS(const graph &); + template + constexpr DFS make_DFS(const graph &, Args &&...); template - class DLS : public abstractSearch { + class DLS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - DLS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; - path run(state begin, state target, int depth); + using state = typename abstractTargetedSearch::state; + + path run(state begin, int depth) const; }; - template - constexpr DLS make_DLS(const graph &); + template + constexpr DLS make_DLS(const graph &, Args &&...); template - class IDDFS : public abstractSearch { + class IDDFS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - IDDFS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; - path run(state begin, state target); + using state = typename abstractTargetedSearch::state; + + path run(state begin) const; }; - template - constexpr IDDFS make_IDDFS(const graph &); + template + constexpr IDDFS make_IDDFS(const graph &, Args &&...); template - class UCS : public abstractSearch { + class UCS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - UCS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; + + using state = typename abstractTargetedSearch::state; - path run(state begin, state target); + path run(state begin) const; }; - template - constexpr UCS make_UCS(const graph &); + template + constexpr UCS make_UCS(const graph &, Args &&...); template - class AStar : public abstractSearch { + class AStar : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - AStar(const graph &g); + using abstractTargetedSearch::abstractTargetedSearch; + + using state = typename abstractTargetedSearch::state; - path run(state begin, state target, std::function heuristic); + path run(state begin, std::function heuristic) const; }; + template + constexpr AStar make_AStar(const graph &, Args &&...); + template - constexpr AStar make_AStar(const graph &); + class Dijkstra : public abstractSearch { + public: + using abstractSearch::abstractSearch; + + using state = typename abstractSearch::state; + + // TODO + std::map> run(state begin) const; + }; + + template + constexpr Dijkstra make_Dijkstra(const graph &, Args &&...); } template @@ -1129,6 +1175,8 @@ constexpr bool operator>=(const basic_node + template typename graph::iterator graph::begin() noexcept { return _nodes.begin(); @@ -1697,6 +1745,16 @@ std::vector::node::edge> graph +bool graph::is_cyclic() const { + +} + +template +bool graph::is_isomorphic() const { + +} + template std::ostream &graph::print(std::ostream &os) const { using std::setw; @@ -1750,7 +1808,7 @@ std::ostream &graph::print(std::ostream &os) const { size_type max_size_1{0}, max_size_2{0}; for_each(cbegin(), cend(), [&max_size_1, &max_size_2, this](const value_type & element) { - std::list child = element.second->get_edges(); + std::list child{element.second->get_edges()}; for_each(child.cbegin(), child.cend(), [ &, this](const typename node::edge & i) { ostringstream out_1, out_2; out_1 << element.first; @@ -1771,7 +1829,7 @@ std::ostream &graph::print(std::ostream &os) const { size_type p{0}; for_each(cbegin(), cend(), [ =, &os, &p](const value_type & element) { - std::list child = element.second->get_edges(); + std::list child{element.second->get_edges()}; for_each(child.cbegin(), child.cend(), [ =, &os, &p](const typename node::edge & i) { ostringstream out_1, out_2; out_1 << element.first << '"' << separator; @@ -1884,6 +1942,60 @@ graph &graph::load(const char* filepath) { return *this; } +template +std::ostream &graph::generate_dot(std::ostream &os, const std::string &name) const { + const std::string tab{" "}; + + /// Displaying nature + graph name + if (name.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-") != name.npos) { + GRAPH_THROW_WITH(invalid_argument, "Wrong graph name given; accepted characters: [a-zA-Z0-9_-]") + } + + if (get_nature() == DIRECTED) { + os << "di"; + } + os << "graph "; + if (!name.empty()) { + os << name << ' '; + } + os << "{\n"; + + /// Displaying nodes' name + for (const_iterator it{cbegin()}; it != cend(); ++it) { + os << tab << it->first << '\n'; + } + + if (get_nature() == DIRECTED) { + for_each(cbegin(), cend(), [ =, &os](const value_type & element) { + std::list child{element.second->get_edges()}; + for_each(child.cbegin(), child.cend(), [ =, &os](const typename node::edge & i) { + if (i.cost() != infinity) { + os << tab << element.first << " -> " << i.target()->first << '\n'; + } + }); + }); + } else { + std::set> list_edges; + for_each(cbegin(), cend(), [ =, &os, &list_edges](const value_type & element) { + std::list child{element.second->get_edges()}; + for_each(child.cbegin(), child.cend(), [ =, &os, &list_edges](const typename node::edge & i) { + if (i.cost() != infinity) { + const Key min{std::min(element.first, i.target()->first)}; + const Key max{std::max(element.first, i.target()->first)}; + list_edges.emplace(std::make_pair(min, max)); + } + }); + }); + + for_each(list_edges.cbegin(), list_edges.cend(), [ =, &os](const std::pair &p) { + os << tab << p.first << " -- " << p.second << '\n'; + }); + } + os << '}'; + + return os; +} + template template bool graph::operator==(const graph &other) const noexcept { @@ -1892,7 +2004,7 @@ bool graph::operator==(const graph &other) const typedef std::list::iterator, Iterator1>::edge> Set1; typedef std::list::iterator, Iterator2>::edge> Set2; - if (get_nature() != other.get_nature() || + if (get_nature() != other.get_nature() || get_nbr_nodes() != other.get_nbr_nodes() || get_nbr_edges() != other.get_nbr_edges()) { return false; @@ -2017,21 +2129,27 @@ std::pair search::path::pop_front() { } template -search::pathComparator::pathComparator(stateType target, std::function h) : _target(target), _heuristic(h) {} +search::pathComparator::pathComparator(std::function h) : _heuristic(h) {} template bool search::pathComparator::operator() (const path &p1, const path &p2) { - return (p1.total_cost() + _heuristic(p1.back_state(), _target)) > (p2.total_cost() + _heuristic(p2.back_state(), _target)); + return (p1.total_cost() + _heuristic(p1.back_state())) > (p2.total_cost() + _heuristic(p2.back_state())); } template -search::abstractSearch::abstractSearch(const graph &g_) : g(g_) {} +search::abstractSearch::abstractSearch(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} -template -search::abstractFirstSearch::abstractFirstSearch(const graph &g) : abstractSearch(g) {} +template +search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, state target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { + this->_targets.emplace_back(target); +} + +template +search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, const std::list &list_target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), + _targets(list_target) {} template -search::path::state, Cost> search::abstractFirstSearch::run(state begin, state target) { +search::path::state, Cost> search::abstractFirstSearch::run(state begin) const { std::list expanded; std::deque> frontier; @@ -2049,7 +2167,7 @@ search::path_is_goal(last)) { return p; } @@ -2072,21 +2190,18 @@ search::path -constexpr typename search::BFS search::make_BFS(const graph &g) { - return BFS(g); +template +constexpr typename search::BFS search::make_BFS(const graph &g, Args &&... args) { + return BFS(g, std::forward(args)...); } -template -constexpr typename search::DFS search::make_DFS(const graph &g) { - return DFS(g); +template +constexpr typename search::DFS search::make_DFS(const graph &g, Args &&... args) { + return DFS(g, std::forward(args)...); } template -search::DLS::DLS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::DLS::run(state begin, state target, int depth) { +search::path::state, Cost> search::DLS::run(state begin, int depth) const { std::list expanded; std::deque> frontier; @@ -2105,7 +2220,7 @@ search::path::state, Cost> search::DLS_is_goal(last)) { return p; } @@ -2146,20 +2261,17 @@ search::path::state, Cost> search::DLS();*/ } -template -constexpr typename search::DLS search::make_DLS(const graph &g) { - return DLS(g); +template +constexpr typename search::DLS search::make_DLS(const graph &g, Args &&... args) { + return DLS(g, std::forward(args)...); } template -search::IDDFS::IDDFS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::IDDFS::run(state begin, state target) { - search::DLS dls{make_DLS(this->g)}; +search::path::state, Cost> search::IDDFS::run(state begin) const { + search::DLS dls{make_DLS(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { - path found{dls.run(begin, target, i)}; + path found{dls.run(begin, i)}; if (!found.empty()) { return found; } @@ -2167,18 +2279,15 @@ search::path::state, Cost> search::IDD return path(); } -template -constexpr typename search::IDDFS search::make_IDDFS(const graph &g) { - return IDDFS(g); +template +constexpr typename search::IDDFS search::make_IDDFS(const graph &g, Args &&... args) { + return IDDFS(g, std::forward(args)...); } template -search::UCS::UCS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::UCS::run(state begin, state target) { +search::path::state, Cost> search::UCS::run(state begin) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(target, [](state, state) -> double { return 0; }))); + std::priority_queue, std::vector>, pathComparator> frontier(pathComparator([](state) -> double { return 0; } )); { path p; @@ -2194,7 +2303,7 @@ search::path::state, Cost> search::UCS_is_goal(last)) { return p; } @@ -2213,18 +2322,15 @@ search::path::state, Cost> search::UCS -constexpr typename search::UCS search::make_UCS(const graph &g) { - return UCS(g); +template +constexpr typename search::UCS search::make_UCS(const graph &g, Args &&... args) { + return UCS(g, std::forward(args)...); } template -search::AStar::AStar(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::AStar::run(state begin, state target, std::function heuristic) { +search::path::state, Cost> search::AStar::run(state begin, std::function heuristic) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(target, heuristic))); + std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(heuristic))); { path p; @@ -2240,7 +2346,7 @@ search::path::state, Cost> search::ASt state last{p.back_state()}; expanded.push_back(last); - if (last == target) { + if (this->_is_goal(last)) { return p; } @@ -2259,8 +2365,19 @@ search::path::state, Cost> search::ASt return empty; } +template +constexpr typename search::AStar search::make_AStar(const graph &g, Args &&... args) { + return AStar(g, std::forward(args)...); +} + template -constexpr typename search::AStar search::make_AStar(const graph &g) { - return AStar(g); +std::map::state, search::path::state, Cost>> search::Dijkstra::run(state begin) const { + } + +template +constexpr typename search::Dijkstra search::make_Dijkstra(const graph &g, Args &&... args) { + return Dijkstra(g, std::forward(args)...); +} + #endif diff --git a/src/Graph.cpp b/src/Graph.cpp index 13c8e77..6968905 100644 --- a/src/Graph.cpp +++ b/src/Graph.cpp @@ -2,6 +2,8 @@ /// Created by Terae on 06/12/17. /// +#include + template typename graph::iterator graph::begin() noexcept { return _nodes.begin(); @@ -611,6 +613,16 @@ std::vector::node::edge> graph +bool graph::is_cyclic() const { + +} + +template +bool graph::is_isomorphic() const { + +} + template std::ostream &graph::print(std::ostream &os) const { using std::setw; @@ -664,7 +676,7 @@ std::ostream &graph::print(std::ostream &os) const { size_type max_size_1{0}, max_size_2{0}; for_each(cbegin(), cend(), [&max_size_1, &max_size_2, this](const value_type & element) { - std::list child = element.second->get_edges(); + std::list child{element.second->get_edges()}; for_each(child.cbegin(), child.cend(), [ &, this](const typename node::edge & i) { ostringstream out_1, out_2; out_1 << element.first; @@ -685,7 +697,7 @@ std::ostream &graph::print(std::ostream &os) const { size_type p{0}; for_each(cbegin(), cend(), [ =, &os, &p](const value_type & element) { - std::list child = element.second->get_edges(); + std::list child{element.second->get_edges()}; for_each(child.cbegin(), child.cend(), [ =, &os, &p](const typename node::edge & i) { ostringstream out_1, out_2; out_1 << element.first << '"' << separator; @@ -798,6 +810,60 @@ graph &graph::load(const char* filepath) { return *this; } +template +std::ostream &graph::generate_dot(std::ostream &os, const std::string &name) const { + const std::string tab{" "}; + + //! Displaying nature + graph name + if (name.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-") != name.npos) { + GRAPH_THROW_WITH(invalid_argument, "Wrong graph name given; accepted characters: [a-zA-Z0-9_-]") + } + + if (get_nature() == DIRECTED) { + os << "di"; + } + os << "graph "; + if (!name.empty()) { + os << name << ' '; + } + os << "{\n"; + + //! Displaying nodes' name + for (const_iterator it{cbegin()}; it != cend(); ++it) { + os << tab << it->first << '\n'; + } + + if (get_nature() == DIRECTED) { + for_each(cbegin(), cend(), [ =, &os](const value_type & element) { + std::list child{element.second->get_edges()}; + for_each(child.cbegin(), child.cend(), [ =, &os](const typename node::edge & i) { + if (i.cost() != infinity) { + os << tab << element.first << " -> " << i.target()->first << '\n'; + } + }); + }); + } else { /// get_nature() == UNDIRECTED + std::set> list_edges; + for_each(cbegin(), cend(), [ =, &os, &list_edges](const value_type & element) { + std::list child{element.second->get_edges()}; + for_each(child.cbegin(), child.cend(), [ =, &os, &list_edges](const typename node::edge & i) { + if (i.cost() != infinity) { + const Key min{std::min(element.first, i.target()->first)}; + const Key max{std::max(element.first, i.target()->first)}; + list_edges.emplace(std::make_pair(min, max)); + } + }); + }); + + for_each(list_edges.cbegin(), list_edges.cend(), [ =, &os](const std::pair &p) { + os << tab << p.first << " -- " << p.second << '\n'; + }); + } + os << '}'; + + return os; +} + template template bool graph::operator==(const graph &other) const noexcept { @@ -806,7 +872,7 @@ bool graph::operator==(const graph &other) const typedef std::list::iterator, Iterator1>::edge> Set1; typedef std::list::iterator, Iterator2>::edge> Set2; - if (get_nature() != other.get_nature() || + if (get_nature() != other.get_nature() || get_nbr_nodes() != other.get_nbr_nodes() || get_nbr_edges() != other.get_nbr_edges()) { return false; diff --git a/src/Graph.h b/src/Graph.h index 115ed1a..a52b655 100644 --- a/src/Graph.h +++ b/src/Graph.h @@ -286,22 +286,31 @@ class graph { template ::value>> inline std::vector get_edges (const key_type &) const; + // TODO + bool is_cyclic() const; + + // TODO + bool is_isomorphic() const; + /// //! @section Text functions /// - template friend std::ostream &operator<<(std::ostream &os, const graph &g); - template friend std::istream &operator>>(std::istream &is, graph &g); + template friend std::ostream &operator<<(std::ostream &, const graph &); + template friend std::istream &operator>>(std::istream &, graph &); void save(const char* filepath) const; graph &load(const char* filepath); + /// @param name Optional; accepted characters: [a-zA-Z0-9_-] + std::ostream &generate_dot(std::ostream &, const std::string &name = "") const; + /// //! @section Bool operators /// - template bool operator==(const graph &other) const noexcept; - template bool operator!=(const graph &other) const noexcept; + template bool operator==(const graph &) const noexcept; + template bool operator!=(const graph &) const noexcept; /// CRTP: https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern class node : public basic_node { diff --git a/src/GraphSearch.cpp b/src/GraphSearch.cpp index b2177c6..7144e91 100644 --- a/src/GraphSearch.cpp +++ b/src/GraphSearch.cpp @@ -73,11 +73,11 @@ std::pair search::path::pop_front() { ///////////////////////////////////////////////// template -search::pathComparator::pathComparator(stateType target, std::function h) : _target(target), _heuristic(h) {} +search::pathComparator::pathComparator(std::function h) : _heuristic(h) {} template bool search::pathComparator::operator() (const path &p1, const path &p2) { - return (p1.total_cost() + _heuristic(p1.back_state(), _target)) > (p2.total_cost() + _heuristic(p2.back_state(), _target)); + return (p1.total_cost() + _heuristic(p1.back_state())) > (p2.total_cost() + _heuristic(p2.back_state())); } ///////////////////////////////////////////////// @@ -85,17 +85,23 @@ bool search::pathComparator::operator() (const path -search::abstractSearch::abstractSearch(const graph &g_) : g(g_) {} +search::abstractSearch::abstractSearch(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} + +template +search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, state target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { + this->_targets.emplace_back(target); +} + +template +search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, const std::list &list_target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), + _targets(list_target) {} ///////////////////////////////////////////////////// ///// IMPLEMENTATION OF FIRST SEARCH ALGORITHMS ///// ///////////////////////////////////////////////////// template -search::abstractFirstSearch::abstractFirstSearch(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::abstractFirstSearch::run(state begin, state target) { +search::path::state, Cost> search::abstractFirstSearch::run(state begin) const { std::list expanded; std::deque> frontier; @@ -114,7 +120,7 @@ search::path_is_goal(last)) { return p; } @@ -138,14 +144,14 @@ search::path -constexpr typename search::BFS search::make_BFS(const graph &g) { - return BFS(g); +template +constexpr typename search::BFS search::make_BFS(const graph &g, Args &&... args) { + return BFS(g, std::forward(args)...); } -template -constexpr typename search::DFS search::make_DFS(const graph &g) { - return DFS(g); +template +constexpr typename search::DFS search::make_DFS(const graph &g, Args &&... args) { + return DFS(g, std::forward(args)...); } //////////////////////////////////////////////////////////// @@ -153,10 +159,7 @@ constexpr typename search::DFS search::make_DFS(const graph -search::DLS::DLS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::DLS::run(state begin, state target, int depth) { +search::path::state, Cost> search::DLS::run(state begin, int depth) const { std::list expanded; std::deque> frontier; @@ -176,7 +179,7 @@ search::path::state, Cost> search::DLS_is_goal(last)) { return p; } @@ -218,20 +221,17 @@ search::path::state, Cost> search::DLS();*/ } -template -constexpr typename search::DLS search::make_DLS(const graph &g) { - return DLS(g); +template +constexpr typename search::DLS search::make_DLS(const graph &g, Args &&... args) { + return DLS(g, std::forward(args)...); } template -search::IDDFS::IDDFS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::IDDFS::run(state begin, state target) { - search::DLS dls{make_DLS(this->g)}; +search::path::state, Cost> search::IDDFS::run(state begin) const { + search::DLS dls{make_DLS(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { - path found{dls.run(begin, target, i)}; + path found{dls.run(begin, i)}; if (!found.empty()) { return found; } @@ -239,9 +239,9 @@ search::path::state, Cost> search::IDD return path(); } -template -constexpr typename search::IDDFS search::make_IDDFS(const graph &g) { - return IDDFS(g); +template +constexpr typename search::IDDFS search::make_IDDFS(const graph &g, Args &&... args) { + return IDDFS(g, std::forward(args)...); } //////////////////////////////////////////////////// @@ -249,12 +249,9 @@ constexpr typename search::IDDFS search::make_IDDFS(const gra //////////////////////////////////////////////////// template -search::UCS::UCS(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::UCS::run(state begin, state target) { +search::path::state, Cost> search::UCS::run(state begin) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(target, [](state, state) -> double { return 0; }))); + std::priority_queue, std::vector>, pathComparator> frontier(pathComparator([](state) -> double { return 0; } )); { path p; @@ -271,7 +268,7 @@ search::path::state, Cost> search::UCS_is_goal(last)) { return p; } @@ -291,9 +288,9 @@ search::path::state, Cost> search::UCS -constexpr typename search::UCS search::make_UCS(const graph &g) { - return UCS(g); +template +constexpr typename search::UCS search::make_UCS(const graph &g, Args &&... args) { + return UCS(g, std::forward(args)...); } /////////////////////////////////////////// @@ -301,12 +298,9 @@ constexpr typename search::UCS search::make_UCS(const graph -search::AStar::AStar(const graph &g) : abstractSearch(g) {} - -template -search::path::state, Cost> search::AStar::run(state begin, state target, std::function heuristic) { +search::path::state, Cost> search::AStar::run(state begin, std::function heuristic) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(target, heuristic))); + std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(heuristic))); { path p; @@ -323,7 +317,7 @@ search::path::state, Cost> search::ASt state last{p.back_state()}; expanded.push_back(last); - if (last == target) { + if (this->_is_goal(last)) { return p; } @@ -343,7 +337,21 @@ search::path::state, Cost> search::ASt return empty; } +template +constexpr typename search::AStar search::make_AStar(const graph &g, Args &&... args) { + return AStar(g, std::forward(args)...); +} + +///////////////////////////////////////////////// +///// IMPLEMENTATION OF THE Dijkstra SEARCH ///// +///////////////////////////////////////////////// + template -constexpr typename search::AStar search::make_AStar(const graph &g) { - return AStar(g); -} \ No newline at end of file +std::map::state, search::path::state, Cost>> search::Dijkstra::run(state begin) const { + +} + +template +constexpr typename search::Dijkstra search::make_Dijkstra(const graph &g, Args &&... args) { + return Dijkstra(g, std::forward(args)...); +} diff --git a/src/GraphSearch.h b/src/GraphSearch.h index 7ad7bc6..28b9293 100644 --- a/src/GraphSearch.h +++ b/src/GraphSearch.h @@ -10,11 +10,11 @@ namespace search { template class path { template friend class pathComparator; - template friend class abstractSearch; template friend class abstractFirstSearch; template friend class DLS; template friend class UCS; template friend class AStar; + template friend class Dijkstra; public: path(); @@ -43,122 +43,295 @@ namespace search { template class pathComparator { private: - stateType _target; - std::function _heuristic; + std::function _heuristic; public: - pathComparator(stateType target, std::function heuristic); + pathComparator(std::function heuristic); bool operator() (const path &, const path &); }; /// - /// @brief Abstract class of all search algorithms + /// @brief Abstract class for all search algorithms + /// + /// Subclasses: + /// - @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// - @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// - @ref BFS Breadth-First Search algorithm + /// - @ref DFS Depth-First Search algorithm + /// - @ref DLS Depth-Limited Search algorithm + /// - @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// - @ref UCS Uniform-Cost Search algorithm + /// - @ref AStar A* Search algorithm + /// - @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 /// template class abstractSearch { + public: + using state = typename graph::const_iterator; + + explicit abstractSearch(const graph &, std::function is_goal); + protected: const graph &g; - abstractSearch(const graph &); + + std::function _is_goal; + }; + + /// + /// @brief Abstract class for all search algorithms with a specified target + /// + /// Allow the user to give one or several nodes-goal to the algorithm + /// instead of giving a function parameter in entry + /// + /// Subclasses: + /// - @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// - @ref BFS Breadth-First Search algorithm + /// - @ref DFS Depth-First Search algorithm + /// - @ref DLS Depth-Limited Search algorithm + /// - @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// - @ref UCS Uniform-Cost Search algorithm + /// - @ref AStar A* Search algorithm + /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// + template + class abstractTargetedSearch : public abstractSearch { + public: + using abstractSearch::abstractSearch; + + using state = typename graph::const_iterator; + + explicit abstractTargetedSearch(const graph &, state target); + explicit abstractTargetedSearch(const graph &, const std::list &list_target); + + protected: + std::list _targets; }; /// /// @brief Abstract class for Depth-First and Breadth-First Searches + /// /// @tparam insertFront Specialization parameter between DFS (true) and BFS(false) using respectively a `std::stack` and a `std::queue` /// + /// Subclasses: + /// - @ref BFS Breadth-First Search algorithm + /// - @ref DFS Depth-First Search algorithm + /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// template - class abstractFirstSearch : public abstractSearch { + class abstractFirstSearch : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - abstractFirstSearch(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; - path run(state begin, state target); + using state = typename abstractTargetedSearch::state; + + path run(state begin) const; }; /// /// @brief Breadth-First Search class /// @see https://en.wikipedia.org/wiki/Breadth-First_Search /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template using BFS = abstractFirstSearch; - template - constexpr BFS make_BFS(const graph &); + template + constexpr BFS make_BFS(const graph &, Args &&...); /// /// @brief Depth-First Search class /// @see https://en.wikipedia.org/wiki/Depth-First_Search /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template using DFS = abstractFirstSearch; - template - constexpr DFS make_DFS(const graph &); + template + constexpr DFS make_DFS(const graph &, Args &&...); /// /// @brief Depth-Limited Search class /// @see https://en.wikipedia.org/wiki/Iterative_Deepening_Depth-First_Search + /// /// @tparam l Predetermined depth limit 'l' to create a Depth-Limited Search (fix DFS's loop problem). Have to be well choose, in function of the problem. /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template - class DLS : public abstractSearch { + class DLS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - DLS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; + + using state = typename abstractTargetedSearch::state; - path run(state begin, state target, int depth); + path run(state begin, int depth) const; }; - template - constexpr DLS make_DLS(const graph &); + template + constexpr DLS make_DLS(const graph &, Args &&...); /// /// @brief Iterative-Deepening Depth-First Search /// @see https://en.wikipedia.org/wiki/Iterative_Deepening_Depth-First_Search /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template - class IDDFS : public abstractSearch { + class IDDFS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - IDDFS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; - path run(state begin, state target); + using state = typename abstractTargetedSearch::state; + + path run(state begin) const; }; - template - constexpr IDDFS make_IDDFS(const graph &); + template + constexpr IDDFS make_IDDFS(const graph &, Args &&...); /// /// @brief Uniform-Cost Search /// @see https://en.wikipedia.org/wiki/Talk:Uniform-Cost_Search /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref AStar A* Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template - class UCS : public abstractSearch { + class UCS : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - UCS(const graph &); + using abstractTargetedSearch::abstractTargetedSearch; + + using state = typename abstractTargetedSearch::state; - path run(state begin, state target); + path run(state begin) const; }; - template - constexpr UCS make_UCS(const graph &); + template + constexpr UCS make_UCS(const graph &, Args &&...); /// /// @brief A* Search class /// @see https://en.wikipedia.org/wiki/A*_search_algorithm /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref Dijkstra Dijkstra algorithm + /// + /// @since version 1.1 + /// template - class AStar : public abstractSearch { + class AStar : public abstractTargetedSearch { public: - using state = typename graph::const_iterator; - AStar(const graph &g); + using abstractTargetedSearch::abstractTargetedSearch; - path run(state begin, state target, std::function heuristic); + using state = typename abstractTargetedSearch::state; + + path run(state begin, std::function heuristic) const; }; + template + constexpr AStar make_AStar(const graph &, Args &&...); + + /// + /// @brief Dijkstra class + /// @see https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + /// + /// @sa @ref abstractSearch Abstract class for all search algorithms + /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target + /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref BFS Breadth-First Search algorithm + /// @sa @ref DFS Depth-First Search algorithm + /// @sa @ref DLS Depth-Limited Search algorithm + /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm + /// @sa @ref UCS Uniform-Cost Search algorithm + /// @sa @ref AStar A* Search algorithm + /// + /// @since version 1.1 + /// template - constexpr AStar make_AStar(const graph &); + class Dijkstra : public abstractSearch { + public: + using abstractSearch::abstractSearch; + + using state = typename abstractSearch::state; + + // TODO + std::map> run(state begin) const; + }; + + template + constexpr Dijkstra make_Dijkstra(const graph &, Args &&...); } #include "GraphSearch.cpp" \ No newline at end of file diff --git a/test/src/unit-search.cpp b/test/src/unit-search.cpp index d749640..9f0811a 100644 --- a/test/src/unit-search.cpp +++ b/test/src/unit-search.cpp @@ -24,9 +24,10 @@ TEST_CASE("search") { g("node 3", "node 2") = 32; g("node 2", "node 4") = 24; - search::AStar a(g); - search::path p{a.run(g.find("node 1"), g.find("node 4"), [](const Graph::const_iterator & it, const Graph::const_iterator & target) -> double { - return std::abs(it->second->get() - target->second->get()); + Graph::const_iterator target{g.find("node 4")}; + search::AStar a(g, target); + search::path p{a.run(g.find("node 1"), [&g](const Graph::const_iterator & it) -> double { + return std::abs(it->second->get() - g["node 4"]); }) }; diff --git a/test/src/unit-text.cpp b/test/src/unit-text.cpp index e9a53ef..2553ec2 100644 --- a/test/src/unit-text.cpp +++ b/test/src/unit-text.cpp @@ -376,4 +376,49 @@ TEST_CASE("text") { Graph_undirected g3; CHECK_THROWS_WITH(g3.load("/tmp/graph.txt"), "[graph.exception.invalid_argument] Bad graph nature (expected 'digraph') when calling 'operator>>'."); } + + SECTION("generate_dot(ostream &, string)") { + Graph_directed g1; + g1[0]; + g1(1, 2) = 1; + g1(1, 3) = 1; + g1(4, 2) = 1; + g1(1, 4); // infinite edge + ostringstream out1; + const string result1{"digraph g1 {\n" + " 0\n" + " 1\n" + " 2\n" + " 3\n" + " 4\n" + " 1 -> 2\n" + " 1 -> 3\n" + " 4 -> 2\n" + "}"}; + g1.generate_dot(out1, "g1"); + CHECK(result1 == out1.str()); + + Graph_undirected g2; + g2[0]; + g2(1, 2) = 1; + g2(1, 3) = 1; + g2(4, 2) = 1; + g2(1, 4); // infinite edge + ostringstream out2; + const string result2{"graph g2 {\n" + " 0\n" + " 1\n" + " 2\n" + " 3\n" + " 4\n" + " 1 -- 2\n" + " 1 -- 3\n" + " 2 -- 4\n" + "}"}; + g2.generate_dot(out2, "g2"); + CHECK(result2 == out2.str()); + + CHECK_THROWS_WITH(g1.generate_dot(out1, "wrong name"), "[graph.exception.invalid_argument] Wrong graph name given; accepted characters: [a-zA-Z0-9_-] when calling 'generate_dot'."); + + } } From 165dd2da44da426bb0d3131ad469a2a2825e94b7 Mon Sep 17 00:00:00 2001 From: Benjamin Bigey Date: Wed, 24 Jan 2018 17:25:52 +0100 Subject: [PATCH 2/4] Normalization of function names in GraphSearch class. --- doc/examples/route_finding.cpp | 62 ++++---- single_include/graph.hpp | 138 ++++++++--------- src/GraphSearch.cpp | 56 +++---- src/GraphSearch.h | 270 ++++++++++++++++----------------- test/src/unit-search.cpp | 2 +- 5 files changed, 264 insertions(+), 264 deletions(-) diff --git a/doc/examples/route_finding.cpp b/doc/examples/route_finding.cpp index a757515..ca601ba 100644 --- a/doc/examples/route_finding.cpp +++ b/doc/examples/route_finding.cpp @@ -62,42 +62,42 @@ int main() { const string BEGIN{"Arad"}; - auto DFS = search::make_DFS(map, map.find("Bucharest")); - auto pDFS = DFS.run (map.find(BEGIN)); + auto dfs = search::make_dfs(map, map.find("Bucharest")); + auto pdfs = dfs.run (map.find(BEGIN)); - auto BFS = search::make_BFS(map, map.find("Bucharest")); - auto pBFS = BFS.run (map.find(BEGIN)); + auto bfs = search::make_bfs(map, map.find("Bucharest")); + auto pbfs = bfs.run (map.find(BEGIN)); - auto DLS = search::make_DLS(map, map.find("Bucharest")); - auto pDLS = DLS.run (map.find(BEGIN), 5); + auto dls = search::make_dls(map, map.find("Bucharest")); + auto pdls = dls.run (map.find(BEGIN), 5); - auto IDDFS = search::make_IDDFS(map, map.find("Bucharest")); - auto pIDDFS = IDDFS.run(map.find(BEGIN)); + auto iddfs = search::make_iddfs(map, map.find("Bucharest")); + auto piddfs = iddfs.run(map.find(BEGIN)); - auto UCS = search::make_UCS(map, map.find("Bucharest")); - auto pUCS = UCS.run (map.find(BEGIN)); + auto ucs = search::make_ucs(map, map.find("Bucharest")); + auto pucs = ucs.run (map.find(BEGIN)); - auto aStar = search::make_AStar(map, map.find("Bucharest")); + auto astar = search::make_astar(map, map.find("Bucharest")); auto heuristic = [&straight_line_Bucharest](const graph_undirected::const_iterator & it) -> double { if (it->first == "Bucharest") { return straight_line_Bucharest[it->first]; } }; - auto pAStar = aStar.run(map.find(BEGIN), heuristic); + auto pastar = astar.run(map.find(BEGIN), heuristic); - const size_t nr_digits_IDDFS{static_cast(pIDDFS.empty() ? 0 : log10(pIDDFS.get_nr_steps()) + 1)}; + const size_t nr_digits_iddfs{static_cast(piddfs.empty() ? 0 : log10(piddfs.get_nr_steps()) + 1)}; cout << "\nCalculation of the shortest path from '" << BEGIN << "' to 'Bucharest' with several search algorithms:\n" - << " | \x1B[34m\x1B[1mBreadth-First Search\x1B[0m | \x1B[34m\x1B[1mDepth-First Search\x1B[0m | \x1B[34m\x1B[1mDepth-Limited Search (5)\x1B[0m | \x1B[34m\x1B[1mUniform-Cost Search\x1B[0m | \x1B[34m\x1B[1mIterative-Deepening Depth-First Search (" << pIDDFS.get_nr_steps() << ")\x1B[0m | \x1B[34m\x1B[1mA* Search\x1B[0m |\n" - << "--------------|----------------------|----------------------|--------------------------|----------------------|-------------------------------------------" << string(nr_digits_IDDFS, '-') << "|----------------------|\n" - << " Total cost |\x1B[31m" << setw(13) << pBFS.total_cost() << " \x1B[0m|\x1B[31m" << setw(14) << pDFS.total_cost() << " \x1B[0m|\x1B[31m" << setw(15) << pDLS.total_cost() << " \x1B[0m|\x1B[31m" << setw(14) << pUCS.total_cost() << " \x1B[0m|\x1B[31m" << setw(25) << pIDDFS.total_cost() << string(nr_digits_IDDFS, ' ') << " \x1B[0m|\x1B[31m" << setw(14) << pAStar.total_cost() << " \x1B[0m|\n" + << " | \x1B[34m\x1B[1mBreadth-First Search\x1B[0m | \x1B[34m\x1B[1mDepth-First Search\x1B[0m | \x1B[34m\x1B[1mDepth-Limited Search (5)\x1B[0m | \x1B[34m\x1B[1mUniform-Cost Search\x1B[0m | \x1B[34m\x1B[1mIterative-Deepening Depth-First Search (" << piddfs.get_nr_steps() << ")\x1B[0m | \x1B[34m\x1B[1mA* Search\x1B[0m |\n" + << "--------------|----------------------|----------------------|--------------------------|----------------------|-------------------------------------------" << string(nr_digits_iddfs, '-') << "|----------------------|\n" + << " Total cost |\x1B[31m" << setw(13) << pbfs.total_cost() << " \x1B[0m|\x1B[31m" << setw(14) << pdfs.total_cost() << " \x1B[0m|\x1B[31m" << setw(15) << pdls.total_cost() << " \x1B[0m|\x1B[31m" << setw(14) << pucs.total_cost() << " \x1B[0m|\x1B[31m" << setw(25) << piddfs.total_cost() << string(nr_digits_iddfs, ' ') << " \x1B[0m|\x1B[31m" << setw(14) << pastar.total_cost() << " \x1B[0m|\n" << " | | | | | | |\n"; int i{1}, col1{0}, col2{0}, col3{0}, col4{0}, col5{0}, col6{0}; - for (; !(pBFS.empty() && pDFS.empty() && pDLS.empty() && pIDDFS.empty() && pUCS.empty() && pAStar.empty()); ++i) { + for (; !(pbfs.empty() && pdfs.empty() && pdls.empty() && piddfs.empty() && pucs.empty() && pastar.empty()); ++i) { cout << left << setw(13) << (" Step " + to_string(i)) << " |" << right; - if (!pBFS.empty()) { - auto p = pBFS.pop_front(); + if (!pbfs.empty()) { + auto p = pbfs.pop_front(); col1 += p.second; cout << setw(21) << (p.first->first + " (" + to_string(col1) + ")"); } else { @@ -105,8 +105,8 @@ int main() { } cout << " |"; - if (!pDFS.empty()) { - auto p = pDFS.pop_front(); + if (!pdfs.empty()) { + auto p = pdfs.pop_front(); col2 += p.second; cout << setw(21) << (p.first->first + " (" + to_string(col2) + ")"); } else { @@ -114,8 +114,8 @@ int main() { } cout << " |"; - if (!pDLS.empty()) { - auto p = pDLS.pop_front(); + if (!pdls.empty()) { + auto p = pdls.pop_front(); col3 += p.second; cout << setw(25) << (p.first->first + " (" + to_string(col3) + ")"); } else { @@ -123,8 +123,8 @@ int main() { } cout << " |"; - if (!pUCS.empty()) { - auto p = pUCS.pop_front(); + if (!pucs.empty()) { + auto p = pucs.pop_front(); col4 += p.second; cout << setw(21) << (p.first->first + " (" + to_string(col4) + ")"); } else { @@ -132,17 +132,17 @@ int main() { } cout << " |"; - if (!pIDDFS.empty()) { - auto p = pIDDFS.pop_front(); + if (!piddfs.empty()) { + auto p = piddfs.pop_front(); col5 += p.second; - cout << setw(42 + static_cast(nr_digits_IDDFS)) << (p.first->first + " (" + to_string(col5) + ")"); + cout << setw(42 + static_cast(nr_digits_iddfs)) << (p.first->first + " (" + to_string(col5) + ")"); } else { - cout << string(23, ' ') << '-' << string(18 + nr_digits_IDDFS, ' '); + cout << string(23, ' ') << '-' << string(18 + nr_digits_iddfs, ' '); } cout << " |"; - if (!pAStar.empty()) { - auto p = pAStar.pop_front(); + if (!pastar.empty()) { + auto p = pastar.pop_front(); col6 += p.second; cout << setw(21) << (p.first->first + " (" + to_string(col6) + ")"); } else { diff --git a/single_include/graph.hpp b/single_include/graph.hpp index 378557f..76b7e9c 100644 --- a/single_include/graph.hpp +++ b/single_include/graph.hpp @@ -757,12 +757,12 @@ using graph_undirected = graph; namespace search { template class path { - template friend class pathComparator; - template friend class abstractFirstSearch; - template friend class DLS; - template friend class UCS; - template friend class AStar; - template friend class Dijkstra; + template friend class path_comparator; + template friend class abstract_first_search; + template friend class dls; + template friend class ucs; + template friend class astar; + template friend class dijkstra; public: path(); @@ -788,22 +788,22 @@ namespace search { }; template - class pathComparator { + class path_comparator { private: std::function _heuristic; public: - pathComparator(std::function heuristic); + path_comparator(std::function heuristic); bool operator() (const path &, const path &); }; template - class abstractSearch { + class abstract_search { public: using state = typename graph::const_iterator; - explicit abstractSearch(const graph &, std::function is_goal); + explicit abstract_search(const graph &, std::function is_goal); protected: const graph &g; @@ -812,106 +812,106 @@ namespace search { }; template - class abstractTargetedSearch : public abstractSearch { + class abstract_targeted_search : public abstract_search { public: - using abstractSearch::abstractSearch; + using abstract_search::abstract_search; using state = typename graph::const_iterator; - explicit abstractTargetedSearch(const graph &, state target); - explicit abstractTargetedSearch(const graph &, const std::list &list_target); + explicit abstract_targeted_search(const graph &, state target); + explicit abstract_targeted_search(const graph &, const std::list &list_target); protected: std::list _targets; }; template - class abstractFirstSearch : public abstractTargetedSearch { + class abstract_first_search : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; template - using BFS = abstractFirstSearch; + using bfs = abstract_first_search; template - constexpr BFS make_BFS(const graph &, Args &&...); + constexpr bfs make_bfs(const graph &, Args &&...); template - using DFS = abstractFirstSearch; + using dfs = abstract_first_search; template - constexpr DFS make_DFS(const graph &, Args &&...); + constexpr dfs make_dfs(const graph &, Args &&...); template - class DLS : public abstractTargetedSearch { + class dls : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin, int depth) const; }; template - constexpr DLS make_DLS(const graph &, Args &&...); + constexpr dls make_dls(const graph &, Args &&...); template - class IDDFS : public abstractTargetedSearch { + class iddfs : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; template - constexpr IDDFS make_IDDFS(const graph &, Args &&...); + constexpr iddfs make_iddfs(const graph &, Args &&...); template - class UCS : public abstractTargetedSearch { + class ucs : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; template - constexpr UCS make_UCS(const graph &, Args &&...); + constexpr ucs make_ucs(const graph &, Args &&...); template - class AStar : public abstractTargetedSearch { + class astar : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin, std::function heuristic) const; }; template - constexpr AStar make_AStar(const graph &, Args &&...); + constexpr astar make_astar(const graph &, Args &&...); template - class Dijkstra : public abstractSearch { + class dijkstra : public abstract_search { public: - using abstractSearch::abstractSearch; + using abstract_search::abstract_search; - using state = typename abstractSearch::state; + using state = typename abstract_search::state; // TODO std::map> run(state begin) const; }; template - constexpr Dijkstra make_Dijkstra(const graph &, Args &&...); + constexpr dijkstra make_dijkstra(const graph &, Args &&...); } template @@ -2129,27 +2129,27 @@ std::pair search::path::pop_front() { } template -search::pathComparator::pathComparator(std::function h) : _heuristic(h) {} +search::path_comparator::path_comparator(std::function h) : _heuristic(h) {} template -bool search::pathComparator::operator() (const path &p1, const path &p2) { +bool search::path_comparator::operator() (const path &p1, const path &p2) { return (p1.total_cost() + _heuristic(p1.back_state())) > (p2.total_cost() + _heuristic(p2.back_state())); } template -search::abstractSearch::abstractSearch(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} +search::abstract_search::abstract_search(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} template -search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, state target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { +search::abstract_targeted_search::abstract_targeted_search(const graph &g, state target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { this->_targets.emplace_back(target); } template -search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, const std::list &list_target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), +search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), _targets(list_target) {} template -search::path::state, Cost> search::abstractFirstSearch::run(state begin) const { +search::path::state, Cost> search::abstract_first_search::run(state begin) const { std::list expanded; std::deque> frontier; @@ -2191,17 +2191,17 @@ search::path -constexpr typename search::BFS search::make_BFS(const graph &g, Args &&... args) { - return BFS(g, std::forward(args)...); +constexpr typename search::bfs search::make_bfs(const graph &g, Args &&... args) { + return bfs(g, std::forward(args)...); } template -constexpr typename search::DFS search::make_DFS(const graph &g, Args &&... args) { - return DFS(g, std::forward(args)...); +constexpr typename search::dfs search::make_dfs(const graph &g, Args &&... args) { + return dfs(g, std::forward(args)...); } template -search::path::state, Cost> search::DLS::run(state begin, int depth) const { +search::path::state, Cost> search::dls::run(state begin, int depth) const { std::list expanded; std::deque> frontier; @@ -2262,13 +2262,13 @@ search::path::state, Cost> search::DLS -constexpr typename search::DLS search::make_DLS(const graph &g, Args &&... args) { - return DLS(g, std::forward(args)...); +constexpr typename search::dls search::make_dls(const graph &g, Args &&... args) { + return dls(g, std::forward(args)...); } template -search::path::state, Cost> search::IDDFS::run(state begin) const { - search::DLS dls{make_DLS(this->g, this->_targets)}; +search::path::state, Cost> search::iddfs::run(state begin) const { + search::dls dls{make_DLS(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { path found{dls.run(begin, i)}; @@ -2280,14 +2280,14 @@ search::path::state, Cost> search::IDD } template -constexpr typename search::IDDFS search::make_IDDFS(const graph &g, Args &&... args) { - return IDDFS(g, std::forward(args)...); +constexpr typename search::iddfs search::make_iddfs(const graph &g, Args &&... args) { + return iddfs(g, std::forward(args)...); } template -search::path::state, Cost> search::UCS::run(state begin) const { +search::path::state, Cost> search::ucs::run(state begin) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier(pathComparator([](state) -> double { return 0; } )); + std::priority_queue, std::vector>, path_comparator> frontier(path_comparator([](state) -> double { return 0; } )); { path p; @@ -2323,14 +2323,14 @@ search::path::state, Cost> search::UCS -constexpr typename search::UCS search::make_UCS(const graph &g, Args &&... args) { - return UCS(g, std::forward(args)...); +constexpr typename search::ucs search::make_ucs(const graph &g, Args &&... args) { + return ucs(g, std::forward(args)...); } template -search::path::state, Cost> search::AStar::run(state begin, std::function heuristic) const { +search::path::state, Cost> search::astar::run(state begin, std::function heuristic) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(heuristic))); + std::priority_queue, std::vector>, path_comparator> frontier((path_comparator(heuristic))); { path p; @@ -2366,18 +2366,18 @@ search::path::state, Cost> search::ASt } template -constexpr typename search::AStar search::make_AStar(const graph &g, Args &&... args) { - return AStar(g, std::forward(args)...); +constexpr typename search::astar search::make_astar(const graph &g, Args &&... args) { + return astar(g, std::forward(args)...); } template -std::map::state, search::path::state, Cost>> search::Dijkstra::run(state begin) const { +std::map::state, search::path::state, Cost>> search::dijkstra::run(state begin) const { } template -constexpr typename search::Dijkstra search::make_Dijkstra(const graph &g, Args &&... args) { - return Dijkstra(g, std::forward(args)...); +constexpr typename search::dijkstra search::make_dijkstra(const graph &g, Args &&... args) { + return dijkstra(g, std::forward(args)...); } #endif diff --git a/src/GraphSearch.cpp b/src/GraphSearch.cpp index 7144e91..775ffdc 100644 --- a/src/GraphSearch.cpp +++ b/src/GraphSearch.cpp @@ -73,10 +73,10 @@ std::pair search::path::pop_front() { ///////////////////////////////////////////////// template -search::pathComparator::pathComparator(std::function h) : _heuristic(h) {} +search::path_comparator::path_comparator(std::function h) : _heuristic(h) {} template -bool search::pathComparator::operator() (const path &p1, const path &p2) { +bool search::path_comparator::operator() (const path &p1, const path &p2) { return (p1.total_cost() + _heuristic(p1.back_state())) > (p2.total_cost() + _heuristic(p2.back_state())); } @@ -85,15 +85,15 @@ bool search::pathComparator::operator() (const path -search::abstractSearch::abstractSearch(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} +search::abstract_search::abstract_search(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} template -search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, state target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { +search::abstract_targeted_search::abstract_targeted_search(const graph &g, state target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { this->_targets.emplace_back(target); } template -search::abstractTargetedSearch::abstractTargetedSearch(const graph &g, const std::list &list_target) : abstractSearch(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), +search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), _targets(list_target) {} ///////////////////////////////////////////////////// @@ -101,7 +101,7 @@ search::abstractTargetedSearch::abstractTargetedSearch(const ///////////////////////////////////////////////////// template -search::path::state, Cost> search::abstractFirstSearch::run(state begin) const { +search::path::state, Cost> search::abstract_first_search::run(state begin) const { std::list expanded; std::deque> frontier; @@ -145,13 +145,13 @@ search::path -constexpr typename search::BFS search::make_BFS(const graph &g, Args &&... args) { - return BFS(g, std::forward(args)...); +constexpr typename search::bfs search::make_bfs(const graph &g, Args &&... args) { + return bfs(g, std::forward(args)...); } template -constexpr typename search::DFS search::make_DFS(const graph &g, Args &&... args) { - return DFS(g, std::forward(args)...); +constexpr typename search::dfs search::make_dfs(const graph &g, Args &&... args) { + return dfs(g, std::forward(args)...); } //////////////////////////////////////////////////////////// @@ -159,7 +159,7 @@ constexpr typename search::DFS search::make_DFS(const graph -search::path::state, Cost> search::DLS::run(state begin, int depth) const { +search::path::state, Cost> search::dls::run(state begin, int depth) const { std::list expanded; std::deque> frontier; @@ -222,13 +222,13 @@ search::path::state, Cost> search::DLS -constexpr typename search::DLS search::make_DLS(const graph &g, Args &&... args) { - return DLS(g, std::forward(args)...); +constexpr typename search::dls search::make_dls(const graph &g, Args &&... args) { + return dls(g, std::forward(args)...); } template -search::path::state, Cost> search::IDDFS::run(state begin) const { - search::DLS dls{make_DLS(this->g, this->_targets)}; +search::path::state, Cost> search::iddfs::run(state begin) const { + search::dls dls{make_DLS(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { path found{dls.run(begin, i)}; @@ -240,8 +240,8 @@ search::path::state, Cost> search::IDD } template -constexpr typename search::IDDFS search::make_IDDFS(const graph &g, Args &&... args) { - return IDDFS(g, std::forward(args)...); +constexpr typename search::iddfs search::make_iddfs(const graph &g, Args &&... args) { + return iddfs(g, std::forward(args)...); } //////////////////////////////////////////////////// @@ -249,9 +249,9 @@ constexpr typename search::IDDFS search::make_IDDFS(const gra //////////////////////////////////////////////////// template -search::path::state, Cost> search::UCS::run(state begin) const { +search::path::state, Cost> search::ucs::run(state begin) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier(pathComparator([](state) -> double { return 0; } )); + std::priority_queue, std::vector>, path_comparator> frontier(path_comparator([](state) -> double { return 0; } )); { path p; @@ -289,8 +289,8 @@ search::path::state, Cost> search::UCS -constexpr typename search::UCS search::make_UCS(const graph &g, Args &&... args) { - return UCS(g, std::forward(args)...); +constexpr typename search::ucs search::make_ucs(const graph &g, Args &&... args) { + return ucs(g, std::forward(args)...); } /////////////////////////////////////////// @@ -298,9 +298,9 @@ constexpr typename search::UCS search::make_UCS(const graph -search::path::state, Cost> search::AStar::run(state begin, std::function heuristic) const { +search::path::state, Cost> search::astar::run(state begin, std::function heuristic) const { std::list expanded; - std::priority_queue, std::vector>, pathComparator> frontier((pathComparator(heuristic))); + std::priority_queue, std::vector>, path_comparator> frontier((path_comparator(heuristic))); { path p; @@ -338,8 +338,8 @@ search::path::state, Cost> search::ASt } template -constexpr typename search::AStar search::make_AStar(const graph &g, Args &&... args) { - return AStar(g, std::forward(args)...); +constexpr typename search::astar search::make_astar(const graph &g, Args &&... args) { + return astar(g, std::forward(args)...); } ///////////////////////////////////////////////// @@ -347,11 +347,11 @@ constexpr typename search::AStar search::make_AStar(const gra ///////////////////////////////////////////////// template -std::map::state, search::path::state, Cost>> search::Dijkstra::run(state begin) const { +std::map::state, search::path::state, Cost>> search::dijkstra::run(state begin) const { } template -constexpr typename search::Dijkstra search::make_Dijkstra(const graph &g, Args &&... args) { - return Dijkstra(g, std::forward(args)...); +constexpr typename search::dijkstra search::make_dijkstra(const graph &g, Args &&... args) { + return dijkstra(g, std::forward(args)...); } diff --git a/src/GraphSearch.h b/src/GraphSearch.h index 28b9293..1e8fb65 100644 --- a/src/GraphSearch.h +++ b/src/GraphSearch.h @@ -9,12 +9,12 @@ namespace search { template class path { - template friend class pathComparator; - template friend class abstractFirstSearch; - template friend class DLS; - template friend class UCS; - template friend class AStar; - template friend class Dijkstra; + template friend class path_comparator; + template friend class abstract_first_search; + template friend class dls; + template friend class ucs; + template friend class astar; + template friend class dijkstra; public: path(); @@ -41,12 +41,12 @@ namespace search { }; template - class pathComparator { + class path_comparator { private: std::function _heuristic; public: - pathComparator(std::function heuristic); + path_comparator(std::function heuristic); bool operator() (const path &, const path &); }; @@ -55,24 +55,24 @@ namespace search { /// @brief Abstract class for all search algorithms /// /// Subclasses: - /// - @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// - @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// - @ref BFS Breadth-First Search algorithm - /// - @ref DFS Depth-First Search algorithm - /// - @ref DLS Depth-Limited Search algorithm - /// - @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// - @ref UCS Uniform-Cost Search algorithm - /// - @ref AStar A* Search algorithm - /// - @ref Dijkstra Dijkstra algorithm + /// - @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// - @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// - @ref bfs Breadth-First Search algorithm + /// - @ref dfs Depth-First Search algorithm + /// - @ref dls Depth-Limited Search algorithm + /// - @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// - @ref ucs Uniform-Cost Search algorithm + /// - @ref astar A* Search algorithm + /// - @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class abstractSearch { + class abstract_search { public: using state = typename graph::const_iterator; - explicit abstractSearch(const graph &, std::function is_goal); + explicit abstract_search(const graph &, std::function is_goal); protected: const graph &g; @@ -87,28 +87,28 @@ namespace search { /// instead of giving a function parameter in entry /// /// Subclasses: - /// - @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// - @ref BFS Breadth-First Search algorithm - /// - @ref DFS Depth-First Search algorithm - /// - @ref DLS Depth-Limited Search algorithm - /// - @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// - @ref UCS Uniform-Cost Search algorithm - /// - @ref AStar A* Search algorithm + /// - @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// - @ref bfs Breadth-First Search algorithm + /// - @ref dfs Depth-First Search algorithm + /// - @ref dls Depth-Limited Search algorithm + /// - @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// - @ref ucs Uniform-Cost Search algorithm + /// - @ref astar A* Search algorithm /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class abstractTargetedSearch : public abstractSearch { + class abstract_targeted_search : public abstract_search { public: - using abstractSearch::abstractSearch; + using abstract_search::abstract_search; using state = typename graph::const_iterator; - explicit abstractTargetedSearch(const graph &, state target); - explicit abstractTargetedSearch(const graph &, const std::list &list_target); + explicit abstract_targeted_search(const graph &, state target); + explicit abstract_targeted_search(const graph &, const std::list &list_target); protected: std::list _targets; @@ -117,26 +117,26 @@ namespace search { /// /// @brief Abstract class for Depth-First and Breadth-First Searches /// - /// @tparam insertFront Specialization parameter between DFS (true) and BFS(false) using respectively a `std::stack` and a `std::queue` + /// @tparam insertFront Specialization parameter between dfs (true) and bfs(false) using respectively a `std::stack` and a `std::queue` /// /// Subclasses: - /// - @ref BFS Breadth-First Search algorithm - /// - @ref DFS Depth-First Search algorithm + /// - @ref bfs Breadth-First Search algorithm + /// - @ref dfs Depth-First Search algorithm /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// template - class abstractFirstSearch : public abstractTargetedSearch { + class abstract_first_search : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; @@ -145,193 +145,193 @@ namespace search { /// @brief Breadth-First Search class /// @see https://en.wikipedia.org/wiki/Breadth-First_Search /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - using BFS = abstractFirstSearch; + using bfs = abstract_first_search; template - constexpr BFS make_BFS(const graph &, Args &&...); + constexpr bfs make_bfs(const graph &, Args &&...); /// /// @brief Depth-First Search class /// @see https://en.wikipedia.org/wiki/Depth-First_Search /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - using DFS = abstractFirstSearch; + using dfs = abstract_first_search; template - constexpr DFS make_DFS(const graph &, Args &&...); + constexpr dfs make_dfs(const graph &, Args &&...); /// /// @brief Depth-Limited Search class /// @see https://en.wikipedia.org/wiki/Iterative_Deepening_Depth-First_Search /// - /// @tparam l Predetermined depth limit 'l' to create a Depth-Limited Search (fix DFS's loop problem). Have to be well choose, in function of the problem. + /// @tparam l Predetermined depth limit 'l' to create a Depth-Limited Search (fix dfs's loop problem). Have to be well choose, in function of the problem. /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class DLS : public abstractTargetedSearch { + class dls : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin, int depth) const; }; template - constexpr DLS make_DLS(const graph &, Args &&...); + constexpr dls make_dls(const graph &, Args &&...); /// /// @brief Iterative-Deepening Depth-First Search /// @see https://en.wikipedia.org/wiki/Iterative_Deepening_Depth-First_Search /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class IDDFS : public abstractTargetedSearch { + class iddfs : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; template - constexpr IDDFS make_IDDFS(const graph &, Args &&...); + constexpr iddfs make_iddfs(const graph &, Args &&...); /// /// @brief Uniform-Cost Search /// @see https://en.wikipedia.org/wiki/Talk:Uniform-Cost_Search /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref AStar A* Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref astar A* Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class UCS : public abstractTargetedSearch { + class ucs : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin) const; }; template - constexpr UCS make_UCS(const graph &, Args &&...); + constexpr ucs make_ucs(const graph &, Args &&...); /// /// @brief A* Search class /// @see https://en.wikipedia.org/wiki/A*_search_algorithm /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref Dijkstra Dijkstra algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref dijkstra dijkstra algorithm /// /// @since version 1.1 /// template - class AStar : public abstractTargetedSearch { + class astar : public abstract_targeted_search { public: - using abstractTargetedSearch::abstractTargetedSearch; + using abstract_targeted_search::abstract_targeted_search; - using state = typename abstractTargetedSearch::state; + using state = typename abstract_targeted_search::state; path run(state begin, std::function heuristic) const; }; template - constexpr AStar make_AStar(const graph &, Args &&...); + constexpr astar make_astar(const graph &, Args &&...); /// - /// @brief Dijkstra class - /// @see https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + /// @brief dijkstra class + /// @see https://en.wikipedia.org/wiki/dijkstra%27s_algorithm /// - /// @sa @ref abstractSearch Abstract class for all search algorithms - /// @sa @ref abstractTargetedSearch Abstract class for all search algorithms with a specified target - /// @sa @ref abstractFirstSearch Abstract class for First Search algorithms (BFS, DFS) - /// @sa @ref BFS Breadth-First Search algorithm - /// @sa @ref DFS Depth-First Search algorithm - /// @sa @ref DLS Depth-Limited Search algorithm - /// @sa @ref IDDFS Iterative-Deepening Depth-First Search algorithm - /// @sa @ref UCS Uniform-Cost Search algorithm - /// @sa @ref AStar A* Search algorithm + /// @sa @ref abstract_search Abstract class for all search algorithms + /// @sa @ref abstract_targeted_search Abstract class for all search algorithms with a specified target + /// @sa @ref abstract_first_search Abstract class for First Search algorithms (BFS, DFS) + /// @sa @ref bfs Breadth-First Search algorithm + /// @sa @ref dfs Depth-First Search algorithm + /// @sa @ref dls Depth-Limited Search algorithm + /// @sa @ref iddfs Iterative-Deepening Depth-First Search algorithm + /// @sa @ref ucs Uniform-Cost Search algorithm + /// @sa @ref astar A* Search algorithm /// /// @since version 1.1 /// template - class Dijkstra : public abstractSearch { + class dijkstra : public abstract_search { public: - using abstractSearch::abstractSearch; + using abstract_search::abstract_search; - using state = typename abstractSearch::state; + using state = typename abstract_search::state; // TODO std::map> run(state begin) const; }; template - constexpr Dijkstra make_Dijkstra(const graph &, Args &&...); + constexpr dijkstra make_dijkstra(const graph &, Args &&...); } #include "GraphSearch.cpp" \ No newline at end of file diff --git a/test/src/unit-search.cpp b/test/src/unit-search.cpp index 9f0811a..5f8c4b6 100644 --- a/test/src/unit-search.cpp +++ b/test/src/unit-search.cpp @@ -25,7 +25,7 @@ TEST_CASE("search") { g("node 2", "node 4") = 24; Graph::const_iterator target{g.find("node 4")}; - search::AStar a(g, target); + search::astar a(g, target); search::path p{a.run(g.find("node 1"), [&g](const Graph::const_iterator & it) -> double { return std::abs(it->second->get() - g["node 4"]); }) From f21f3417c706ef9a39856e483594cd684479328f Mon Sep 17 00:00:00 2001 From: Benjamin Bigey Date: Thu, 25 Jan 2018 14:31:58 +0100 Subject: [PATCH 3/4] Better usage of search::run(), update of benchmarks for A*. --- benchmarks/Makefile | 5 +- benchmarks/src/benchmarks.cpp | 168 ++++++++++++++++++--------------- doc/examples/route_finding.cpp | 24 ++--- single_include/graph.hpp | 55 ++++++++++- src/GraphSearch.cpp | 44 ++++++++- src/GraphSearch.h | 9 ++ test/src/unit-search.cpp | 4 +- 7 files changed, 214 insertions(+), 95 deletions(-) diff --git a/benchmarks/Makefile b/benchmarks/Makefile index bd48e43..93f4534 100644 --- a/benchmarks/Makefile +++ b/benchmarks/Makefile @@ -2,14 +2,11 @@ # Build/run graph.hpp benchmarks, eg. CXX=g++-7 make # -all: generation_files graph_benchmarks +all: graph_benchmarks bash -c 'time ./graph_benchmarks' graph_benchmarks: src/benchmarks.cpp ../single_include/graph.hpp $(CXX) -std=c++11 -pthread $(CXXFLAGS) -DNDEBUG -O3 -flto -I third-party/benchpress/src/benchpress -I ../single_include src/benchmarks.cpp $(LDFLAGS) -o $@ -generation_files: - (test -e files/grid_graph.txt && test -e files/complete_graph.txt) || (cd files; g++ generate_files.cpp -o exec; ./exec; rm exec) - clean: rm -f graph_benchmarks diff --git a/benchmarks/src/benchmarks.cpp b/benchmarks/src/benchmarks.cpp index 59f0188..21a169d 100644 --- a/benchmarks/src/benchmarks.cpp +++ b/benchmarks/src/benchmarks.cpp @@ -4,16 +4,20 @@ #define BENCHPRESS_CONFIG_MAIN -#include -#include #include +#include +#include #include #include -#include +#include +#include #include +#define MAX 500 + struct Coord { int x, y; + Coord(int x_ = 0, int y_ = 0) : x(x_), y(y_) {} friend std::ostream &operator<<(std::ostream &os, const Coord &c) { return os << '[' << c.x << ", " << c.y << ']'; } @@ -28,7 +32,7 @@ struct Coord { return y < c.y; } }; -using Graph_grid = graph_undirected; +using Graph_grid = graph_undirected; using Graph_directed = graph_directed ; struct StartUp { @@ -46,41 +50,26 @@ struct StartUp { }; StartUp startup; -enum class EMode { input, output, make_complete/*, search*/ }; - -static void bench(benchpress::context &ctx, - const std::string &in_path, - const EMode mode) { - // using string streams for benmarking to factor-out cold-cache disk access -#if defined( FROMFILE ) - std::ifstream istr; - { - istr.open(in_path, std::ifstream::in); - if (!istr) { - std::cerr << "Unexistant file '" << in_path << "'." << std::endl; - exit(1); - } - } -#else - std::stringstream istr; - { - // read file into string stream - std::ifstream input_file(in_path); - if (input_file) { - istr << input_file.rdbuf(); - input_file.close(); - } else { - std::cerr << "Unexistant file '" << in_path << "'." << std::endl; - exit(1); +enum class EMode { input, output, make_complete, astar/*, search*/ }; + +static void bench(benchpress::context &ctx, const EMode mode) { + graph_undirected grid_graph; + if (mode == EMode::input || mode == EMode::output) { + for (int x{-MAX + 1}; x < MAX; ++x) { + for (int y{-MAX + 1}; y < MAX; ++y) { + grid_graph({x, y}, {x, y + 1}) = 1; + grid_graph({x, y}, {x + 1, y}) = 1; + } } } -#endif switch (mode) { - // benchmarking input + /// Benchmarking input case EMode::input: { - ctx.reset_timer(); + std::stringstream istr; + istr << grid_graph; + ctx.reset_timer(); for (size_t i{0}; i < ctx.num_iterations(); ++i) { // clear flags and rewind istr.clear(); @@ -92,16 +81,14 @@ static void bench(benchpress::context &ctx, break; } - // benmarking output + /// Benchmarking output case EMode::output: { - // create GRAPH value from input - Graph_grid g; - istr >> g; - std::stringstream ostr; + ctx.reset_timer(); + std::ostringstream ostr; ctx.reset_timer(); for (size_t i{0}; i < ctx.num_iterations(); ++i) { - ostr << g; + ostr << grid_graph; // reset data ostr.str(std::string()); @@ -110,50 +97,83 @@ static void bench(benchpress::context &ctx, break; } - // benchmarking big amount of nodes and edges + /// Benchmarking big amount of nodes and edges case EMode::make_complete: { - Graph_directed g; - istr >> g; - std::stringstream ostr; + graph_directed complete_graph; + for (int i{1}; i <= MAX; ++i) { + complete_graph["node " + std::to_string(i)] = i; + } + + ctx.reset_timer(); + for (size_t i{0}; i < ctx.num_iterations(); ++i) { + complete_graph.link_all_nodes(42.0); + } + + break; + } + + /// Benchmarking A* Search algorithm + case EMode::astar: { + Graph_grid g; + for (int x{-4 * MAX + 1}; x < 4 * MAX; ++x) { + for (int y{-4 * MAX + 1}; y < 4 * MAX; ++y) { + g[ {x, y}] = x * 100000 + y; + } + } + + int a{0}, b{0}, c{0}, d{0}; + // all nodes linked in the upper-right corner + for (int x{0}; x < 4 * MAX; ++x) { + for (int y{0}; y < 4 * MAX; ++y) { + a += g.add_edge({x, y}, {x, y + 1}, 1); + a += g.add_edge({x, y}, {x + 1, y}, 1); + } + } + std::default_random_engine generator; + std::uniform_int_distribution negative(-4 * MAX + 1, 0); + std::uniform_int_distribution positive(0, 4 * MAX); + + for (int i{0}; i < 200000; ++i) { + int x{positive(generator)}; + int y{negative(generator)}; + b += g.add_edge({x, y}, {x, y + 1}, 1); + b += g.add_edge({x, y}, {x + 1, y}, 1); + } + + for (int i{0}; i < 200000; ++i) { + int x{negative(generator)}; + int y{positive(generator)}; + c += g.add_edge({x, y}, {x, y + 1}, 1); + c += g.add_edge({x, y}, {x + 1, y}, 1); + } + + for (int i{0}; i < 400000; ++i) { + int x{negative(generator)}; + int y{negative(generator)}; + d += g.add_edge({x, y}, {x, y + 1}, 1); + d += g.add_edge({x, y}, {x + 1, y}, 1); + } ctx.reset_timer(); - g.link_all_nodes(42.0); + for (size_t i{0}; i < ctx.num_iterations(); ++i) { + auto astar = search::make_astar(g, Coord(4 * MAX, 4 * MAX)); + auto search_result = astar.run(g.find({-4 * MAX + 1, -4 * MAX + 1}), [](const Graph_grid::const_iterator & it) -> int { + // Return Manhattan distance + return std::abs(4 * MAX - it->first.x) + std::abs(4 * MAX - it->first.y); + }); + } break; } } } -#define BENCHMARKING_I(mode, title, in_path) \ +#define BENCHMARKING_I(mode, title) \ BENCHMARK((title), [](benchpress::context* ctx) {\ - bench(*ctx, (in_path), (mode)); \ + bench(*ctx, (mode)); \ }); -BENCHMARKING_I(EMode::input, "parse grid_graph.txt", "files/grid_graph.txt") -BENCHMARKING_I(EMode::output, "dump grid_graph.txt", "files/grid_graph.txt") -BENCHMARKING_I(EMode::make_complete, "link_all complete_graph_9.txt", "files/complete_graph_9.txt") - -/* -make all -Generation of 0%... -Generation of 10%... -Generation of 20%... -Generation of 30%... -Generation of 40%... -Generation of 50%... -Generation of 60%... -Generation of 70%... -Generation of 80%... -Generation of 90%... -Write on the file 'grid_graph.txt'... -Done. - -bash -c 'time ./graph_benchmarks' -parse grid_graph.txt 1 14427270641 ns/op -dump grid_graph.txt 1 11092073379 ns/op -./graph_benchmarks 67.453s - -real 1m7,469s -user 1m6,762s -sys 0m0,584s - */ \ No newline at end of file +BENCHMARKING_I(EMode::input, "parse grid_graph.txt") +BENCHMARKING_I(EMode::output, "dump grid_graph.txt") +BENCHMARKING_I(EMode::make_complete, "make_complete a graph of 1000 nodes") +BENCHMARKING_I(EMode::astar, "astar on a graph of 1000 nodes") \ No newline at end of file diff --git a/doc/examples/route_finding.cpp b/doc/examples/route_finding.cpp index ca601ba..3c007ff 100644 --- a/doc/examples/route_finding.cpp +++ b/doc/examples/route_finding.cpp @@ -62,28 +62,28 @@ int main() { const string BEGIN{"Arad"}; - auto dfs = search::make_dfs(map, map.find("Bucharest")); - auto pdfs = dfs.run (map.find(BEGIN)); + auto dfs = search::make_dfs(map, "Bucharest"); + auto pdfs = dfs.run (BEGIN); - auto bfs = search::make_bfs(map, map.find("Bucharest")); - auto pbfs = bfs.run (map.find(BEGIN)); + auto bfs = search::make_bfs(map, "Bucharest"); + auto pbfs = bfs.run (BEGIN); - auto dls = search::make_dls(map, map.find("Bucharest")); - auto pdls = dls.run (map.find(BEGIN), 5); + auto dls = search::make_dls(map, "Bucharest"); + auto pdls = dls.run (BEGIN, 5); - auto iddfs = search::make_iddfs(map, map.find("Bucharest")); - auto piddfs = iddfs.run(map.find(BEGIN)); + auto iddfs = search::make_iddfs(map, "Bucharest"); + auto piddfs = iddfs.run(BEGIN); - auto ucs = search::make_ucs(map, map.find("Bucharest")); - auto pucs = ucs.run (map.find(BEGIN)); + auto ucs = search::make_ucs(map, "Bucharest"); + auto pucs = ucs.run (BEGIN); - auto astar = search::make_astar(map, map.find("Bucharest")); + auto astar = search::make_astar(map, "Bucharest"); auto heuristic = [&straight_line_Bucharest](const graph_undirected::const_iterator & it) -> double { if (it->first == "Bucharest") { return straight_line_Bucharest[it->first]; } }; - auto pastar = astar.run(map.find(BEGIN), heuristic); + auto pastar = astar.run(BEGIN, heuristic); const size_t nr_digits_iddfs{static_cast(piddfs.empty() ? 0 : log10(piddfs.get_nr_steps()) + 1)}; cout << "\nCalculation of the shortest path from '" << BEGIN << "' to 'Bucharest' with several search algorithms:\n" diff --git a/single_include/graph.hpp b/single_include/graph.hpp index 76b7e9c..4be568a 100644 --- a/single_include/graph.hpp +++ b/single_include/graph.hpp @@ -4,7 +4,7 @@ * ╚═╝╩╚═╩ ╩╩ ╩ ╩ https://github.com/Terae/Structure * * - * Single header-file generated by terae on 2018-01-24 + * Single header-file generated by terae on 2018-01-25 * * * Licensed under the MIT License . @@ -818,7 +818,10 @@ namespace search { using state = typename graph::const_iterator; + explicit abstract_targeted_search(const graph &, Key target); explicit abstract_targeted_search(const graph &, state target); + + explicit abstract_targeted_search(const graph &, const std::list &list_target); explicit abstract_targeted_search(const graph &, const std::list &list_target); protected: @@ -832,6 +835,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -854,6 +858,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin, int depth) const; path run(state begin, int depth) const; }; @@ -867,6 +872,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -880,6 +886,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -893,6 +900,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin, std::function heuristic) const; path run(state begin, std::function heuristic) const; }; @@ -906,6 +914,7 @@ namespace search { using state = typename abstract_search::state; + std::map> run(Key begin) const; // TODO std::map> run(state begin) const; }; @@ -2139,15 +2148,32 @@ bool search::path_comparator::operator() (const path search::abstract_search::abstract_search(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} +template +search::abstract_targeted_search::abstract_targeted_search(const graph &g, Key target) : abstract_targeted_search(g, g.find(target)) {} + template search::abstract_targeted_search::abstract_targeted_search(const graph &g, state target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { this->_targets.emplace_back(target); } +template +search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_targeted_search(g, [ & ]() -> std::list { + std::list l; + for (Key k : list_target) { + l.emplace_back(g.find(k)); + } + return l; +}()) {} + template search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), _targets(list_target) {} +template +search::path::state, Cost> search::abstract_first_search::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::abstract_first_search::run(state begin) const { std::list expanded; @@ -2200,6 +2226,11 @@ constexpr typename search::dfs search::make_dfs(const graph(g, std::forward(args)...); } +template +search::path::state, Cost> search::dls::run(Key begin, int depth) const { + return run(this->g.find(begin), depth); +} + template search::path::state, Cost> search::dls::run(state begin, int depth) const { std::list expanded; @@ -2266,9 +2297,14 @@ constexpr typename search::dls search::make_dls(const graph(g, std::forward(args)...); } +template +search::path::state, Cost> search::iddfs::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::iddfs::run(state begin) const { - search::dls dls{make_DLS(this->g, this->_targets)}; + search::dls dls{make_dls(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { path found{dls.run(begin, i)}; @@ -2284,6 +2320,11 @@ constexpr typename search::iddfs search::make_iddfs(const gra return iddfs(g, std::forward(args)...); } +template +search::path::state, Cost> search::ucs::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::ucs::run(state begin) const { std::list expanded; @@ -2327,6 +2368,11 @@ constexpr typename search::ucs search::make_ucs(const graph(g, std::forward(args)...); } +template +search::path::state, Cost> search::astar::run(Key begin, std::function heuristic) const { + return run(this->g.find(begin), heuristic); +} + template search::path::state, Cost> search::astar::run(state begin, std::function heuristic) const { std::list expanded; @@ -2370,6 +2416,11 @@ constexpr typename search::astar search::make_astar(const gra return astar(g, std::forward(args)...); } +template +std::map::state, search::path::state, Cost>> search::dijkstra::run(Key begin) const { + return run(this->g.find(begin)); +} + template std::map::state, search::path::state, Cost>> search::dijkstra::run(state begin) const { diff --git a/src/GraphSearch.cpp b/src/GraphSearch.cpp index 775ffdc..6ba61ea 100644 --- a/src/GraphSearch.cpp +++ b/src/GraphSearch.cpp @@ -87,11 +87,23 @@ bool search::path_comparator::operator() (const path search::abstract_search::abstract_search(const graph &g_, std::function is_goal) : g(g_), _is_goal(is_goal) {} +template +search::abstract_targeted_search::abstract_targeted_search(const graph &g, Key target) : abstract_targeted_search(g, g.find(target)) {} + template search::abstract_targeted_search::abstract_targeted_search(const graph &g, state target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }) { this->_targets.emplace_back(target); } +template +search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_targeted_search(g, [ & ]() -> std::list { + std::list l; + for (Key k : list_target) { + l.emplace_back(g.find(k)); + } + return l; +}()) {} + template search::abstract_targeted_search::abstract_targeted_search(const graph &g, const std::list &list_target) : abstract_search(g, [this](state node) -> bool { return std::find(_targets.cbegin(), _targets.cend(), node) != _targets.cend(); }), _targets(list_target) {} @@ -100,6 +112,11 @@ search::abstract_targeted_search::abstract_targeted_search(co ///// IMPLEMENTATION OF FIRST SEARCH ALGORITHMS ///// ///////////////////////////////////////////////////// +template +search::path::state, Cost> search::abstract_first_search::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::abstract_first_search::run(state begin) const { std::list expanded; @@ -158,6 +175,11 @@ constexpr typename search::dfs search::make_dfs(const graph +search::path::state, Cost> search::dls::run(Key begin, int depth) const { + return run(this->g.find(begin), depth); +} + template search::path::state, Cost> search::dls::run(state begin, int depth) const { std::list expanded; @@ -226,9 +248,14 @@ constexpr typename search::dls search::make_dls(const graph(g, std::forward(args)...); } +template +search::path::state, Cost> search::iddfs::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::iddfs::run(state begin) const { - search::dls dls{make_DLS(this->g, this->_targets)}; + search::dls dls{make_dls(this->g, this->_targets)}; for (int i{0}; i < std::numeric_limits::max(); ++i) { path found{dls.run(begin, i)}; @@ -248,6 +275,11 @@ constexpr typename search::iddfs search::make_iddfs(const gra ///// IMPLEMENTATION OF UNIFORM-COST ALGORITHM ///// //////////////////////////////////////////////////// +template +search::path::state, Cost> search::ucs::run(Key begin) const { + return run(this->g.find(begin)); +} + template search::path::state, Cost> search::ucs::run(state begin) const { std::list expanded; @@ -297,6 +329,11 @@ constexpr typename search::ucs search::make_ucs(const graph +search::path::state, Cost> search::astar::run(Key begin, std::function heuristic) const { + return run(this->g.find(begin), heuristic); +} + template search::path::state, Cost> search::astar::run(state begin, std::function heuristic) const { std::list expanded; @@ -346,6 +383,11 @@ constexpr typename search::astar search::make_astar(const gra ///// IMPLEMENTATION OF THE Dijkstra SEARCH ///// ///////////////////////////////////////////////// +template +std::map::state, search::path::state, Cost>> search::dijkstra::run(Key begin) const { + return run(this->g.find(begin)); +} + template std::map::state, search::path::state, Cost>> search::dijkstra::run(state begin) const { diff --git a/src/GraphSearch.h b/src/GraphSearch.h index 1e8fb65..4126222 100644 --- a/src/GraphSearch.h +++ b/src/GraphSearch.h @@ -107,7 +107,10 @@ namespace search { using state = typename graph::const_iterator; + explicit abstract_targeted_search(const graph &, Key target); explicit abstract_targeted_search(const graph &, state target); + + explicit abstract_targeted_search(const graph &, const std::list &list_target); explicit abstract_targeted_search(const graph &, const std::list &list_target); protected: @@ -138,6 +141,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -210,6 +214,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin, int depth) const; path run(state begin, int depth) const; }; @@ -239,6 +244,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -268,6 +274,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin) const; path run(state begin) const; }; @@ -297,6 +304,7 @@ namespace search { using state = typename abstract_targeted_search::state; + path run(Key begin, std::function heuristic) const; path run(state begin, std::function heuristic) const; }; @@ -326,6 +334,7 @@ namespace search { using state = typename abstract_search::state; + std::map> run(Key begin) const; // TODO std::map> run(state begin) const; }; diff --git a/test/src/unit-search.cpp b/test/src/unit-search.cpp index 5f8c4b6..6d6b8cf 100644 --- a/test/src/unit-search.cpp +++ b/test/src/unit-search.cpp @@ -24,8 +24,8 @@ TEST_CASE("search") { g("node 3", "node 2") = 32; g("node 2", "node 4") = 24; - Graph::const_iterator target{g.find("node 4")}; - search::astar a(g, target); + std::list targets = {"node 4"}; + search::astar a(g, targets); search::path p{a.run(g.find("node 1"), [&g](const Graph::const_iterator & it) -> double { return std::abs(it->second->get() - g["node 4"]); }) From f0ee96dee51953d05cbb932aa30a20ce066fba0d Mon Sep 17 00:00:00 2001 From: Benjamin Bigey Date: Thu, 25 Jan 2018 15:44:32 +0100 Subject: [PATCH 4/4] Update to version 1.1.1 --- CHANGELOG.md | 10 ++++++++-- CMakeLists.txt | 2 +- doc/Doxyfile | 2 +- scripts/pretty_code.sh | 2 +- single_include/graph.hpp | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c50b38..21ab758 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log -## [v1.0.1](https://github.com/terae/graph/releases/tag/v1.0.1) (2018-01-06) +## [v1.1.1](https://github.com/terae/graph/releases/tag/v1.1.0) (2018-01-25) +[Full Changelog](https://github.com/terae/compare/v1.1.0...v1.1.1) +## [v1.1.0](https://github.com/terae/graph/releases/tag/v1.1.0) (2018-01-17) +[Full Changelog](https://github.com/terae/graph/compare/v1.0.1...v1.1.0) -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file +## [v1.0.1](https://github.com/terae/graph/releases/tag/v1.1.1) (2018-01-06) + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ec39db..03dbecf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(LIBRARY_CMAKE_PROJECT_CONFIG_FILE "${LIBRARY_CMAKE_CONFIG_DIR}/${LIBRARY_NAM ## ## PROJECT ## -project(${LIBRARY_NAME} LANGUAGES CXX VERSION 1.0.1) +project(${LIBRARY_NAME} LANGUAGES CXX VERSION 1.1.1) ## ## OPTIONS diff --git a/doc/Doxyfile b/doc/Doxyfile index df93763..1a212a7 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "A STL-like graph library" -PROJECT_NUMBER = 1.0.1 +PROJECT_NUMBER = 1.1.1 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/scripts/pretty_code.sh b/scripts/pretty_code.sh index 17111a7..6631f77 100644 --- a/scripts/pretty_code.sh +++ b/scripts/pretty_code.sh @@ -25,7 +25,7 @@ FILE="$LOCATION/graph.hpp" cat > "$FILE" << EOF /* * ╔═╗╦═╗╔═╗╔═╗╦ ╦ C++ Graph library - * ║ ╦╠╦╝╠═╣╠═╝╠═╣ Version 1.0.1 + * ║ ╦╠╦╝╠═╣╠═╝╠═╣ Version 1.1.1 * ╚═╝╩╚═╩ ╩╩ ╩ ╩ https://github.com/Terae/Structure * * diff --git a/single_include/graph.hpp b/single_include/graph.hpp index 4be568a..0f7dfd6 100644 --- a/single_include/graph.hpp +++ b/single_include/graph.hpp @@ -1,6 +1,6 @@ /* * ╔═╗╦═╗╔═╗╔═╗╦ ╦ C++ Graph library - * ║ ╦╠╦╝╠═╣╠═╝╠═╣ Version 1.0.1 + * ║ ╦╠╦╝╠═╣╠═╝╠═╣ Version 1.1.1 * ╚═╝╩╚═╩ ╩╩ ╩ ╩ https://github.com/Terae/Structure * *