diff --git a/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp b/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp index 9d6ddd3..cad229b 100644 --- a/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp +++ b/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp @@ -1,247 +1,247 @@ //===- examples/agent-functionalities/Reliability-functionality.cpp *C++-*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file examples/agent-functionalities/Reliability-functionality.cpp /// /// \author Daniel Schnoell (daniel.schnoell@tuwien.ac.at ) /// /// \date 2019 /// /// \brief A simple example on defining Relianility Functionalities. /// //===----------------------------------------------------------------------===// #define Reliability_trace_level 5 #include "rosa/config/version.h" #include "rosa/support/log.h" #include "rosa/agent/CrossCombinator.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/ReliabilityConfidenceCombinator.h" #include #include using namespace rosa::agent; int main(void) { typedef double SensorValueType; typedef long StateType; typedef double ReliabilityType; std::unique_ptr> Confidence(new RangeConfidence( {{0, PartialFunction( { {{0, 3}, std::make_shared>( 0, 1.0 / 3)}, {{3, 6}, std::make_shared>(1, 0)}, {{6, 9}, std::make_shared>( 3.0, -1.0 / 3)}, }, 0)}, {1, PartialFunction( { {{6, 9}, std::make_shared>( -2, 1.0 / 3)}, {{9, 12}, std::make_shared>(1, 0)}, {{12, 15}, std::make_shared>( 5, -1.0 / 3)}, }, 0)}, {2, PartialFunction( { {{12, 15}, std::make_shared>( -4, 1.0 / 3)}, {{15, 18}, std::make_shared>(1, 0)}, {{18, 21}, std::make_shared>( 7, -1.0 / 3)}, }, 0)}})); std::unique_ptr> Reliability( new LinearFunction(1, -1.0 / 3)); std::unique_ptr> ReliabilitySlope( new LinearFunction(1, -1.0 / 3)); std::unique_ptr> TimeConfidence( new LinearFunction(1, -1.0 / 3)); auto lowlevel = new ReliabilityAndConfidenceCombinator(); std::vector states; states.push_back(0); states.push_back(1); states.push_back(2); lowlevel->setConfidenceFunction(Confidence); lowlevel->setReliabilityFunction(Reliability); lowlevel->setReliabilitySlopeFunction(ReliabilitySlope); lowlevel->setTimeConfidenceFunction(TimeConfidence); lowlevel->setStates(states); lowlevel->setHistoryLength(2); lowlevel->setValueSetCounter(1); /* ----------------------------- Do Something * ---------------------------------------------------------------- */ std::cout << "Testing the lowlevel component with static feedback telling it " "that the most lickely state is 2.\n"; for (int a = 0; a < 30; a++) std::cout << "a: " << a << "\n" << (lowlevel->feedback({{0, 0}, {1, 0.3}, {2, 0.8}}), lowlevel->getmostLikelyIdentifierAndReliability(a)) << "\n"; std::cout << "---------------------------------------------------------------" "---------------------------------\n"; std::cout << "------------------------------------High level " "Test---------------------------------------------\n"; std::cout << "Configured in a way that the Master thinks that both Sensors " "should have the same State.\n While feeding both the \"opposite\" " "values one acending the other decending from the maximum.\n"; std::unique_ptr> Confidence2(new RangeConfidence( {{0, PartialFunction( { {{0, 3}, std::make_shared>( 0, 1.0 / 3)}, {{3, 6}, std::make_shared>(1, 0)}, {{6, 9}, std::make_shared>( 3.0, -1.0 / 3)}, }, 0)}, {1, PartialFunction( { {{6, 9}, std::make_shared>( -2, 1.0 / 3)}, {{9, 12}, std::make_shared>(1, 0)}, {{12, 15}, std::make_shared>( 5, -1.0 / 3)}, }, 0)}, {2, PartialFunction( { {{12, 15}, std::make_shared>( -4, 1.0 / 3)}, {{15, 18}, std::make_shared>(1, 0)}, {{18, 21}, std::make_shared>( 7, -1.0 / 3)}, }, 0)}})); std::unique_ptr> Reliability2( new LinearFunction(1, -1.0 / 9)); std::unique_ptr> ReliabilitySlope2( new LinearFunction(1, -1.0 / 9)); std::unique_ptr> TimeConfidence2( new LinearFunction(1, -1.0 / 9)); auto lowlevel2 = new ReliabilityAndConfidenceCombinator(); std::vector states2; states2.push_back(0); states2.push_back(1); states2.push_back(2); lowlevel2->setConfidenceFunction(Confidence2); lowlevel2->setReliabilityFunction(Reliability2); lowlevel2->setReliabilitySlopeFunction(ReliabilitySlope2); lowlevel2->setTimeConfidenceFunction(TimeConfidence2); lowlevel2->setStates(states2); lowlevel2->setHistoryLength(2); lowlevel2->setValueSetCounter(1); CrossCombinator *highlevel = new CrossCombinator(); std::unique_ptr> func1(new PartialFunction( { {{0, 1}, std::make_shared>(1, 0)}, {{1, 2}, std::make_shared>(2, -1.0)}, }, 0)); highlevel->addCrossReliabilityProfile(0, 1, func1); highlevel->setCrossReliabilityCombinatorMethod( - CrossCombinator::AVERAGE); + CrossCombinator::predefinedMethods::AVERAGE); highlevel->setCrossReliabilityParameter(1); - highlevel->addStates(0, states); - highlevel->addStates(1, states); + highlevel->addIdentifiers(0, states); + highlevel->addIdentifiers(1, states); for (int a = 0; a < 21; a++) { auto out1 = lowlevel->getmostLikelyIdentifierAndReliability(a), out2 = lowlevel2->getmostLikelyIdentifierAndReliability((int)21 - a); std::cout << "s1: " << out1 << "\ns2:" << out2 << "\n"; std::vector> tmp2; tmp2.push_back({0, out1.Identifier, out1.Reliability}); tmp2.push_back({1, out2.Identifier, out2.Reliability}); auto out_o = highlevel->operator()(tmp2); std::cout << "it: " << a << "\t rel: " << out_o.CrossReliability << "\n"; std::cout << "\t subs:\n"; for (auto q : out_o.CrossConfidence) { std::cout << "\t\t id:" << q.first << "\n"; /* for(auto z: q.second) { std::cout << "\t\t\t Identifier: " << z.Identifier << "\tRel: " << z.Reliability << "\n"; tmp.push_back({z.Identifier,z.Reliability}); } */ for (auto z : q.second) { std::cout << "\t\t\t Identifier: " << z.Identifier << "\tRel: " << z.Reliability << "\n"; } if (q.first == 0) lowlevel->feedback(q.second); else lowlevel2->feedback(q.second); } } /* ----------------------------- Cleanup * --------------------------------------------------------------------- */ delete highlevel; delete lowlevel; delete lowlevel2; } \ No newline at end of file diff --git a/include/rosa/agent/CrossCombinator.h b/include/rosa/agent/CrossCombinator.h index 12596b7..7c005d7 100644 --- a/include/rosa/agent/CrossCombinator.h +++ b/include/rosa/agent/CrossCombinator.h @@ -1,538 +1,552 @@ //===-- rosa/delux/CrossReliability.h ---------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/delux/CrossReliability.h /// /// \author Daniel Schnoell /// /// \date 2019 /// /// \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_CROSSRELIABILITY_H #define ROSA_AGENT_CROSSRELIABILITY_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 #include //assert #include // for static methods #include #include namespace rosa { namespace agent { template -std::vector> & -operator<<(std::vector> &me, - std::vector> Values) { +std::vector> &operator<<( + std::vector> &me, + 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 is a kind of -/// confidence. +/// \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 Datatype of the State ( Typically double or float) -/// \tparam ReliabilityType Datatype of the Reliability ( -/// Typically long or int) +/// \tparam IdentifierType Datatype of the Identifier ( Typically double or +/// float) \tparam ReliabilityType Datatype 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 /// commonly used Reliability ], \c getCrossConfidence() [ this is the feedback /// for all Slaves ] -template class CrossCombinator { +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"); // --------------------------------------------------------------------------- // useful definitions // --------------------------------------------------------------------------- /// typedef To shorten the writing. /// \c ConfOrRel using ConfOrRel = ConfOrRel; /// To shorten the writing. using Abstraction = typename rosa::agent::Abstraction; /// The return type for the \c operator()() Method struct returnType { ReliabilityType CrossReliability; std::map> CrossConfidence; }; // ------------------------------------------------------------------------- // Relevant Methods // ------------------------------------------------------------------------- /// Calculates the Reliability and the CrossConfidences for each id for all - /// of there states. + /// of there Identifiers. /// - /// \param Values It gets the States and Reliabilities of + /// \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> Values) { + returnType operator()( + std::vector> Values) { return {getOutputReliability(Values), getCrossConfidence(Values)}; } /// returns the combined via \c CombinedCrossRelCombinationMethod \c /// setCombinedCrossRelCombinationMethod() Cross Reliability for all ids \c /// CrossReliability() \param Values the used Values ReliabilityType getCombinedCrossReliability( std::vector> Values) { ReliabilityType 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); + 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 relibility \param Values the /// used Values ReliabilityType getCombinedInputReliability( std::vector> Values) { ReliabilityType combinedInputRel = -1; std::vector> 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( std::vector> Values) { return OutputReliabilityCombinationMethod( getCombinedInputReliability(Values), getCombinedCrossReliability(Values)); } /// retruns the crossConfidence for all ids \c CrossConfidence() /// \param Values the used Values std::map> getCrossConfidence( std::vector> Values) { std::vector> Agents; 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 : States[id]) { + 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 state represented by a numerical value and calculates + /// \brief it uses the Identifier value and calculates /// the Confidence of a given agent( represented by there id ) for a given - /// state in connection to all other given agents + /// 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(id_t MainAgent, IdentifierType TheoreticalValue, std::vector> &SlaveAgents) { ReliabilityType crossReliabiability; std::vector values; for (std::pair SlaveAgent : SlaveAgents) { if (SlaveAgent.first == MainAgent) continue; if (TheoreticalValue == SlaveAgent.second) crossReliabiability = 1; else crossReliabiability = 1 / (crossReliabilityParameter * AbsuluteValue(TheoreticalValue, SlaveAgent.second)); // profile reliability ReliabilityType crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent, SlaveAgent.first, AbsuluteValue(TheoreticalValue, SlaveAgent.second)); values.push_back( std::max(crossReliabiability, crossReliabilityFromProfile)); } return Method(values); } /// Calculates the Cross Reliability - /// \brief it uses the state represented by a numerical value and calculates + /// \brief it uses the Identifier value and calculates /// the Reliability of a given agent( represented by there 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(std::pair &&MainAgent, std::vector> &SlaveAgents) { ReliabilityType crossReliabiability; std::vector values; for (std::pair SlaveAgent : SlaveAgents) { if (SlaveAgent.first == MainAgent.first) continue; if (MainAgent.second == SlaveAgent.second) crossReliabiability = 1; else crossReliabiability = 1 / (crossReliabilityParameter * AbsuluteValue(MainAgent.second, SlaveAgent.second)); // profile reliability ReliabilityType crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent.first, SlaveAgent.first, AbsuluteValue(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 state - /// difference + /// adds a Cross Reliability Profile used to get the Reliability of the + /// Identifier difference + /// /// \param idA The id of the one \c Agent ( idealy the id of \c Unit to make /// it absolutly unique ) /// /// \param idB The id of the other \c Agent /// /// \param Function A unique pointer to an \c Abstraction it would use the /// difference in Identifier for its input void addCrossReliabilityProfile(id_t idA, id_t idB, std::unique_ptr &Function) { Abstraction *ptr = Function.release(); Functions.push_back({true, idA, idB, ptr}); } /// sets the cross reliability parameter void setCrossReliabilityParameter(ReliabilityType val) { crossReliabilityParameter = val; } - /// This is the adder for the states - /// \param id The id of the Agent of the states - /// \param States id specific states. this will be copied So that if Slaves - /// have different States they can be used correctly. - /// \brief The States of all connected lowlevel Agents has to be known to be - /// able to iterate over them - void addStates(id_t id, std::vector States) { - this->States.insert({id, States}); + /// 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 lowlevel Agents has to be known to be able to + /// iterate over them + void addIdentifiers(id_t id, std::vector Identifiers) { + this->Identifiers.insert({id, Identifiers}); } // ------------------------------------------------------------------------- // Combinator Settings // ------------------------------------------------------------------------- /// sets the used method to combine the values /// \param Meth The Function which defines the combination method. predef: \c /// CONJUNCTION() \c AVERAGE() \c DISJUNCTION() void setCrossReliabilityCombinatorMethod( - ReliabilityType (*Meth)(std::vector values)) { + std::function values)> + Meth) { Method = Meth; } /// sets the combination method for the combined cross reliability /// \param Meth the method which should be used. predef: \c /// CombinedCrossRelCombinationMethodMin() \c /// CombinedCrossRelCombinationMethodMax() \c /// CombinedCrossRelCombinationMethodMult() \c /// CombinedCrossRelCombinationMethodAverage() void setCombinedCrossRelCombinationMethod( - ReliabilityType (*Meth)(ReliabilityType, ReliabilityType)) { + std::function Meth) { CombinedCrossRelCombinationMethod = Meth; } /// sets the combined input rel method /// \param Meth the method which should be used predef: \c /// CombinedInputRelCombinationMethodMin() \c /// CombinedInputRelCombinationMethodMax() \c /// CombinedInputRelCombinationMethodMult() \c /// CombinedInputRelCombinationMethodAverage() void setCombinedInputRelCombinationMethod( - ReliabilityType (*Meth)(ReliabilityType, ReliabilityType)) { + std::function Meth) { CombinedInputRelCombinationMethod = Meth; } /// sets the used OutputReliabilityCombinationMethod /// \param Meth the used Method. predef: \c /// OutputReliabilityCombinationMethodMin() \c /// OutputReliabilityCombinationMethodMax() \c /// OutputReliabilityCombinationMethodMult() \c /// OutputReliabilityCombinationMethodAverage() void setOutputReliabilityCombinationMethod( - ReliabilityType (*Meth)(ReliabilityType, ReliabilityType)) { + std::function Meth) { OutputReliabilityCombinationMethod = Meth; } // ------------------------------------------------------------------------- // Predefined Functions // ------------------------------------------------------------------------- /// predefined combination method - static ReliabilityType CONJUNCTION(std::vector values) { - return *std::min_element(values.begin(), values.end()); - } + struct predefinedMethods { + static ReliabilityType CONJUNCTION(std::vector values) { + return *std::min_element(values.begin(), values.end()); + } - /// predefined combination method - static ReliabilityType AVERAGE(std::vector values) { - return std::accumulate(values.begin(), values.end(), 0.0) / values.size(); - } + /// predefined combination method + static ReliabilityType AVERAGE(std::vector values) { + return std::accumulate(values.begin(), values.end(), 0.0) / values.size(); + } - /// predefined combination method - static ReliabilityType DISJUNCTION(std::vector values) { - return *std::max_element(values.begin(), values.end()); - } + /// predefined combination method + static ReliabilityType DISJUNCTION(std::vector 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + OutputReliabilityCombinationMethodMult(ReliabilityType A, + ReliabilityType B) { + return A * B; + } - /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { - return (A + B) / 2; - } + /// predefined combination method + static ReliabilityType + OutputReliabilityCombinationMethodAverage(ReliabilityType A, + ReliabilityType B) { + return (A + B) / 2; + } + }; // ------------------------------------------------------------------------- // Cleanup // ------------------------------------------------------------------------- ~CrossCombinator() { for (auto tmp : Functions) delete tmp.Funct; Functions.clear(); } // -------------------------------------------------------------------------- // Needed stuff and stored stuff // -------------------------------------------------------------------------- private: struct Functionblock { bool exists = false; id_t A; id_t B; Abstraction *Funct; }; - std::map> States; + std::map> Identifiers; /// From Maxi in his code defined as 1 can be changed by set ReliabilityType crossReliabilityParameter = 1; /// Stored Cross Reliability Functions std::vector Functions; /// Method which is used to combine the generated values - ReliabilityType (*Method)(std::vector values) = AVERAGE; + std::function)> Method = + predefinedMethods::AVERAGE; - ReliabilityType (*CombinedCrossRelCombinationMethod)( - ReliabilityType, ReliabilityType) = CombinedCrossRelCombinationMethodMin; + std::function + CombinedCrossRelCombinationMethod = + predefinedMethods::CombinedCrossRelCombinationMethodMin; - ReliabilityType (*CombinedInputRelCombinationMethod)( - ReliabilityType, ReliabilityType) = CombinedInputRelCombinationMethodMin; + std::function + CombinedInputRelCombinationMethod = + predefinedMethods::CombinedInputRelCombinationMethodMin; - ReliabilityType (*OutputReliabilityCombinationMethod)( - ReliabilityType, ReliabilityType) = OutputReliabilityCombinationMethodMin; + std::function + OutputReliabilityCombinationMethod = + predefinedMethods::OutputReliabilityCombinationMethodMin; //-------------------------------------------------------------------------------- // helper function /// evaluates the absolute Value of two values /// \note this is actually the absolute distance but to keep it somewhat /// conform with maxis code template Type_t AbsuluteValue(Type_t A, Type_t B) { return ((A - B) < 0) ? B - A : A - B; } /// 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 /// for the LinerFunction /// /// \note it doesn't matter if they are swapped - ReliabilityType getCrossReliabilityFromProfile(id_t nameA, id_t nameB, - IdentifierType IdentifierDifference) { + ReliabilityType + getCrossReliabilityFromProfile(id_t nameA, id_t nameB, + IdentifierType IdentifierDifference) { 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_CROSSRELIABILITY_H \ No newline at end of file diff --git a/include/rosa/agent/ReliabilityConfidenceCombinator.h b/include/rosa/agent/ReliabilityConfidenceCombinator.h index 901a12e..6670b0e 100644 --- a/include/rosa/agent/ReliabilityConfidenceCombinator.h +++ b/include/rosa/agent/ReliabilityConfidenceCombinator.h @@ -1,804 +1,745 @@ //===-- 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 +#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 Reliability Combinator /// more readable \tparam IdentifierType The datatype of the States \tparam /// ReliabilityType The datatype of the Reliability template 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; // 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(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 &c) { std::size_t index = 0; for (ConfOrRel data : c) { out << index << " : " << data << "\n"; index++; } return out; } }; -/// This calculates the minimum of the Reliabilities & the given value -/// \param me The vector with the Reliabilities -/// \param value The comparing value -template -std::vector min(std::vector me, - typename Conf::_ReliabilityType value) { - static_assert(std::is_arithmetic::value); - for (auto tmp : me) - tmp.Reliability = std::min(tmp.Reliability, value); - return me; -} -/// This calculates the maximum of the Reliabilities & the given value -/// \param me The vector with the Reliabilities -/// \param value The comparing value -template -std::vector max(std::vector me, - typename Conf::_ReliabilityType value) { - static_assert(std::is_arithmetic::value); - for (auto tmp : me) - tmp.Reliability = std::max(tmp.Reliability, value); - return me; -} -/// This calculates the average of the Reliabilities & the given value -/// \param me The vector with the Reliabilities -/// \param value The comparing value -template -std::vector average(std::vector me, - typename Conf::_ReliabilityType value) { - static_assert(std::is_arithmetic::value); - for (auto tmp : me) - tmp.Reliability = (tmp.Reliability + value) / 2; - return me; -} - -/// This calculates the average of the Reliabilities & the given value -/// \param me The vector with the Reliabilities -/// \param value The comparing value -template -std::vector mult(std::vector me, - typename Conf::_ReliabilityType value) { - static_assert(std::is_arithmetic::value); - for (auto tmp : me) - tmp.Reliability = tmp.Reliability * value / 2; - return me; -} - -/// This average's the Reliabilities of the same Identifiers -template -std::vector average(std::vector A, std::vector B) { - static_assert(std::is_arithmetic::value); - 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; -} -/// This min's the Reliabilities of the same Identifiers -template -std::vector min(std::vector A, std::vector B) { - static_assert(std::is_arithmetic::value); - 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; -} -/// This max's the Reliabilities of the same Identifiers -template -std::vector max(std::vector A, std::vector B) { - static_assert(std::is_arithmetic::value); - 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; -} -/// This mult's the Reliabilities of the same Identifiers -template -std::vector mult(std::vector A, std::vector B) { - static_assert(std::is_arithmetic::value); - 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; -} - /// 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 Datatype of the Sensor value ( Typically /// double or float) \tparam IdentifierType Datatype of the State ( Typically /// long or int) /// \tparam ReliabilityType Datatype 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->nextline /// | | /// 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 ///
 /// Default values for Combinators:
 ///	InputReliabilityCombinator		= combinationMin;
 ///	PossibleIdentifierCombinationMethod=PossibleIdentifierCombinationMethodMin;
 /// FeedbackCombinatorMethod		= FeedbackCombinatorMethodAverage;
 /// HistoryCombinatorMethod			= HistoryCombinatorMethodMax;
 ///	
/// To understand the place where the combinator methods come into play a list /// for each getter which Methods are used. /// ///
 /// \c getInputReliability():
 ///		-InputReliabilityCombinator
 /// \c getPossibleIdentifiers():
 ///		-InputReliabilityCombinator
 ///		-PossibleIdentifierCombinationMethod
 /// \c getpossibleIdentifiersWithMasterFeedback():
 ///		-InputReliabilityCombinator
 ///		-PossibleIdentifierCombinationMethod
 ///		-FeedbackCombinatorMethod
 /// \c getPossibleIdentifiersWithHistory():
 ///		-InputReliabilityCombinator
 ///		-PossibleIdentifierCombinationMethod
 ///		-FeedbackCombinatorMethod
 ///		-HistoryCombinatorMethod
 /// \c getmostLikelyIdentifierAndReliability():
 ///		-InputReliabilityCombinator
 ///		-PossibleIdentifierCombinationMethod
 ///		-FeedbackCombinatorMethod
 ///		-HistoryCombinatorMethod
 /// 
/// /// /// /// template class ReliabilityAndConfidenceCombinator { public: static_assert(std::is_arithmetic::value, "LowLevel: SensorValueType 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 ConfOrRel using ConfOrRel = ConfOrRel; /// 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() auto getInputReliability(SensorValueType SensorValue) { auto 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() auto getPossibleIdentifiers(SensorValueType SensorValue) { std::vector 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. auto getpossibleIdentifiersWithMasterFeedback(SensorValueType SensorValue) { std::vector 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. auto getPossibleIdentifiersWithHistory(SensorValueType SensorValue) { 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 << 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(SensorValueType SensorValue) { #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 << 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 /// \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(std::vector ValuesFromMaster) { this->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 /// Sensor value void setConfidenceFunction( std::unique_ptr> &Confidence) { this->Confidence = std::move(Confidence); } /// This is the setter for Reliability Function /// \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::unique_ptr> &Reliability) { this->Reliability = std::move(Reliability); } /// This is the setter for ReliabilitySlope Function /// \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::unique_ptr> &ReliabilitySlope) { this->ReliabilitySlope = std::move(ReliabilitySlope); } /// This is the setter for TimeConfidence Function /// \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::unique_ptr> &TimeConfidence) { this->TimeConfidence = std::move(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(std::vector states) { this->States = states; } /// This sets the Maximum length of the History /// \param length The length void setHistoryLength(std::size_t length) { 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(unsigned int ValueSetCounter) { this->valueSetCounter = ValueSetCounter; } // // ----------------combinator setters----------------------------------------- // /// This sets the combination method used by the History /// \param Meth the method which should be used. predefined \c /// HistoryCombinatorMethodMin() \c HistoryCombinatorMethodMax() \c /// HistoryCombinatorMethodMult() \c HistoryCombinatorMethodAverage() - void setHistoryCombinatorMethod(ReliabilityType (*Meth)(ReliabilityType, - ReliabilityType)) { + void setHistoryCombinatorMethod( + std::function Meth) { HistoryCombinatorMethod = Meth; } /// sets the predefined method for the combination of the possible Identifiers /// and the master \param Meth the method predefined ones are \c /// FeedbackCombinatorMethodAverage() \c FeedbackCombinatorMethodMin() \c /// FeedbackCombinatorMethodMax() \c FeedbackCombinatorMethodMult() - void setFeedbackCombinatorMethod(std::vector (*Meth)( - std::vector, std::vector)) { + void setFeedbackCombinatorMethod( + std::function(std::vector, + std::vector)> + Meth) { FeedbackCombinatorMethod = Meth; } /// Sets the used combination method for Possible Identifiers /// \param Meth a Pointer for the used Method. Predefined methods \c /// PossibleIdentifierCombinationMethodMin() \c /// PossibleIdentifierCombinationMethodMax() \c /// PossibleIdentifierCombinationMethodAverage() void setPossibleIdentifierCombinationMethod( - std::vector (*Meth)(std::vector, ReliabilityType)) { + std::function(std::vector, + ReliabilityType)> + Meth) { PossibleIdentifierCombinationMethod = Meth; } /// sets the input reliability combinator method /// \param method the to be used method /// \note there are predefined methods \c combinationMin() \c combinationMax() /// \c combinationAverage() void setInputReliabilityCombinator( - ReliabilityType (*method)(ReliabilityType, ReliabilityType)) { + std::function method) { InputReliabilityCombinator = method; } // // ----------------predefined combinators------------------------------------ // struct predefinedMethods { /// predefined Method static ReliabilityType HistoryCombinatorMethodMin(ReliabilityType A, ReliabilityType B) { return std::min(A, B); } /// predefined Method static ReliabilityType HistoryCombinatorMethodMax(ReliabilityType A, ReliabilityType B) { return std::max(A, B); } /// predefined Method static ReliabilityType HistoryCombinatorMethodMult(ReliabilityType A, ReliabilityType B) { return A * B; } /// predefined Method static ReliabilityType HistoryCombinatorMethodAverage(ReliabilityType A, ReliabilityType B) { return (A + B) / 2; } /// predefined method static std::vector FeedbackCombinatorMethodAverage(std::vector A, std::vector B) { - return average(A, B); + 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 FeedbackCombinatorMethodMin(std::vector A, std::vector B) { - return min(A, B); + 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 FeedbackCombinatorMethodMax(std::vector A, std::vector B) { - return max(A, B); + 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 FeedbackCombinatorMethodMult(std::vector A, std::vector B) { - return mult(A, B); + 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 PossibleIdentifierCombinationMethodMin(std::vector A, ReliabilityType B) { - return min(A, B); + for (auto tmp : A) + tmp.Reliability = std::min(tmp.Reliability, B); + return A; } /// Predefined combination method for possible Identifiers static std::vector PossibleIdentifierCombinationMethodMax(std::vector A, ReliabilityType B) { - return max(A, B); + for (auto tmp : A) + tmp.Reliability = std::max(tmp.Reliability, B); + return A; } /// Predefined combination method for possible Identifiers static std::vector PossibleIdentifierCombinationMethodAverage(std::vector A, ReliabilityType B) { - return average(A, B); + for (auto tmp : A) + tmp.Reliability = (tmp.Reliability + B) / 2; + return A; } /// Predefined combination method for possible Identifiers static std::vector PossibleIdentifierCombinationMethodMult(std::vector A, ReliabilityType B) { - return mult(A, B); + for (auto tmp : A) + tmp.Reliability = tmp.Reliability * B / 2; + return A; } /// The predefined min combinator method static ReliabilityType combinationMin(ReliabilityType A, ReliabilityType B) { return std::min(A, B); } /// The predefined max combinator method static ReliabilityType combinationMax(ReliabilityType A, ReliabilityType B) { return std::max(A, B); } /// The predefined average combinator method static ReliabilityType combinationAverage(ReliabilityType A, ReliabilityType B) { return (A + B) / 2; } /// The predefined average combinator method static ReliabilityType combinationMult(ReliabilityType A, ReliabilityType B) { return A * B; } }; // ---------------------------------------------------------------- // Stored Values // ---------------------------------------------------------------- private: std::vector> History; std::size_t HistoryMaxSize; std::vector ValuesFromMaster; SensorValueType previousSensorValue; unsigned int valueSetCounter; std::vector States; bool PreviousSensorValueExists = false; std::unique_ptr< RangeConfidence> Confidence; std::unique_ptr> Reliability; std::unique_ptr> ReliabilitySlope; std::unique_ptr> TimeConfidence; // combination functions - ReliabilityType (*InputReliabilityCombinator)( - ReliabilityType, ReliabilityType) = predefinedMethods::combinationMin; - - std::vector (*PossibleIdentifierCombinationMethod)( - std::vector, ReliabilityType) = - predefinedMethods::PossibleIdentifierCombinationMethodMin; - - std::vector (*FeedbackCombinatorMethod)(std::vector, - std::vector) = - predefinedMethods::FeedbackCombinatorMethodAverage; - - ReliabilityType (*HistoryCombinatorMethod)(ReliabilityType, ReliabilityType) = - predefinedMethods::HistoryCombinatorMethodMax; + std::function + InputReliabilityCombinator = predefinedMethods::combinationMin; + + std::function(std::vector, ReliabilityType)> + PossibleIdentifierCombinationMethod = + predefinedMethods::PossibleIdentifierCombinationMethodMin; + + std::function(std::vector, + std::vector)> + FeedbackCombinatorMethod = + predefinedMethods::FeedbackCombinatorMethodAverage; + std::function + 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 /// 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(SensorValueType actualValue, SensorValueType lastValue, unsigned int valueSetCounter) { ReliabilityType relAbs = Reliability->operator()(actualValue); if (PreviousSensorValueExists) { ReliabilityType relSlo = ReliabilitySlope->operator()( (lastValue - actualValue) / (SensorValueType)valueSetCounter); return InputReliabilityCombinator(relAbs, relSlo); } else return relAbs; } /// adapts the possible Identifiers by checking the History and combines those /// values. currently with max /// \brief combines the historic values with the \c TimeConfidence function /// and returns the maximum Reliability for all Identifiers. std::vector getAllPossibleIdentifiersBasedOnHistory() { // iterate through all history entries std::size_t posInHistory = 0; std::vector 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(std::vector actualPossibleIdentifiers) { // 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