diff --git a/include/rosa/agent/CrossReliability.h b/include/rosa/agent/CrossReliability.h index 8442566..03c6410 100644 --- a/include/rosa/agent/CrossReliability.h +++ b/include/rosa/agent/CrossReliability.h @@ -1,286 +1,345 @@ //===-- 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 maby 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 +#define ROSA_LOG_LEVEL 100 + +#include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Functionality.h" -#include "rosa/agent/LinearFunctions.hpp" #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 class CrossReliability : public Functionality { - using PartialFunction = typename rosa::agent::PartialFunction; +/// 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 coresponding Cross Reliability +/// function have to be specified +template +class CrossReliability : public Abstraction { + using Abstraction = typename rosa::agent::Abstraction; struct Functionblock { bool exists = false; id_t A; id_t B; - PartialFunction *Funct; + Abstraction *Funct; }; + /// From Maxi in his code defined as 1 can be changed by set Type crossReliabilityParameter = 1; + /// Stored Cross Reliability Functions std::vector Functions; + + /// Method which is used to combine the generated values Type (*Method)(std::vector values) = AVERAGE; //-------------------------------------------------------------------------------- - // helper functions + // helper function /// evalues the absolute distance between two values - Type AbsuluteValue(Type A, Type B) { return ((A - B) < 0) ? B - A : A - B; } + /// \note this is actually the absolute distance but to ceep it somewhat + /// conform with maxis code + template Type_t AbsuluteValue(Type_t A, Type_t B) { + static_assert(std::is_arithmetic::value); + return ((A - B) < 0) ? B - A : A - B; + } /// verry 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(); }; /// evaluest the corisponding LinearFunction thith 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 + /// for the LinerFunction + /// + /// \note If the block nameA nameB doesn't exist it logs the error and returns + /// 0 + /// \note it doesn't matter if they are swapped Type getCrossReliabilityFromProfile(id_t nameA, id_t nameB, - Type scoreDifference) { + StateType scoreDifference) { Functionblock block = searchFunction(Functions, nameA, nameB); - if (!block.exists) - // throw "does not exist"; // exceptions are disabled in rosa Todo : - // handle - // this right - return block.Funct->operator()(scoreDifference); + 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); } public: - void addCrossReliabilityProfile(id_t idA, id_t idB, - PartialFunction *Function) { + /// adds a Cross Reliability Profile used to get the Reliability of the state + /// difference + void addCrossReliabilityProfile(id_t idA, id_t idB, Abstraction *Function) { Functions.push_back({true, idA, idB, Function}); } + /// sets the cross reliability parameter void setCrossReliabilityParameter(Type val) { crossReliabilityParameter = val; } - + /// sets the used method to combine the values void setCrossReliabilityMethod(Type (*Meth)(std::vector values)) { Method = Meth; } ~CrossReliability() { for (auto tmp : Functions) delete tmp.Funct; + Functions.clear(); } /// Calculets the CrossReliability /// \note both Main and Slaveagents are represented by there data and an /// unique identifier /// /// \param MainAgent defines the value pair around which the Cross Reliability /// is calculated - /// \param SlaveAgents defines all value pairs of the connected Agents - Type operator()(std::pair &MainAgent, - std::vector> &SlaveAgents); + /// \param SlaveAgents defines all value pairs of the connected Agents it + /// doesn't matter if Main agent exists inside this vector + Type operator()(std::pair &MainAgent, + std::vector> &SlaveAgents); /// predefined combination method static Type CONJUNCTION(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return *std::min_element(values.begin(), values.end()); } /// predefined combination method static Type AVERAGE(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return std::accumulate(values.begin(), values.end(), 0.0) / values.size(); } /// predefined combination method static Type DISJUNCTION(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return *std::max_element(values.begin(), values.end()); } }; -template -inline Type CrossReliability:: -operator()(std::pair &MainAgent, - std::vector> &SlaveAgents) { - static_assert(std::is_arithmetic::value); // sanitny check +template +inline Type CrossReliability:: +operator()(std::pair &MainAgent, + std::vector> &SlaveAgents) { + static_assert(std::is_arithmetic::value); // sanitny check + static_assert(std::is_arithmetic::value); // sanitny check Type crossReliabiability; std::vector values; - for (std::pair SlaveAgent : SlaveAgents) { + 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 Type crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent.first, SlaveAgent.first, AbsuluteValue(MainAgent.second, SlaveAgent.second)); values.push_back( std::max(crossReliabiability, crossReliabilityFromProfile)); } return Method(values); } -template class CrossConfidence : public Functionality { - using PartialFunction = typename rosa::agent::PartialFunction; +/// Calculates the Cross Confidence +/// \brief It uses the a theoretical 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 this can be used to get a Confidence of +/// the current state +/// +/// \note all combination of agents and there coresponding Cross Reliability +/// function have to be specified +template +class CrossConfidence : public Abstraction { + using Abstraction = typename rosa::agent::Abstraction; struct Functionblock { bool exists = false; id_t A; id_t B; - PartialFunction *Funct; + Abstraction *Funct; }; + /// From Maxi in his code defined as 1 can be changed by set Type crossReliabilityParameter = 1; + /// Stored Cross Reliability Functions std::vector Functions; + + /// Method which is used to combine the generated values Type (*Method)(std::vector values) = AVERAGE; //-------------------------------------------------------------------------------- - // helper functions + // helper function /// evalues the absolute distance between two values - Type AbsuluteValue(Type A, Type B) { return ((A - B) < 0) ? B - A : A - B; } + /// \note this is actually the absolute distance but to ceep it somewhat + /// conform with maxis code + template Type_t AbsuluteValue(Type_t A, Type_t B) { + static_assert(std::is_arithmetic::value); + return ((A - B) < 0) ? B - A : A - B; + } /// verry 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(); }; /// evaluest the corisponding LinearFunction thith 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 + /// for the LinerFunction + /// + /// \note it doesn't matter if they are swapped Type getCrossReliabilityFromProfile(id_t nameA, id_t nameB, - Type scoreDifference) { + StateType scoreDifference) { Functionblock block = searchFunction(Functions, nameA, nameB); - if (!block.exists) - // throw "does not exist"; // exceptions are disabled in rosa Todo : - // handle - // this right - return block.Funct->operator()(scoreDifference); + 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); } public: - void addCrossReliabilityProfile(id_t idA, id_t idB, - PartialFunction *Function) { + /// adds a Cross Reliability Profile used to get the Reliability of the state + /// difference + void addCrossReliabilityProfile(id_t idA, id_t idB, Abstraction *Function) { Functions.push_back({true, idA, idB, Function}); } + /// sets the cross reliability parameter void setCrossReliabilityParameter(Type val) { crossReliabilityParameter = val; } - + /// sets the used method to combine the values void setCrossReliabilityMethod(Type (*Meth)(std::vector values)) { Method = Meth; } ~CrossConfidence() { for (auto tmp : Functions) delete tmp.Funct; + Functions.clear(); } - Type operator()(id_t MainAgent, Type TheoreticalValue, - std::vector> &SlaveAgents); + Type operator()(id_t MainAgent, StateType TheoreticalValue, + std::vector> &SlaveAgents); /// predefined combination method static Type CONJUNCTION(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return *std::min_element(values.begin(), values.end()); } /// predefined combination method static Type AVERAGE(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return std::accumulate(values.begin(), values.end(), 0.0) / values.size(); } /// predefined combination method static Type DISJUNCTION(std::vector values) { static_assert(std::is_arithmetic::value); // sanitny check return *std::max_element(values.begin(), values.end()); } }; -template -inline Type CrossConfidence:: -operator()(id_t MainAgent, Type TheoreticalValue, - std::vector> &SlaveAgents) { +template +inline Type CrossConfidence:: +operator()(id_t MainAgent, StateType TheoreticalValue, + std::vector> &SlaveAgents) { + static_assert(std::is_arithmetic::value); // sanitny check + static_assert(std::is_arithmetic::value); // sanitny check + Type crossReliabiability; std::vector values; - for (std::pair SlaveAgent : SlaveAgents) { + 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 Type crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent, SlaveAgent.first, AbsuluteValue(TheoreticalValue, SlaveAgent.second)); values.push_back( std::max(crossReliabiability, crossReliabilityFromProfile)); } return Method(values); } } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_CROSSRELIABILITY_H \ No newline at end of file