4

I am trying to implement Dijkstra's algorithm which can find the shortest path between the start node and the end node. Before reach the end node there are some 'must-pass' intermediate nodes (more than one) for example 2 or 3 must pass nodes which must pass before reach the end node.

If i have one must pass node the solution i found is find two different paths from the must pass node to destination and from must pass node to start node.

I am out of ideas how i can implement such an algorithm. Any suggestions?

Thanks.

List<Node> closestPathFromOrigin = null;

double maxD = Double.POSITIVE_INFINITY;
double _distance = 0;
int temp1 = 0;
List<Node> referencePath = new ArrayList<>();
boolean check = false;
Node startNode = null;

public List<Node> recursion(ArrayList<Node> points, ArrayList<Node> intermediatePoints) {

    if (!check) {
        System.out.println("--- DATA ---");
        System.out.println("Intermediate points: " + intermediatePoints);
        System.out.println("points: " + points.get(0).lat + " " + points.get(1).lat);
        System.out.println("--Find the nearest intermediate point from the start point of driver--");
        startNode = points.get(0);
        System.out.println("Start point of driver: " + startNode.lat + " " + startNode.lon);
        for (int i = 0; i < intermediatePoints.size(); i++) {
            List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
            _distance = 0;
            for (int j = 0; j < _path.size() - 1; j++) {
                _distance += calculateDistance(_path.get(j), _path.get(j + 1));
            }
            if (_distance < maxD) {
                maxD = _distance;
                closestPathFromOrigin = _path;
                temp1 = i;
            }
        }
        System.out.println("NearestPoint from driver's origin: " + intermediatePoints.get(temp1));

        referencePath.addAll(closestPathFromOrigin);
        startNode = intermediatePoints.get(temp1);
        System.out.println("New StartNode: the nearestPoint from driver's origin: " + startNode.lat + " " + startNode.lon);
        check = true;
        intermediatePoints.remove(intermediatePoints.get(temp1));
        System.out.println("New Intermediate points: " + intermediatePoints);
        System.out.println("Intermediate points empty? No -> recursion, Yes -> stop");
        if (!intermediatePoints.isEmpty()) {
            System.out.println("Recursion!!! with new data of: intermediatePoints: " + intermediatePoints);
            recursion(points, intermediatePoints);
        } else {
            System.out.println("Stop");
            return referencePath;
        }
    } else {
        System.out.println("Recursion: startNode: " + startNode.lat + " " + startNode.lon);
        for (int i = 0; i < intermediatePoints.size(); i++) {
            if (intermediatePoints.size() > 1) {
                System.out.println("From the new start point to the next nearest intermediate points if more than one points");
                List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
                _distance = 0;
                for (int j = 0; j < _path.size() - 1; j++) {
                    _distance += calculateDistance(_path.get(j), _path.get(j + 1));
                }
                if (_distance < maxD) {
                    maxD = _distance;
                    closestPathFromOrigin = _path;
                    temp1 = i;
                }
                referencePath.addAll(closestPathFromOrigin);
                startNode = intermediatePoints.get(temp1);
                check = true;
                intermediatePoints.remove(intermediatePoints.get(temp1));
                if (!intermediatePoints.isEmpty()) {
                    recursion(points, intermediatePoints);
                } else {
                    return referencePath;
                }
            } else {
                System.out.println("From the new start point to the next nearest intermediate points if just one point");
                List<Node> _path = dijkstra(startNode, intermediatePoints.get(i));
                //Collections.reverse(_path);
                referencePath.addAll(_path);
            }
            if (i == intermediatePoints.size() - 1) {
                System.out.println("Last Entry in intermediate points - find path to destination: " + points.get(1).lat + " " + intermediatePoints.get(i));
                //List<Node> _path1 = dijkstra(points.get(1), intermediatePoints.get(i));
                List<Node> _path1 = dijkstra(intermediatePoints.get(i), points.get(1));

                Collections.reverse(_path1);
                referencePath.addAll(_path1);
               //  referencePath.addAll(_path2);
            }
        }
    }
    return referencePath;
}
  • 4
    If you have must pass nodes then you will run your Djikstra's algorithm multiple times. Do your same logic with start to intermediate 1, then again from intermediate 1 to intermediate 2, etc... until you reach your end. –  Aug 18 '14 at 17:22
  • Show us, what you have tried please – Balázs Édes Aug 18 '14 at 17:22
  • I tried to do a recursion method by calling the Dijkstra's algorithm several times. First find the nearest point from the start node. I just add the code above. –  Aug 18 '14 at 17:25
  • So this is a directed graph? or undirected? – Alpenglow Aug 18 '14 at 17:37
  • BTW, if you have an end node, you should actually use A* instead of Dijkstra's. But if the order in which to pass the intermediate nodes is not fixed, then you could use Dijkstra's to find shortest paths from some must-pass node to all the others in one pass. – tobias_k Aug 18 '14 at 17:38
  • 1
    Is a directed graph. –  Aug 18 '14 at 17:40
  • 1
    @DanK He didn't specify that the must-pass nodes have an order. How do you suppose he could find an optimal order efficiently? – G. Bach Aug 19 '14 at 01:54

3 Answers3

5

This is a generalisation of the travelling salesman problem. The TSP comes up as the case where all vertices are "must-pass".

Find shortest paths between each pair of must-pass vertices, from the source to each must-pass vertex, and from each must-pass vertex to the sink. Then use the famous O(n 2^n) dynamic programming algorithm for TSP to find the shortest path from source to sink meeting your constraints; here n will be two plus the number of must-pass vertices.

tmyklebu
  • 13,915
  • 3
  • 28
  • 57
  • Thanks a lot. Do you have an tutorial link in order to understand how i can implement the TSP algorithm? –  Aug 18 '14 at 17:36
1

By finding shortest path between must include node and two(end and start) node. Form graph, then run shortest path algo(Dijkstra's algorithm). Start and end nodes will be same.

kafee651
  • 67
  • 9
1

Unfortunately this problem is reduced to TSP so dont expect a polynomial solution but if no of intermediate node are small then you can do this reasonably fast like following :-

  1. try every sequence of nodes to visit possible.
  2. say you have s->a->b->c->d
  3. then evaluate min(s,d) + min(d,a) + min(c,d) using dijkstra
  4. the sequence that has minimum distance is your answer.

Time complexity : O(k!*ElogV) where k is no of must pass nodes

Vikram Bhat
  • 6,106
  • 3
  • 20
  • 19