Introduction to Logistics Routing and Distribution Challenges Within the logistics and supply chain industry, intelligent routing is key for delivering products to customers faster and more cost-effectively. Different modes of distribution — road, rail, air, and sea — each carry their own trade-offs between distance, cost, and delivery time. Road transportation alone is responsible for roughly 53% of global transport CO2 emissions, and organisations worldwide are under growing pressure to improve delivery management without expanding their environmental footprint. According to a McKinsey-cited industry analysis, the road freight market is expected to grow by around 6% annually through 2027. As volumes grow, the need for greener routing becomes more than a sustainability talking point — it becomes an operational constraint. The pressures stack up: cutting fuel use, meeting tight delivery deadlines, and planning routes that are demonstrably better for the environment. The growth in online shopping has compounded this. Over half of retailers now offer same-day delivery in some markets, and customer expectations continue to compress the planning window for every shipment. Sitting underneath all of this is the Vehicle Routing Problem (VRP) — a complex optimisation task that asks for the most efficient set of routes for a fleet of vehicles serving multiple delivery points. The VRP is the structural reason that “just plan better routes” is harder than it sounds. Practical solutions need to balance fuel, distance, time, capacity, and time windows simultaneously, and the search space explodes as the number of stops grows. We explore the wider landscape of AI-driven navigation and pathfinding in a related article; here, we walk through the VRP itself and how to solve a realistic instance with Python and Google OR-Tools. A brief timeline of routing optimisation and VRP. Source: DistanceMatrix What Is the Vehicle Routing Problem? The Vehicle Routing Problem focuses on finding the most cost-effective routes for a fleet of vehicles to deliver goods to multiple customers from one or more depots. It is NP-hard, which means that solving it exactly becomes computationally infeasible as the problem grows. In practice, heuristic and metaheuristic methods dominate — they give good-enough routes in reasonable time, even when the optimal route is out of reach. (This is an observed pattern across operations-research literature, not a benchmark of any single tool.) An example of a VRP where each node is visited once by a single vehicle starting and ending at a central depot. Source: AWS Amazon There are several VRP variants, each modelling a different real-world constraint: Travelling Salesman Problem (TSP) — find the shortest route visiting every stop once and returning to the start. One vehicle, no capacity limits. The combinatorial baseline. Capacitated VRP (CVRP) — each vehicle has a weight or volume limit, and routes must respect it. This is the version most distribution fleets actually face. VRP with Time Windows (VRPTW) — every customer has a delivery slot. Routes must arrive within window, which couples routing to scheduling. An example of a vehicle routing problem with time windows. Source: Altamira Solving any of these well delivers the same class of business outcome: fewer kilometres driven, lower fuel burn, fewer vehicles on the road, and tighter adherence to delivery promises. Which Algorithms Solve the VRP in Practice? Three families of metaheuristics show up repeatedly in the literature and in production routing engines: Genetic Algorithms — evolve a population of candidate routes through selection, crossover, and mutation. Good at escaping local optima on large instances. Ant Colony Optimisation — mimics how ants reinforce short paths with pheromone trails. Strong on sparse graphs and when routes share structure. Simulated Annealing — accepts occasional worse moves early in the search to avoid getting trapped, then gradually “cools” toward a final solution. For most teams, the practical entry point is not implementing these from scratch but using a library that exposes them behind a clean API. Google OR-Tools is the one we reach for most often in Python projects — it ships with first-solution heuristics (cheapest arc, savings, Christofides) and local-search metaheuristics (guided local search, simulated annealing, tabu search), and it handles capacities, time windows, and pickup-and-delivery constraints out of the box. Step-by-Step: Solving a VRP with Python and Google OR-Tools To make this concrete, we will walk through a realistic instance: a manufacturer with a central depot needs to dispatch three vehicles across thirteen major US cities, minimising total distance while respecting a per-vehicle maximum route length. Setup You need Python 3.7+ and the OR-Tools package: pip install ortools Defining the Problem The depot sits in Denver, Colorado (index 4 in the matrix below). Twelve other cities — New York, Los Angeles, Chicago, Minneapolis, Dallas, Seattle, Boston, San Francisco, St. Louis, Houston, Phoenix, and Salt Lake City — are the delivery points. Three vehicles start and end at the depot. The objective: minimise the total distance, with no single vehicle exceeding 4,000 miles. The data the solver needs: A distance matrix — pairwise distances between every pair of locations. The number of vehicles in the fleet. The depot index — the start and end node for every vehicle. (For CVRP) per-vehicle capacities and per-stop demands; for VRPTW, per-stop time windows. Data Model from ortools.constraint_solver import routing_enums_pb2 from ortools.constraint_solver import pywrapcp def create_data_model(): """Stores the data for the problem.""" data = {} # 0 NY, 1 LA, 2 Chicago, 3 Minneapolis, 4 Denver (depot), # 5 Dallas, 6 Seattle, 7 Boston, 8 San Francisco, # 9 St. Louis, 10 Houston, 11 Phoenix, 12 Salt Lake City data["distance_matrix"] = [ [0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972], [2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579], [713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260], [1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987], [1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371], [1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999], [2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701], [213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099], [2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600], [875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162], [1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200], [2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504], [1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0], ] data["num_vehicles"] = 3 data["depot"] = 4 return data Building the Routing Model OR-Tools separates the index manager (which translates between routing indices and node indices) from the routing model (which holds the constraints and the solver state): def main(): data = create_data_model() manager = pywrapcp.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"], ) routing = pywrapcp.RoutingModel(manager) The Distance Callback The solver asks “what does it cost to go from node A to node B?” through a callback. Ours just reads the distance matrix: def distance_callback(from_index, to_index): from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data["distance_matrix"][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(distance_callback) routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) Adding a Maximum-Distance Constraint To prevent the solver from loading one vehicle with most of the cities, we add a per-vehicle distance dimension capped at 4,000 miles: dimension_name = "Distance" routing.AddDimension( transit_callback_index, 0, # no slack 4000, # maximum travel distance per vehicle True, # start cumulative at zero dimension_name, ) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(0) Setting the global span cost coefficient higher than zero would tell the solver to balance route lengths across vehicles. We leave it at zero to keep the objective focused on total distance. Solving and Printing search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) solution = routing.SolveWithParameters(search_parameters) if solution: print_solution(data, manager, routing, solution) def print_solution(data, manager, routing, solution): print(f"Objective: {solution.ObjectiveValue()}") for vehicle_id in range(data["num_vehicles"]): index = routing.Start(vehicle_id) route = f"Route for vehicle {vehicle_id}:\n" route_distance = 0 while not routing.IsEnd(index): route += f" {manager.IndexToNode(index)} ->" previous_index = index index = solution.Value(routing.NextVar(index)) route_distance += routing.GetArcCostForVehicle( previous_index, index, vehicle_id ) route += f" {manager.IndexToNode(index)}\n" route += f"Distance of the route: {route_distance} miles\n" print(route) if __name__ == "__main__": main() Output Objective: 8653 Route for vehicle 0: 4 -> 9 -> 0 -> 7 -> 2 -> 3 -> 4 Distance of the route: 3790 miles Route for vehicle 1: 4 -> 5 -> 10 -> 4 Distance of the route: 1767 miles Route for vehicle 2: 4 -> 11 -> 1 -> 8 -> 6 -> 12 -> 4 Distance of the route: 3096 miles Maximum of the route distances: 3790 miles Vehicle 0 swings east and north (St. Louis, New York, Boston, Chicago, Minneapolis). Vehicle 1 handles the southern leg (Dallas, Houston). Vehicle 2 covers the west (Phoenix, LA, San Francisco, Seattle, Salt Lake City). All three respect the 4,000-mile cap, and the total distance comes in at 8,653 miles. A visualisation of the output. Source: TechnoLynx How to Extend This Model The skeleton above is deliberately small. Real fleets need more: Capacities — add a Capacity dimension with per-stop demands and per-vehicle limits to turn this into a CVRP. Time windows — add a Time dimension with service times, travel-time callback, and per-stop windows for VRPTW. Heterogeneous fleet — register different transit callbacks per vehicle when costs differ (refrigerated trucks, electric vans, sub-contractors). Multiple depots — pass arrays for the starts and ends arguments to the index manager. The structure of the solve — manager, model, callback, dimensions, search parameters — stays the same. Most production complexity lives in the dimensions you add and the search parameters you tune. Where VRP Actually Pays Off VRP-based optimisation has been credited with substantial cost reductions in distribution case studies. One Coca-Cola distribution study reported around 34% in cost reductions after consolidating into a centralised network with optimised routing — a published-survey figure, not a benchmark you should expect to reproduce, but a useful order-of-magnitude indicator of what better routing can unlock. The more recent shift is the layering of machine learning on top of VRP. Amazon’s one-hour delivery operation, for example, combines demand forecasting (where will orders come from in the next hour?) with routing (which vehicle should serve them?). The forecast tells the system which inventory to pre-position; the router turns that pre-positioning into actual schedules. What we see in our own engagements — as an observed pattern across logistics-leaning projects, not a benchmarked rate — is that the biggest gains come less from a more clever algorithm and more from honest constraint modelling: getting capacities right, getting time windows right, and getting service-time estimates that match what drivers actually do. A mediocre solver fed accurate constraints beats a sophisticated solver fed wishful constraints almost every time. The benefits that compound from there are familiar: Cost — fewer miles, less fuel, less wear. Speed — tighter adherence to promised delivery windows. Fleet utilisation — the same work done by fewer vehicles. Carbon — directly correlated with miles driven, so route savings convert almost one-for-one. For the broader picture of how this fits into supply-chain AI, see how AI is reshaping the supply chain. What TechnoLynx Builds Around This At TechnoLynx, our work in this area is rarely “install OR-Tools and call it a day.” Production routing systems sit at the intersection of optimisation, real-time data, and integration. We work with clients on: Custom constraint models — the difference between a textbook VRP and a working distribution system is the long tail of real constraints: driver shifts, customer access windows, vehicle-skill matching, multi-trip routes. Demand forecasting upstream of routing — using historical orders and seasonality to pre-position inventory and shape the routing problem itself. Real-time replanning — handling exceptions (late starts, missed windows, vehicle breakdowns) without re-solving from scratch. The aim is to make routing decisions that hold up when the world moves, not just on the day the model is delivered. If your distribution operation is hitting the limits of spreadsheet-driven planning, reach out to TechnoLynx — we can scope what an AI-driven routing layer would look like for your specific constraints. Where to Read Next For the bigger arc of how AI is changing supply-chain operations, the companion piece Transformative Role of AI in Supply Chain Management sits one level up from this article — less code, more strategic framing. Frequently Asked Questions What is the Vehicle Routing Problem? The Vehicle Routing Problem (VRP) is the optimisation question of how to assign a set of delivery stops to a fleet of vehicles, and in what order each vehicle should visit them, to minimise a cost function like total distance or total time. It generalises the Travelling Salesman Problem to multiple vehicles and typically adds constraints such as vehicle capacities, time windows, and maximum route length. It is NP-hard, so practical solvers use heuristics and metaheuristics rather than exact methods. Why is the VRP hard to solve exactly? The number of possible route assignments grows factorially with the number of stops, so exhaustive search is infeasible beyond roughly twenty stops. Even with smarter branch-and-bound techniques, exact solutions for instances with hundreds of stops are out of reach in production time budgets. This is why operational systems rely on heuristics — they give good solutions in seconds rather than provably optimal ones in hours. Which Python library is best for solving the VRP? Google OR-Tools is the most widely used open-source option. It exposes a clean Python API, ships with both first-solution heuristics and local-search metaheuristics, and handles the standard VRP variants (capacitated, time-windowed, multi-depot, pickup-and-delivery) without custom code. For specialised cases — very large instances or unusual constraints — commercial solvers like Gurobi or specialised routing engines may justify their cost, but OR-Tools is the right starting point for most teams. How much can route optimisation actually save? Published case studies report cost reductions in the 10–35% range when distribution operations move from manual or spreadsheet-based planning to optimised routing — though the exact figure depends heavily on the baseline. In our experience, the largest gains come from operations with many stops per vehicle, tight time windows, and previously static route plans. Operations already running mature TMS software tend to see smaller incremental improvements. What is the difference between TSP, CVRP, and VRPTW? TSP (Travelling Salesman Problem) is the single-vehicle, no-capacity case — find the shortest tour that visits every stop once. CVRP (Capacitated VRP) extends this to a fleet where each vehicle has a weight or volume limit and each stop has a demand. VRPTW (VRP with Time Windows) adds a per-stop delivery window, coupling routing to scheduling. Most real distribution problems are some combination of CVRP and VRPTW. Sources for the Images Freepik. Logistics means of transport together with technological and futuristic holograms DistanceMatrix.ai. Streamlining Logistics: The Science of Routing Optimisation and the VRP Nightingale, M. and Subramanian, S. (2023). Deploy a serverless application to optimise vehicle routing with Amazon Location Service. AWS. Didenko, O. (2021). Vehicle Routing Software Problem: How to Effectively Solve. Altamira. References Baker, B.M. and Ayechew, M.A. (2003). A genetic algorithm for the vehicle routing problem. Computers & Operations Research, 30(5), pp. 787–800. Bell, J.E. and McMullen, P.R. (2004). Ant colony optimization techniques for the vehicle routing problem. Advanced Engineering Informatics, 18(1), pp. 41–48. Google (2024). Vehicle Routing Problem — OR-Tools. Jayarathna, D.G.N.D., Lanel, G.H.J. and Juman, Z.A.M.S. (2022). Industrial vehicle routing problem: a case study. Journal of Shipping and Trade, 7(6). Joshi, V. (2017). The Trials and Tribulations of the Travelling Salesman. basecs. Praveen, V. et al. (2022). Vehicle Routing Optimisation Problem: A Study on the Capacitated VRP. Materials Today: Proceedings, 64(1), pp. 670–674. Selyukh, A. (2018). Optimized Prime: How AI and Anticipation Power Amazon’s 1-Hour Deliveries. NPR. Shipsy (2024). Key Challenges in Real-Life Vehicle Routing. Truden, C., Maier, K. and Armbrust, P. (2022). Decomposition of the VRP with time windows on the time dimension. Transportation Research Procedia, 62, pp. 131–138. Wei, L., Zhang, Z., Zhang, D. and Leung, S.C.H. (2018). A simulated annealing algorithm for the capacitated VRP with two-dimensional loading constraints. European Journal of Operational Research, 265(3), pp. 843–859.