Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386496
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
33 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/examples/agent-functionalities/agent-functionalities.cpp b/examples/agent-functionalities/agent-functionalities.cpp
index 2da67b8..c1d77a1 100644
--- a/examples/agent-functionalities/agent-functionalities.cpp
+++ b/examples/agent-functionalities/agent-functionalities.cpp
@@ -1,170 +1,183 @@
//===-- examples/agent-functionalities/agent-functionalities.cpp *-- C++-*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/agent-functionalities/agent-functionalities.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief A simple example on defining \c rosa::Agent instances using
/// \c rosa::agent::Functionality object as components.
///
//===----------------------------------------------------------------------===//
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/FunctionAbstractions.hpp"
#include "rosa/agent/RangeConfidence.hpp"
#include "rosa/agent/Confidence.hpp"
#include "rosa/config/version.h"
#include "rosa/core/Agent.hpp"
#include "rosa/core/MessagingSystem.hpp"
#include "rosa/support/log.h"
#include "rosa/support/terminal_colors.h"
#include <vector>
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::terminal;
/// A dummy wrapper for testing \c rosa::MessagingSystem.
///
/// \note Since we test \c rosa::MessagingSystem directly here, we need to get
/// access to its protected members. That we do by imitating to be a decent
/// subclass of \c rosa::MessagingSystem, while calling protected member
/// functions on an object of a type from which we actually don't inherit.
struct SystemTester : protected MessagingSystem {
template <typename T, typename... Funs>
static AgentHandle createMyAgent(MessagingSystem *S, const std::string &Name,
Funs &&... Fs) {
return ((SystemTester *)S)->createAgent<T>(Name, std::move(Fs)...);
}
static void destroyMyAgent(MessagingSystem *S, const AgentHandle &H) {
((SystemTester *)S)->destroyUnit(unwrapAgent(H));
}
};
/// A special \c rosa::Agent with its own state.
class MyAgent : public Agent {
public:
using Tick = AtomConstant<atom("tick")>;
private:
enum class Categories { Bad, Normal, Good };
static const std::map<Categories, const char *> CategoryNames;
History<uint8_t, 10, HistoryPolicy::FIFO> H;
Confidence<uint8_t> C;
RangeAbstraction<uint8_t, Categories> A;
PartialFunction<int, int> L;
- RangeConfidence<float, float> RCL;
- RangeConfidence<float, float> RCS;
+ RangeConfidence<float, Categories, float> RCL;
+ RangeConfidence<float, Categories, float> RCS;
public:
void handler(Tick, uint8_t V) noexcept {
// Record \p V to the \c rosa::agent::History, then print state info.
H << V;
ASSERT(H.entry() == V); // Sanity check.
LOG_INFO_STREAM << "\nNext value: " << PRINTABLE(V)
<< ", confidence: " << C(H)
<< ", category: " << CategoryNames.at(A(H.entry()))
<< ", partial: " << int(L(H.entry()))
<< ", range-confidence-linear: ";
- std::vector<float> res_lin = RCL(H.entry());
+
+ std::map<Categories, float> res_lin = RCL(H.entry());
for (auto i : res_lin){
- LOG_INFO_STREAM << " " << i;
+ LOG_INFO_STREAM << " " << CategoryNames.at(i.first)
+ << " " << i.second << "," ;
}
- LOG_INFO_STREAM << ", range-confidence-sine: ";
- std::vector<float> res_sine = RCS(H.entry());
+ LOG_INFO_STREAM << " range-confidence-sine: ";
+ std::map<Categories, float> res_sine = RCS(H.entry());
for (auto i : res_sine){
- LOG_INFO_STREAM << " " << i;
+ LOG_INFO_STREAM << " " << CategoryNames.at(i.first)
+ << " " << i.second << "," ;
}
LOG_INFO_STREAM << '\n';
+
}
MyAgent(const AtomValue Kind, const rosa::id_t Id, const std::string &Name,
MessagingSystem &S)
: Agent(Kind, Id, Name, S, THISMEMBER(handler)), H(), C(5, 20, 1),
A({{{(uint8_t)10, (uint8_t)14}, Categories::Normal},
{{(uint8_t)15, (uint8_t)17}, Categories::Good},
{{(uint8_t)18, (uint8_t)19}, Categories::Normal}},
Categories::Bad),
L({{{0, 2}, std::make_shared<LinearFunction<int, int>>(0, 1)},
{{2, 4}, std::make_shared<LinearFunction<int, int>>(2, 0)},
{{4, 6}, std::make_shared<LinearFunction<int, int>>(6, -1)}},
0),
RCL({
- PartialFunction<float, float>({
- {{0, 3}, std::make_shared<LinearFunction<float, float>>(0, 1.0/3)},
- {{3, 6}, std::make_shared<LinearFunction<float, float>>(1, 0)},
- {{6, 9}, std::make_shared<LinearFunction<float, float>>(3.0, -1.0/3)},
- },0),
- PartialFunction<float, float>({
- {{6, 9}, std::make_shared<LinearFunction<float, float>>(-2, 1.0/3)},
- {{9, 12}, std::make_shared<LinearFunction<float, float>>(1, 0)},
- {{12, 15}, std::make_shared<LinearFunction<float, float>>(5, -1.0/3)},
- },0),
- PartialFunction<float, float>({
- {{12, 15}, std::make_shared<LinearFunction<float, float>>(-4, 1.0/3)},
- {{15, 18}, std::make_shared<LinearFunction<float, float>>(1, 0)},
- {{18, 21}, std::make_shared<LinearFunction<float, float>>(7, -1.0/3)},
- },0)
+ {Categories::Bad, PartialFunction<float, float>({
+ {{0, 3}, std::make_shared<LinearFunction<float, float>>
+ (0, 1.0/3)},
+ {{3, 6}, std::make_shared<LinearFunction<float, float>>
+ (1, 0)},
+ {{6, 9}, std::make_shared<LinearFunction<float, float>>
+ (3.0, -1.0/3)},
+ },0)},
+ {Categories::Normal, PartialFunction<float, float>({
+ {{6, 9}, std::make_shared<LinearFunction<float, float>>
+ (-2, 1.0/3)},
+ {{9, 12}, std::make_shared<LinearFunction<float, float>>
+ (1, 0)},
+ {{12, 15}, std::make_shared<LinearFunction<float, float>>
+ (5, -1.0/3)},
+ },0)},
+ {Categories::Good, PartialFunction<float, float>({
+ {{12, 15}, std::make_shared<LinearFunction<float, float>>
+ (-4, 1.0/3)},
+ {{15, 18}, std::make_shared<LinearFunction<float, float>>
+ (1, 0)},
+ {{18, 21}, std::make_shared<LinearFunction<float, float>>
+ (7, -1.0/3)},
+ },0)}
}),
RCS({
- PartialFunction<float, float>({
+ {Categories::Bad, PartialFunction<float, float>({
{{0, 3}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2, 0.5)},
{{3, 6}, std::make_shared<LinearFunction<float, float>>(1, 0)},
{{6, 9}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2 + 3, 0.5)},
- },0),
- PartialFunction<float, float>({
+ },0)},
+ {Categories::Normal, PartialFunction<float, float>({
{{6, 9}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2, 0.5)},
{{9, 12}, std::make_shared<LinearFunction<float, float>>(1, 0)},
{{12, 15}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2 + 3, 0.5)},
- },0),
- PartialFunction<float, float>({
+ },0)},
+ {Categories::Good, PartialFunction<float, float>({
{{12, 15}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2, 0.5)},
{{15, 18}, std::make_shared<LinearFunction<float, float>>(1, 0)},
{{18, 21}, std::make_shared<SineFunction<float, float>>
(M_PI/3, 0.5, -M_PI/2 + 3, 0.5)},
- },0)
- }){}
+ },0)}
+ }, true){}
};
const std::map<MyAgent::Categories, const char *> MyAgent::CategoryNames{
{Categories::Bad, "Bad"},
{Categories::Normal, "Normal"},
{Categories::Good, "Good"}};
int main(void) {
LOG_INFO_STREAM << library_string() << " -- " << Color::Red
<< "agent-functionalities example" << Color::Default
<< '\n';
std::unique_ptr<MessagingSystem> S = MessagingSystem::createSystem("Sys");
MessagingSystem *SP = S.get();
AgentHandle A = SystemTester::createMyAgent<MyAgent>(SP, "MyAgent");
std::vector<uint8_t> Vs{0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13,
15, 14, 15, 16, 19, 20, 21};
for (auto I = Vs.begin(); I != Vs.end(); ++I) {
A.send<MyAgent::Tick, uint8_t>(MyAgent::Tick::Value, *I);
}
SystemTester::destroyMyAgent(SP, A);
return 0;
}
diff --git a/include/rosa/agent/Abstraction.hpp b/include/rosa/agent/Abstraction.hpp
index fa9e03e..b44b2de 100644
--- a/include/rosa/agent/Abstraction.hpp
+++ b/include/rosa/agent/Abstraction.hpp
@@ -1,193 +1,238 @@
//===-- rosa/agent/Abstraction.hpp ------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/Abstraction.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Definition of *abstraction* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_ABSTRACTION_HPP
#define ROSA_AGENT_ABSTRACTION_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/support/debug.hpp"
#include <algorithm>
#include <map>
namespace rosa {
namespace agent {
/// Abstracts values from a type to another one.
///
/// \tparam T type to abstract from
/// \tparam A type to abstract to
template <typename T, typename A> class Abstraction : public Functionality {
protected:
/// Value to abstract to by default.
const A Default;
-
public:
/// Creates an instance.
///
/// \param Default value to abstract to by default
Abstraction(const A Default) noexcept : Default(Default) {}
/// Destroys \p this object.
~Abstraction(void) = default;
+ /// Checks wether the Abstraction evaluates to default at the given position
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
+ /// \return true, the default implementation always falls back to the default
+ /// value
+ virtual bool isDefaultAt(const T &V) const noexcept{
+ (void)V;
+ return true;
+ }
+
/// Abstracts a value from type \p T to type \p A.
///
/// \note The default implementation always returns
/// \c rosa::agent::Abstraction::Default, hence the actual argument is
/// ignored.
///
/// \return the abstracted value
virtual A operator()(const T &) const noexcept { return Default; }
};
/// Implements \c rosa::agent::Abstraction as a \c std::map from a type to
/// another one.
///
/// \note This implementation is supposed to be used to abstract between
/// enumeration types, which is statically enforced.
///
/// \tparam T type to abstract from
/// \tparam A type to abstract to
template <typename T, typename A>
class MapAbstraction : public Abstraction<T, A>, private std::map<T, A> {
// Make sure the actual type arguments are enumerations.
STATIC_ASSERT((std::is_enum<T>::value && std::is_enum<A>::value),
"mapping not enumerations");
// Bringing into scope inherited members.
using Abstraction<T, A>::Default;
using std::map<T, A>::end;
using std::map<T, A>::find;
public:
/// Creates an instance by initializing the underlying \c std::map.
///
/// \param Map the mapping to do abstraction according to
/// \param Default value to abstract to by default
MapAbstraction(const std::map<T, A> &Map, const A Default) noexcept
: Abstraction<T, A>(Default),
std::map<T, A>(Map) {}
/// Destroys \p this object.
~MapAbstraction(void) = default;
+ /// Checks wether the Abstraction evaluates to default at the given position
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
+ /// \return true if the Abstraction falls back to the default value
+ bool isDefaultAt(const T &V) const noexcept override {
+ const auto I = find(V);
+ return I == end() ? true : false;
+ }
+
/// Abstracts a value from type \p T to type \p A based on the set mapping.
///
/// Results in the value associated by the set mapping to the argument, or
/// \c rosa::agent::MapAbstraction::Default if the actual argument is not
/// associated with anything by the set mapping.
///
/// \param V value to abstract
///
/// \return the abstracted value based on the set mapping
A operator()(const T &V) const noexcept override {
const auto I = find(V);
return I == end() ? Default : *I;
}
};
/// Implements \c rosa::agent::Abstraction as a \c std::map from ranges of a
/// type to values of another type.
///
/// \note This implementation is supposed to be used to abstract ranges of
/// arithmetic types into enumerations, which is statically enforced.
///
/// \invariant The keys in the underlying \c std::map define valid ranges
/// such that `first <= second` and there are no overlapping ranges defined by
/// the keys.
///
/// \tparam T type to abstract from
/// \tparam A type to abstract to
template <typename T, typename A>
class RangeAbstraction : public Abstraction<T, A>,
private std::map<std::pair<T, T>, A> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<T>::value), "abstracting not arithmetic");
/// \todo check if this compiles with the definition of abstractions as
/// self-aware properties
//STATIC_ASSERT((std::is_enum<A>::value), "abstracting not to enumeration");
// Bringing into scope inherited members.
using Abstraction<T, A>::Default;
using std::map<std::pair<T, T>, A>::begin;
using std::map<std::pair<T, T>, A>::end;
using std::map<std::pair<T, T>, A>::find;
public:
/// Creates an instance by Initializing the unserlying \c std::map.
///
/// \param Map the mapping to do abstraction according to
/// \param Default value to abstract to by default
///
/// \pre Each key defines a valid range such that `first <= second` and
/// there are no overlapping ranges defined by the keys.
RangeAbstraction(const std::map<std::pair<T, T>, A> &Map, const A &Default)
: Abstraction<T, A>(Default), std::map<std::pair<T, T>, A>(Map) {
// Sanity check.
ASSERT(std::all_of(
begin(), end(), [this](const std::pair<std::pair<T, T>, A> &P) {
return P.first.first <= P.first.second &&
std::all_of(++find(P.first), end(),
[&P](const std::pair<std::pair<T, T>, A> &R) {
// \note Values in \c Map are sorted.
return P.first.first < P.first.second &&
P.first.second <= R.first.first ||
P.first.first == P.first.second &&
P.first.second < R.first.first;
});
}));
}
/// Destroys \p this object.
~RangeAbstraction(void) = default;
+ /// Checks wether the Abstraction evaluates to default at the given position
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
+ /// \return true if the Abstraction falls back to the default value
+ bool isDefaultAt(const T &V) const noexcept override {
+ auto I = begin();
+ bool Found = false; // Indicates if \c I refers to a matching range.
+ bool Failed = false; // Indicates if it is pointless to continue searching.
+ while (!Found && !Failed && I != end()) {
+ if (V < I->first.first) {
+ // No match so far and \p V is below the next range, never will match.
+ // \note Keys are sorted in the map.
+ return true;
+ } else if (I->first.first <= V && V < I->first.second) {
+ // Matching range found.
+ return false;
+ } else {
+ // Cannot conclude in this step, move to the next range.
+ ++I;
+ }
+ }
+ return true;
+ }
+
/// Abstracts a value from type \p T to type \p A based on the set mapping.
///
/// Results in the value associated by the set mapping to the argument, or
/// \c rosa::agent::RangeAbstraction::Default if the actual argument is not
/// included in any of the ranges in the set mapping.
///
/// \param V value to abstract
///
/// \return the abstracted value based on the set mapping
A operator()(const T &V) const noexcept override {
auto I = begin();
bool Found = false; // Indicates if \c I refers to a matching range.
bool Failed = false; // Indicates if it is pointless to continue searching.
while (!Found && !Failed && I != end()) {
if (V < I->first.first) {
// No match so far and \p V is below the next range, never will match.
// \note Keys are sorted in the map.
Failed = true;
} else if (I->first.first <= V && V < I->first.second) {
// Matching range found.
Found = true;
} else {
// Cannot conclude in this step, move to the next range.
++I;
}
}
ASSERT(!Found || I != end());
return Found ? I->second : Default;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_ABSTRACTION_HPP
diff --git a/include/rosa/agent/FunctionAbstractions.hpp b/include/rosa/agent/FunctionAbstractions.hpp
index 1cd0d10..9a7127a 100644
--- a/include/rosa/agent/FunctionAbstractions.hpp
+++ b/include/rosa/agent/FunctionAbstractions.hpp
@@ -1,175 +1,224 @@
//===-- rosa/agent/FunctionAbstractions.hpp ---------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/FunctionAbstractions.hpp
///
/// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *FunctionAbstractions* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
#define ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/agent/Abstraction.hpp"
#include "rosa/support/debug.hpp"
#include <algorithm>
#include <vector>
#include <cmath>
#include <memory>
namespace rosa {
namespace agent {
-/// Evaluates a linear function at a given value.
+/// Implements \c rosa::agent::Abstraction as a linear function,
+/// y = Coefficient * X + Intercept.
///
-/// \tparam T type of the functions domain
-/// \tparam A type of the functions range
-template <typename T, typename A> class LinearFunction :
- public Abstraction<T, A>{
+/// \note This implementation is supposed to be used to represent a linear
+/// function from an arithmetic domain to an arithmetic range. This is enforced
+/// statically.
+///
+/// \tparam D type of the functions domain
+/// \tparam R type of the functions range
+template <typename D, typename R> class LinearFunction :
+ public Abstraction<D, R>{
// Make sure the actual type arguments are matching our expectations.
- STATIC_ASSERT((std::is_arithmetic<T>::value),
+ STATIC_ASSERT((std::is_arithmetic<D>::value),
"LinearFunction not arithmetic T");
- STATIC_ASSERT((std::is_arithmetic<A>::value),
+ STATIC_ASSERT((std::is_arithmetic<R>::value),
"LinearFunction not to arithmetic");
protected:
- const T Intercept;
- const T Coefficient;
+ /// The Intercept of the linear function
+ const D Intercept;
+ /// The Coefficient of the linear function
+ const D Coefficient;
public:
/// Creates an instance.
///
/// \param Intercept the intercept of the linear function
/// \param Coefficient the coefficient of the linear function
- /// domain
- LinearFunction(T Intercept, T Coefficient) noexcept
- : Abstraction<T, A>(Intercept),
+ LinearFunction(D Intercept, D Coefficient) noexcept
+ : Abstraction<D, R>(Intercept),
Intercept(Intercept),
Coefficient(Coefficient) {}
/// Destroys \p this object.
~LinearFunction(void) = default;
+ /// Checks wether the Abstraction evaluates to default at the given position
+ /// As LinearFunctions can be evaluated everythwere, this is always false
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
+ ///
+ /// \return false
+ bool isDefaultAt(const D &V) const noexcept override {
+ (void)V;
+ return false;
+ }
+
/// Evaluates the linear function
///
/// \param X the value at which to evaluate the function
- /// \return the result
- virtual A operator()(const T &X) const noexcept override {
+ ///
+ /// \return Coefficient*X + Intercept
+ virtual R operator()(const D &X) const noexcept override {
return Intercept + X*Coefficient;
}
};
-/// Evaluates a sine function at a given value.
+/// Implements \c rosa::agent::Abstraction as a sine function,
+/// y = Amplitude * sin(Frequency * X + Phase) + Average.
///
-/// \tparam T type of the functions domain
-/// \tparam A type of the functions range
-template <typename T, typename A> class SineFunction :
- public Abstraction<T, A>{
+/// \note This implementation is supposed to be used to represent a sine
+/// function from an arithmetic domain to an arithmetic range. This is enforced
+/// statically.
+///
+/// \tparam D type of the functions domain
+/// \tparam R type of the functions range
+template <typename D, typename R> class SineFunction :
+ public Abstraction<D, R>{
// Make sure the actual type arguments are matching our expectations.
- STATIC_ASSERT((std::is_arithmetic<T>::value),
+ STATIC_ASSERT((std::is_arithmetic<D>::value),
"SineFunction not arithmetic T");
- STATIC_ASSERT((std::is_arithmetic<A>::value),
+ STATIC_ASSERT((std::is_arithmetic<R>::value),
"SineFunction not to arithmetic");
protected:
- const T Frequency;
- const T Amplitude;
- const T Phase;
- const T Average;
+ /// The frequency of the sine wave
+ const D Frequency;
+ /// The Ampiltude of the sine wave
+ const D Amplitude;
+ /// The Phase-shift of the sine wave
+ const D Phase;
+ /// The y-shift of the sine wave
+ const D Average;
public:
/// Creates an instance.
///
/// \param Frequency the frequency of the sine wave
/// \param Amplitude the amplitude of the sine wave
/// \param Phase the phase of the sine wave
/// \param Average the average of the sine wave
- /// domain
- SineFunction(T Frequency, T Amplitude, T Phase, T Average) noexcept
- : Abstraction<T, A>(Average),
+ SineFunction(D Frequency, D Amplitude, D Phase, D Average) noexcept
+ : Abstraction<D, R>(Average),
Frequency(Frequency),
Amplitude(Amplitude),
Phase(Phase),
Average(Average) {}
/// Destroys \p this object.
~SineFunction(void) = default;
- /// Evaluates the linear function
+ /// Checks wether the Abstraction evaluates to default at the given position
+ /// As SineFunctions can be evaluated everythwere, this is always false
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
+ ///
+ /// \return false
+ bool isDefaultAt(const D &V) const noexcept override {
+ (void)V;
+ return false;
+ }
+
+ /// Evaluates the sine function
///
/// \param X the value at which to evaluate the function
- /// \return the result
- virtual A operator()(const T &X) const noexcept override {
+ /// \return the value of the sine-function at X
+ virtual R operator()(const D &X) const noexcept override {
return Amplitude*sin(Frequency * X + Phase) + Average;
}
};
-
-/// Implements \c rosa::agent::RangeAbstraction as an abstraction from
-/// \c std::map from ranges of a type to abstractions of that type to another
-/// type. The resulting abstractions are evaluated for the given values.
+/// Implements \c rosa::agent::Abstraction as a partial function from a domain
+// /to a range.
///
-/// \note This implementation is supposed to be used to abstract ranges of
-/// arithmetic types into abstractions from that type to another arithmetic
-/// type, which is statically enforced.
+/// \note This implementation is supposed to be used to represent a partial
+/// function from an arithmetic domain to an arithmetic range. This is enforced
+/// statically.
///
-/// \invariant The keys in the underlying \c std::map define valid ranges
-/// such that `first <= second` and there are no overlapping ranges defined by
-/// the keys.
+/// A partial function is defined as a list of abstractions, where each
+/// abstraction is associated a range in which it is defined. These ranges must
+/// be mutually exclusive.
///
-/// \tparam T type to abstract from
-/// \tparam A type to abstract to
-template <typename T, typename A>
-class PartialFunction : private Abstraction<T, A> {
+/// \tparam D type of the functions domain
+/// \tparam R type of the functions range
+template <typename D, typename R>
+class PartialFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
- STATIC_ASSERT((std::is_arithmetic<T>::value), "abstracting not arithmetic");
- STATIC_ASSERT((std::is_arithmetic<A>::value),
+ STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
+ STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
private:
- RangeAbstraction<T, std::shared_ptr<Abstraction<T, A>>> RA;
+ /// A \c rosa::agent::RangeAbstraction RA is used to represent the association
+ /// from ranges to Abstractions.
+ /// This returns the Abstraction that is defined for any given value, or
+ /// a default Abstraction if no Abstraction is defined for that value.
+ RangeAbstraction<D, std::shared_ptr<Abstraction<D, R>>> RA;
public:
- /// Creates an instance by Initializing the underlying \c RangeAbstraction.
+ /// Creates an instance by Initializing the underlying \c Abstraction.
///
/// \param Map the mapping to do abstraction according to
/// \param Default abstraction to abstract to by default
///
/// \pre Each key defines a valid range such that `first <= second` and
/// there are no overlapping ranges defined by the keys.
- PartialFunction(const std::map<std::pair<T, T>,
- std::shared_ptr<Abstraction<T, A>>> &Map,
- const A Default)
- : Abstraction<T, A>(Default),
- RA(Map, std::shared_ptr<Abstraction<T, A>>
- (new Abstraction<T, A>(Default))) {
+ PartialFunction(const std::map<std::pair<D, D>,
+ std::shared_ptr<Abstraction<D, R>>> &Map,
+ const R Default)
+ : Abstraction<D, R>(Default),
+ RA(Map, std::shared_ptr<Abstraction<D, R>>
+ (new Abstraction<D, R>(Default))) {
}
/// Destroys \p this object.
~PartialFunction(void) = default;
- /// Evaluates an Abstraction from type \p T to type \p A based on the set
- /// mapping.
+ /// Checks wether the Abstraction evaluates to default at the given position
+ ///
+ /// \param V the value at which to check if the function falls back to it's
+ /// default value.
///
- /// Results in the value associated by the set mapping to the argument, or
- /// \c rosa::agent::RangeAbstraction::Default if the actual argument is not
- /// included in any of the ranges in the set mapping.
+ /// \return false if the value falls into a defined range and the Abstraction
+ /// defined for that range does not fall back to it's default value.
+ bool isDefaultAt(const D &V) const noexcept override {
+ return RA.isDefaultAt(V) ? true : RA(V)->isDefaultAt(V);
+ }
+
+ /// Searches for an Abstraction for the given value and executes it for that
+ /// value, if such an Abstraction is found. The default Abstraction is
+ /// evaluated otherwise.
///
/// \param V value to abstract
///
/// \return the abstracted value based on the set mapping
- A operator()(const T &V) const noexcept override {
+ R operator()(const D &V) const noexcept override {
return RA(V)->operator()(V);
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
diff --git a/include/rosa/agent/RangeConfidence.hpp b/include/rosa/agent/RangeConfidence.hpp
index 0966a87..0d8732e 100644
--- a/include/rosa/agent/RangeConfidence.hpp
+++ b/include/rosa/agent/RangeConfidence.hpp
@@ -1,89 +1,109 @@
//===-- rosa/agent/RangeConfidence.hpp --------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/RangeConfidence.hpp
///
/// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *RangeConfidence* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_RANGECONFIDENCE_HPP
#define ROSA_AGENT_RANGECONFIDENCE_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/FunctionAbstractions.hpp"
#include "rosa/support/debug.hpp"
#include <algorithm>
#include <vector>
#include <cmath>
#include <memory>
namespace rosa {
namespace agent {
-/// Evaluates a vector of Abstractions at a given value and returns the results
-/// as a vector
+/// Evaluates a map of ID's to Abstractions at a given value and returns the
+/// results as a map from ID's to results of the corresponding Abstraction
///
/// \note This implementation is supposed to be used to abstract ranges of
-/// arithmetic types into vectors of another arithmetic type, which is
-/// statically enforced.
+/// arithmetic types into maps whose values are of another arithmetic type,
+/// which is statically enforced.
///
-/// \tparam T type to abstract from
-/// \tparam A type to abstract a vector of to
-template <typename T, typename A>
-class RangeConfidence : public Abstraction<T, std::vector<A>>,
- private std::vector<PartialFunction<T, A>>{
+/// \tparam D type to abstract from
+/// \tparam I type the type of the ID's
+/// \tparam R type of the range
+template <typename D, typename I, typename R>
+class RangeConfidence : protected Abstraction<D, std::map<I, R>>,
+ private std::map<I, PartialFunction<D, R>>{
// Make sure the actual type arguments are matching our expectations.
- STATIC_ASSERT((std::is_arithmetic<T>::value), "abstracting not arithmetic");
- STATIC_ASSERT((std::is_arithmetic<A>::value),
+ STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
+ STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
- // Bringing into scope inherited members.
- using std::vector<PartialFunction<T, A>>::size;
- using std::vector<PartialFunction<T, A>>::begin;
- using std::vector<PartialFunction<T, A>>::end;
+private:
+ /// Wether to include default results in the result-map or not
+ bool IgnoreDefaults;
public:
- /// Creates an instance by Initializing the underlying \c RangeAbstraction.
+ /// Creates an instance by Initializing the underlying \c Abstraction and
+ /// \c std::map.
///
/// \param Abstractions the Abstractions to be evaluated
- RangeConfidence(const std::vector<PartialFunction<T, A>> &Abstractions)
- : Abstraction<T, std::vector<A>>({}),
- std::vector<PartialFunction<T, A>>(Abstractions) {
+ /// \param IgnoreDefaults wether to include default results in the result-map
+ /// or not (defaults to false).
+ RangeConfidence(const std::map<I, PartialFunction<D, R>> &Abstractions,
+ bool IgnoreDefaults = false)
+ : Abstraction<D, std::map<I, R>>({}),
+ std::map<I, PartialFunction<D, R>>(Abstractions),
+ IgnoreDefaults(IgnoreDefaults){
}
/// Destroys \p this object.
~RangeConfidence(void) = default;
- /// Evaluates an Abstraction from type \p T to type \p A based on the set
- /// mapping.
+ /// Checks wether all Abstractions evaluate to default at the given position
///
- /// Results in the value associated by the set mapping to the argument, or
- /// \c rosa::agent::RangeAbstraction::Default if the actual argument is not
- /// included in any of the ranges in the set mapping.
+ /// \param V the value at which to check if the functions falls back to it's
+ /// default value.
+ ///
+ /// \return true, if all Abstractions evaluate to default
+ bool isDefaultAt(const D &V) const noexcept override {
+ for (auto const& p : ((std::map<I, PartialFunction<D, R>>)*this)){
+ if(!p.second.isDefaultAt(V))
+ return false;
+ }
+ return true;
+ }
+
+ /// All Abstractions stored in the underlying \c std::map are evaluated for
+ /// the given value. Their results are stored in another map, with
+ /// corresponding keys.
+ /// If IgnoreDefaults is set, Abstractions that default for that value are not
+ /// evaluated and inserted into the resulting \c std::map
///
/// \param V value to abstract
///
- /// \return the abstracted value based on the set mapping
- std::vector<A> operator()(const T &V) const noexcept override {
- std::vector<A> ret;
- for (auto const& func : ((std::vector<PartialFunction<T, A>>)*this)){
- ret.push_back(func(V));
+ /// \return a \c std::map containing the results of the stored Abstractions,
+ /// indexable by the key's the Abstractions are associated with
+ std::map<I, R> operator()(const D &V) const noexcept override {
+ std::map<I, R> ret;
+ for (auto const& p : ((std::map<I, PartialFunction<D, R>>)*this)){
+ if(!IgnoreDefaults || !p.second.isDefaultAt(V))
+ ret.insert(std::pair<I, R>(p.first, p.second(V)));
}
return ret;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_RANGECONFIDENCE_HPP
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 6:52 PM (13 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157305
Default Alt Text
(33 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment