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() ); } } } }
@Test public void unfortunateRelationshipOrderingInTriangle() { /* * (b) * ^ \ * / v * (a)---->(c) * * Relationships are created in such a way that they are iterated in the worst order, * i.e. (S) a-->b, (E) c<--b, (S) a-->c */ graph.makeEdgeChain( "a,b,c" ); graph.makeEdgeChain( "a,c" ); final Node a = graph.getNode( "a" ); final Node c = graph.getNode( "c" ); testShortestPathFinder( finder -> assertPathDef( finder.findSinglePath( a, c ), "a", "c" ), PathExpanders.forTypeAndDirection( R1, OUTGOING ), 2 ); testShortestPathFinder( finder -> assertPathDef( finder.findSinglePath( c, a ), "c", "a" ), PathExpanders.forTypeAndDirection( R1, INCOMING ), 2 ); }
@Test public void makeSureShortestPathsReturnsNoLoops() { // Layout: // // (a)-->(b)==>(c)-->(e) // ^ / // \ v // (d) // graph.makeEdgeChain( "a,b,c,d,b,c,e" ); testShortestPathFinder( finder -> { final Node a = graph.getNode( "a" ); final Node e = graph.getNode( "e" ); assertPaths( finder.findAllPaths( a, e ), "a,b,c,e", "a,b,c,e" ); }, PathExpanders.forTypeAndDirection( R1, BOTH ), 6 ); }
@Test public void testDirectedFinder() { // Layout: // // (a)->(b)->(c)->(d)->(e)->(f)-------\ // \ v // >(g)->(h)->(i)->(j)->(k)->(l)->(m) // graph.makeEdgeChain( "a,b,c,d,e,f,m" ); graph.makeEdgeChain( "a,g,h,i,j,k,l,m" ); testShortestPathFinder( finder -> assertPaths( finder.findAllPaths( graph.getNode( "a" ), graph.getNode( "j" ) ), "a,g,h,i,j" ), PathExpanders.forTypeAndDirection( R1, OUTGOING ), 4 ); }
@Test public void testSimplestGraph() { // Layout: // __ // / \ // (s) (t) // \__/ graph.makeEdge( "s", "t" ); graph.makeEdge( "s", "t" ); testShortestPathFinder( finder -> { final Iterable<Path> paths = finder.findAllPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertPaths( paths, "s,t", "s,t" ); assertPaths( asList( finder.findSinglePath( graph.getNode( "s" ), graph.getNode( "t" ) ) ), "s,t" ); }, PathExpanders.forTypeAndDirection( R1, BOTH ), 1 ); }
@Test public void testSmallGraph() { Relationship shortCTOXRelationship = createGraph( true ); PathFinder<WeightedPath> finder = factory.dijkstra( PathExpanders.forTypeAndDirection( MyRelTypes.R1, Direction.OUTGOING ), CommonEvaluators.doubleCostEvaluator( "cost" ) ); // Assert that there are two matching paths Node startNode = graph.getNode( "start" ); Node endNode = graph.getNode( "x" ); assertPaths( finder.findAllPaths( startNode, endNode ), "start,a,b,c,x", "start,a,b,c,d,e,x" ); // Assert that for the shorter one it picked the correct relationship // of the two from (c) --> (x) for ( WeightedPath path : finder.findAllPaths( startNode, endNode ) ) { if ( getPathDef( path ).equals( "start,a,b,c,x" ) ) { assertContainsRelationship( path, shortCTOXRelationship ); } } }
@Test public void testSmallGraphWithDefaults() { Relationship shortCTOXRelationship = createGraph( true ); PathFinder<WeightedPath> finder = factory.dijkstra( PathExpanders.forTypeAndDirection( MyRelTypes.R1, Direction.OUTGOING ), CommonEvaluators.doubleCostEvaluator( "cost", 1.0d ) ); // Assert that there are two matching paths Node startNode = graph.getNode( "start" ); Node endNode = graph.getNode( "x" ); assertPaths( finder.findAllPaths( startNode, endNode ), "start,a,b,c,x", "start,a,b,c,d,e,x" ); // Assert that for the shorter one it picked the correct relationship // of the two from (c) --> (x) for ( WeightedPath path : finder.findAllPaths( startNode, endNode ) ) { if ( getPathDef( path ).equals( "start,a,b,c,x" ) ) { assertContainsRelationship( path, shortCTOXRelationship ); } } }
@Test public void makeSureRelationshipNotConnectedIssueNotThere() { /* * (g) * / ^ * v \ * (a)<--(b)<--(c)<--(d)<--(e)<--(f) (i) * ^ / * \ v * (h) */ graph.makeEdgeChain( "i,g,f,e,d,c,b,a" ); graph.makeEdgeChain( "i,h,f" ); testShortestPathFinder( finder -> { final Node start = graph.getNode( "a" ); final Node end = graph.getNode( "i" ); assertPaths( finder.findAllPaths( start, end ), "a,b,c,d,e,f,g,i", "a,b,c,d,e,f,h,i" ); }, PathExpanders.forTypeAndDirection( R1, INCOMING ), 10 ); }
@Test public void makeSureShortestPathCanBeFetchedEvenIfANodeHasLoops() { // Layout: // // = means loop :) // // (m) // / \ // (s) (o)= // \ / // (n)= // | // (p) graph.makeEdgeChain( "m,s,n,p" ); graph.makeEdgeChain( "m,o,n" ); graph.makeEdge( "o", "o" ); graph.makeEdge( "n", "n" ); testShortestPathFinder( finder -> assertPaths( finder.findAllPaths( graph.getNode( "m" ), graph.getNode( "p" ) ), "m,s,n,p", "m,o,n,p" ), PathExpanders.forTypeAndDirection( R1, BOTH ), 3 ); }
@Test public void testCrossedCircle() { // Layout: // (s) // / \ // (3) (1) // | \ / | // | / \ | // (4) (2) // \ / // (t) graph.makeEdge( "s", "1" ); graph.makeEdge( "s", "3" ); graph.makeEdge( "1", "2" ); graph.makeEdge( "1", "4" ); graph.makeEdge( "3", "2" ); graph.makeEdge( "3", "4" ); graph.makeEdge( "2", "t" ); graph.makeEdge( "4", "t" ); testShortestPathFinder( finder -> assertPaths( finder.findAllPaths( graph.getNode( "s" ), graph.getNode( "t" ) ), "s,1,2,t", "s,1,4,t", "s,3,2,t", "s,3,4,t" ), PathExpanders.forTypeAndDirection( R1, BOTH ), 3 ); }
@Test public void testAnotherSimpleGraph() { // Layout: // (m) // / \ // (s) (o)---(t) // \ / \ // (n)---(p)---(q) graph.makeEdge( "s", "m" ); graph.makeEdge( "m", "o" ); graph.makeEdge( "s", "n" ); graph.makeEdge( "n", "p" ); graph.makeEdge( "p", "q" ); graph.makeEdge( "q", "t" ); graph.makeEdge( "n", "o" ); graph.makeEdge( "o", "t" ); testShortestPathFinder( finder -> { final Iterable<Path> paths = finder.findAllPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertPaths( paths, "s,m,o,t", "s,n,o,t" ); }, PathExpanders.forTypeAndDirection( R1, BOTH ), 6 ); }
@Test public void makeSureAMaxResultCountIsObeyed() { // Layout: // // (a)--(b)--(c)--(d)--(e) // | / | \ // (f)--(g)---------(h) | \ // | | | // (i)-----------------(j) | // | | // (k)---------------------- // graph.makeEdgeChain( "a,b,c,d,e" ); graph.makeEdgeChain( "a,f,g,h,e" ); graph.makeEdgeChain( "f,i,j,e" ); graph.makeEdgeChain( "i,k,e" ); final Node a = graph.getNode( "a" ); final Node e = graph.getNode( "e" ); final PathExpander expander = PathExpanders.forTypeAndDirection( R1, OUTGOING ); testShortestPathFinder( finder -> assertEquals( 4, Iterables.count( finder.findAllPaths( a, e ) ) ), expander, 10, 10 ); for ( int i = 4; i >= 1; i-- ) { final int count = i; testShortestPathFinder( finder -> assertEquals( count, Iterables.count( finder.findAllPaths( a, e ) ) ), expander, 10, count ); } }
@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" ); }
@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" ); }
@Test public void testExactDepthFinder() { // Layout (a to k): // // (a)--(c)--(g)--(k) // / / // (b)-----(d)------(j) // | \ / // (e)--(f)--(h)--(i) // graph.makeEdgeChain( "a,c,g,k" ); graph.makeEdgeChain( "a,b,d,j,k" ); graph.makeEdgeChain( "b,e,f,h,i,j" ); graph.makeEdgeChain( "d,h" ); PathExpander<Object> expander = PathExpanders.forTypeAndDirection( MyRelTypes.R1, Direction.OUTGOING ); Node a = graph.getNode( "a" ); Node k = graph.getNode( "k" ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 3 ).findAllPaths( a, k ), "a,c,g,k" ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 4 ).findAllPaths( a, k ), "a,b,d,j,k" ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 5 ).findAllPaths( a, k ) ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 6 ).findAllPaths( a, k ), "a,b,d,h,i,j,k" ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 7 ).findAllPaths( a, k ), "a,b,e,f,h,i,j,k" ); assertPaths( GraphAlgoFactory.pathsWithLength( expander, 8 ).findAllPaths( a, k ) ); }
new CountingPathExpander( PathExpanders.forTypeAndDirection( relType, Direction.OUTGOING ) ); final ShortestPath shortestPath = new ShortestPath( Integer.MAX_VALUE, countingPathExpander, Integer.MAX_VALUE ); try ( ResourceIterator<Node> allF = graphDb.findNodes( F ) )
/** * Get a single relationship between two nodes. * * @param node1 first node. * @param node2 second node. * @param type relationship type. * @param direction relationship direction from first node's point of view (can be BOTH). * @return a single relationship, null if there is no such relationship between the nodes. If there is * more than one relationship, one (unspecified which one) will be returned. */ public static Relationship getSingleRelationshipOrNull(Node node1, Node node2, RelationshipType type, Direction direction) { Path singlePath = shortestPath(forTypeAndDirection(type, direction), 1, 1).findSinglePath(node1, node2); if (singlePath == null) { return null; } return singlePath.lastRelationship(); }
public Iterable<Person> getShortestPathTo( Person otherPerson, int maxDepth ) { // use graph algo to calculate a shortest path PathFinder<Path> finder = GraphAlgoFactory.shortestPath( forTypeAndDirection(FRIEND, BOTH ), maxDepth ); Path path = finder.findSinglePath( underlyingNode, otherPerson.getUnderlyingNode() ); return createPersonsFromNodes( path ); }
private long getNumberOfPathsToPerson( Person otherPerson ) { PathFinder<Path> finder = GraphAlgoFactory.allPaths( forTypeAndDirection( FRIEND, BOTH ), 2 ); Iterable<Path> paths = finder.findAllPaths( getUnderlyingNode(), otherPerson.getUnderlyingNode() ); return count( paths ); }
public WeightedPath findCheapestPathWithDijkstra( final Node nodeA, final Node nodeB ) { // START SNIPPET: dijkstraUsage PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra( PathExpanders.forTypeAndDirection( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" ); WeightedPath path = finder.findSinglePath( nodeA, nodeB ); // Get the weight for the found path path.weight(); // END SNIPPET: dijkstraUsage return path; }