vle.discrete-time

To build discrete time models

Introduction

The vle extension vle.discrete-time can be used to model and simulate discrete time atomic models into VLE. Discrete time atomic models are models that compute at time t outputs of variables v1, …, vn taking into account values of variables v1,…, vn, given a user specified parameter D, at times

t, t - D, t - 2 * D,…,

The packages related to this extension are:

  • vle.discrete-time provides the discrete time extension itself.
  • vle.discrete-time.decision provides a decision agent having a discrete time dynamic. It embeds a KnowledgeBase from package vle.extension.decision. This is an experimental package.
  • vle.discrete-time_test provides tests for discrete time models.

Evolution of state variables vi is described by C++ equation syntax close to mathematical formulation. These expressions must be written in the compute function.

For example the expression V1 = V1(-1) + V2() + V3(-2) computes, at current time t, the value of V1 as the sum of the value of V1 at time t - D, the current value of V2 and the value of V3 at time t - 2*D.

Behavior of temporal structures into discrete time models

Fig: A discrete-time atomic model with 6 variables, 3 can be updated from external event (inputs), 3 are sent by default at each time step on the network (outputs)

The interface (input and output ports) is given for an example in the above figure. Note that variables v1, …, v3 are not necessary inputs they could also be outputs. And variables v4, …, v6 could also have their input ports.

Writing atomic models

The vle/discrete-time/TemporalValues.hpp API provides functionnalities to handle variables (double, vector or polymorphic vle::value) and their history. Particularly, access operators are defined for these data structures. Available variables types are :

  • double. To use a temporal value of type double, you must use the struct vle::discrete_time::Var (see examples below).
  • vector of double. To use a temporal value of type vector of double, you must use the struct vle::discrete_time::Vect.
  • vle::value::Value: To use a temporal value of this type you must use the struct vle::discrete_time::ValueVle.

Temporal values maintain an historic of updates with dates and are browseable using access operator. Updates can be directly set by a devs::Dynamic if the temporal value is declared (in constructor or not) using the function Var::init, Vect::init or ValueVle::init (see lines 13, 14 in code).

Behavior of temporal structures into discrete time models

Fig: Example of updates for a temporal value of type Var.

In example depicted in the above figure, at current time t, the state of historic of Var S is:

[t1, a1],[t2, a3],[t3, a2],[t4, a1].

Operator () on S will give one of the update value. The signal is supposed to be piecewise constant function. Then

  • S(-0.3) returns value at time t - 0.3 * D, ie a1.
  • S(-3.6) returns value at time t - 3.6 * D, ie a3.
  • S() returns last update value, ie a1.

Operator = of Var allows to set an update (for example into the compute function of discrete-time model).

For Vectors (struct Vect):

  • S[1](-0.3) returns value at time t - 0.3 * D for the dimension 1.
  • S[0](-3.6) returns value at time t - 3.6 * D for the dimension 0.
  • S[2]() returns last update vector at index 2.
  • S[2]=1.5 updates value of S at dim 2 with 1.5.

Below is given an example of dynamic for an atomic model that relies on the extension vle.discrete-time.

class MyModel : public DiscreteTimeDyn
{
public:
  //Declaration of variables
  Var x;
  Vect y;
  Var z; // used in this module as an input
  MyModel(const vd::DynamicsInit& model, const vd::InitEventList& events) :
            DiscreteTimeDyn(model, events)
  {
    //Initialisation of variables from experimental conditions
    x.init(this, "x", events);
    y.init(this, "y", events);
    //Overwrite initialisations (Optionnal)
    x.init_value(3.0);
    x.history_size(3);
    y.dim(2)
  }
  void compute(const vd::Time& /*time*/)
  {
    x =  x(-1) - y[1]() / z();
    y[0] = z() - 1;
    y[1] = y[0]() + 1;
  }
};

Configuring atomic models

To configure discrete time atomic models, one can use the parameters from the vpz conditions listed below. The X refers to an internal variable (a real, a vector or a vle value).

