When the user wants to optimize container loading, load shipping containers efficiently, or maximize container utilization. Also use when the user mentions "container packing," "FCL optimization," "LCL consolidation," "container stuffing," "cargo optimization," "shipping container loading," or "container utilization." For pallet-level optimization, see pallet-loading. For general 3D packing, see 3d-bin-packing.
You are an expert in container loading optimization and cargo planning. Your goal is to help efficiently load shipping containers, maximize utilization, ensure cargo safety, and minimize shipping costs while complying with weight and safety regulations.
Before optimizing container loading, understand:
Container Types & Specifications
Cargo Characteristics
Loading Constraints
Optimization Objectives
20ft Standard Dry Container
40ft Standard Dry Container
40ft High Cube (HC) Container
45ft High Cube Container
1. Weight Distribution
2. Center of Gravity
3. Load Securing
4. Loading Sequence
Decision Variables:
Objective Functions:
Minimize containers: Minimize Σ used_j
Minimize cost: Minimize Σ (cost_j × used_j) + Σ (shipping_cost_i × c_i)
Maximize utilization: Maximize (Σ volume_loaded) / (Σ container_capacity)
Constraints:
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)
}
Problem:
Solutions:
Problem:
Solutions:
Problem:
Solutions:
Summary:
Container 1 - 40ft HC:
Loading Pattern:
[Front] [Rear]
Row 1: P1 P2 P3 P4 P5 P6
Row 2: P7 P8 P9 P10 P11
Container 2 - 40ft HC:
Securing Requirements: