Exploring picking strategies in warehouse operations, simulation in R

Exploring picking strategies in warehouse operations, simulation in R

In today’s fast-paced logistics and supply chain environment, warehouse efficiency is critical to meeting customer demands and maintaining profitability. The customer expectations for a wider catalogue for selection, faster deliveries and almost zero error in delivery, are becoming the new normal. One of the key aspects of warehouse management is the picking process, where items are retrieved from storage locations to fulfil customer orders. Picking strategies significantly impact the speed, accuracy, and cost of order fulfillment. In this post, we’ll explore different picking strategies and demonstrate how to simulate these processes using R, specifically leveraging the "tidyverse" and "purrr" libraries.

What’s a picking strategy ?

When a customer places an order online, the order is routed to one of the warehouses or fulfilment centres (FC). The choice of the warehouse could be based on various criteria such as inventory availability, delivery times, cost of processing etc. To fulfil this order, the warehouse adopts various picking strategies which are methodologies used to retrieve items from the warehouse against the customer order. The choice of strategy depends on various factors, including the type of products stored, order volume, and warehouse layout. Here are some common picking strategies:

Order picking:

  • Definition: In this strategy, each order is picked individually. The picker completes one order before moving on to the next.
  • Use Case: Best suited for small warehouses with low order volumes or when orders vary significantly in size and composition. Used in both B2C and B2B warehouses
  • Pros: Simple to implement, easy to track progress for each order.
  • Cons: Can be time-consuming and inefficient, especially with high order volumes.

Batch Picking:

  • Definition: Batch picking involves grouping multiple orders together and picking them together in one go. The items are later sorted by order.
  • Use Case: Effective for warehouses with high order volumes and similar items across orders.
  • Pros: Reduces travel time by allowing pickers to collect items for multiple orders in a single pick task. Also, bulk picking reduces risk of errors i.e. damages or short / wrong pick cases.
  • Cons: Requires additional sorting and can be complex to manage.

Zone Picking:

  • Definition: In zone picking, the warehouse is divided into zones, and each picker is responsible for a specific zone. Orders are split among zones, and the items are consolidated later.
  • Use Case: Ideal for large warehouses with a wide variety of products and different storage types which might need separate infrastructure support for picking.
  • Pros: Increases efficiency by reducing picker travel time and specialising pickers in certain zones.
  • Cons: Requires coordination between zones, which can add complexity and is often orchestrated by a WMS software.

Cluster Picking:

  • Definition: Cluster picking involves grouping multiple orders into clusters, where each cluster is treated as a single picking task. The picker collects items for all orders in the cluster simultaneously, optimising the pick path to minimise travel distance.
  • Use Case: Suitable for environments with a moderate number of orders and when there’s a need to optimise picking efficiency without the complexity of full batch picking.
  • Pros: Reduces travel time and improves efficiency by picking for multiple orders at once, while still maintaining a manageable level of complexity.
  • Cons: Requires careful planning to group orders effectively and ensure that the cluster size is appropriate for the picker’s capacity.


Simulating Picking Strategies with R

Simulations can provide valuable insights into how different picking strategies perform in specific warehouse layouts. Let’s take an example of simulating an order picking and batch picking strategy using R.

Assumptions considered for inventory and order profile are as below -

  • Total SKUs — 19500
  • Total OB volume per day — 6.8L units
  • Total orders — 120
  • SKUs per order — 325
  • Order profile follows Pareto distribution i.e. 80% of the volume flows in 20% of the SKUs
  • The warehouse layout is a simple 2x2 grid

Below code defines the SKU count and warehouse layout

# Load necessary libraries
library(tidyverse)
library(purrr)
library(EnvStats)  # For rpareto function

# Define the number of SKUs
total_skus <- 19500

# Define warehouse layout for 18000 SKUs
warehouse_layout <- tibble(
  SKU = 1:total_skus,
  Aisle = sample(1:100, total_skus, replace = TRUE),
  Bin = sample(1:100, total_skus, replace = TRUE)
)

# Define the Pareto distribution for SKUs
top_skus <- ceiling(0.2 * total_skus)  # Top 20% SKUs        

Orders are created with Pareto distribution so that the total quantity is 6.5L units

# Function to generate orders with an 80/20 Pareto distribution of SKUs
generate_pareto_order <- function(order_size = 325, target_quantity = 650000, num_orders=1) {
  # Calculate total quantity per order
  #order_size <- 250
  #target_quantity <- 550000
  #num_orders <- 1
  total_order_quantity <- target_quantity / num_orders
  
  # Select SKUs based on Pareto principle
  sku_indices <- c(
    sample(1:top_skus, size = order_size * 0.8, replace = TRUE),
    sample((top_skus + 1):total_skus, size = order_size * 0.2, replace = TRUE)
  ) %>% sample()  # Shuffle the indices
  
  # Generate Pareto-distributed quantities and scale to match total_order_quantity
  quantities <- rpareto(325, location = 1, shape = 1.16) %>%
    ceiling() 
 
  # Scale quantities to sum up to total_order_quantity
  scale_factor <- total_order_quantity / sum(quantities)
  quantities <- ceiling(quantities * scale_factor)

  # Create the order as a tibble
  tibble(SKU = warehouse_layout$SKU[sku_indices], Quantity = quantities)
  #sample_order <- tibble(SKU = warehouse_layout$SKU[sku_indices], Quantity = quantities) 
  #sample_order %>% sum(Quantity)
}

# Example order with 250 SKUs using 80/20 Pareto-distributed quantities
order <- generate_pareto_order(order_size = 325)

# Sample order data 
print(head(order))        

Manhattan distance method is used to calculate distance between two inventory locations. Objective is the minimise distance while calculating optimal pick-path.

# Function to find the nearest location
find_nearest_location <- function(current_location, sku_locations) {
  sku_locations %>%
    rowwise() %>%
    mutate(Distance = abs(Aisle - current_location[1]) + abs(Bin - current_location[2])) %>%
    ungroup() %>%
    slice_min(Distance) %>%
    select(Aisle, Bin) %>%
    unlist() %>%
    as.numeric()
}

# Function to calculate Manhattan distance
manhattan_distance <- function(loc1, loc2) {
  sum(abs(loc1 - loc2))
}        

Calculating picking distance

# Function to simulate order picking
simulate_picking <- function(order) {
  current_location <- c(Aisle = 1, Bin = 1)
  
  total_distance <- order %>%
    mutate(Distance = map2_dbl(SKU, Quantity, ~{
      sku_locations <- warehouse_layout %>% filter(SKU == .x)
      nearest_location <- find_nearest_location(current_location, sku_locations)
      distance <- manhattan_distance(current_location, nearest_location)
      current_location <<- nearest_location  # Update current location
      distance   # Multiply distance by the quantity of SKU
    })) %>%
    summarise(Distance = sum(Distance))%>%
    pull(Distance)
  
  total_distance
}        

Simulating picking distance for single order

# Simulate picking for the generated order
total_distance <- simulate_picking(order)
total_time <- total_distance * 2  # Assume 2 seconds per unit distance
cat("Total distance traveled:", total_distance, "\n")        

Simulating for multiple orders with Order picking strategy

# Function to run simulation for multiple orders
simulate_multiple_orders <- function(num_orders) {
  total_order_quantity <- 650000 / num_orders # qty per order
  orders <- replicate(num_orders, generate_pareto_order(order_size = 325,target_quantity = total_order_quantity), simplify = FALSE)
  distances <- map_dbl(orders, simulate_picking)
  distances
}

# Run simulation for 100 orders with 250 SKUs each
simulation_results <- simulate_multiple_orders(120)

# Analyze results
avg_distance <- mean(simulation_results)
total_order_wise_pick_distance<- sum(simulation_results)
avg_time <- avg_distance * 2
cat("Average distance traveled:", avg_distance, "\n")
cat("Total distance traveled in order wise pick scenario:", total_order_wise_pick_distance, "\n")

# Visualization
qplot(simulation_results, geom = "histogram", bins = 30, fill = I("#3d403e"),
      xlab = "Total distance traveled", ylab = "Frequency", main = "Distribution of Picking Distances (250 SKUs per Order, 80/20 Pareto)") + theme_minimal()        

Simulating with Batch picking strategy

simulate_batch_picking <- function(num_batches,orders_per_batch) {
  num_orders <- num_batches * orders_per_batch
  total_order_quantity <- 650000 / num_orders # qty per order
  batches <- replicate(num_batches, {
    orders <- replicate(orders_per_batch, generate_pareto_order(order_size = 325,target_quantity = total_order_quantity), simplify = FALSE)
    batch <- bind_rows(orders) %>% 
      group_by(SKU)%>%
      summarise(Quantity = sum(Quantity))
    distances <- simulate_picking(batch)
    distances
  }, simplify = TRUE)
}

simulation_results_batch_pick <- simulate_batch_picking(num_batches = 10,orders_per_batch = 12)
total_distance_batch_pick <- sum(simulation_results_batch_pick)
cat("Total distance travelled in case of batch pick scenario:", total_distance_batch_pick)

final_results <- data.frame(pick_strategy = c('order-wise pick','batch-wise pick'),
                            distance = c(total_order_wise_pick_distance,total_distance_batch_pick))

final_results %>% 
  ggplot(aes(distance,pick_strategy, label = distance))+geom_col()+
  geom_label()+
  xlim(0,2800000)+
  scale_x_continuous(labels = scales::comma)+
  labs(title = 'Batch wise picking is ~20% more efficient (10 batch and 10 orders / batch)',
       x = "Distance", y = NULL)+
  theme_minimal()        

In this case, batch picking gives ~25% better efficiency for picking, but with additional effort of order wise sorting later, which is usually less effort as compared to picking.

Key Takeaways

  1. Efficiency Gains: Batch and cluster picking generally result in lower total travel distances compared to order picking, making them more efficient for high-volume operations.
  2. Warehouse Layout: The layout of the warehouse and the distribution of SKUs significantly impact the performance of different picking strategies.
  3. Simulation as a Tool: Using R for simulations allows warehouse managers to test different strategies in a virtual environment before implementing changes in the physical warehouse.

Conclusion

Choosing the right picking strategy is crucial for optimizing warehouse operations. By leveraging simulations in R, warehouse managers can make data-driven decisions that enhance efficiency and reduce costs. Whether you’re dealing with a small-scale operation or a large, complex warehouse, understanding and simulating different picking strategies can lead to significant improvements in your order fulfillment process.

要查看或添加评论,请登录