@Override protected Traverser instantiateTraverser( Node start, Node end ) { // Bidirectional traversal GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription base = db.traversalDescription().depthFirst().uniqueness( uniqueness() ); return db.bidirectionalTraversalDescription() .startSide( base.expand( expander ).evaluator( toDepth( maxDepth / 2 ) ) ) .endSide( base.expand( expander.reverse() ).evaluator( toDepth( maxDepth - maxDepth / 2 ) ) ) .traverse( start, end ); } }
@Override protected Traverser instantiateTraverser( Node start, Node end ) { GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription side = db.traversalDescription().breadthFirst().uniqueness( uniqueness ).order( ( startSource, expander ) -> new LiteDepthFirstSelector( startSource, startThreshold, expander ) ); return db.bidirectionalTraversalDescription().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 ) .traverse( start, end ); } }
@Override protected Traverser instantiateTraverser( Node start, Node end ) { GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription sideBase = db.traversalDescription().breadthFirst().uniqueness( NODE_PATH ); return db.bidirectionalTraversalDescription().mirroredSides( sideBase.expand( expander ) ) .sideSelector( LEVEL_STOP_DESCENT_ON_RESULT, maxDepth ) .collisionEvaluator( toDepth( maxDepth ) ) .traverse( start, end ); }
private void testCIsReturnedOnDepthTwo( TraversalDescription description ) { try ( Transaction transaction = beginTx() ) { description = description.expand( PathExpanders.forTypeAndDirection( ONE, OUTGOING ) ); int i = 0; for ( Path position : description.traverse( node( "A" ) ) ) { assertEquals( i++, position.length() ); } } } }
private Traverser traverser( Node start, final Node end, PathInterest<Double> interest ) { PathExpander dijkstraExpander; PathEvaluator dijkstraEvaluator; if ( stateInUse ) { dijkstraExpander = expander; dijkstraEvaluator = Evaluators.includeWhereEndNodeIs( end ); } else { MutableDouble shortestSoFar = new MutableDouble( Double.MAX_VALUE ); dijkstraExpander = new DijkstraPathExpander( expander, shortestSoFar, epsilon, interest.stopAfterLowestCost() ); dijkstraEvaluator = new DijkstraEvaluator( shortestSoFar, end, costEvaluator ); } lastTraverser = new MonoDirectionalTraversalDescription( ) .uniqueness( Uniqueness.NODE_PATH ) .expand( dijkstraExpander, stateFactory ) .order( new DijkstraSelectorFactory( interest, costEvaluator ) ) .evaluator( dijkstraEvaluator ).traverse( start ); return lastTraverser; }
private Traverser traverseToDepth( GraphDatabaseService graphDb, final Node startNode, final int depth ) { TraversalDescription traversalDescription = graphDb.traversalDescription() .expand( PathExpanders.allTypesAndDirections() ) .depthFirst() .evaluator( path -> { if ( path.length() < depth ) { return Evaluation.INCLUDE_AND_CONTINUE; } else { return Evaluation.INCLUDE_AND_PRUNE; } } ); return traversalDescription.traverse( startNode ); }
@Test public void pathWithConstantDirection() { Node l = getNodeWithName( "l" ); expectPaths( getGraphDb().traversalDescription() .expand( PathExpanders.forConstantDirectionWithTypes( Types.A ) ) .traverse( l ), "l", "l,m", "l,m,n" ); Node n = getNodeWithName( "n" ); expectPaths( getGraphDb().traversalDescription() .expand( PathExpanders.forConstantDirectionWithTypes( Types.A ) ) .traverse( n ), "n", "n,m", "n,m,l", "n,o" ); Node q = getNodeWithName( "q" ); expectPaths( getGraphDb().traversalDescription() .expand( PathExpanders.forConstantDirectionWithTypes( Types.B ) ) .traverse( q ), "q", "q,p", "q,p,o" ); } }
private ResourceIterable<WeightedPath> findPaths( Node start, Node end, boolean multiplePaths ) { PathInterest interest; if ( multiplePaths ) { interest = stopAfterLowestWeight ? PathInterestFactory.allShortest() : PathInterestFactory.all(); } else { interest = PathInterestFactory.single(); } GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription traversalDescription = db.traversalDescription().uniqueness( Uniqueness.NONE ) .expand( expander, initialState ); lastTraverser = traversalDescription.order( new SelectorFactory( end, interest ) ) .evaluator( includeWhereEndNodeIs( end ) ) .traverse( start ); return Iterators.asResourceIterable( new WeightedPathIterator( lastTraverser.iterator(), costEvaluator, stopAfterLowestWeight ) ); }
@Test public void multipleStartAndEndNodes() { /* * (a)--\ -->(f) * v / * (b)-->(d)<--(e)-->(g) * ^ * (c)--/ */ createGraph( "a TO d", "b TO d", "c TO d", "e TO d", "e TO f", "e TO g" ); PathExpander<Void> expander = PathExpanderBuilder.empty().add( to ).build(); TraversalDescription side = getGraphDb().traversalDescription().uniqueness( NODE_PATH ).expand( expander ); expectPaths( getGraphDb().bidirectionalTraversalDescription().mirroredSides( side ).traverse( asList( getNodeWithName( "a" ), getNodeWithName( "b" ), getNodeWithName( "c" ) ), asList( getNodeWithName( "f" ), getNodeWithName( "g" ) ) ), "a,d,e,f", "a,d,e,g", "b,d,e,f", "b,d,e,g", "c,d,e,f", "c,d,e,g" ); }
@Test public void makeSureNodesAreTraversedInCorrectOrder() { PathExpander expander = new OrderedByTypeExpander().add( firstComment ).add( comment ).add( next ); Iterator<Node> itr = getGraphDb().traversalDescription().depthFirst().expand( expander ).traverse( node( "A1" ) ).nodes().iterator(); assertOrder( itr, "A1", "C1", "C2", "C3", "A2", "C4", "C5", "C6", "A3", "C7", "C8", "C9" ); expander = new OrderedByTypeExpander().add( next ).add( firstComment ).add( comment ); itr = getGraphDb().traversalDescription().depthFirst().expand( expander ).traverse( node( "A1" ) ).nodes().iterator(); assertOrder( itr, "A1", "A2", "A3", "C7", "C8", "C9", "C4", "C5", "C6", "C1", "C2", "C3" ); }
@Test public void depthAsState() { /* * (a) -> (b) -> (c) -> (d) * \ ^ * v / * (e) -> (f) -> (g) -> (h) */ createGraph( "a to b", "b to c", "c to d", "b to e", "e to f", "f to d", "f to g", "g to h" ); try ( Transaction tx = beginTx() ) { DepthStateExpander expander = new DepthStateExpander(); Iterables.count( getGraphDb().traversalDescription().expand( expander, new InitialBranchState.State<>( 0, 0 ) ).traverse( getNodeWithName( "a" ) ) ); tx.success(); } }
@Test public void pathsForOneDirection() { /* * (a)-->(b)==>(c)-->(d) * ^ / * \--(f)<--(e)<-/ */ createGraph( "a TO b", "b TO c", "c TO d", "d TO e", "e TO f", "f TO a" ); PathExpander<Void> expander = PathExpanders.forTypeAndDirection( to, OUTGOING ); expectPaths( getGraphDb().bidirectionalTraversalDescription() .mirroredSides( getGraphDb().traversalDescription().uniqueness( NODE_PATH ).expand( expander ) ) .traverse( getNodeWithName( "a" ), getNodeWithName( "f" ) ), "a,b,c,d,e,f" ); expectPaths( getGraphDb().bidirectionalTraversalDescription() .mirroredSides( getGraphDb().traversalDescription().uniqueness( RELATIONSHIP_PATH ).expand( expander ) ) .traverse( getNodeWithName( "a" ), getNodeWithName( "f" ) ), "a,b,c,d,e,f", "a,b,c,d,e,f" ); }
private Traverser traverser( Node start, final Node end, PathInterest interest ) { final MutableDouble shortestSoFar = new MutableDouble( Double.MAX_VALUE ); final MutableDouble startSideShortest = new MutableDouble( 0 ); final MutableDouble endSideShortest = new MutableDouble( 0 ); PathExpander dijkstraExpander = new DijkstraBidirectionalPathExpander( expander, shortestSoFar, true, startSideShortest, endSideShortest, epsilon ); GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription side = db.traversalDescription().expand( dijkstraExpander, stateFactory ) .order( new DijkstraSelectorFactory( interest, costEvaluator ) ) .evaluator( new DijkstraBidirectionalEvaluator( costEvaluator ) ) .uniqueness( Uniqueness.NODE_PATH ); TraversalDescription startSide = side; TraversalDescription endSide = side.reverse(); BidirectionalTraversalDescription traversal = db.bidirectionalTraversalDescription() .startSide( startSide ) .endSide( endSide ) .collisionEvaluator( Evaluators.all() ) .collisionPolicy( ( evaluator, pathPredicate ) -> new DijkstraBranchCollisionDetector( evaluator, costEvaluator, shortestSoFar, epsilon, pathPredicate ) ); lastTraverser = traversal.traverse( start, end ); return lastTraverser; }
@Test public void evenDifferentDirectionsKeepsOrder() { PathExpander expander = new OrderedByTypeExpander() .add( next, INCOMING ) .add( firstComment ) .add( comment ) .add( next, OUTGOING ); Iterator<Node> itr = getGraphDb().traversalDescription().depthFirst().expand( expander ).traverse( node( "A2" ) ).nodes().iterator(); assertOrder( itr, "A2", "A1", "C1", "C2", "C3", "C4", "C5", "C6", "A3", "C7", "C8", "C9" ); }
@Test public void everyOtherDepthAsState() { /* * (a) -> (b) -> (c) -> (e) */ createGraph( "a to b", "b to c", "c to d", "d to e" ); try ( Transaction tx = beginTx() ) { /* * Asserts that state continues down branches even when expander doesn't * set new state for every step. */ IncrementEveryOtherDepthCountingExpander expander = new IncrementEveryOtherDepthCountingExpander(); Iterables.count( getGraphDb().traversalDescription().expand( expander, new InitialBranchState.State<>( 0, 0 ) ).traverse( getNodeWithName( "a" ) ) ); tx.success(); } }
@Test public void evaluateState() { /* * (a)-1->(b)-2->(c)-3->(d) * \ ^ * 4 6 * (e)-5->(f) */ createGraph( "a TO b", "b TO c", "c TO d", "a TO e", "e TO f", "f TO c" ); try ( Transaction tx = beginTx() ) { PathEvaluator<Integer> evaluator = new PathEvaluator.Adapter<Integer>() { @Override public Evaluation evaluate( Path path, BranchState<Integer> state ) { return ofIncludes( path.endNode().getProperty( "name" ).equals( "c" ) && state.getState() == 3 ); } }; expectPaths( getGraphDb().traversalDescription().uniqueness( Uniqueness.NODE_PATH ).expand( new RelationshipWeightExpander(), new InitialBranchState.State<>( 1, 1 ) ) .evaluator( evaluator ).traverse( getNodeWithName( "a" ) ), "a,b,c" ); tx.success(); } }
@Test public void mirroredTraversalReversesInitialState() { /* * (a)-->(b)-->(c)-->(d) */ createGraph( "a TO b", "b TO c", "c TO d" ); BranchCollisionPolicy collisionPolicy = ( evaluator, pathPredicate ) -> new StandardBranchCollisionDetector( null, null ) { @Override protected boolean includePath( Path path, TraversalBranch startPath, TraversalBranch endPath ) { assertEquals( 0, startPath.state() ); assertEquals( 10, endPath.state() ); return true; } }; Iterables.count( getGraphDb().bidirectionalTraversalDescription() // Just make up a number bigger than the path length (in this case 10) so that we can assert it in // the collision policy later .mirroredSides( getGraphDb().traversalDescription().uniqueness( NODE_PATH ).expand( PathExpanders.forType( to ), new InitialBranchState.State<>( 0, 10 ) ) ) .collisionPolicy( collisionPolicy ) .traverse( getNodeWithName( "a" ), getNodeWithName( "d" ) ) ); } }
@Test public void collisionEvaluator() { /* * (d)-->(e)-- * ^ | \ * | v v * (a)-->(b)<--(f) * | ^ * v / * (c)-/ */ createGraph( "a TO b", "a TO c", "c TO b", "a TO d", "d TO e", "e TO b", "e TO f", "f TO b" ); PathExpander<Void> expander = PathExpanders.forTypeAndDirection( to, OUTGOING ); BidirectionalTraversalDescription traversal = getGraphDb().bidirectionalTraversalDescription() .mirroredSides( getGraphDb().traversalDescription().uniqueness( NODE_PATH ).expand( expander ) ); expectPaths( traversal .collisionEvaluator( includeIfContainsAll( getNodeWithName( "e" ) ) ) .traverse( getNodeWithName( "a" ), getNodeWithName( "b" ) ), "a,d,e,b", "a,d,e,f,b" ); expectPaths( traversal .collisionEvaluator( includeIfContainsAll( getNodeWithName( "e" ), getNodeWithName( "f" ) ) ) .traverse( getNodeWithName( "a" ), getNodeWithName( "b" ) ), "a,d,e,f,b" ); }
td = td.expand(new RelationshipSequenceExpander(relSequenceList, beginSequenceAtStart)); td = td.evaluator(new LabelSequenceEvaluator(labelSequenceList, filterStartNode, beginSequenceAtStart, (int) minLevel)); } else { if (pathFilter != null && !pathFilter.trim().isEmpty()) { td = td.expand(new RelationshipSequenceExpander(pathFilter.trim(), beginSequenceAtStart));
@Override protected Traverser instantiateTraverser( Node start, Node end ) { // Bidirectional traversal GraphDatabaseService db = start.getGraphDatabase(); TraversalDescription base = db.traversalDescription().depthFirst().uniqueness( uniqueness() ); return db.bidirectionalTraversalDescription() .startSide( base.expand( expander ).evaluator( toDepth( maxDepth / 2 ) ) ) .endSide( base.expand( expander.reverse() ).evaluator( toDepth( maxDepth - maxDepth / 2 ) ) ) .traverse( start, end ); } }