vle.recursive
Introduction
The package vle.recursive allows to perform multisimulations. Based on the vle API, one can launch simulations of an embedded model into a vle Dynamics. It provides:
 An API MetaManager for performing multi simulations
 A dynamic based on this API that can be configured by experimental conditions
The goals are:
 to provide both an API and a PDEVS dynamic for multi simulation, based on the same approach for configuration.
 to use the same approach for configuring MPI and thread parallelization provided into vle. Use either the vle implementation of vle (if available) or native threading parallelization.
 to facilitate the stochastic simulation.
 to provide simple tools for aggregating simulation results.
 to provide an alternative to multi simulation with R, with less memory allocation.
Tutorial on vle.recursive package
Let us consider the SIR model as described on the Wikipedia page:
dS/dt =  beta * I * S;
dI/dt = beta * I * S  gamma * I;
dR/dt = gamma * I;
One also defines a simple stochastic version (called SIRnoise):
dS/dt =  beta * I * S * espilon1;
dI/dt = beta * I * S * epislon1  gamma * I * epsilon2;
dR/dt = gamma * I * epsilon2;
epsilon1 ~ N(1, 0.3)
epsilon2 ~ N(1, 0.3)
The default parameters of the models are: S(0) = 99; I(0)=1; R(0)=0; beta=0.002; gamma=0.1. For the stochastic version, we also have a parameter ‘seed’ that gives the seed of the random number generator. Below, the result of the deterministic version with default paramters, for 60 integration time steps, are plotted into gvle.
 Performing multiple simulations: we consider 5 different values of S(0) and for each, we compute the mean value of the final states of S for 6 replicates with different ‘seed’ values.
namespace vr = vle::recursive;
namespace vv = vle::value;
vv::Map init;
init.addString("package","vle.recursive_test");
init.addString("vpz","SIRnoise.vpz");
//config output, 'mean' on replicate, 'all' on inputs
vv::Map& conf_out = init.addMap("output_Sfinal");
conf_out.addString("path", "view/top:SIRnoise.S");
conf_out.addString("integration", "last");
conf_out.addString("aggregation_replicate", "mean");
conf_out.addString("aggregation_input", "all");
//set 5 input values for S(0)
vv::Tuple& Svalues = init.addTuple(
"input_condSIRnoise.init_value_S", 5, 0.0);
Svalues[0] = 150;
Svalues[1] = 120;
Svalues[2] = 99;
Svalues[3] = 75;
Svalues[4] = 50;
//set 6 seeds for initializing the rng.
vv::Tuple& seeds = init.addTuple(
"replicate_condSIRnoise.init_value_seed", 6, 0.0);
seeds[0] = 45694;
seeds[1] = 55695;
seeds[2] = 65696;
seeds[3] = 85698;
seeds[4] = 95699;
vr::MetaManager meta;
vle::manager::Error err;
std::unique_ptr<vv::Map> res = meta.run(init, err);
if (err.code ==1) {
std::cout << " error: " << err.message << "\n";
}
std::cout << " Results of final S: " << *res << "\n";
//(Sfinal, ((11.5526,22.2598,36.1712,51.3126,45.0968)))
 Evaluating the model on observations: let us consider we have at our disposal three observations of the number of infectious subjects, at times 20, 30 and 40. And we want to compute the mean square error of the simulations for different values of beta.
vv::Map init;
init.addString("package","vle.recursive_test");
init.addString("vpz","SIR.vpz");
//config output, mse on S
vv::Map& conf_out = init.addMap("output_mseI");
conf_out.addString("path", "view/top:SIR.I");
conf_out.addString("integration", "mse");
vv::Tuple& mseTimes = conf_out.addTuple("mse_times", 3,0.0);
mseTimes[0] = 20;
mseTimes[1] = 30;
mseTimes[2] = 40;
vv::Tuple& mseObs = conf_out.addTuple("mse_observations", 3,0.0);
mseObs[0] = 6;
mseObs[1] = 10;
mseObs[2] = 15;
conf_out.addString("aggregation_input", "all");
//set 3 input values for beta parameter
vv::Tuple& beta = init.addTuple("input_condSIR.init_value_beta", 3, 0.0);
beta[0] = 0.001;
beta[1] = 0.002;
beta[2] = 0.003;
vr::MetaManager meta;
vle::manager::Error err;
std::unique_ptr<vv::Map> res = meta.run(init, err);
if (err.code ==1) {
std::cout << " error: " << err.message << "\n";
}
std::cout << " Mse on I for beta in (0.001,0.002,0.003): " << *res << "\n";
//(mseI, ((102.158,0.233604,228.278)))
(code of the tutorial into vle.recursive_test)
The MetaManager API
The MetaManager is configured by a vle::value::Map provided by the user. It can contains:

vpz (string) : it gives the name of the vpz file. It allows to identify together with package the embedded model.

package (string) : it gives the name of the package where is located the embedded model. It allows to identify together with vpz the embedded model.

define_X (value::Boolean, optional) : where X is of the form condname.portname. If true, the port portname of the condition condname will be added to the embedded model. If false, it will be removed. This action is perfomed before taking into account propagate, input and replicate paremeters (see below).

propagate_X (value::Value, optional) : where X is of the form condname.portname, it specifies the value to set for all simulations to a port condition of the embedded model.

input_X (value::Set or value::Tuple): where X is of the form condname.portname, it gives for one input the values to simulate. The size of the value::Set or value::Tuple defines the number N of combination inputs to simulate. For each input, it is required to have the same value of N.

replicate_X (value::Set or value::Tuple, optional) where X is of the form condname.portname, it gives the values to simulate for the replicates (eg. seeds). The size of the value::Set or value::Tuple defines the number M of replicates to simulate. For each input, it is required to have the same value M. If no replicate is specified then M=1. Finally, the total number of simulations performed is N * M.

output_Y (vle::value::Map) : where Y is an id for the output. The map should/could provide:
 path (string): is of the form viewname/pathOfTheAtomicModel.ObsPort. It identifies the column of outputs ObsPort computed by the atomic model pathOfTheAtomicModel and stored into the view viewname.
 integration (amongst ’last’, ‘max’, ‘mse’ or ‘all’, default ’last’): the type of temporal integration to perform. the output with id X. The string has the following form:
 aggregation_replicate (amongst ‘mean’, ‘variance’, ‘quantile’, default ‘mean’): It gives the type of aggregation to perform on the simulations replicates, once the temporal integration has been performed.
 aggregation_input (amongst ‘mean’, ‘max’, ‘all’ default ‘all’): It gives the type of aggregation to perform on the simulations inputs, once replicates have been aggregated.
 mse_times (value::Tuple): required only if integration=‘mse’. It gives times at which the mse_observations are given.
 mse_observations (value::Tuple): required only if integration=‘mse’. It gives the serie of observations for computing the MSE. mse_observations and mse_times must have the same length.
 replicate_quantile (value::Double): required only if aggregation_replicate=‘quantile’. It gives the quantile order to use for aggregating replicates.

config_parallel_type (string amongst threads, cvle and single; default single). It sets the type of parallelization to perform.

config_parallel_spawn (bool; default false). If true, each simulation is launched in a sub process.

config_parallel_nb_slots (int > 0). it gives the number of slots to use for parallelization.

config_parallel_rm_files (bool; default true). Used only if config_parallel_type is set to cvle. Simulation files created into directory working_dir are removed after analysis.

working_dir (string). Required only if config_parallel_type is set to cvle. It gives the working directory where are produced result file of single simulations.
The MetaManager dynamic
The MetaManager atomic model has the following dynamic, implemented in PDEVS framework:
 If the conditions provide an initialization map for the MetaManager API, it performs the simulation of the experimental plan during the PDEVS initialization step, then it falls asleep for a given duration, then it outputs the results, and then falls asleep indefinitely.
 Each time it receives an experiment plan setting on its input port, it performs the simulation of the experiment plan, then it falls asleep for a duration, then it outputs the results and then falls asleep indefinitely. the results.
Configuring the dynamic consists in giving the elements required for the API configuration directly into conditions ports. Other configuration keys are:
 step_duration (double, default 0). It gives the duration time, for the embedding simulator engine clock, required for the simulation of the experiment plan.