diff --git a/include/rosa/agent/CrossCombinator.h b/include/rosa/agent/CrossCombinator.h index 679cbc1..9f612a4 100644 --- a/include/rosa/agent/CrossCombinator.h +++ b/include/rosa/agent/CrossCombinator.h @@ -1,558 +1,560 @@ //===-- rosa/delux/CrossCombinator.h ----------------------------*- 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/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/agent/LikelinessConfidenceCombinator.h" #include "rosa/core/forward_declarations.h" // needed for id_t #include "rosa/support/log.h" // needed for error "handling" // nedded headers #include #include //assert #include // for static methods #include #include namespace rosa { namespace agent { -template +template std::vector> &operator<<( std::vector> &me, - std::vector> Values) { + std::vector> Values) { for (auto tmp : Values) { std::pair 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 +/// calculates the Likeliness of them together. Also it can creates the +/// feedback that is needed by the \c LikelinessAndConfidenceCombinator, 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 +/// or float) \tparam LikelinessType Data type of the Likeliness ( 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 +/// \c LikelinessAndConfidenceCombinator. The \c operator()() combines the +/// Likeliness of all connected Slaves and uses that as its own Likeliness /// 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 ] +/// \note more information about how the Likeliness and feedback is +/// created at \c operator()() , \c getCombinedCrossLikeliness() , \c +/// getCombinedInputLikeliness() , \c getOutputLikeliness() [ this is the +/// used Likeliness ], \c getCrossConfidence() [ this is the feedback +/// for all Compares ] /// -/// a bit more special Methods \c CrossConfidence() ,\c CrossReliability() -template +/// a bit more special Methods \c CrossConfidence() ,\c CrossLikeliness() +template class CrossCombinator { public: static_assert(std::is_arithmetic::value, "HighLevel: IdentifierType has to be an arithmetic type\n"); - static_assert(std::is_arithmetic::value, - "HighLevel: ReliabilityType has to be an arithmetic type\n"); + static_assert(std::is_arithmetic::value, + "HighLevel: LikelinessType has to be an arithmetic type\n"); // --------------------------------------------------------------------------- // useful definitions // --------------------------------------------------------------------------- /// typedef To shorten the writing. - /// \c ConfOrRel - using ConfOrRel = ConfOrRel; + /// \c Symbol + using Symbol = Symbol; /// To shorten the writing. using Abstraction = - typename rosa::agent::Abstraction; + typename rosa::agent::Abstraction; /// The return type for the \c operator()() Method struct returnType { - ReliabilityType CrossReliability; - std::map> CrossConfidence; + LikelinessType CrossLikeliness; + std::map> Likeliness; }; // ------------------------------------------------------------------------- // Relevant Methods // ------------------------------------------------------------------------- - /// Calculates the Reliability and the CrossConfidences for each id for all + /// Calculates the CrossLikeliness and the Likeliness for each id for all /// of there Identifiers. /// /// \param Values It gets the Identifiers and Reliabilities of - /// all connected Slaves inside a vector. + /// all connected Compare Agentss inside a vector. /// /// \return it returns a struct \c returnType containing the \c - /// getCombinedCrossReliability() and \c getCrossConfidence() + /// getCombinedCrossLikeliness() and \c getCrossConfidence() returnType operator()( - std::vector> Values) { - return {getOutputReliability(Values), getCrossConfidence(Values)}; + std::vector> Values) { + return {getOutputLikeliness(Values), getCrossConfidence(Values)}; } - /// returns the combined Cross Reliability via \c + /// returns the combined Cross Likeliness via \c /// CombinedCrossRelCombinationMethod \c /// setCombinedCrossRelCombinationMethod() for all ids \c - /// CrossReliability() \param Values the used Values - ReliabilityType getCombinedCrossReliability( - const std::vector> + /// CrossLikeliness() \param Values the used Values + LikelinessType getCombinedCrossLikeliness( + const std::vector> &Values) noexcept { - ReliabilityType combinedCrossRel = -1; + LikelinessType combinedCrossRel = -1; std::vector> 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); + // calculate the cross Likeliness for this Compare agent + LikelinessType realCrossLikelinessOfCompareInput = + CrossLikeliness({id, sc}, Agents); if (combinedCrossRel != -1) combinedCrossRel = CombinedCrossRelCombinationMethod( - combinedCrossRel, realCrossReliabilityOfSlaveAgent); + combinedCrossRel, realCrossLikelinessOfCompareInput); else - combinedCrossRel = realCrossReliabilityOfSlaveAgent; + combinedCrossRel = realCrossLikelinessOfCompareInput; } return combinedCrossRel; } /// returns the combined via \c CombinedInputRelCombinationMethod \c - /// setCombinedInputRelCombinationMethod() input reliability \param Values + /// setCombinedInputRelCombinationMethod() input Likeliness \param Values /// the used Values - ReliabilityType getCombinedInputReliability( - const std::vector> + LikelinessType getCombinedInputLikeliness( + const std::vector> &Values) noexcept { - ReliabilityType combinedInputRel = -1; + LikelinessType combinedInputRel = -1; std::vector> Agents; Agents << Values; for (auto Value : Values) { - ReliabilityType rel = std::get<2>(Value); + LikelinessType 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> + /// returns the combination via \c OutputLikelinessCombinationMethod \c + /// setOutputLikelinessCombinationMethod() of the Cross Likeliness and + /// input Likeliness \param Values the used Values + LikelinessType getOutputLikeliness( + const std::vector> &Values) noexcept { - return OutputReliabilityCombinationMethod( - getCombinedInputReliability(Values), - getCombinedCrossReliability(Values)); + return OutputLikelinessCombinationMethod( + getCombinedInputLikeliness(Values), + getCombinedCrossLikeliness(Values)); } /// returns the crossConfidence for all ids \c CrossConfidence() /// \param Values the used Values - std::map> getCrossConfidence( - const std::vector> + std::map> getCrossConfidence( + const std::vector> &Values) noexcept { std::vector> Agents; - std::map> output; - std::vector output_temporary; + std::map> output; + std::vector 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; + Symbol data; data.Identifier = thoIdentifier; - data.Reliability = CrossConfidence(id, thoIdentifier, Agents); + data.Likeliness = 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 + /// \note all combination of agents and there corresponding Cross Likeliness /// function have to be specified - ReliabilityType + LikelinessType CrossConfidence(const id_t &MainAgent, const IdentifierType &TheoreticalValue, const std::vector> - &SlaveAgents) noexcept { + &CompareInputs) noexcept { - ReliabilityType crossReliabiability; + LikelinessType crossReliabiability; - std::vector values; + std::vector values; - for (std::pair SlaveAgent : SlaveAgents) { + for (std::pair CompareInput : CompareInputs) { - if (SlaveAgent.first == MainAgent) + if (CompareInput.first == MainAgent) continue; - if (TheoreticalValue == SlaveAgent.second) + if (TheoreticalValue == CompareInput.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)); + 1 / (crossLikelinessParameter * + std::abs(TheoreticalValue - CompareInput.second)); + + // profile Likeliness + LikelinessType crossLikelinessFromProfile = + getCrossLikelinessFromProfile( + MainAgent, CompareInput.first, + std::abs(TheoreticalValue - CompareInput.second)); values.push_back( - std::max(crossReliabiability, crossReliabilityFromProfile)); + std::max(crossReliabiability, crossLikelinessFromProfile)); } return Method(values); } - /// Calculates the Cross Reliability + /// Calculates the Cross Likeliness /// \brief it uses the Identifier value and calculates - /// the Reliability of a given agent( represented by their id ) in connection + /// the Likeliness 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 + /// \note all combination of agents and there corresponding Cross Likeliness /// function have to be specified - ReliabilityType - CrossReliability(const std::pair &MainAgent, + LikelinessType + CrossLikeliness(const std::pair &MainAgent, const std::vector> - &SlaveAgents) noexcept { + &CompareInputs) noexcept { - ReliabilityType crossReliabiability; - std::vector values; + LikelinessType crossReliabiability; + std::vector values; - for (std::pair SlaveAgent : SlaveAgents) { + for (std::pair CompareInput : CompareInputs) { - if (SlaveAgent.first == MainAgent.first) + if (CompareInput.first == MainAgent.first) continue; - if (MainAgent.second == SlaveAgent.second) + if (MainAgent.second == CompareInput.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)); + 1 / (crossLikelinessParameter * + std::abs(MainAgent.second - CompareInput.second)); + + // profile Likeliness + LikelinessType crossLikelinessFromProfile = + getCrossLikelinessFromProfile( + MainAgent.first, CompareInput.first, + std::abs(MainAgent.second - CompareInput.second)); values.push_back( - std::max(crossReliabiability, crossReliabilityFromProfile)); + std::max(crossReliabiability, crossLikelinessFromProfile)); } return Method(values); } // -------------------------------------------------------------------------- // Defining the class // -------------------------------------------------------------------------- - /// adds a Cross Reliability Profile used to get the Reliability of the + /// adds a Cross Likeliness Profile used to get the Likeliness 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( + void addCrossLikelinessProfile( //conf const id_t &idA, const id_t &idB, const std::shared_ptr &Function) noexcept { - Functions.push_back({true, idA, idB, Function}); + Functions.push_back({true, idA, idB, Function}); //confidence Profiles } - /// sets the cross reliability parameter - void setCrossReliabilityParameter(const ReliabilityType &val) noexcept { - crossReliabilityParameter = val; + /// sets the cross Likeliness parameter + void setCrossLikelinessParameter(const LikelinessType &val) noexcept { + crossLikelinessParameter = 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 - /// 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 + /// Compares have different Identifiers they can be used correctly. \brief The + /// Identifiers of all connected Compare Agents has to be known to be able to /// iterate over them void - addIdentifiers(const id_t &id, + addIdentifiers(const id_t &id, //add IdentifierIdentifiers const std::vector &_Identifiers) noexcept { Identifiers.insert({id, _Identifiers}); } // ------------------------------------------------------------------------- // Combinator Settings // ------------------------------------------------------------------------- + // remove Method + /// 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 values)> + void setCrossLikelinessCombinatorMethod( + const std::function values)> &Meth) noexcept { Method = Meth; } - /// sets the combination method for the combined cross reliability + /// sets the combination method for the combined cross Likeliness /// \param Meth the method which should be used. predefined functions in the /// struct \c predefinedMethods CombinedCrossRelCombinationMethod() void setCombinedCrossRelCombinationMethod( - const std::function + const std::function &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() void setCombinedInputRelCombinationMethod( - const std::function + const std::function &Meth) noexcept { CombinedInputRelCombinationMethod = Meth; } - /// sets the used OutputReliabilityCombinationMethod + /// sets the used OutputLikelinessCombinationMethod /// \param Meth the method which should be used. predefined functions in the - /// struct \c predefinedMethods OutputReliabilityCombinationMethod() - void setOutputReliabilityCombinationMethod( - const std::function + /// struct \c predefinedMethods OutputLikelinessCombinationMethod() + void setOutputLikelinessCombinationMethod( + const std::function &Meth) noexcept { - OutputReliabilityCombinationMethod = Meth; + OutputLikelinessCombinationMethod = 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 values) { + static LikelinessType CONJUNCTION(std::vector values) { return *std::min_element(values.begin(), values.end()); } /// predefined combination method - static ReliabilityType AVERAGE(std::vector values) { + static LikelinessType AVERAGE(std::vector values) { return std::accumulate(values.begin(), values.end(), 0.0) / values.size(); } /// predefined combination method - static ReliabilityType DISJUNCTION(std::vector values) { + static LikelinessType DISJUNCTION(std::vector values) { return *std::max_element(values.begin(), values.end()); } /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) { + static LikelinessType + CombinedCrossRelCombinationMethodMin(LikelinessType A, LikelinessType B) { return std::min(A, B); } /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { + static LikelinessType + CombinedCrossRelCombinationMethodMax(LikelinessType A, LikelinessType B) { return std::max(A, B); } /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodMult(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + CombinedCrossRelCombinationMethodMult(LikelinessType A, + LikelinessType B) { return A * B; } /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + CombinedCrossRelCombinationMethodAverage(LikelinessType A, + LikelinessType B) { return (A + B) / 2; } /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) { + static LikelinessType + CombinedInputRelCombinationMethodMin(LikelinessType A, LikelinessType B) { return std::min(A, B); } /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { + static LikelinessType + CombinedInputRelCombinationMethodMax(LikelinessType A, LikelinessType B) { return std::max(A, B); } /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMult(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + CombinedInputRelCombinationMethodMult(LikelinessType A, + LikelinessType B) { return A * B; } /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + CombinedInputRelCombinationMethodAverage(LikelinessType A, + LikelinessType B) { return (A + B) / 2; } /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMin(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + OutputLikelinessCombinationMethodMin(LikelinessType A, + LikelinessType B) { return std::min(A, B); } /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMax(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + OutputLikelinessCombinationMethodMax(LikelinessType A, + LikelinessType B) { return std::max(A, B); } /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMult(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + OutputLikelinessCombinationMethodMult(LikelinessType A, + LikelinessType B) { return A * B; } /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { + static LikelinessType + OutputLikelinessCombinationMethodAverage(LikelinessType A, + LikelinessType 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 Funct; }; std::map> Identifiers; /// From Maxi in his code defined as 1 can be changed by set - ReliabilityType crossReliabilityParameter = 1; + LikelinessType crossLikelinessParameter = 1; - /// Stored Cross Reliability Functions + /// Stored Cross Likeliness Functions std::vector Functions; /// Method which is used to combine the generated values - std::function)> Method = + std::function)> Method = predefinedMethods::AVERAGE; - std::function + std::function CombinedCrossRelCombinationMethod = predefinedMethods::CombinedCrossRelCombinationMethodMin; - std::function + std::function CombinedInputRelCombinationMethod = predefinedMethods::CombinedInputRelCombinationMethodMin; - std::function - OutputReliabilityCombinationMethod = - predefinedMethods::OutputReliabilityCombinationMethodMin; + std::function + OutputLikelinessCombinationMethod = + predefinedMethods::OutputLikelinessCombinationMethodMin; //-------------------------------------------------------------------------------- // helper function /// very inefficient searchFunction Functionblock (*searchFunction)(std::vector vect, const id_t nameA, const id_t nameB) = [](std::vector 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 + /// \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( + LikelinessType getCrossLikelinessFromProfile( 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) + "," + + LOG_ERROR(("CrossLikeliness: 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/ReliabilityConfidenceCombinator.h b/include/rosa/agent/ReliabilityConfidenceCombinator.h index f8a2074..d9b8a61 100644 --- a/include/rosa/agent/ReliabilityConfidenceCombinator.h +++ b/include/rosa/agent/ReliabilityConfidenceCombinator.h @@ -1,761 +1,761 @@ //===-- rosa/agent/ReliabilityConfidenceCombinator.h ------------*- 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/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 #include #include #include /// 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 Likeliness Combinator /// more readable \tparam IdentifierType The Data-type of the Identifiers \tparam /// LikelinessType The Data-type of the Likeliness /// \note this should/will be changed into a std::pair because it isn't needed /// anymore template struct Symbol { /// 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 _LikelinessType = LikelinessType; /// The actual place where the data is stored IdentifierType Identifier; /// The actual place where the data is stored LikelinessType Likeliness; Symbol(IdentifierType _Identifier, LikelinessType _Likeliness) : Identifier(_Identifier), Likeliness(_Likeliness){}; Symbol(){}; /// 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 Symbol &c) { out << "Identifier: " << c.Identifier << "\t Likeliness: " << c.Likeliness << " "; return out; } /// needed or it throws an clang diagnosic error using map = std::map; // 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 &operator<<(std::vector &me, map &&data) { for (auto tmp : data) { me.push_back(Symbol(tmp.first, tmp.second)); #if Reliability_trace_level <= trace_everything LOG_TRACE_STREAM << "\n" << Symbol(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 &c) { std::size_t index = 0; for (Symbol data : c) { out << index << " : " << data << "\n"; index++; } return out; } }; /// This is the combinator for Reliability and confidences it takes the /// Value, its "History" and feedback from \c /// CrossCombinator to calculate different Reliabilities. /// \tparam ValueType Data-type of the Value ( Typically /// double or float) \tparam IdentifierType Data-type of the Identifier ( 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 ///---------------------------------------------------------------------------------- /// /// /// ->AbsoluteReliabilityFunction---> getInputReliability() /// | | /// | V -/// Sensor Value ---| PossibleIdentifierCombinationMethod -> next line +/// Sensor Value ---| ReliabilityAndConfidenceCombinator -> next line /// | A | /// | | V -/// ->ConfidenceFunction--- getPossibleIdentifiers() +/// ->ConfidenceFunction getPossibleIdentifiers() /// ///----------------------------------------------------------------------------------- /// /// feedback /// | /// V /// FeedbackSymbols -/// | -> History ---| -/// V | V -/// here -> LikelinessFeedbackCombinator -------->LikelinessHistoryCombinator->next line +/// | -> History -------| +/// V | V +/// here -> LikelinessFeedbackCombinator ------>LikelinessHistoryCombinator->next line /// | | /// V V -/// getpossibleIdentifiersWithMasterFeedback()SymbolsWithHistory() +/// getpossibleIdentifiersWithMasterFeedback() SymbolsWithHistory() /// ///---------------------------------------------------------------------------------- /// /// here -> sort -> most likely -> bestSymbol() /// ///--------------------------------------------------------------------------------- /// \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 ///
 /// Default values for Combinators:
