Skip to content

Commit

Permalink
Removed option to find path with exact depth from ShortestPath
Browse files Browse the repository at this point in the history
It does not make sense to find a shortest path with specified length and ExactDepthPathFinder already provides that functionality.
 - Added further testing for ExactDepthPathFinder.
 - GraphAlgoFactory now uses ExactDepthPathFinder instead of ShortsetPath.
 - Fixed ExactDepthPathFinder not handeling neighbouring node (depth 1).

Fixing imports
  • Loading branch information
burqen committed May 19, 2015
1 parent 3132c99 commit 6884c91
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 224 deletions.
Expand Up @@ -23,6 +23,7 @@
import org.neo4j.graphalgo.impl.path.AllPaths;
import org.neo4j.graphalgo.impl.path.AllSimplePaths;
import org.neo4j.graphalgo.impl.path.Dijkstra;
import org.neo4j.graphalgo.impl.path.ExactDepthPathFinder;
import org.neo4j.graphalgo.impl.path.ShortestPath;
import org.neo4j.graphalgo.impl.util.DoubleEvaluator;
import org.neo4j.graphdb.Node;
Expand All @@ -37,7 +38,7 @@
* Static factory methods for the recommended implementations of common
* graph algorithms for Neo4j. The algorithms exposed here are implementations
* which are tested extensively and also scale on bigger graphs.
*
*
* @author Mattias Persson
*/
public abstract class GraphAlgoFactory
Expand Down Expand Up @@ -73,7 +74,7 @@ public static PathFinder<Path> allPaths( PathExpander expander, int maxDepth )
{
return new AllPaths( maxDepth, expander );
}

/**
* Returns an algorithm which can find all simple paths between two
* nodes. These returned paths cannot contain loops (i.e. a node cannot
Expand Down Expand Up @@ -107,7 +108,7 @@ public static PathFinder<Path> allSimplePaths( PathExpander expander,
{
return new AllSimplePaths( maxDepth, expander );
}

/**
* Returns an algorithm which can find all shortest paths (that is paths
* with as short {@link Path#length()} as possible) between two nodes. These
Expand All @@ -130,7 +131,7 @@ public static PathFinder<Path> shortestPath( RelationshipExpander expander, int
* with as short {@link Path#length()} as possible) between two nodes. These
* returned paths cannot contain loops (i.e. a node cannot occur more than
* once in any returned path).
*
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param maxDepth the max {@link Path#length()} returned paths are allowed
Expand All @@ -141,13 +142,13 @@ public static PathFinder<Path> shortestPath( PathExpander expander, int maxDepth
{
return new ShortestPath( maxDepth, expander );
}

/**
* Returns an algorithm which can find all shortest paths (that is paths
* with as short {@link Path#length()} as possible) between two nodes. These
* returned paths cannot contain loops (i.e. a node cannot occur more than
* once in any returned path).
*
*
* @param expander the {@link RelationshipExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param maxDepth the max {@link Path#length()} returned paths are allowed
Expand All @@ -160,13 +161,13 @@ public static PathFinder<Path> shortestPath( RelationshipExpander expander, int
{
return new ShortestPath( maxDepth, expander, maxHitCount );
}

/**
* Returns an algorithm which can find all shortest paths (that is paths
* with as short {@link Path#length()} as possible) between two nodes. These
* returned paths cannot contain loops (i.e. a node cannot occur more than
* once in any returned path).
*
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param maxDepth the max {@link Path#length()} returned paths are allowed
Expand All @@ -179,12 +180,12 @@ public static PathFinder<Path> shortestPath( PathExpander expander, int maxDepth
{
return new ShortestPath( maxDepth, expander, maxHitCount );
}

/**
* Returns an algorithm which can find simple all paths of a certain length
* between two nodes. These returned paths cannot contain loops (i.e. a node
* could not occur more than once in any returned path).
*
*
* @param expander the {@link RelationshipExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param length the {@link Path#length()} returned paths will have, if any
Expand All @@ -193,14 +194,14 @@ public static PathFinder<Path> shortestPath( PathExpander expander, int maxDepth
*/
public static PathFinder<Path> pathsWithLength( RelationshipExpander expander, int length )
{
return new ShortestPath( length, expander, Integer.MAX_VALUE, true );
return new ExactDepthPathFinder( expander, length, Integer.MAX_VALUE, false );
}

/**
* Returns an algorithm which can find simple all paths of a certain length
* between two nodes. These returned paths cannot contain loops (i.e. a node
* could not occur more than once in any returned path).
*
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param length the {@link Path#length()} returned paths will have, if any
Expand All @@ -209,20 +210,20 @@ public static PathFinder<Path> pathsWithLength( RelationshipExpander expander, i
*/
public static PathFinder<Path> pathsWithLength( PathExpander expander, int length )
{
return new ShortestPath( length, expander, Integer.MAX_VALUE, true );
return new ExactDepthPathFinder( expander, length, Integer.MAX_VALUE, false );
}

/**
* Returns a {@link PathFinder} which uses the A* algorithm to find the
* cheapest path between two nodes. The definition of "cheap" is the lowest
* possible cost to get from the start node to the end node, where the cost
* is returned from {@code lengthEvaluator} and {@code estimateEvaluator}.
* These returned paths cannot contain loops (i.e. a node cannot occur more
* than once in any returned path).
*
*
* See http://en.wikipedia.org/wiki/A*_search_algorithm for more
* information.
*
*
* @param expander the {@link RelationshipExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param lengthEvaluator evaluator that can return the cost represented
Expand All @@ -246,10 +247,10 @@ public static PathFinder<WeightedPath> aStar( RelationshipExpander expander,
* is returned from {@code lengthEvaluator} and {@code estimateEvaluator}.
* These returned paths cannot contain loops (i.e. a node cannot occur more
* than once in any returned path).
*
*
* See http://en.wikipedia.org/wiki/A*_search_algorithm for more
* information.
*
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param lengthEvaluator evaluator that can return the cost represented
Expand All @@ -265,18 +266,18 @@ public static PathFinder<WeightedPath> aStar( PathExpander expander,
{
return new AStar( expander, lengthEvaluator, estimateEvaluator );
}

/**
* Returns a {@link PathFinder} which uses the Dijkstra algorithm to find
* the cheapest path between two nodes. The definition of "cheap" is the
* lowest possible cost to get from the start node to the end node, where
* the cost is returned from {@code costEvaluator}. These returned paths
* cannot contain loops (i.e. a node cannot occur more than once in any
* returned path).
*
*
* See http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm for more
* information.
*
*
* @param expander the {@link RelationshipExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param costEvaluator evaluator that can return the cost represented
Expand All @@ -289,18 +290,18 @@ public static PathFinder<WeightedPath> dijkstra( RelationshipExpander expander,
{
return new Dijkstra( expander, costEvaluator );
}

/**
* Returns a {@link PathFinder} which uses the Dijkstra algorithm to find
* the cheapest path between two nodes. The definition of "cheap" is the
* lowest possible cost to get from the start node to the end node, where
* the cost is returned from {@code costEvaluator}. These returned paths
* cannot contain loops (i.e. a node cannot occur more than once in any
* returned path).
*
*
* See http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm for more
* information.
*
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param costEvaluator evaluator that can return the cost represented
Expand All @@ -313,13 +314,13 @@ public static PathFinder<WeightedPath> dijkstra( PathExpander expander,
{
return new Dijkstra( expander, costEvaluator );
}

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link RelationshipExpander} to use for expanding
* {@link Relationship}s for each {@link Node}.
* @param relationshipPropertyRepresentingCost the property to represent cost
Expand All @@ -332,13 +333,13 @@ public static PathFinder<WeightedPath> dijkstra( RelationshipExpander expander,
{
return dijkstra( expander, new DoubleEvaluator( relationshipPropertyRepresentingCost ) );
}

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param relationshipPropertyRepresentingCost the property to represent cost
Expand All @@ -351,13 +352,13 @@ public static PathFinder<WeightedPath> dijkstra( PathExpander expander,
{
return dijkstra( expander, new DoubleEvaluator( relationshipPropertyRepresentingCost ) );
}

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param stateFactory initial state for the traversal branches.
Expand All @@ -373,10 +374,10 @@ public static PathFinder<WeightedPath> dijkstra( PathExpander expander,

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param stateFactory initial state for the traversal branches.
Expand All @@ -389,13 +390,13 @@ public static PathFinder<WeightedPath> dijkstra( PathExpander expander,
{
return new Dijkstra( expander, stateFactory, costEvaluator );
}

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param stateFactory initial state for the traversal branches.
Expand All @@ -412,10 +413,10 @@ public static PathFinder<WeightedPath> dijkstra( PathExpander expander,

/**
* See {@link #dijkstra(RelationshipExpander, CostEvaluator)}.
*
*
* Uses a cost evaluator which uses the supplied property key to
* represent the cost (values of type <bold>double</bold>).
*
* represent the cost (values of type <bold>double</bold>).
*
* @param expander the {@link PathExpander} to use for expanding
* {@link Relationship}s for each {@link Path}.
* @param stateFactory initial state for the traversal branches.
Expand Down
Expand Up @@ -19,13 +19,6 @@
*/
package org.neo4j.graphalgo.impl.path;

import static org.neo4j.graphdb.traversal.Evaluators.atDepth;
import static org.neo4j.graphdb.traversal.Evaluators.toDepth;
import static org.neo4j.kernel.StandardExpander.toPathExpander;
import static org.neo4j.kernel.Traversal.bidirectionalTraversal;
import static org.neo4j.kernel.Traversal.traversal;
import static org.neo4j.kernel.Uniqueness.RELATIONSHIP_GLOBAL;

import org.neo4j.graphalgo.impl.util.LiteDepthFirstSelector;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PathExpander;
Expand All @@ -35,6 +28,13 @@
import org.neo4j.graphdb.traversal.TraversalBranch;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.graphdb.traversal.Uniqueness;

import static org.neo4j.graphdb.traversal.Evaluators.atDepth;
import static org.neo4j.graphdb.traversal.Evaluators.toDepth;
import static org.neo4j.kernel.StandardExpander.toPathExpander;
import static org.neo4j.kernel.Traversal.bidirectionalTraversal;
import static org.neo4j.kernel.Traversal.traversal;

/**
* Tries to find paths in a graph from a start node to an end node where the
Expand All @@ -53,39 +53,38 @@ public class ExactDepthPathFinder extends TraversalPathFinder
private final PathExpander expander;
private final int onDepth;
private final int startThreshold;
private final Uniqueness uniqueness;

public ExactDepthPathFinder( RelationshipExpander expander, int onDepth,
int startThreshold )
public ExactDepthPathFinder( RelationshipExpander expander, int onDepth, int startThreshold, boolean allowLoops )
{
this( toPathExpander( expander ), onDepth, startThreshold );
this( toPathExpander( expander ), onDepth, startThreshold, allowLoops );
}

public ExactDepthPathFinder( PathExpander expander, int onDepth, int startThreshold )
public ExactDepthPathFinder( PathExpander expander, int onDepth, int startThreshold, boolean allowLoops )
{
this.expander = expander;
this.onDepth = onDepth;
this.startThreshold = startThreshold;
this.uniqueness = allowLoops ? Uniqueness.RELATIONSHIP_GLOBAL : Uniqueness.NODE_PATH;
}

@Override
protected Traverser instantiateTraverser( Node start, Node end )
{
TraversalDescription side = traversal().breadthFirst().expand( expander ).uniqueness( RELATIONSHIP_GLOBAL ).order(
new BranchOrderingPolicy()
TraversalDescription side =
traversal().breadthFirst().uniqueness( uniqueness ).order( new BranchOrderingPolicy()
{
@Override
public BranchSelector create( TraversalBranch startSource, PathExpander expander )
{
return new LiteDepthFirstSelector( startSource,
startThreshold, expander );
return new LiteDepthFirstSelector( startSource, startThreshold, expander );
}
} );

return bidirectionalTraversal()
.startSide( side.evaluator( toDepth( onDepth/2 ) ) )
.endSide( side.evaluator( toDepth( onDepth-onDepth/2 ) ) )
return bidirectionalTraversal().startSide( side.expand( expander ).evaluator( toDepth( onDepth / 2 ) ) )
.endSide( side.expand( expander.reverse() ).evaluator( toDepth( onDepth - onDepth / 2 ) ) )
.collisionEvaluator( atDepth( onDepth ) )
// TODO Level side selector will make the traversal return wrong result, why?
// .sideSelector( SideSelectorPolicies.LEVEL, onDepth )
// TODO Level side selector will make the traversal return wrong result, why?
// .sideSelector( SideSelectorPolicies.LEVEL, onDepth )
.traverse( start, end );
}
}

0 comments on commit 6884c91

Please sign in to comment.