File: google-maps/map_routing.py

Date: 2026-06-05

Time: 13:49

google-maps/map_routing.py — Map Routing Service

Purpose

This file implements a map routing service — the core pathfinding engine behind a Google Maps-style system design. It owns the responsibility of modeling a road network as a weighted graph and computing routes through it, including shortest-path queries, alternative routes, ETA estimation, turn-by-turn directions, and basic map tile serving. It's a self-contained single-file implementation designed to demonstrate the key algorithmic and architectural concepts you'd discuss in a system design interview for Google Maps.

Key Components

Data Models

Four @dataclass types define the domain:

Geo Utilities

MapService

The main class. Three internal data structures:

| Field | Type | Role |

|-------|------|------|

| self.nodes | dict[str, Node] | Node lookup by ID |

| self.adj | dict[str, dict[str, dict]] | Adjacency list — adj[u][v] is edge data dict |

| self.geocode_map | dict[str, tuple] | Name-to-coordinates index (lowercased) |

Graph construction:

Pathfinding:

Alternative routes:

Route construction:

Supporting features:

Patterns

1. Graph as adjacency dict — Rather than a formal graph class, the road network is a nested dict (adj[u][v] = {roadname, distancekm, speedlimitkmh}). This is the standard Python idiom for weighted directed graphs and keeps edge lookup O(1).

2. Strategy pattern via optimize parameter — The weight function and heuristic both branch on optimize, allowing the same algorithm to serve both shortest-distance and fastest-time queries without code duplication.

3. Yen's algorithm for K-shortest paths — A well-known algorithm choice for alternative routes. The implementation blocks edges (not nodes) from previously found paths, which is the edge-disjoint variant.

4. Input types vs. internal representationEdge dataclass is used only at the API boundary (add_edge). Internally, edges are plain dicts. This avoids coupling internal traversal to the input schema.

5. Dual-mode A*/Dijkstra — The heuristic is conditionally zero, which collapses A* to Dijkstra. One code path, two algorithms.

Dependencies

Imports: Only standard library — heapq for the priority queue, math for trig/geo calculations, dataclasses for the data models. No external dependencies.

Imported by: testmaprouting.py — the test suite. No other modules in the repo depend on this.

Flow

A typical usage sequence:

1. Build graph: Call addnode() for each intersection, then addedge() for each road segment.

2. Query a route: Call shortest_path("A", "B", optimize="time").

3. Alternative routes: alternative_routes("A", "B", k=3) iterates: for each prefix of the best path, it blocks the edge that was taken and re-runs A* from the spur node. Candidate paths are kept in a min-heap sorted by total distance.

Invariants

Error Handling

Error handling is minimal and follows the "return None" convention:

There are no exceptions raised anywhere in this module — all failures are communicated via None or empty collections.

Topics to Explore

Beliefs