140 likes | 148 Views
Learn how to address common BFS minimum path issues, including re-expansion problems and data storage solutions. Explore algorithms, complexities, and optimization strategies for efficient pathfinding.
E N D
BFS: Min. Path Issues 0 {1,2} {0} {1,4} {4,3} {3,1} {2,3} wavefront = b t = 5 s t = 5 s a 2 b c t = 5 s reachingEdge = a reachingEdge = c • What happened? • Node 1 was re-expanded • Overwrote the reachingEdge • Messed up the path traceback 1 d t = 6 s d 3 e t = 3 s dest e 4 source
Solution 0 {2,3} {4,3} {1,2} {0} {3,1} {1,4} wavefront = b t = 5 s t = 5 s a 2 b, 5 s c t = 5 s Store shortest travel time from source at each node Only process node if shortest travel time to it has dropped a, 5 s 1 d t = 6 s d, 11 s 3 e t = 3 s dest e, 14 s 4 Fixed! source
Need To Store More Data structWaveElem { Node *node; int edgeID; // ID of edge used to reach this node double travelTime; // Total travel time to reach node WaveElem (Node *n, int id, float time) { node = n; edgeID = id; travelTime = time; } }; class Node { ... // Outgoing edges etc. intreachingEdge; // ID of the edge used to reach this node double bestTime; // Shortest time found to this node so far }
BFS with Re-expansion boolbfsPath (Node* sourceNode, int destID) { ... while (wavefront not empty) { WaveElem wave = wavefront.front (); // Get next node wavefront.pop_front(); // Remove from wavefront Node *currNode = wave.node; if (wave.travelTime < node->bestTime) { // Was this a better path to this node? Update if so. currNode->reachingEdge = wave.edgeID; currNode->bestTime = wave.travelTime; if (currNode->id == destID) // Found destination? return true;
BFS with Re-expansion for (each outEdgeof currNode) { Node *toNode = outEdge.toNode; wavefront.push_back ( WaveElem(toNode, outEdge.id, currNode->bestTime+ travelTime (outEdge)); } } // End if best path to this node } // End while wavefront not empty (more to search) return false; // No path exists! }
Breadth-First Search: Complexity while (wavefront not empty) { • If we use a visited flag: • Executes maximum N times • Work in loop is O(1) • O(N) ~100,000 10-7 < 1 s • BFS with re-expansion: • Difficult to bound • Can be significantly slower • Demo • How could we limit re-expansion?
Limiting Re-expansion • Only re-visit a node in BFS when • We find a new path with a lower cost to that node
BFS Wavefront boolbfsPath (Node* sourceNode, int destID) { list<WaveElem> wavefront; while (wavefront not empty) { WaveElem wave = wavefront.front(); // Get next element wavefront.pop_front(); // Remove from wavefront Node *currNode= wave.node; if (wave.travelTime< currNode->bestTime) { ... currNode->bestTime = wave.travelTime; wavefront.push_back( WaveElem(toNode, outEdge.id, currNode->bestTime+ travelTime (outEdge)); ... 78, 20s 2, 5s 39, 12s Wavefront: FIFO Queue
Take the Smallest Entry in Wavefront? 0 wavefront = {1/20s,4/19s} {0/0s} {1/20s} {1/20s,1/10s} {1/20s,2/5s} {1/20s,3/16s} b t = 5 s t = 20 s a 2 b, 5 s c t = 5 s c, 10 s 1 d t = 6 s d, 16 s 3 e t = 3 s Found shortest path with no / minimal re-expansion Djikstra’s algorithm dest e, 19 s 4 source
How Much Work To Get Smallest? • Linked list • Insertion: O(1) • Remove smallest: scan entire list • O(M), where M is active wavefront entries • M can be up to O(N), but usually more like O(N0.5) • Binary tree? • Insertion: O(log M) • Remove smallest • O(log M) 78, 20s 2, 5s 39, 12s list<WaveElem> wavefront
Overall Complexity • O(N) items added/removed in wavefront • Work to remove next item: • Linked list: O(M) O(N0.5) to O(N) • Binary tree: O(log M) O (log N) • Overall complexity • Linked list: O(N1.5) to O(N2) • N 100,000 and ~10-7 s per function • 3.2 s to 1000 s (wide range!) • Binary tree: O(N logN) • <1 s
Anything Faster than Binary Tree? • Heap • Insertion: O(log N) • Removal of smallest element: O(log N) • But absolute time smaller than binary tree
(Min) Heap • Like a binary tree • But not fully sorted • Key of parent < key of children • For all nodes in the tree • Very good for priority queues Smallest item always at root of heap 3 36 20 37 60 35 40 No ordering between sibling nodes in the heap 50