/** * @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