macro_rules! evolutionary_search {
    (
        $init_population:tt,
        $fitness:tt,
        $selection:tt,
        $mutation:tt,
        $crossover:tt,
        $cmp:tt,
        $state: ty,
        $desired_fitness: expr,
        $generation_num: expr,
        $step: expr,
        $($reps: expr,)?
        ComputingMode::$computing_mode: tt
    ) => { ... };
    (
        $init_population:tt,
        $fitness:tt,
        $selection:tt,
        $mutation:tt,
        $crossover:tt,
        $cmp:tt,
        $state: ty,
        $desired_fitness: expr,
        $generation_num: expr,
        $step: expr,
        $($reps: expr)?
    ) => { ... };
}
Expand description

Macro to optimizes the simulation parameters by adopting an evolutionary searching strategy. Specifically, krABMaga provides a genetic algorithm-based approach. The macro will generate a dataframe with the results of the exploration. The dataframe can be saved in a csv file.

Arguments

  • init_population - function that creates the population, must return an array of individual (an individual is the state of the simulation to compute)
  • fitness - function that computes the fitness value, takes a single individual and the schedule, must return an f32
  • mutation - function that perform the mutation, takes a single individual as parameter
  • crossover - function that creates the population, takes the entire population as parameter
  • state - state of the simulation representing an individual
  • desired_fitness - desired fitness value
  • generation_num - max number of generations to compute
  • step - number of steps of the single simulation
  • reps - number of repetitions of the simulation using each individual (optional, default is 1)

Last parameter is the computing mode to use. Without the last parameter, the macro will use the default computing mode (Sequential). The computing mode can be:

  • ComputingMode::Parallel: the exploration will be performed in parallel
  • ComputingMode::Distributed: the exploration will be performed distributing the computation on different machines
  • ComputingMode::Cloud: computation will be performed on the cloud.

Example

pub const STEP: u64 = 100;
pub const REPETITIONS: u32 = 20;

pub const DESIRED_FITNESS: f32 = 0.;
pub const MAX_GENERATION: u32 = 2_000;

fn main() {
    let result = explore_ga_sequential!(
        init_population,
        fitness,
        selection,
        mutation,
        crossover,
        cmp,
        State,
        DESIRED_FITNESS,
        MAX_GENERATION,
        STEP,
        REPETITIONS, //optional
        // ComputingMode::Parallel, ComputingMode::Distributed or ComputingMode::Cloud
    );
    if !result.is_empty() {
        let name = "explore_result".to_string();
        let _res = write_csv(&name, &result);
    }
}

// Create the initial population. In genetic algorithms, an individual is represented as a String
fn init_population() -> Vec<String> { ... }

// Compute the fitness value of an individual using results of each repetition
// * computed_ind: Vec with couple of (state, fitness)
//   of an individual for each repetition in the current generation
fn fitness(computed_ind: &mut Vec<(EpidemicNetworkState, Schedule)>) -> f32 { ... }

// Select/Order the population based on the fitness value
fn selection(population_fitness: &mut Vec<(String, f32)>) { ... }

// Perform the mutation of an individual
fn mutation(individual: &mut String) { ... }

// Perform the crossover to generate the new population
fn crossover(population: &mut Vec<String>) { ... }

// Compare two individuals
fn cmp(fitness1: &f32, fitness2: &f32) -> bool { ... }