Generator

From VLE

Jump to: navigation, search

Generator is a model which does only generate an event without data (just a beep) evenry X time units, X can be a paramater.

Contents

First version

We considarate that none input event can occur.

Constructor :

Generator(const vd::DynamicsInit& init, const vd::InitEventList& events)
        : vd::Dynamics(init, events)
{ m_duration = vv::toDouble(events.get("duration")); }

Here we retrieve the parameter duration (the time step of the generation of events).

Don't forget to declare m_duration privately after the all public declarations :

private:
    double m_duration;

Destructor

virtual ~Generator()
{ }

The destructor is empty but obligatory.

Init :

virtual vd::Time init(const vd::Time& /* time */)
{ return m_duration; }

We return the date of the first generation of event.


Output :

virtual void output(const vd::Time& /* time */, vd::ExternalEventList& output) const
{ output.addEvent(buildEvent("out")); }

The model generates an empty event on port out. The name of the port could be a model parameter. VLE can also retrieve the name of the output port if we want to make the example more generic (with getModel (). GetOutputPortList ()).

TimeAdvance (Ta) :

virtual vd::Time timeAdvance() const
{ return m_duration; }

We return the duration between two generations which will allow to launch an event every m_duration time units.


Second version

If the modeller add a input port on the model and connect on it a other model of type Generator, the model must continue to generate its events at regular step.


Model's attributes

private:
    double m_duration, m_sigma;
    vd::Time m_lastTime;

Two new attributes

  • m_sigma : This attribute is used to calculate the remaining time between each received event to continue to generate events at regular step.
  • m_lastTime : This attribute is used to retrieve te date which occured the las event.


The constructor and destructor stay the same.


Init :

virtual vd::Time init(const vd::Time& time)
{
    m_lastTime = time;
    m_sigma = m_duration;
    return m_duration;
}

We initialize m_lastTime at the date of the begin, and m_sigma at the parameter m_duration.


The output function stay the same too.


TimeAdvance (Ta) :

virtual vd::Time timeAdvance() const
{ return m_sigma; }

We return here the time remaining before the next generation for the model continue to produce an event at regular step.


InternalTransition :

virtual void internalTransition(const vd::Time& time)
 {
    m_lastTime = time;
    m_sigma = m_duration;
}

The InternalTransition function attributes the value time to m_lastTime which will then give us the possibiliy to update m_sigma if is an externalTransition. It then resets m_sigma with the parameter duration defined by the user.


ExternalTansition :

virtual void externalTransition(const vd::ExternalEventList& /* event */,
                                    const vd::Time&  time )
{
     m_sigma -= time - m_lastTime;
     m_lastTime = time;
}

ExternalTransition function updates m_sigma value as the time remaining before the next event to generate. It then assigns the value time at m_lastTime as in the internalTransition function.


Third version

If an input event happens exactly at the same time that the generation of the external event, the model must continue to perform well.

It suffices to add the confluentTransition function :

virtual void confluentTransitions(const vd::Time& time,
                                    const vd::ExternalEventList& /* event */ )
{
    internalTransition(time);
}

When the model must do an internal transition and an external transition at the same time, we ignore external events and we only do the interank transition.


Observation

It's possible to observe values of each variable of generator model's state by a time step

For this, we must add the following function :

    virtual vv::Value* observation(const vd::ObservationEvent&  event) const
    {
        if (event.onPort("lastTime")) {
            return new vv::Double(m_lastTime);
	} else if (event.onPort("sigma")) {
            return new vv::Double(m_sigma);
	}
        return 0;
    }


From GVLE, we must then create a view of type redirect in a text file (for example) And the observables we want observe, here lastTime and sigma.

To see how to create a view in GVLE, please visit: http://www.vle-project.org/pub/vle/docs/v3.0.0/cours-gvle.pdf

During the simulation, a .dat file is created in the output folder.

On the first ligne of this file are writted the differents variables observed over time, beginning with the date, follows are observables put in GVLE (lastTime and sigma in our example).


Unitary tests

To verify that our model is exactly what we want, it's possible to make unit testing on it.

First, create a folder test in the package's src folder. Here :

cd $HOME/examples/src ;  mkdir test

We will then create a file a = blob; f = src / test / test-generator.cpp h = 3d74b23621ac1c2ae0fcd3ab6ee1ee2b1e285206; hb = HEAD test-generator.cpp to do these tests, and a file a = blob; f = src / test / CMakeLists.txt h = 93a14eaeab5cabc9e1dc19b1c0aa4d9d57244792; hb = HEAD CMakeLists.txt to compile.

Code Explanation

vle::utils::Package::package().select("examples");

We select our package with this function : "examples".


vpz::Vpz file(utils::Path::path().getPackageExpFile(
        "generator_perturb.vpz"));

Then we choose our model (the .vpz file) with this function.

	vpz::Output& o(file.project().experiment().views().outputs().get("view"));

We retrieve a reference on the view, which us enable to retrieve simulation's datas.


Tests

BOOST_REQUIRE_EQUAL(result.shape()[0], (value::MatrixView::size_type)3);
BOOST_REQUIRE_EQUAL(result.shape()[1], (value::MatrixView::size_type)290);

We observe two things : the date and two attributs (sigma and last_time), so we check tha result.shape()[0] is egal to 3.

The simulation lasts 29 units of time and we observe the dynamics of the model every 0.1 units of time, so there are 290 lines generated.

BOOST_REQUIRE_CLOSE(value::toDouble(result[0][0]), 2455308, 1e-2); // observation's date
BOOST_REQUIRE_CLOSE(value::toDouble(result[1][0]), 2455308, 1e-2); // lastTime
BOOST_REQUIRE_CLOSE(value::toDouble(result[2][0]), 5, 1e-2); // sigma

Then we check that the different observations (date, sigma and last_time) are correct.

The simulation starts in the example at 2455308.00000 (julian date representing April 24, 2010), we verify that the result on line 0 is the expected date. value:: toDouble (result [0] [0]) is the date value obtained 2455308 that we want to obtain and 1e-2 means that we want a margin of error <0.01% (because we work infloat).

The lastTime is init with the curent date so is normal it have the same value.

To finish, we check Sigma is init to 5 (duration between two event's generation).


This page was last modified on 20 July 2010, at 07:43. This page has been accessed 2,448 times.