Mecalux Hackathon — "Warehouse Optimizer" challenge solution.
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
# Produces: build/optimizer (Linux/Mac) or build/Release/optimizer.exe (Windows)Requires: C++17 compiler (g++ 9+ or clang++ 10+ or MSVC 2019+), CMake 3.14+.
./build/optimizer <case_dir> <output_csv> [options]
# Options:
# --time=100 Total wall-clock budget in seconds (default: 100)
# --threads=N Parallel workers (default: hardware_concurrency)
# --seed=42 Single seed (default: 42)
# --seed-list=1,2,3 Try specific seeds, keep best result
# --random-seeds=N Generate and try N random seeds
# --quiet Suppress verbose output
# --init=greedy|random Initialization strategy (default: greedy)
# --heuristic=default|weighted|randomized
# Bay scoring heuristic (default: default)
# Basic usage (unchanged behaviour):
./build/optimizer cases/Case0 output/solution.csv
# Use all CPU cores for 25 s — recommended for presentations:
./build/optimizer cases/Case0 output/solution.csv --time=25 --random-seeds=8
# Explicit thread count:
./build/optimizer cases/Case0 output/solution.csv --time=25 --threads=12 --random-seeds=12
# 32 seeds in batches of 8 (4 batches × ~6 s each ≈ 25 s total):
./build/optimizer cases/Case0 output/solution.csv --time=25 --threads=8 --random-seeds=32
# Weighted heuristic + all cores:
./build/optimizer cases/Case0 output/solution.csv --time=25 --random-seeds=8 --heuristic=weighted
# Maximum diversity:
./build/optimizer cases/Case0 output/solution.csv --time=25 --random-seeds=16 --init=random --heuristic=randomizedOr use the helper script:
bash scripts/run_case.sh cases/Case0 25 42
bash scripts/run_all_public_cases.sh 25 42All inputs are CSV files in the case directory:
| File | Columns | Description |
|---|---|---|
warehouse.csv |
x,y |
Vertices of the orthogonal warehouse polygon (in order) |
obstacles.csv |
x,y,width,depth |
Axis-aligned rectangular obstacles |
ceiling.csv |
x,height |
Piecewise-constant ceiling height by X position |
types_of_bays.csv |
id,width,depth,height,gap,nLoads,price |
Bay type specifications |
solution.csv:
id,x,y,rotation
1,0,0,0
2,500,0,90
...
id: bay type idx,y: bottom-left corner after rotationrotation: 0, 90, 180, or 270 degrees
Q = (Σ price_i / nLoads_i)^(2 - Σ area_i / area_warehouse)
Minimize Q. Lower is better.
Σ price_i / nLoads_i: sum of price-per-load for all placed bays (want this small → efficient bays)Σ area_i / area_warehouse: fraction of warehouse covered (want this close to 1 → full coverage)- The exponent
2 - ratiodecreases as coverage increases, which lowers Q
Strategy: Place many high-efficiency (low price/load) bays that cover as much area as possible.
- Bays must be fully inside the warehouse polygon
- Bays cannot overlap each other (touching OK)
- Bays cannot overlap obstacles (touching OK)
- Bay height must not exceed the ceiling height at any point of its X footprint
- Rotations are arbitrary float degrees 0–360 (axis-aligned 0/90/180/270 during greedy; SA also explores continuous angles)
- Phase 1 — Initial solution (35% of time budget):
--init=greedy(default): Sort bay types by heuristic score. For each candidate grid position (snapped to walls/obstacles/placed-bay edges), place the best-fitting bay at all 4 axis-aligned rotations.--init=random: Sample bay types by weighted probability, try random positions across the bounding box. 50% discrete rotations, 50% continuous.
- Phase 2 — Multi-start (up to 50% of time budget): Repeat Phase 1 with shuffled/re-scored orderings; keep the best result seen.
- Phase 3 — Simulated Annealing (remaining time): Add/remove/swap/rotate bays with temperature-controlled acceptance. Rotation moves include both discrete perturbations (±5/10/15/30/45/90°) and continuous random angles.
Heuristic modes (--heuristic):
| Mode | Score formula | Best for |
|---|---|---|
default |
nLoads/price |
Stable, reproducible runs |
weighted |
nLoads/price + 0.3 × area/maxArea |
Cases where large bays pay off |
randomized |
nLoads/price × (1 ± 0.15) |
Multi-seed diversity |
Total time budget: configurable (default 100s).
cd web
python3 -m http.server 8080
# Open http://localhost:8080 in your browserThen:
- Click each file input label to load the CSV files
- Click Render (or press Enter)
- The warehouse, obstacles, and bays are shown in SVG
- Click any bay for details in the sidebar
- Scroll to zoom, drag to pan
mkdir cases/CaseX
# Copy and fill in:
# cases/CaseX/warehouse.csv
# cases/CaseX/obstacles.csv
# cases/CaseX/ceiling.csv
# cases/CaseX/types_of_bays.csv
bash scripts/run_case.sh cases/CaseXwarehouse-optimizer/
├── CMakeLists.txt
├── README.md
├── src/
│ ├── main.cpp CLI entry point
│ ├── csv_parser.h/cpp Input file parsing
│ ├── geometry.h/cpp Polygon, rect, collision, spatial grid
│ ├── optimizer.h/cpp Greedy + SA placement algorithm
│ ├── scoring.h/cpp Q function computation
│ └── validator.h/cpp Constraint validation
├── web/
│ ├── index.html Visualizer UI
│ ├── viewer.js SVG rendering + file loading
│ └── style.css Dark-theme styling
├── scripts/
│ ├── run_case.sh
│ └── run_all_public_cases.sh
├── cases/
│ └── Case0/ Example case
└── output/ Generated solutions