Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.

ODEM-rs: Object-Based Discrete-Event Modeling in Rust

Crates.io Documentation License: MIT

ODEM-rs is a modular object-based discrete-event modeling framework for Rust. It provides an extensible, deterministic simulation environment with structured concurrency using async/await.

:rocket: Features

  • Process-Based Simulation: Model simulation entities as concurrent agents with isolated state and internal concurrency.
  • Event-Driven Execution: Skips directly between events rather than using a fixed time step.
  • Deterministic & Reproducible: Uses pseudo-random number generators (PRNGs) and cooperative concurrency for portably reproducable results.
  • Extensible & Modular: Provides traits and modular components across multiple crates.
  • no_std Compatible: Supports bare-metal execution with minimal reductions in provided utilities.

:package: Crate Organization

The ODEM-rs workspace consists of several crates, each serving a specific purpose:

Crate Description
odem-rs Main library providing the entry point to the simulation framework.
odem-rs-core Foundational structures, traits, and event-scheduling logic.
odem-rs-meta Procedural macros for auto-generating configuration traits.
odem-rs-sync Synchronization primitives and communication structures for agents and jobs.
odem-rs-util Utility tools such as object pools, PRNG streams, and statistics modules.

:book: Getting Started

Installation

Add ODEM-rs to your Cargo.toml:

[dependencies]
odem-rs = "0.1"

Or include specific sub-crates if you only need certain components.

Example: Barbershop Simulation

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

#[derive(Config, Default)]
struct Barbershop {
	barber: Facility,
	rng_stream: RngStream,
}

struct Customer;

impl Behavior<Barbershop> for Customer {
	type Output = ();
	async fn actions(&self, sim: &Sim<Barbershop>) {
		let mut duration = sim.global().rng_stream.rng();
		let chair = sim.global().barber.seize().await;
		sim.advance(duration.random_range(12.0..18.0)).await;
		chair.release();
	}
}

async fn sim_main(sim: &Sim<Barbershop>) {
	sim.fork(async {
		let mut delay = sim.global().rng_stream.rng();
		let pool = Pool::dynamic();
		loop {
			sim.advance(delay.random_range(12.0..24.0)).await;
			sim.activate(pool.alloc(Agent::new(Customer)));
		}
	}).or(sim.advance(12.0 * 60.0)).await;
}

fn main() {
	simulation(sim_main).ok();
}

More examples can be found in the examples directory.

:busts_in_silhouette: Contributors & Acknowledgments

ODEM-rs is part of my doctoral research and has received invaluable contributions from:

  • Lukas Markeffsky – Type system discussions and problem-solving.
  • Paula Wiesner – Initial agent-based prototyping.
  • Jens-Peter Redlich – Academic advisory support.
  • Joachim Fischer – Mentorship and insights into simulation modeling.

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

:scroll: License

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