A discrete simulation library for simulating [[https://authors.library.caltech.edu/60491/1/MGM%20113.pdf][Complex Adaptive Systems]]. Specifically, =simul= is a /discrete-event simulator/ using /incremental time progression/, with [[https://en.wikipedia.org/wiki/M/M/c_queue][M/M/c queues]] for interactions between agents.
Warning
Experimental and unstable. Almost all APIs are expected to change.
** Barebones basic example
[dependencies] simul = "0.1"
use simul::Simulation; use simul::agent::*;
// Runs a simulation with a producer that produces work at every tick of // discrete time (period=1), and a consumer that cannot keep up (can only // process that work every third tick). let mut simulation = Simulation::new( let mut simulation = Simulation::new(SimulationParameters { // We pass in two agents: // one that produces -> consumer every tick // one that simply consumes w/ no side effects every third tick agents: vec![ periodicproducingagent("producer", 1, "consumer"), periodicconsumingagent("consumer", 3), ], // You can set the starting epoch for the simulation. 0 is normal. startingtime: 0, // Whether to collect telemetry on queue depths at every tick. // Useful if you're interested in backlogs, bottlenecks, etc. Costs performance. enablequeuedepthtelemetry: true, // We pass in a halt condition so the simulation knows when it is finished. // In this case, it is "when the simulation is 10 ticks old, we're done." halt_check: |s: &Simulation| s.time == 10, });
simulation.run();
** Poisson-distributed example w/ Plotting
Here's an example of an outputted graph from a simulation run. In this simulation, we show the average waiting time of customers in a line at a cafe. The customers arrive at a Poisson-distributed arrival rate (=lambda<-60.0=) and a Poisson-distributed coffee-serving rate with the same distribution.
This simulation maps to the real world by assuming one tick of discrete-simulation time is equal to one second.
Basically, the barista serves coffees at around 60 seconds per drink and the customers arrive at about the same rate, both modeled by a stochastic Poisson generator.
This simulation has a =halt_check= condition of the simulation's time being equal to =606012=, representing a full 12-hour day of the cafe being open.
[[./readme-assets/cafe-example-queued-durations.png]]
This is a code example for generating the above, from =main.rs=:
use plotters::prelude::; use rand_distr::Poisson; use simul::agent::; use simul::*; use std::path::PathBuf;
fn main() { runexamplecafe_simulation(); }
fn runexamplecafesimulation() -> Result<(), Box
simulation.run();
plot_queued_durations_for_processed_tickets(
&simulation,
&["Barista".into()],
&"/tmp/cafe-example-queued-durations.png".to_string().into(),
)
}