#simulated-annealing #distributed-systems #experiment #annealing #sim #simulation

simul

一个面向高级用例的离散事件模拟库,旨在快速模拟现实世界问题和运行模拟实验。一些示例用例可能包括模拟物流或运筹学问题,运行实验以确定最佳参数,模拟排队系统、分布式系统、性能工程等。

18个不稳定版本 (3个重大更改)

0.4.1 2024年3月31日
0.4.0 2024年3月31日
0.3.3 2024年3月26日
0.2.3 2023年7月7日
0.1.7 2023年7月5日

#200 in 数学

每月38次下载

MIT许可证

145KB
559

simul是一个面向高级用例的离散事件模拟库,旨在快速模拟现实世界问题和运行模拟实验。

simul是一个使用增量时间推进离散事件模拟器,使用M/M/c队列来模拟代理之间的交互。它还支持一些实验形式和模拟退火,以多次复制模拟,并改变模拟参数。

用例

使用方法

警告

实验性和不稳定。几乎所有API都预计会更改。

基本用法

[dependencies]
simul = "0.3.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(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![
        periodic_producing_agent("producer".to_string(), 1, "consumer".to_string()),
        periodic_consuming_agent("consumer".to_string(), 3),
    ],
    // You can set the starting epoch for the simulation. 0 is normal.
    starting_time: 0,
    // Whether to collect telemetry on queue depths at every tick.
    // Useful if you're interested in backlogs, bottlenecks, etc. Costs performance.
    enable_queue_depth_metric: true,
    /// Records a metric on the number of cycles agents were asleep for.
    enable_agent_asleep_cycles_metric: 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();

带绘图泊松分布的示例

以下是一个模拟运行输出的图形示例。在这个模拟中,我们显示了咖啡馆排队中顾客的平均等待时间。顾客以泊松分布的到达率(lambda<-60.0)和相同的泊松分布的咖啡服务率到达。

这个模拟通过假设离散模拟时间的一个刻度等于一秒来映射到现实世界。

基本上,咖啡师每杯咖啡大约需要60秒,顾客的到达率大约相同,两者都由随机泊松发生器建模。

这个模拟有一个halt_check条件,表示模拟时间等于60*60*12,即12个小时的完整营业日。

下面是生成上述情况的代码示例。

use plotters::prelude::*;
use rand_distr::Poisson;
use simul::agent::*;
use simul::*;
use std::path::PathBuf;

fn main() {
    run_example_cafe_simulation();
}

fn run_example_cafe_simulation() -> Result<(), Box<dyn std::error::Error>> {
    let mut simulation = Simulation::new(SimulationParameters {
        agents: vec![
            poisson_distributed_consuming_agent("Barista".to_string(), Poisson::new(60.0).unwrap()),
            poisson_distributed_producing_agent(
                "Customers".to_string(),
                Poisson::new(60.0).unwrap(),
                "Barista".to_string(),
            ),
        ],
        starting_time: 0,
        enable_queue_depth_metric: true,
        halt_check: |s: &Simulation| s.time == 60 * 60 * 12,
    });

    simulation.run();

    plot_queued_durations_for_processed_messages(
        &simulation,
        &["Barista".into()],
        &"/tmp/cafe-example-queued-durations.png".to_string().into(),
    )
}

贡献

问题、错误和特性在TODO.org中跟踪

依赖项

~1.3–2MB
~40K SLoC