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