Skip to main content

SingleRandomStratified

Move Type: Basic Complexity: O(strata × sample_size) instead of O(containers)

Sample containers from stratified groups (scope items) for more intelligent exploration. Reduces search space while maintaining coverage across different container types.

Overview

SingleRandomStratified evaluates single object moves but samples destination containers in a stratified manner - taking samples from different groups (scope items) rather than uniformly at random. This ensures coverage across different container types (e.g., small, medium, large) without exhaustive search.

Use when:

  • Containers naturally group into strata (e.g., by size, region, type)
  • Want balanced exploration across container types
  • Problem is large (>10K containers)
  • Random sampling alone gives poor coverage

Avoid when:

  • Containers are homogeneous (no natural strata)
  • Problem is small (<1K containers, use Single)
  • Don't have meaningful scope hierarchy
  • Need exhaustive search

Quick Example

# Stratified sampling across regions
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="region",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=100, # 100 samples per region
),
),
]
)
)
)

Parameters

ParameterTypeRequiredDefaultDescription
destinationsToExploreDestinationsToExploreOptionsYes-Defines strata (scope items) for sampling
stratifiedSampleSizeSampleSizeYes-Sample size per stratum

Parameter Details

destinationsToExplore:

  • Defines the stratification - how to group containers
  • Typically uses moveToCurrentScopeItem to stratify by scope
  • Example: region scope creates strata by region

stratifiedSampleSize:

  • Number of containers to sample per stratum
  • Uses SampleSize struct with defaultSampleSize
  • Total samples = sample_size × number_of_strata

How It Works

Given a hot container and object to move:

  1. Define strata: Group containers by scope (e.g., region, size class)
  2. Sample per stratum: Take sample_size random containers from each stratum
  3. Evaluate samples: Test moving object to each sampled container
  4. Apply best: Apply the move that improves objective most

Visual Example

System with 30,000 containers stratified by size into 5 groups:

Stratum 1 Stratum 2 Stratum 3 Stratum 4 Stratum 5
+-------------+ +-------------+ +-------------+ +-------------+ +-------------+
| Very Small | | Small | | Medium | | Large | | Very Large |
| 6000 cont. | | 6000 cont. | | 6000 cont. | | 6000 cont. | | 6000 cont. |
| | | | | | | | | |
| Sample 100 | | Sample 100 | | Sample 100 | | Sample 100 | | Sample 100 |
+-------------+ +-------------+ +-------------+ +-------------+ +-------------+

Total evaluations: 100 × 5 = 500 (instead of 30,000!)
Coverage: Guaranteed samples from each size class

Comparison with Random Sampling

AspectUniform RandomStratified Random
SamplingRandom from all containersRandom per stratum
CoverageMay miss rare typesGuarantees coverage
BiasToward common typesBalanced across types
Use caseHomogeneous containersHeterogeneous containers

Complexity

Moves evaluated per iteration: O(S × K)

Where:

  • S = sample size per stratum (stratifiedSampleSize)
  • K = number of strata (scope items)

Example - Large stratified problem:

  • Total containers: 30,000
  • Strata (regions): 5
  • Sample per stratum: 100
  • Moves evaluated: 100 × 5 = 500 (vs 30,000 for full Single)
  • Speedup: 60x

Example - Very large problem:

  • Total containers: 100,000
  • Strata (regions): 10
  • Sample per stratum: 50
  • Moves evaluated: 50 × 10 = 500 (vs 100,000 for full Single)
  • Speedup: 200x

Usage Patterns

Region-Based Stratification

Sample across regions for coverage:

# Ensure coverage across all regions
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="region",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=50, # Sample 50 containers per region
),
),
]
)
)
)

Size-Based Stratification

Ensure coverage across container sizes:

# Stratify by container size class
# Assumes containers are organized into size-based scope items
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="size_class",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=100, # 100 samples per size class
),
),
]
)
)
)

Large-Scale with Stratification

Very large problems with stratification:

# Large-scale: 100K containers across 10 regions
# Sample 50 per region = 500 total evaluations
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="region",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=50, # Small sample, many strata
),
),
]
)
)
)

Adaptive Sample Size

Tune sample size by stratum:

