/* * Copyright 2008 Network Engine for Objects in Lund AB [neotechnology.com] * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.graphalgo.shortestpath; import java.util.List; import org.neo4j.graphalgo.shortestpath.std.IntegerAdder; import org.neo4j.graphalgo.shortestpath.std.IntegerComparator; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.RelationshipType; /** * FindPath class. This class can be used to perform shortest path computations * between two nodes on an unweighted network. Currently just wraps two Dijkstras * from sart and end node, trying to intersect in the middle. * {@link Dijkstra}. * @author Patrik Larsson */ public class FindPath implements SingleSourceSingleSinkShortestPath<Integer> { Dijkstra<Integer> dijkstra; /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#calculate() */ public boolean calculate() { return dijkstra.calculate(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#calculateMultiple() */ public boolean calculateMultiple() { return dijkstra.calculateMultiple(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getCost() */ public Integer getCost() { return dijkstra.getCost(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getDirection() */ public Direction getDirection() { return dijkstra.getDirection(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPath() */ public List<PropertyContainer> getPath() { return dijkstra.getPath(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPathAsNodes() */ public List<Node> getPathAsNodes() { return dijkstra.getPathAsNodes(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPathAsRelationships() */ public List<Relationship> getPathAsRelationships() { return dijkstra.getPathAsRelationships(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPaths() */ public List<List<PropertyContainer>> getPaths() { return dijkstra.getPaths(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPathsAsNodes() */ public List<List<Node>> getPathsAsNodes() { return dijkstra.getPathsAsNodes(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getPathsAsRelationships() */ public List<List<Relationship>> getPathsAsRelationships() { return dijkstra.getPathsAsRelationships(); } /** * @return * @see org.neo4j.graphalgo.shortestpath.Dijkstra#getRelationshipTypes() */ public RelationshipType[] getRelationshipTypes() { return dijkstra.getRelationshipTypes(); } /** * @param maxNodesToTraverse * @see org.neo4j.graphalgo.shortestpath.Dijkstra#limitMaxNodesToTraverse(long) */ public void limitMaxNodesToTraverse( long maxNodesToTraverse ) { dijkstra.limitMaxNodesToTraverse( maxNodesToTraverse ); } /** * @param maxRelationShipsToTraverse * @see org.neo4j.graphalgo.shortestpath.Dijkstra#limitMaxRelationShipsToTraverse(long) */ public void limitMaxRelationShipsToTraverse( long maxRelationShipsToTraverse ) { dijkstra.limitMaxRelationShipsToTraverse( maxRelationShipsToTraverse ); } /** * @see org.neo4j.graphalgo.shortestpath.Dijkstra#reset() */ public void reset() { dijkstra.reset(); } /** * @param endNode * @see org.neo4j.graphalgo.shortestpath.Dijkstra#setEndNode(org.neo4j.api.core.Node) */ public void setEndNode( Node endNode ) { dijkstra.setEndNode( endNode ); } /** * @param startNode * @see org.neo4j.graphalgo.shortestpath.Dijkstra#setStartNode(org.neo4j.api.core.Node) */ public void setStartNode( Node startNode ) { dijkstra.setStartNode( startNode ); } public void limitMaxCostToTraverse( MaxCostEvaluator<Integer> evaluator ) { dijkstra.limitMaxCostToTraverse( evaluator ); } /** * This is an algo that will initiate a Dijkstra from start- and end node * with relationship cost of 1 per path step along the costRelationshipTypes * @param startNode the node to start at * @param endNode the node to find a path to * @param relationDirection the direction to traverse all cost relationships in * @param costRelationTypes the types of relationships that are going to be on the path */ public FindPath( Node startNode, Node endNode, Direction relationDirection, RelationshipType... costRelationTypes ) { dijkstra = new Dijkstra<Integer>( 0, startNode, endNode, new CostEvaluator<Integer>() { public Integer getCost( Relationship relationship, boolean backwards ) { return 1; } }, new IntegerAdder(), new IntegerComparator(), relationDirection, costRelationTypes ); } /** * A depth-limited variant of the double-starting Dijkstra. If one of the paths is costing more (longer than) * maxCost, the Dijkstra there will stop. * Potentially, if the shortest path between 2 nodes is length 12, at maxCost 4 it would not be found since the two segments * at max depth 4 would not meet. * For this, at least maxCost = 6 has to be set in order to find paths with length 12. * @param startNode the start node * @param endNode the end node * @param maxCost the maximum length of the path before giving up * @param relationDirection the direction to traverse all cost relationships in * @param costRelationTypes the types of relationships that are going to be on the path */ public FindPath( Node startNode, Node endNode, final int maxCost, Direction relationDirection, RelationshipType... costRelationTypes ) { this(startNode, endNode, relationDirection, costRelationTypes); MaxCostEvaluator<Integer> maxCostComparator = new MaxCostEvaluator<Integer>() { public boolean maxCostExceeded(Integer currentCost) { return currentCost > maxCost; } }; dijkstra.limitMaxCostToTraverse(maxCostComparator); } }