Vehicle Breakdown Contingency Plan to Reduce Delivery Failures

In the sector of logistics and transportation, the reliable movement of goods is paramount to the success of any supply chain. The efficiency and effectiveness of these operations heavily depend on the uninterrupted functionality of vehicles tasked with delivering products to their designated destinations. Vehicle breakdowns, however, remain an ever-present threat, capable of causing significant disruptions, delays, and ultimately, delivery failures.

To mitigate the adverse impact of vehicle breakdowns on the logistics ecosystem, accurate and systematic contingency planning is essential. This technical notebook explores the strategies, methodologies, and tools involved in designing a robust Vehicle Breakdown Contingency Plan (VBCP). The primary objective is to minimize the likelihood of delivery failures and optimize the recovery process when vehicle breakdowns inevitably occur.

In this technical notebook, we utilize the capabilities of various NextBillion.ai products, specifically, the Route Optimization API, Isochrone API, Directions API, and the Web Map SDK. Our objective is to propose a viable solution for mitigating vehicle breakdowns within the courier delivery sector. Our exploration revolves around optimizing this issue by minimizing either time or distance.

By implementing a well-structured Vehicle Breakdown Contingency Plan, logistics and transportation professionals can better adapt to unforeseen challenges, maintain delivery schedules, and ultimately reduce the negative impact of vehicle breakdowns on their operations. The subsequent sections of this technical notebook will delve deeper into each of these critical aspects, providing a comprehensive guide for practitioners seeking to enhance the reliability and resilience of their supply chain operations.

Problem Statement

This scenario involves a courier company operating from a singular warehouse in a designated city, executing 50 daily orders using a fleet of 10 vehicles, each accommodating up to 10 units. Commencing at 12:15 with a 5-hour shift duration, the challenge arises from the inherent unpredictability of vehicle breakdowns. A system must be devised to adeptly manage deliveries in the event of a breakdown, swiftly identifying the nearest available vehicles and redistributing the affected vehicle’s load among them. 

This redistribution must adhere to two critical conditions: 

  • the combined capacity of the selected vehicles must meet the total load, and 
  • the drivers’ maximum shift times must not be exceeded.

Approach

  1. Utilize the Route Optimization API for preemptive job assignment to vehicles before the shift commencement.
  2. To simulate breakdown scenarios, induce failures at specific points along a vehicle’s route.
  3. Conduct a 15-minute isochrone analysis from the failure point, identifying vehicles within this temporal range. Subsequently, for each vehicle, execute the following sequence until all orders are reassigned:
    • Assess the vehicle’s capacity to fulfill orders, considering potential space availability due to prior deliveries.
    • Execute an MVRP from the failure point, incorporating any new orders and pending deliveries. Confirm the vehicle’s ability to fulfill these orders and return to the depot within the shift duration.     
    • If the conditions align, assign the new orders to the vehicle.
    • Repeat the above process for isochrones of 30 and 45 minutes until either no available vehicles are within those timeframes or all orders have been successfully reassigned.

Constraints

In outlining the solution, we acknowledge certain constraints, although it’s worth noting that the Route Optimization API can effectively handle each of them.

  1. Uniform Vehicle Capacity: All vehicles are presumed to possess identical capacities.
  2. Payload Weight Consideration: Payload weight is not a variable in determining vehicle capacity. We operate under the assumption that all items share a uniform unit weight, and that each item is singular in quantity.
  3. Generalized Order Assignment: Any vehicle can be assigned any order without consideration for specific skills or specializations. For instance, specialized vehicles, such as refrigerated ones for transporting frozen goods, are not factored into the assignment process.

Additionally, to enable the integration of NextBillion functionalities, the API key should be set using the command:

nextbillion.setApiKey(apiKey)

Parameters

This section encapsulates the foundational variables influencing our optimization model for efficient courier delivery operations.

Vehicle capacity:  10     

Number of vehicles:  5     

Selected city:  Los Angeles 

Number of orders:  50

Objective Function:  Minimize Time     

Shift duration (in hours):  5     

Shift start time: October 11’ 2023, 12.15 AM

Solution Steps

Let’s break down the solution steps to gain a better understanding.

1. Generate Random Data

Orders Map

The map below shows the spatial distribution of orders denoted by 📦, alongside the central depot marked with 🏢.

generate random data

The following code snippet integrates Map functionality to visually represent the geographical layout of orders and the depot on an interactive map. The map is created dynamically based on provided data, and markers are drawn accordingly.

{
apiKey;

  const centroid = city.centroid.split(",");
  const nbmap = createMap("map", centroid);

  nbmap.on("load", function () {
    drawDepot(nbmap.map, centroid);

    data.jobs.forEach((job, i) => {
      drawOrder(nbmap.map, job.location);
    });
  });
}
List of Vehicles

This is the list of vehicles available in the database.

ID

Description

Time Start

Time End

Minutes

Orders

1

Isuzu VehiCROSS

0:15

5:15

300

10

2

Lexus LS

0:15

5:15

300

10

3

Jaguar S-Type

0:15

5:15

300

10

4

Porsche Cayenne

0:15

5:15

300

10

5

Suzuki XL-7

0:15

5:15

300

10

6

Ford Edge

0:15

5:15

300

0

7

Lexus GS

0:15

5:15

300

0

8

Audi A6

0:15

5:15

300

0

9

