From d6a885cce6ae53e29ae4c7c937952e9aadf0959d Mon Sep 17 00:00:00 2001
From: florijan <florijan@memgraph.io>
Date: Tue, 19 Sep 2017 09:54:52 +0200
Subject: [PATCH] Traversal API removed

Summary: Removed the traversal API, been waiting for named path to land because that data structure has replaced traversal's Path. I left the wiki page of the API, just put a warning that it's not used.

Reviewers: buda, teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D809
---
 src/query/typed_value.hpp   |   1 -
 src/traversal/enums.hpp     |  68 ----
 src/traversal/path.hpp      | 218 -----------
 src/traversal/templates.hpp | 727 ------------------------------------
 src/traversal/traversal.hpp |  60 ---
 tests/unit/traversal.cpp    | 691 ----------------------------------
 6 files changed, 1765 deletions(-)
 delete mode 100644 src/traversal/enums.hpp
 delete mode 100644 src/traversal/path.hpp
 delete mode 100644 src/traversal/templates.hpp
 delete mode 100644 src/traversal/traversal.hpp
 delete mode 100644 tests/unit/traversal.cpp

diff --git a/src/query/typed_value.hpp b/src/query/typed_value.hpp
index de38a2249..fae0f793a 100644
--- a/src/query/typed_value.hpp
+++ b/src/query/typed_value.hpp
@@ -12,7 +12,6 @@
 #include "storage/edge_accessor.hpp"
 #include "storage/property_value.hpp"
 #include "storage/vertex_accessor.hpp"
-#include "traversal/path.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/total_ordering.hpp"
 
