My TraversalDescription cannot be used to find more than 1 path because of default Uniqueness.NODE_GLOBAL
: once discovered, the end node will never be visited again.
So, the 1-st step is to do:
td = td.uniqueness(Uniqueness.NODE_PATH);
But now we don't have a stop condition and traversal returns not only shortest paths.
2-nd step is to add path evaluator that brings a stop condition:
class EndNodeAndNotDeeperEvaluator implements Evaluator
{
int depth = Integer.MAX_VALUE;
Node endNode;
public EndNodeAndNotDeeperEvaluator(Node node) {
endNode = node;
}
@Override
public Evaluation evaluate(Path path) {
if (path.length() > depth)
return Evaluation.EXCLUDE_AND_PRUNE;
if (path.endNode().equals(endNode)) {
depth = path.length();
return Evaluation.INCLUDE_AND_PRUNE;
}
return Evaluation.EXCLUDE_AND_CONTINUE;
}
}
td = td.evaluator(new EndNodeAndNotDeeperEvaluator(endNode));
Now it works! ...for short paths (length < 10)
But for more long paths it does not give any result, but gives OutOfMemoryException.
This is because a lot of obviously not shortest paths are being investigated.
3-rd step: We need to make sure that each intermediate node is not encountered at the previous levels:
public class EndNodeAndNotDeeperEvaluator implements Evaluator
{
private Node endNode;
private Map<Long,Integer> nodeDepths = new HashMap(100000);
public EndNodeAndNotDeeperEvaluator(Node node) {
endNode = node;
}
@Override
public Evaluation evaluate(Path path) {
Node pEndNode = path.endNode();
Integer nodeDepth = nodeDepths.get(pEndNode.getId());
if (nodeDepth == null) {
nodeDepths.put(pEndNode.getId(), path.length());
}
else if (path.length() > nodeDepth) {
return Evaluation.EXCLUDE_AND_PRUNE;
}
if (pEndNode.equals(endNode)) {
//System.err.println(" map.size="+nodeDepths.size());
return Evaluation.INCLUDE_AND_PRUNE;
}
return Evaluation.EXCLUDE_AND_CONTINUE;
}
}
And now it works for all shortest paths that I have.
But not very quickly... For longest paths (length=81) it takes about 6700ms...
While the usual traversal with Uniqueness.NODE_GLOBAL
takes 550ms (finds only first path);
And the built in GraphAlgoFactory.shortestPath(...).findAllPaths(...)
takes 90ms!