-///	InputReliabilityCombinator		= combinationMin;
-///	PossibleIdentifierCombinationMethod=PossibleIdentifierCombinationMethodMin;
+///	AbsoluteAndSlopeReliabilityCombinationMethod		= combinationMin;
+///	ReliabilityAndConfidenceCombinator=ReliabilityAndConfidenceCombinatorMin;
 /// LikelinessFeedbackCombinator		= LikelinessFeedbackCombinatorAverage;
 /// LikelinessHistoryCombinator			= LikelinessHistoryCombinatorMax;
 ///	
/// To understand the place where the combinator methods come into play a list /// for each early exit and which Methods are used. /// ///
 /// \c getInputReliability():
-///		-InputReliabilityCombinator
+///		-AbsoluteAndSlopeReliabilityCombinationMethod
 /// \c getPossibleIdentifiers():
-///		-InputReliabilityCombinator
-///		-PossibleIdentifierCombinationMethod
+///		-AbsoluteAndSlopeReliabilityCombinationMethod
+///		-ReliabilityAndConfidenceCombinator
 /// \c getpossibleIdentifiersWithMasterFeedback():
-///		-InputReliabilityCombinator
-///		-PossibleIdentifierCombinationMethod
+///		-AbsoluteAndSlopeReliabilityCombinationMethod
+///		-ReliabilityAndConfidenceCombinator
 ///		-LikelinessFeedbackCombinator
 /// \c SymbolsWithHistory():
