views:

146

answers:

7

Hi! Is there an algorithm that can check, in a directed graph, if a vertex, let's say V2, is reachable from a vertex V1, without traversing all the vertices?

+7  A: 

Depth first search or breadth first search. Stop when you find one. But there's no way to tell there's none without going through every one, no. You can improve the performance sometimes with some heuristics, like if you have additional information about the graph. For example, if the graph represents a coordinate space like a real map, and most of the time you know that there's going to be a mostly direct path, then you can attempt to have the depth-first search look along lines that "aim towards the target". However, imagine the case where the start and end points are right next to each other, but with no vector inbetween, and to find it, you have to go way out of the way. You have to check every case in order to be exhaustive.

eruciform
updated. there are some heuristics to speed up finding a path quicker, depending on your knowledge of the data. but you can't speed up the worst case.
eruciform
+2  A: 

I doubt it has a name, but a breadth-first search might go like this:

Add V1 to a queue of nodes to be visited
While there are nodes in the queue:
    If the node is V2, return true
    Mark the node as visited
    For every node at the end of an outgoing edge which is not yet visited:
        Add this node to the queue
    End for
End while
Return false
romkyns
+1 for giving words instead of plain code.
Andrei Ciobanu
+9  A: 

You might find a route to that node without traversing all the edges, and if so you can give a yes answer as soon as you do. Nothing short of traversing all the edges can confirm that the node isn't reachable (unless there's some other constraint you haven't stated that could be used to eliminate the possibility earlier).

Edit: I should add that it depends on how often you need to do queries versus how large (and dense) your graph is. If you need to do a huge number of queries on a relatively small graph, it may make sense to pre-process the data in the graph to produce a matrix with a bit at the intersection of any V1 and V2 to indicate whether there's a connection from V1 to V2. This doesn't avoid traversing the graph, but it can avoid traversing the graph at the time of the query. I.e., it's basically a greedy algorithm that assumes you're going to eventually use enough of the combinations that it's easiest to just traverse them all and store the result. Depending on the size of the graph, the pre-processing step may be slow, but once it's done executing a query becomes quite fast (constant time, and usually a pretty small constant at that).

Jerry Coffin
I want to check first if V2 is reachable from V1, so that I can decide whether to continue traversing the graph for the path from V1 to V2 or not. The graph represents a road network.
@jalbautista: In general, the only way to find whether there's a route from one node to another is to find a route, or exhaust all possibilities trying to, which will verify that there is no route.
Jerry Coffin
+1: There may be ways you can speed up the query of "is it impossible to reach V2 from V1".. or "is it possible to reach V2 from V1"..there might be key routes to which you can attach some sort of index, for example if you had any bridges, you might want to keep an x-depth source index, and a y-depth destination index, and look up x-y combinations through the bridge as a first guess. This won't tell you the route, but will tell you the existence of a route, for example.
maxwellb
@maxwellb: bridges?
JAB
given an edge E, if the set of all nodes which can reach the source node of E, intersected with the set of all nodes which the destination node of E can reach, is empty, then E is a bridge. If V1 cannot reach E, and E can reach V2, you know that V1 cannot reach V2. This may be an optimization if you can determine bridges ahead of time and create such an index.
maxwellb
+2  A: 

Create an adjacency matrix when the graph is created. At the same time you do this, create matrices consisting of the powers of the adjacency matrix up to the number of nodes in the graph. To find if there is a path from node u to node v, check the matrices (starting from M^1 and going to M^n) and examine the value at (u, v) in each matrix. If, for any of the matrices checked, that value is greater than zero, you can stop the check because there is indeed a connection. (This gives you even more information as well: the power tells you the number of steps between nodes, and the value tells you how many paths there are between nodes for that step number.)

(Note that if you know the number of steps in the longest path in your graph, for whatever reason, you only need to create a number of matrices up to that power. As well, if you want to save memory, you could just store the base adjacency matrix and create the others as you go along, but for large matrices that may take a fair amount of time if you aren't using an efficient method of doing the multiplications, whether from a library or written on your own.)

It would probably be easiest to just do a depth- or breadth-first search, though, as others have suggested, not only because they're comparatively easy to implement but also because you can generate the path between nodes as you go along. (Technically you'd be generating multiple paths and discarding loops/dead-end ones along the way, but whatever.)

JAB
@jalbautista Indeed an approach that works without traversing the graph. But please note that this method performs worse than BFS/DFS.
Dave
@Dave: unless the adjacency matrix is how your graph is actually represented already. Unlikely for a road network, but I think your statement is too broad as it is to be strictly true.
romkyns
+1  A: 

In principle, you can't determine that a path exists without traversing some part of the graph, because the failure case (a path does not exist) cannot be determined without traversing the entire graph.

You MAY be able to improve your performance by searching backwards (search from destination to starting point), or by alternating between forward and backward search steps.

Any good AI textbook will talk at length about search techniques. Elaine Rich's book was good in this area. Amazon is your FRIEND.

John R. Strohm
A: 

In order to be sure, you either have to find a path, or traverse all vertices that are reachable from V1 once. I would recommend an implementation of depth first or breadth first search that stops when it encounters a vertex that it has already seen. The vertex will be processed on the first occurrence only. You need to make sure that the search starts at V1 and stops when it runs out of vertices or encounters V2.

Cheers, Jacob

TheJacobTaylor
A: 

Another approach to this problem would allow you to ignore all of the vertices. If you were to only look at the edges, you can produce a transitive closure array that will show you each vertex that is reachable from any other vertex.

Start with your list of edges: Va -> Vc Va -> Vd ....

Create an array with start location as the rows and end location as the columns. Fill the arrays with 0. For each edge in the list of edges, place a one in the start,end coordinate of the edge.

Now you iterate a few times until either V1,V2 is 1 or there are no changes.

For each row:
    NextRowN = RowN
    For each column that is true for RowN
        Use boolean OR to OR in the results of that row of that number with the current NextRowN.
    Set RowN to NextRowN

If you run this algorithm until the end, you will quickly have a complete list of all reachable vertices without looking at any of them. The runtime is proportional to the number of edges. This would work well with a reasonable implementation and a reasonable number of edges.

A slightly more complex version of this algorithm would be to only calculate the vertices reachable by V1. To do this, you would focus your scope on the ones that are currently reachable at any given time. You can also limit adding rows to only one time, since the other rows are never changing.

Cheers, Jacob

TheJacobTaylor