# Start with small samples, increase later
# Stage 1: Quick exploration
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="region",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=25, # Quick initial pass
),
),
]
)
)
)

# Stage 2: Refined search
solver.addSolver(
SolverSpecs(
localSearchSolverSpec=LocalSearchSolverSpec(
moveTypeList=[
SingleRandomStratifiedMoveTypeSpec(
destinationsToExplore=DestinationsToExploreOptions(
moveToCurrentScopeItem=MoveToCurrentScopeItemSpec(
scopeNameForExploringMovesToCurrentScopeItem="region",
),
),
stratifiedSampleSize=SampleSize(
defaultSampleSize=100, # More thorough
),
),
SingleMoveTypeSpec(), # Final exhaustive pass
]
)
)
)

Performance Characteristics

Stratification Benefit

StrataSample/StratumTotal SamplesTotal ContainersSpeedupCoverage
510050030K60xExcellent
1050500100K200xExcellent
2025500100K200xGood
150050030K60xPoor (no stratification)

Key insight: More strata with smaller samples often better than fewer strata with large samples.

When Does It Help?

SingleRandomStratified helps when:

  • Heterogeneous containers: Different types/sizes/regions
  • Need coverage: Important to explore all container types
  • Large scale: Too many containers for exhaustive search
  • Scope hierarchy exists: Natural stratification available
  • Biased objectives: Some container types heavily preferred

SingleRandomStratified does NOT help when:

  • Homogeneous containers: All similar, no natural grouping
  • Small problems: Overhead not worth it
  • No scope hierarchy: Can't define meaningful strata
  • Equal sampling sufficient: Uniform random works fine

Comparison with Variants

Move TypeSampling StrategyCoverageUse Case
SingleExhaustiveCompleteSmall problems
SingleFastEarly exitVariableMedium problems
SingleRandomBatchesRandom batchesUniform randomLarge + multi-core
SingleRandomStratifiedStratified randomBalanced across typesLarge + heterogeneous
SingleColdestStratifiedColdest-first per stratumBalanced, greedyCapacity-focused
SingleRandomObjectStratifiedStratified objectsObject diversityObject stratification

Decision tree:

  1. Small problem (<1K containers) → Single
  2. Large + homogeneousSingleRandomBatches
  3. Large + heterogeneousSingleRandomStratified
  4. Large + capacity focusSingleColdestStratified

Troubleshooting

Problem: Poor solution quality despite stratification

Diagnosis: Sample size too small per stratum OR stratification not meaningful

Solutions:

  • Increase stratifiedSampleSize
  • Verify scope hierarchy creates meaningful groups
  • Check if containers vary significantly within strata
  • Try different stratification (different scope)
  • Combine with Single for final refinement

Problem: Not seeing speedup vs uniform sampling

Diagnosis: Containers are homogeneous OR too few strata

Solutions:

  • Check if containers naturally group by scope
  • May not need stratification (use SingleRandomBatches)
  • Verify number of strata is reasonable (5-20 ideal)
  • Ensure strata have balanced sizes

Problem: Missing good moves in small strata

Diagnosis: Some strata have few containers but small sample size

Solutions:

  • Increase sample size for small strata
  • Consider stratum size when setting samples
  • Use per-object sample size overrides
  • May need different stratification approach

Problem: Non-deterministic results

Diagnosis: Random sampling produces different results

Solutions:

  • Set randomSeed in LocalSearchSolverSpec
  • Increase sample size for stability
  • Run multiple times and pick best
  • Accept variance as trade-off for speed

Choosing Stratification

Good stratification characteristics:

  1. Meaningful groups: Containers in same stratum are similar
  2. Balanced sizes: Strata have roughly equal number of containers
  3. Diverse outcomes: Moving to different strata has different effects
  4. Reasonable count: 5-20 strata ideal

Common stratification strategies:

  • Geographic: Region, datacenter, rack
  • Capacity: Size classes (small/medium/large)
  • Type: Container type, tier, priority
  • Load: Current utilization bins

Example scope hierarchies:

region > datacenter > rack > container
tier > container_type > container
size_class > region > container

Stratified variants:

Sampling alternatives:

Use together:

  1. SingleRandomStratified for quick improvement with coverage
  2. Single for final refinement
  3. Combine with Swap for capacity constraints

Source Code

Next Steps