diff --git a/alib2graph_algo/src/traverse/IDDFS.cpp b/alib2graph_algo/src/traverse/IDDFS.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d827cc485f0485f95936237adf4842608104c759
--- /dev/null
+++ b/alib2graph_algo/src/traverse/IDDFS.cpp
@@ -0,0 +1,228 @@
+// IDDFS.cpp
+//
+//     Created on: 27. 02. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#include "IDDFS.hpp"
+
+#include <registration/AlgoRegistration.hpp>
+#include <graph/GraphClasses.hpp>
+#include <grid/GridClasses.hpp>
+
+namespace traverse {
+class IDDFSBidirectional {};
+}
+
+namespace {
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Normal Graph uni-directional
+
+auto IDDFS1 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::UndirectedGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFS2 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::UndirectedMultiGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFS3 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::DirectedGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFS4 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::DirectedMultiGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFS5 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::MixedGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFS6 = registration::AbstractRegister<traverse::IDDFS,
+                                             ext::vector<DefaultNodeType>,
+                                             const graph::MixedMultiGraph<> &,
+                                             const DefaultNodeType &,
+                                             const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFSGrid1 = registration::AbstractRegister<traverse::IDDFS,
+                                                 ext::vector<DefaultSquareGridNodeType>,
+                                                 const grid::SquareGrid4<> &,
+                                                 const DefaultSquareGridNodeType &,
+                                                 const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto IDDFSGrid2 = registration::AbstractRegister<traverse::IDDFS,
+                                                 ext::vector<DefaultSquareGridNodeType>,
+                                                 const grid::SquareGrid8<> &,
+                                                 const DefaultSquareGridNodeType &,
+                                                 const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathRegistration);
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Normal Graph bidirectional
+
+auto IDDFSBidirectional1 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::UndirectedGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSBidirectional2 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::UndirectedMultiGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSBidirectional3 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::DirectedGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSBidirectional4 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::DirectedMultiGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSBidirectional5 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::MixedGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSBidirectional6 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                          ext::vector<DefaultNodeType>,
+                                                          const graph::MixedMultiGraph<> &,
+                                                          const DefaultNodeType &,
+                                                          const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSGridBidirectional1 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                              ext::vector<DefaultSquareGridNodeType>,
+                                                              const grid::SquareGrid4<> &,
+                                                              const DefaultSquareGridNodeType &,
+                                                              const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto IDDFSGridbidirectional2 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                              ext::vector<DefaultSquareGridNodeType>,
+                                                              const grid::SquareGrid8<> &,
+                                                              const DefaultSquareGridNodeType &,
+                                                              const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Weighted Graph uni-directional
+
+auto WIDDFS1 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedUndirectedGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFS2 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedUndirectedMultiGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFS3 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedDirectedGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFS4 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedDirectedMultiGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFS5 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedMixedGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFS6 = registration::AbstractRegister<traverse::IDDFS,
+                                              ext::vector<DefaultNodeType>,
+                                              const graph::WeightedMixedMultiGraph<> &,
+                                              const DefaultNodeType &,
+                                              const DefaultNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFSGrid1 = registration::AbstractRegister<traverse::IDDFS,
+                                                  ext::vector<DefaultSquareGridNodeType>,
+                                                  const grid::WeightedSquareGrid4<> &,
+                                                  const DefaultSquareGridNodeType &,
+                                                  const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathRegistration);
+
+auto WIDDFSGrid2 = registration::AbstractRegister<traverse::IDDFS,
+                                                  ext::vector<DefaultSquareGridNodeType>,
+                                                  const grid::WeightedSquareGrid8<> &,
+                                                  const DefaultSquareGridNodeType &,
+                                                  const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathRegistration);
+
+// ---------------------------------------------------------------------------------------------------------------------
+// Weighted Graph bidirectional
+
+auto WIDDFSBidirectional1 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedUndirectedGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSBidirectional2 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedUndirectedMultiGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSBidirectional3 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedDirectedGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSBidirectional4 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedDirectedMultiGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSBidirectional5 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedMixedGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSBidirectional6 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                           ext::vector<DefaultNodeType>,
+                                                           const graph::WeightedMixedMultiGraph<> &,
+                                                           const DefaultNodeType &,
+                                                           const DefaultNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSGridBidirectional1 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                               ext::vector<DefaultSquareGridNodeType>,
+                                                               const grid::WeightedSquareGrid4<> &,
+                                                               const DefaultSquareGridNodeType &,
+                                                               const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+auto WIDDFSGridbidirectional2 = registration::AbstractRegister<traverse::IDDFSBidirectional,
+                                                               ext::vector<DefaultSquareGridNodeType>,
+                                                               const grid::WeightedSquareGrid8<> &,
+                                                               const DefaultSquareGridNodeType &,
+                                                               const DefaultSquareGridNodeType &>(traverse::IDDFS::findPathBidirectionalRegistration);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+}
diff --git a/alib2graph_algo/src/traverse/IDDFS.hpp b/alib2graph_algo/src/traverse/IDDFS.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..36b32e8653f48180f6964bdf936da10997ff8c19
--- /dev/null
+++ b/alib2graph_algo/src/traverse/IDDFS.hpp
@@ -0,0 +1,456 @@
+// IDIDDFS.hpp
+//
+//     Created on: 27. 02. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#ifndef ALIB2_IDIDDFS_HPP
+#define ALIB2_IDIDDFS_HPP
+
+#include <functional>
+#include <alib/vector>
+#include <queue>
+#include <limits>
+#include <alib/set>
+#include <alib/map>
+
+#include <common/ReconstructPath.hpp>
+
+namespace traverse {
+
+class IDDFS {
+// ---------------------------------------------------------------------------------------------------------------------
+
+ public:
+
+  /// Run IDDFS algorithm from the \p start node in the \p graph.
+  /// Be aware that running this algorithm on a non-tree graph gonna be extremely slow.
+  ///
+  /// Whenever node is opened, \p f_user is called with two parameters (the opened node and distance to this node).
+  /// If return of \p f_user is true, then the algorithm is stopped.
+  ///
+  /// \param graph to explore.
+  /// \param start initial node.
+  /// \param max_depth set maximal allowed depth for IDDFS.
+  /// \param f_user function which is called for every opened node with value of currently shortest path.
+  ///
+  template<
+      typename TGraph,
+      typename TNode,
+      typename F = std::function<bool(const TNode &, const size_t &)>>
+  static
+  void
+  run(const TGraph &graph,
+      const TNode &start,
+      unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
+      F f_user = [](const TNode &, const size_t &) -> bool { return false; });
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  /// Find the shortest path using IDDFS algorithm from the \p start node to the \p goal node in the \p graph.
+  /// Be aware that running this algorithm on a non-tree graph gonna be extremely slow.
+  ///
+  /// Whenever node is opened, \p f_user is called with two parameters (the opened node and distance to this node).
+  ///
+  /// \param graph to explore.
+  /// \param start initial node.
+  /// \param goal final node.
+  /// \param max_depth set maximal allowed depth for IDDFS.
+  /// \param f_user function which is called for every opened node with value of currently shortest path.
+  ///
+  /// \returns nodes in shortest path, if there is no such path vector is empty.
+  ///
+  template<
+      typename TGraph,
+      typename TNode,
+      typename F = std::function<void(const TNode &, const size_t &)>>
+  static
+  ext::vector<TNode>
+  findPath(const TGraph &graph,
+           const TNode &start,
+           const TNode &goal,
+           unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
+           F f_user = [](const TNode &, const size_t &) {});
+
+  template<typename TGraph, typename TNode>
+  static
+  ext::vector<TNode>
+  findPathRegistration(const TGraph &graph,
+                       const TNode &start,
+                       const TNode &goal) {
+    return findPath(graph, start, goal);
+
+  }
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  /// Find the shortest path using IDDFS algorithm from the \p start node to the \p goal node in the \p graph.
+  /// This algorithm is run in both direction, from \p start and also from \p goal.
+  /// Be aware that running this algorithm on a non-tree graph gonna be extremely slow.
+  ///
+  /// Whenever node is opened, \p f_user is called with two parameters (the opened node and distance to this node).
+  ///
+  /// \param graph to explore.
+  /// \param start initial node.
+  /// \param goal final node.
+  /// \param max_depth set maximal allowed depth for IDDFS.
+  /// \param f_user function which is called for every opened node with value of currently shortest path.
+  ///
+  /// \returns nodes in shortest path, if there is no such path vector is empty.
+  ///
+  template<
+      typename TGraph,
+      typename TNode,
+      typename F = std::function<void(const TNode &, const size_t &)>>
+  static
+  ext::vector<TNode>
+  findPathBidirectional(const TGraph &graph,
+                        const TNode &start,
+                        const TNode &goal,
+                        unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
+                        F f_user = [](const TNode &, const size_t &) {});
+
+  template<typename TGraph, typename TNode>
+  static
+  ext::vector<TNode>
+  findPathBidirectionalRegistration(const TGraph &graph,
+                                    const TNode &start,
+                                    const TNode &goal) {
+    return findPath(graph, start, goal);
+
+  }
+
+// =====================================================================================================================
+
+ private:
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename TNode>
+  struct Data {
+    ext::vector<TNode> path; // current path
+    ext::set<TNode> path_set; // current path set for quick search
+    ext::set<TNode> v; // visited
+  };
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename TGraph, typename TNode, typename F1, typename F2>
+  static
+  ext::vector<TNode>
+  implNormal(const TGraph &graph,
+             const TNode &start,
+             unsigned long max_depth,
+             F1 f_user,
+             F2 f_stop);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename FSucc, typename TNode, typename F1, typename F2>
+  static
+  bool
+  expansion(FSucc successors,
+            IDDFS::Data<TNode> &data,
+            const TNode &n,
+            bool save_nodes,
+            unsigned long max_depth,
+            F1 f_user,
+            F2 f_stop);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename TGraph, typename TNode, typename F1, typename F2>
+  static
+  ext::vector<TNode>
+  implBidirectional(const TGraph &graph,
+                    const TNode &start,
+                    const TNode &goal,
+                    unsigned long max_depth,
+                    F1 f_user,
+                    F2 f_stop);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename FSucc, typename TNode, typename F1, typename F2>
+  static
+  ext::set<TNode>
+  backward_expansion(FSucc successors,
+                     const IDDFS::Data<TNode> &forward_data,
+                     IDDFS::Data<TNode> &backward_data,
+                     const TNode &node,
+                     unsigned long max_depth,
+                     F1 f_user,
+                     F2 f_stop);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename TGraph, typename TNode>
+  static
+  ext::vector<TNode>
+  constructPath(const TGraph &graph,
+                const TNode &start,
+                const TNode &goal,
+                TNode intersection,
+                unsigned long max_forward_depth,
+                unsigned long max_backward_depth);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  template<typename TNode>
+  inline static void init(IDDFS::Data<TNode> &data, const TNode &start);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+};
+
+// =====================================================================================================================
+
+template<typename TGraph, typename TNode, typename F>
+void IDDFS::run(const TGraph &graph, const TNode &start, unsigned long max_depth, F f_user) {
+  implNormal(graph, start, max_depth, f_user, [](const TNode &) -> bool { return false; });
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TGraph, typename TNode, typename F>
+ext::vector<TNode> IDDFS::findPath(const TGraph &graph,
+                                   const TNode &start,
+                                   const TNode &goal,
+                                   unsigned long max_depth,
+                                   F f_user) {
+  return implNormal(graph, start, max_depth,
+                    [&](const TNode &n, const auto &d) -> bool {
+                      f_user(n, d);
+                      return false;
+                    },
+                    [&goal](const TNode &n) -> bool { return goal == n; });
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TGraph, typename TNode, typename F>
+ext::vector<TNode> IDDFS::findPathBidirectional(const TGraph &graph,
+                                                const TNode &start,
+                                                const TNode &goal,
+                                                unsigned long max_depth,
+                                                F f_user) {
+  return implBidirectional(graph, start, goal, max_depth,
+                           [&](const TNode &n, const auto &d) -> bool {
+                             f_user(n, d);
+                             return false;
+                           },
+                           [](const TNode &) -> bool { return false; });
+}
+
+// =====================================================================================================================
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TGraph, typename TNode, typename F1, typename F2>
+ext::vector<TNode> IDDFS::implNormal(const TGraph &graph,
+                                     const TNode &start,
+                                     unsigned long max_depth,
+                                     F1 f_user,
+                                     F2 f_stop) {
+  for (unsigned long i = 1; i < max_depth; ++i) {
+    Data<TNode> data;
+
+    // Init search
+    init(data, start);
+
+    bool stop =
+        expansion([&](const TNode &node) { return graph.successors(node); }, data, start, false, i, f_user, f_stop);
+
+    if (stop) {
+      return data.path;
+    }
+  }
+
+  return ext::vector<TNode>();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename FSucc, typename TNode, typename F1, typename F2>
+bool IDDFS::expansion(FSucc successors,
+                      IDDFS::Data<TNode> &data,
+                      const TNode &n,
+                      bool save_nodes,
+                      unsigned long max_depth,
+                      F1 f_user,
+                      F2 f_stop) {
+  if (max_depth == 0) return false; // Continue with search
+  else if (save_nodes && max_depth == 1) {
+    data.v.insert(n); // Remember only the deepest nodes
+  }
+
+  // Run user's function
+  if (f_user(n, data.path.size())) {
+    return true; // Stop algorithm
+  }
+
+  // Stop if reach the goal
+  if (f_stop(n)) {
+    return true; // Stop algorithm
+  }
+
+  for (const auto &s : successors(n)) {
+
+    // Check if node is not in path
+    if (data.path_set.find(s) != data.path_set.end()) {
+      continue;
+    }
+
+    data.path.push_back(s); // Insert current node
+    data.path_set.insert(s);
+    bool stop = expansion(successors, data, s, save_nodes, max_depth - 1, f_user, f_stop);
+
+    if (stop) {
+      return true; // Stop algorithm
+    }
+
+    data.path.pop_back(); // Remove current node
+    data.path_set.erase(data.path_set.find(s));
+  }
+
+  return false; // Continue with search
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TGraph, typename TNode, typename F1, typename F2>
+ext::vector<TNode> IDDFS::implBidirectional(const TGraph &graph,
+                                            const TNode &start,
+                                            const TNode &goal,
+                                            unsigned long max_depth,
+                                            F1 f_user,
+                                            F2 f_stop) {
+  for (unsigned long i = 1; i < max_depth; ++i) {
+    // -------------------------------
+    // Forward search
+    Data<TNode> forward_data;
+
+    // Init forward search
+    init(forward_data, start);
+
+    expansion([&](const TNode &n) { return graph.successors(n); }, forward_data, start, true, i, f_user, f_stop);
+
+    // -------------------------------
+    // Backward search
+
+    ext::set<TNode> intersection;
+
+    Data<TNode> backward_data;
+
+    // Init backward search
+    init(backward_data, goal);
+
+    intersection = backward_expansion([&](const TNode &node) { return graph.predecessors(node); },
+                                      forward_data,
+                                      backward_data,
+                                      goal,
+                                      i,
+                                      f_user,
+                                      f_stop); // even run
+
+    // If there is a intersection, then we can construct path
+    if (intersection.size() != 0) {
+      return constructPath(graph, start, goal, *intersection.begin(), i, i);
+    }
+
+    // Init backward search
+    init(backward_data, goal);
+
+    intersection = backward_expansion([&](const TNode &node) { return graph.predecessors(node); },
+                                      forward_data,
+                                      backward_data,
+                                      goal,
+                                      i + 1,
+                                      f_user,
+                                      f_stop); // odd run
+
+    // If there is a intersection, then we can reconstruct path
+    if (intersection.size() != 0) {
+      return constructPath(graph, start, goal, *intersection.begin(), i, i + 1);
+    }
+  }
+
+  return ext::vector<TNode>();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename FSucc, typename TNode, typename F1, typename F2>
+ext::set<TNode> IDDFS::backward_expansion(FSucc successors,
+                                          const IDDFS::Data<TNode> &forward_data,
+                                          IDDFS::Data<TNode> &backward_data,
+                                          const TNode &node,
+                                          unsigned long max_depth,
+                                          F1 f_user,
+                                          F2 f_stop) {
+  expansion(successors, backward_data, node, true, max_depth, f_user, f_stop);
+
+  // Check for intersection
+  ext::set<TNode> intersection;
+  std::set_intersection(forward_data.v.begin(), forward_data.v.end(),
+                        backward_data.v.begin(), backward_data.v.end(),
+                        std::inserter(intersection, intersection.begin()));
+
+  return intersection;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TGraph, typename TNode>
+ext::vector<TNode> IDDFS::constructPath(const TGraph &graph,
+                                        const TNode &start,
+                                        const TNode &goal,
+                                        TNode intersection,
+                                        unsigned long max_forward_depth,
+                                        unsigned long max_backward_depth) {
+  Data<TNode> forward_data, backward_data;
+  init(forward_data, start);
+  init(backward_data, goal);
+
+  // Re-run forward search
+  expansion([&](const TNode &node) { return graph.successors(node); },
+            forward_data,
+            start,
+            false,
+            max_forward_depth,
+            [](const TNode &, const size_t &) -> bool { return false; },
+            [&](const TNode &n) -> bool { return n == intersection; }
+  );
+
+  // Re-run backward search
+  expansion([&](const TNode &node) { return graph.predecessors(node); },
+            backward_data,
+            goal,
+            false,
+            max_backward_depth,
+            [](const TNode &, const size_t &) -> bool { return false; },
+            [&](const TNode &n) -> bool { return n == intersection; }
+  );
+
+  return common::ReconstructPath::joinPath(forward_data.path, backward_data.path);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode>
+void IDDFS::init(IDDFS::Data<TNode> &data, const TNode &start) {
+  // Make sure that data are wiped
+  data.path.clear();
+  data.v.clear();
+
+  data.path.push_back(start);
+  data.path_set.insert(start);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+} // namespace traverse
+#endif //ALIB2_IDIDDFS_HPP