## Search in the document preview

**ECE 297:
Graphs and Pathfinding
**

Efficient use of graphs

Tomasz Czajkowski

ECE297: Design and Communication 1

Internet Routing source

dest

Nodes: computers and switches Edges: cables Find a path to connect computers Typical minimum weight path definition: •Fewest routers •Or least congested

2

Circuit Board Design

Nodes: small square for metal Edges: squares we can connect Find paths to connect chip I/Os

3

Integrated Circuits

Nodes: small grid squares for metal Edges: squares we can connect Find paths to connect gates Huge graph (tens of millions of nodes) need fast algorithms

4

Can pathfinding algorithms be helpful in our project?

5

Directions: How?

6

Model as Graph Problem (Node)

(Edge) B athurst

Path: sequence of connected nodes from a source to a dest

source

dest

7

Model as Graph Problem

Path: store as sequence of nodes?

B athurst

source

dest

back lane

Now sequence of nodes doesn’t uniquely

describe path

8

Model as Graph Problem

B athurst

Better: sequence of connected edges from a source to a dest

source

dest

9

Finding Routes

Find path from source to dest – Is there only one path?

Any path? Fewest nodes? Fewest edges? Minimum travel time! Graph texts:

minimum weight path or shortest path

source

dest

10

Blue path: 200 m / 40 kmh + 300 m / 50 kmh + 1 turn 18 s + 21.6 s + 15 s = 54.6 s

200 m

300 m

Red path: 100 m / 40 kmh + 200 m / 40 kmh + 200 m / 50 kmh + 2 turns 9 s + 18 s + 14.4 s + 2*15 s

= 71.4 s

100 m

Minimum Travel Time Definition
Distance / speed limit + *turn_penalty* per street change

Which is better if turn_penalty = 15s?

source

dest

11

Minimum Travel Time Definition

Don’t left turns take longer than right turns? – Yes, we’re ignoring to keep simple

Street change with no turn? – Still 15 s

*Bloor St. EastBloor St. West
*

*Yonge St.
*

*Yonge St.
*

15 s penalty

No penalty

12

Depth First Search

Shortest Path Algorithm #1

13

Recursion?

int main () { Node *sourceNode = getNodebyID (sourceID); bool found = findPath (sourceNode, destID); . . . }

bool findPath (Node* currNode, int destID) { ... }

source

dest

14

bool findPath (Node* currNode, int destID) {
if (currNode->id == destID)
return (true);
for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
bool found = findPath (toNode, destID);
if (found)
return (true);
}
return (false);
}

Recursion?

source

dest

1

2

3

3

4

15

Recursion?

source dest

bool findPath (Node* currNode, int destID) {
if (currNode->id == destID)
return (true);
for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
bool found = findPath (toNode, destID);
if (found)
return (true);
}
return (false);
}

Infinite Loop!

16

How to Fix?

source dest

bool findPath (Node* currNode, int destID) { if (currNode->id == destID) return (true); currNode->visited = true;

for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
if (!toNode->visited) {
bool found = findPath (toNode, destID);
if (found)
return (true);
}
}
return (false);
}

toNode visited

17

Output? bool findPath (Node* currNode, int destID) { . . . return (true); . . . }

18

source dest

• Says whether or not a path was found

• But not what the path is!

• Worst directions ever: yes, a path exists!

• How to fix?

Depth First Seach: Output Fix
bool findPath (Node* currNode, int destID, list<Edge> path) {
if (currNode->id == destID) return true;
currNode->visited = true;
for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
if (!toNode->visited) {
list<Edge> newPath = path;
newPath.push_back (outEdge);
bool found = findPath (toNode, destID, newPath);
if (found)
return (true);
}
}
return (false);
}

source dest

Anything Missing?

a

b

c

d {} {a}

{a,b}

{a,b,c,d}

{a,b,c}

19

Easy Fix Part 2
bool findPath (Node* currNode, int destID, list<Edge> path) {
if (currNode->id == destID)
* print out or save the path, then return (true);
* currNode->visited = true;

for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
if (!toNode->visited) {
list<Edge> newPath = path;
newPath.push_back (outEdge);
bool found = findPath (toNode, destID, newPath);
if (found)

return (true); } } return (false); } source

dest

20

Depth First Search (DFS)

Developed depth first search in a graph – Need a visited flag – Unlike a tree (can go in circles

otherwise)

Graph is big (>100,000 nodes, N) – Complexity of DFS?

21

Complexity Analysis
bool findPath (Node* currNode, int destID, list<Edge> path) {
if (currNode->id == destID)
* print out or save the path, then return (true);
* currNode->visited = true;

for each (*outEdge of currNode*) {
Node *toNode = outEdge.toNode;
if (!toNode->visited) {
list<Edge> newPath = path;
newPath.push_back (outEdge);
bool found = findPath (toNode, destID, newPath);
if (found)
return (true);
}
}
return (false);
}

At most one findPath call per Node

Executes once per outgoing edge

Average: about 4

22

Complexity

findPath executes at most O(N) times – Constant, O(1), work in each call – Except copying path – path could have O(N) nodes – Total worst-case complexity: O(N2) – Average path shorter

Average case somewhat better, but hard to analyze

23

Complexity

Can we do better? – Don’t pass entire path around – One way: each Node stores the edge used to

reach it • e.g. node.reachingEdge

– Reconstruct path when you reach the dest • By following the previous edges / “bread crumbs”

– Now work per findPath is O(1) Total complexity is O(N) • Good for a graph algorithm!

24

Thank you

ECE297: Design and Communication 25