From 54691cfcc29fcd2d1870fc8311ceb09392095a97 Mon Sep 17 00:00:00 2001
From: p-mary <mary@labri.fr>
Date: Fri, 30 Nov 2018 14:33:59 +0100
Subject: [PATCH] add tlp::selectShortestPaths(Graph*, node, node, ...) in
 GraphTools + cleanup and performance improvements for path finder interactor

---
 .../tulip-core/include/tulip}/Dikjstra.h      |  47 ++--
 library/tulip-core/include/tulip/GraphTools.h |  20 ++
 library/tulip-core/src/CMakeLists.txt         |   1 +
 library/tulip-core/src/Dikjstra.cpp           | 218 ++++++++++++++++
 library/tulip-core/src/GraphTools.cpp         |  52 ++++
 plugins/interactor/PathFinder/CMakeLists.txt  |   1 -
 plugins/interactor/PathFinder/PathFinder.cpp  |   8 +-
 plugins/interactor/PathFinder/PathFinder.h    |   2 +-
 .../PathFinderConfigurationWidget.cpp         |   9 +-
 .../PathFinderConfigurationWidget.h           |   4 +-
 .../PathFinder/PathFinding/DFS/DFS.cpp        |  31 +--
 .../PathFinder/PathFinding/DFS/DFS.h          |   8 +-
 .../PathFinding/Dikjstra/Dikjstra.cpp         | 232 ------------------
 .../PathFinder/PathFinding/PathAlgorithm.cpp  | 104 ++++----
 .../PathFinder/PathFinding/PathAlgorithm.h    |   7 +-
 .../designer/PathFinderConfiguration.ui       |  13 +-
 tests/gui/interactor_path_finder.tlp          |  22 +-
 17 files changed, 421 insertions(+), 358 deletions(-)
 rename {plugins/interactor/PathFinder/PathFinding/Dikjstra => library/tulip-core/include/tulip}/Dikjstra.h (64%)
 create mode 100644 library/tulip-core/src/Dikjstra.cpp
 delete mode 100644 plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.cpp

diff --git a/plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.h b/library/tulip-core/include/tulip/Dikjstra.h
similarity index 64%
rename from plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.h
rename to library/tulip-core/include/tulip/Dikjstra.h
index adcdb247bc..7d31983343 100644
--- a/plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.h
+++ b/library/tulip-core/include/tulip/Dikjstra.h
@@ -17,11 +17,13 @@
  *
  */
 
-#ifndef DIKJSTRA_H
-#define DIKJSTRA_H
+///@cond DOXYGEN_HIDDEN
+#ifndef DIKJSTRA_TOOL_H
+#define DIKJSTRA_TOOL_H
 #include <vector>
 #include <set>
 #include <climits>
+#include <functional>
 #include <tulip/Graph.h>
 #include <tulip/Vector.h>
 #include <tulip/LayoutProperty.h>
@@ -29,28 +31,27 @@
 #include <tulip/StaticProperty.h>
 #include <tulip/MutableContainer.h>
 
