|
@@ -35,7 +35,8 @@
|
|
|
namespace artis {
|
|
|
namespace qss {
|
|
|
|
|
|
-struct QuantifierParameters {
|
|
|
+struct QuantifierParameters
|
|
|
+{
|
|
|
bool allow_offsets;
|
|
|
bool zero_init_offset;
|
|
|
double quantum;
|
|
@@ -44,42 +45,49 @@ struct QuantifierParameters {
|
|
|
|
|
|
template<class Time>
|
|
|
class Quantifier
|
|
|
- : public artis::pdevs::Dynamics<Time, Quantifier<Time>, QuantifierParameters> {
|
|
|
+ : public artis::pdevs::Dynamics<Time, Quantifier<Time>, QuantifierParameters>
|
|
|
+{
|
|
|
public:
|
|
|
- enum inputs {
|
|
|
- IN, RESET
|
|
|
+ struct input
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ IN, RESET
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
- enum outputs {
|
|
|
- OUT
|
|
|
- };
|
|
|
-
|
|
|
- enum states {
|
|
|
- STATE, ADAPTIVE_STATE, STEP_NUMBER, OFFSET, UP_THRESHOLD, DOWN_THRESHOLD
|
|
|
+ struct output
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ OUT
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
Quantifier(const std::string &name,
|
|
|
const artis::pdevs::Context<Time, Quantifier<Time>, QuantifierParameters> &context)
|
|
|
:
|
|
|
- artis::pdevs::Dynamics<Time, Quantifier<Time>, QuantifierParameters>(name,
|
|
|
- context) {
|
|
|
+ artis::pdevs::Dynamics<Time, Quantifier<Time>, QuantifierParameters>(name, context)
|
|
|
+ {
|
|
|
DECLARE_STATES(int,
|
|
|
- ((STATE, &Quantifier<Time>::_state), (ADAPTIVE_STATE, &Quantifier<Time>::_adaptive_state)));
|
|
|
+ ((state::PHASE, &Quantifier<Time>::_phase),
|
|
|
+ (state::ADAPTIVE_STATE, &Quantifier<Time>::_adaptive_state)));
|
|
|
DECLARE_STATES(unsigned int,
|
|
|
- ((STEP_NUMBER, &Quantifier<Time>::_step_number)));
|
|
|
+ ((state::STEP_NUMBER, &Quantifier<Time>::_step_number)));
|
|
|
DECLARE_STATES(double,
|
|
|
- ((OFFSET, &Quantifier<Time>::_offset), (UP_THRESHOLD, &Quantifier<Time>::_up_threshold), (DOWN_THRESHOLD, &Quantifier<
|
|
|
- Time>::_down_threshold)));
|
|
|
+ ((state::OFFSET, &Quantifier<Time>::_offset),
|
|
|
+ (state::UP_THRESHOLD, &Quantifier<Time>::_up_threshold),
|
|
|
+ (state::DOWN_THRESHOLD, &Quantifier<Time>::_down_threshold)));
|
|
|
|
|
|
- this->input_ports({{IN, "in"},
|
|
|
- {RESET, "reset"}});
|
|
|
- this->output_port({OUT, "out"});
|
|
|
- this->observables({{UP, "up"},
|
|
|
- {DOWN, "down"},
|
|
|
- {VALUE, "value"}});
|
|
|
+ this->input_ports({{input::IN, "in"},
|
|
|
+ {input::RESET, "reset"}});
|
|
|
+ this->output_port({output::OUT, "out"});
|
|
|
+ this->observables({{var::UP, "up"},
|
|
|
+ {var::DOWN, "down"},
|
|
|
+ {var::VALUE, "value"}});
|
|
|
|
|
|
_adaptive = context.parameters().allow_offsets;
|
|
|
- _adaptive_state = _adaptive ? POSSIBLE : IMPOSSIBLE;
|
|
|
+ _adaptive_state = _adaptive ? adaptive_state::POSSIBLE : adaptive_state::IMPOSSIBLE;
|
|
|
_zero_init_offset = context.parameters().zero_init_offset;
|
|
|
_step_size = context.parameters().quantum;
|
|
|
|
|
@@ -90,30 +98,34 @@ public:
|
|
|
assert(_past_length > 2);
|
|
|
}
|
|
|
|
|
|
- virtual ~Quantifier() {}
|
|
|
+ virtual ~Quantifier()
|
|
|
+ {}
|
|
|
|
|
|
virtual void dconf(const typename Time::type &t, const typename Time::type &e,
|
|
|
- const common::Bag<Time> &bag) {
|
|
|
+ const common::Bag<Time> &bag)
|
|
|
+ {
|
|
|
dint(t);
|
|
|
dext(t, e, bag);
|
|
|
}
|
|
|
|
|
|
- virtual void dint(const typename Time::type & /* t */) {
|
|
|
- switch (_state) {
|
|
|
- case INIT:break;
|
|
|
- case IDLE:break;
|
|
|
- case RESPONSE:_state = IDLE;
|
|
|
+ virtual void dint(const typename Time::type & /* t */)
|
|
|
+ {
|
|
|
+ switch (_phase) {
|
|
|
+ case phase::INIT:break;
|
|
|
+ case phase::IDLE:break;
|
|
|
+ case phase::RESPONSE:_phase = phase::IDLE;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
virtual void dext(const typename Time::type &t, const typename Time::type &e,
|
|
|
- const common::Bag<Time> &bag) {
|
|
|
+ const common::Bag<Time> &bag)
|
|
|
+ {
|
|
|
bool reset = false;
|
|
|
|
|
|
std::for_each(bag.begin(), bag.end(),
|
|
|
[this, t, e, &reset](const common::ExternalEvent<Time> &event) {
|
|
|
- if (event.on_port(IN)) {
|
|
|
+ if (event.on_port(input::IN)) {
|
|
|
IntegratorData data;
|
|
|
double shifting_factor;
|
|
|
double value;
|
|
@@ -121,10 +133,10 @@ public:
|
|
|
|
|
|
event.data()(data);
|
|
|
value = data.value;
|
|
|
- if (_state == INIT) {
|
|
|
+ if (_phase == phase::INIT) {
|
|
|
init_step_number_and_offset(value);
|
|
|
update_thresholds();
|
|
|
- _state = RESPONSE;
|
|
|
+ _phase = phase::RESPONSE;
|
|
|
} else {
|
|
|
cnt = 0;
|
|
|
while (value >= _up_threshold or value <= _down_threshold) {
|
|
@@ -135,9 +147,9 @@ public:
|
|
|
_step_number--;
|
|
|
}
|
|
|
switch (_adaptive_state) {
|
|
|
- case IMPOSSIBLE:update_thresholds();
|
|
|
+ case adaptive_state::IMPOSSIBLE:update_thresholds();
|
|
|
break;
|
|
|
- case POSSIBLE:
|
|
|
+ case adaptive_state::POSSIBLE:
|
|
|
if (value >= _up_threshold) {
|
|
|
store_change(_step_size, t);
|
|
|
} else {
|
|
@@ -151,74 +163,75 @@ public:
|
|
|
if (shifting_factor != 0 and shifting_factor != 1) {
|
|
|
if (value >= _up_threshold) {
|
|
|
update_thresholds(shifting_factor,
|
|
|
- DIRECTION_DOWN);
|
|
|
+ direction::DIRECTION_DOWN);
|
|
|
} else {
|
|
|
update_thresholds(shifting_factor,
|
|
|
- DIRECTION_UP);
|
|
|
+ direction::DIRECTION_UP);
|
|
|
}
|
|
|
- _adaptive_state = DONE;
|
|
|
+ _adaptive_state = adaptive_state::DONE;
|
|
|
} else {
|
|
|
update_thresholds();
|
|
|
}
|
|
|
break;
|
|
|
- case DONE:init_step_number_and_offset(value);
|
|
|
- _adaptive_state = POSSIBLE;
|
|
|
+ case adaptive_state::DONE:init_step_number_and_offset(value);
|
|
|
+ _adaptive_state = adaptive_state::POSSIBLE;
|
|
|
update_thresholds();
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- } else if (event.on_port(RESET)) {
|
|
|
+ } else if (event.on_port(input::RESET)) {
|
|
|
_offset = 0;
|
|
|
reset = true;
|
|
|
_archive.clear();
|
|
|
}
|
|
|
});
|
|
|
if (reset) {
|
|
|
- _state = INIT;
|
|
|
+ _phase = phase::INIT;
|
|
|
} else {
|
|
|
- _state = RESPONSE;
|
|
|
+ _phase = phase::RESPONSE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- virtual void start(const typename Time::type & /* time */) {
|
|
|
+ virtual void start(const typename Time::type & /* time */)
|
|
|
+ {
|
|
|
_offset = 0;
|
|
|
- _state = INIT;
|
|
|
+ _phase = phase::INIT;
|
|
|
}
|
|
|
|
|
|
- virtual typename Time::type ta(const typename Time::type & /* time */) {
|
|
|
- switch (_state) {
|
|
|
- case INIT:
|
|
|
- case IDLE:return Time::infinity;
|
|
|
- case RESPONSE:return 0.0;
|
|
|
+ virtual typename Time::type ta(const typename Time::type & /* time */)
|
|
|
+ {
|
|
|
+ switch (_phase) {
|
|
|
+ case phase::INIT:
|
|
|
+ case phase::IDLE:return Time::infinity;
|
|
|
+ case phase::RESPONSE:return 0.0;
|
|
|
}
|
|
|
return Time::infinity;
|
|
|
}
|
|
|
|
|
|
- virtual common::Bag<Time> lambda(const typename Time::type & /* time */) const {
|
|
|
+ virtual common::Bag<Time> lambda(const typename Time::type & /* time */) const
|
|
|
+ {
|
|
|
common::Bag<Time> msgs;
|
|
|
const QuantifierData data = {_up_threshold, _down_threshold};
|
|
|
|
|
|
- msgs.push_back(common::ExternalEvent<Time>(OUT, data));
|
|
|
+ msgs.push_back(common::ExternalEvent<Time>(output::OUT, data));
|
|
|
return msgs;
|
|
|
}
|
|
|
|
|
|
virtual common::Value observe(const typename Time::type & /* t */,
|
|
|
- unsigned int index) const {
|
|
|
+ unsigned int index) const
|
|
|
+ {
|
|
|
switch (index) {
|
|
|
- case UP:return (double) _up_threshold;
|
|
|
- case DOWN:return (double) _down_threshold;
|
|
|
- case VALUE:return (double) (_up_threshold - _down_threshold);
|
|
|
+ case var::UP:return (double) _up_threshold;
|
|
|
+ case var::DOWN:return (double) _down_threshold;
|
|
|
+ case var::VALUE:return (double) (_up_threshold - _down_threshold);
|
|
|
default:return common::Value();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- typedef enum {
|
|
|
- DIRECTION_UP, DIRECTION_DOWN
|
|
|
- } Direction;
|
|
|
-
|
|
|
- void init_step_number_and_offset(double value) {
|
|
|
+ void init_step_number_and_offset(double value)
|
|
|
+ {
|
|
|
_step_number = static_cast<long int>(std::floor(value / _step_size));
|
|
|
if (_zero_init_offset) {
|
|
|
_offset = 0;
|
|
@@ -227,7 +240,8 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- bool monotonous(unsigned int range) {
|
|
|
+ bool monotonous(unsigned int range)
|
|
|
+ {
|
|
|
if ((range + 1) > _archive.size()) {
|
|
|
return false;
|
|
|
}
|
|
@@ -239,7 +253,8 @@ private:
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- bool oscillating(unsigned int range) {
|
|
|
+ bool oscillating(unsigned int range)
|
|
|
+ {
|
|
|
if ((range + 1) > _archive.size()) {
|
|
|
return false;
|
|
|
}
|
|
@@ -251,7 +266,8 @@ private:
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- double shift_quanta() {
|
|
|
+ double shift_quanta()
|
|
|
+ {
|
|
|
double factor = 0;
|
|
|
|
|
|
if (oscillating(_past_length - 1) and
|
|
@@ -283,7 +299,8 @@ private:
|
|
|
return factor;
|
|
|
}
|
|
|
|
|
|
- void store_change(double val, const typename Time::type &time) {
|
|
|
+ void store_change(double val, const typename Time::type &time)
|
|
|
+ {
|
|
|
record_t record;
|
|
|
|
|
|
record.date = time;
|
|
@@ -294,24 +311,35 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void update_thresholds() {
|
|
|
+ void update_thresholds()
|
|
|
+ {
|
|
|
auto step_number = static_cast<double>(_step_number);
|
|
|
|
|
|
_up_threshold = _offset + _step_size * (step_number + 1);
|
|
|
_down_threshold = _offset + _step_size * (step_number - 1);
|
|
|
}
|
|
|
|
|
|
- void update_thresholds(double factor) {
|
|
|
+ void update_thresholds(double factor)
|
|
|
+ {
|
|
|
auto step_number = static_cast<double>(_step_number);
|
|
|
|
|
|
_up_threshold = _offset + _step_size * (step_number + (1 - factor));
|
|
|
_down_threshold = _offset + _step_size * (step_number - (1 - factor));
|
|
|
}
|
|
|
|
|
|
- void update_thresholds(double factor, Direction d) {
|
|
|
+ struct direction
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ DIRECTION_UP, DIRECTION_DOWN
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ void update_thresholds(double factor, const typename direction::values &d)
|
|
|
+ {
|
|
|
auto step_number = static_cast<double>(_step_number);
|
|
|
|
|
|
- if (d == DIRECTION_UP) {
|
|
|
+ if (d == direction::DIRECTION_UP) {
|
|
|
_up_threshold = _offset + _step_size * (step_number + (1 - factor));
|
|
|
_down_threshold = _offset + _step_size * (step_number - 1);
|
|
|
} else {
|
|
@@ -320,19 +348,40 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- typedef enum vars {
|
|
|
- UP, DOWN, VALUE
|
|
|
- } Observable;
|
|
|
+ struct state
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ PHASE, ADAPTIVE_STATE, STEP_NUMBER, OFFSET, UP_THRESHOLD, DOWN_THRESHOLD
|
|
|
+ };
|
|
|
+ };
|
|
|
|
|
|
- typedef enum {
|
|
|
- INIT, IDLE, RESPONSE
|
|
|
- } State;
|
|
|
+ struct var
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ UP, DOWN, VALUE
|
|
|
+ };
|
|
|
+ };
|
|
|
|
|
|
- typedef enum {
|
|
|
- IMPOSSIBLE, POSSIBLE, DONE
|
|
|
- } AdaptiveState;
|
|
|
+ struct phase
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ INIT, IDLE, RESPONSE
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ struct adaptive_state
|
|
|
+ {
|
|
|
+ enum values
|
|
|
+ {
|
|
|
+ IMPOSSIBLE, POSSIBLE, DONE
|
|
|
+ };
|
|
|
+ };
|
|
|
|
|
|
- struct record_t {
|
|
|
+ struct record_t
|
|
|
+ {
|
|
|
double value;
|
|
|
typename Time::type date;
|
|
|
};
|
|
@@ -344,7 +393,7 @@ private:
|
|
|
double _step_size;
|
|
|
|
|
|
// state
|
|
|
- int _state;
|
|
|
+ int _phase;
|
|
|
int _adaptive_state;
|
|
|
|
|
|
unsigned int _step_number; // long int
|
|
@@ -359,4 +408,4 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#endif
|
|
|
+#endif
|