Algorithm Overview
The route-finding algorithm inFindLogic.js implements a custom pathfinding solution to find the optimal bus route between two geographic points. It uses a breadth-first search approach with distance-based optimization.
Location: src/server/FindLogic.js
Core Classes
Point Class
Represents a geographic location with latitude and longitude coordinates. Location:src/server/FindLogic.js:2-23
Haversine Formula
Thedistance() method implements the Haversine formula to calculate great-circle distance between two points on Earth.
Haversine Formula Explanation
Haversine Formula Explanation
The formula calculates the shortest distance over Earth’s surface:
- Convert to radians: Multiply degrees by π/180
- Calculate differences:
dLatanddLon - Apply Haversine:
- Calculate angular distance:
- Convert to kilometers:
distance = R × cwhere R = 6371 km
The Haversine formula assumes Earth is a perfect sphere. For more accuracy, consider using the Vincenty formula which accounts for Earth’s ellipsoid shape.
Stop Class
ExtendsPoint with bus stop specific properties.
Location: src/server/FindLogic.js:25-32
id- Unique stop identifierbranch_id- Bus line/branch identifiername- Human-readable stop namelatitude/longitude- Geographic coordinates (inherited)
Route Class
Represents a sequence of stops forming a potential route. Location:src/server/FindLogic.js:82-120
Key Methods
isValid()
isValid()
Purpose: Ensures the route doesn’t visit the same stop twiceLogic:
- Compares all pairs of stops
- Returns
falseif any duplicate IDs found - Prevents circular routes
isEqual(otherRoute)
isEqual(otherRoute)
Purpose: Checks if two routes are identicalLogic:
- Compares lengths first (fast rejection)
- Compares stop IDs in sequence
- Used to deduplicate routes
distance(destination)
distance(destination)
Purpose: Calculates distance from route’s end to destinationUsage: For sorting routes by proximity to destination
getNextRoutes()
getNextRoutes()
Purpose: Generates all valid route extensions from current routeLogic:
- Gets possible next stops from last point
- Creates new routes by appending each stop
- Filters out invalid routes (with duplicates)
Algorithm Configuration
| Parameter | Value | Purpose |
|---|---|---|
walkKmh | 1 km/h | Walking speed (conservative estimate) |
busKmh | 60 km/h | Average bus speed |
busWaitH | 0.5 hours | Expected wait time for bus |
maxWalkKm | 0.8 km | Maximum walking distance to/from stops |
Helper Functions
getCloseStops(from)
Finds all stops within walking distance of a point. Location:src/server/FindLogic.js:70-73
- Starting the journey
- Transferring between lines
- Ending the journey
getNextStop(point)
Gets the next stop on the same bus line. Location:src/server/FindLogic.js:57-68
- Find current stop index in
allStopsarray - Return
nullif at end of array - Return
nullif next stop is on different branch - Otherwise return next stop
This assumes stops are ordered sequentially in the
allStops array. The data structure depends on proper ordering from the backend.posiblesNextStops(stop)
Combines sequential and transfer possibilities. Location:src/server/FindLogic.js:75-79
- All stops within walking distance (for transfers)
- Next stop on same line (for staying on bus)
Main Algorithm: findRoute()
The core pathfinding function that implements a modified breadth-first search. Location:src/server/FindLogic.js:42-161
Algorithm Steps
Algorithm Characteristics
Search Strategy
The algorithm uses a greedy best-first search approach:- Explores all routes in parallel
- Sorts by distance to destination
- Keeps only the most promising routes
- Continues until destination is reachable
Termination Conditions
The search stops when:- Success: Closest route is within walking distance of destination
- Failure: No new routes can be generated
- Timeout: 50 iterations reached (
maxCount)
Performance Optimizations
Route Limit (10,000)
Route Limit (10,000)
Iteration Limit (50)
Iteration Limit (50)
Route Deduplication
Route Deduplication
Early Termination
Early Termination
walkKmh (1 km) instead of maxWalkKm (0.8 km) - potential bug?Algorithm Complexity
Time Complexity
- Best Case: O(n) - Direct route found immediately
- Average Case: O(n × m × k) where:
- n = number of stops
- m = average branches per stop
- k = iterations (max 50)
- Worst Case: O(n² × k) with deduplication overhead
Space Complexity
- Route Storage: O(maxRoutes × avgRouteLength)
- Maximum: ~10,000 routes × ~10 stops = 100,000 Stop objects
For large cities with thousands of stops, this algorithm may struggle. Consider implementing A* or Dijkstra’s algorithm for better scalability.
Algorithm Limitations
Current Issues
- No Cost Function: Doesn’t optimize for travel time
- Fixed Parameters: Walk/wait times are constants
- Sequential Stop Assumption: Relies on stops being ordered
- No Transfer Penalty: Doesn’t discourage excessive transfers
- Greedy Approach: May miss optimal solution
Potential Improvements
Implement A* Algorithm
Implement A* Algorithm
Replace greedy search with A* for guaranteed optimal path:
Add Transfer Penalty
Add Transfer Penalty
Discourage excessive transfers:
Optimize Deduplication
Optimize Deduplication
Use Set for O(1) lookup instead of O(n) filter:
Example Route Calculation
Let’s trace through a simple example: Input:- Start: (-34.5593, -58.4569)
- Destination: (-34.5805, -58.4513)
- Find Starting Stops: 3 stops within 0.8km of start
- Initial Routes:
[Route([Stop1]), Route([Stop2]), Route([Stop3])] - Iteration 1: Each route generates 2-4 extensions → 10 total routes
- Sort by Distance: Routes closest to destination first
- Iteration 2: Top 10 routes expanded → 30 total routes
- Deduplication: 5 duplicates removed → 25 routes
- Check Termination: Closest route 0.5km from destination
- Stop: Destination within walking distance
- Return:
[Stop2, Stop7, Stop15, Stop22]
Testing Considerations
Key test cases for the algorithm:- Direct route (start and end on same bus line)
- Single transfer required
- Multiple transfers required
- No route available (isolated locations)
- Very close start/end points
- Maximum walking distance edge cases
Next Steps
Explore related architecture:- Backend Architecture - How the algorithm is invoked
- Frontend Architecture - How routes are displayed