-#include "../PathAlgorithm.h"
-
 namespace tlp {
 
-class Dikjstra : public PathAlgorithm {
+class Dikjstra {
 public:
   //============================================================
-  void initDikjstra(const tlp::Graph *const graph, const tlp::Graph *const forbiddenNodes,
-                    tlp::node src, EdgeOrientation directed,
-                    const tlp::EdgeStaticProperty<double> &weights, double maxDist,
-                    const std::set<tlp::node> &focus);
+  Dikjstra(const Graph *const graph,
+	   node src,
+	   const EdgeStaticProperty<double> &weights,
+	   NodeStaticProperty<double> &nodeDistance,
+	   std::function<Iterator<edge>* (node)>& getFunc);
   //========================================================
-  bool searchPaths(tlp::node n, tlp::BooleanProperty *result);
+  bool searchPaths(node n, BooleanProperty *result);
   //=========================================================
-  bool searchPath(tlp::node n, tlp::BooleanProperty *result, std::vector<tlp::node> &vNodes);
+  bool searchPath(node n, BooleanProperty *result);
   //=============================================================
 private:
-  void internalSearchPaths(tlp::node n, tlp::BooleanProperty *result);
+  void internalSearchPaths(node n, BooleanProperty *result);
   //=========================================================
   struct DikjstraElement {
-    DikjstraElement(const double dist = DBL_MAX, const tlp::node previous = tlp::node(),
-                    const tlp::node n = tlp::node())
+    DikjstraElement(const double dist = DBL_MAX, const node previous = node(),
+                    const node n = node())
         : dist(dist), previous(previous), n(n) {}
     bool operator==(const DikjstraElement &b) const {
       return n == b.n;
@@ -59,9 +60,9 @@ class Dikjstra : public PathAlgorithm {
       return n != b.n;
     }
     double dist;
-    tlp::node previous;
-    tlp::node n;
-    std::vector<tlp::edge> usedEdge;
+    node previous;
+    node n;
+    std::vector<edge> usedEdge;
   };
 
   struct LessDikjstraElement {
@@ -74,13 +75,11 @@ class Dikjstra : public PathAlgorithm {
     }
   };
 
-  tlp::Graph const *graph;
-  tlp::Graph const *forbiddenNodes;
-  tlp::node src;
-  tlp::MutableContainer<bool> usedEdges;
-
-public:
-  tlp::MutableContainer<double> nodeDistance;
+  Graph const *graph;
+  node src;
+  MutableContainer<bool> usedEdges;
+  NodeStaticProperty<double>& nodeDistance;
 };
 } // namespace tlp
 #endif // DIKJSTRA_H
+///@endcond
diff --git a/library/tulip-core/include/tulip/GraphTools.h b/library/tulip-core/include/tulip/GraphTools.h
index a1cfcb0f7f..f44dffc619 100644
--- a/library/tulip-core/include/tulip/GraphTools.h
+++ b/library/tulip-core/include/tulip/GraphTools.h
@@ -174,6 +174,26 @@ TLP_SCOPE void buildEdgesUniformQuantification(const Graph *graph, const Numeric
  */
 TLP_SCOPE unsigned makeSelectionGraph(const Graph *graph, BooleanProperty *selection,
                                       bool *test = nullptr);
+
+enum ShortestPathType { OnePath = 0, OneDirectedPath = 1 , OneReversedPath = 2,
+			AllPaths = 3, AllDirectedPaths = 4, AllReversedPaths = 5 };
+
+/**
+ * @brief set selection to the shortets paths
+ * @param graph The graph to compute on.
+ * @param src The source node of the paths
+ * @param tgt The target node of the paths
+ * @param pathType The type of path to consider
+ * @param weights A Double property to get the edges weight if weighted paths have to be considered. Can be set to null to select unweighted paths.
+ * @param selection The Boolean property to consider as selection.
+ * @return false if no path exist between the src and tgt nodes; true if not.
+ */
+TLP_SCOPE bool selectShortestPaths(const Graph *const graph,
+				   node src, node tgt,
+				   ShortestPathType pathType,
+				   const DoubleProperty *const weights,
+				   BooleanProperty* selection);
+
 } // namespace tlp
 #endif
 ///@endcond
diff --git a/library/tulip-core/src/CMakeLists.txt b/library/tulip-core/src/CMakeLists.txt
index 36f8d31d10..3b59265dab 100644
--- a/library/tulip-core/src/CMakeLists.txt
+++ b/library/tulip-core/src/CMakeLists.txt
@@ -12,6 +12,7 @@ ConnectedTest.cpp
 ConvexHull.cpp
 DataSet.cpp
 Delaunay.cpp
+Dikjstra.cpp
 DoubleProperty.cpp
 DrawingTools.cpp
 FaceIterator.cpp
diff --git a/library/tulip-core/src/Dikjstra.cpp b/library/tulip-core/src/Dikjstra.cpp
new file mode 100644
index 0000000000..d7ef08538e
--- /dev/null
+++ b/library/tulip-core/src/Dikjstra.cpp
@@ -0,0 +1,218 @@
+/**
+ *
+ * This file is part of Tulip (http://tulip.labri.fr)
+ *
+ * Authors: David Auber and the Tulip development Team
+ * from LaBRI, University of Bordeaux
+ *
+ * Tulip is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Tulip is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ */
+
+#include <tulip/Dikjstra.h>
+#include <tulip/LayoutProperty.h>
+#include <tulip/BooleanProperty.h>
+#include <tulip/GraphTools.h>
+
+using namespace tlp;
+using namespace std;
+
+//============================================================
+Dikjstra::Dikjstra(const Graph *const graph, node src,
+		   const EdgeStaticProperty<double> &weights,
+		   NodeStaticProperty<double> &nd,
+		   std::function<Iterator<edge>* (node)>& getEdges):
+  nodeDistance(nd) {
+  assert(src.isValid());
+  this->graph = graph;
+  usedEdges.setAll(false);
+  this->src = src;
+  set<DikjstraElement *, LessDikjstraElement> dikjstraTable;
+  NodeStaticProperty<DikjstraElement *> mapDik(graph);
+  mapDik.setAll(nullptr);
+
+  unsigned int i = 0;
+  for (auto n : graph->nodes()) {
+    DikjstraElement *tmp;
+    if (n != src)
+      // init all nodes to +inf
+      tmp = new DikjstraElement(DBL_MAX / 2. + 10., node(), n);
+    else
+      // init starting node to 0
+      tmp = new DikjstraElement(0, n, n);
+
+    dikjstraTable.insert(tmp);
+
+    mapDik[i++] = tmp;
+  }
+
+  while (!dikjstraTable.empty()) {
+    // select the first element in the list the one with min value
+    set<DikjstraElement *, LessDikjstraElement>::iterator it = dikjstraTable.begin();
+    DikjstraElement &u = *(*it);
+    dikjstraTable.erase(it);
+
+    edge e;
+
+    Iterator<edge> *iter = getEdges(u.n);
+
+    while (iter->hasNext()) {
+      e = iter->next();
+      node v = graph->opposite(e, u.n);
+      auto dEle = mapDik[v];
+      double eWeight = weights.getEdgeValue(e);
+      assert(eWeight > 0);
+
+      if (fabs((u.dist + eWeight) - dEle->dist) < 1E-9) // path of the same length
+        dEle->usedEdge.push_back(e);
+      else if ((u.dist + eWeight) < dEle->dist) {
+	  // we find a node closer with that path
+	  dEle->usedEdge.clear();
+	  //**********************************************
+	  dikjstraTable.erase(dEle);
+
+	  dEle->dist = u.dist + eWeight;
+	  dEle->previous = u.n;
+	  dEle->usedEdge.push_back(e);
+	  dikjstraTable.insert(dEle);
+	}
+    } delete iter;
+  }
+
+  usedEdges.setAll(false);
+  i = 0;
+  for (auto n : graph->nodes()) {
+    DikjstraElement *dEle = mapDik[i++];
+    nodeDistance[n] = dEle->dist;
+
+    for (auto e : dEle->usedEdge) {
+      usedEdges.set(e.id, true);
+    }
+
+    delete dEle;
+  }
+}
+//=============================================================================
+bool Dikjstra::searchPath(node n, BooleanProperty *result) {
+  bool ok = true;
+
+  while (ok) {
+    result->setNodeValue(n, true);
+    ok = false;
+    Iterator<edge>* it = graph->getInOutEdges(n);
+    while (it->hasNext()) {
+      edge e = it->next();
+      if (!usedEdges.get(e.id))
+        continue; // edge does not belong to the shortest path
+
+      if (result->getEdgeValue(e))
+        continue; // edge already treated
+
+      node tgt = graph->opposite(e, n);
+
+      if (nodeDistance[tgt] >= nodeDistance[n])
+        continue;
+
+      n = tgt;
+      result->setEdgeValue(e, true);
+      ok = true;
+      break;
+    } delete it;
+  }
+
+  if (n != src) {
+#ifndef NDEBUG
+    cout << "Path does not exist !" << endl;
+#endif /* NDEBUG */
+    return false;
+  }
+
+  return true;
+}
+//=======================================================================
+void Dikjstra::internalSearchPaths(node n, BooleanProperty *result) {
+  result->setNodeValue(n, true);
+  for (auto e : graph->getInOutEdges(n)) {
+    if (!usedEdges.get(e.id))
+      continue;
+
+    if (result->getEdgeValue(e))
+      continue;
+
+    node tgt = graph->opposite(e, n);
+
+    if (nodeDistance[tgt] >= nodeDistance[n])
+      continue;
+
+    result->setEdgeValue(e, true);
+    if (!result->getNodeValue(tgt))
+      internalSearchPaths(tgt, result);
+  }
+}
+//========================================
+bool Dikjstra::searchPaths(node n, BooleanProperty *result) {
+  internalSearchPaths(n, result);
+  return result->getNodeValue(src);
+}
+
+//========================================
+#define SMALLEST_WEIGHT 1.E-6
+
+bool selectShortestPaths(const Graph *const graph,
+			 node src, node tgt,
+			 ShortestPathType pathType,
+			 const DoubleProperty *const weights,
+			 BooleanProperty *result) {
+  std::function<Iterator<edge>* (node)> getOutEdges =
+    [&](node un) { return graph->getOutEdges(un); };
+  std::function<Iterator<edge>* (node)> getInOutEdges =
+    [&](node un) { return graph->getInOutEdges(un); };
+  std::function<Iterator<edge>* (node)> getInEdges =
+    [&](node un) { return graph->getInEdges(un); };
+
+  std::function<Iterator<edge>* (node)> getEdges;
+  switch (pathType) {
+  case ShortestPathType::OnePath:
+  case ShortestPathType::AllPaths:
+    getEdges = getInOutEdges;
+    break;
+  case ShortestPathType::OneDirectedPath:
+  case ShortestPathType::AllDirectedPaths:
+    getEdges = getOutEdges;
+    break;
+  case ShortestPathType::OneReversedPath:
+  case ShortestPathType::AllReversedPaths:
+    getEdges = getInEdges;
+    break;
+  }
+
+  EdgeStaticProperty<double> eWeights(graph);
+  if (!weights) {
+    eWeights.setAll(SMALLEST_WEIGHT);
+  } else {
+    auto fn = [&](edge e, unsigned int i) {
+      double val(weights->getEdgeValue(e));
+
+      eWeights[i] = val ? val : SMALLEST_WEIGHT;
+    };
+    TLP_PARALLEL_MAP_EDGES_AND_INDICES(graph, fn);
+  }
+
+  NodeStaticProperty<double> nodeDistance(graph);
+  Dikjstra dikjstra(graph, src, eWeights, nodeDistance, getEdges);
+
+  result->setAllNodeValue(false);
+  result->setAllEdgeValue(false);
+
+  if (uint(pathType) < ShortestPathType::AllPaths)
+    return dikjstra.searchPath(tgt, result);
+  return dikjstra.searchPaths(tgt, result);
+}
diff --git a/library/tulip-core/src/GraphTools.cpp b/library/tulip-core/src/GraphTools.cpp
index a98d1aaa77..ce2e18fca5 100644
--- a/library/tulip-core/src/GraphTools.cpp
+++ b/library/tulip-core/src/GraphTools.cpp
@@ -31,6 +31,7 @@
 #include <tulip/Ordering.h>
 #include <tulip/PlanarConMap.h>
 #include <tulip/GraphParallelTools.h>
+#include <tulip/Dikjstra.h>
 
 #include <queue>
 #include <stack>
@@ -713,4 +714,55 @@ unsigned makeSelectionGraph(const Graph *graph, BooleanProperty *selection, bool
 
   return added;
 }
+
+#define SMALLEST_WEIGHT 1.E-6
+
+bool selectShortestPaths(const Graph *const graph,
+			 node src, node tgt,
+			 ShortestPathType pathType,
+			 const DoubleProperty *const weights,
+			 BooleanProperty *result) {
+  std::function<Iterator<edge>* (node)> getOutEdges =
+    [&](node un) { return graph->getOutEdges(un); };
+  std::function<Iterator<edge>* (node)> getInOutEdges =
+    [&](node un) { return graph->getInOutEdges(un); };
+  std::function<Iterator<edge>* (node)> getInEdges =
+    [&](node un) { return graph->getInEdges(un); };
+
+  std::function<Iterator<edge>* (node)> getEdges;
+  switch (pathType) {
+  case ShortestPathType::OnePath:
+  case ShortestPathType::AllPaths:
+    getEdges = getInOutEdges;
+    break;
+  case ShortestPathType::OneDirectedPath:
+  case ShortestPathType::AllDirectedPaths:
+    getEdges = getOutEdges;
+    break;
+  case ShortestPathType::OneReversedPath:
+  case ShortestPathType::AllReversedPaths:
+    getEdges = getInEdges;
+    break;
+  }
+
+  EdgeStaticProperty<double> eWeights(graph);
+  if (!weights) {
+    eWeights.setAll(SMALLEST_WEIGHT);
+  } else {
+    auto fn = [&](edge e, unsigned int i) {
+      double val(weights->getEdgeValue(e));
+
+      eWeights[i] = val ? val : SMALLEST_WEIGHT;
+    };
+    TLP_PARALLEL_MAP_EDGES_AND_INDICES(graph, fn);
+  }
+
+  NodeStaticProperty<double> nodeDistance(graph);
+  Dikjstra dikjstra(graph, src, eWeights, nodeDistance, getEdges);
+
+  if (uint(pathType) < ShortestPathType::AllPaths)
+    return dikjstra.searchPath(tgt, result);
+  return dikjstra.searchPaths(tgt, result);
+}
+
 } // namespace tlp
diff --git a/plugins/interactor/PathFinder/CMakeLists.txt b/plugins/interactor/PathFinder/CMakeLists.txt
index ea9025564f..9fc421593d 100644
--- a/plugins/interactor/PathFinder/CMakeLists.txt
+++ b/plugins/interactor/PathFinder/CMakeLists.txt
@@ -8,7 +8,6 @@ SET(LIB_SRCS
     PathFinderTools.cpp
     PathFinding/PathAlgorithm.cpp
     PathFinding/DFS/DFS.cpp
-    PathFinding/Dikjstra/Dikjstra.cpp
     highlighters/EnclosingCircleHighlighter.cpp
     highlighters/PathHighlighter.cpp
     highlighters/ZoomAndPanHighlighter.cpp
diff --git a/plugins/interactor/PathFinder/PathFinder.cpp b/plugins/interactor/PathFinder/PathFinder.cpp
index 369354b7e1..45fefce6f7 100644
--- a/plugins/interactor/PathFinder/PathFinder.cpp
+++ b/plugins/interactor/PathFinder/PathFinder.cpp
@@ -50,8 +50,8 @@ PathFinder::PathFinder(const tlp::PluginContext *)
       tolerance(DEFAULT_TOLERANCE), _configurationWidget(nullptr), highlightersListWidget(nullptr),
       configureHighlighterBtn(nullptr) {
 
-  edgeOrientationLabels[PathAlgorithm::Oriented] = "Consider edges as oriented";
-  edgeOrientationLabels[PathAlgorithm::NonOriented] = "Consider edges as non-oriented";
+  edgeOrientationLabels[PathAlgorithm::Directed] = "Consider edges as directed";
+  edgeOrientationLabels[PathAlgorithm::Undirected] = "Consider edges as undirected";
   edgeOrientationLabels[PathAlgorithm::Reversed] = "Consider edges as reversed";
   pathsTypesLabels[PathAlgorithm::AllPaths] = "Select all paths";
   pathsTypesLabels[PathAlgorithm::AllShortest] = "Select all shortest paths";
@@ -174,9 +174,7 @@ void PathFinder::setPathsType(const QString &pathType) {
   }
 
   bool disabled(pathsTypes != PathAlgorithm::AllPaths);
-  _configurationWidget->toleranceCheckDisabled(disabled);
-  _configurationWidget->toleranceSpinDisabled(disabled);
-  _configurationWidget->toleranceLabelDisabled(disabled);
+  _configurationWidget->toleranceDisabled(disabled);
 }
 
 double PathFinder::getTolerance() {
diff --git a/plugins/interactor/PathFinder/PathFinder.h b/plugins/interactor/PathFinder/PathFinder.h
index 67aacb7879..9b7af3ee7e 100644
--- a/plugins/interactor/PathFinder/PathFinder.h
+++ b/plugins/interactor/PathFinder/PathFinder.h
@@ -26,7 +26,7 @@
 #include "PathFinding/PathAlgorithm.h"
 
 #define NO_METRIC "None"
-#define DEFAULT_ORIENTATION PathAlgorithm::NonOriented
+#define DEFAULT_ORIENTATION PathAlgorithm::Undirected
 #define DEFAULT_PATHS_TYPE PathAlgorithm::OneShortest
 #define DEFAULT_TOLERANCE 100
 #define DEFAULT_TOLERANCE_ACTIVATION false
diff --git a/plugins/interactor/PathFinder/PathFinderConfigurationWidget.cpp b/plugins/interactor/PathFinder/PathFinderConfigurationWidget.cpp
index 0a8259b64e..cc72e8385e 100644
--- a/plugins/interactor/PathFinder/PathFinderConfigurationWidget.cpp
+++ b/plugins/interactor/PathFinder/PathFinderConfigurationWidget.cpp
@@ -85,14 +85,9 @@ void PathFinderConfigurationWidget::addbottomWidget(QWidget *w) {
   _ui->bottomArea->addWidget(w, 0, Qt::AlignLeft);
 }
 
-void PathFinderConfigurationWidget::toleranceCheckDisabled(const bool disabled) {
+void PathFinderConfigurationWidget::toleranceDisabled(const bool disabled) {
   _ui->toleranceCheck->setDisabled(disabled);
-}
-
-void PathFinderConfigurationWidget::toleranceSpinDisabled(const bool disabled) {
   _ui->toleranceSpin->setDisabled(disabled);
-}
-
-void PathFinderConfigurationWidget::toleranceLabelDisabled(const bool disabled) {
   _ui->toleranceLabel->setDisabled(disabled);
+  _ui->tolerancePercentLabel->setDisabled(disabled);
 }
diff --git a/plugins/interactor/PathFinder/PathFinderConfigurationWidget.h b/plugins/interactor/PathFinder/PathFinderConfigurationWidget.h
index 60c0f07b0c..30fc157e64 100644
--- a/plugins/interactor/PathFinder/PathFinderConfigurationWidget.h
+++ b/plugins/interactor/PathFinder/PathFinderConfigurationWidget.h
@@ -51,9 +51,7 @@ class PathFinderConfigurationWidget : public QWidget {
   void setToleranceSpinValue(const int val);
   void highlightersLabelDisabled(const bool disable);
   void addbottomWidget(QWidget *w);
-  void toleranceCheckDisabled(const bool disabled);
-  void toleranceSpinDisabled(const bool disabled);
-  void toleranceLabelDisabled(const bool disabled);
+  void toleranceDisabled(const bool disabled);
 
 signals:
   void setWeightMetric(const QString &);
diff --git a/plugins/interactor/PathFinder/PathFinding/DFS/DFS.cpp b/plugins/interactor/PathFinder/PathFinding/DFS/DFS.cpp
index c0acd13641..77cab2e3a7 100644
--- a/plugins/interactor/PathFinder/PathFinding/DFS/DFS.cpp
+++ b/plugins/interactor/PathFinder/PathFinding/DFS/DFS.cpp
@@ -26,25 +26,28 @@
 using namespace tlp;
 using namespace std;
 
-DFS::DFS(Graph *graph, BooleanProperty *result, DoubleProperty *dists, node tgt,
+DFS::DFS(Graph *graph, BooleanProperty *result, node tgt,
          const EdgeStaticProperty<double> &eWeights, EdgeOrientation edgesOrientation,
          double maxDist)
-    : graph(graph), result(result), dists(dists), tgt(tgt), weights(eWeights), currentDist(0),
+    : graph(graph), result(result), tgt(tgt), weights(eWeights), currentDist(0),
       edgesOrientation(edgesOrientation), maxDist(maxDist) {
 #ifndef NDEBUG
   assert(graph->getRoot() == result->getGraph()->getRoot());
 #endif /* NDEBUG */
-  dists->setAllNodeValue(DBL_MAX);
-  visitable = new BooleanProperty(graph);
-  visitable->setAllNodeValue(true);
-  visitable->setAllEdgeValue(true);
 }
 
-DFS::~DFS() {
-  delete visitable;
+bool DFS::searchPaths(node src) {
+  DoubleProperty dists(result->getGraph());
+  dists.setAllNodeValue(DBL_MAX);
+
+  BooleanProperty visitable(graph);
+  visitable.setAllNodeValue(true);
+
+  return computeSearchPaths(src, &visitable, &dists);
 }
 
-bool DFS::searchPaths(node src) {
+bool DFS::computeSearchPaths(node src, BooleanProperty *visitable,
+			     DoubleProperty *dists) {
   if (!visitable->getNodeValue(src))
     return false;
 
@@ -78,17 +81,17 @@ bool DFS::searchPaths(node src) {
     return true;
   }
 
-  bool result = false;
+  bool res = false;
   visitable->setNodeValue(src, false);
 
   Iterator<edge> *edgeIt = nullptr;
 
   switch (edgesOrientation) {
-  case NonOriented:
+  case Undirected:
     edgeIt = graph->getInOutEdges(src);
     break;
 
-  case Oriented:
+  case Directed:
     edgeIt = graph->getOutEdges(src);
     break;
 
@@ -100,11 +103,11 @@ bool DFS::searchPaths(node src) {
   for (auto e : edgeIt) {
     currentDist += weights.getEdgeValue(e);
     path.push_back(e);
-    result |= searchPaths(graph->opposite(e, src));
+    res |= computeSearchPaths(graph->opposite(e, src), visitable, dists);
     path.pop_back();
     currentDist -= weights.getEdgeValue(e);
   }
 
   visitable->setNodeValue(src, true);
-  return result;
+  return res;
 }
diff --git a/plugins/interactor/PathFinder/PathFinding/DFS/DFS.h b/plugins/interactor/PathFinder/PathFinding/DFS/DFS.h
index 2801de37f2..605bf411f1 100644
--- a/plugins/interactor/PathFinder/PathFinding/DFS/DFS.h
+++ b/plugins/interactor/PathFinder/PathFinding/DFS/DFS.h
@@ -50,12 +50,10 @@ class DFS : public PathAlgorithm {
    * @param maxDist The maximal distance the algorithm can go from the source node before dropping
    * the search (DBL_MAX by default)
    */
-  DFS(tlp::Graph *graph, tlp::BooleanProperty *result, tlp::DoubleProperty *dists, tlp::node tgt,
+  DFS(tlp::Graph *graph, tlp::BooleanProperty *result, tlp::node tgt,
       const tlp::EdgeStaticProperty<double> &weights, EdgeOrientation edgesOrientation,
       double maxDist = DBL_MAX);
 
-  ~DFS();
-
   /**
    * Compute the path between the source node and the target node. Caution ! This method is
    * recursive and could cause a stack overflow on big graphs.
@@ -67,14 +65,14 @@ class DFS : public PathAlgorithm {
 private:
   tlp::Graph *graph;
   tlp::BooleanProperty *result;
-  tlp::DoubleProperty *dists;
-  tlp::BooleanProperty *visitable;
   tlp::node tgt;
   const tlp::EdgeStaticProperty<double> &weights;
   std::vector<tlp::edge> path;
   double currentDist;
   EdgeOrientation edgesOrientation;
   double maxDist;
+
+  bool computeSearchPaths(tlp::node src, tlp::BooleanProperty *visitable, tlp::DoubleProperty *dists);
 };
 } // namespace tlp
 #endif /* DFS_H_ */
diff --git a/plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.cpp b/plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.cpp
deleted file mode 100644
index 14974ad578..0000000000
--- a/plugins/interactor/PathFinder/PathFinding/Dikjstra/Dikjstra.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/**
- *
- * This file is part of Tulip (http://tulip.labri.fr)
- *
- * Authors: David Auber and the Tulip development Team
- * from LaBRI, University of Bordeaux
- *
- * Tulip is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Tulip is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- */
-
-#include "Dikjstra.h"
-#include <tulip/LayoutProperty.h>
-#include <tulip/BooleanProperty.h>
-
-using namespace tlp;
-using namespace std;
-
-//============================================================
-void Dikjstra::initDikjstra(const tlp::Graph *const graph, const tlp::Graph *const forbiddenNodes,
-                            tlp::node src, EdgeOrientation directed,
-                            const tlp::EdgeStaticProperty<double> &weights, double,
-                            const set<node> &focus) {
-  assert(src.isValid());
-  this->graph = graph;
-  this->forbiddenNodes = forbiddenNodes;
-  usedEdges.setAll(false);
-  this->src = src;
-  set<DikjstraElement *, LessDikjstraElement> dikjstraTable;
-  set<DikjstraElement *, LessDikjstraElement> focusTable;
-  MutableContainer<DikjstraElement *> mapDik;
-  mapDik.setAll(nullptr);
-
-  for (auto n : graph->nodes()) {
-    if (n != src) { // init all nodes to +inf
-      DikjstraElement *tmp = new DikjstraElement(DBL_MAX / 2. + 10., node(), n);
-      dikjstraTable.insert(tmp);
-
-      if (focus.find(n) != focus.end())
-        focusTable.insert(tmp);
-
-      mapDik.set(n.id, tmp);
-    } else { // init starting node to 0
-      DikjstraElement *tmp = new DikjstraElement(0, n, n);
-      dikjstraTable.insert(tmp);
-      mapDik.set(n.id, tmp);
-    }
-  }
-
-  nodeDistance.setAll(DBL_MAX);
-  nodeDistance.set(src.id, 0);
-
-  while (!dikjstraTable.empty()) {
-    // select the first element in the list the one with min value
-    set<DikjstraElement *, LessDikjstraElement>::iterator it = dikjstraTable.begin();
-    DikjstraElement &u = *(*it);
-    dikjstraTable.erase(it);
-
-    if (!focusTable.empty()) {
-      set<DikjstraElement *, LessDikjstraElement>::reverse_iterator it = focusTable.rbegin();
-      // set<DikjstraElement *>::iterator it2 = focusTable.begin();
-      double maxDist = (*it)->dist;
-
-      if (u.dist > maxDist)
-        break;
-
-      /*
-       if (fabs(u.dist - maxDist) > 1E-9) {
-          if (u.dist > maxDist) {
-              assert(maxDist < (DBL_MAX/2.));
-              break;
-          }
-      }
-      */
-      // if ((u.dist > maxDist) break;
-    }
-
-    if (forbiddenNodes != nullptr)
-      if (forbiddenNodes->isElement(u.n) && u.n != this->src)
-        continue;
-
-    edge e;
-
-    Iterator<edge> *iter = nullptr;
-
-    switch (directed) {
-    case Oriented:
-      iter = graph->getOutEdges(u.n);
-      break;
-
-    case NonOriented:
-      iter = graph->getInOutEdges(u.n);
-      break;
-
-    case Reversed:
-      iter = graph->getInEdges(u.n);
-      break;
-    }
-
-    for (auto e : iter) {
-      node v = graph->opposite(e, u.n);
-      DikjstraElement &dEle = *mapDik.get(v.id);
-      double eWeight = weights.getEdgeValue(e);
-      assert(eWeight > 0);
-
-      /*
-                  if (DBL_MAX - u.dist <  eWeight)
-              cerr << __PRETTY_FUNCTION__ << "at line : " << __LINE__ << " : Double overflow" <<
-         endl;
-            if (DBL_MAX - fabs((u.dist + eWeight)) < dEle.dist)
-              cerr << __PRETTY_FUNCTION__ << "at line : " << __LINE__ << " : Double overflow" <<
-         endl;
-                    */
-      if (fabs((u.dist + eWeight) - dEle.dist) < 1E-9) // path of the same length
-        dEle.usedEdge.push_back(e);
-      else
-
-          // we find a node closer with that path
-          if ((u.dist + eWeight) < dEle.dist) {
-        dEle.usedEdge.clear();
-        //**********************************************
-        dikjstraTable.erase(&dEle);
-
-        if (focus.find(dEle.n) != focus.end()) {
-          focusTable.erase(&dEle);
-        }
-
-        dEle.dist = u.dist + eWeight;
-        /*
-        if (DBL_MAX - u.dist <  eWeight)
-        cerr << __PRETTY_FUNCTION__ << "at line : " << __LINE__ << " : Double overflow" << endl;
-        */
-        dEle.previous = u.n;
-        dEle.usedEdge.push_back(e);
-        dikjstraTable.insert(&dEle);
-
-        if (focus.find(dEle.n) != focus.end()) {
-          focusTable.insert(&dEle);
-        }
-      }
-    }
-  }
-
-  usedEdges.setAll(false);
-  for (auto n : graph->nodes()) {
-    DikjstraElement *dEle = mapDik.get(n.id);
-    nodeDistance.set(n.id, dEle->dist);
-
-    for (unsigned int i = 0; i < dEle->usedEdge.size(); ++i) {
-      usedEdges.set(dEle->usedEdge[i].id, true);
-    }
-
-    delete dEle;
-  }
-}
-//=======================================================================
-void Dikjstra::internalSearchPaths(node n, BooleanProperty *result) {
-  if (result->getNodeValue(n))
-    return;
-
-  result->setNodeValue(n, true);
-  for (auto e : graph->getInOutEdges(n)) {
-    if (!usedEdges.get(e.id))
-      continue;
-
-    if (result->getEdgeValue(e))
-      continue;
-
-    node tgt = graph->opposite(e, n);
-
-    if (nodeDistance.get(tgt.id) >= nodeDistance.get(n.id))
-      continue;
-
-    result->setEdgeValue(e, true);
-    searchPaths(tgt, result);
-  }
-}
-//=============================================================================
-bool Dikjstra::searchPath(node n, BooleanProperty *result, vector<node> &vNodes) {
-  result->setAllNodeValue(false);
-  result->setAllEdgeValue(false);
-  bool ok = true;
-
-  while (ok) {
-    result->setNodeValue(n, true);
-    vNodes.push_back(n);
-    ok = false;
-    edge validEdge;
-    for (auto e : graph->getInOutEdges(n)) {
-      if (!usedEdges.get(e.id))
-        continue; // edge does not belong to the shortest path
-
-      if (result->getEdgeValue(e))
-        continue; // edge already treated
-
-      node tgt = graph->opposite(e, n);
-
-      if (nodeDistance.get(tgt.id) >= nodeDistance.get(n.id))
-        continue;
-
-      validEdge = e;
-    }
-
-    if (validEdge.isValid()) {
-      ok = true;
-      n = graph->opposite(validEdge, n);
-      result->setEdgeValue(validEdge, true);
-    }
-  }
-
-  if (n != src) {
-#ifndef NDEBUG
-    cout << "Path does not exist !" << endl;
-#endif /* NDEBUG */
-    return false;
-  }
-
-  return true;
-}
-//========================================
-bool Dikjstra::searchPaths(tlp::node n, tlp::BooleanProperty *result) {
-  internalSearchPaths(n, result);
-  return result->getNodeValue(src);
-}
diff --git a/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.cpp b/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.cpp
index ec14b6ecbb..7faf37264c 100644
--- a/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.cpp
+++ b/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.cpp
@@ -24,8 +24,8 @@
 #include <tulip/MutableContainer.h>
 #include <tulip/Graph.h>
 #include <tulip/GraphParallelTools.h>
+#include <tulip/GraphTools.h>
 
-#include "Dikjstra/Dikjstra.h"
 #include "DFS/DFS.h"
 
 #define SMALLEST_WEIGHT 1.E-6
@@ -59,60 +59,66 @@ bool PathAlgorithm::computePath(Graph *graph, PathType pathType, EdgeOrientation
   assert(src != tgt);
 #endif /* NDEBUG */
 
-  // We always compute Dikjstra as it is used in the all path computation too
-  EdgeStaticProperty<double> eWeights(graph);
-
-  if (!weights) {
-    eWeights.setAll(SMALLEST_WEIGHT);
+  bool retVal = false;
+  tlp::ShortestPathType spt;
+
+  if (pathType == AllShortest) {
+    switch (edgesOrientation) {
+    case Directed:
+      spt = ShortestPathType::AllDirectedPaths;
+      break;
+    case Undirected:
+      spt = ShortestPathType::AllPaths;
+      break;
+    case Reversed:
+    default:
+      spt = ShortestPathType::AllReversedPaths;
+    }
   } else {
-    auto fn = [&](edge e, unsigned int i) {
-      double val(weights->getEdgeValue(e));
-
-      eWeights[i] = val ? val : SMALLEST_WEIGHT;
-    };
-    TLP_PARALLEL_MAP_EDGES_AND_INDICES(graph, fn);
+    switch (edgesOrientation) {
+    case Directed:
+      spt = ShortestPathType::OneDirectedPath;
+      break;
+    case Undirected:
+      spt = ShortestPathType::OnePath;
+      break;
+    case Reversed:
+    default:
+      spt = ShortestPathType::OneReversedPath;
+    }
   }
+  retVal = selectShortestPaths(graph, src, tgt, spt, weights, result);
+  if (pathType == AllPaths && retVal) {
+    EdgeStaticProperty<double> eWeights(graph);
+
+    if (!weights) {
+      eWeights.setAll(SMALLEST_WEIGHT);
+    } else {
+      auto fn = [&](edge e, unsigned int i) {
+	double val(weights->getEdgeValue(e));
+
+	eWeights[i] = val ? val : SMALLEST_WEIGHT;
+      };
+      TLP_PARALLEL_MAP_EDGES_AND_INDICES(graph, fn);
+    }
 
-  set<node> focus;
-  vector<node> vNodes;
-  Dikjstra dikjstra;
-  dikjstra.initDikjstra(graph, nullptr, src, edgesOrientation, eWeights, 0, focus);
-
-  bool retVal = false;
+    double pathLength;
 
-  switch (pathType) {
-  case AllShortest:
-    retVal = dikjstra.searchPaths(tgt, result);
-    break;
-
-  case OneShortest:
-    retVal = dikjstra.searchPath(tgt, result, vNodes);
-    break;
-
-  case AllPaths:
-    retVal = dikjstra.searchPath(tgt, result, vNodes);
-
-    if (retVal) {
-      double pathLength;
-
-      if (tolerance == DBL_MAX)
-        pathLength = DBL_MAX;
-      else {
-        pathLength = computePathLength(result, eWeights);
-        pathLength *= tolerance;
-      }
-
-      if (tolerance > 1) { // We only compute the other paths if the tolerance is greater than 1.
-                           // Meaning that the user doesn't want only the shortest path.
-        result->setAllNodeValue(false);
-        result->setAllEdgeValue(false);
-        DoubleProperty dists(result->getGraph());
-        DFS d(graph, result, &dists, tgt, eWeights, edgesOrientation, pathLength);
-        retVal = d.searchPaths(src);
-      }
+    if (tolerance == DBL_MAX)
+      pathLength = DBL_MAX;
+    else {
+      pathLength = computePathLength(result, eWeights);
+      pathLength *= tolerance;
     }
 
-    break;
+    if (tolerance > 1) {
+      // We only compute the other paths if the tolerance is greater than 1.
+      // Meaning that the user doesn't want only the shortest path.
+      result->setAllNodeValue(false);
+      result->setAllEdgeValue(false);
+      DFS d(graph, result, tgt, eWeights, edgesOrientation, pathLength);
+      retVal = d.searchPaths(src);
+    }
   }
   return retVal;
 }
diff --git a/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.h b/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.h
index e87f2226fa..4593e6915a 100644
--- a/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.h
+++ b/plugins/interactor/PathFinder/PathFinding/PathAlgorithm.h
@@ -36,10 +36,10 @@ class Graph;
 class PathAlgorithm {
 public:
   /**
-   * By default, Tulip works on oriented edges. This behavior can be overloaded by forcing the edges
-   * to be Oriented, non oriented or reversed.
+   * By default, Tulip works on directed edges. This behavior can be overloaded by forcing the edges
+   * to be directed, undirected or reversed.
    */
-  enum EdgeOrientation { Oriented, NonOriented, Reversed };
+  enum EdgeOrientation { Directed, Undirected, Reversed };
 
   /**
    * A path algorithm can look for only one (shortest) path, all the shortest paths or all the
@@ -61,7 +61,6 @@ class PathAlgorithm {
    *
    * @see PathType
    * @see EdgeOrientation
-   * @see Dikjstra
    * @see DFS
    */
   static bool computePath(tlp::Graph *graph, PathType pathType, EdgeOrientation edgesOrientation,
diff --git a/plugins/interactor/PathFinder/designer/PathFinderConfiguration.ui b/plugins/interactor/PathFinder/designer/PathFinderConfiguration.ui
index 95c401a76a..1209a504c4 100644
--- a/plugins/interactor/PathFinder/designer/PathFinderConfiguration.ui
+++ b/plugins/interactor/PathFinder/designer/PathFinderConfiguration.ui
@@ -168,6 +168,9 @@ p, li { white-space: pre-wrap; }
      </property>
      <item>
       <widget class="QCheckBox" name="toleranceCheck">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
        <property name="text">
         <string>Max path length:</string>
        </property>
@@ -175,6 +178,9 @@ p, li { white-space: pre-wrap; }
      </item>
      <item>
       <widget class="QSpinBox" name="toleranceSpin">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
        <property name="minimum">
         <number>100</number>
        </property>
@@ -187,9 +193,12 @@ p, li { white-space: pre-wrap; }
       </widget>
      </item>
      <item>
-      <widget class="QLabel" name="label_6">
+      <widget class="QLabel" name="tolerancePercentLabel">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
        <property name="text">
-        <string>%</string>
+        <string>% of the shortest path length</string>
        </property>
       </widget>
      </item>
diff --git a/tests/gui/interactor_path_finder.tlp b/tests/gui/interactor_path_finder.tlp
index 3357722a49..36f24513c8 100644
--- a/tests/gui/interactor_path_finder.tlp
+++ b/tests/gui/interactor_path_finder.tlp
@@ -1,5 +1,5 @@
 (tlp "2.3"
-(date "05-18-2018")
+(date "11-30-2018")
 (comments "This file was generated by Tulip.")
 (nb_nodes 200)
 ;(nodes <node_id> <node_id> ...)
@@ -895,22 +895,22 @@
 )
 (property  0 color "viewColor"
 (default "(255,0,0,255)" "(0,0,0,255)")
+(node 4 "(85,170,255,255)")
 (node 11 "(85,170,255,255)")
+(node 16 "(85,170,255,255)")
+(node 24 "(85,170,255,255)")
+(node 26 "(85,170,255,255)")
+(node 29 "(85,170,255,255)")
+(node 33 "(85,170,255,255)")
 (node 45 "(85,170,255,255)")
-(node 56 "(85,170,255,255)")
-(node 77 "(85,170,255,255)")
+(node 51 "(85,170,255,255)")
 (node 80 "(85,170,255,255)")
-(node 116 "(85,170,255,255)")
-(node 119 "(85,170,255,255)")
-(node 125 "(85,170,255,255)")
+(node 89 "(85,170,255,255)")
+(node 114 "(85,170,255,255)")
 (node 131 "(85,170,255,255)")
 (node 133 "(85,170,255,255)")
-(node 146 "(85,170,255,255)")
+(node 136 "(85,170,255,255)")
 (node 161 "(85,170,255,255)")
-(node 182 "(85,170,255,255)")
-(node 193 "(85,170,255,255)")
-(node 195 "(85,170,255,255)")
-(node 198 "(85,170,255,255)")
 )
 (property  0 string "viewFont"
 (default "TulipBitmapDir/font.ttf" "TulipBitmapDir/font.ttf")