Skip to content

Commit

Permalink
devs: allows negative time in time advance
Browse files Browse the repository at this point in the history
If a vle::devs::Dynamics::timeAdvance returns a negative value, VLE
kernel will interpret this value as an absolute date instead of a
duration. Seems to be useful to (re)synchronize model with integer dates
and permits to reduce real representation problems. (closes: vle-forge#241).
  • Loading branch information
Gauthier Quesnel authored and quesnel committed Nov 10, 2017
1 parent 49490e8 commit 8edd1e0
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 28 deletions.
30 changes: 27 additions & 3 deletions src/vle/devs/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,16 @@ class VLE_API Dynamics

/**
* @brief Process the initialization of the model by initializing the
* initial state and return the duration (or timeAdvance) of the initial
* state.
* initial state and return the duration of the initial state.
*
* If @e init returns 0 or a positive real, this value means the
* duration of the current state. But, if @e init returns a negative
* real, this value means an absolute value.
*
* @param time the time of the creation of this model.
* @return duration of the initial state.
*
* @return duration of the initial state ([0, +oo{) or an absolute
* date (]-oo, 0[).
*/
virtual Time init(Time /* time */)
{
Expand Down Expand Up @@ -147,6 +153,24 @@ class VLE_API Dynamics
/**
* @brief Process the time advance function: compute the duration of the
* current state.
*
* If @e timeAdvance returns 0 or a positive real, this value means
* the duration of the current state. But, if @e timeAdvance returns a
* negative real, this value means an absolute value.
*
* @code
* class Model : public vle::devs::Dynamics
* {
* void timeAdvance() const
* {
* return 0.1; // Wake up me in current time + 0.1.
*
* return -123.456; // Wake up me at date 123.456.
* }
* }
*
* @endcode
*
* @return duration of the current state.
*/
virtual Time timeAdvance() const
Expand Down
67 changes: 47 additions & 20 deletions src/vle/devs/Simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,30 +135,21 @@ Simulator::output(Time time)
m_dynamics->output(time, m_result);
}

Time
Simulator::timeAdvance()
{
Time tn = m_dynamics->timeAdvance();

if (tn < 0.0)
throw utils::ModellingError(
(fmt(_("Negative time advance in '%1%' (%2%)")) % getName() % tn)
.str());

return tn;
}

Time
Simulator::init(Time time)
{
Time tn = m_dynamics->init(time);

if (tn < 0.0)
if (tn >= 0)
return m_tn = tn + time;

if (-tn < time)
throw utils::ModellingError(
(fmt(_("Negative init function in '%1%' (%2%)")) % getName() % tn)
.str());
_("Bad absolute date: %f must be greater than the current date %f"),
tn, time);

m_tn = -tn;

m_tn = tn + time;
return m_tn;
}

Expand All @@ -167,36 +158,72 @@ Simulator::confluentTransitions(Time time)
{
assert(not m_external_events.empty() and "Simulator d-conf error");
assert(m_have_internal == true and "Simulator d-conf error");

m_dynamics->confluentTransitions(time, m_external_events);

m_external_events.clear();
m_have_internal = false;

m_tn = timeAdvance() + time;
Time tn = m_dynamics->timeAdvance();

if (tn >= 0)
return m_tn = tn + time;

if (-tn < time)
throw utils::ModellingError(
_("Bad absolute date: %f must be greater than the current date %f"),
tn, time);

m_tn = -tn;

return m_tn;
}

Time
Simulator::internalTransition(Time time)
{
assert(m_have_internal == true and "Simulator d-int error");

m_dynamics->internalTransition(time);

m_have_internal = false;

m_tn = timeAdvance() + time;
Time tn = m_dynamics->timeAdvance();

if (tn >= 0)
return m_tn = tn + time;

if (-tn < time)
throw utils::ModellingError(
_("Bad absolute date: %f must be greater than the current date %f"),
tn, time);

m_tn = -tn;

return m_tn;
}

Time
Simulator::externalTransition(Time time)
{
assert(not m_external_events.empty() and "Simulator d-ext error");

m_dynamics->externalTransition(m_external_events, time);

m_external_events.clear();

m_tn = timeAdvance() + time;
Time tn = m_dynamics->timeAdvance();

if (tn >= 0)
return m_tn = tn + time;

if (-tn < time)
throw utils::ModellingError(
_("Bad absolute date: %f must be greater than the current date %f"),
tn, time);

m_tn = -tn;

return m_tn;
}

