odem-rs 0.3.0

Object-based Discrete-Event Modelling in Rust using async/await
Documentation

Object-based Discrete-Event Modeling for Rust

crates.io docs.rs License: MIT MSRV

Odem-rs is a discrete-event simulation library for Rust that uses async/await to model concurrent agents. It provides a deterministic, extensible framework for building Monte Carlo-style simulation models where agents interact through scheduled jobs.

Key Features

  • Process-Based Simulation: Models simulation entities as asynchronous agents with isolated state and internally concurrent jobs.
  • Event-Driven Execution: Skips directly between significant events rather than executing at fixed time intervals.
  • Deterministic & Portable: Uses deterministic PRNGs and cooperative concurrency for reproducible results.
  • Flexible & Extensible: Provides library traits to tailor simulators and data structures for custom needs.
  • Safe & Sound: Validated with Miri to detect undefined behavior and enforce stacked borrow rules.
  • Integrated: Integrates seamlessly with tracing, uom, rand, and rayon.
  • Embedded-friendly: Can be used in bare-metal environments with a reduced feature-set.

Try the interactive simulation dashboard to experiment with example models in your browser.

Getting Started

Installation

Add odem-rs to your Cargo.toml:

[dependencies]
odem-rs = "0.3"

Example: Barbershop Simulation

To get you started quickly, here is an example scenario featuring a simple barbershop model. Customers arrive at random intervals and request service from a single barber. Once a customer arrives, they occupy the barber for a random duration simulating the haircut, then release the barber for the next customer. The simulation will run for 12 hours.

use odem_rs::{prelude::*, sync::facility::Facility};
use core::pin::pin;

#[derive(Config, Default)]
#[time = "Time<f64>"]
struct Barbershop {
	joe: Facility,
	rng_stream: RngStream,
}

struct Customer(Time<f64>);
impl Behavior<Barbershop> for Customer {
	type Output = ();

	async fn actions(&self, sim: &Sim<Barbershop>) {
		let chair = sim.global().joe.seize().await;
		sim.advance(self.0).await;
		chair.release();
	}
}

#[odem_rs::main]
async fn main(sim: &Sim<Barbershop>) {
	sim.fork(async {
		let mut rng_a = sim.global().rng_stream.rng();
		let mut rng_s = sim.global().rng_stream.rng();
		let pool = pin!(Pool::dynamic().with(Agent::new));

		loop {
			let arrival = minute::new(rng_a.random_range(12.0..24.0));
			let service = minute::new(rng_s.random_range(12.0..18.0));
			sim.advance(arrival).await;
			sim.activate(pool.alloc(Customer(service)));
		}
	}).or(sim.advance(hour::new(12.0))).await;
}

More examples can be found in the examples directory.

Execution Model

Odem-rs follows a discrete-event execution model, where simulation advances incrementally based on scheduled events. At any given model time, all continuations (representing agents and jobs) that are scheduled for execution are processed instantaneously in terms of model time before the clock is advanced. Thus, the passing of model time is explicit, allowing for deterministic execution. The execution order is determined by:

  • Model time: Monotonically increasing time preserves cause-and-effect relationships between processes.
  • Rank (between agents): Defines execution priority among different agents.
  • Precedence (between jobs): Ensures the correct sequencing of dependent jobs within one agent.
  • Insertion Order: Resolves ties between jobs with equal precedence by executing them in the order they were scheduled.

Once all tasks at a given model time have executed, the simulation clock jumps to the next scheduled event. This execution model is managed by an event calendar integrated into the async/await runtime executor, ensuring deterministic ordering while leveraging Rust's native concurrency.

Feature Flags

Odem-rs uses Cargo feature flags to control optional functionality. All flags listed as "default" are enabled when you add odem-rs as a dependency without further configuration. To start from a minimal base, set default-features = false and enable only what you need.

Feature Default Description
std yes Standard library support (implies alloc).
alloc yes Heap allocation for dynamic data structures.
tracing yes Structured instrumentation via the tracing crate.
debug-tracing no Debug-level trace output for internal state machines.
uom yes Type-safe SI quantities for model time.
rand_pcg yes PCG-family pseudo-random number generators.
rand_xoshiro no XoShiRo-family pseudo-random number generators.
rayon yes Parallel iteration for independent simulation runs.
libm no Software math functions for no_std environments.

See the API documentation for detailed descriptions of each feature flag.

Re-exported Crates

Odem-rs re-exports its ecosystem dependencies so you can use version-compatible crates without adding them separately.

Crate Version Feature
rand 0.10 always
intrusive_collections 0.10 always
uom 0.38 uom
tracing 0.1 tracing
rayon 1 rayon
typed_arena 2 alloc
rand_pcg 0.10 rand_pcg
rand_xoshiro 0.8 rand_xoshiro
use odem_rs::rand;           // rand 0.10
use odem_rs::uom;            // uom 0.38  (requires feature "uom")
use odem_rs::rayon;          // rayon 1   (requires feature "rayon")

Contributors & Acknowledgments

Odem-rs is the result of doctoral research and has benefited from contributions by:

  • Lukas Markeffsky, with whom I enjoyed in-depth discussions on Rust's type system and whose incredible insight and sharp mind helped a lot to find and resolve soundness issues in addition to improving the ergonomics of the library.
  • Paula Wiesner, with whom I performed early prototyping of agent-based approaches and who is still interested in the progress of this project, despite having successfully moved past academia. I appreciate the enthusiasm!

I welcome contributions, feedback, and feature requests! Open an issue or submit a PR.

License

Odem-rs is licensed under MIT. See LICENSE for details.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in odem-rs by you, shall be licensed as MIT, without any additional terms or conditions.