Land Rover Range Rover Sport

0:15

5:15

300

0

10

Maserati Spyder

0:15

5:15

300

0

 

2. Submit the problem to the Route Optimization API Endpoint

In this phase, the problem is submitted to the API endpoint, and the resulting data is retrieved and processed. The obtained information, stored in `mvrpResult`, encompasses the optimized routes for efficient vehicle allocation and order distribution.

mvrpResult = (await mvrp(data)).result				
initialRoutes = new Map(
  mvrpResult.routes.map((route) => [route.vehicle, route])
)				

To enhance clarity, the initial routes are organized into a Map structure, `initialRoutes`, where each vehicle is paired with its corresponding route data.

3. Visualize Vehicle Routes

To facilitate analysis, the notebook provides an interactive selection mechanism. Below, choose a vehicle from the dropdown menu to visualize its route:

Select Vehicle: Isuzu VehiCROSS

vehicle routes

4. Simulate Failure

Opt for a vehicle to undergo simulated failure, and specify the route step where the failure should occur:

  • Vehicle to fail: Isuzu VehiCROSS

  • Vehicle breakdown step: Reichel Group

The subsequent cell facilitates visualizing the route undertaken by the designated vehicle post-failure.

5. Reassign orders

After simulating a breakdown, the next crucial step involves the strategic reassignment of orders to maintain operational efficiency. 


isochrone = runIsochrone(
  failureStep.location,
  failedVehicle.time_window[0] + failureStep.duration
)

Here, an isochrone analysis is conducted from the failure location, extending up to the calculated time window of the failed vehicle.

reassign orders
Reassign orders from failed vehicle

The following table summarizes the status of job assignments and travel times for the affected vehicles.

 

Vehicle Name

Jobs (original)

Jobs Completed

Jobs (Reassigned)

Jobs (Updated)

Travel Time (Original)

Travel Time (Updated)

Porsche Cayenne

10

3

3

10

132

162

Lexus LS

10

3

3

10

159

171

Reassignment Process Overview

1. Isochrone Exploration

    • Determine vehicles within the isochrone radius.
    • Prioritize vehicles based on proximity to the failure point.

2. Iterative Assignment

For each selected vehicle:

    • Assess available capacity for new assignments.
    • Execute MVRP to validate the feasibility of new orders.

3. Result

A comprehensive report encompassing unassigned orders, reassigned orders, updated routes, and associated geometries.


  reassignResult = {
  let newOrders = new Map();
  let routes = new Map();
  let geometries = new Map();

  let unassignedOrderIds = onlyJobs(initialRoutes.get(failedVehicle.id).steps)
    .filter(afterFailure)
    .map((step) => step.id);

  let isochroneIdx = 0;

  while (unassignedOrderIds.length > 0 && isochroneIdx < 3) {
    const sortedVehicleIds = vehiclesInIsochrones[isochroneIdx]
      .map((vehicleId) => [
        vehicleId,
        turf.distance(
          turf.point(failureStep.location),
          turf.point(orders.get(nextVehicleStepsMap.get(vehicleId)).location)
        )
      ])
      .sort((a, b) => a[1] - b[1])
      .map(([vehicleId]) => vehicleId);

    for (let vehicleId of sortedVehicleIds) {
      const vehicle = vehicles.get(vehicleId);

      const remainingSteps = onlyJobs(initialRoutes.get(vehicleId).steps)
        .filter(afterFailure)
        .map((step) => step.id);

      const nAssignable = Math.min(
        vehicleCapacity - remainingSteps.length,
        unassignedOrderIds.length
      );

      if (nAssignable > 0) {
        const mvrpInput = processMVRPInputs(
          // Vehicles
          [
            createVehicle(
              vehicleId,
              vehicle.description,
              [failureStep.arrival, vehicle.time_window[1]], // TODO change this
              failureStep.location,
              finalStepMap.get(vehicleId).location
            )
          ],
          // Jobs
          [
            // nAssignable incomplete jobs from failed vehicle
            ...unassignedOrderIds.slice(0, nAssignable),
            // Remaining jobs from current vehicle
            ...remainingSteps
          ].map((stepId) => orders.get(stepId)),
          serviceTime,
          vehicleCapacity
        );

        // Run MVRP to check if nAssignable orders can be assigned to the vehicle
        const res = await mvrp(mvrpInput);
        if (res.status === "Ok" && res.result.summary.unassigned === 0) {
          routes.set(vehicleId, res.result.routes);
          newOrders.set(vehicleId, unassignedOrderIds.slice(0, nAssignable));
          const newGeometry = await getUpdatedGeometry(
            vehicleId,
            res.result.routes[0]
          );
          geometries.set(vehicleId, newGeometry);

          unassignedOrderIds = unassignedOrderIds.slice(nAssignable);
        }
      }
    }
    isochroneIdx++;
  }

  return { unassignedOrderIds, newOrders, routes, geometries };
}
    
    

All orders were successfully reassigned

Updated Routes

Select a vehicle to see its reassigned route: Porsche Cayenne

The subsequent cells represent the updated route map reassigned to Porsche Canyon.

Result

  • Undelivered orders in the failed vehicle: 6
  • Reassigned orders: 6
  • The impact of vehicle failure is reduced by 100%

This concludes the reassignment process, showcasing a resilient system capable of swiftly adapting to disruptions while maintaining optimal operational outcomes.