diff --git a/src/traversal/enums.hpp b/src/traversal/enums.hpp
deleted file mode 100644
index e6ff48921..000000000
--- a/src/traversal/enums.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright 2017 Memgraph
-// Created by Florijan Stamenkovic on 23.02.17.
-//
-
-#pragma once
-
-namespace traversal_template {
-
-/**
- * Indicates the type of uniqueness used when matching data to a pattern.
- * "Uniqueness" means that a single Vertex or Edge in the result path
- * may not map to a single element in the pattern.
- *
- * This is equivalent to saying that a single Vertex or Edge may not occur
- * more then once in the resulting path.
- *
- * Often the "-morphism terminology is used, where Homomorphism means
- * there are not uniqueness constraints, "Cyphermorphism" (Neo4j's current
- * default) means Edge uniqueness, and Isomorphism means Vertex uniqueness
- * (which also implies Edge uniqueness).
- *
- * TODO: Look into the slides on uniqueness from OpenCypher implementor meeting,
- * it is mentioned that Vertex uniqueness can result in exponential performance
- * degradation. Figure out why and how.
- */
-enum class Uniqueness { None, Vertex, Edge };
-
-/**
- * Indicates how a path should be expanded using the traversal API. For the
- * given path (we ignore relationship directionality in the example because it
- * does not affect it):
- *
- *      p = (node_N)-[]-(node_N+1)-...-(node_M)
- *
- * the Expansion::Front enum means that the path is expanded from (node_N)
- * backwards, so the resulting path would be:
- *
- *      q = (node_N-1)-[]-(node_N)-[]-(node_N+1)-...-(node_M)
- *
- * The Expansion::Back enum has the opposite meaning, path p would get expanded
- * from node_M.
- *
- * Note that this implies that a Path has direction (start and finish).
- */
-enum class Expansion { Front, Back };
-
-/**
- * Indicates which relationships from the expansion vertex should be used to
- * expand
- * the path. Direction::In means that incoming relationships are used for
- * expansion.
- *
- * For example, for the given graph data:
- *
- *    (a)-[]->(b)<-[]-(c)
- *
- * And the given current path
- *
- *    p = (b)
- *
- * Expansion (let's assume Expansion::Back) in the Direction::In would result
- * in:
- *
- *    q = (b)<-[]-(a)
- */
-enum class Direction { In, Out, Both };
-}
diff --git a/src/traversal/path.hpp b/src/traversal/path.hpp
deleted file mode 100644
index 45966bc9d..000000000
--- a/src/traversal/path.hpp
+++ /dev/null
@@ -1,218 +0,0 @@
-//
-// Copyright 2017 Memgraph
-// Created by Florijan Stamenkovic on 23.02.17.
-//
-
-#pragma once
-
-#include <algorithm>
-#include <functional>
-#include <list>
-
-#include "enums.hpp"
-#include "utils/assert.hpp"
-
-/**
- * For a documentation of this namespace and it's
- * intended usage (namespace specialization) take
- * a look at the docs in "templates.hpp".
- */
-namespace traversal_template {
-
-/**
- * A path containing zero or more vertices. Between
- * each two vertices is an edge.
- *
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TVertex, typename TEdge>
-class Path {
- public:
-  Path() {}
-
-  size_t Size() const { return vertices_.size(); }
-
-  friend std::ostream &operator<<(std::ostream &stream, const Path &path) {
-    auto vertices_it = path.vertices_.begin();
-    auto vertices_end = path.vertices_.end();
-    auto edges_it = path.edges_.begin();
-
-    if (vertices_it != vertices_end) stream << *vertices_it++;
-
-    while (vertices_it != vertices_end)
-
-      // current vertex has incoming if it is
-      if (edges_it->to() == *vertices_it)
-        stream << "-" << *edges_it++ << "->" << *vertices_it++;
-      else
-        stream << "<-" << *edges_it++ << "-" << *vertices_it++;
-
-    return stream;
-  }
-
-  bool operator==(const Path &other) const {
-    return vertices_ == other.vertices_ && edges_ == other.edges_;
-  }
-
-  bool operator!=(const Path &other) const { return !(*this == other); }
-
-  /**
-   * Starts the path. At this moment the Path must be empty.
-   *
-   * @return A reference to this same path.
-   */
-  Path &Start(const TVertex &v) {
-    debug_assert(vertices_.size() == 0,
-                 "Can only start iteration on empty path");
-    vertices_.push_back(v);
-    return *this;
-  }
-
-  /**
-   * Checks if the given vertex is contained in this path.
-   */
-  bool Contains(const TVertex &vertex) const {
-    for (const auto &v : vertices_)
-      if (v == vertex) return true;
-
-    return false;
-  }
-
-  /**
-   * Checks if the given edge is contained in this path.
-   */
-  bool Contains(const TEdge &edge) const {
-    for (const auto &e : edges_)
-      if (e == edge) return true;
-
-    return false;
-  }
-
-  /**
-   * Gets the last Vertex of this path. Fails if the path contains no elements.
-   */
-  const TVertex &Back() const {
-    debug_assert(vertices_.size() > 0,
-                 "Can only get a Vertex on non-empty path");
-    return vertices_.back();
-  }
-
-  /**
-   * Appends a traversal to the end of this path.
-   *
-   * @param edge  The edge along with the traversal happens.
-   * @param vertex  The new vertex to append to the path.
-   * @param direction  The direction along which the traversal happens
-   *    (relative to the currently last vertex in path).
-   * @return A reference to this same path.
-   */
-  Path &Append(const TEdge &edge, const TVertex &vertex) {
-    edges_.emplace_back(edge);
-    vertices_.emplace_back(vertex);
-    return *this;
-  }
-
-  /**
-   * Removes the last element from the path. Fails if the path contains no
-   * elements.
-   */
-  void PopBack() {
-    debug_assert(vertices_.size() > 0,
-                 "Can only remove a vertex from a non-empty path");
-    vertices_.pop_back();
-
-    if (vertices_.size() > 0) edges_.pop_back();
-  }
-
-  /**
-   * Gets the first Vertex of this path. Fails if the path contains no elements.
-   */
-  const TVertex &Front() const {
-    debug_assert(vertices_.size() > 0,
-                 "Can only get a vertex from a non-empty path");
-    return vertices_.front();
-  }
-
-  /**
-   * Prepends a traversal to the beginning of this path.
-   *
-   * @param edge  The edge along with the traversal happens.
-   * @param vertex  The new vertex to prepend to the path.
-   * @return A reference to this same path.
-   */
-  Path &Prepend(const TEdge &edge, const TVertex &vertex) {
-    edges_.emplace_front(edge);
-    vertices_.emplace_front(vertex);
-    return *this;
-  }
-
-  /**
-   * Removes the first element from the path. Fails if the path contains no
-   * elements.
-   */
-  void PopFront() {
-    debug_assert(vertices_.size() > 0,
-                 "Can only remove a vertex from a non-empty path");
-    vertices_.pop_front();
-
-    if (vertices_.size() > 0) edges_.pop_front();
-  }
-
-  /**
-   * Removes all the elements from the path.
-   */
-  void Clear() {
-    edges_.clear();
-    vertices_.clear();
-  }
-
-  /**
-   * Returns all the vertices in this path.
-   */
-  const auto &Vertices() const { return vertices_; }
-
-  /**
-   * Returns all the edges in this path.
-   */
-  const auto &Edges() const { return edges_; }
-
- private:
-  std::list<TVertex> vertices_;
-  std::list<TEdge> edges_;
-};
-
-/**
- * An ordered sequence of Path reference wrappers. Used when
- * visiting cartesian products of traversals.
- */
-// TODO review: do we like std::list inheritance (and why)?
-// alternatively we could do:
-//    A. using Paths = std::list<std::reference_wrapper<Path>>;
-//    B. encapsulation
-template <typename TVertex, typename TEdge>
-class Paths : public std::list<std::reference_wrapper<Path<TVertex, TEdge>>> {
-  using Path = Path<TVertex, TEdge>;
-
- public:
-  bool operator==(const Paths<TVertex, TEdge> &other) const {
-    return std::equal(this->begin(), this->end(), other.begin(),
-                      [](const std::reference_wrapper<Path> &p1,
-                         const std::reference_wrapper<Path> &p2) {
-                        return p1.get() == p2.get();
-                      });
-  }
-
-  bool operator!=(const Paths &other) const { return !(*this == other); }
-
-  friend std::ostream &operator<<(std::ostream &stream, const Paths &paths) {
-    stream << "[";
-    auto it = paths.begin();
-    auto end = paths.end();
-
-    if (it != end) stream << *it++;
-    while (it != end) stream << ", " << *it++;
-    return stream << "]";
-  }
-};
-}
diff --git a/src/traversal/templates.hpp b/src/traversal/templates.hpp
deleted file mode 100644
index 697bd3f23..000000000
--- a/src/traversal/templates.hpp
+++ /dev/null
@@ -1,727 +0,0 @@
-//
-// Copyright 2017 Memgraph
-// Created by Florijan Stamenkovic on 20.02.17.
-//
-
-#pragma once
-
-#include <functional>
-#include <list>
-
-#include "enums.hpp"
-#include "path.hpp"
-#include "utils/assert.hpp"
-
-/**
- * This namespace contains traversal class templates that must
- * be parameterized with Vertex and Edge classes. This abstraction
- * is made so that the traversal API can easily be used with real
- * MemgraphDB Vertex and Edge classes, as well as mock classes used
- * for testing independently of the DB engine.
- *
- * For an overview of the traversal API-s architecture (and a how-to-use)
- * consult the Memgraph Wiki.
- *
- * The classes have the following templates:
- *      TVertex - vertex type. Provides functions for getting
- *          incoming and outgoing relationship TEdge objects.
- *      TEdge - edge type. Provides functions for getting
- *          origin and destination TVertex objects.
- *      TIterable - a class given to Begin. Can be iterated over
- *          (iteration provides Vertex references).
- *      TVisitable - a class that provides the Visit function
- *          that accepts a single std::function<void(Path &p)>
- *          argument. The path traversal classes here all conform
- *          to this definition, and can therefore be chained.
- */
-namespace traversal_template {
-
-/**
- * An object that enables Vertex and Edge uniqueness checks
- * across multiple paths (multiple interdependent UniquenessGroups).
- *
- * It is intended that only the BeginType keeps a UniquenessGroup
- * object and all of it's expansions only provide access to it.
- *
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TVertex, typename TEdge>
-class UniquenessGroup {
- public:
-  UniquenessGroup(const Path<TVertex, TEdge> &path) : current_path_(path) {}
-
-  /**
-   * Checks if this group or any of it's
-   * subgroups contains the given vertex.
-   *
-   * @param vertex
-   * @return
-   */
-  bool Contains(const TVertex &vertex) const {
-    if (current_path_.Contains(vertex)) return true;
-
-    for (const auto &group : subgroups_)
-      if (group.get().Contains(vertex)) return true;
-
-    return false;
-  }
-
-  /**
-   * Checks if this group or any of it's
-   * subgroups contains the given edge.
-   *
-   * @param vertex
-   * @return
-   */
-  bool Contains(const TEdge &edge) const {
-    if (current_path_.Contains(edge)) return true;
-
-    for (const auto &group : subgroups_)
-      if (group.get().Contains(edge)) return true;
-
-    return false;
-  }
-
-  /**
-   * Adds the given UniquenessGroup to this groups collection
-   * of subgroups.
-   *
-   * @param subgroup
-   */
-  void Add(const UniquenessGroup<TVertex, TEdge> &subgroup) {
-    subgroups_.emplace_back(subgroup);
-  }
-
- private:
-  // the currently traversed path of this uniqueness group
-  // set by the BeginType
-  const Path<TVertex, TEdge> &current_path_;
-
-  std::vector<std::reference_wrapper<const UniquenessGroup<TVertex, TEdge>>>
-      subgroups_;
-};
-
-/**
- * Base class for path expansion. Provides functionalities common
- * to both one-relationship expansions and variable-number expansions.
- *
- * Template parameters are documented in the namespace documentation,
- * as they are the same for many classes.
- *
- * @tparam TVisitable
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TVisitable, typename TVertex, typename TEdge>
-class ExpandBaseType {
-  using TPath = Path<TVertex, TEdge>;
-  using VertexFilter = std::function<bool(const TVertex &)>;
-  using EdgeFilter = std::function<bool(const TEdge &)>;
-
- public:
-  /**
-   * @return This expander's visitable's uniqueness group.
-   */
-  UniquenessGroup<TVertex, TEdge> &UniquenessGroup() {
-    return visitable_.UniquenessGroup();
-  }
-
- protected:
-  // tracking last appended path elements during traversal
-  TVertex const *current_vertex_ = nullptr;
-  TEdge const *current_edge_ = nullptr;
-
-  // for docs on all member variables consult the only constructor
-  TVisitable &visitable_;
-  const Expansion expansion_;
-  const Direction direction_;
-  const VertexFilter vertex_filter_;
-  const EdgeFilter edge_filter_;
-  const Uniqueness uniqueness_;
-
-  /**
-   * @param visitable The visitable that provides paths to expand from.
-   * @param expansion Indicates how the path should be expanded. Consult
-   *    the enum documentation for an explanation.
-   * @param direction Indicates which relationships are used for expansion
-   *    from a vertex.
-   * @param vertex_filter A function that accepts or rejects a Vertex that
-   *    would get added to the path in this expansion. A path is only
-   *    generated and visited if this function returns true (or is not
-   *    provided).
-   * @param edge_filter A function that accepts or rejects an Edge that
-   *    would get added to the path in this expansion. A path is only
-   *    generated and visited if this function returns true (or is not
-   *    provided).
-   * @param uniqueness Which kind of uniqueness should be applied.
-   */
-  ExpandBaseType(TVisitable &&visitable, Expansion expansion,
-                 Direction direction, VertexFilter vertex_filter,
-                 EdgeFilter edge_filter, Uniqueness uniqueness)
-      : visitable_(std::forward<TVisitable>(visitable)),
-        expansion_(expansion),
-        direction_(direction),
-        vertex_filter_(vertex_filter),
-        edge_filter_(edge_filter),
-        uniqueness_(uniqueness) {}
-
-  /**
-   * Visits the given visitor with every expansion of the given path
-   * that is in-line with this object's expansion-control members
-   * (expansion type and direction).
-   *
-   * @param visitor
-   * @param p
-   */
-  void VisitExpansions(std::function<void(TPath &)> visitor, TPath &p) {
-    // the start or end point of the vertex
-    const auto &origin_vertex =
-        expansion_ == Expansion::Back ? p.Back() : p.Front();
-
-    if (direction_ == Direction::In || direction_ == Direction::Both)
-      VisitExpansions(origin_vertex.in(), p, visitor, Direction::In);
-    if (direction_ == Direction::Out || direction_ == Direction::Both)
-      VisitExpansions(origin_vertex.out(), p, visitor, Direction::Out);
-  }
-
- private:
-  /**
-   * Helper method that handles path expansion and visiting w.r.t.
-   * expansion params.
-   *
-   * NOTE: This function accepts the Direction as a param (it does
-   * NOT use the direction_ member) so that
-   * Direction::Both can be handled with two calls to this function
-   * (for ::In and ::Out).
-   *
-   * @tparam TVertices
-   * @param vertices
-   * @param p
-   * @param visitor
-   * @param direction
-   */
-  template <typename Edges>
-  void VisitExpansions(Edges &edges, TPath &p,
-                       std::function<void(TPath &)> visitor,
-                       Direction direction) {
-    for (const TEdge &e : edges) {
-      // edge filtering and uniqueness
-      if (edge_filter_ && !edge_filter_(e)) continue;
-      if (uniqueness_ == Uniqueness::Edge && UniquenessGroup().Contains(e))
-        continue;
-
-      // vertex filtering and uniqueness
-      const TVertex &v = (direction == Direction::In) ? e.from() : e.to();
-      if (vertex_filter_ && !vertex_filter_(v)) continue;
-      if (uniqueness_ == Uniqueness::Vertex && UniquenessGroup().Contains(v))
-        continue;
-
-      current_edge_ = &e;
-      current_vertex_ = &v;
-
-      switch (expansion_) {
-        case Expansion::Front:
-          p.Prepend(e, v);
-          visitor(p);
-          p.PopFront();
-          break;
-        case Expansion::Back:
-          p.Append(e, v);
-          visitor(p);
-          p.PopBack();
-          break;
-      }
-
-      current_edge_ = nullptr;
-      current_vertex_ = nullptr;
-    }
-  }
-};
-
-/**
- * Expansion along a variable number of traversals.
- *
- * Template parameters are documented in the namespace documentation,
- * as they are the same for many classes.
- *
- * @tparam TVisitable
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TVisitable, typename TVertex, typename TEdge>
-class ExpandVariableType : public ExpandBaseType<TVisitable, TVertex, TEdge> {
-  using TPath = Path<TVertex, TEdge>;
-  using VertexFilter = std::function<bool(const TVertex &)>;
-  using EdgeFilter = std::function<bool(const TEdge &)>;
-
- public:
-  /**
-   * For most params see the ExpandBaseType::ExpandBaseType documentation.
-   *
-   * @param min_length Minimum number of vertices in a path for it to be
-   *    visited. Inclusive.
-   * @param max_length Maximum number of vertices in a path for it to be
-   *    visited. Exclusive.
-   */
-  ExpandVariableType(TVisitable &&visitable, Expansion expansion,
-                     Direction direction, VertexFilter vertex_filter,
-                     EdgeFilter edge_filter, int min_length, int max_length,
-                     Uniqueness uniqueness)
-      : ExpandBaseType<TVisitable, TVertex, TEdge>(
-            std::forward<TVisitable>(visitable), expansion, direction, {},
-            edge_filter, uniqueness),
-        min_length_(min_length),
-        max_length_(max_length),
-        current_vertex_filter_(vertex_filter) {}
-
-  /**
-   * Calls the given visitor function once for every path this traversal
-   * generates.
-   *
-   * @param visitor
-   */
-  void Visit(std::function<void(TPath &)> visitor) {
-    this->visitable_.Visit(
-        [this, &visitor](TPath &p) { VisitRecursive(visitor, p, p.Size()); });
-  }
-
-  /**
-   * Expands from this expansion along one traversal.
-   * Arguments are simply passed to the expansion constructor.
-   *
-   * @return An expansion that generates paths one traversal longer.
-   */
-  auto Expand(Expansion expansion, Direction direction,
-              VertexFilter vertex_filter = {}, EdgeFilter edge_filter = {});
-
-  /**
-   * Expands from this expansion along a variable number traversal.
-   * Arguments are simply passed to the variable expansion constructor.
-   *
-   * @return An expansion that generates paths variable length longer.
-   */
-  auto ExpandVariable(Expansion expansion, Direction direction,
-                      VertexFilter vertex_filter = {},
-                      EdgeFilter edge_filter = {}, int min_length = 0,
-                      int max_length = 1000);
-
-  /**
-   * Returns a reference to the vertex currently being traversed
-   * by this part of the traversal chain. ONLY VALID DURING
-   * TRAVERSAL!!!
-   */
-  const TVertex &CurrentVertex() const {
-    debug_assert(this->current_vertex_ != nullptr,
-                 "Current vertex not set, function most likely called outside "
-                 "of traversal");
-    return *this->current_vertex_;
-  }
-
-  /**
-   * Returns a reference to the edge currently being traversed
-   * by this part of the traversal chain. ONLY VALID DURING
-   * TRAVERSAL!!!
-   */
-  const std::list<TEdge> &CurrentEdges() const {
-    debug_assert(this->current_edge_ != nullptr,
-                 "Current edge not set, function most likely called outside of "
-                 "traversal");
-    return current_edges_;
-  }
-
- private:
-  // see constructor documentation for member var explanation
-  const int min_length_;
-  const int max_length_;
-
-  // the expand variable has another vertex filter used only on the last path
-  // element
-  // because traversal is done recursively using superclass functionality,
-  // so we give an empty filter to superclass so it does not end traversal, and
-  // use
-  // this filter to see if we actually need to visit the path or not
-  const VertexFilter current_vertex_filter_;
-
-  // variable length traversal can return all the traversed edges as a list
-  // store them here during traversal
-  std::list<TEdge> current_edges_;
-
-  /**
-   * Helper function for recursive path visiting.
-   * TODO: Try to make a stack implementation. It would be safer.
-   *
-   * @param visitor
-   * @param p
-   * @param p_start_size The size of the path before variable-length expansion.
-   *    It's necessary to keep track of it because min and max length are
-   *    evaluated against how much this traversal generated, not against the
-   *    actual path length (there could have been plan expansions before this
-   * variable length).
-   */
-  void VisitRecursive(std::function<void(TPath &)> visitor, TPath &p,
-                      const size_t p_start_size) {
-    debug_assert(p.Size() >= p_start_size,
-                 "Current path must be greater then start size");
-
-    size_t recursion_size = p.Size() - p_start_size;
-
-    // only append to current_edges once the first traversal happened
-    if (recursion_size > 0) current_edges_.emplace_back(*this->current_edge_);
-
-    if (recursion_size >= min_length_ &&
-        (!current_vertex_filter_ ||
-         current_vertex_filter_(*this->current_vertex_)))
-      visitor(p);
-
-    if (recursion_size >= max_length_ - 1) return;
-
-    // a lambda we'll inject to ExpandVisit, that calls this function
-    // with the expanded path
-    auto recursive_visitor = [this, &visitor, p_start_size](TPath &path) {
-      VisitRecursive(visitor, path, p_start_size);
-    };
-
-    this->VisitExpansions(recursive_visitor, p);
-
-    if (recursion_size > 0) current_edges_.pop_back();
-  }
-};
-
-/**
- * Expansion along a single traversal.
- *
- * Template parameters are documented in the namespace documentation,
- * as they are the same for many classes.
- *
- * @tparam TVisitable
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TVisitable, typename TVertex, typename TEdge>
-class ExpandType : public ExpandBaseType<TVisitable, TVertex, TEdge> {
-  using TPath = Path<TVertex, TEdge>;
-  using VertexFilter = std::function<bool(const TVertex &)>;
-  using EdgeFilter = std::function<bool(const TEdge &)>;
-
- public:
-  /**
-   * For all params see the ExpandBaseType::ExpandBaseType documentation.
-   */
-  ExpandType(TVisitable &&visitable, Expansion expansion, Direction direction,
-             VertexFilter vertex_filter, EdgeFilter edge_filter,
-             Uniqueness uniqueness)
-      : ExpandBaseType<TVisitable, TVertex, TEdge>(
-            std::forward<TVisitable>(visitable), expansion, direction,
-            vertex_filter, edge_filter, uniqueness) {}
-
-  /**
-   * Calls the given visitor function once for every path this traversal
-   * generates.
-   *
-   * @param visitor
-   */
-  void Visit(std::function<void(TPath &)> visitor) {
-    this->visitable_.Visit(
-        [this, &visitor](TPath &p) { this->VisitExpansions(visitor, p); });
-  }
-
-  /**
-   * Returns a reference to the vertex currently being traversed
-   * by this part of the traversal chain. ONLY VALID DURING
-   * TRAVERSAL!!!
-   */
-  const TVertex &CurrentVertex() const {
-    debug_assert(this->current_vertex_ != nullptr,
-                 "Current vertex not set, function most likely called outside "
-                 "of traversal");
-    return *this->current_vertex_;
-  }
-
-  /**
-   * Returns a reference to the edge currently being traversed
-   * by this part of the traversal chain. ONLY VALID DURING
-   * TRAVERSAL!!!
-   */
-  const TEdge &CurrentEdge() const {
-    debug_assert(this->current_edge_ != nullptr,
-                 "Current edge not set, function most likely called outside of "
-                 "traversal");
-    return *this->current_edge_;
-  }
-
-  /**
-   * Expands from this expansion along one traversal.
-   * Arguments are simply passed to the expansion constructor.
-   *
-   * @return An expansion that generates paths one traversal longer.
-   */
-  auto Expand(Expansion expansion, Direction direction,
-              VertexFilter vertex_filter = {}, EdgeFilter edge_filter = {}) {
-    return ExpandType<ExpandType<TVisitable, TVertex, TEdge> &, TVertex, TEdge>(
-        *this, expansion, direction, vertex_filter, edge_filter,
-        this->uniqueness_);
-  }
-
-  /**
-   * Expands from this expansion along a variable number traversal.
-   * Arguments are simply passed to the variable expansion constructor.
-   *
-   * @return An expansion that generates paths variable length longer.
-   */
-  auto ExpandVariable(Expansion expansion, Direction direction,
-                      VertexFilter vertex_filter = {},
-                      EdgeFilter edge_filter = {}, int min_length = 0,
-                      int max_length = 1000) {
-    return ExpandVariableType<const ExpandType<TVisitable, TVertex, TEdge> &,
-                              TVertex, TEdge>(
-        *this, expansion, direction, vertex_filter, edge_filter, min_length,
-        max_length, this->uniqueness_);
-  }
-};
-
-/**
- * Start traversals from an iterable over Vertices.
- *
- * @tparam TIterable
- * @tparam TVertex
- * @tparam TEdge
- */
-template <typename TIterable, typename TVertex, typename TEdge>
-class BeginType {
-  using TPath = Path<TVertex, TEdge>;
-  using VertexFilter = std::function<bool(const TVertex &)>;
-  using EdgeFilter = std::function<bool(const TEdge &)>;
-
- public:
-  BeginType(const TIterable &vertices, VertexFilter vertex_filter)
-      : vertices_(vertices),
-        vertex_filter_(vertex_filter),
-        uniqueness_group_(path) {}
-
-  /**
-   * Calls the visitor with a path containing a single vertex
-   * yielded by the given collection of vertices and accepted
-   * by the filter.
-   *
-   * @param visitor
-   */
-  void Visit(std::function<void(TPath &)> visitor) {
-    for (const TVertex &v : vertices_) {
-      if (vertex_filter_ && !vertex_filter_(v)) continue;
-
-      path.Start(v);
-      visitor(path);
-      path.PopFront();
-    }
-  }
-
-  /**
-   * The UniquenessGroup of this BeginType (the only one that
-   * exists for all the expansions from this Begin).
-   */
-  UniquenessGroup<TVertex, TEdge> &UniquenessGroup() {
-    return uniqueness_group_;
-  }
-
-  /**
-   * Returns a reference to the vertex currently being traversed
-   * by this part of the traversal chain. ONLY VALID DURING
-   * TRAVERSAL!!!
-   */
-  const TVertex &CurrentVertex() const {
-    debug_assert(path.Size() > 0,
-                 "Current path is empty, function most likely called outside "
-                 "of traversal");
-    return path.Front();
-  }
-
-  /**
-   * Expands from this expansion along one traversal.
-   * Arguments are simply passed to the expansion constructor.
-   *
-   * @return An expansion that generates paths one traversal longer.
-   */
-  auto Expand(Expansion expansion, Direction direction,
-              VertexFilter vertex_filter = {}, EdgeFilter edge_filter = {},
-              Uniqueness uniqueness = Uniqueness::Edge) {
-    return ExpandType<BeginType<TIterable, TVertex, TEdge> &, TVertex, TEdge>(
-        *this, expansion, direction, vertex_filter, edge_filter, uniqueness);
-  }
-
-  /**
-   * Expands from this expansion along a variable number traversal.
-   * Arguments are simply passed to the variable expansion constructor.
-   *
-   * @return An expansion that generates paths variable length longer.
-   */
-  auto ExpandVariable(Expansion expansion, Direction direction,
-                      VertexFilter vertex_filter = {},
-                      EdgeFilter edge_filter = {}, int min_length = 1,
-                      int max_length = 1000,
-                      Uniqueness uniqueness = Uniqueness::Edge) {
-    return ExpandVariableType<BeginType<TIterable, TVertex, TEdge> &, TVertex,
-                              TEdge>(*this, expansion, direction, vertex_filter,
-                                     edge_filter, min_length, max_length,
-                                     uniqueness);
-  }
-
- private:
-  const TIterable &vertices_;
-  // the BeingType has only one path that gets appended to and emitted to
-  // visitors
-  TPath path;
-  const VertexFilter vertex_filter_;
-  // TODO review: why do I have to have namespace:: here???
-  traversal_template::UniquenessGroup<TVertex, TEdge> uniqueness_group_;
-};
-
-/**
- * Creates a BeginType.
- *
- * Template arguments are explained in namespace documentation.
- *
- * Function arguments are simply forwarded to the BeginType constructor.
- *
- * @return A BeginType.
- */
-template <typename TIterable, typename TVertex, typename TEdge>
-auto Begin(const TIterable &vertices,
-           std::function<bool(const TVertex &)> vertex_filter = {}) {
-  return BeginType<TIterable, TVertex, TEdge>(vertices, vertex_filter);
-}
-
-/**
- * Creates a start point for a recursion of Cartesian wrappers.
- */
-template <typename TVisitable, typename TVertex, typename TEdge>
-class CartesianUnaryType {
-  using TPath = Path<TVertex, TEdge>;
-  using TPaths = Paths<TVertex, TEdge>;
-
- public:
-  CartesianUnaryType(TVisitable &&visitable)
-      : visitable_(std::forward<TVisitable>(visitable)) {}
-
-  void Visit(std::function<void(TPaths &)> visitor) const {
-    TPaths paths;
-    visitable_.Visit([&visitor, &paths](TPath &p) {
-      paths.emplace_back(p);
-      visitor(paths);
-      paths.pop_back();
-    });
-  }
-
- private:
-  const TVisitable visitable_;
-};
-
-/**
- * Provides means to visit a cartesian product of traversals.
- *
- * @tparam TVisitableFirst A visitable whose visitor accepts a list of path
- * reference (recursion down).
- * @tparam TVisitableOthers Visitables whose visitor accepts a single path
- * reference.
- */
-template <typename TVisitableFirst, typename TVisitableOthers, typename TVertex,
-          typename TEdge>
-class CartesianBinaryType {
-  using TPath = Path<TVertex, TEdge>;
-  using TPaths = Paths<TVertex, TEdge>;
-
- public:
-  /**
-   * @tparam visitable_first A visitable whose visitor accepts a list of path
-   * reference (recursion down).
-   * @tparam visitable_others Visitable whose visitor accepts a single path
-   * reference.
-   */
-  CartesianBinaryType(TVisitableFirst &&visitable_first,
-                      TVisitableOthers &&visitable_others)
-      : visitable_first_(std::forward<TVisitableFirst>(visitable_first)),
-        visitable_others_(std::forward<TVisitableOthers>(visitable_others)) {}
-
-  /**
-   * Calls the given visitor with a list of reference wrappers to Paths
-   * for every combination in this cartesian.
-   *
-   * @param visitor
-   */
-  void Visit(std::function<void(TPaths &)> visitor) const {
-    // TODO currently cartesian product does NOT check for uniqueness
-    // for example between edges in the emitted path combinations
-
-    visitable_first_.Visit([this, &visitor](TPath &path) {
-      visitable_others_.Visit([&path, &visitor](TPaths &paths) {
-        paths.emplace_front(path);
-        visitor(paths);
-        paths.pop_front();
-      });
-    });
-  }
-
- private:
-  const TVisitableFirst visitable_first_;
-  const TVisitableOthers visitable_others_;
-};
-
-/**
- * Creates an object that can be visited with a function that accepts a list
- * of path reference wrappers. That function will be called one for every
- * element
- * of a cartesian product of the given visitables (that emit paths).
- *
- * @tparam TVisitableFirst  A visitable that emits paths.
- * @tparam TVisitableOthers  An arbitrary number of visitables that emit paths.
- * @param first  A visitable that emits paths.
- * @param others  An arbitrary number of visitables that emit paths.
- * @return  See above.
- */
-template <typename TVisitable, typename TVertex, typename TEdge>
-auto Cartesian(TVisitable &&visitable) {
-  return CartesianUnaryType<TVisitable, TVertex, TEdge>(
-      std::forward<TVisitable>(visitable));
-}
-
-/**
- * Creates an object that can be visited with a function that accepts a list
- * of path reference wrappers. That function will be called one for every
- * element
- * of a cartesian product of the given visitables (that emit paths).
- *
- * @tparam TVisitableFirst  A visitable that emits paths.
- * @tparam TVisitableOthers  An arbitrary number of visitables that emit paths.
- * @param first  A visitable that emits paths.
- * @param others  An arbitrary number of visitables that emit paths.
- * @return  See above.
- */
-template <typename TVisitableFirst, typename Vertex, typename Edge,
-          typename... TVisitableOthers>
-auto Cartesian(TVisitableFirst &&first, TVisitableOthers &&... others) {
-  return CartesianBinaryType<
-      TVisitableFirst,
-      decltype(Cartesian(std::forward<TVisitableOthers>(others)...)), Vertex,
-      Edge>(std::forward<TVisitableFirst>(first),
-            Cartesian(std::forward<TVisitableOthers>(others)...));
-}
-
-template <typename TVisitable, typename TVertex, typename TEdge>
-auto ExpandVariableType<TVisitable, TVertex, TEdge>::Expand(
-    Expansion expansion, Direction direction, VertexFilter vertex_filter,
-    EdgeFilter edge_filter) {
-  return ExpandType<ExpandVariableType<TVisitable, TVertex, TEdge> &, TVertex,
-                    TEdge>(*this, expansion, direction, vertex_filter,
-                           edge_filter, this->uniqueness_);
-}
-
-template <typename TVisitable, typename TVertex, typename TEdge>
-auto ExpandVariableType<TVisitable, TVertex, TEdge>::ExpandVariable(
-    Expansion expansion, Direction direction, VertexFilter vertex_filter,
-    EdgeFilter edge_filter, int min_length, int max_length) {
-  return ExpandVariableType<ExpandVariableType<TVisitable, TVertex, TEdge> &,
-                            TVertex, TEdge>(
-      *this, expansion, direction, vertex_filter, edge_filter, min_length,
-      max_length, this->uniqueness_);
-}
-}
diff --git a/src/traversal/traversal.hpp b/src/traversal/traversal.hpp
deleted file mode 100644
index 429471761..000000000
--- a/src/traversal/traversal.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright 2017 Memgraph
-// Created by Florijan Stamenkovic on 02.03.17.
-//
-
-#pragma once
-
-#include "enums.hpp"
-#include "path.hpp"
-#include "templates.hpp"
-
-#include "storage/edge_accessor.hpp"
-#include "storage/vertex_accessor.hpp"
-
-/**
- * A specialization of the "traversal" namespace that uses
- * real DB VertexAccessor and EdgeAccessor classes.
- */
-namespace traversal {
-
-// expose Path and Paths as class template instantiations
-using Path = traversal_template::Path<VertexAccessor, EdgeAccessor>;
-using Paths = traversal_template::Paths<VertexAccessor, EdgeAccessor>;
-
-/**
- * Specialization of the traversal_template::Begin function.
- */
-template <typename TCollection>
-auto Begin(const TCollection &vertices,
-           std::function<bool(const VertexAccessor &)> vertex_filter = {}) {
-  return traversal_template::Begin<TCollection, VertexAccessor, EdgeAccessor>(
-      vertices, vertex_filter);
-}
-
-/**
- * Specialization of the traversal_template::Cartesian function that accepts
- * a single argument.
- */
-template <typename TVisitable>
-auto Cartesian(TVisitable &&visitable) {
-  return traversal_template::Cartesian<TVisitable, VertexAccessor,
-                                       EdgeAccessor>(
-      std::forward<TVisitable>(visitable));
-}
-
-/**
- * Specialization of the traversal_template::Cartesian function that accepts
- * multiple arguments.
- */
-template <typename TVisitableFirst, typename... TVisitableOthers>
-auto Cartesian(TVisitableFirst &&first, TVisitableOthers &&... others) {
-  return traversal_template::CartesianBinaryType<
-      TVisitableFirst,
-      decltype(Cartesian(std::forward<TVisitableOthers>(others)...)),
-      VertexAccessor, EdgeAccessor>(
-      std::forward<TVisitableFirst>(first),
-      Cartesian(std::forward<TVisitableOthers>(others)...));
-}
-}
-
diff --git a/tests/unit/traversal.cpp b/tests/unit/traversal.cpp
deleted file mode 100644
index b7d32ccb3..000000000
--- a/tests/unit/traversal.cpp
+++ /dev/null
@@ -1,691 +0,0 @@
-//
-// Copyright 2017 Memgraph
-// Created by Florijan Stamenkovic on 24.01.17..
-//
-
-#include <iostream>
-#include <list>
-#include <list>
-#include <memory>
-#include <unordered_set>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-#include "traversal/enums.hpp"
-#include "traversal/path.hpp"
-#include "traversal/templates.hpp"
-
-/**
- * A specialization of the "traversal" namespace that uses
- * test Vertex and Edge classes (as opposed to the real database
- * ones).
- */
-namespace traversal_test {
-
-// add the standard enums to this namespace
-using Direction = traversal_template::Direction;
-using Expansion = traversal_template::Expansion;
-using Uniqueness = traversal_template::Uniqueness;
-
-// forward declaring Edge because Vertex holds references to it
-class Edge;
-
-/**
- * A Vertex class for traversal testing. Has only the
- * traversal capabilities and an exposed id_ member.
- */
-class Vertex {
-  friend class Edge;
-
- public:
-  // unique identifier (uniqueness guaranteed by this class)
-  const int id_;
-
-  // vertex set by the user, for testing purposes
-  const int label_;
-
-  Vertex(int label = 0) : id_(counter_++), label_(label) {}
-
-  const auto &in() const { return *in_; }
-  const auto &out() const { return *out_; }
-
-  friend std::ostream &operator<<(std::ostream &stream, const Vertex &v) {
-    return stream << "(" << v.id_ << ")";
-  }
-
-  bool operator==(const Vertex &v) const { return this->id_ == v.id_; }
-  bool operator!=(const Vertex &v) const { return !(*this == v); }
-
- private:
-  // shared pointers to outgoing and incoming edges are used so that when
-  // a Vertex is copied it still points to the same connectivity storage
-  std::shared_ptr<std::vector<Edge>> in_ =
-      std::make_shared<std::vector<Edge>>();
-  std::shared_ptr<std::vector<Edge>> out_ =
-      std::make_shared<std::vector<Edge>>();
-
-  // Vertex counter, used for generating IDs
-  static int counter_;
-};
-
-int Vertex::counter_ = 0;
-
-/**
- * An Edge class for traversal testing. Has only traversal capabilities
- * and an exposed id_ member.
- */
-class Edge {
- public:
-  // unique identifier (uniqueness guaranteed by this class)
-  const int id_;
-
-  // vertex set by the user, for testing purposes
-  const int type_;
-
-  Edge(const Vertex &from, const Vertex &to, int type = 0)
-      : id_(counter_++), type_(type), from_(from), to_(to) {
-    from.out_->emplace_back(*this);
-    to.in_->emplace_back(*this);
-  }
-
-  const Vertex &from() const { return from_; }
-  const Vertex &to() const { return to_; }
-
-  bool operator==(const Edge &e) const { return id_ == e.id_; }
-  bool operator!=(const Edge &e) const { return !(*this == e); }
-
-  friend std::ostream &operator<<(std::ostream &stream, const Edge &e) {
-    return stream << "[" << e.id_ << "]";
-  }
-
- private:
-  const Vertex &from_;
-  const Vertex &to_;
-
-  // Edge counter, used for generating IDs
-  static int counter_;
-};
-
-int Edge::counter_ = 0;
-
-// expose Path and Paths as class template instantiations
-using Path = traversal_template::Path<Vertex, Edge>;
-using Paths = traversal_template::Paths<Vertex, Edge>;
-
-/**
- * Specialization of the traversal_template::Begin function.
- */
-template <typename TCollection>
-auto Begin(const TCollection &vertices,
-           std::function<bool(const Vertex &)> vertex_filter = {}) {
-  return traversal_template::Begin<TCollection, Vertex, Edge>(vertices,
-                                                              vertex_filter);
-}
-
-/**
- * Specialization of the traversal_template::Cartesian function that accepts
- * a single argument.
- */
-template <typename TVisitable>
-auto Cartesian(TVisitable &&visitable) {
-  return traversal_template::Cartesian<TVisitable, Vertex, Edge>(
-      std::forward<TVisitable>(visitable));
-}
-
-/**
- * Specialization of the traversal_template::Cartesian function that accepts
- * multiple arguments.
- */
-template <typename TVisitableFirst, typename... TVisitableOthers>
-auto Cartesian(TVisitableFirst &&first, TVisitableOthers &&... others) {
-  return traversal_template::CartesianBinaryType<
-      TVisitableFirst,
-      decltype(Cartesian(std::forward<TVisitableOthers>(others)...)), Vertex,
-      Edge>(std::forward<TVisitableFirst>(first),
-            Cartesian(std::forward<TVisitableOthers>(others)...));
-}
-}
-
-/**
- * Hash calculations for text vertex, edge, Path and Paths.
- * Only for testing purposes.
- */
-namespace std {
-
-template <>
-struct hash<traversal_test::Vertex> {
- public:
-  size_t operator()(const traversal_test::Vertex &vertex) const {
-    return (size_t)vertex.id_;
-  }
-};
-
-template <>
-struct hash<traversal_test::Edge> {
- public:
-  size_t operator()(const traversal_test::Edge &edge) const {
-    return (size_t)edge.id_;
-  }
-};
-
-template <>
-struct hash<traversal_test::Path> {
- public:
-  std::size_t operator()(const traversal_test::Path &path) const {
-    std::size_t r_val = 0;
-
-    for (const auto &vertex : path.Vertices())
-      r_val ^= std::hash<traversal_test::Vertex>{}(vertex);
-
-    return r_val;
-  }
-};
-
-template <>
-struct hash<traversal_test::Paths> {
- public:
-  std::size_t operator()(const traversal_test::Paths &paths) const {
-    std::size_t r_val = 0;
-
-    for (const auto &path : paths)
-      r_val ^= std::hash<traversal_test::Path>{}(path);
-
-    return r_val;
-  }
-};
-}
-
-/**
- * Hash for a list of edges, used in tests.
- */
-namespace std {
-template <>
-struct hash<std::list<traversal_test::Edge>> {
- public:
-  std::size_t operator()(const std::list<traversal_test::Edge> &edges) const {
-    std::size_t r_val = 0;
-
-    for (const auto &edge : edges)
-      r_val ^= std::hash<traversal_test::Edge>{}(edge);
-
-    return r_val;
-  }
-};
-}
-
-using namespace traversal_test;
-
-template <typename TElement, typename TVisitable>
-std::unordered_set<TElement> accumulate_visited(const TVisitable &visitable) {
-  // we accept const here so we can receive r-values
-  // we cast the const-ness away because the Visit function is not const
-  std::unordered_set<TElement> results;
-  const_cast<TVisitable &>(visitable).Visit(
-      [&results](auto e) { results.insert(e); });
-  return results;
-};
-
-TEST(Traversal, VertexCreationAndEquality) {
-  Vertex v0;
-  Vertex v1;
-  EXPECT_EQ(v0, v0);
-  EXPECT_NE(v0, v1);
-}
-
-TEST(Traversal, EdgeCreationAndEquality) {
-  Vertex v0;
-  Vertex v1;
-
-  Edge e0(v0, v1);
-  Edge e1(v0, v1);
-  EXPECT_EQ(e0, e0);
-  EXPECT_NE(e0, e1);
-}
-
-TEST(Traversal, PathCreationAndEquality) {
-  Vertex v0;
-  Vertex v1;
-  Vertex v2;
-  Edge e0(v0, v1);
-  Edge e1(v0, v2);
-
-  // first test single-vertex-path equality
-  Path ref_path;
-  ref_path.Start(v0);
-  EXPECT_EQ(ref_path, Path().Start(v0));
-  EXPECT_NE(ref_path, Path().Start(v1));
-
-  // now test two-vertex-path equality
-  // reference path is (v0)-[e0]->(v1)
-  ref_path.Append(e0, v1);
-  EXPECT_EQ(ref_path, Path().Start(v0).Append(e0, v1));
-
-  // test against one-vertex paths
-  EXPECT_NE(ref_path, Path().Start(v0));
-  EXPECT_NE(ref_path, Path().Start(v1));
-
-  // test on different vertex
-  EXPECT_NE(ref_path, Path().Start(v0).Append(e0, v2));
-  // test on different edge
-  EXPECT_NE(ref_path, Path().Start(v0).Append(e1, v1));
-  // test on different expansion direction
-  EXPECT_NE(ref_path, Path().Start(v0).Prepend(e0, v1));
-}
-
-TEST(Traversal, Begin) {
-  std::vector<Vertex> vertices(3);
-
-  std::unordered_set<Path> expected;
-  for (const auto &vertex : vertices) expected.insert(Path().Start(vertex));
-  EXPECT_EQ(expected.size(), 3);
-
-  auto result = accumulate_visited<Path>(Begin(vertices));
-  EXPECT_EQ(result, expected);
-}
-
-TEST(Traversal, BeginExpand) {
-  Vertex v0, v1, v2, v3;
-  Edge e0(v0, v1);
-  Edge e1(v0, v2);
-  Edge e2(v2, v3);
-
-  // test traversal from (v0)
-  auto expected = std::unordered_set<Path>{Path().Start(v0).Append(e0, v1),
-                                           Path().Start(v0).Append(e1, v2)};
-  auto result = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0}).Expand(Expansion::Back, Direction::Out));
-  EXPECT_EQ(expected, result);
-}
-
-TEST(Traversal, BeginExpandVariable) {
-  Vertex v0, v1, v2, v3, v4;
-  Edge e0(v0, v1);
-  Edge e1(v0, v2);
-  Edge e2(v2, v3);
-  // disconnected from the above graph, just to have something else
-  Vertex v5, v6;
-  Edge e3(v5, v6);
-
-  // test traversal from (v0)
-  auto expected = std::unordered_set<Path>{
-      Path().Start(v0).Append(e0, v1), Path().Start(v0).Append(e1, v2),
-      Path().Start(v0).Append(e1, v2).Append(e2, v3)};
-  auto result = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out));
-  EXPECT_EQ(expected, result);
-}
-
-TEST(Traversal, BeginFilter) {
-  Vertex v0(1), v1(1), v2(2);
-
-  std::unordered_set<Path> expected{Path().Start(v0), Path().Start(v1)};
-
-  auto result = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0, v1, v2},
-            [](const Vertex &v) { return v.label_ == 1; }));
-  EXPECT_EQ(expected, result);
-}
-
-TEST(Traversal, BeginCurrent) {
-  Vertex v0, v1, v2, v3, v4;
-
-  std::unordered_set<Vertex> expected{v0, v1, v2};
-  std::vector<Vertex> begin_input{v0, v1, v2};
-  auto b = Begin(begin_input);
-
-  b.Visit([&b, &expected](Path &path) {
-    EXPECT_EQ(1, expected.erase(b.CurrentVertex()));
-  });
-
-  EXPECT_EQ(0, expected.size());
-}
-
-TEST(Traversal, ExpandExpand) {
-  Vertex v0, v1, v2, v3, v4, v5;
-  Edge e0(v0, v1);
-  Edge e1(v0, v2);
-  Edge e2(v1, v3);
-  Edge e3(v2, v4);
-  Edge e4(v2, v5);
-
-  // not part of the results
-  Vertex v6, v7;
-  Edge e5(v4, v6);
-  Edge e6(v7, v1);
-
-  // test traversal from (v0)
-  auto expected =
-      std::unordered_set<Path>{Path().Start(v0).Append(e0, v1).Append(e2, v3),
-                               Path().Start(v0).Append(e1, v2).Append(e3, v4),
-                               Path().Start(v0).Append(e1, v2).Append(e4, v5)};
-  auto result =
-      accumulate_visited<Path>(Begin(std::vector<Vertex>{v0})
-                                   .Expand(Expansion::Back, Direction::Out)
-                                   .Expand(Expansion::Back, Direction::Out));
-  EXPECT_EQ(expected, result);
-}
-
-TEST(Traversal, ExpandFilter) {
-  // make a one-level deep tree and 4 children that have {1,2} vertex labels and
-  // {3,4} edge types
-  Vertex root;
-  Vertex v1(1);
-  Edge e1(root, v1, 3);
-  Vertex v2(1);
-  Edge e2(root, v2, 4);
-  Vertex v3(2);
-  Edge e3(root, v3, 3);
-  Vertex v4(2);
-  Edge e4(root, v4, 4);
-
-  // filter to accept only label 1 and edge type 3, expect exactly one path
-  auto result = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{root})
-          .Expand(Expansion::Back, Direction::Out,
-                  [](const Vertex &v) { return v.label_ == 1; },
-                  [](const Edge &e) { return e.type_ == 3; }));
-
-  auto expected = std::unordered_set<Path>{Path().Start(root).Append(e1, v1)};
-  EXPECT_EQ(expected, result);
-}
-
-TEST(Traversal, ExpandCurrent) {
-  //  make a complete binary tree two levels deep (7 nodes)
-  Vertex v0;
-  Vertex v1, v2;
-  Edge e1(v0, v1), e2(v0, v2);
-  Vertex v3, v4, v5, v6;
-  Edge e3(v1, v3), e4(v1, v4), e5(v2, v5), e6(v2, v6);
-
-  // traverse two levels deep and accumulate results
-  std::vector<Vertex> begin_input{v0};
-  auto begin = Begin(begin_input);
-  auto expand0 = begin.Expand(Expansion::Back, Direction::Out);
-  auto expand1 = expand0.Expand(Expansion::Back, Direction::Out);
-
-  // expected results
-  std::unordered_set<Vertex> expected_expand0_vertices{v1, v2};
-  std::unordered_set<Edge> expected_expand0_edges{e1, e2};
-  std::unordered_set<Vertex> expected_expand1_vertices{v3, v4, v5, v6};
-  std::unordered_set<Edge> expected_expand1_edges{e3, e4, e5, e6};
-
-  expand1.Visit([&](Path &path) {
-    // we can't check that erasure on the first level because it only gets
-    // erased the first time a path containing first level stuff gets visited
-    expected_expand0_vertices.erase(expand0.CurrentVertex());
-    expected_expand0_edges.erase(expand0.CurrentEdge());
-    EXPECT_EQ(1, expected_expand1_vertices.erase(expand1.CurrentVertex()));
-    EXPECT_EQ(1, expected_expand1_edges.erase(expand1.CurrentEdge()));
-  });
-
-  EXPECT_EQ(0, expected_expand0_vertices.size());
-  EXPECT_EQ(0, expected_expand0_edges.size());
-  EXPECT_EQ(0, expected_expand1_vertices.size());
-  EXPECT_EQ(0, expected_expand1_edges.size());
-}
-
-TEST(Traversal, ExpandVariableLimits) {
-  // make a chain
-  Vertex v0;
-  Vertex v1;
-  Edge e1(v0, v1);
-  Vertex v2;
-  Edge e2(v1, v2);
-  Vertex v3;
-  Edge e3(v2, v3);
-  Vertex v4;
-  Edge e4(v3, v4);
-
-  // all possible results
-  std::vector<Path> all_possible{Path().Start(v0)};
-  all_possible.emplace_back(Path(all_possible.back()).Append(e1, v1));
-  all_possible.emplace_back(Path(all_possible.back()).Append(e2, v2));
-  all_possible.emplace_back(Path(all_possible.back()).Append(e3, v3));
-  all_possible.emplace_back(Path(all_possible.back()).Append(e4, v4));
-
-  // default is one or more traversals
-  auto result0 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out));
-  EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1,
-                                              all_possible.end()));
-
-  // zero or more traversals
-  auto result1 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 0));
-  EXPECT_EQ(result1,
-            std::unordered_set<Path>(all_possible.begin(), all_possible.end()));
-
-  // an exact number of traversals [2, 4)
-  auto result2 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 2, 4));
-  EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.begin() + 2,
-                                              all_possible.begin() + 4));
-}
-
-TEST(Traversal, ExpandVariableFilter) {
-  // make a chain with vertex labels and edge types with these values
-  // (0)-[1]->(1)-[2]->(2)-[3]->(3)
-  Vertex v0(0);
-  Vertex v1(1);
-  Edge e1(v0, v1, 1);
-  Vertex v2(2);
-  Edge e2(v1, v2, 2);
-  Vertex v3(3);
-  Edge e3(v2, v3, 3);
-
-  // all possible paths
-  std::vector<Path> all_possible{Path().Start(v0)};
-  all_possible.emplace_back(Path(all_possible.back()).Append(e1, v1));
-  all_possible.emplace_back(Path(all_possible.back()).Append(e2, v2));
-  all_possible.emplace_back(Path(all_possible.back()).Append(e3, v3));
-
-  // filter on edge type < 3
-  auto result0 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out, {},
-                          [](const Edge &e) { return e.type_ < 3; }));
-  EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1,
-                                              all_possible.begin() + 3));
-
-  // filter on edge type > 1, expect nothing because the first edge is 1
-  auto result1 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out, {},
-                          [](const Edge &e) { return e.type_ > 1; }));
-  EXPECT_EQ(result1.size(), 0);
-
-  // filter on vertex label > 1, expect last 2 results
-  auto result2 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .ExpandVariable(Expansion::Back, Direction::Out,
-                          [](const Vertex &v) { return v.label_ > 1; }, {}));
-  EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.end() - 2,
-                                              all_possible.end()));
-}
-
-TEST(Traversal, ExpandVariableCurrent) {
-  // a chain
-  Vertex v0;
-  Vertex v1;
-  Edge e1(v0, v1);
-  Vertex v2;
-  Edge e2(v1, v2);
-  Vertex v3;
-  Edge e3(v2, v3);
-
-  // ensure that expanded vertices and all edge sets get visited as current
-  std::unordered_set<Vertex> expected_vertices{v1, v2, v3};
-  std::unordered_set<std::list<Edge>> expected_edge_lists{
-      std::list<Edge>{e1}, std::list<Edge>{e1, e2},
-      std::list<Edge>{e1, e2, e3}};
-
-  std::vector<Vertex> begin_input{v0};
-  auto begin = Begin(begin_input);
-  auto expand = begin.ExpandVariable(Expansion::Back, Direction::Out);
-
-  expand.Visit([&](Path &path) {
-    EXPECT_EQ(1, expected_vertices.erase(expand.CurrentVertex()));
-    EXPECT_EQ(1, expected_edge_lists.erase(expand.CurrentEdges()));
-  });
-}
-
-TEST(Traversal, EnumExpansion) {
-  // (v0)-[]->(v1)
-  Vertex v0, v1;
-  Edge e0(v0, v1);
-
-  //  Expansion::Back
-  auto result0 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0}).Expand(Expansion::Back, Direction::Out));
-  auto expected0 = std::unordered_set<Path>{Path().Start(v0).Append(e0, v1)};
-  EXPECT_EQ(result0, expected0);
-
-  //  Expansion::Front
-  auto result1 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0}).Expand(Expansion::Front, Direction::Out));
-  auto expected1 = std::unordered_set<Path>{Path().Start(v0).Prepend(e0, v1)};
-  EXPECT_EQ(result1, expected1);
-}
-
-TEST(Traversal, EnumDirection) {
-  // (v0)-[]->(v1)-[]->(v2)
-  Vertex v0, v1, v2;
-  Edge e0(v0, v1), e1(v1, v2);
-
-  //  Direction::Out
-  auto result0 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::Out));
-  auto expected0 = std::unordered_set<Path>{Path().Start(v1).Append(e1, v2)};
-  EXPECT_EQ(result0, expected0);
-
-  //  Direction::In
-  auto result1 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::In));
-  auto expected1 = std::unordered_set<Path>{Path().Start(v1).Append(e0, v0)};
-  EXPECT_EQ(result1, expected1);
-
-  // Direction::Both
-  auto result2 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::Both));
-  auto expected2 = std::unordered_set<Path>{Path().Start(v1).Append(e0, v0),
-                                            Path().Start(v1).Append(e1, v2)};
-  EXPECT_EQ(result2, expected2);
-}
-
-TEST(Traversal, EnumUniqueness) {
-  // make a (v0)-[]->(v1), where (v0) has a recursive relationship to self
-  Vertex v0, v1;
-  Edge e0(v0, v0), e1(v0, v1);
-
-  //  Uniqueness::Edge
-  auto result0 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Edge)
-          .Expand(Expansion::Back, Direction::Out));
-  auto expected0 =
-      std::unordered_set<Path>{Path().Start(v0).Append(e0, v0).Append(e1, v1)};
-  EXPECT_EQ(result0, expected0);
-
-  //  Uniqueness::Vertex
-  auto result1 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Vertex)
-          .Expand(Expansion::Back, Direction::Out));
-  EXPECT_EQ(result1.size(), 0);
-
-  // Uniqueness::None
-  auto result2 = accumulate_visited<Path>(
-      Begin(std::vector<Vertex>{v0})
-          .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::None)
-          .Expand(Expansion::Back, Direction::Out));
-  auto expected2 =
-      std::unordered_set<Path>{Path().Start(v0).Append(e0, v0).Append(e1, v1),
-                               Path().Start(v0).Append(e0, v0).Append(e0, v0)};
-  EXPECT_EQ(result2, expected2);
-}
-
-TEST(Traversal, Cartesian) {
-  // first make two simple trees
-  Vertex v0, v1, v2;
-  Edge e1(v0, v1), e2(v0, v1);
-  Vertex v3, v4, v5;
-  Edge e3(v3, v4), e4(v3, v5);
-
-  // now accumulate all paths from three starting points
-  std::vector<Vertex> begin0{v0}, begin1{v3};
-  auto paths0 = Begin(begin0).Expand(Expansion::Back, Direction::Out);
-  auto paths1 = Begin(begin1).Expand(Expansion::Back, Direction::Out);
-  auto paths0_set = accumulate_visited<Path>(paths0);
-  auto paths1_set = accumulate_visited<Path>(paths1);
-  EXPECT_EQ(2, paths0_set.size());
-  EXPECT_EQ(2, paths1_set.size());
-
-  // now make a cartesian product of (0, 1, 0) and remember the results
-  std::unordered_set<Paths> expected;
-  for (auto &path1 : paths0_set)
-    for (auto &path2 : paths1_set)
-      for (auto &path3 : paths0_set) {
-        Paths paths;
-        paths.emplace_back(std::ref(const_cast<Path &>(path1)));
-        paths.emplace_back(std::ref(const_cast<Path &>(path2)));
-        paths.emplace_back(std::ref(const_cast<Path &>(path3)));
-        expected.insert(paths);
-      }
-  EXPECT_EQ(8, expected.size());
-
-  // now use the Cartesian API
-  auto paths2 = Begin(begin0).Expand(Expansion::Back, Direction::Out);
-  Cartesian(paths0, paths1, paths2).Visit([&expected](Paths &p) {
-    EXPECT_EQ(1, expected.erase(p));
-  });
-
-  EXPECT_EQ(0, expected.size());
-}
-
-TEST(Traversal, UniquenessSubgroups) {
-  // graph is (v1)<-[]-(v0)-[]->(v2)
-  Vertex v0, v1, v2;
-  Edge e1(v0, v1), e2(v0, v1);
-  std::vector<Vertex> begin_v{v0};
-
-  // counts the number of visits to the visitable
-  auto visit_counter = [](const auto &visitable) {
-    auto r_val = 0;
-    visitable.Visit([&r_val](const auto &x) { r_val++; });
-    return r_val;
-  };
-
-  // make a few experiments with different uniqueness sharing
-
-  // no uniqueness sharing
-  {
-    auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out);
-    auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out);
-    EXPECT_EQ(4, visit_counter(Cartesian(paths0, paths1)));
-  }
-
-  // edge uniqueness sharing
-  {
-    auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {},
-                                        Uniqueness::Edge);
-    auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {},
-                                        Uniqueness::Edge);
-    paths1.UniquenessGroup().Add(paths0.UniquenessGroup());
-    EXPECT_EQ(2, visit_counter(Cartesian(paths0, paths1)));
-  }
-
-  // vertex uniqueness sharing
-  {
-    auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {},
-                                        Uniqueness::Vertex);
-    auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {},
-                                        Uniqueness::Vertex);
-    paths1.UniquenessGroup().Add(paths0.UniquenessGroup());
-    EXPECT_EQ(0, visit_counter(Cartesian(paths0, paths1)));
-  }
-}