Warehouse slotting and layout optimization skill for pick path minimization and space utilization.
Optimizes warehouse layouts and product placement to minimize pick paths and maximize space utilization.
npx claudepluginhub a5c-ai/babysitterThis skill is limited to using the following tools:
You are warehouse-slotting-optimizer - a specialized skill for optimizing warehouse slotting and layout to minimize pick paths and maximize space utilization.
This skill enables AI-powered warehouse optimization including:
import pandas as pd
import numpy as np
def velocity_analysis(order_data: pd.DataFrame):
"""
Analyze SKU velocity by pick frequency
"""
# Aggregate picks by SKU
sku_picks = order_data.groupby('sku').agg({
'quantity': 'sum',
'order_id': 'count'
}).rename(columns={'order_id': 'pick_count'})
# Sort by picks descending
sku_picks = sku_picks.sort_values('pick_count', ascending=False)
# Calculate cumulative percentages
total_picks = sku_picks['pick_count'].sum()
sku_picks['cum_picks'] = sku_picks['pick_count'].cumsum()
sku_picks['cum_pct'] = sku_picks['cum_picks'] / total_picks * 100
# Assign velocity class
def assign_velocity(pct):
if pct <= 80:
return 'Fast' # A items - top 80% of picks
elif pct <= 95:
return 'Medium' # B items
else:
return 'Slow' # C items
sku_picks['velocity_class'] = sku_picks['cum_pct'].apply(assign_velocity)
return {
"sku_velocity": sku_picks,
"summary": {
"total_skus": len(sku_picks),
"fast_movers": len(sku_picks[sku_picks['velocity_class'] == 'Fast']),
"medium_movers": len(sku_picks[sku_picks['velocity_class'] == 'Medium']),
"slow_movers": len(sku_picks[sku_picks['velocity_class'] == 'Slow'])
}
}
def optimize_golden_zone(skus: pd.DataFrame, warehouse_config: dict):
"""
Optimize placement in golden zone (ergonomic prime picking zone)
Golden zone: waist to shoulder height, immediate reach
"""
golden_zone = warehouse_config.get('golden_zone', {
'height_min': 24, # inches from floor
'height_max': 54,
'reach_max': 24 # inches from aisle
})
# Calculate golden zone capacity
rack_config = warehouse_config.get('rack', {
'bays': 100,
'levels': 5,
'positions_per_bay': 3
})
# Levels in golden zone (typically levels 2-3 of 5)
golden_levels = [2, 3] # Assuming 5 levels
golden_positions = (rack_config['bays'] *
len(golden_levels) *
rack_config['positions_per_bay'])
# Sort SKUs by pick frequency
fast_skus = skus[skus['velocity_class'] == 'Fast'].copy()
fast_skus = fast_skus.sort_values('pick_count', ascending=False)
# Assign to golden zone
assignments = []
position_count = 0
for idx, row in fast_skus.iterrows():
if position_count < golden_positions:
assignments.append({
'sku': idx,
'zone': 'golden',
'level': golden_levels[position_count % len(golden_levels)],
'priority': position_count + 1
})
position_count += 1
else:
assignments.append({
'sku': idx,
'zone': 'standard',
'level': None,
'priority': position_count + 1
})
return {
"golden_zone_capacity": golden_positions,
"skus_in_golden": position_count,
"assignments": assignments,
"golden_zone_pick_coverage": fast_skus.head(golden_positions)['pick_count'].sum() /
skus['pick_count'].sum() * 100
}
def optimize_pick_path(picks: list, warehouse_layout: dict):
"""
Optimize pick path through warehouse
Uses traveling salesman heuristic
"""
from scipy.spatial.distance import cdist
import itertools
# Get location coordinates for picks
locations = []
for pick in picks:
loc = warehouse_layout['locations'].get(pick['location'])
if loc:
locations.append((pick['location'], loc['x'], loc['y']))
# Calculate distance matrix
coords = np.array([(l[1], l[2]) for l in locations])
dist_matrix = cdist(coords, coords)
# Nearest neighbor heuristic
n = len(locations)
visited = [False] * n
path = [0] # Start at first location
visited[0] = True
for _ in range(n - 1):
current = path[-1]
nearest = None
nearest_dist = float('inf')
for j in range(n):
if not visited[j] and dist_matrix[current][j] < nearest_dist:
nearest = j
nearest_dist = dist_matrix[current][j]
if nearest is not None:
path.append(nearest)
visited[nearest] = True
# Calculate total distance
total_distance = sum(dist_matrix[path[i]][path[i+1]]
for i in range(len(path)-1))
# Return optimized sequence
optimized_picks = [picks[i] for i in path]
return {
"optimized_sequence": optimized_picks,
"total_distance": total_distance,
"locations_count": n,
"estimated_time_minutes": total_distance / warehouse_layout.get('walk_speed', 100) * 60
}
def size_forward_pick_area(sku_data: pd.DataFrame, replenishment_cost: float,
space_cost_per_unit: float):
"""
Determine optimal forward pick area size
Balance replenishment cost vs. space cost
"""
# Sort by velocity
sku_data = sku_data.sort_values('picks_per_day', ascending=False)
results = []
cumulative_picks = 0
total_picks = sku_data['picks_per_day'].sum()
for i, (idx, row) in enumerate(sku_data.iterrows()):
cumulative_picks += row['picks_per_day']
pick_coverage = cumulative_picks / total_picks
# Estimate costs
forward_skus = i + 1
space_cost = forward_skus * row.get('cube', 1) * space_cost_per_unit
replen_trips = sku_data.head(forward_skus)['picks_per_day'].sum() / \
sku_data.head(forward_skus)['case_qty'].mean()
replen_cost = replen_trips * replenishment_cost
total_cost = space_cost + replen_cost
results.append({
'forward_skus': forward_skus,
'pick_coverage': pick_coverage,
'space_cost': space_cost,
'replen_cost': replen_cost,
'total_cost': total_cost
})
if pick_coverage >= 0.95:
break
# Find optimal
optimal = min(results, key=lambda x: x['total_cost'])
return {
"analysis": results,
"optimal_forward_skus": optimal['forward_skus'],
"pick_coverage": optimal['pick_coverage'],
"total_cost": optimal['total_cost']
}
def slot_assignment(skus: pd.DataFrame, locations: pd.DataFrame,
constraints: dict = None):
"""
Assign SKUs to warehouse locations
Considers:
- Velocity (fast movers to best locations)
- Cube (size compatibility)
- Weight (heavy items at floor level)
- Family grouping (related items together)
"""
constraints = constraints or {}
# Score each location
def score_location(loc):
score = 0
# Distance from shipping (lower is better)
score -= loc.get('distance_to_ship', 0) * 0.01
# Ergonomic zone bonus
if 24 <= loc.get('height', 0) <= 54:
score += 10
# Ground level for heavy
if loc.get('level', 0) == 1:
score += 5
return score
locations['score'] = locations.apply(score_location, axis=1)
locations = locations.sort_values('score', ascending=False)
# Sort SKUs by assignment priority
skus['priority'] = skus['picks_per_day'] * 100 - skus.get('cube', 1)
skus = skus.sort_values('priority', ascending=False)
assignments = []
used_locations = set()
for sku_idx, sku in skus.iterrows():
for loc_idx, loc in locations.iterrows():
if loc_idx in used_locations:
continue
# Check constraints
if sku.get('cube', 1) > loc.get('capacity', float('inf')):
continue
if sku.get('weight', 0) > loc.get('weight_limit', float('inf')):
continue
# Assign
assignments.append({
'sku': sku_idx,
'location': loc_idx,
'picks_per_day': sku['picks_per_day'],
'location_score': loc['score']
})
used_locations.add(loc_idx)
break
return {
"assignments": assignments,
"assigned_count": len(assignments),
"unassigned_skus": len(skus) - len(assignments)
}
def calculate_slotting_metrics(current_slotting: pd.DataFrame,
order_history: pd.DataFrame,
warehouse_config: dict):
"""
Calculate slotting performance metrics
"""
metrics = {}
# Pick density (picks per foot traveled)
total_picks = len(order_history)
# Estimate travel based on current slotting
travel_estimate = estimate_total_travel(current_slotting, order_history, warehouse_config)
metrics['pick_density'] = total_picks / travel_estimate if travel_estimate > 0 else 0
# Golden zone utilization
golden_picks = order_history.merge(current_slotting, on='sku')
golden_picks = golden_picks[golden_picks['zone'] == 'golden']
metrics['golden_zone_pick_pct'] = len(golden_picks) / total_picks * 100
# Slot utilization
total_slots = len(current_slotting)
active_slots = current_slotting[current_slotting['picks_per_day'] > 0]
metrics['slot_utilization'] = len(active_slots) / total_slots * 100
# Velocity alignment score (are fast movers in best spots?)
current_slotting = current_slotting.sort_values('picks_per_day', ascending=False)
current_slotting['ideal_rank'] = range(1, len(current_slotting) + 1)
current_slotting['actual_rank'] = current_slotting['location_score'].rank(ascending=False)
correlation = current_slotting['ideal_rank'].corr(current_slotting['actual_rank'])
metrics['velocity_alignment'] = correlation
return metrics
def estimate_total_travel(slotting, orders, config):
# Simplified travel estimation
avg_picks_per_order = len(orders) / orders['order_id'].nunique()
avg_travel_per_pick = config.get('avg_aisle_length', 100) / 2
return len(orders) * avg_travel_per_pick
This skill integrates with the following processes:
warehouse-layout-slotting-optimization.jsinventory-optimization-analysis.js{
"velocity_analysis": {
"fast_movers": 150,
"medium_movers": 450,
"slow_movers": 2400
},
"golden_zone": {
"capacity": 300,
"pick_coverage": 72.5
},
"slotting_metrics": {
"pick_density": 2.3,
"velocity_alignment": 0.85
},
"recommendations": [
"Move top 50 SKUs to golden zone",
"Consider forward pick area for 200 SKUs"
]
}
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.