Page MenuHomePhorge

No OneTemporary

Size
33 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline