diff --git a/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp b/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp index 975b95f..65032f8 100644 --- a/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp +++ b/examples/agent-functionalities/Reliability-functionality-agent-context/Reliability-agents.cpp @@ -1,334 +1,334 @@ //===- 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 inside a /// master slave context. -/// \note This is not finished +/// \note This is not finished. and is currently inactive /// //===----------------------------------------------------------------------===// #define Reliability_trace_level 5 #include "rosa/config/version.h" #include "rosa/support/log.h" #include "rosa/agent/CrossReliability.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/Reliability.h" #include "rosa/deluxe/DeluxeContext.hpp" #include #include typedef double SensorValueType; typedef long StateType; typedef double ReliabilityType; #include "./helper.h" // just stuff from Rel-func to increase readability using namespace rosa::agent; using namespace rosa; using namespace rosa::deluxe; using namespace rosa::terminal; #define NumberOfSimulationCycles 10 // ------------------------------------------------------------------------------- // Bunch of recusive templates to simplify usage // ------------------------------------------------------------------------------- template struct conversion; template class A, typename... TypesB, template class B> struct conversion, B> { using type = typename conversion, std::tuple>::type; }; template class A, typename... TypesB, template class B> struct conversion<0, A, B> { using type = DeluxeTuple; }; template using unrolled_data_type = typename conversion, std::tuple<>>::type; //-------------------------------------------------------------------------------- template struct __convert_to_vector { void operator()(std::vector> &feedback, unrolled_data_type I) { __convert_to_vector()(feedback, I); feedback.push_back({std::get(I), std::get(I)}); } }; template struct __convert_to_vector { void operator()(std::vector> &feedback, unrolled_data_type I) { feedback.push_back({std::get<0>(I), std::get<1>(I)}); } }; template void convert_to_vector( std::vector> &feedback, unrolled_data_type I) { __convert_to_vector()(feedback, I); } //---------------------------------------------------------------------------- // template struct unrole_vector {}; // // template v, typename... vT, // template class T, typename... TT, typename... types> // struct unrole_vector,T, types...> { // void operator()(c vec, types... A) { // unrole_vector, T, auto>()(vec, // vec.at(size).score, // vec.at(size).score); // } //}; // --------------------------------------------------------------------------- // main // --------------------------------------------------------------------------- int main(void) { const std::size_t number_of_states = 3; std::unique_ptr C = DeluxeContext::create("Deluxe"); //---------------------- Sensors ------------------------------------- //-------------------------------------------------------------------- const std::string SensorName1 = "Sensor1"; const std::string SensorName2 = "Sensor2"; const std::string SensorName3 = "Sensor3"; AgentHandle Sensor1 = C->createSensor( SensorName1, [&SensorName1](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName1 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); AgentHandle Sensor2 = C->createSensor( SensorName2, [&SensorName2](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName2 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); AgentHandle Sensor3 = C->createSensor( SensorName3, [&SensorName3](std::pair I) { LOG_INFO_STREAM << "\n******\n" << SensorName3 << " sensor-input " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; }); //------------------------- lowlevel agents -------------------------------- //-------------------------------------------------------------------------- const std::string LowLevelAgentName1 = "LowLevelAgent1"; const std::string LowLevelAgentName2 = "LowLevelAgent2"; const std::string LowLevelAgentName3 = "LowLevelAgent3"; using conf = unrolled_data_type< number_of_states, StateType, ReliabilityType>; // this is the confidence expressed as one tuple it // uses the format // (first.state,first.rel,second.sate...) using LowLevelAgentMasterResult = void; // no return using LowLevelReturnFromMaster = std::pair; using FloatMasterHandler = std::function; using FloatResult = Optional>; using FloatHandler = std::function, bool>)>; auto lowlevel1 = create_lowlevel_func(); auto lowlevel2 = create_lowlevel_func(); auto lowlevel3 = create_lowlevel_func(); AgentHandle SlaveAgent1 = C->createAgent( LowLevelAgentName1, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName1, lowlevel1](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName1 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel1->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName1, lowlevel1]( std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName1 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel1->operator()(std::get<0>(I.first)); DeluxeTuple ret(tmp.score, tmp.Reliability); return {ret}; })); AgentHandle SlaveAgent2 = C->createAgent( LowLevelAgentName2, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName2, lowlevel2](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName2 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel2->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName2, lowlevel2]( std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName2 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel2->operator()(std::get<0>(I.first)); DeluxeTuple ret(tmp.score, tmp.Reliability); return {ret}; })); AgentHandle SlaveAgent3 = C->createAgent( LowLevelAgentName3, // Master-input handler. FloatMasterHandler( [&LowLevelAgentName3, lowlevel3](LowLevelReturnFromMaster I) -> LowLevelAgentMasterResult { LOG_INFO_STREAM << "inside: " << LowLevelAgentName3 << "feedback\n"; if (I.second) { std::vector> feedback; convert_to_vector(feedback, I.first); lowlevel3->feedback(feedback); } }), // Slave-input handler. FloatHandler( [&LowLevelAgentName3, lowlevel3]( std::pair, bool> I) -> FloatResult { LOG_INFO_STREAM << "\n******\n" << LowLevelAgentName3 << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto tmp = lowlevel3->operator()(std::get<0>(I.first)); DeluxeTuple ret(tmp.score, tmp.Reliability); return {ret}; })); //------------------------- high level rel --------------------------------- //-------------------------------------------------------------------------- auto highlevel = create_highlevel_func(); using conf1 = Optional>; // this is the confidence expressed as one tuple it // uses the format // (first.state,first.rel,second.sate...) using MasterResult = std::tuple>, conf1, conf1, conf1>; using SlaveOutputs = DeluxeTuple; using MasterHandler = std::function, std::pair, std::pair)>; AgentHandle MasterAgent = C->createAgent( "Master Agent", MasterHandler([&](std::pair I0, std::pair I1, std::pair I2) -> MasterResult { ReliabilityForHighLevelAgents::InputType input; input.push_back({0, std::get<0>(I0.first), std::get<1>(I0.first)}); input.push_back({1, std::get<0>(I1.first), std::get<1>(I1.first)}); input.push_back({2, std::get<0>(I2.first), std::get<1>(I2.first)}); auto out = highlevel->operator()(input); DeluxeTuple rel(out.CrossReliability); conf c[3]; for (std::size_t at = 0; at < 3; at++) { std::get<0>(c[at]) = out.CrossConfidence.at(at).at(0).score; std::get<1>(c[at]) = out.CrossConfidence.at(at).at(0).Reliability; std::get<2>(c[at]) = out.CrossConfidence.at(at).at(1).score; std::get<3>(c[at]) = out.CrossConfidence.at(at).at(1).Reliability; std::get<4>(c[at]) = out.CrossConfidence.at(at).at(2).score; std::get<5>(c[at]) = out.CrossConfidence.at(at).at(2).Reliability; } return {{rel}, {c[0]}, {c[1]}, {c[2]}}; })); // ------------------------------------------------------------------------- // Sensors and connecting // ------------------------------------------------------------------------- std::vector FloatValues(NumberOfSimulationCycles); std::generate(FloatValues.begin(), FloatValues.end(), [f = 0.5f](void) mutable { f += 0.3f; return std::floor(f) + 0.5f; }); C->registerSensorValues(Sensor1, FloatValues.begin(), FloatValues.end()); C->registerSensorValues(Sensor2, FloatValues.begin(), FloatValues.end()); C->registerSensorValues(Sensor3, FloatValues.begin(), FloatValues.end()); // Connection C->connectSensor(SlaveAgent1, 0, Sensor1, "Sensor 1"); C->connectSensor(SlaveAgent2, 0, Sensor2, "Sensor 2"); C->connectSensor(SlaveAgent3, 0, Sensor3, "Sensor 3"); C->connectAgents(MasterAgent, 0, SlaveAgent1, "Slave1"); C->connectAgents(MasterAgent, 1, SlaveAgent2, "Slave2"); C->connectAgents(MasterAgent, 2, SlaveAgent3, "Slave3"); // Logger AgentHandle LoggerAgent = C->createAgent( "Logger Agent", std::function>( std::pair, bool>)>( [](std::pair, bool> Sum) -> Optional> { if (Sum.second) { LOG_INFO_STREAM << "Result: Rel: " << std::get<0>(Sum.first) << "\n"; } return {}; })); C->connectAgents(LoggerAgent, 0, MasterAgent, "Sum Agent Channel"); // ------------------------------------------------------------------------------- // Simulate // ------------------------------------------------------------------------------- C->simulate(NumberOfSimulationCycles); delete highlevel; delete lowlevel1; delete lowlevel2; } \ No newline at end of file diff --git a/include/rosa/agent/CrossCombinator.h b/include/rosa/agent/CrossCombinator.h index 05b33f5..eafb2d0 100644 --- a/include/rosa/agent/CrossCombinator.h +++ b/include/rosa/agent/CrossCombinator.h @@ -1,540 +1,551 @@ //===-- rosa/delux/CrossCombinator.h ----------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/CrossCombinator.h /// /// \author Daniel Schnoell /// /// \date 2019 /// \note based on Maximilian Goetzinger(maxgot @utu.fi) code in /// CAM_Dirty_include SA-EWS2_Version... inside Agent.cpp /// /// \brief /// /// \todo there is 1 exception that needs to be handled correctly. /// \note the default search function is extremely slow maybe this could be done /// via template for storage class and the functions/methods to efficiently find /// the correct LinearFunction //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_CROSSCOMBINATOR_H #define ROSA_AGENT_CROSSCOMBINATOR_H #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/ReliabilityConfidenceCombinator.h" #include "rosa/core/forward_declarations.h" // needed for id_t #include "rosa/support/log.h" // needed for error "handling" // nedded headers #include #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 Identifiers and Reliabilities of all given ids and /// calculates the Reliability of them together. Also it can creates the /// feedback that is needed by the \c ReliabilityAndConfidenceCombinator, which /// is a kind of confidence. /// /// \tparam IdentifierType Data type of the Identifier ( Typically double /// or float) \tparam ReliabilityType Data type of the Reliability ( Typically /// long or int) /// /// \note This class is commonly in a master slave relationship as master with /// \c ReliabilityAndConfidenceCombinator. The \c operator()() combines the /// Reliability of all connected Slaves and uses that as its own Reliability /// also creates the feedback for the Slaves. /// /// \note more information about how the Reliability and feedback is /// created at \c operator()() , \c getCombinedCrossReliability() , \c /// getCombinedInputReliability() , \c getOutputReliability() [ this is the /// used Reliability ], \c getCrossConfidence() [ this is the feedback /// for all Slaves ] /// /// a bit more special Methods \c CrossConfidence() ,\c CrossReliability() template 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 Identifiers. /// /// \param Values It gets the Identifiers and Reliabilities of /// all connected Slaves inside a vector. /// /// \return it returns a struct \c returnType containing the \c /// getCombinedCrossReliability() and \c getCrossConfidence() returnType operator()( std::vector> Values) { return {getOutputReliability(Values), getCrossConfidence(Values)}; } /// returns the combined Cross Reliability via \c /// CombinedCrossRelCombinationMethod \c /// setCombinedCrossRelCombinationMethod() for all ids \c /// CrossReliability() \param Values the used Values ReliabilityType getCombinedCrossReliability( - std::vector> Values) { + const std::vector> + &Values) noexcept { 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); if (combinedCrossRel != -1) combinedCrossRel = CombinedCrossRelCombinationMethod( combinedCrossRel, realCrossReliabilityOfSlaveAgent); else combinedCrossRel = realCrossReliabilityOfSlaveAgent; } return combinedCrossRel; } /// returns the combined via \c CombinedInputRelCombinationMethod \c /// setCombinedInputRelCombinationMethod() input reliability \param Values /// the used Values ReliabilityType getCombinedInputReliability( - std::vector> Values) { + const std::vector> + &Values) noexcept { 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) { + const std::vector> + &Values) noexcept { return OutputReliabilityCombinationMethod( getCombinedInputReliability(Values), getCombinedCrossReliability(Values)); } /// returns the crossConfidence for all ids \c CrossConfidence() /// \param Values the used Values std::map> getCrossConfidence( - std::vector> Values) { + const std::vector> + &Values) noexcept { 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 : Identifiers[id]) { ConfOrRel data; data.Identifier = thoIdentifier; data.Reliability = CrossConfidence(id, thoIdentifier, Agents); output_temporary.push_back(data); } output.insert({id, output_temporary}); } return output; } /// Calculates the Cross Confidence /// \brief it uses the Identifier value and calculates /// the Confidence of a given agent( represented by their id ) for a given /// Identifiers in connection to all other given agents /// /// \note all combination of agents and there corresponding Cross Reliability /// function have to be specified ReliabilityType - CrossConfidence(id_t MainAgent, IdentifierType TheoreticalValue, - std::vector> &SlaveAgents) { + CrossConfidence(const id_t &MainAgent, const IdentifierType &TheoreticalValue, + const std::vector> + &SlaveAgents) noexcept { 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 * std::abs(TheoreticalValue - SlaveAgent.second)); // profile reliability ReliabilityType crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent, SlaveAgent.first, std::abs(TheoreticalValue - SlaveAgent.second)); values.push_back( std::max(crossReliabiability, crossReliabilityFromProfile)); } return Method(values); } /// Calculates the Cross Reliability /// \brief it uses the Identifier value and calculates /// the Reliability of a given agent( represented by their id ) in connection /// to all other given agents /// /// \note all combination of agents and there corresponding Cross Reliability /// function have to be specified ReliabilityType - CrossReliability(std::pair &&MainAgent, - std::vector> &SlaveAgents) { + CrossReliability(const std::pair &MainAgent, + const std::vector> + &SlaveAgents) noexcept { 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 * std::abs(MainAgent.second - SlaveAgent.second)); // profile reliability ReliabilityType crossReliabilityFromProfile = getCrossReliabilityFromProfile( MainAgent.first, SlaveAgent.first, std::abs(MainAgent.second - SlaveAgent.second)); values.push_back( std::max(crossReliabiability, crossReliabilityFromProfile)); } return Method(values); } // -------------------------------------------------------------------------- // Defining the class // -------------------------------------------------------------------------- /// adds a Cross Reliability Profile used to get the Reliability of the /// Identifier difference /// /// \param idA The id of the one \c Agent ( ideally the id of \c Unit to make /// it absolutely unique ) /// /// \param idB The id of the other \c Agent /// /// \param Function A shared pointer to an \c Abstraction it would use the /// difference in Identifier for its input - void addCrossReliabilityProfile(id_t idA, id_t idB, - std::shared_ptr &Function) { + void addCrossReliabilityProfile( + const id_t &idA, const id_t &idB, + const std::shared_ptr &Function) noexcept { Functions.push_back({true, idA, idB, Function}); } /// sets the cross reliability parameter - void setCrossReliabilityParameter(ReliabilityType val) { + void setCrossReliabilityParameter(const ReliabilityType &val) noexcept { crossReliabilityParameter = val; } /// This is the adder for the Identifiers /// \param id The id of the Agent of the Identifiers /// \param Identifiers id specific Identifiers. This will be copied So that if /// Slaves have different Identifiers they can be used correctly. \brief The /// Identifiers of all connected slave Agents has to be known to be able to /// iterate over them - void addIdentifiers(id_t id, std::vector Identifiers) { + void addIdentifiers(const id_t &id, + const std::vector &Identifiers) noexcept { this->Identifiers.insert({id, Identifiers}); } // ------------------------------------------------------------------------- // Combinator Settings // ------------------------------------------------------------------------- /// sets the used method to combine the values /// \param Meth the method which should be used. predefined functions in the /// struct \c predefinedMethods \c /// CONJUNCTION() \c AVERAGE() \c DISJUNCTION() void setCrossReliabilityCombinatorMethod( - std::function values)> - Meth) { + const std::function values)> + &Meth) noexcept { Method = Meth; } /// sets the combination method for the combined cross reliability /// \param Meth the method which should be used. predefined functions in the /// struct \c predefinedMethods CombinedCrossRelCombinationMethod() void setCombinedCrossRelCombinationMethod( - std::function Meth) { + const std::function + &Meth) noexcept { CombinedCrossRelCombinationMethod = Meth; } /// sets the combined input rel method /// \param Meth the method which should be used. predefined functions in the /// struct \c predefinedMethods CombinedInputRelCombinationMethod() void setCombinedInputRelCombinationMethod( - std::function Meth) { + const std::function + &Meth) noexcept { CombinedInputRelCombinationMethod = Meth; } /// sets the used OutputReliabilityCombinationMethod /// \param Meth the method which should be used. predefined functions in the /// struct \c predefinedMethods OutputReliabilityCombinationMethod() void setOutputReliabilityCombinationMethod( - std::function Meth) { + const std::function + &Meth) noexcept { OutputReliabilityCombinationMethod = Meth; } // ------------------------------------------------------------------------- // Predefined Functions // ------------------------------------------------------------------------- /// This struct is a pseudo name space to have easier access to all predefined /// methods while still not overcrowding the class it self struct predefinedMethods { /// predefined combination method static ReliabilityType CONJUNCTION(std::vector 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() { Functions.clear(); } // -------------------------------------------------------------------------- // Parameters // -------------------------------------------------------------------------- private: struct Functionblock { bool exists = false; id_t A; id_t B; std::shared_ptr Funct; }; std::map> Identifiers; /// From Maxi in his code defined as 1 can be changed by set ReliabilityType crossReliabilityParameter = 1; /// Stored Cross Reliability Functions std::vector Functions; /// Method which is used to combine the generated values std::function)> Method = predefinedMethods::AVERAGE; std::function CombinedCrossRelCombinationMethod = predefinedMethods::CombinedCrossRelCombinationMethodMin; std::function CombinedInputRelCombinationMethod = predefinedMethods::CombinedInputRelCombinationMethodMin; std::function OutputReliabilityCombinationMethod = predefinedMethods::OutputReliabilityCombinationMethodMin; //-------------------------------------------------------------------------------- // helper function /// very inefficient searchFunction Functionblock (*searchFunction)(std::vector vect, const id_t nameA, const id_t nameB) = [](std::vector vect, const id_t nameA, const id_t nameB) -> Functionblock { for (Functionblock tmp : vect) { if (tmp.A == nameA && tmp.B == nameB) return tmp; if (tmp.A == nameB && tmp.B == nameA) return tmp; } return Functionblock(); }; /// evaluates the corresponding LinearFunction with the Identifier difference /// \param nameA these two parameters are the unique identifiers /// \param nameB these two parameters are the unique identifiers /// for the LinerFunction /// /// \note it doesn't matter if they are swapped - ReliabilityType - getCrossReliabilityFromProfile(id_t nameA, id_t nameB, - IdentifierType IdentifierDifference) { + ReliabilityType getCrossReliabilityFromProfile( + const id_t &nameA, const id_t &nameB, + const IdentifierType &IdentifierDifference) noexcept { Functionblock block = searchFunction(Functions, nameA, nameB); if (!block.exists) { LOG_ERROR(("CrossReliability: Block:" + std::to_string(nameA) + "," + std::to_string(nameB) + "doesn't exist returning 0")); return 0; } return block.Funct->operator()(IdentifierDifference); } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_CROSSCOMBINATOR_H \ No newline at end of file