diff --git a/include/rosa/agent/DistanceMetrics.hpp b/include/rosa/agent/DistanceMetrics.hpp index 466a88c..e5956be 100644 --- a/include/rosa/agent/DistanceMetrics.hpp +++ b/include/rosa/agent/DistanceMetrics.hpp @@ -1,140 +1,158 @@ //===-- rosa/agent/DistanceMetrics.hpp ---------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/DistanceMetrics.hpp /// /// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at) /// /// \date 2020 /// /// \brief Definition of *DistanceMetrics* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_DISTANCEMETRICS_HPP #define ROSA_AGENT_DISTANCEMETRICS_HPP #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Functionality.h" #include "rosa/support/debug.hpp" +#include + namespace rosa { namespace agent { /// Implements \c rosa::agent::Abstraction as the absolute difference between /// two values /// /// \note This implementation is supposed to be used to represent a difference-metric /// function from an arithmetic domain to an arithmetic range. This is enforced /// statically. /// /// \tparam D type of the input values /// \tparam R type of the difference template class AbsoluteDistance : public Abstraction, R> { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "abstracting not to arithmetic"); public: /// Creates an instance by Initializing the underlying \c Abstraction. AbsoluteDistance(void) : Abstraction, R>(0) { } /// Destroys \p this object. ~AbsoluteDistance(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 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 std::pair &V) const noexcept override { (void)(V); return false; } /// Calculates the distance-metric for the given value. If this is the first /// value, the Default-Value is returned /// /// \param V value to abstract /// /// \return the absolute distanct R operator()(const std::pair &V) const noexcept override { - return V.first - V.second; + // @NOTE reached >98% using 1_0.0001_0.005_1_5_absolute + // inner 0.0001 + // outer 0.005 + return (V.first - V.second); } }; /// Implements \c rosa::agent::Abstraction as the relative difference between /// two values /// /// \note This implementation is supposed to be used to represent a difference-metric /// function from an arithmetic domain to an arithmetic range. This is enforced /// statically. /// /// \tparam D type of the input values /// \tparam R type of the difference template class RelativeDistance : public Abstraction, R> { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "abstracting not to arithmetic"); public: /// Creates an instance by Initializing the underlying \c Abstraction. RelativeDistance(void) : Abstraction, R>(0) { } /// Destroys \p this object. ~RelativeDistance(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 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 std::pair &V) const noexcept override { (void)(V); return false; } /// Calculates the distance-metric for the given value. If this is the first /// value, the Default-Value is returned /// /// \param V value to abstract /// /// \return the absolute distanct R operator()(const std::pair &V) const noexcept override { + // first = sample + // second = history + + + // Daniels 1st proposal + //return (((R)V.second-V.first)*(std::abs(V.first)+1))/(std::pow(V.first,2)+1); + + // Daniels 2nd proposal + //return (((R)V.first-V.second)*(std::abs(V.first-V.second)+1))/(std::pow(V.first-V.second,2)+1); + + // Daniels 3rd proposal + //return ((R)V.first-V.second)*std::abs((R)V.first-V.second)/(1+std::abs((R)V.first-V.second)); + + // Maxis proposal + return ((R)V.first-V.second)/(1+std::abs(V.first-V.second)); + /* + R Norm = ((R)100) - V.first; R Dist = ((R)V.second) - V.first; if (Dist == 0) { return 0; } else { - if (V.first >= 5 || V.second >= 5) { - Dist = Dist / V.first; - } else { - Dist = Dist / (V.second+46.008); - } + Dist = Dist / (V.first+Norm); } - return Dist; + return Dist;*/ } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_DISTANCEMETRICS_HPP diff --git a/include/rosa/agent/FunctionAbstractions.hpp b/include/rosa/agent/FunctionAbstractions.hpp index 9b54210..0639568 100644 --- a/include/rosa/agent/FunctionAbstractions.hpp +++ b/include/rosa/agent/FunctionAbstractions.hpp @@ -1,431 +1,513 @@ //===-- rosa/agent/FunctionAbstractions.hpp ---------------------*- C++ -*-===// // // The RoSA Framework // // Distributed under the terms and conditions of the Boost Software License 1.0. // See accompanying file LICENSE. // // If you did not receive a copy of the license file, see // http://www.boost.org/LICENSE_1_0.txt. // //===----------------------------------------------------------------------===// /// /// \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/Abstraction.hpp" #include "rosa/agent/Functionality.h" #include "rosa/support/debug.hpp" #include #include #include #include namespace rosa { namespace agent { //@benedikt: check if your partialfunctions can take infinity as // argument /// Implements \c rosa::agent::Abstraction as a linear function, /// y = Coefficient * X + Intercept. /// /// \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 class LinearFunction : public Abstraction { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "LinearFunction not arithmetic T"); STATIC_ASSERT((std::is_arithmetic::value), "LinearFunction not to arithmetic"); protected: /// The Intercept of the linear function const R Intercept; /// The Coefficient of the linear function const R Coefficient; public: /// Creates an instance. /// /// \param Intercept the intercept of the linear function /// \param Coefficient the coefficient of the linear function LinearFunction(R Intercept, R Coefficient) noexcept : Abstraction(Intercept), Intercept(Intercept), Coefficient(Coefficient) {} /// Creates an instance given the two points on a linear function. /// /// \param x1 The x-value of the first point /// \param y1 The x-value of the first point /// \param x2 The y-value of the second point /// \param y2 The y-value of the second point LinearFunction(D x1, R y1, D x2, R y2) noexcept - : LinearFunction(y1 - static_cast(x1) * (y1 - y2) / - (static_cast(x1) - static_cast(x2)), + : LinearFunction(y1 - static_cast(x1) * (y1 - y2) / + (static_cast(x1) - static_cast(x2)), (y1 - y2) / - (static_cast(x1) - static_cast(x2))) {} + (static_cast(x1) - static_cast(x2))) {} /// Creates an instance given the two points on a linear function. /// /// \param p1 The coordinates of the first point /// \param p2 The coordinates of the second point LinearFunction(std::pair p1, std::pair p2) noexcept : LinearFunction(p1.first, p1.second, p2.first, p2.second) {} /// 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; } /// Getter for member variable Intercept /// /// \return Intercept D getIntercept() const { return Intercept; } /// Setter for member variable Intercept /// /// \param Intercept the new Intercept void setIntercept(const D &Intercept) { this->Intercept = Intercept; } /// Getter for member variable Coefficient /// /// \return Coefficient D getCoefficient() const { return Coefficient; } /// Setter for member variable Coefficient /// /// \param Coefficient the new Intercept void setCoefficient(const D &Coefficient) { this->Coefficient = Coefficient; } /// Set Intercept and Coefficient from two points on the linear function /// /// \param x1 The x-value of the first point /// \param y1 The x-value of the first point /// \param x2 The y-value of the second point /// \param y2 The y-value of the second point void setFromPoints(D x1, R y1, D x2, R y2) { Coefficient = (y1 - y2) / (x1 - x2); Intercept = y1 - Coefficient * x1; } /// Set Intercept and Coefficient from two points on the linear function /// /// \param p1 The coordinates of the first point /// \param p2 The coordinates of the second point inline void setFromPoints(std::pair p1, std::pair p2) { setFromPoints(p1.first, p1.second, p2.first, p2.second); } /// Evaluates the linear function /// /// \param X the value at which to evaluate the function /// /// \return Coefficient*X + Intercept virtual R operator()(const D &X) const noexcept override { return Intercept + X * Coefficient; } }; /// Implements \c rosa::agent::Abstraction as a sine function, /// y = Amplitude * sin(Frequency * X + Phase) + Average. /// /// \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 class SineFunction : public Abstraction { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "SineFunction not arithmetic T"); STATIC_ASSERT((std::is_arithmetic::value), "SineFunction not to arithmetic"); protected: /// 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 SineFunction(D Frequency, D Amplitude, D Phase, D Average) noexcept : Abstraction(Average), Frequency(Frequency), Amplitude(Amplitude), Phase(Phase), Average(Average) {} /// Destroys \p this object. ~SineFunction(void) = default; /// 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 value of the sine-function at X virtual R operator()(const D &X) const noexcept override { return Amplitude * sin(Frequency * X + Phase) + Average; } }; enum StepDirection { StepUp, StepDown }; /// Implements \c rosa::agent::PartialFunction as a step function from 0 to 1 /// with a ramp in between /// /// \tparam D type of the functions domain /// \tparam R type of the functions range template class StepFunction : public Abstraction { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "abstracting not to arithmetic"); private: D Coefficient; D RightLimit; StepDirection Direction; public: /// Creates an instance by Initializing the underlying \c Abstraction. /// /// \param Coefficient Coefficient of the ramp /// \param Direction wether to step up or down /// /// \pre Coefficient > 0 StepFunction(D Coefficient, StepDirection Direction = StepUp) : Abstraction(0), Coefficient(Coefficient), RightLimit(1.0f / Coefficient), Direction(Direction) { ASSERT(Coefficient > 0); } /// Destroys \p this object. ~StepFunction(void) = default; /// Setter for Coefficient /// /// \param Coefficient the new Coefficient void setCoefficient(const D &Coefficient) { ASSERT(Coefficient > 0); this->Coefficient = Coefficient; this->RightLimit = 1 / Coefficient; } /// Setter for RightLimit /// /// \param _RightLimit the new RightLimit void setRightLimit(const D &_RightLimit) { ASSERT(_RightLimit > 0); this->RightLimit = _RightLimit; this->Coefficient = 1 / _RightLimit; } /// 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 false if the is negative, true otherwise bool isDefaultAt(const D &V) const noexcept override { return V > 0; } /// Executes the Abstraction /// /// \param V value to abstract /// /// \return the abstracted value R operator()(const D &V) const noexcept override { R ret = 0; if (V <= 0) ret = 0; else if (V >= RightLimit) ret = 1; else ret = V * Coefficient; return Direction == StepDirection::StepUp ? ret : 1 - ret; } }; /// Implements \c rosa::agent::Abstraction as a typical (cross-)likeliness /// function. /// /// The function has a likeliness parameter \c P and implements \code /// f(x) -> 1 / (P * x) /// \endcode on the domain \code [0, Inf) \endcode with \code f(0) = 1 \endcode /// . /// /// \note This implementation is supposed to be used to represent a function /// from an arithmetic domain to an arithmetic range. This is enforced /// statically. /// /// \note This function can be used as cross-likeliness profile in \c /// rosa::agent::CrossCombinator for those input combinations that are not to be /// assessed with the default \c crossLikelinessParameter. /// /// \tparam D type of the functions domain /// \tparam R type of the functions range template class LikelinessFunction : public Abstraction { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "abstracting not to arithmetic"); private: //// The likeliness parameter. const R P; public: /// Creates an instance. /// /// \param P likeliness parameter LikelinessFunction(const R P) : Abstraction(0), P(P) {} /// Destroys \p this object. ~LikelinessFunction(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 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 V < 0; } /// Evaluates the likeliness function at the given position. /// /// \param V value to abstract /// /// \return the abstracted value R operator()(const D &V) const noexcept override { if (V < 0) { return this->Default; } else if (V == 0) { return static_cast(1); } else { return static_cast(1) / (P * V); } } }; /// Implements \c rosa::agent::Abstraction as a partial function from a domain /// to a range. /// /// \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. /// /// 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 D type of the functions domain /// \tparam R type of the functions range template class PartialFunction : public Abstraction { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "abstracting not to arithmetic"); private: /// 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>> RA; public: /// 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::shared_ptr>> &Map, const R Default) : Abstraction(Default), RA(Map, std::shared_ptr>(new Abstraction(Default))) { } /// Destroys \p this object. ~PartialFunction(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 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 R operator()(const D &V) const noexcept override { - return RA(V)->operator()(V); + R Ret = RA(V)->operator()(V); + //@TODO move to ClipperFunction + if (Ret < 0) + return 0; + if (Ret > 1) + return 1; + return Ret; + } +}; + +// Begrenzer!!! + +/// Implements \c rosa::agent::Abstraction as a partial function from a domain +/// to a range. +/// +/// \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. +/// +/// 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 D type of the functions domain +/// \tparam R type of the functions range +template +class ClipperFunction : public Abstraction { + // Make sure the actual type arguments are matching our expectations. + STATIC_ASSERT((std::is_arithmetic::value), "abstracting not arithmetic"); + STATIC_ASSERT((std::is_arithmetic::value), + "abstracting not to arithmetic"); + +private: + /// 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. + std::shared_ptr> Function; + R Min; + R Max; + +public: + /// Creates an instance by Initializing the underlying \c Abstraction. + /// + /// \param Default abstraction to abstract to by default + /// \param Min min value to be returned + /// \param Max max value to be returned + /// + /// \pre Each key defines a valid range such that `first <= second` and + /// there are no overlapping ranges defined by the keys. + ClipperFunction(std::shared_ptr> &Function, const R Default, const R Min, const R Max) + : Abstraction(Default), + Function(Function), Min(Min), Max(Max) { + } + + /// Destroys \p this object. + ~ClipperFunction(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 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 Function.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 + R operator()(const D &V) const noexcept override { + R Ret = Function(V); + if (Ret < Min) + return Min; + if (Ret > Max) + return Max; + return Ret; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP