| Crates.io | odem-rs |
| lib.rs | odem-rs |
| version | 0.2.0 |
| created_at | 2025-02-21 16:49:42.976998+00 |
| updated_at | 2025-06-20 21:45:02.5749+00 |
| description | Object-based Discrete-Event Modelling in Rust using async/await |
| homepage | |
| repository | https://gitlab.informatik.hu-berlin.de/weber/odem-rs |
| max_upload_size | |
| id | 1564448 |
| size | 137,587 |
ODEM-rs is a high-performance, object-based discrete-event modeling library for Rust, designed to facilitate
Monte Carlo-style simulation models using Rustโs async/await system. It provides an extensible,
deterministic, and event-driven framework where concurrent agents interact through scheduled jobs.
tracing, uom, and rand.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:
Once all scheduled tasks for a specific model time have executed, the simulation time jumps to the next scheduled event,
skipping idle periods. This execution model is managed by an event calendar, which is a part of the async/await
runtime executor. The executor schedules and processes continuations in deterministic order as described above. This
allows ODEM-rs to seamlessly integrate with Rustโs async runtime model, leveraging native concurrency while maintaining
strict event sequencing.
Add ODEM-rs to your Cargo.toml:
[dependencies]
odem-rs = "0.2"
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());
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(Agent::new(Customer(service))));
}
}).or(sim.advance(hour::new(12.0))).await;
}
More examples can be found in the examples directory.
ODEM-rs is part of ongoing doctoral research and has benefited from contributions by:
I welcome contributions, feedback, and feature requests! Open an issue or submit a PR.
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.