v2/
lib.rs

1//! # Simulation Library (version 2)
2//! This library provides an algorithm for a simulation.
3//!
4
5mod config;
6mod exec;
7mod io;
8mod parameter;
9
10use base::{
11    opinion::MyFloat,
12    runner::{run, RuntimeParams},
13    stat::FileWriters,
14};
15use config::Config;
16use exec::{AgentExt, Instance};
17use input::format::DataFormat;
18use io::MyPath;
19use polars_arrow::datatypes::Metadata;
20use rand_distr::{uniform::SampleUniform, Distribution, Exp1, Open01, Standard, StandardNormal};
21use std::path::PathBuf;
22
23/// A command line interface structure for the simulation
24#[derive(clap::Parser)]
25pub struct Cli {
26    /// string to identify given configuration data
27    identifier: String,
28    /// the path of output files
29    output_dir: PathBuf,
30    /// the path of a runtime config file
31    #[arg(long)]
32    runtime: MyPath<RuntimeParams>,
33    /// the path of a network config file
34    #[arg(long)]
35    network: PathBuf,
36    /// the path of a agent config file
37    #[arg(long)]
38    agent: PathBuf,
39    /// the path of a strategy config file
40    #[arg(long)]
41    strategy: PathBuf,
42    /// Enable inhibition information
43    #[arg(short, default_value_t = false)]
44    enable_inhibition: bool,
45    /// delayed steps of selfish from receiving information
46    #[arg(short, default_value_t = 0)]
47    delay_selfish: u32,
48    /// Enable overwriting of a output file
49    #[arg(short, default_value_t = false)]
50    overwriting: bool,
51    /// Compress a output file
52    #[arg(short, default_value_t = false)]
53    compressing: bool,
54}
55
56/// An entry point for the simulation
57pub async fn start<V>(args: Cli) -> anyhow::Result<()>
58where
59    V: MyFloat + SampleUniform + 'static,
60    Open01: Distribution<V>,
61    Standard: Distribution<V>,
62    StandardNormal: Distribution<V>,
63    Exp1: Distribution<V>,
64    V::Sampler: Sync + Send,
65    for<'de> V: serde::Deserialize<'de>,
66{
67    let Cli {
68        identifier,
69        output_dir,
70        runtime,
71        network,
72        agent,
73        strategy,
74        enable_inhibition,
75        delay_selfish,
76        overwriting,
77        compressing,
78    } = args;
79    let runtime_params = DataFormat::read(runtime.verified("")?)?.parse::<RuntimeParams>()?;
80    let metadata = Metadata::from_iter([
81        ("app".to_string(), env!("CARGO_PKG_NAME").to_string()),
82        ("version".to_string(), env!("CARGO_PKG_VERSION").to_string()),
83        ("runtime".to_string(), runtime.to_string_lossy().to_string()),
84        (
85            "agent_config".to_string(),
86            agent.to_string_lossy().to_string(),
87        ),
88        (
89            "network_config".to_string(),
90            network.to_string_lossy().to_string(),
91        ),
92        (
93            "strategy_config".to_string(),
94            strategy.to_string_lossy().to_string(),
95        ),
96        (
97            "enable_inhibition".to_string(),
98            enable_inhibition.to_string(),
99        ),
100        ("delay_selfish".to_string(), delay_selfish.to_string()),
101        (
102            "iteration_count".to_string(),
103            runtime_params.iteration_count.to_string(),
104        ),
105    ]);
106    let config = Config::try_new(network, agent, strategy)?;
107    let writers =
108        FileWriters::try_new(&identifier, &output_dir, overwriting, compressing, metadata)?;
109    let exec = config.into_exec(enable_inhibition, delay_selfish)?;
110    run::<V, _, AgentExt<V>, Instance>(writers, &runtime_params, exec, None).await
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::{start, Cli};
116
117    #[test]
118    fn test_start() -> anyhow::Result<()> {
119        let args = Cli {
120            identifier: "test-start".to_string(),
121            output_dir: "./test/result".into(),
122            runtime: "./test/runtime.toml".into(),
123            agent: "./test/agent_config.toml".into(),
124            network: "./test/network_config.toml".into(),
125            strategy: "./test/strategy_config.toml".into(),
126            enable_inhibition: true,
127            delay_selfish: 0,
128            overwriting: true,
129            compressing: true,
130        };
131        let rt = tokio::runtime::Runtime::new()?;
132        rt.block_on(async { start::<f32>(args).await })?;
133        Ok(())
134    }
135}