关于 container-loading-optimization
用于规划集装箱货物装载的技能,面向物流团队,综合考虑尺寸、重量、安全和装载顺序,并权衡箱量、利用率与运输成本。
主要功能
- 01评估集装箱与货物规格
- 02规划重量分布和货物固定
- 03考虑 LIFO/FIFO 装载顺序
- 04兼顾箱量、成本与利用率
适用场景
- 01规划托盘货或散货装箱
- 02在容量限制内平衡重量
- 03安排多目的地货物装载
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ kishorkukreja/ awesome-supply-chain --skill container-loading-optimization安装后在 Claude Code 中输入/container-loading-optimization确认已加载。
详细介绍
集装箱装载优化
你是集装箱装载优化和货物规划方面的专家。你的目标是帮助高效装载集装箱、最大限度提高利用率、确保货物安全,并在遵守重量和安全法规的同时降低运输成本。
初步评估
在优化集装箱装载前,请先了解:
-
集装箱类型和规格
- 集装箱尺寸?(20 英尺、40 英尺、40 英尺高柜、45 英尺?)
- 内部尺寸和载重能力?
- FCL(整箱货)还是 LCL(拼箱货)?
- 标准干货箱、冷藏箱(reefer)、开顶箱还是框架箱?
- 可用集装箱数量?
-
货物特性
- 托盘货还是散货?
- 如适用,托盘尺寸是多少(GMA、EUR、自定义)?
- 包装尺寸和重量?
- 是否可堆叠、是否易碎?
- 温度要求?
-
装载限制
- 重量分布要求?
- 卡车运输的车轴重量限制?
- 装载顺序(LIFO/FIFO)?
- 多目的地货物?
- 固定和支撑要求?
-
优化目标
- 尽量减少集装箱数量?
- 最大限度提高每个集装箱的利用率?
- 尽量降低运输成本?
- 确保重量均匀分布?
- 针对特定装载顺序进行优化?
集装箱装载框架
标准集装箱尺寸
20 英尺标准干货箱
- 外部:20' 长 x 8' 宽 x 8'6" 高(6.1m x 2.4m x 2.6m)
- 内部:19'4" x 7'8" x 7'10"(5.9m x 2.35m x 2.39m)
- 容积:1,172 cu ft(33.2 m³)
- 最大总重:67,200 lbs(30,480 kg)
- 自重:约 5,000 lbs(2,300 kg)
- 载货量:约 62,000 lbs(28,180 kg)
40 英尺标准干货箱
- 外部:40' 长 x 8' 宽 x 8'6" 高(12.2m x 2.4m x 2.6m)
- 内部:39'6" x 7'8" x 7'10"(12.03m x 2.35m x 2.39m)
- 容积:2,390 cu ft(67.7 m³)
- 最大总重:67,200 lbs(30,480 kg)
- 自重:约 8,200 lbs(3,750 kg)
- 载货量:约 59,000 lbs(26,730 kg)
40 英尺高柜(HC)
- 外部:40' 长 x 8' 宽 x 9'6" 高(12.2m x 2.4m x 2.9m)
- 内部:39'6" x 7'8" x 8'10"(12.03m x 2.35m x 2.69m)
- 容积:2,694 cu ft(76.3 m³)
- 最大总重:67,200 lbs(30,480 kg)
- 自重:约 8,800 lbs(4,000 kg)
- 载货量:约 58,400 lbs(26,480 kg)
45 英尺高柜
- 外部:45' 长 x 8' 宽 x 9'6" 高(13.72m x 2.4m x 2.9m)
- 内部:44'6" x 7'8" x 8'10"(13.55m x 2.35m x 2.69m)
- 容积:3,043 cu ft(86.1 m³)
- 最大总重:67,200 lbs(30,480 kg)
- 载货量:约 58,000 lbs(26,300 kg)
关键装载原则
1. 重量分布
- 沿集装箱长度均匀分配重量
- 目标:前后重量差异小于 2%
- 考虑卡车运输的车轴重量限制
- 避免载荷集中
2. 重心
- 保持重心较低(集装箱底部 1/3 处)
- 保持横向平衡(左右平衡)
- 保持纵向平衡(前后平衡)
3. 货物固定
- 固定货物以防移位
- 使用垫料、充气袋、绑带或支撑物
- 填充空隙以尽量减少移动
- 考虑运输过程中的动态作用力
4. 装载顺序
- 单一目的地采用 LIFO(后进先出)
- 多站卸货采用 FIFO(先进先出)
- 重物放底部,轻物放顶部
- 保护易碎物品
数学建模
集装箱装载问题
决策变量:
- x_i、y_i、z_i = 物品 i 在集装箱中的位置
- c_i = 分配给物品 i 的集装箱编号
- o_i = 物品 i 的摆放方向
- used_j = 若使用集装箱 j,则为 1
目标函数:
-
最小化集装箱数量: 最小化 Σ used_j
-
最小化成本: 最小化 Σ (cost_j × used_j) + Σ (shipping_cost_i × c_i)
-
最大化利用率: 最大化 (Σ 已装载体积) / (Σ 集装箱容量)
约束条件:
- 集装箱内物品不得重叠
- 每个集装箱的载重限制
- 重量分布平衡
- 如有要求,遵守装载顺序
- 车轴重量限制
- 货物兼容性(化学品、食品等)
算法与解决方法
托盘货物装载
class PalletizedContainerLoader:
"""
Container loading optimizer for palletized cargo
Handles standard pallets loaded into containers
"""
def __init__(self, container_type='40HC'):
"""
Initialize with container type
Parameters:
- container_type: '20', '40', '40HC', '45HC'
"""
# Container internal dimensions (inches)
containers = {
'20': {'L': 232, 'W': 92, 'H': 94, 'capacity': 62000, 'cost': 1.0},
'40': {'L': 474, 'W': 92, 'H': 94, 'capacity': 59000, 'cost': 1.5},
'40HC': {'L': 474, 'W': 92, 'H': 106, 'capacity': 58400, 'cost': 1.6},
'45HC': {'L': 534, 'W': 92, 'H': 106, 'capacity': 58000, 'cost': 1.8}
}
if container_type not in containers:
raise ValueError(f"Unknown container type: {container_type}")
self.container_type = container_type
self.container_dims = containers[container_type]
self.pallets = []
self.solution = None
def add_pallet(self, length, width, height, weight, quantity=1, pallet_id=None):
"""Add pallet to load"""
for i in range(quantity):
pid = f"{pallet_id}_{i}" if pallet_id and quantity > 1 else pallet_id or f"P{len(self.pallets)}"
self.pallets.append({
'id': pid,
'dims': (length, width, height),
'weight': weight
})
def optimize_loading(self, allow_rotation=True, double_stack=True):
"""
Optimize pallet loading into containers
Parameters:
- allow_rotation: allow 90-degree rotation
- double_stack: allow stacking pallets
Returns loading plan
"""
# Sort pallets by volume (largest first)
sorted_pallets = sorted(self.pallets,
key=lambda p: p['dims'][0] * p['dims'][1] * p['dims'][2],
reverse=True)
containers = []
for pallet in sorted_pallets:
placed = False
# Try existing containers
for container in containers:
if self._try_place_pallet(container, pallet, allow_rotation, double_stack):
placed = True
break
# Create new container if needed
if not placed:
new_container = {
'pallets': [],
'weight': 0,
'positions': [],
'grid': self._create_empty_grid()
}
if self._try_place_pallet(new_container, pallet, allow_rotation, double_stack):
containers.append(new_container)
else:
print(f"Warning: Could not place pallet {pallet['id']}")
# Calculate metrics
self.solution = self._calculate_solution_metrics(containers)
return self.solution
def _try_place_pallet(self, container, pallet, allow_rotation, double_stack):
"""Try to place pallet in container"""
L, W, H = self.container_dims['L'], self.container_dims['W'], self.container_dims['H']
max_weight = self.container_dims['capacity']
# Check weight
if container['weight'] + pallet['weight'] > max_weight:
return False
# Try different positions and orientations
orientations = [(pallet['dims'][0], pallet['dims'][1], pallet['dims'][2], False)]
if allow_rotation:
orientations.append((pallet['dims'][1], pallet['dims'][0], pallet['dims'][2], True))
# Try floor positions first
for l, w, h, rotated in orientations:
# Try placing on floor
for x in range(0, int(L - l) + 1, 4): # 4-inch increments
for y in range(0, int(W - w) + 1, 4):
if self._check_space_available(container['grid'], x, y, 0, l, w, h):
# Place pallet
self._occupy_space(container['grid'], x, y, 0, l, w, h)
container['pallets'].append(pallet)
container['weight'] += pallet['weight']
container['positions'].append({
'pallet': pallet,
'position': (x, y, 0),
'dims': (l, w, h),
'rotated': rotated,
'level': 'floor'
})
return True
# Try stacking if allowed
if double_stack:
for l, w, h, rotated in orientations:
# Find existing pallets to stack on
for pos in container['positions']:
if pos['level'] == 'floor':
base_x, base_y, base_z = pos['position']
base_l, base_w, base_h = pos['dims']
# Check if new pallet fits on top
if (l <= base_l and w <= base_w and
base_z + base_h + h <= H):
stack_z = base_z + base_h
if self._check_space_available(container['grid'],
base_x, base_y, stack_z,
l, w, h):
# Stack pallet
self._occupy_space(container['grid'],
base_x, base_y, stack_z,
l, w, h)
container['pallets'].append(pallet)
container['weight'] += pallet['weight']
container['positions'].append({
'pallet': pallet,
'position': (base_x, base_y, stack_z),
'dims': (l, w, h),
'rotated': rotated,
'level': 'stacked'
})
return True
return False
def _create_empty_grid(self):
"""Create 3D occupancy grid"""
# Simplified grid (4-inch resolution)
L = int(self.container_dims['L'] / 4)
W = int(self.container_dims['W'] / 4)
H = int(self.container_dims['H'] / 4)
return [[[False for _ in range(H)] for _ in range(W)] for _ in range(L)]
def _check_space_available(self, grid, x, y, z, l, w, h):
"""Check if space is available in grid"""
x_cells = int(x / 4)
y_cells = int(y / 4)
z_cells = int(z / 4)
l_cells = int((l + 3) / 4)
w_cells = int((w + 3) / 4)
h_cells = int((h + 3) / 4)
try:
for i in range(x_cells, x_cells + l_cells):
for j in range(y_cells, y_cells + w_cells):
for k in range(z_cells, z_cells + h_cells):
if i >= len(grid) or j >= len(grid[0]) or k >= len(grid[0][0]):
return False
if grid[i][j][k]:
return False
return True
except:
return False
def _occupy_space(self, grid, x, y, z, l, w, h):
"""Mark space as occupied in grid"""
x_cells = int(x / 4)
y_cells = int(y / 4)
z_cells = int(z / 4)
l_cells = int((l + 3) / 4)
w_cells = int((w + 3) / 4)
h_cells = int((h + 3) / 4)
for i in range(x_cells, min(x_cells + l_cells, len(grid))):
for j in range(y_cells, min(y_cells + w_cells, len(grid[0]))):
for k in range(z_cells, min(z_cells + h_cells, len(grid[0][0]))):
grid[i][j][k] = True
def _calculate_solution_metrics(self, containers):
"""Calculate solution metrics"""
L = self.container_dims['L']
W = self.container_dims['W']
H = self.container_dims['H']
container_volume = L * W * H
solution = {
'num_containers': len(containers),
'container_type': self.container_type,
'containers': []
}
for idx, cont in enumerate(containers):
# Calculate volume used
volume_used = sum(
pos['dims'][0] * pos['dims'][1] * pos['dims'][2]
for pos in cont['positions']
)
utilization = (volume_used / container_volume * 100)
solution['containers'].append({
'container_id': idx,
'num_pallets': len(cont['pallets']),
'weight': cont['weight'],
'volume_used': volume_used,
'utilization': utilization,
'positions': cont['positions']
})
return solution
def print_solution(self):
"""Print loading solution"""
if not self.solution:
print("No solution available")
return
print("=" * 70)
print("CONTAINER LOADING SOLUTION")
print("=" * 70)
print(f"Container Type: {self.solution['container_type']}")
print(f"Pallets to load: {len(self.pallets)}")
print(f"Containers used: {self.solution['num_containers']}")
print()
for cont in self.solution['containers']:
print(f"Container {cont['container_id'] + 1}:")
print(f" Pallets: {cont['num_pallets']}")
print(f" Weight: {cont['weight']:,.0f} lbs")
print(f" Utilization: {cont['utilization']:.1f}%")
print()
# Example Usage
if __name__ == "__main__":
# Create loader for 40ft HC container
loader = PalletizedContainerLoader(container_type='40HC')
# Add GMA pallets (48x40x60 inches, 1500 lbs each)
loader.add_pallet(48, 40, 60, 1500, quantity=20, pallet_id='GMA')
# Add EUR pallets (47x32x55 inches, 1200 lbs each)
loader.add_pallet(47, 32, 55, 1200, quantity=10, pallet_id='EUR')
# Optimize
solution = loader.optimize_loading(allow_rotation=True, double_stack=True)
# Print results
loader.print_solution()
散装货物装载
def optimize_loose_cargo_loading(items, container_type='40HC'):
"""
Optimize loading of non-palletized (loose) cargo
Uses 3D bin packing algorithms
"""
from skills.three_d_bin_packing import ThreeDimensionalBinPacker
# Container dimensions
containers = {
'20': (232, 92, 94, 62000),
'40': (474, 92, 94, 59000),
'40HC': (474, 92, 106, 58400),
'45HC': (534, 92, 106, 58000)
}
L, W, H, max_weight = containers[container_type]
# Use 3D bin packing
packer = ThreeDimensionalBinPacker(L, W, H, max_weight)
for item in items:
packer.add_item(
item['length'], item['width'], item['height'],
item['weight'], item.get('id')
)
solution = packer.solve(algorithm='extreme_point', allow_rotation=True)
return solution
多目的地装载
def optimize_multi_destination_loading(shipments, container_type='40HC'):
"""
Optimize container loading for multi-destination shipments
Ensures items are loaded in reverse delivery order (LIFO)
Parameters:
- shipments: list of dicts with 'destination', 'items', 'priority'
- container_type: container size
Returns: loading plan with zones
"""
# Sort shipments by delivery order (last delivery first)
sorted_shipments = sorted(shipments,
key=lambda s: s.get('priority', 0),
reverse=True)
containers = []
for shipment in sorted_shipments:
destination = shipment['destination']
items = shipment['items']
# Try to add to existing container
placed = False
for container in containers:
# Check if can add zone
if container['remaining_capacity'] >= sum(i['volume'] for i in items):
# Add zone
container['zones'].append({
'destination': destination,
'items': items
})
placed = True
break
if not placed:
# Create new container
new_container = {
'zones': [{
'destination': destination,
'items': items
}],
'remaining_capacity': 1000 # Simplified
}
containers.append(new_container)
return {
'containers': containers,
'num_containers': len(containers)
}
常见挑战与解决方案
挑战:先达到体积上限还是先达到重量上限
问题:
- 集装箱已装满,但未达到重量限制(先达到体积上限)
- 或者已达到重量限制,但仍有剩余空间(先达到重量上限)
- 容量利用效率低
解决方案:
- 混装高密度和轻型货物,以实现平衡
- 计算立方重量比
- 根据货物密度选择合适的集装箱尺寸
- 考虑与其他货物拼箱
- 对于重货:使用较小的集装箱或按重量运输
- 对于轻货:尽可能充分利用体积
挑战:重量分布
问题:
- 重量分布不均
- 违反轴重限制
- 集装箱不稳定
解决方案:
- 计算每延米重量
- 目标是均匀分布(偏差 ±2%)
- 将重物放在中部/底部
- 使用装载规划软件
- 平衡左右、前后重量
- 考虑卡车轴重限制
挑战:托盘尺寸混杂
问题:
- GMA 和 EUR 托盘难以共同装载
- 不同尺寸之间存在空间浪费
解决方案:
- 将尺寸相近的托盘分组
- 先装载最大的托盘
- 使用填充货物填补空隙
- 考虑为不同类型的托盘使用单独的集装箱
- 在装入集装箱前优化托盘摆放方式
输出格式
集装箱装载计划
摘要:
- 货件:订单 #12345
- 所需集装箱:2 x 40ft HC
- 托盘总数:22
- 总重量:48,500 lbs
- 平均利用率:87%
集装箱 1 - 40ft HC:
- 已装载托盘:11
- 重量:24,800 lbs(容量的 42%)
- 体积利用率:89%
- 重量分布:前部 48%,后部 52% ✓
装载方式:
[Front] [Rear]
Row 1: P1 P2 P3 P4 P5 P6
Row 2: P7 P8 P9 P10 P11
集装箱 2 - 40ft HC:
- 已装载托盘:11
- 重量:23,700 lbs(容量的 41%)
- 体积利用率:85%
- 重量分布:前部 51%,后部 49% ✓
加固要求:
- 为所有托盘缠绕拉伸膜
- 在各排之间使用挡货杆
- 在空隙处放置充气袋
- 使用编号为 #ABC123 的封条封闭箱门
要询问的问题
- 使用哪种尺寸的集装箱?(20ft、40ft、40ft HC、45ft HC)
- 物品已装托盘还是散装?
- 托盘的尺寸和重量是多少?
- 是否有重量限制或重量分布要求?
- 这是单一目的地配送还是多点配送?
- 是否有特殊货物(易碎品、危险品、温控货物)?
- 是否有装载顺序要求(LIFO/FIFO)?
相关技能
- pallet-loading:用于集装箱装载前的托盘级优化
- 3d-bin-packing:用于散装货物装载
- vehicle-loading-optimization:用于卡车装载
- load-building-optimization:用于订单整合
- freight-optimization:用于运输成本优化
评论
支持 Markdown