/**
* @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-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_QSS_MODELS_HPP
#define TESTS_QSS_MODELS_HPP
#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::Bag &bag) override {
std::for_each(bag.begin(), bag.end(),
[this](const common::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::Bag
lambda(const typename common::DoubleTime::type & /* t */) const override {
common::Bag bag;
if (_phase == PEST) {
artis::qss::IntegratorData data = {_prey_amount * _prey_proportion};
bag.push_back(common::ExternalEvent(OUT_X, data));
data = {_predator_amount * _predator_proportion};
bag.push_back(common::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::Bag &bag,
const artis::common::DoubleTime::type & /* t */) override {
std::for_each(bag.begin(), bag.end(),
[this](const artis::common::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::Bag
lambda(const artis::common::DoubleTime::type & /* t */) const override {
artis::common::Bag msgs;
artis::qss::IntegratorData data = {_y};
msgs.push_back(
artis::common::ExternalEvent(OUT, data));
return msgs;
}
artis::common::Value observe(const artis::common::DoubleTime::type & /* t */,
unsigned int index) const override {
if (index == VALUE) {
return (double) _y;
}
return artis::common::Value();
}
private:
// parameters
double _init_value;
double _b;
double _d;
double _e;
// state
double _x;
double _y;
};
}
}
} // namespace artis tests qss
#endif