Architecture Overview¶
High-level design of Waremax.
Design Philosophy¶
Waremax is designed around these principles:
- Modularity: Independent, composable crates
- Determinism: Same inputs produce same outputs
- Performance: Efficient discrete event simulation
- Extensibility: Easy to add custom components
System Architecture¶
┌─────────────────────────────────────────────────────────┐
│ CLI Layer │
│ ┌─────┐ ┌─────────┐ ┌───────┐ ┌─────────┐ ┌─────────┐ │
│ │ run │ │validate │ │ sweep │ │benchmark│ │ analyze │ │
│ └─────┘ └─────────┘ └───────┘ └─────────┘ └─────────┘ │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────┐
│ Configuration Layer │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ waremax-config │ │waremax-testing │ │
│ │ (parsing) │ │ (presets) │ │
│ └────────────────┘ └────────────────┘ │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────┐
│ Simulation Layer │
│ ┌─────────────────────────────────────────────────────┐│
│ │ waremax-sim ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │waremax-core │ │waremax- │ │waremax- │ ││
│ │ │ (DES engine)│ │entities │ │policies │ ││
│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────┘│
└────────────────────────┬────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────┐
│ Data Layer │
│ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │
│ │waremax-map │ │waremax- │ │ waremax-metrics │ │
│ │ (topology) │ │storage │ │ (collection) │ │
│ └────────────┘ └────────────┘ └────────────────────┘ │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────┐
│ Analysis Layer │
│ ┌─────────────────────────────────────────────────────┐│
│ │ waremax-analysis ││
│ │ (statistics, comparisons, reporting) ││
│ └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
Core Concepts¶
Discrete Event Simulation (DES)¶
The simulation is event-driven:
- Events are scheduled with timestamps
- Events are processed in time order
- Processing an event may schedule new events
- Simulation advances by jumping between events
// Conceptual event loop
while let Some(event) = scheduler.next_event() {
simulation_time = event.time;
event.process(&mut state);
// Processing may schedule new events
}
Entity-Component Design¶
Simulation entities (robots, stations) are modular:
Policy Abstraction¶
Decisions are made by pluggable policies:
trait TaskAllocationPolicy {
fn allocate(&self, task: &Task, robots: &[Robot]) -> Option<RobotId>;
}
Key Data Structures¶
Event¶
struct Event {
time: SimTime,
priority: u32,
payload: EventType,
}
enum EventType {
OrderArrival(Order),
TaskAssignment(TaskId, RobotId),
RobotArrival(RobotId, NodeId),
ServiceComplete(RobotId, StationId),
// ...
}
Simulation State¶
struct SimulationState {
time: SimTime,
map: WarehouseMap,
robots: Vec<Robot>,
stations: Vec<Station>,
tasks: TaskQueue,
metrics: MetricsCollector,
}
Configuration¶
struct Scenario {
simulation: SimulationConfig,
map: MapConfig,
robots: RobotConfig,
stations: Vec<StationConfig>,
orders: OrderConfig,
policies: PolicyConfig,
// ...
}
Execution Flow¶
Initialization¶
1. Parse configuration (YAML → Scenario)
2. Build warehouse map (MapConfig → WarehouseMap)
3. Create entities (robots, stations)
4. Initialize policies
5. Schedule initial events (order generator)
Main Loop¶
1. Pop next event from scheduler
2. Advance simulation time
3. Process event (update state, create new events)
4. Collect metrics
5. Check termination condition
6. Repeat
Termination¶
Threading Model¶
Single-Threaded Simulation¶
Each simulation runs single-threaded for determinism:
Parallel Runs¶
Multiple simulations can run in parallel:
// Sweep runs multiple configurations in parallel
scenarios.par_iter().map(|s| simulate(s)).collect()
Memory Model¶
Ownership¶
- Simulation owns all entities
- Events contain references/IDs, not owned data
- Metrics are collected incrementally
Efficiency¶
- Events are lightweight
- Entity lookup via IDs (not pointer chasing)
- Pre-allocated collections where possible
Error Handling¶
Configuration Errors¶
Caught early during parsing:
Simulation Errors¶
Handled during execution:
Related¶
- Crate Structure: Detailed crate breakdown
- Data Flow: How data moves
- Discrete Event Simulation: DES concepts