Expand Down
1 change: 0 additions & 1 deletion src/vle/devs/Simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class VLE_LOCAL Simulator
/*-*-*-*-*-*-*-*-*-*/

Time init(Time time);
Time timeAdvance();
void finish();
void output(Time time);
Time internalTransition(Time time);
Expand Down
93 changes: 89 additions & 4 deletions src/vle/devs/test/mdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,13 +726,50 @@ class Root : public devs::Executive
}
};

//
// This model is used to try the relative/absolute date in DEVS kernel.
//
class TimeModel : public devs::Dynamics
{
public:
TimeModel(const devs::DynamicsInit& atom,
const devs::InitEventList& events)
: devs::Dynamics(atom, events)
{}

virtual devs::Time init(devs::Time /* time */) override
{
absolute = 2;

return -123;
}

virtual devs::Time timeAdvance() const override
{
if (absolute)
return -321;

return 1;
}

virtual void internalTransition(devs::Time /* time */) override
{
if (absolute > 0)
--absolute;
}

int absolute;
};


DECLARE_DYNAMICS_SYMBOL(dynamics_MyBeep, MyBeep)
DECLARE_DYNAMICS_SYMBOL(dynamics_counter, Counter)
DECLARE_DYNAMICS_SYMBOL(dynamics_transform, Transform)
DECLARE_DYNAMICS_SYMBOL(dynamics_confluent_transitionA, Confluent_transitionA)
DECLARE_DYNAMICS_SYMBOL(dynamics_confluent_transitionB, Confluent_transitionB)
DECLARE_DYNAMICS_SYMBOL(dynamics_confluent_transitionC, Confluent_transitionC)
DECLARE_DYNAMICS_SYMBOL(dynamics_confluent_transitionD, Confluent_transitionD)
DECLARE_DYNAMICS_SYMBOL(dynamics_time_model, TimeModel)
DECLARE_EXECUTIVE_SYMBOL(exe_branch, Branch)
DECLARE_EXECUTIVE_SYMBOL(exe_deleteconnection, DeleteConnection)
DECLARE_EXECUTIVE_SYMBOL(exe_genexecutive, GenExecutive)
Expand Down Expand Up @@ -786,6 +823,7 @@ test_gensvpz()

while (root.run())
;

std::unique_ptr<value::Map> out = root.outputs();
root.finish();

Expand Down Expand Up @@ -940,17 +978,64 @@ test_confluent_transition_2()
}
}

int
main()
void test_time_model()
{
auto ctx = vle::utils::make_context();
vpz::Vpz vpz;

vpz.project().experiment().setDuration(2000.0);
vpz.project().experiment().setBegin(-1000.0);

{
auto x = vpz.project().dynamics().dynamiclist().emplace(
"dyn_1", vpz::Dynamic("dyn_1"));
Ensures(x.second == true);
x.first->second.setLibrary("dynamics_time_model");
}

{
auto* depth0 = new vpz::CoupledModel("depth0", nullptr);
auto *atom = depth0->addAtomicModel("atom");
atom->setDynamics("dyn_1");
atom->addOutputPort("out");

vpz.project().model().setGraph(std::unique_ptr<vpz::BaseModel>(depth0));
}

devs::RootCoordinator root(ctx);
root.load(vpz);
vpz.clear();
root.init();

root.run();
Ensures(root.getCurrentTime() == -1000);
root.run();
Ensures(root.getCurrentTime() == 123);
root.run();
Ensures(root.getCurrentTime() == 321);

devs::Time t = 321;
while (t < 1000) {
Ensures(root.getCurrentTime() == t);
++t;
root.run();
}

root.finish();
}

int main()
{
vle::Init app;

test_normal_behaviour();
test_confluent_transition();
test_confluent_transition_2();
test_gensvpz();
test_gens_delete_connection();
test_gens_ordereddeleter();
test_confluent_transition();
test_confluent_transition_2();
test_time_model();

return unit_test::report_errors();
}

0 comments on commit 8edd1e0

Please sign in to comment.