/**
* @file tests/pdevs/models.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
/*
* ARTIS - the multimodeling and simulation environment
* This file is a part of the ARTIS environment
*
* Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef TESTS_PDEVS_MODELS_HPP
#define TESTS_PDEVS_MODELS_HPP
#include
#include
#include
#include
#include
#define DELAY 100
namespace artis {
namespace tests {
namespace pdevs {
struct data {
double x;
double y;
data()
: x(0), y(0) {}
data(double _x, double _y)
: x(_x), y(_y) {}
};
class Inactive : public artis::pdevs::Dynamics {
public:
Inactive(const std::string &name,
const artis::pdevs::Context &context)
:
artis::pdevs::Dynamics(name, context) {}
~Inactive() override = default;
};
class A : public artis::pdevs::Dynamics {
public:
enum inputs {
IN
};
enum outputs {
OUT
};
A(const std::string &name,
const artis::pdevs::Context &context)
:
artis::pdevs::Dynamics(name, context) {
input_ports({{IN, "in"}});
output_ports({{OUT, "out"}});
}
~A() override = default;
void dint(const typename common::DoubleTime::type &t) override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_INT,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
if (_phase == WAIT) {
++_value.x;
--_value.y;
_phase = SEND;
} else if (_phase == SEND) {
_phase = WAIT;
}
}
void
dext(const typename common::DoubleTime::type &t,
const typename common::DoubleTime::type & /* e */,
const common::Bag &msgs) override {
#ifndef WITH_TRACE
(void)t;
(void)msgs;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_EXT,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
_phase = SEND;
}
void dconf(const typename common::DoubleTime::type &t,
const typename common::DoubleTime::type & /* e */,
const common::Bag &msgs) override {
#ifndef WITH_TRACE
(void)t;
(void)msgs;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_CONF,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
}
void start(const typename common::DoubleTime::type &t) override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::START,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
_phase = SEND;
}
typename common::DoubleTime::type
ta(const typename common::DoubleTime::type &t) const override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::TA,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
if (_phase == WAIT) {
return 1;
} else {
return 0;
}
}
common::Bag
lambda(const typename common::DoubleTime::type &t) const override {
#ifndef WITH_TRACE
(void)t;
#endif
common::Bag msgs;
if (_phase == SEND) {
msgs.push_back(
artis::common::ExternalEvent(OUT, _value));
}
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::LAMBDA,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
return msgs;
}
private:
enum Phase {
WAIT, SEND
};
Phase _phase;
data _value;
};
class B : public artis::pdevs::Dynamics {
public:
enum inputs {
IN
};
enum outputs {
OUT
};
B(const std::string &name,
const artis::pdevs::Context &context)
:
artis::pdevs::Dynamics(name, context),
_value(0) {
input_ports({{IN, "in"}});
output_ports({{OUT, "out"}});
}
~B() override = default;
void dint(const typename common::DoubleTime::type &t) override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_INT,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
if (_phase == SEND) {
_phase = WAIT;
}
}
void
dext(const typename common::DoubleTime::type &t,
const typename common::DoubleTime::type & /* e */,
const common::Bag &msgs) override {
#ifndef WITH_TRACE
(void)t;
(void)msgs;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_EXT,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
_phase = SEND;
}
void dconf(const typename common::DoubleTime::type &t,
const typename common::DoubleTime::type &e,
const common::Bag &msgs) override {
#ifndef WITH_TRACE
(void)t;
(void)msgs;
#endif
dext(t, e, msgs);
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::DELTA_CONF,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
}
void start(const typename common::DoubleTime::type &t) override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::START,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
_phase = WAIT;
}
typename common::DoubleTime::type ta(
const typename common::DoubleTime::type &t) const override {
#ifndef WITH_TRACE
(void)t;
#endif
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::TA,
common::LevelType::USER);
common::Trace::trace().flush();
#endif
if (_phase == WAIT) {
return common::DoubleTime::infinity;
} else {
return 0;
}
}
common::Bag lambda(
const typename common::DoubleTime::type &t) const override {
#ifndef WITH_TRACE
(void)t;
#endif
common::Bag msgs;
if (_phase == SEND) {
msgs.push_back(
artis::common::ExternalEvent(OUT, _value));
}
#ifdef WITH_TRACE
common::Trace::trace()
<< common::TraceElement(get_name(), t,
common::FormalismType::PDEVS,
common::FunctionType::LAMBDA,
common::LevelType::USER)
<< "messages = " << msgs.to_string();
common::Trace::trace().flush();
#endif
return msgs;
}
private:
enum Phase {
WAIT, SEND
};
Phase _phase;
double _value;
};
class TwoStateModel : public artis::pdevs::Dynamics {
public:
TwoStateModel(const std::string &name,
const artis::pdevs::Context &context)
:
artis::pdevs::Dynamics(name, context) {}
~TwoStateModel() override = default;
void dint(const typename common::DoubleTime::type &t) override {
if (_phase == S1) {
_phase = S2;
} else if (_phase == S2) {
_phase = S1;
}
_last_time = t;
}
void start(const typename common::DoubleTime::type &t) override {
_phase = S1;
_last_time = t;
}
typename common::DoubleTime::type
ta(const typename common::DoubleTime::type & /* t */) const override {
if (_phase == S1) {
return 5;
} else {
return 6;
}
}
common::Bag
lambda(const typename common::DoubleTime::type &t) const override {
std::cout << (t - _last_time) << std::endl;
return common::Bag();
}
private:
enum Phase {
S1, S2
};
Phase _phase;
typename common::DoubleTime::type _last_time;
};
class ThreeStateModel
: public artis::pdevs::Dynamics {
public:
enum outputs {
OUT
};
enum states {
HEIGHTS, SPEEDS, SCALES, N, INDEX, SIGMA, LAST_TIME
};
ThreeStateModel(const std::string &name,
const artis::pdevs::Context &context)
:
artis::pdevs::Dynamics(name, context) {
DECLARE_STATES(std::vector,
((HEIGHTS, &ThreeStateModel::heights), (SPEEDS, &ThreeStateModel::speeds), (SCALES, &ThreeStateModel::scales)));
DECLARE_STATES(unsigned int,
((N, &ThreeStateModel::n), (INDEX, &ThreeStateModel::index)));
DECLARE_STATES(typename common::DoubleTime::type,
((SIGMA, &ThreeStateModel::sigma), (LAST_TIME, &ThreeStateModel::_last_time)));
output_ports({{OUT, "out"}});
}
~ThreeStateModel() override = default;
void dconf(const typename common::DoubleTime::type &t,
const typename common::DoubleTime::type &e,
const common::Bag &msgs) override {
dext(t, e, msgs);
}
void dext(const typename common::DoubleTime::type & /* t */,
const typename common::DoubleTime::type & /* e */,
const common::Bag &msgs) override {
for (common::Bag::const_iterator it = msgs.begin();
it != msgs.end();
++it) {
++n;
}
if (sigma == 1) {
if (n > 3) {
++index;
if (index == scales.size()) {
index = 0;
}
sigma = common::DoubleTime::infinity;
if (scales[index] == 1) {
scales[index] = 2;
} else {
scales[index] = 1;
}
n = 0;
}
} else {
sigma = 1;
n = 0;
}
}
void dint(const typename common::DoubleTime::type &t) override {
mark_full(t);
if (full_N()) {
raz();
}
compute();
}
void start(const typename common::DoubleTime::type &t) override {
heights = {0, 0, 0, 0, 0};
speeds = {0.21, 0.3, 0.7, 0.56, 0.14};
scales = {1, 1, 1, 1, 1};
index = 0;
n = 0;
sigma = 0;
_last_time = t;
}
typename common::DoubleTime::type
ta(const typename common::DoubleTime::type & /* t */) const override { return sigma; }
common::Bag
lambda(const typename common::DoubleTime::type & /* t */) const override {
common::Bag msgs;
if (full()) {
msgs.push_back(artis::common::ExternalEvent(OUT, 0));
}
return msgs;
}
private:
void compute() {
for (unsigned int i = 0; i < heights.size(); ++i) {
if (heights[i] != -1 and heights[i] < 10) {
heights[i] += speeds[i] * scales[i];
}
}
}
void display() const {
for (std::vector::const_iterator it = heights.begin();
it != heights.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
void display_full() const {
unsigned int i = 1;
for (std::vector::const_iterator it = heights.begin();
it != heights.end(); ++it, ++i) {
if (*it > 10) {
std::cout << "S" << i;
}
}
std::cout << std::endl;
}
bool full() const {
unsigned int n = 0;
for (std::vector::const_iterator it = heights.begin();
it != heights.end(); ++it) {
if (*it > 10) {
++n;
}
}
return n > 0;
}
bool full_N() const {
unsigned int n = 0;
for (std::vector::const_iterator it = heights.begin();
it != heights.end(); ++it) {
if (*it == -1) {
++n;
}
}
return n >= 2;
}
void mark_full(const typename common::DoubleTime::type &t) {
for (std::vector::iterator it = heights.begin();
it != heights.end(); ++it) {
if (*it > 10) {
*it = -1;
_last_time = t;
}
}
}
void raz() {
for (std::vector::iterator it = heights.begin();
it != heights.end(); ++it) {
if (*it == -1) {
*it = 0;
}
}
}
// state
std::vector heights;
std::vector speeds;
std::vector scales;
unsigned int index;
unsigned int n;
typename common::DoubleTime::type sigma;
typename common::DoubleTime::type _last_time;
};
}
}
} // namespace artis tests pdevs
#endif