Skip to content

Commit

Permalink
plugins/metric/LeafMetric: Simplify implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
anlambert committed Nov 28, 2024
1 parent d0db946 commit 617d99f
Showing 1 changed file with 11 additions and 92 deletions.
103 changes: 11 additions & 92 deletions plugins/metric/LeafMetric.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2019-2020 The Talipot developers
* Copyright (C) 2019-2024 The Talipot developers
*
* Talipot is a fork of Tulip, created by David Auber
* and the Tulip development Team from LaBRI, University of Bordeaux
Expand All @@ -14,6 +14,7 @@
#include <stack>

#include <talipot/AcyclicTest.h>
#include <talipot/GraphTools.h>

#include "LeafMetric.h"

Expand All @@ -24,104 +25,22 @@ using namespace tlp;

//=======================================================================
LeafMetric::LeafMetric(const tlp::PluginContext *context) : DoubleAlgorithm(context) {}

// structure below is used to implement dfs loop
struct dfsLeafStruct {
node current;
Iterator<node> *outNodes;
double res;

dfsLeafStruct(node n, Iterator<node> *nodes) : current(n), outNodes(nodes), res(0.0) {}
};
//=======================================================================
// original recursive algorithm
/*double LeafMetric::getNodeValue(const tlp::node n) {
if (result->getNodeValue(n) != 0)
return result->getNodeValue(n);
double res=0;
for (auto n : graph->getOutNodes(n))
res += getNodeValue(n);
if (res==0) res=1.0;
result->setNodeValue(n, res);
return res;
}*/
//=======================================================================
double LeafMetric::getNodeValue(tlp::node current) {
double value = result->getNodeValue(current);

if (value != 0.0) {
return value;
}

// dfs loop
stack<dfsLeafStruct> dfsLevels;
Iterator<node> *outNodes = graph->getOutNodes(current);
dfsLeafStruct dfsParams(current, outNodes);
double res = 0.0;
dfsLevels.push(dfsParams);

while (!dfsLevels.empty()) {
while (outNodes->hasNext()) {
node neighbour = outNodes->next();
value = result->getNodeValue(neighbour);

// compute res
if (value != 0.0) {
res += value;
} else {
// store res for current
dfsLevels.top().res = res;
// push new dfsParams on stack
current = dfsParams.current = neighbour;
outNodes = dfsParams.outNodes = graph->getOutNodes(neighbour);
res = dfsParams.res = 0.0;
dfsLevels.push(dfsParams);
// and go deeper
break;
}
}

if (outNodes->hasNext()) {
// new dfsParams has been pushed on stack
continue;
}

// save current res
if (res == 0.0) {
res = 1.0;
}

result->setNodeValue(current, res);
// unstack current dfsParams
delete outNodes;
dfsLevels.pop();

if (dfsLevels.empty()) {
break;
}

// get dfsParams on top of dfsLevels
dfsParams = dfsLevels.top();
current = dfsParams.current;
outNodes = dfsParams.outNodes;
// update new current res if any
dfsParams.res += res;
res = dfsParams.res;
}

return res;
}
//=======================================================================
bool LeafMetric::run() {
result->setAllNodeValue(0);
result->setAllEdgeValue(0);
for (auto n : graph->nodes()) {
result->setNodeValue(n, getNodeValue(n));
for (auto n : reversed(dfs(graph, true))) {
double val = 1.0;
if (graph->outdeg(n) > 0) {
val = iteratorReduce(graph->getOutNodes(n), 0.0, [this](double curVal, const node m) {
return curVal + result->getNodeValue(m);
});
}
result->setNodeValue(n, val);
}
return true;
}
//=======================================================================
bool LeafMetric::check(std::string &erreurMsg) {
bool LeafMetric::check(string &erreurMsg) {
if (!AcyclicTest::isAcyclic(graph)) {
erreurMsg = "The graph must be a acyclic.";
return false;
Expand Down

0 comments on commit 617d99f

Please sign in to comment.