/** * @file tests/qss/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-2022 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_QSS_MODELS_HPP #define TESTS_QSS_MODELS_HPP #include #include #include #include #include namespace artis { namespace tests { namespace qss { class Constant : public artis::qss::Derivative { public: Constant(const std::string &name, const artis::pdevs::Context &context) : artis::qss::Derivative(name, context) {} ~Constant() override = default; double compute() const override { return 0.5; } }; struct ParabolaParameters { double alpha; }; class Parabola : public artis::qss::Derivative { public: Parabola(const std::string &name, const artis::pdevs::Context &context) : artis::qss::Derivative( name, context), _alpha(context.parameters().alpha) { internal("X", &Parabola::_x); } ~Parabola() override = default; double compute() const override { return _alpha * _x; } private: double _alpha; double _x; }; struct PreyPredatorParameters { double a; double b; double d; double e; }; class Predator : public artis::qss::Derivative { public: unsigned int IN_X; Predator(const std::string &name, const artis::pdevs::Context &context) : artis::qss::Derivative( name, context), _b(context.parameters().b), _d(context.parameters().d), _e(context.parameters().e) { internal("Y", &Predator::_y); IN_X = external("X", &Predator::_x); } ~Predator() override = default; double compute() const override { return _b * _d * _x * _y - _e * _y; } private: // parameters double _b; double _d; double _e; // state double _x; double _y; }; class Prey : public artis::qss::Derivative { public: unsigned int IN_Y; Prey(const std::string &name, const artis::pdevs::Context &context) : artis::qss::Derivative( name, context), _a(context.parameters().a), _b(context.parameters().b) { internal("X", &Prey::_x); IN_Y = external("Y", &Prey::_y); } ~Prey() override = default; double compute() const override { return _a * _x - _b * _y * _x; } private: // parameters double _a; double _b; // state double _x; double _y; }; struct SmartGardenerParameters { double threshold; double prey_proportion; double predator_proportion; double delay; }; class SmartGardener : public artis::pdevs::Dynamics { public: enum inputs { IN_X, IN_Y }; enum outputs { OUT_X, OUT_Y }; SmartGardener(const std::string &name, const artis::pdevs::Context &context) : artis::pdevs::Dynamics( name, context), _threshold(context.parameters().threshold), _prey_proportion(context.parameters().prey_proportion), _predator_proportion(context.parameters().predator_proportion), _delay(context.parameters().delay) { input_ports({{IN_X, "in_x"}, {IN_Y, "in_y"}}); output_ports({{OUT_X, "out_x"}, {OUT_Y, "out_y"}}); } ~SmartGardener() override = default; void dint(const typename common::DoubleTime::type & /* t */) override { switch (_phase) { case INIT:_phase = IDLE; _sigma = _delay; break; case IDLE: if (_prey_amount > _threshold) { _phase = PEST; } else { _phase = IDLE; _sigma = _delay; } break; case PEST:_phase = IDLE; _sigma = _delay; break; } } void dext(const typename common::DoubleTime::type & /* t */, const typename common::DoubleTime::type &e, const common::event::Bag &bag) override { std::for_each(bag.begin(), bag.end(), [this](const common::event::ExternalEvent &event) { artis::qss::IntegratorData data; event.data()(data); if (event.on_port(IN_X)) { _prey_amount = data.value; } else if (event.on_port(IN_Y)) { _predator_amount = data.value; } }); _sigma -= e; } void start(const typename common::DoubleTime::type & /* t */) override { _phase = INIT; } typename common::DoubleTime::type ta(const typename common::DoubleTime::type & /* t */) const override { switch (_phase) { case INIT:return 0.0; case IDLE:return _sigma; case PEST:return 0.0; } return common::DoubleTime::infinity; } common::event::Bag lambda(const typename common::DoubleTime::type & /* t */) const override { common::event::Bag bag; if (_phase == PEST) { artis::qss::IntegratorData data = {_prey_amount * _prey_proportion}; bag.push_back(common::event::ExternalEvent(OUT_X, data)); data = {_predator_amount * _predator_proportion}; bag.push_back(common::event::ExternalEvent(OUT_Y, data)); } return bag; } private: enum Phase { INIT, IDLE, PEST }; // parameters double _threshold; double _prey_proportion; double _predator_proportion; double _delay; // state Phase _phase; common::DoubleTime::type _sigma; double _prey_amount; double _predator_amount; }; struct DiscretePreyPredatorParameters { artis::common::DoubleTime::type time_step; double init_value; double a; double b; double d; double e; }; class DiscretePredator : public artis::dtss::Dynamics { public: enum inputs { RESET, IN_X, IN_Y }; enum outputs { OUT }; enum vars { VALUE }; DiscretePredator(const std::string &name, const artis::dtss::Context &context) : artis::dtss::Dynamics( name, context), _init_value(context.parameters().init_value), _b(context.parameters().b), _d(context.parameters().d), _e(context.parameters().e) { input_ports({{RESET, "reset"}, {IN_X, "in_x"}, {IN_Y, "in_y"}}); output_ports({{OUT, "out"}}); observables({{VALUE, "value"}}); } ~DiscretePredator() override = default; void transition(const artis::common::event::Bag &bag, const artis::common::DoubleTime::type & /* t */) override { std::for_each(bag.begin(), bag.end(), [this](const artis::common::event::ExternalEvent &event) { if (event.on_port(IN_X)) { artis::qss::IntegratorData data; event.data()(data); _x = data.value; } else if (event.on_port(RESET)) { // TODO } }); _y += (_b * _d * _x * _y - _e * _y) * time_step(); } void start(const artis::common::DoubleTime::type & /* t */) override { _y = _init_value; } artis::common::event::Bag lambda(const artis::common::DoubleTime::type & /* t */) const override { artis::common::event::Bag msgs; artis::qss::IntegratorData data = {_y}; msgs.push_back( artis::common::event::ExternalEvent(OUT, data)); return msgs; } artis::common::event::Value observe(const artis::common::DoubleTime::type & /* t */, unsigned int index) const override { if (index == VALUE) { return (double) _y; } return artis::common::event::Value(); } private: // parameters double _init_value; double _b; double _d; double _e; // state double _x; double _y; }; class PreyPredator : public artis::qss::MultiDerivative { public: PreyPredator(const std::string &name, const artis::pdevs::Context &context) : artis::qss::MultiDerivative( name, context), _a(context.parameters().a), _b(context.parameters().b), _d(context.parameters().d), _e(context.parameters().e) { internal("X", &PreyPredator::_x); internal("Y", &PreyPredator::_y); } ~PreyPredator() override = default; std::vector compute() override { return {_a * _x - _b * _y * _x, _b * _d * _x * _y - _e * _y}; } private: // parameters double _a; double _b; double _d; double _e; // state double _x; double _y; }; } } } // namespace artis tests qss #endif