What is the most efficient way of finding a path through a small world graph?

前端 未结 7 1194
隐瞒了意图╮
隐瞒了意图╮ 2020-12-25 08:47

I have a sea of weighted nodes with edges linking clusters of nodes together. This graph follows the typical small world layout.

I wish to find a path finding algori

相关标签:
7条回答
  • 2020-12-25 08:59

    Dijkstras algorithm, small example for you

    graph = {}
    
    graph["start"] = {}
    graph["start"]["a"] = 6
    graph["start"]["b"] = 2
    graph["a"] = {}
    graph["a"]["finish"] = 1
    graph["b"] = {}
    graph["b"]["a"] = 3
    graph["b"]["finish"] = 5
    graph["finish"] = {}
    
    infinity = float("inf")
    costs = {}
    costs["a"] = 6
    costs["b"] = 2
    costs["finish"] = infinity
    print "The weight of each node is: ", costs
    
    parents = {}
    parents["a"] = "start"
    parents["b"] = "start"
    parents["finish"] = None
    
    processed = []
    
    def find_lowest_cost_node(costs):
        lowest_cost = float("inf")
        lowest_cost_node = None
        for node in costs:
            cost = costs[node]
            if cost < lowest_cost and node not in processed:
                lowest_cost = cost
                lowest_cost_node = node
        return lowest_cost_node
    
    node = find_lowest_cost_node(costs)
    print "Start: the lowest cost node is", node, "with weight",\
        graph["start"]["{}".format(node)]
    
    while node is not None:
        cost = costs[node]
        print "Continue execution ..."
        print "The weight of node {} is".format(node), cost
        neighbors = graph[node]
        if neighbors != {}:
            print "The node {} has neighbors:".format(node), neighbors
        else:
            print "It is finish, we have the answer: {}".format(cost)
        for neighbor in neighbors.keys():
            new_cost = cost + neighbors[neighbor]
            if costs[neighbor] > new_cost:
                costs[neighbor] = new_cost
                parents[neighbor] = node
        processed.append(node)
        print "This nodes we researched:", processed
        node = find_lowest_cost_node(costs)
        if node is not None:
            print "Look at the neighbor:", node
    
    # to draw graph
    import networkx
    G = networkx.Graph()
    G.add_nodes_from(graph)
    G.add_edge("start", "a", weight=6)
    G.add_edge("b", "a", weight=3)
    G.add_edge("start", "b", weight=2)
    G.add_edge("a", "finish", weight=1)
    G.add_edge("b", "finish", weight=5)
    
    import matplotlib.pyplot as plt
    networkx.draw(G, with_labels=True)
    plt.show()
    
    print "But the shortest path is:", networkx.shortest_path(G, "start", "finish")
    
    0 讨论(0)
  • 2020-12-25 09:01

    General notes

    Dijkstra's algorithm and it optimised variant A* find the path with "the" minimal cost through your graph. The important things are a) defining your graph correctly and b) defining an appropriate cost function.

    In the face of a changing cost function Dijksta requires one to re-calculate the solution.

    For load-balancing I would extend Dikstra to not only calculate the optimal path, but use some kind of flood-fill behaviour to create a set of possible paths (sorted by cost) to find alternatives. Only knowledge about the specific problem and cost function can answer whether and how this might work.

    Ant Colony Optimisation on the other hand seems to be much more flexible in adapting to a changing cost function, by continuing the iteration after/while the cost function changes.

    Efficiency

    This depends very much on your problem domain. If you have a good heuristic (see the Complexity section of the A* article) and seldom cost changes then A*'s polynomial runtime might favour repeated re-calculations. ACO on the other hand has to iterate over and over again before converging on an approximate solution. If cost changes occur very frequently, continuing the iteration at a constant rate might be more efficient than updating the A*-solution, since information is retained within the state of the algorithm. ACO doesn't promise the optimal solution, though and probably has higher start-up costs before converging onto a "good" solution. Again that very much depends on your specific domain, graph and cost function as well as your requirements on optimality.

    0 讨论(0)
  • 2020-12-25 09:09

    The most commonly used algorithm for this problem is A* (A Star), which is a generalized Dijkstra's algorithm search with added heuristics - the purpose of the heuristics is to direct the search towards the search goal so that typical searches finish faster.

    This algorithm has many variants, derived versions and improvements, Google search or the Wikipedia page should be a good starting point.

    0 讨论(0)
  • 2020-12-25 09:09

    I have heard of a NN implementation to handle this kind of problem as well. So if you want to use NNs you will eventually find your way ;-) but they must be inferior in comparison to "genetic algorithms".

    If the computational/time consumption is an issue, I would highly suggest using genetic algorithms. This is excactly the type of problems they are exceptional at.

    GAs are based on a function that describes your satisfaction for any given solution. You can modify this function to suit your needs (ie. you can include not only path cost but any factor you wish).

    0 讨论(0)
  • 2020-12-25 09:11

    With A*, the path cost does not need to be constant, so you could start with the following graph:

    A---1---B---1---C
    |               |
    \-------1-------/
    

    where we want to go from A to C. Initially, the path finding algorithm will choose the A-C path since A-B-C is 2 whereas A-C is 1. We can add an extra term to the paths:

    A---r---B---r---C
    |               |
    \-------r-------/
    

    with

    r(NM) = k(NM) + users(NM) / 10
    

    where

    r(NM) is the cost for a connection between N and M,
    k(NM) is the constant cost for a connection between N and M,
    users(NM) is the number of objects using the connection
    

    As users are added to the system, the route A-C will become more expensive than A-B-C at twenty users (1 + 20/10) = 3, A-B-C is 2. As users are removed from the system, the A-C route will become the best option again.

    The real power of the A* is the heuristic you use to calculate the cost of each connection.

    0 讨论(0)
  • 2020-12-25 09:14

    Would a common Dijkstra's not be sufficient?

    http://improve.dk/generic-dijkstras-algorithm/

    0 讨论(0)
提交回复
热议问题