Advertisement
DNKpp

Untitled

Sep 12th, 2018
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.89 KB | None | 0 0
  1. #include <vector>
  2. #include <thread>
  3. #include <cassert>
  4. #include <functional>
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <optional>
  8. #include <future>
  9. #include <chrono>
  10. #include <fstream>
  11.  
  12. namespace graph
  13. {
  14.     template <class TVertexDescriptor, class TNode, class TNodeCompare = std::less<TNode>, class TKeyHash = std::hash<TVertexDescriptor>, class TKeyEqual = std::equal_to<TVertexDescriptor>>
  15.     class NodeMap
  16.     {
  17.     public:
  18.         explicit NodeMap(TNodeCompare _nodeCompare = TNodeCompare(), TKeyHash _hash = TKeyHash(), TKeyEqual _equal = TKeyEqual()) :
  19.             m_Nodes(10, std::move(_hash), std::move(_equal)),   // ToDo: not sure if that bucket_count parameter fits well; possible other solution available?
  20.             m_NodeCompare(std::move(_nodeCompare))
  21.         {
  22.         }
  23.         void insert(TVertexDescriptor _key, TNode _node)
  24.         {
  25.             if (auto result = m_Nodes.insert({ _key, _node });
  26.                 !result.second && m_NodeCompare(_node, result.first->second))
  27.             {
  28.                 result.first->second = _node;
  29.             }
  30.         }
  31.  
  32.         auto take_less()
  33.         {
  34.             auto itr = std::min_element(std::begin(m_Nodes), std::end(m_Nodes),
  35.                 [&comp = m_NodeCompare](const auto& _lhs, const auto& _rhs) { return comp(_lhs.second, _rhs.second); }
  36.             );
  37.             assert(itr != std::end(m_Nodes));
  38.             auto node = std::move(*itr);
  39.             m_Nodes.erase(itr);
  40.             return node;
  41.         }
  42.  
  43.         const TNode* find(const TVertexDescriptor& _key) const
  44.         {
  45.             auto itr = m_Nodes.find(_key);
  46.             return std::end(m_Nodes) == itr ? nullptr : &itr->second;
  47.         }
  48.  
  49.         bool contains(const TVertexDescriptor& _key) const
  50.         {
  51.             return m_Nodes.count(_key) == 1;    // ToDo: use std::unordered_map::contains in C++20
  52.         }
  53.  
  54.         bool empty() const
  55.         {
  56.             return std::empty(m_Nodes);
  57.         }
  58.  
  59.     private:
  60.         std::unordered_map<TVertexDescriptor, TNode, TKeyHash, TKeyEqual> m_Nodes;
  61.         TNodeCompare m_NodeCompare;
  62.     };
  63.  
  64.     template <class TVertexDescriptor, class TNeighbourFinder>
  65.     class BreadthFirstSearch
  66.     {
  67.     public:
  68.         template <class TTNeighbourFinder>
  69.         explicit BreadthFirstSearch(TVertexDescriptor _start, TTNeighbourFinder&& _neighbourFinder) :
  70.             m_NeighbourFinder(std::forward<TTNeighbourFinder>(_neighbourFinder))
  71.         {
  72.             m_OpenList.insert(std::move(_start), Node());
  73.         }
  74.  
  75.         std::optional<TVertexDescriptor> next()
  76.         {
  77.             if (std::empty(m_OpenList))
  78.                 return std::nullopt;
  79.             auto node = m_OpenList.take_less();
  80.             m_ClosedList.insert(node.first, node.second);
  81.             m_NeighbourFinder(node.first,
  82.                 [&openList = m_OpenList, &closedList = m_ClosedList, node = Node{ node.first, node.second.cost + 1 }](const auto& _vertex)
  83.                 {
  84.                     if (!closedList.contains(_vertex))
  85.                     {
  86.                         openList.insert(_vertex, node);
  87.                     }
  88.                 }
  89.             );
  90.             return node.first;
  91.         }
  92.  
  93.         std::optional<std::vector<TVertexDescriptor>> extract_path(const TVertexDescriptor& _vertex) const
  94.         {
  95.             if (auto curNode = m_ClosedList.find(_vertex))
  96.             {
  97.                 std::vector<TVertexDescriptor> path{ _vertex };
  98.                 while (curNode && curNode->parent)
  99.                 {
  100.                     path.emplace_back(*curNode->parent);
  101.                     curNode = m_ClosedList.find(*curNode->parent);
  102.                 }
  103.                 std::reverse(std::begin(path), std::end(path));
  104.                 return path;
  105.             }
  106.             return std::nullopt;
  107.         }
  108.  
  109.     private:
  110.         struct Node
  111.         {
  112.             std::optional<TVertexDescriptor> parent;
  113.             int cost = 0;
  114.  
  115.             friend bool operator <(const Node& _lhs, const Node& _rhs)
  116.             {
  117.                 return _lhs.cost < _rhs.cost;
  118.             }
  119.         };
  120.  
  121.         NodeMap<TVertexDescriptor, Node> m_OpenList;
  122.         NodeMap<TVertexDescriptor, Node> m_ClosedList;
  123.         TNeighbourFinder m_NeighbourFinder;
  124.     };
  125.  
  126.     template <class TVertexDescriptor, class TNeighbourFinder>
  127.     auto make_BreadthFirstSearch(TVertexDescriptor _start, TNeighbourFinder&& _neighbourFinder)
  128.     {
  129.         return BreadthFirstSearch<TVertexDescriptor, TNeighbourFinder>(std::move(_start), std::forward<TNeighbourFinder>(_neighbourFinder));
  130.     }
  131.  
  132.     template <class TVertexDescriptor, class TCallable, typename = std::enable_if_t<std::is_invocable_r_v<bool, TCallable, const TVertexDescriptor&>>>
  133.     bool _reached_destination(const TVertexDescriptor& _current, TCallable&& _func)
  134.     {
  135.         return _func(_current);
  136.     }
  137.  
  138.     template <class TVertexDescriptor>
  139.     bool _reached_destination(const TVertexDescriptor& _current, const TVertexDescriptor& _destination)
  140.     {
  141.         return _current == _destination;
  142.     }
  143.  
  144.     template <class TGoal, class TPathFinder>
  145.     auto find_path(TGoal&& _destination, TPathFinder&& _pathFinder) -> std::optional<std::vector<int>>
  146.     {
  147.         while (auto current = _pathFinder.next())
  148.         {
  149.             if (_reached_destination(*current, _destination))
  150.             {
  151.                 return _pathFinder.extract_path(*current);
  152.             }
  153.         }
  154.         return std::nullopt;
  155.     }
  156. } // namespace graph
  157.  
  158. template <class TDestination, class TNeighbourFinder>
  159. void search_path_and_print(int _from, TDestination&& _to, TNeighbourFinder&& _neighbourFinder)
  160. {
  161.     for (auto node : graph::find_path(std::forward<TDestination>(_to), graph::make_BreadthFirstSearch(_from, std::forward<TNeighbourFinder>(_neighbourFinder))).value_or(std::vector<int>()))
  162.     {
  163.         std::cout << node << std::endl;
  164.     }
  165. }
  166.  
  167. int main()
  168. {
  169.     std::vector<int> nodes{ 1, 2, 3, 4, 5, 6, 7 };
  170.     std::vector<std::pair<int, int>> connections
  171.     {
  172.         { 1, 2 },
  173.         { 2, 3 },
  174.         { 2, 4 },
  175.         { 4, 5 },
  176.         { 3, 6 },
  177.         { 3, 7 },
  178.         { 6, 7 },
  179.         { 7, 1 }
  180.     };
  181.  
  182.     auto neighbourFinder = [&connections](const auto& _vertex, auto&& _callback)
  183.     {
  184.         auto next = [itr = std::begin(connections), end = std::end(connections)](const auto& _vertex) mutable->std::optional<int>
  185.         {
  186.             itr = std::find_if(itr, end, [&_vertex](const auto& _pair) { return _pair.first == _vertex || _pair.second == _vertex; });
  187.             if (itr != end)
  188.             {
  189.                 auto result = itr->first == _vertex ? itr->second : itr->first;
  190.                 ++itr;
  191.                 return result;
  192.             }
  193.             return std::nullopt;
  194.         };
  195.  
  196.         while (auto neigh = next(_vertex))
  197.             _callback(*neigh);
  198.     };
  199.  
  200.     search_path_and_print(1, 6, neighbourFinder);
  201.     search_path_and_print(1, [](const auto& _node) { return _node == 6; }, neighbourFinder);
  202.     std::cin.get();
  203. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement