Algorithm Node A Connected to Node B in a graph

I am looking for an algorithm to test for a valid connection (shortest or longest) between two arbitrary nodes in a graph.

My graph is snapped to a grid with logical (x, y) coordinates with north / south / east / west connections, but the nodes can be randomly removed, so you can't assume that taking the edge with the coordinates closest to the target will always take you there.

The code is in python. The node data structure (object) has a list of connected nodes. The elements of the list are ref refs, so we can search that node list of the connected nodes list recursively, like this:

for pnode in self.connected_nodes:
    for cnode in pnode.connected_nodes:
        ...etc

      

I have included a diagram showing how the nodes display the x, y coordinates and how they relate north / east / south / west. Sometimes there are missing nodes (between J and K) and sometimes there are missing edges (between G and H). The presence of nodes and edges in the stream (although when we run the algorithm it takes a fixed snapshot in time) and it can only be determined by checking each node for it the list of connected nodes.

The algorithm should give a simple true / false about whether a valid connection exists between the two nodes. Recursion through each list of connected nodes blows up the number of operations required - if a node is n edges, no more than 4 ^ n operations are required. My understanding is something like Diistrika's algorithm, if you find the shortest path based on edge weights, but if there is no connection at all, will it still work?

For some background I am using this to model 2D destructible objects. Each node represents a piece of material, and if one or more nodes are out of touch with the rest of the material, then it should detach. In the diagram - D, H, R - should be away from the main body as they are not connected.

enter image description here

UPDATE:

While many of the answers posted may well work, DFS is fast, lightweight, and very appropriate. I am not fond of the idea of ​​glueing extra edges between nodes with high weights to use Dijkstra, because the node itself may disappear as well as the edges. The SSC method seems to be more suitable for distinguishing between strong and loosely coupled plots, which in my plot will work if there is one edge between G and H.

Here is my experiment code for DFS search that creates the same graph as the chart.

class node(object):
    def __init__(self, id):
        self.connected_nodes  = []
        self.id               = id

    def dfs_is_connected(self, node):
        # Initialise our stack and our discovered list
        stack      = []
        discovered = []

        # Declare operations count to track how many iterations it took
        op_count = 0

        # Push this node to the stack, for our starting point
        stack.append(self)

        # Keeping iterating while the stack isn't empty
        while stack:
            # Pop top element off the stack
            current_node = stack.pop()

            # Is this the droid/node you are looking for?
            if current_node.id == node.id:
                # Stop!
                return True, op_count

            # Check if current node has not been discovered
            if current_node not in discovered:

                # Increment op count
                op_count += 1

                # Is this the droid/node you are looking for?
                if current_node.id == node.id:
                    # Stop!
                    return True, op_count

                # Put this node in the discovered list
                discovered.append(current_node)

                # Iterate through all connected nodes of the current node
                for connected_node in current_node.connected_nodes:
                    # Push this connected node into the stack
                    stack.append(connected_node)

        # Couldn't find the node, return false. Sorry bud
        return False, op_count


if __name__ == "__main__":

    # Initialise all nodes
    a = node('a')
    b = node('b')
    c = node('c')
    d = node('d')
    e = node('e')
    f = node('f')
    g = node('g')
    h = node('h')
    j = node('j')
    k = node('k')
    l = node('l')
    m = node('m')
    n = node('n')
    p = node('p')
    q = node('q')
    r = node('r')
    s = node('s')

    # Connect up nodes
    a.connected_nodes.extend([b, e])
    b.connected_nodes.extend([a, f, c])
    c.connected_nodes.extend([b, g])
    d.connected_nodes.extend([r])
    e.connected_nodes.extend([a, f, j])
    f.connected_nodes.extend([e, b, g])
    g.connected_nodes.extend([c, f, k])
    h.connected_nodes.extend([r])
    j.connected_nodes.extend([e, l])
    k.connected_nodes.extend([g, n])
    l.connected_nodes.extend([j, m, s])
    m.connected_nodes.extend([l, p, n])
    n.connected_nodes.extend([k, m, q])
    p.connected_nodes.extend([s, m, q])
    q.connected_nodes.extend([p, n])
    r.connected_nodes.extend([h, d])
    s.connected_nodes.extend([l, p])

    # Check if a is connected to q
    print a.dfs_is_connected(q)
    print a.dfs_is_connected(d)
    print p.dfs_is_connected(h)

      

+3


source to share


4 answers


To find this, you just need to run a simple DFS or BFS on one of the nodes, it will find all the available nodes in the contiguous component of the graph, so you just mark it if you find another node while running the algorithm.



+2


source


There is a way to use Dijkstra to find a path. If there is an edge between two nodes, put 1 for the weight, if there is no node, put the weight sys.maxint

. Then, when the min route is calculated, if it is greater than the number of nodes, there is no path between them.



Another approach is to first find the strongly related components of the graph. If the nodes are on the same strong component, then use Dijkstra to find a path, otherwise there is no path that connects them.

+1


source


You can take a look at A* Path Finding Algorithm

(which uses a heuristic to make it more efficient than Dijkstra, so if it's not all you can use in your problem, you might be better off using Dijkstra's algorithm, but you need a positive weight. not what you have on your graph, you can just give each edge a weight 1).

Looking at the pseudocode on Wikipedia, it A*

moves from one node to another, getting the neighbors of the current node. Dijkstra Algorithm maintains an adjacency list so that it knows which nodes are related to each other.

Thus, if you start from node H

, you can only go to R

and D

. Since these nodes are not connected to others, the algorithm will not go through other nodes.

0


source


You can find the strongly connected components (SCC) of your graph and then check if the nodes in one component are interested or not. In your example, HRD will be the first component and remain the second, so for the result, H and R will be true, but H and A will be false. See SCC Algorithm here: https://class.coursera.org/algo-004/lecture/53 .

0


source







All Articles