Container Yard Optimization Basics: Building the Foundation
Essential Guide to Yard Optimization and Stacking Algorithms | Part 2 of Building Smart Container Terminals Series.
Anyone who has played Tetris understands the fundamental challenge of container yard management: placing pieces efficiently while considering future moves. But unlike Tetris, container terminal operations involve multiple competing objectives, complex constraints, and real-world consequences where mistakes can cost millions.
Understanding the Container Terminal Puzzle
Imagine a massive chessboard where each move affects not just the current state but ripples through future operations. A container terminal typically handles hundreds or thousands of containers daily, each with its own set of requirements:
- A 40-foot reefer container needs a constant power supply
- A container with dangerous goods requires specific safety distances
- A container departing tomorrow should be more accessible than one leaving next week
The complexity grows exponentially when you consider that a typical yard might have:
- 50,000+ ground slots
- Multiple container types (standard, reefer, open top)
- Varying departure schedules
- Different shipping lines with preferred areas
- Equipment limitations and maintenance schedules
Building a Scoring System: The Foundation of Smart Stacking
When I started developing this system, I realized I needed a way to evaluate potential container positions systematically (a container position is defined by a triad of values: bay, row, and tier). Here’s a significantly simplified version of how the system score positions:
def calculate_container_position_score(container, block, position):
# Base score starts at 0
score = 0.0
# Check fundamental constraints
if not is_position_valid(container, block, position):
return float('-inf')
# Weight distribution score
stack = get_container_stack(block, position)
weight_score = calculate_container_weight_score(container, stack)
score += weight_score * WEIGHT_FACTOR
# Departure time score
etd_score = calculate_container_departure_score(container, stack)
score += etd_score * ETD_FACTOR
# Distance optimization
distance_score = calculate_container_distance_score(container, position)
score += distance_score * DISTANCE_FACTOR
...
# Shipping line grouping
...
# Special container handling
...
return score
Let’s break down some of the scoring components:
Weight Distribution (Stack Stability)
The system evaluates weight distribution to ensure stack stability:
- Heavier containers must be placed below lighter ones
- Each stack has a maximum weight capacity (typically 150,000 kg)
- Define the optimal weight difference between containers ( in this implementation, around 30,000 kg)
- The score decreases as weight distribution becomes less ideal
Departure Time Optimization
The ETD (Estimated Time of Departure) scoring considers:
- Containers departing earlier should be more accessible
- The ideal grouping has containers with similar departure times
- Maximum ETD difference threshold (N days)
- Score penalizes positions that would require future reshuffling
Special Handling Considerations
The scoring system includes specialized logic for different container types:
- Reefer Containers:
- It must be near power supply points
- Maximum distance to the power supply (10 meters in this implementation)
- Requires available reefer capacity in the block
2. Dangerous Goods:
- Specific blocks must be designated for dangerous goods
- Separation requirements between incompatible classes
- Maximum number of dangerous goods stacks per block
3. High-Priority Containers:
- Premium customer considerations
- Time-sensitive cargo handling
- Special handling requirements
This scoring system forms the foundation of intelligent container positioning, enabling efficient yard operations while maintaining safety and operational requirements. Let’s explore each element in more detail.
Weight Distribution: The Foundation of Safety
Weight distribution isn’t just about putting heavy containers at the bottom. It’s about creating stable stacks that can withstand various conditions:
def calculate_weight_score(container, stack):
"""
Calculate weight-based score for container placement.
Args:
container: Container object with weight attribute
stack: List of Container objects representing current stack
Returns:
float: Score between 0 and 100
"""
if not stack:
return 100 # Perfect score for empty stack
max_stack_weight = 150000.0 # 150 tons max
current_stack_weight = sum(c.weight for c in stack)
# Check total weight limit
if current_stack_weight + container.weight > max_stack_weight:
return -100
# Check weight distribution (heavier containers should be at bottom)
top_container = stack[-1]
if container.weight > top_container.weight:
return -100
# Score based on weight difference ratio
weight_difference = top_container.weight - container.weight
max_weight_difference = 30000.0 # up to 30 tons ideal difference
return min(weight_difference / max_weight_difference, 100)
Improper container placement can create cascading operational risks — much like a delayed chain reaction.
The weight factor in container stacking is critical for two main reasons:
- Stack Stability
- Heavier containers on top create dangerous downward pressure
- Example: A 30-ton container on top of a 20-ton container risks stack tipping or collapse
2. Maximum Stack Weight
- Each stack position has weight limits based on ground conditions
- Example: A typical stack limit is 150 tons
- Exceeding this can damage yard pavement or cause subsidence
Time Management: The Art of Accessibility
In Container terminals, every container has a scheduled departure time, and the efficiency of yard operations depends heavily on how the system manages these temporal constraints.
The Temporal Challenge
Consider a container stack with these departure times:
- Bottom: Departing tomorrow
- Middle: Departing in 2 days
- Top: Departing in 5 days
This arrangement necessitates two reshuffles — first moving the top container, then the middle one, to access the bottom container. Each reshuffle:
- Takes several minutes of crane time
- Relevant costs in operational expenses
- Increases risk of damage or delays
- Affects terminal productivity
Departure Time Optimization
The scoring system evaluates temporal accessibility using several factors:
def calculate_container_departure_score(container, stack):
"""
Calculate accessibility score based on departure times.
Args:
container: Container to be placed
stack: Existing container stack
Returns:
float: Score between 0 (poor) and 100 (optimal)
"""
if not stack:
return 100 # Ground position is optimal
# Calculate time-based conflicts
conflicts = 0
weighted_conflicts = 0
for existing_container in stack:
if existing_container.departure_time > container.departure_time:
conflicts += 1
# Weight conflicts by time difference
time_diff = (existing_container.departure_time -
container.departure_time).days
weighted_conflicts += conflicts * (1 + (time_diff / 7))
# Penalize based on:
# 1. Number of conflicts
# 2. Time difference magnitude
# 3. Stack position
base_penalty = ...
time_penalty = ...
return max(0, 100 - base_penalty - time_penalty)
The Limitations of Pure Heuristics
While this scoring system provided a good foundation, I quickly discovered its limitations:
Static vs. Dynamic Reality
Like a chess algorithm that only considers the current board state, this algorithm couldn’t anticipate emerging or stational patterns.
The Human Factor
Terminal operators often make decisions based on experience and intuition that are hard to quantify. This type of knowledge isn’t easily captured in static rules.
Computational Complexity
As yard size grows, the number of possible positions grows significantly. For each container, we need to evaluate:
- Multiple blocks
- Multiple positions within each block
- Multiple stack configurations
- Multiple time horizons
Looking Ahead: From Rules to Intelligence
These limitations pointed me toward the need for more sophisticated solutions. In my next article, we’ll explore how an event-driven architecture enables real-time optimization. At the end of this series, we’ll see how modern terminal operations require a system that can:
- Learn from historical data
- Adapt to changing patterns
- Predict future yard states
- Balance multiple objectives dynamically
The journey from basic heuristics to intelligent optimization is just beginning, but understanding these fundamentals is crucial for building more sophisticated solutions.
This is Article 2 in the series “Building a Smart Container Terminal: From Heuristics to AI”. For background, read the introduction here.