-///		-InputReliabilityCombinator
-///		-PossibleIdentifierCombinationMethod
+///		-AbsoluteAndSlopeReliabilityCombinationMethod
+///		-ReliabilityAndConfidenceCombinator
 ///		-LikelinessFeedbackCombinator
 ///		-LikelinessHistoryCombinator
 /// \c bestSymbol():
-///		-InputReliabilityCombinator
-///		-PossibleIdentifierCombinationMethod
+///		-AbsoluteAndSlopeReliabilityCombinationMethod
+///		-ReliabilityAndConfidenceCombinator
 ///		-LikelinessFeedbackCombinator
 ///		-LikelinessHistoryCombinator
 /// 
template class ReliabilityAndConfidenceCombinator { public: static_assert(std::is_arithmetic::value, "LowLevel: ValueType has to an arithmetic type\n"); static_assert(std::is_arithmetic::value, "LowLevel: IdentifierType has to an arithmetic type\n"); static_assert(std::is_arithmetic::value, "LowLevel: ReliabilityType has to an arithmetic type\n"); /// Typedef to shorten the writing. /// \c Symbol using Symbol = Symbol; /// 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() + /// the combination method \c setAbsoluteAndSlopeReliabilityCombinationMethod() ReliabilityType getInputReliability(const ValueType &SensorValue) noexcept { ReliabilityType inputReliability = getReliability(SensorValue, previousSensorValue, timeStep); 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() + /// setReliabilityAndConfidenceCombinator() std::vector getPossibleIdentifiers(const ValueType &SensorValue) noexcept { std::vector possibleIdentifiers; ReliabilityType inputReliability = getInputReliability(SensorValue); #if Reliability_trace_level <= trace_vectors LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end; #endif possibleIdentifiers << ConfidenceFunction->operator()(SensorValue); - possibleIdentifiers = PossibleIdentifierCombinationMethod( + possibleIdentifiers = ReliabilityAndConfidenceCombinator( 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 LikelinessFeedbackCombinator and returns the result. std::vector getpossibleIdentifiersWithMasterFeedback( const ValueType &SensorValue) noexcept { std::vector possibleIdentifiers; ReliabilityType inputReliability = getInputReliability(SensorValue); #if Reliability_trace_level <= trace_vectors LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end; #endif possibleIdentifiers << ConfidenceFunction->operator()(SensorValue); - possibleIdentifiers = PossibleIdentifierCombinationMethod( + possibleIdentifiers = ReliabilityAndConfidenceCombinator( possibleIdentifiers, inputReliability); possibleIdentifiers = LikelinessFeedbackCombinator(possibleIdentifiers, FeedbackSymbols); 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 SymbolsWithHistory( const ValueType &SensorValue) noexcept { std::vector ActuallPossibleIdentifiers; std::vector possibleIdentifiers; ReliabilityType inputReliability = getInputReliability(SensorValue); #if Reliability_trace_level <= trace_vectors LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end; #endif possibleIdentifiers << ConfidenceFunction->operator()(SensorValue); - possibleIdentifiers = PossibleIdentifierCombinationMethod( + possibleIdentifiers = ReliabilityAndConfidenceCombinator( possibleIdentifiers, inputReliability); possibleIdentifiers = LikelinessFeedbackCombinator(possibleIdentifiers, FeedbackSymbols); 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 SymbolsFromHistory(); } /// Calculates the Reliability /// \param SensorValue The current Values of the Sensor /// /// \return Reliability and Identifier of the current SensorValue /// Symbol bestSymbol( const ValueType &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 ActuallPossibleIdentifiers; std::vector possibleIdentifiers; ReliabilityType inputReliability = getInputReliability(SensorValue); #if Reliability_trace_level <= trace_vectors LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end; #endif possibleIdentifiers << ConfidenceFunction->operator()(SensorValue); - possibleIdentifiers = PossibleIdentifierCombinationMethod( + possibleIdentifiers = ReliabilityAndConfidenceCombinator( possibleIdentifiers, inputReliability); possibleIdentifiers = LikelinessFeedbackCombinator(possibleIdentifiers, FeedbackSymbols); 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 = SymbolsFromHistory(); std::sort(possibleIdentifiers.begin(), possibleIdentifiers.end(), [](Symbol A, Symbol B) -> bool { return A.Likeliness > B.Likeliness; }); #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 _FeedbackSymbols 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 &_FeedbackSymbols) noexcept // it is being copied internally anyway { FeedbackSymbols = _FeedbackSymbols; } // // ----------------------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 /// Sensor value void setConfidenceFunction( std::shared_ptr> &_ConfidenceFunction) noexcept { ConfidenceFunction = _ConfidenceFunction; } /// This is the setter for AbsoluteReliabilityFunction /// \param _AbsoluteReliabilityFunction A pointer to the Functional for the AbsoluteReliabilityFunction /// \brief The AbsoluteReliabilityFunction takes the current Sensor value and return the /// AbsoluteReliabilityFunction of the value. void setAbsoluteReliabilityFunction( std::shared_ptr> &_AbsoluteReliabilityFunction) noexcept { AbsoluteReliabilityFunction = _AbsoluteReliabilityFunction; } /// This is the setter for ReliabilitySlopeFunction Function /// \param _ReliabilitySlopeFunction A pointer to the Functional for the /// ReliabilitySlopeFunction /// \brief The ReliabilitySlopeFunction 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> &_ReliabilitySlopeFunction) noexcept { ReliabilitySlopeFunction = _ReliabilitySlopeFunction; } /// This is the setter for TimeFunctionForLikeliness Function /// \param _TimeFunctionForLikeliness A pointer to the Functional for the TimeFunctionForLikeliness /// \brief The time function takes the position in the History with greater /// equals older and return a Reliability of how "relevant" it is. void setTimeFunctionForLikelinessFunction( std::shared_ptr> &_TimeFunctionForLikeliness) noexcept { TimeFunctionForLikeliness = _TimeFunctionForLikeliness; } /// This is the setter for all possible Identifiers /// \param Identifiers A vector containing all Identifiers /// \brief This exists even though \c Identifier Type is an arithmetic Type because /// the Identifiers do not need to be "next" to each other ( ex. Identifiers={ 1 7 24 }) void setIdentifiers(const std::vector &Identifiers) noexcept { this->Identifiers = Identifiers; } /// 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 timeStep the new Value /// \note This might actually be only an artifact. It is only used to get the /// reliability from the \c ReliabilitySlopeFunction [ ReliabilitySlopeFunction->operator()( /// (lastValue - actualValue) / (ValueType)timeStep) ] void settimeStep(const unsigned int &timeStep) noexcept { this->timeStep = timeStep; } // // ----------------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 LikelinessHistoryCombinator() void setLikelinessHistoryCombinator( const std::function &Meth) noexcept { LikelinessHistoryCombinator = 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 LikelinessFeedbackCombinator() void setLikelinessFeedbackCombinator( const std::function( std::vector, std::vector)> &Meth) noexcept { LikelinessFeedbackCombinator = Meth; } /// Sets the used combination method for Possible Identifiers /// \param Meth the method which should be used. predefined inside the \c - /// predefinedMethods struct PossibleIdentifierCombinationMethod() - void setPossibleIdentifierCombinationMethod( + /// predefinedMethods struct setReliabilityAndConfidenceCombinator() + void setReliabilityAndConfidenceCombinator( const std::function( std::vector, ReliabilityType)> &Meth) noexcept { - PossibleIdentifierCombinationMethod = Meth; + ReliabilityAndConfidenceCombinator = Meth; } /// sets the input reliability combinator method /// \param method the method which should be used. predefined inside the \c /// predefinedMethods struct combination() - void setInputReliabilityCombinator( + void setAbsoluteAndSlopeReliabilityCombinationMethod( const std::function &&method) noexcept { - InputReliabilityCombinator = method; + AbsoluteAndSlopeReliabilityCombinationMethod = 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 LikelinessHistoryCombinatorMin(ReliabilityType A, ReliabilityType B) noexcept { return std::min(A, B); } /// predefined Method static ReliabilityType LikelinessHistoryCombinatorMax(ReliabilityType A, ReliabilityType B) noexcept { return std::max(A, B); } /// predefined Method static ReliabilityType LikelinessHistoryCombinatorMult(ReliabilityType A, ReliabilityType B) noexcept { return A * B; } /// predefined Method static ReliabilityType LikelinessHistoryCombinatorAverage(ReliabilityType A, ReliabilityType B) noexcept { return (A + B) / 2; } /// predefined method static std::vector LikelinessFeedbackCombinatorAverage(std::vector A, std::vector B) noexcept { for (auto &tmp_me : A) for (auto &tmp_other : B) { if (tmp_me.Identifier == tmp_other.Identifier) { tmp_me.Likeliness = (tmp_me.Likeliness + tmp_other.Likeliness) / 2; } } return A; } /// predefined method static std::vector LikelinessFeedbackCombinatorMin(std::vector A, std::vector B) noexcept { for (auto &tmp_me : A) for (auto &tmp_other : B) { if (tmp_me.Identifier == tmp_other.Identifier) { tmp_me.Likeliness = std::min(tmp_me.Likeliness + tmp_other.Likeliness); } } return A; } /// predefined method static std::vector LikelinessFeedbackCombinatorMax(std::vector A, std::vector B) noexcept { for (auto &tmp_me : A) for (auto &tmp_other : B) { if (tmp_me.Identifier == tmp_other.Identifier) { tmp_me.Likeliness = std::max(tmp_me.Likeliness + tmp_other.Likeliness); } } return A; } /// predefined method static std::vector LikelinessFeedbackCombinatorMult(std::vector A, std::vector B) noexcept { for (auto &tmp_me : A) for (auto &tmp_other : B) { if (tmp_me.Identifier == tmp_other.Identifier) { tmp_me.Likeliness = tmp_me.Likeliness * tmp_other.Likeliness; } } return A; } /// Predefined combination method for possible Identifiers static std::vector - PossibleIdentifierCombinationMethodMin(std::vector A, + ReliabilityAndConfidenceCombinatorMin(std::vector A, ReliabilityType B) noexcept { for (auto tmp : A) tmp.Likeliness = std::min(tmp.Likeliness, B); return A; } /// Predefined combination method for possible Identifiers static std::vector - PossibleIdentifierCombinationMethodMax(std::vector A, + ReliabilityAndConfidenceCombinatorMax(std::vector A, ReliabilityType B) noexcept { for (auto tmp : A) tmp.Likeliness = std::max(tmp.Likeliness, B); return A; } /// Predefined combination method for possible Identifiers static std::vector - PossibleIdentifierCombinationMethodAverage(std::vector A, + ReliabilityAndConfidenceCombinatorAverage(std::vector A, ReliabilityType B) noexcept { for (auto tmp : A) tmp.Likeliness = (tmp.Likeliness + B) / 2; return A; } /// Predefined combination method for possible Identifiers static std::vector - PossibleIdentifierCombinationMethodMult(std::vector A, + ReliabilityAndConfidenceCombinatorMult(std::vector A, ReliabilityType B) noexcept { for (auto tmp : A) tmp.Likeliness = tmp.Likeliness * 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> History; std::size_t HistoryMaxSize; std::vector FeedbackSymbols; ValueType previousSensorValue; unsigned int timeStep; std::vector Identifiers; bool PreviousSensorValueExists = false; std::shared_ptr< RangeConfidence> ConfidenceFunction; std::shared_ptr> AbsoluteReliabilityFunction; std::shared_ptr> ReliabilitySlopeFunction; std::shared_ptr> TimeFunctionForLikeliness; // combination functions std::function - InputReliabilityCombinator = predefinedMethods::combinationMin; + AbsoluteAndSlopeReliabilityCombinationMethod = predefinedMethods::combinationMin; std::function(std::vector, ReliabilityType)> - PossibleIdentifierCombinationMethod = - predefinedMethods::PossibleIdentifierCombinationMethodMin; + ReliabilityAndConfidenceCombinator = + predefinedMethods::ReliabilityAndConfidenceCombinatorMin; std::function(std::vector, std::vector)> LikelinessFeedbackCombinator = predefinedMethods::LikelinessFeedbackCombinatorAverage; std::function LikelinessHistoryCombinator = predefinedMethods::LikelinessHistoryCombinatorMax; // --------------------------------------------------------------------------- // needed Functions // --------------------------------------------------------------------------- /// returns the Reliability /// \param actualValue The Value of the Sensor /// \param lastValue of the Sensor this is stored in the class /// \param _timeStep 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 /// ReliabilitySlopeFunction if the previous value exists. if it doesn't it only /// returns the \c Reliability function value. ReliabilityType getReliability(const ValueType &actualValue, const ValueType &lastValue, const unsigned int &_timeStep) noexcept { ReliabilityType relAbs = AbsoluteReliabilityFunction->operator()(actualValue); if (PreviousSensorValueExists) { ReliabilityType relSlo = ReliabilitySlopeFunction->operator()( (lastValue - actualValue) / (ValueType)_timeStep); - return InputReliabilityCombinator(relAbs, relSlo); + return AbsoluteAndSlopeReliabilityCombinationMethod(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 TimeFunctionForLikeliness function /// and returns the maximum Reliability for all Identifiers. std::vector SymbolsFromHistory() noexcept { // iterate through all history entries std::size_t posInHistory = 0; std::vector symbolFromHistory; //History Symbols for (auto timeStep = History.begin(); timeStep < History.end(); timeStep++, posInHistory++) { // iterate through all possible Identifiers of each history entry for (Symbol &symbol : *timeStep) { IdentifierType historyIdentifier = symbol.Identifier; ReliabilityType historyConf = symbol.Likeliness; historyConf = historyConf * TimeFunctionForLikeliness->operator()(posInHistory); bool foundIdentifier = false; for (Symbol &pS : symbolFromHistory) { if (pS.Identifier == historyIdentifier) { pS.Likeliness = LikelinessHistoryCombinator(pS.Likeliness, historyConf); foundIdentifier = true; } } if (foundIdentifier == false) { Symbol possibleIdentifier; // Symbol possibleIdentifier.Identifier = historyIdentifier; possibleIdentifier.Likeliness = historyConf; symbolFromHistory.push_back(possibleIdentifier); } } } return symbolFromHistory; } /// 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 &actualPossibleIdentifiers) noexcept { // Symbols // check if the reliability of at least one possible Identifier is high // enough bool atLeastOneRelIsHigh = false; for (Symbol pS : actualPossibleIdentifiers) { if (pS.Likeliness > 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