1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use anyhow::Context;

use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm};

use necsim_core::{
    cogs::{MathsCore, RngCore},
    reporter::Reporter,
};
use necsim_core_bond::{NonNegativeF64, PositiveF64};
use necsim_impls_no_std::cogs::origin_sampler::pre_sampler::OriginPreSampler;
use necsim_partitioning_core::LocalPartition;

use rustcoalescence_scenarios::{Scenario, ScenarioCogs};

use crate::args::config::sample::{Sample, SampleMode, SampleModeRestart, SampleOrigin};

pub(super) fn simulate<
    'p,
    M: MathsCore,
    G: RngCore<M>,
    A: Algorithm<'p, M, G, O, R, P>,
    O: Scenario<M, G>,
    R: Reporter,
    P: LocalPartition<'p, R>,
>(
    local_partition: &mut P,

    sample: Sample,
    rng: G,
    scenario: ScenarioCogs<M, G, O>,
    algorithm_args: A::Arguments,
    pause_before: Option<NonNegativeF64>,
) -> anyhow::Result<SimulationOutcome<M, G>> {
    let lineages = match sample.origin {
        SampleOrigin::Habitat => {
            return A::initialise_and_simulate(
                algorithm_args,
                rng,
                scenario,
                OriginPreSampler::all().percentage(sample.percentage),
                pause_before,
                local_partition,
            )
            .context("Failed to perform the fresh simulation.")
        },
        SampleOrigin::List(lineages) => lineages,
        SampleOrigin::Bincode(loader) => loader.into_lineages(),
    };

    match sample.mode {
        SampleMode::Genesis => A::initialise_and_simulate(
            algorithm_args,
            rng,
            scenario,
            OriginPreSampler::all().percentage(sample.percentage),
            pause_before,
            local_partition,
        )
        .context("Failed to perform the fresh simulation."),
        SampleMode::Resume => A::resume_and_simulate(
            algorithm_args,
            rng,
            scenario,
            OriginPreSampler::all().percentage(sample.percentage),
            lineages.into_iter(),
            None,
            pause_before,
            local_partition,
        )
        .context("Failed to perform the resuming simulation."),
        SampleMode::FixUp(strategy) => A::fixup_for_restart(
            algorithm_args,
            rng,
            scenario,
            OriginPreSampler::all().percentage(sample.percentage),
            lineages.into_iter(),
            PositiveF64::new(pause_before.unwrap().get()).unwrap(),
            strategy,
            local_partition,
        )
        .context("Failed to fix-up the restarting simulation."),
        SampleMode::Restart(SampleModeRestart { after }) => A::resume_and_simulate(
            algorithm_args,
            rng,
            scenario,
            OriginPreSampler::all().percentage(sample.percentage),
            lineages.into_iter(),
            Some(after),
            pause_before,
            local_partition,
        )
        .context("Failed to perform the restarting simulation."),
    }
}