Basic settings:

  • time_step (double, default 1.0) : the time step of the discrete time atomic model.
  • dim_X (int, default 2) : if X is a vector, it defines the dimension of the vector. Used only if X is a vector.
  • history_size_X (uint, default 1) : it gives the size of the history of internal variable X.
  • init_value_X (vle::Value, default vle::Double(0.0)) : the initial value of the internal variable X. It can be a vv::Double for a variable without history, a vv::Tuple for a variable with history or a vv::Table for a vector. Checks are performed with dim_X and history_size_X.
  • syncs (set of strings, default empty): each variable into this set are parameterized with a value of 1 for sync parameter.
  • sync_X (uint, default 0): if sync_X > 0, the value of X at times n * sync_X * time_step, with n > 0 is expected to be provided by an external event before calling the compute function. This option has priority on syncs.

Advanced settings for output configurations:

  • output_period (uint, default 1): gives the time step of output. Output will produce values each time_step * output_period.
  • output_period_X (uint, default 1): a specific value of output_period for variable X. This option has priority on output_period.
  • output_nil (bool, default false): if true, the output function will produce a Null value for a variable which last update is not equals to current time, otherwise it will gives the last updated value.
  • output_nil_X (bool, default false): a specific value of output_nil for variable X. This option has priority on output_nil.

Advanced settings for debugging:

  • snapshot_before (bool, default false) : if true, a snapshot of variable values is done before the compute function. It can be observed on the port X_before.
  • snapshot_after (bool, default false) : if true, a snapshot of variable values is done after the compute function. It can be observed on the port X_after.
  • error_no_sync_X (bool, default false) : if true, the access to X at the current time X() will send an error if the last time of update of X is before the current time.

Advanced settings for multiple update:

  • allow_update_X (bool, default false): if false, the first value set for X at a given time step is kept. The following updates for X at this time step are ignored.
  • forcing_X (a vle Map or Set, default empty): this option can not be used simultaneously with allow_update. The map (or set of such map) represents a forcing event. A forcing event forces the model to set a value to X at a given time. The map should contain:
    • time (double): the time of forcing event
    • value (real, vector or vle Value): the value of forcing event
    • before_output (bool, default false): true if the forcing event should occur before the output function of the dynamic.

Advanced settings for dynamic management of variables (this configuration can be dynamically set by an external event on port dyn_init with a map):

  • dyn_allow (bool, default false): if true, input and output ports added for example by an executive are automatically added as state variables after thecompute function.
  • dyn_type (‘Var’, ‘Vect’ or ‘ValueVle’, default ‘Var’): gives the type of new state variables to add. Used only if dyn_allow is true.
  • dyn_sync (uint, default 0): gives the type of synchronisation of new state variables to add as with sync_X. Used only if dyn_allow is true.
  • dyn_init_value (vle::Value, default vle::Double(0.0)): gives the initial value of new variables as with init_value_X. Used only if dyn_allow is true.
  • dyn_dim (uint, default 2): gives the dimension when creating a new Vect. Used only if dyn_allow is equal to true and dyn_type == Vect.
  • dyn_denys (set of strings, default empty): port names into this set are not added as state variables, even if dynamic managment is allowed.
  • dyn_allow_X (bool, default true): if sync_X is true, if the port named X exist, a variable of the name X can be added dynamically. If sync_X is false, the port named X is not considered for dynamic managment of variables. This option has priority on dyn_denys.

Advanced settings for synchronisation:

  • bags_to_eat (int, default 0) : the number of bags to wait before computing the values of variables (calls of compute user function).

Technical details

Diagram activity of discrete time models

Fig: The activity diagram of a discrete time model: sequence of calls at a given time step.

DEVS state of disctrete time models

Fig: The DEVS state transition graph for discrete-time atomic models.

This extension is intended to improve the functionnalities of extension vle.extension.difference-equation, to improve perfomance results and to limit the behavior in order to facilitate the coupling with other extensions :

  • there is no propagation of the perturbation : it requires a state backup and other extensions do not have this.
  • there is no initialization process of the dynamics (no initValue function): synchronisation at the time of instantiation of the atomic model makes it difficult to couple with DSDEVS.
  • there is no external variables. All variables are internal variables.
  • it provides vector of variables and polymorphic vle values.
  • It uses a DEVS state approah for the code of transitions