rustsim-core 0.0.1

Core ABM engine: agents, models, stores, schedulers, stepping, data collection
Documentation
use rand::rngs::StdRng;
use rand::SeedableRng;
use rustsim_core::{
    collect::collect_step,
    prelude::{Agent, AgentStore, Fastest, HashMapStore, StandardModel, Time},
    standard::HasAgentIds,
    types::AgentId,
};
mod support;
use support::NothingSpace;

#[derive(Debug, Clone)]
struct CounterAgent {
    id: AgentId,
    value: i32,
}

impl Agent for CounterAgent {
    fn id(&self) -> AgentId {
        self.id
    }
}

type CounterModel =
    StandardModel<NothingSpace, CounterAgent, HashMapStore<CounterAgent>, (), StdRng, Fastest>;

fn counter_step(
    agent: &mut CounterAgent,
    _ctx: &mut rustsim_core::step_context::StepContext<
        '_,
        NothingSpace,
        CounterAgent,
        (),
        StdRng,
        Fastest,
    >,
) {
    agent.value += 1;
}

#[derive(Debug, Clone, PartialEq)]
struct AgentSnapshot {
    time: Time,
    id: AgentId,
    value: i32,
}

#[derive(Debug, Clone, PartialEq)]
struct ModelSnapshot {
    time: Time,
    agent_count: usize,
}

#[test]
fn collect_agent_and_model_data_across_steps() {
    let mut store = HashMapStore::new();
    store.insert(CounterAgent { id: 1, value: 0 });
    store.insert(CounterAgent { id: 2, value: 10 });

    let mut model = CounterModel::new(
        store,
        NothingSpace,
        Fastest::new(),
        (),
        StdRng::seed_from_u64(0),
        Some(Box::new(counter_step)),
        None,
        true,
    );

    let agent_report = |agent: &CounterAgent, model: &CounterModel| AgentSnapshot {
        time: model.time(),
        id: agent.id(),
        value: agent.value,
    };

    let model_report = |model: &CounterModel| ModelSnapshot {
        time: model.time(),
        agent_count: model.agent_ids().len(),
    };

    let mut agent_data: Vec<AgentSnapshot> = Vec::new();
    let mut model_data: Vec<ModelSnapshot> = Vec::new();

    let ids: Vec<AgentId> = model.agent_ids();
    collect_step(
        &model,
        &ids,
        Some(&agent_report),
        Some(&model_report),
        &mut agent_data,
        &mut model_data,
    );

    assert_eq!(agent_data.len(), 2);
    assert_eq!(model_data.len(), 1);
    assert_eq!(model_data[0].agent_count, 2);
    assert_eq!(model_data[0].time, Time::Discrete(0));

    model.step();

    let ids: Vec<AgentId> = model.agent_ids();
    collect_step(
        &model,
        &ids,
        Some(&agent_report),
        Some(&model_report),
        &mut agent_data,
        &mut model_data,
    );

    assert_eq!(agent_data.len(), 4);
    assert_eq!(model_data.len(), 2);
    assert_eq!(model_data[1].time, Time::Discrete(1));

    let post_step: Vec<_> = agent_data[2..].to_vec();
    for snap in &post_step {
        assert_eq!(snap.time, Time::Discrete(1));
        assert!(snap.value > 0);
    }
}