Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386316
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
64 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/rosa/agent/CrossCombinator.h b/include/rosa/agent/CrossCombinator.h
index eafb2d0..4c279fe 100644
--- a/include/rosa/agent/CrossCombinator.h
+++ b/include/rosa/agent/CrossCombinator.h
@@ -1,551 +1,552 @@
//===-- rosa/delux/CrossCombinator.h ----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/CrossCombinator.h
///
/// \author Daniel Schnoell
///
/// \date 2019
/// \note based on Maximilian Goetzinger(maxgot @utu.fi) code in
/// CAM_Dirty_include SA-EWS2_Version... inside Agent.cpp
///
/// \brief
///
/// \todo there is 1 exception that needs to be handled correctly.
/// \note the default search function is extremely slow maybe this could be done
/// via template for storage class and the functions/methods to efficiently find
/// the correct LinearFunction
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_CROSSCOMBINATOR_H
#define ROSA_AGENT_CROSSCOMBINATOR_H
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/Functionality.h"
#include "rosa/agent/ReliabilityConfidenceCombinator.h"
#include "rosa/core/forward_declarations.h" // needed for id_t
#include "rosa/support/log.h" // needed for error "handling"
// nedded headers
#include <string>
#include <type_traits> //assert
#include <vector>
// for static methods
#include <algorithm>
#include <numeric>
namespace rosa {
namespace agent {
template <typename id, typename IdentifierType, typename ReliabilityType>
std::vector<std::pair<id_t, IdentifierType>> &operator<<(
std::vector<std::pair<id_t, IdentifierType>> &me,
std::vector<std::tuple<id, IdentifierType, ReliabilityType>> Values) {
for (auto tmp : Values) {
std::pair<id, IdentifierType> tmp2;
tmp2.first = std::get<0>(tmp);
tmp2.second = std::get<1>(tmp);
me.push_back(tmp2);
}
return me;
}
/// This is the Combinator class for cross Reliabilities. It has many functions
/// with different purposes
/// \brief It takes the Identifiers and Reliabilities of all given ids and
/// calculates the Reliability of them together. Also it can creates the
/// feedback that is needed by the \c ReliabilityAndConfidenceCombinator, which
/// is a kind of confidence.
///
/// \tparam IdentifierType Data type of the Identifier ( Typically double
/// or float) \tparam ReliabilityType Data type of the Reliability ( Typically
/// long or int)
///
/// \note This class is commonly in a master slave relationship as master with
/// \c ReliabilityAndConfidenceCombinator. The \c operator()() combines the
/// Reliability of all connected Slaves and uses that as its own Reliability
/// also creates the feedback for the Slaves.
///
/// \note more information about how the Reliability and feedback is
/// created at \c operator()() , \c getCombinedCrossReliability() , \c
/// getCombinedInputReliability() , \c getOutputReliability() [ this is the
/// used Reliability ], \c getCrossConfidence() [ this is the feedback
/// for all Slaves ]
///
/// a bit more special Methods \c CrossConfidence() ,\c CrossReliability()
template <typename IdentifierType, typename ReliabilityType>
class CrossCombinator {
public:
static_assert(std::is_arithmetic<IdentifierType>::value,
"HighLevel: IdentifierType has to be an arithmetic type\n");
static_assert(std::is_arithmetic<ReliabilityType>::value,
"HighLevel: ReliabilityType has to be an arithmetic type\n");
// ---------------------------------------------------------------------------
// useful definitions
// ---------------------------------------------------------------------------
/// typedef To shorten the writing.
/// \c ConfOrRel
using ConfOrRel = ConfOrRel<IdentifierType, ReliabilityType>;
/// To shorten the writing.
using Abstraction =
typename rosa::agent::Abstraction<IdentifierType, ReliabilityType>;
/// The return type for the \c operator()() Method
struct returnType {
ReliabilityType CrossReliability;
std::map<id_t, std::vector<ConfOrRel>> CrossConfidence;
};
// -------------------------------------------------------------------------
// Relevant Methods
// -------------------------------------------------------------------------
/// Calculates the Reliability and the CrossConfidences for each id for all
/// of there Identifiers.
///
/// \param Values It gets the Identifiers and Reliabilities of
/// all connected Slaves inside a vector.
///
/// \return it returns a struct \c returnType containing the \c
/// getCombinedCrossReliability() and \c getCrossConfidence()
returnType operator()(
std::vector<std::tuple<id_t, IdentifierType, ReliabilityType>> Values) {
return {getOutputReliability(Values), getCrossConfidence(Values)};
}
/// returns the combined Cross Reliability via \c
/// CombinedCrossRelCombinationMethod \c
/// setCombinedCrossRelCombinationMethod() for all ids \c
/// CrossReliability() \param Values the used Values
ReliabilityType getCombinedCrossReliability(
const std::vector<std::tuple<id_t, IdentifierType, ReliabilityType>>
&Values) noexcept {
ReliabilityType combinedCrossRel = -1;
std::vector<std::pair<id_t, IdentifierType>> Agents;
Agents << Values;
for (auto Value : Values) {
id_t id = std::get<0>(Value);
IdentifierType sc = std::get<1>(Value);
// calculate the cross reliability for this slave agent
ReliabilityType realCrossReliabilityOfSlaveAgent =
CrossReliability({id, sc}, Agents);
if (combinedCrossRel != -1)
combinedCrossRel = CombinedCrossRelCombinationMethod(
combinedCrossRel, realCrossReliabilityOfSlaveAgent);
else
combinedCrossRel = realCrossReliabilityOfSlaveAgent;
}
return combinedCrossRel;
}
/// returns the combined via \c CombinedInputRelCombinationMethod \c
/// setCombinedInputRelCombinationMethod() input reliability \param Values
/// the used Values
ReliabilityType getCombinedInputReliability(
const std::vector<std::tuple<id_t, IdentifierType, ReliabilityType>>
&Values) noexcept {
ReliabilityType combinedInputRel = -1;
std::vector<std::pair<id_t, IdentifierType>> Agents;
Agents << Values;
for (auto Value : Values) {
ReliabilityType rel = std::get<2>(Value);
if (combinedInputRel != -1)
combinedInputRel =
CombinedInputRelCombinationMethod(combinedInputRel, rel);
else
combinedInputRel = rel;
}
return combinedInputRel;
}
/// returns the combination via \c OutputReliabilityCombinationMethod \c
/// setOutputReliabilityCombinationMethod() of the Cross reliability and
/// input reliability \param Values the used Values
ReliabilityType getOutputReliability(
const std::vector<std::tuple<id_t, IdentifierType, ReliabilityType>>
&Values) noexcept {
return OutputReliabilityCombinationMethod(
getCombinedInputReliability(Values),
getCombinedCrossReliability(Values));
}
/// returns the crossConfidence for all ids \c CrossConfidence()
/// \param Values the used Values
std::map<id_t, std::vector<ConfOrRel>> getCrossConfidence(
const std::vector<std::tuple<id_t, IdentifierType, ReliabilityType>>
&Values) noexcept {
std::vector<std::pair<id_t, IdentifierType>> Agents;
std::map<id_t, std::vector<ConfOrRel>> output;
std::vector<ConfOrRel> output_temporary;
Agents << Values;
for (auto Value : Values) {
id_t id = std::get<0>(Value);
output_temporary.clear();
for (IdentifierType thoIdentifier : Identifiers[id]) {
ConfOrRel data;
data.Identifier = thoIdentifier;
data.Reliability = CrossConfidence(id, thoIdentifier, Agents);
output_temporary.push_back(data);
}
output.insert({id, output_temporary});
}
return output;
}
/// Calculates the Cross Confidence
/// \brief it uses the Identifier value and calculates
/// the Confidence of a given agent( represented by their id ) for a given
/// Identifiers in connection to all other given agents
///
/// \note all combination of agents and there corresponding Cross Reliability
/// function have to be specified
ReliabilityType
CrossConfidence(const id_t &MainAgent, const IdentifierType &TheoreticalValue,
const std::vector<std::pair<id_t, IdentifierType>>
&SlaveAgents) noexcept {
ReliabilityType crossReliabiability;
std::vector<ReliabilityType> values;
for (std::pair<id_t, IdentifierType> SlaveAgent : SlaveAgents) {
if (SlaveAgent.first == MainAgent)
continue;
if (TheoreticalValue == SlaveAgent.second)
crossReliabiability = 1;
else
crossReliabiability =
1 / (crossReliabilityParameter *
std::abs(TheoreticalValue - SlaveAgent.second));
// profile reliability
ReliabilityType crossReliabilityFromProfile =
getCrossReliabilityFromProfile(
MainAgent, SlaveAgent.first,
std::abs(TheoreticalValue - SlaveAgent.second));
values.push_back(
std::max(crossReliabiability, crossReliabilityFromProfile));
}
return Method(values);
}
/// Calculates the Cross Reliability
/// \brief it uses the Identifier value and calculates
/// the Reliability of a given agent( represented by their id ) in connection
/// to all other given agents
///
/// \note all combination of agents and there corresponding Cross Reliability
/// function have to be specified
ReliabilityType
CrossReliability(const std::pair<id_t, IdentifierType> &MainAgent,
const std::vector<std::pair<id_t, IdentifierType>>
&SlaveAgents) noexcept {
ReliabilityType crossReliabiability;
std::vector<ReliabilityType> values;
for (std::pair<id_t, IdentifierType> SlaveAgent : SlaveAgents) {
if (SlaveAgent.first == MainAgent.first)
continue;
if (MainAgent.second == SlaveAgent.second)
crossReliabiability = 1;
else
crossReliabiability =
1 / (crossReliabilityParameter *
std::abs(MainAgent.second - SlaveAgent.second));
// profile reliability
ReliabilityType crossReliabilityFromProfile =
getCrossReliabilityFromProfile(
MainAgent.first, SlaveAgent.first,
std::abs(MainAgent.second - SlaveAgent.second));
values.push_back(
std::max(crossReliabiability, crossReliabilityFromProfile));
}
return Method(values);
}
// --------------------------------------------------------------------------
// Defining the class
// --------------------------------------------------------------------------
/// adds a Cross Reliability Profile used to get the Reliability of the
/// Identifier difference
///
/// \param idA The id of the one \c Agent ( ideally the id of \c Unit to make
/// it absolutely unique )
///
/// \param idB The id of the other \c Agent
///
/// \param Function A shared pointer to an \c Abstraction it would use the
/// difference in Identifier for its input
void addCrossReliabilityProfile(
const id_t &idA, const id_t &idB,
const std::shared_ptr<Abstraction> &Function) noexcept {
Functions.push_back({true, idA, idB, Function});
}
/// sets the cross reliability parameter
void setCrossReliabilityParameter(const ReliabilityType &val) noexcept {
crossReliabilityParameter = val;
}
/// This is the adder for the Identifiers
/// \param id The id of the Agent of the Identifiers
- /// \param Identifiers id specific Identifiers. This will be copied So that if
+ /// \param _Identifiers id specific Identifiers. This will be copied So that if
/// Slaves have different Identifiers they can be used correctly. \brief The
/// Identifiers of all connected slave Agents has to be known to be able to
/// iterate over them
- void addIdentifiers(const id_t &id,
- const std::vector<IdentifierType> &Identifiers) noexcept {
- this->Identifiers.insert({id, Identifiers});
+ void
+ addIdentifiers(const id_t &id,
+ const std::vector<IdentifierType> &_Identifiers) noexcept {
+ Identifiers.insert({id, _Identifiers});
}
// -------------------------------------------------------------------------
// Combinator Settings
// -------------------------------------------------------------------------
/// sets the used method to combine the values
/// \param Meth the method which should be used. predefined functions in the
/// struct \c predefinedMethods \c
/// CONJUNCTION() \c AVERAGE() \c DISJUNCTION()
void setCrossReliabilityCombinatorMethod(
const std::function<ReliabilityType(std::vector<ReliabilityType> values)>
&Meth) noexcept {
Method = Meth;
}
/// sets the combination method for the combined cross reliability
/// \param Meth the method which should be used. predefined functions in the
/// struct \c predefinedMethods CombinedCrossRelCombinationMethod<method>()
void setCombinedCrossRelCombinationMethod(
const std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
&Meth) noexcept {
CombinedCrossRelCombinationMethod = Meth;
}
/// sets the combined input rel method
/// \param Meth the method which should be used. predefined functions in the
/// struct \c predefinedMethods CombinedInputRelCombinationMethod<method>()
void setCombinedInputRelCombinationMethod(
const std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
&Meth) noexcept {
CombinedInputRelCombinationMethod = Meth;
}
/// sets the used OutputReliabilityCombinationMethod
/// \param Meth the method which should be used. predefined functions in the
/// struct \c predefinedMethods OutputReliabilityCombinationMethod<method>()
void setOutputReliabilityCombinationMethod(
const std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
&Meth) noexcept {
OutputReliabilityCombinationMethod = Meth;
}
// -------------------------------------------------------------------------
// Predefined Functions
// -------------------------------------------------------------------------
/// This struct is a pseudo name space to have easier access to all predefined
/// methods while still not overcrowding the class it self
struct predefinedMethods {
/// predefined combination method
static ReliabilityType CONJUNCTION(std::vector<ReliabilityType> values) {
return *std::min_element(values.begin(), values.end());
}
/// predefined combination method
static ReliabilityType AVERAGE(std::vector<ReliabilityType> values) {
return std::accumulate(values.begin(), values.end(), 0.0) / values.size();
}
/// predefined combination method
static ReliabilityType DISJUNCTION(std::vector<ReliabilityType> values) {
return *std::max_element(values.begin(), values.end());
}
/// predefined combination Method
static ReliabilityType
CombinedCrossRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) {
return std::min(A, B);
}
/// predefined combination Method
static ReliabilityType
CombinedCrossRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) {
return std::max(A, B);
}
/// predefined combination Method
static ReliabilityType
CombinedCrossRelCombinationMethodMult(ReliabilityType A,
ReliabilityType B) {
return A * B;
}
/// predefined combination Method
static ReliabilityType
CombinedCrossRelCombinationMethodAverage(ReliabilityType A,
ReliabilityType B) {
return (A + B) / 2;
}
/// predefined combination Method
static ReliabilityType
CombinedInputRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) {
return std::min(A, B);
}
/// predefined combination Method
static ReliabilityType
CombinedInputRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) {
return std::max(A, B);
}
/// predefined combination Method
static ReliabilityType
CombinedInputRelCombinationMethodMult(ReliabilityType A,
ReliabilityType B) {
return A * B;
}
/// predefined combination Method
static ReliabilityType
CombinedInputRelCombinationMethodAverage(ReliabilityType A,
ReliabilityType B) {
return (A + B) / 2;
}
/// predefined combination method
static ReliabilityType
OutputReliabilityCombinationMethodMin(ReliabilityType A,
ReliabilityType B) {
return std::min(A, B);
}
/// predefined combination method
static ReliabilityType
OutputReliabilityCombinationMethodMax(ReliabilityType A,
ReliabilityType B) {
return std::max(A, B);
}
/// predefined combination method
static ReliabilityType
OutputReliabilityCombinationMethodMult(ReliabilityType A,
ReliabilityType B) {
return A * B;
}
/// predefined combination method
static ReliabilityType
OutputReliabilityCombinationMethodAverage(ReliabilityType A,
ReliabilityType B) {
return (A + B) / 2;
}
};
// -------------------------------------------------------------------------
// Cleanup
// -------------------------------------------------------------------------
~CrossCombinator() { Functions.clear(); }
// --------------------------------------------------------------------------
// Parameters
// --------------------------------------------------------------------------
private:
struct Functionblock {
bool exists = false;
id_t A;
id_t B;
std::shared_ptr<Abstraction> Funct;
};
std::map<id_t, std::vector<IdentifierType>> Identifiers;
/// From Maxi in his code defined as 1 can be changed by set
ReliabilityType crossReliabilityParameter = 1;
/// Stored Cross Reliability Functions
std::vector<Functionblock> Functions;
/// Method which is used to combine the generated values
std::function<ReliabilityType(std::vector<ReliabilityType>)> Method =
predefinedMethods::AVERAGE;
std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
CombinedCrossRelCombinationMethod =
predefinedMethods::CombinedCrossRelCombinationMethodMin;
std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
CombinedInputRelCombinationMethod =
predefinedMethods::CombinedInputRelCombinationMethodMin;
std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
OutputReliabilityCombinationMethod =
predefinedMethods::OutputReliabilityCombinationMethodMin;
//--------------------------------------------------------------------------------
// helper function
/// very inefficient searchFunction
Functionblock (*searchFunction)(std::vector<Functionblock> vect,
const id_t nameA, const id_t nameB) =
[](std::vector<Functionblock> vect, const id_t nameA,
const id_t nameB) -> Functionblock {
for (Functionblock tmp : vect) {
if (tmp.A == nameA && tmp.B == nameB)
return tmp;
if (tmp.A == nameB && tmp.B == nameA)
return tmp;
}
return Functionblock();
};
/// evaluates the corresponding LinearFunction with the Identifier difference
/// \param nameA these two parameters are the unique identifiers
/// \param nameB these two parameters are the unique identifiers
/// for the LinerFunction
///
/// \note it doesn't matter if they are swapped
ReliabilityType getCrossReliabilityFromProfile(
const id_t &nameA, const id_t &nameB,
const IdentifierType &IdentifierDifference) noexcept {
Functionblock block = searchFunction(Functions, nameA, nameB);
if (!block.exists) {
LOG_ERROR(("CrossReliability: Block:" + std::to_string(nameA) + "," +
std::to_string(nameB) + "doesn't exist returning 0"));
return 0;
}
return block.Funct->operator()(IdentifierDifference);
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_CROSSCOMBINATOR_H
\ No newline at end of file
diff --git a/include/rosa/agent/FunctionAbstractions.hpp b/include/rosa/agent/FunctionAbstractions.hpp
index 2fa6912..b0c1ce4 100644
--- a/include/rosa/agent/FunctionAbstractions.hpp
+++ b/include/rosa/agent/FunctionAbstractions.hpp
@@ -1,364 +1,364 @@
//===-- 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 <algorithm>
#include <cmath>
#include <memory>
#include <vector>
namespace rosa {
namespace agent {
/// 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 <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<D>::value),
"LinearFunction not arithmetic T");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"LinearFunction not to arithmetic");
protected:
/// The Intercept of the linear function
- const D Intercept;
+ const R Intercept;
/// The Coefficient of the linear function
- const D Coefficient;
+ const R Coefficient;
public:
/// Creates an instance given the intercept and the coefficient of a linear
/// function.
///
/// \param Intercept the intercept of the linear function
/// \param Coefficient the coefficient of the linear function
- LinearFunction(D Intercept, D Coefficient) noexcept
+ LinearFunction(R Intercept, R Coefficient) noexcept
: Abstraction<D, R>(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
: Abstraction<D, R>(y1 - x1 * (y1 - y2) / (x1 - x2),
(y1 - y2) / (x1 - 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<D, R> p1, std::pair<D, R> p2) noexcept
: LinearFunction<D, R>(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<D, R> p1, std::pair<D, R> 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 <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<D>::value),
"SineFunction not arithmetic T");
STATIC_ASSERT((std::is_arithmetic<R>::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<D, R>(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 <typename D, typename R>
class StepFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::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<D, R>(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 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 <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<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::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<D, std::shared_ptr<Abstraction<D, R>>> 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::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;
/// 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);
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
diff --git a/include/rosa/agent/ReliabilityConfidenceCombinator.h b/include/rosa/agent/ReliabilityConfidenceCombinator.h
index 1d22046..bfc3f62 100644
--- a/include/rosa/agent/ReliabilityConfidenceCombinator.h
+++ b/include/rosa/agent/ReliabilityConfidenceCombinator.h
@@ -1,755 +1,755 @@
//===-- rosa/agent/ReliabilityConfidenceCombinator.h ------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/ReliabilityConfidenceCombinator.h
///
/// \author Daniel Schnoell (daniel.schnoell@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *ReliabilityConfidenceCombinator* *functionality*.
///
/// \note based on Maximilian Goetzinger (maxgot@utu.fi) code in
/// CAM_Dirty_include SA-EWS2_Version... inside Agent.cpp
///
/// \note By defining and setting Reliability_trace_level it is possible to
/// change the level to which it should be traced. \note All classes throw
/// runtime errors if not all things are set
///
/// \note should the Reliability be capped?
///
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_ReliabilityConfidenceCombinator_H
#define ROSA_AGENT_ReliabilityConfidenceCombinator_H
#include "rosa/core/forward_declarations.h" // needed for id_t
#include "rosa/support/log.h"
#include "rosa/agent/FunctionAbstractions.hpp"
#include "rosa/agent/Functionality.h"
#include "rosa/agent/RangeConfidence.hpp"
#include <algorithm>
#include <functional>
#include <type_traits>
#include <vector>
/// 0 everything
/// 1 vectors
/// 2 outputs
#define trace_everything 0
#define trace_vectors 1
#define trace_outputs 2
#ifndef Reliability_trace_level
#define Reliability_trace_level 0
#endif
#define trace_end "\n\n\n"
namespace rosa {
namespace agent {
/// This is a struct with a few methods that make Reliability Combinator
/// more readable \tparam IdentifierType The Data-type of the States \tparam
/// ReliabilityType The Data-type of the Reliability
/// \note this should/will be changed into a std::pair because it isn't needed
/// anymore
template <typename IdentifierType, typename ReliabilityType> struct ConfOrRel {
/// making both Template Arguments readable to make a few things easier
using _IdentifierType = IdentifierType;
/// making both Template Arguments readable to make a few things easier
using _ReliabilityType = ReliabilityType;
/// The actual place where the data is stored
IdentifierType Identifier;
/// The actual place where the data is stored
ReliabilityType Reliability;
ConfOrRel(IdentifierType _Identifier, ReliabilityType _Reliability)
: Identifier(_Identifier), Reliability(_Reliability){};
ConfOrRel(){};
/// Pushes the Data in a Human readable form
/// \param out The stream where it is written to
/// \param c The struct itself
friend std::ostream &operator<<(std::ostream &out, const ConfOrRel &c) {
out << "Identifier: " << c.Identifier << "\t Reliability: " << c.Reliability
<< " ";
return out;
}
/// needed or it throws an clang diagnosic error
using map =
std::map<IdentifierType, ReliabilityType>; // needed or it throws an
// clang diagnosic error
/// Filles the vector with the data inside the map
/// \param me The vector to be filled
/// \param data The data wich is to be pushed into the vector
friend std::vector<ConfOrRel> &operator<<(std::vector<ConfOrRel> &me,
map &&data) {
for (auto tmp : data) {
me.push_back(ConfOrRel(tmp.first, tmp.second));
#if Reliability_trace_level <= trace_everything
LOG_TRACE_STREAM << "\n" << ConfOrRel(tmp.first, tmp.second) << trace_end;
#endif
}
return me;
}
/// This is to push the data inside a vector in a human readable way into the
/// ostream \param out The ostream \param c The vector which is read
friend std::ostream &operator<<(std::ostream &out,
const std::vector<ConfOrRel> &c) {
std::size_t index = 0;
for (ConfOrRel data : c) {
out << index << " : " << data << "\n";
index++;
}
return out;
}
};
/// This is the combinator for Reliability and confidences it takes the
/// Sensor value, its "History" and feedback from \c
/// CrossCombinator to calculate different Reliabilities.
/// \tparam SensorValueType Data-type of the Sensor value ( Typically
/// double or float) \tparam IdentifierType Data-type of the State ( Typically
/// long or int)
/// \tparam ReliabilityType Data-type of the Reliability (
/// Typically double or float)
///
/// \note more information about how it calculates
/// the Reliabilities it should be considered feedback is a sort of Confidence
/// \verbatim
///----------------------------------------------------------------------------------
///
///
/// ->Reliability---> getInputReliability()
/// | |
/// | V
/// Sensor Value ---| PossibleIdentifierCombinationMethod -> next line
/// | A |
/// | | V
/// ->Confidence--- getPossibleIdentifiers()
///
///-----------------------------------------------------------------------------------
///
/// feedback
/// |
/// V
/// ValuesFromMaster
/// | -> History ---|
/// V | V
/// here -> FeedbackCombinatorMethod -------->HistoryCombinatorMethod->next line
/// | |
/// V V
/// getpossibleIdentifiersWithMasterFeedback()getPossibleIdentifiersWithHistory()
///
///----------------------------------------------------------------------------------
///
/// here -> sort -> most likely -> getmostLikelyIdentifierAndReliability()
///
///---------------------------------------------------------------------------------
/// \endverbatim
/// the mentioned methods are early outs so if two ore more of them are run in
/// the same step they will be interpreted as different time steps
/// <pre>
/// Default values for Combinators:
/// InputReliabilityCombinator = combinationMin;
/// PossibleIdentifierCombinationMethod=PossibleIdentifierCombinationMethodMin;
/// FeedbackCombinatorMethod = FeedbackCombinatorMethodAverage;
/// HistoryCombinatorMethod = HistoryCombinatorMethodMax;
/// </pre>
/// To understand the place where the combinator methods come into play a list
/// for each early exit and which Methods are used.
///
/// <pre>
/// \c getInputReliability():
/// -InputReliabilityCombinator
/// \c getPossibleIdentifiers():
/// -InputReliabilityCombinator
/// -PossibleIdentifierCombinationMethod
/// \c getpossibleIdentifiersWithMasterFeedback():
/// -InputReliabilityCombinator
/// -PossibleIdentifierCombinationMethod
/// -FeedbackCombinatorMethod
/// \c getPossibleIdentifiersWithHistory():
/// -InputReliabilityCombinator
/// -PossibleIdentifierCombinationMethod
/// -FeedbackCombinatorMethod
/// -HistoryCombinatorMethod
/// \c getmostLikelyIdentifierAndReliability():
/// -InputReliabilityCombinator
/// -PossibleIdentifierCombinationMethod
/// -FeedbackCombinatorMethod
/// -HistoryCombinatorMethod
/// </pre>
template <typename SensorValueType, typename IdentifierType,
typename ReliabilityType>
class ReliabilityAndConfidenceCombinator {
public:
static_assert(std::is_arithmetic<SensorValueType>::value,
"LowLevel: SensorValueType has to an arithmetic type\n");
static_assert(std::is_arithmetic<IdentifierType>::value,
"LowLevel: IdentifierType has to an arithmetic type\n");
static_assert(std::is_arithmetic<ReliabilityType>::value,
"LowLevel: ReliabilityType has to an arithmetic type\n");
/// Typedef to shorten the writing.
/// \c ConfOrRel
using ConfOrRel = ConfOrRel<IdentifierType, ReliabilityType>;
/// Calculates the input Reliability by combining Reliability of the Sensor
/// and the Slope Reliability \param SensorValue The sensor Value \note to set
/// the combination method \c setInputReliabilityCombinator()
ReliabilityType
getInputReliability(const SensorValueType &SensorValue) noexcept {
ReliabilityType inputReliability =
getReliability(SensorValue, previousSensorValue, valueSetCounter);
previousSensorValue = SensorValue;
PreviousSensorValueExists = true;
return inputReliability;
}
/// Calculates the possible Identifiers
/// \param SensorValue the Sensor Value
/// \brief it combines the input reliability and the confidence of the Sensor.
/// The use combination method can be set using \c
/// setPossibleIdentifierCombinationMethod()
std::vector<ConfOrRel>
getPossibleIdentifiers(const SensorValueType &SensorValue) noexcept {
std::vector<ConfOrRel> possibleIdentifiers;
ReliabilityType inputReliability = getInputReliability(SensorValue);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end;
#endif
possibleIdentifiers << Confidence->operator()(SensorValue);
possibleIdentifiers = PossibleIdentifierCombinationMethod(
possibleIdentifiers, inputReliability);
return possibleIdentifiers;
}
/// return the Possible Values with the feedback in mind
/// \param SensorValue The sensor Value
/// \brief it combines the input reliability and the confidence of the Sensor.
/// The combines them with FeedbackCombinatorMethod and returns the result.
std::vector<ConfOrRel> getpossibleIdentifiersWithMasterFeedback(
const SensorValueType &SensorValue) noexcept {
std::vector<ConfOrRel> possibleIdentifiers;
ReliabilityType inputReliability = getInputReliability(SensorValue);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end;
#endif
possibleIdentifiers << Confidence->operator()(SensorValue);
possibleIdentifiers = PossibleIdentifierCombinationMethod(
possibleIdentifiers, inputReliability);
possibleIdentifiers =
FeedbackCombinatorMethod(possibleIdentifiers, ValuesFromMaster);
return possibleIdentifiers;
}
/// returns all possible Identifiers and Reliabilities with the History in
/// mind \param SensorValue the Sensor value how this is done is described at
/// the class.
std::vector<ConfOrRel> getPossibleIdentifiersWithHistory(
const SensorValueType &SensorValue) noexcept {
std::vector<ConfOrRel> ActuallPossibleIdentifiers;
std::vector<ConfOrRel> possibleIdentifiers;
ReliabilityType inputReliability = getInputReliability(SensorValue);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end;
#endif
possibleIdentifiers << Confidence->operator()(SensorValue);
possibleIdentifiers = PossibleIdentifierCombinationMethod(
possibleIdentifiers, inputReliability);
possibleIdentifiers =
FeedbackCombinatorMethod(possibleIdentifiers, ValuesFromMaster);
saveInHistory(possibleIdentifiers);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\nActuallPossibleIdentifiers:\n"
<< possibleIdentifiers << trace_end;
LOG_TRACE_STREAM << "\npossibleIdentifiers:\n"
<< possibleIdentifiers << trace_end;
#endif
possibleIdentifiers.clear();
return getAllPossibleIdentifiersBasedOnHistory();
}
/// Calculates the Reliability
/// \param SensorValue The current Values of the Sensor
///
/// \return Reliability and Identifier of the current SensorValue
///
ConfOrRel getmostLikelyIdentifierAndReliability(
const SensorValueType &SensorValue) noexcept {
#if Reliability_trace_level <= trace_outputs
LOG_TRACE_STREAM << "\nTrace level is set to: " << Reliability_trace_level
<< "\n"
<< "Will trace: "
<< ((Reliability_trace_level == trace_outputs)
? "outputs"
: (Reliability_trace_level == trace_vectors)
? "vectors"
: (Reliability_trace_level ==
trace_everything)
? "everything"
: "undefined")
<< trace_end;
#endif
std::vector<ConfOrRel> ActuallPossibleIdentifiers;
std::vector<ConfOrRel> possibleIdentifiers;
ReliabilityType inputReliability = getInputReliability(SensorValue);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end;
#endif
possibleIdentifiers << Confidence->operator()(SensorValue);
possibleIdentifiers = PossibleIdentifierCombinationMethod(
possibleIdentifiers, inputReliability);
possibleIdentifiers =
FeedbackCombinatorMethod(possibleIdentifiers, ValuesFromMaster);
saveInHistory(possibleIdentifiers);
#if Reliability_trace_level <= trace_vectors
LOG_TRACE_STREAM << "\nActuallPossibleIdentifiers:\n"
<< possibleIdentifiers << trace_end;
LOG_TRACE_STREAM << "\npossibleIdentifiers:\n"
<< possibleIdentifiers << trace_end;
#endif
possibleIdentifiers.clear();
possibleIdentifiers = getAllPossibleIdentifiersBasedOnHistory();
std::sort(possibleIdentifiers.begin(), possibleIdentifiers.end(),
[](ConfOrRel A, ConfOrRel B) -> bool {
return A.Reliability > B.Reliability;
});
#if Reliability_trace_level <= trace_outputs
LOG_TRACE_STREAM << "\noutput lowlevel: " << possibleIdentifiers.at(0)
<< trace_end;
#endif
return possibleIdentifiers.at(0);
}
/// feedback for this functionality most commonly it comes from a Master Agent
- /// \param ValuesFromMaster The Identifiers + Reliability for the feedback
+ /// \param _ValuesFromMaster The Identifiers + Reliability for the feedback
/// \brief This input kind of resembles a confidence but not
/// directly it more or less says: compared to the other Identifiers inside
/// the System these are the Identifiers with the Reliability that you have.
void feedback(
const std::vector<ConfOrRel>
- &ValuesFromMaster) noexcept // it is being copied internally anyway
+ &_ValuesFromMaster) noexcept // it is being copied internally anyway
{
- this->ValuesFromMaster = ValuesFromMaster;
+ ValuesFromMaster = _ValuesFromMaster;
}
//
// ----------------------Reliability and Confidence Function setters----------
//
/// This is the setter for Confidence Function
- /// \param Confidence A pointer to the Functional for the \c Confidence of the
+ /// \param _Confidence A pointer to the Functional for the \c Confidence of the
/// Sensor value
void setConfidenceFunction(
std::shared_ptr<RangeConfidence<ReliabilityType, IdentifierType,
- SensorValueType>> &Confidence) noexcept {
- this->Confidence = Confidence;
+ SensorValueType>> &_Confidence) noexcept {
+ Confidence = _Confidence;
}
/// This is the setter for Reliability Function
- /// \param Reliability A pointer to the Functional for the Reliability
+ /// \param _Reliability A pointer to the Functional for the Reliability
/// \brief The Reliability takes the current Sensor value and return the
/// Reliability of the value.
void setReliabilityFunction(
std::shared_ptr<Abstraction<SensorValueType, ReliabilityType>>
- &Reliability) noexcept {
- this->Reliability = Reliability;
+ &_Reliability) noexcept {
+ Reliability = _Reliability;
}
/// This is the setter for ReliabilitySlope Function
- /// \param ReliabilitySlope A pointer to the Functional for the
+ /// \param _ReliabilitySlope A pointer to the Functional for the
/// ReliabilitySlope
/// \brief The ReliabilitySlope takes the difference of the current Sensor
/// Value to the last one and tells you how likely the change is.
void setReliabilitySlopeFunction(
std::shared_ptr<Abstraction<SensorValueType, ReliabilityType>>
- &ReliabilitySlope) noexcept {
- this->ReliabilitySlope = ReliabilitySlope;
+ &_ReliabilitySlope) noexcept {
+ ReliabilitySlope = _ReliabilitySlope;
}
/// This is the setter for TimeConfidence Function
- /// \param TimeConfidence A pointer to the Functional for the TimeConfidence
+ /// \param _TimeConfidence A pointer to the Functional for the TimeConfidence
/// \brief The time function takes the position in the History with greater
/// equals older and return a Reliability of how "relevant" it is.
void setTimeConfidenceFunction(
std::shared_ptr<Abstraction<std::size_t, ReliabilityType>>
- &TimeConfidence) noexcept {
- this->TimeConfidence = TimeConfidence;
+ &_TimeConfidence) noexcept {
+ TimeConfidence = _TimeConfidence;
}
/// This is the setter for all possible States
/// \param states A vector containing all states
/// \brief This exists even though \c State Type is an arithmetic Type because
/// the states do not need to be "next" to each other ( ex. states={ 1 7 24 })
void setStates(const std::vector<IdentifierType> &states) noexcept {
this->States = states;
}
/// This sets the Maximum length of the History
/// \param length The length
void setHistoryLength(const std::size_t &length) noexcept {
this->HistoryMaxSize = length;
}
/// This sets the Value set Counter
/// \param ValueSetCounter the new Value
/// \note This might actually be only an artifact. It is only used to get the
/// reliability from the \c ReliabilitySlope [ ReliabilitySlope->operator()(
/// (lastValue - actualValue) / (SensorValueType)valueSetCounter) ]
void setValueSetCounter(const unsigned int &ValueSetCounter) noexcept {
this->valueSetCounter = ValueSetCounter;
}
//
// ----------------combinator setters-----------------------------------------
//
/// This sets the combination method used by the History
/// \param Meth the method which should be used. predefined inside the \c
/// predefinedMethods struct HistoryCombinatorMethod<method>()
void setHistoryCombinatorMethod(
const std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
&Meth) noexcept {
HistoryCombinatorMethod = Meth;
}
/// sets the predefined method for the combination of the possible Identifiers
/// and the master
/// \param Meth the method which should be used. predefined inside the \c
/// predefinedMethods struct FeedbackCombinatorMethod<method>()
void setFeedbackCombinatorMethod(
const std::function<std::vector<ConfOrRel>(
std::vector<ConfOrRel>, std::vector<ConfOrRel>)> &Meth) noexcept {
FeedbackCombinatorMethod = Meth;
}
/// Sets the used combination method for Possible Identifiers
/// \param Meth the method which should be used. predefined inside the \c
/// predefinedMethods struct PossibleIdentifierCombinationMethod<method>()
void setPossibleIdentifierCombinationMethod(
const std::function<std::vector<ConfOrRel>(
std::vector<ConfOrRel>, ReliabilityType)> &Meth) noexcept {
PossibleIdentifierCombinationMethod = Meth;
}
/// sets the input reliability combinator method
/// \param method the method which should be used. predefined inside the \c
/// predefinedMethods struct combination<method>()
void setInputReliabilityCombinator(
const std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
&&method) noexcept {
InputReliabilityCombinator = method;
}
//
// ----------------predefined combinators------------------------------------
//
/// This struct is a pseudo name space to have easier access to all predefined
/// methods while still not overcrowding the class it self
struct predefinedMethods {
/// predefined Method
static ReliabilityType
HistoryCombinatorMethodMin(ReliabilityType A, ReliabilityType B) noexcept {
return std::min(A, B);
}
/// predefined Method
static ReliabilityType
HistoryCombinatorMethodMax(ReliabilityType A, ReliabilityType B) noexcept {
return std::max(A, B);
}
/// predefined Method
static ReliabilityType
HistoryCombinatorMethodMult(ReliabilityType A, ReliabilityType B) noexcept {
return A * B;
}
/// predefined Method
static ReliabilityType
HistoryCombinatorMethodAverage(ReliabilityType A,
ReliabilityType B) noexcept {
return (A + B) / 2;
}
/// predefined method
static std::vector<ConfOrRel>
FeedbackCombinatorMethodAverage(std::vector<ConfOrRel> A,
std::vector<ConfOrRel> B) noexcept {
for (auto &tmp_me : A)
for (auto &tmp_other : B) {
if (tmp_me.Identifier == tmp_other.Identifier) {
tmp_me.Reliability =
(tmp_me.Reliability + tmp_other.Reliability) / 2;
}
}
return A;
}
/// predefined method
static std::vector<ConfOrRel>
FeedbackCombinatorMethodMin(std::vector<ConfOrRel> A,
std::vector<ConfOrRel> B) noexcept {
for (auto &tmp_me : A)
for (auto &tmp_other : B) {
if (tmp_me.Identifier == tmp_other.Identifier) {
tmp_me.Reliability =
std::min(tmp_me.Reliability + tmp_other.Reliability);
}
}
return A;
}
/// predefined method
static std::vector<ConfOrRel>
FeedbackCombinatorMethodMax(std::vector<ConfOrRel> A,
std::vector<ConfOrRel> B) noexcept {
for (auto &tmp_me : A)
for (auto &tmp_other : B) {
if (tmp_me.Identifier == tmp_other.Identifier) {
tmp_me.Reliability =
std::max(tmp_me.Reliability + tmp_other.Reliability);
}
}
return A;
}
/// predefined method
static std::vector<ConfOrRel>
FeedbackCombinatorMethodMult(std::vector<ConfOrRel> A,
std::vector<ConfOrRel> B) noexcept {
for (auto &tmp_me : A)
for (auto &tmp_other : B) {
if (tmp_me.Identifier == tmp_other.Identifier) {
tmp_me.Reliability = tmp_me.Reliability * tmp_other.Reliability;
}
}
return A;
}
/// Predefined combination method for possible Identifiers
static std::vector<ConfOrRel>
PossibleIdentifierCombinationMethodMin(std::vector<ConfOrRel> A,
ReliabilityType B) noexcept {
for (auto tmp : A)
tmp.Reliability = std::min(tmp.Reliability, B);
return A;
}
/// Predefined combination method for possible Identifiers
static std::vector<ConfOrRel>
PossibleIdentifierCombinationMethodMax(std::vector<ConfOrRel> A,
ReliabilityType B) noexcept {
for (auto tmp : A)
tmp.Reliability = std::max(tmp.Reliability, B);
return A;
}
/// Predefined combination method for possible Identifiers
static std::vector<ConfOrRel>
PossibleIdentifierCombinationMethodAverage(std::vector<ConfOrRel> A,
ReliabilityType B) noexcept {
for (auto tmp : A)
tmp.Reliability = (tmp.Reliability + B) / 2;
return A;
}
/// Predefined combination method for possible Identifiers
static std::vector<ConfOrRel>
PossibleIdentifierCombinationMethodMult(std::vector<ConfOrRel> A,
ReliabilityType B) noexcept {
for (auto tmp : A)
tmp.Reliability = tmp.Reliability * B / 2;
return A;
}
/// The predefined min combinator method
static ReliabilityType combinationMin(ReliabilityType A,
ReliabilityType B) noexcept {
return std::min(A, B);
}
/// The predefined max combinator method
static ReliabilityType combinationMax(ReliabilityType A,
ReliabilityType B) noexcept {
return std::max(A, B);
}
/// The predefined average combinator method
static ReliabilityType combinationAverage(ReliabilityType A,
ReliabilityType B) noexcept {
return (A + B) / 2;
}
/// The predefined average combinator method
static ReliabilityType combinationMult(ReliabilityType A,
ReliabilityType B) noexcept {
return A * B;
}
};
// ----------------------------------------------------------------
// Stored Values
// ----------------------------------------------------------------
private:
std::vector<std::vector<ConfOrRel>> History;
std::size_t HistoryMaxSize;
std::vector<ConfOrRel> ValuesFromMaster;
SensorValueType previousSensorValue;
unsigned int valueSetCounter;
std::vector<IdentifierType> States;
bool PreviousSensorValueExists = false;
std::shared_ptr<
RangeConfidence<ReliabilityType, IdentifierType, SensorValueType>>
Confidence;
std::shared_ptr<Abstraction<SensorValueType, ReliabilityType>> Reliability;
std::shared_ptr<Abstraction<SensorValueType, ReliabilityType>>
ReliabilitySlope;
std::shared_ptr<Abstraction<std::size_t, ReliabilityType>> TimeConfidence;
// combination functions
std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
InputReliabilityCombinator = predefinedMethods::combinationMin;
std::function<std::vector<ConfOrRel>(std::vector<ConfOrRel>, ReliabilityType)>
PossibleIdentifierCombinationMethod =
predefinedMethods::PossibleIdentifierCombinationMethodMin;
std::function<std::vector<ConfOrRel>(std::vector<ConfOrRel>,
std::vector<ConfOrRel>)>
FeedbackCombinatorMethod =
predefinedMethods::FeedbackCombinatorMethodAverage;
std::function<ReliabilityType(ReliabilityType, ReliabilityType)>
HistoryCombinatorMethod = predefinedMethods::HistoryCombinatorMethodMax;
// ---------------------------------------------------------------------------
// needed Functions
// ---------------------------------------------------------------------------
/// returns the Reliability
/// \param actualValue The Value of the Sensor
/// \param lastValue of the Sensor this is stored in the class
- /// \param valueSetCounter It has an effect on the difference of the current
+ /// \param _valueSetCounter It has an effect on the difference of the current
/// and last value This might not be needed anymore
/// \brief it returns the combination the \c Reliability function and \c
/// ReliabilitySlope if the previous value exists. if it doesn't it only
/// returns the \c Reliability function value.
ReliabilityType getReliability(const SensorValueType &actualValue,
const SensorValueType &lastValue,
- const unsigned int &valueSetCounter) noexcept {
+ const unsigned int &_valueSetCounter) noexcept {
ReliabilityType relAbs = Reliability->operator()(actualValue);
if (PreviousSensorValueExists) {
ReliabilityType relSlo = ReliabilitySlope->operator()(
- (lastValue - actualValue) / (SensorValueType)valueSetCounter);
+ (lastValue - actualValue) / (SensorValueType)_valueSetCounter);
return InputReliabilityCombinator(relAbs, relSlo);
} else
return relAbs;
}
/// adapts the possible Identifiers by checking the History and combines those
/// values.
/// \brief combines the historic values with the \c TimeConfidence function
/// and returns the maximum Reliability for all Identifiers.
std::vector<ConfOrRel> getAllPossibleIdentifiersBasedOnHistory() noexcept {
// iterate through all history entries
std::size_t posInHistory = 0;
std::vector<ConfOrRel> possibleIdentifiers;
for (auto pShE = History.begin(); pShE < History.end();
pShE++, posInHistory++) {
// iterate through all possible Identifiers of each history entry
for (ConfOrRel &pSh : *pShE) {
IdentifierType historyIdentifier = pSh.Identifier;
ReliabilityType historyConf = pSh.Reliability;
historyConf = historyConf * TimeConfidence->operator()(posInHistory);
bool foundIdentifier = false;
for (ConfOrRel &pS : possibleIdentifiers) {
if (pS.Identifier == historyIdentifier) {
pS.Reliability =
HistoryCombinatorMethod(pS.Reliability, historyConf);
foundIdentifier = true;
}
}
if (foundIdentifier == false) {
ConfOrRel possibleIdentifier;
possibleIdentifier.Identifier = historyIdentifier;
possibleIdentifier.Reliability = historyConf;
possibleIdentifiers.push_back(possibleIdentifier);
}
}
}
return possibleIdentifiers;
}
/// saves the Identifiers in the History
/// \brief It checks the incoming Identifiers if any have a Reliability
/// greater than 0.5 all of them get saved inside the History and then the
/// History get shortened to the maximal length. It only saves the Value if
/// the History is empty.
///
/// \param actualPossibleIdentifiers The Identifiers which should be saved
///
/// \note Does the History really make sense if the values are to small it
/// only stores something if it's empty and not if it isn't completely filled
void saveInHistory(
const std::vector<ConfOrRel> &actualPossibleIdentifiers) noexcept {
// check if the reliability of at least one possible Identifier is high
// enough
bool atLeastOneRelIsHigh = false;
for (ConfOrRel pS : actualPossibleIdentifiers) {
if (pS.Reliability > 0.5) {
atLeastOneRelIsHigh = true;
}
}
// save possible Identifiers if at least one possible Identifier is high
// enough (or if the history is empty)
if (History.size() < 1 || atLeastOneRelIsHigh == true) {
History.insert(History.begin(), actualPossibleIdentifiers);
// if history size is higher than allowed, save oldest element
while (History.size() > HistoryMaxSize) {
// delete possibleIdentifierHistory.back();
History.pop_back();
}
}
}
};
} // namespace agent
} // namespace rosa
#endif // !ROSA_AGENT_ReliabilityConfidenceCombinator_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 12:56 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157164
Default Alt Text
(64 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment