diff --git a/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp b/examples/agent-functionalities/Reliability-functionality/Reliability-functionality.cpp index 9725b1a..8c2f8f7 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/CrossReliability.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->mostLikelySoreAndReliability(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); highlevel->setCrossReliabilityParameter(1); highlevel->addStates(0, states); highlevel->addStates(1, states); for (int a = 0; a < 21; a++) { auto out1 = lowlevel->mostLikelySoreAndReliability(a), out2 = lowlevel2->mostLikelySoreAndReliability((int)21 - a); std::cout << "s1: " << out1 << "\ns2:" << out2 << "\n"; std::vector> tmp2; tmp2.push_back({0, out1.score, out1.Reliability}); tmp2.push_back({1, out2.score, 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 score: " << z.score << "\tRel: " << z.Reliability << "\n"; tmp.push_back({z.score,z.Reliability}); } */ for (auto z : q.second) { std::cout << "\t\t\t score: " << z.score << "\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/CrossReliability.h b/include/rosa/agent/CrossCombinator.h similarity index 95% rename from include/rosa/agent/CrossReliability.h rename to include/rosa/agent/CrossCombinator.h index 0ba055c..2dcb741 100644 --- a/include/rosa/agent/CrossReliability.h +++ b/include/rosa/agent/CrossCombinator.h @@ -1,541 +1,539 @@ -//===-- 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) { - 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 scores 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 StateType Datatype of the State ( 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 { -public: - static_assert(std::is_arithmetic::value, - "HighLevel: StateType 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 - typedef 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 Cross Confidences for each id for all - /// of there states. - /// - /// \param Values It gets the States 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) { - 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); - StateType sc = std::get<1>(Value); - - // calculate the cross reliability for this slave agent - ReliabilityType realCrossReliabilityOfSlaveAgent = CrossReliability( - {id, sc}, - Agents); // AVERAGE, MULTIPLICATION, CONJUNCTION (best to worst: - // AVERAGE = CONJUNCTION > MULTIPLICATION >> ) - - 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 set - /// OutputReliabilityCombinationMethod() 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 cross Confidence 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); - - // get cross confidence - output_temporary.clear(); - for (StateType thoScore : States[id]) { - // calculate the cross reliability for this slave agent - ConfOrRel data; - data.score = thoScore; - data.Reliability = CrossConfidence(id, thoScore, 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 - /// the Confidence of a given agent( represented by there id ) for a given - /// state 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, StateType 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 - /// 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 - /// \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 score 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}); - } - - // ------------------------------------------------------------------------- - // 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)) { - 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)) { - 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)) { - 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)) { - OutputReliabilityCombinationMethod = Meth; - } - - // ------------------------------------------------------------------------- - // Predefined Functions - // ------------------------------------------------------------------------- - /// predefined combination method - 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 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 - CombinedCrossRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { - return std::max(A, B); - } - - /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodMult(ReliabilityType A, ReliabilityType B) { - return A * B; - } - - /// predefined combination Method - static ReliabilityType - CombinedCrossRelCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { - return (A + B) / 2; - } - - /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) { - return std::min(A, B); - } - - /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { - return std::max(A, B); - } - - /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodMult(ReliabilityType A, ReliabilityType B) { - return A * B; - } - - /// predefined combination Method - static ReliabilityType - CombinedInputRelCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { - return (A + B) / 2; - } - - /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMin(ReliabilityType A, ReliabilityType B) { - return std::min(A, B); - } - - /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMax(ReliabilityType A, ReliabilityType B) { - return std::max(A, B); - } - - /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodMult(ReliabilityType A, ReliabilityType B) { - return A * B; - } - - /// predefined combination method - static ReliabilityType - OutputReliabilityCombinationMethodAverage(ReliabilityType A, - ReliabilityType B) { - return (A + B) / 2; - } - - // ------------------------------------------------------------------------- - // Cleanup - // ------------------------------------------------------------------------- - - ~CrossCombinator() { - 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; - - /// 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; - - ReliabilityType (*CombinedCrossRelCombinationMethod)( - ReliabilityType, ReliabilityType) = CombinedCrossRelCombinationMethodMin; - - ReliabilityType (*CombinedInputRelCombinationMethod)( - ReliabilityType, ReliabilityType) = CombinedInputRelCombinationMethodMin; - - ReliabilityType (*OutputReliabilityCombinationMethod)( - ReliabilityType, ReliabilityType) = 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 score 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, - StateType scoreDifference) { - 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()(scoreDifference); - } -}; - -} // End namespace agent -} // End namespace rosa - +//===-- 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) { + 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 scores 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 StateType Datatype of the State ( 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 { +public: + static_assert(std::is_arithmetic::value, + "HighLevel: StateType 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 + typedef 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. + /// + /// \param Values It gets the States 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) { + 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); + StateType sc = std::get<1>(Value); + + // calculate the cross reliability for this slave agent + ReliabilityType realCrossReliabilityOfSlaveAgent = CrossReliability( + {id, sc}, + Agents); // AVERAGE, MULTIPLICATION, CONJUNCTION (best to worst: + // AVERAGE = CONJUNCTION > MULTIPLICATION >> ) + + 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 (StateType thoScore : States[id]) { + ConfOrRel data; + data.score = thoScore; + data.Reliability = CrossConfidence(id, thoScore, 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 + /// the Confidence of a given agent( represented by there id ) for a given + /// state 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, StateType 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 + /// 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 + /// \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 score 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}); + } + + // ------------------------------------------------------------------------- + // 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)) { + 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)) { + 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)) { + 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)) { + OutputReliabilityCombinationMethod = Meth; + } + + // ------------------------------------------------------------------------- + // Predefined Functions + // ------------------------------------------------------------------------- + /// predefined combination method + 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 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 + CombinedCrossRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { + return std::max(A, B); + } + + /// predefined combination Method + static ReliabilityType + CombinedCrossRelCombinationMethodMult(ReliabilityType A, ReliabilityType B) { + return A * B; + } + + /// predefined combination Method + static ReliabilityType + CombinedCrossRelCombinationMethodAverage(ReliabilityType A, + ReliabilityType B) { + return (A + B) / 2; + } + + /// predefined combination Method + static ReliabilityType + CombinedInputRelCombinationMethodMin(ReliabilityType A, ReliabilityType B) { + return std::min(A, B); + } + + /// predefined combination Method + static ReliabilityType + CombinedInputRelCombinationMethodMax(ReliabilityType A, ReliabilityType B) { + return std::max(A, B); + } + + /// predefined combination Method + static ReliabilityType + CombinedInputRelCombinationMethodMult(ReliabilityType A, ReliabilityType B) { + return A * B; + } + + /// predefined combination Method + static ReliabilityType + CombinedInputRelCombinationMethodAverage(ReliabilityType A, + ReliabilityType B) { + return (A + B) / 2; + } + + /// predefined combination method + static ReliabilityType + OutputReliabilityCombinationMethodMin(ReliabilityType A, ReliabilityType B) { + return std::min(A, B); + } + + /// predefined combination method + static ReliabilityType + OutputReliabilityCombinationMethodMax(ReliabilityType A, ReliabilityType B) { + return std::max(A, B); + } + + /// predefined combination method + static ReliabilityType + OutputReliabilityCombinationMethodMult(ReliabilityType A, ReliabilityType B) { + return A * B; + } + + /// predefined combination method + static ReliabilityType + OutputReliabilityCombinationMethodAverage(ReliabilityType A, + ReliabilityType B) { + return (A + B) / 2; + } + + // ------------------------------------------------------------------------- + // Cleanup + // ------------------------------------------------------------------------- + + ~CrossCombinator() { + 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; + + /// 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; + + ReliabilityType (*CombinedCrossRelCombinationMethod)( + ReliabilityType, ReliabilityType) = CombinedCrossRelCombinationMethodMin; + + ReliabilityType (*CombinedInputRelCombinationMethod)( + ReliabilityType, ReliabilityType) = CombinedInputRelCombinationMethodMin; + + ReliabilityType (*OutputReliabilityCombinationMethod)( + ReliabilityType, ReliabilityType) = 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 score 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, + StateType scoreDifference) { + 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()(scoreDifference); + } +}; + +} // End namespace agent +} // End namespace rosa + #endif // ROSA_AGENT_CROSSRELIABILITY_H \ No newline at end of file diff --git a/lib/agent/CMakeLists.txt b/lib/agent/CMakeLists.txt index 97c4a62..9f887f9 100644 --- a/lib/agent/CMakeLists.txt +++ b/lib/agent/CMakeLists.txt @@ -1,22 +1,22 @@ set(LIB_INCLUDE_DIR ${ROSA_MAIN_INCLUDE_DIR}/rosa/agent) add_library(ROSAAgent ${LIB_INCLUDE_DIR}/namespace.h namespace.cpp ${LIB_INCLUDE_DIR}/Functionality.h Functionality.cpp ${LIB_INCLUDE_DIR}/Abstraction.hpp Abstraction.cpp ${LIB_INCLUDE_DIR}/FunctionAbstractions.hpp FunctionAbstractions.cpp ${LIB_INCLUDE_DIR}/RangeConfidence.hpp RangeConfidence.cpp ${LIB_INCLUDE_DIR}/History.hpp History.cpp ${LIB_INCLUDE_DIR}/Confidence.hpp Confidence.cpp - ${LIB_INCLUDE_DIR}/CrossReliability.h - CrossReliability.cpp + ${LIB_INCLUDE_DIR}/CrossCombinator.h + CrossCombinator.cpp ${LIB_INCLUDE_DIR}/ReliabilityConfidenceCombinator.h ReliabilityConfidenceCombinator.cpp ) diff --git a/lib/agent/CrossReliability.cpp b/lib/agent/CrossCombinator.cpp similarity index 100% rename from lib/agent/CrossReliability.cpp rename to lib/agent/CrossCombinator.cpp