diff --git a/examples/agent-functionalities/Reliability-functionality.cpp b/examples/agent-functionalities/Reliability-functionality.cpp index 860b303..358edba 100644 --- a/examples/agent-functionalities/Reliability-functionality.cpp +++ b/examples/agent-functionalities/Reliability-functionality.cpp @@ -1,238 +1,245 @@ //===- 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 \c rosa::Agent instances using /// Relianility Functionalities. /// //===----------------------------------------------------------------------===// #include "rosa/config/version.h" #include "rosa/core/Agent.hpp" #include "rosa/core/MessagingSystem.hpp" #include "rosa/support/log.h" #include "rosa/support/terminal_colors.h" #include "rosa/agent/Reliability.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/CrossReliability.h" #include #include using namespace rosa::agent; int main(void) { typedef double SensorValueType; typedef long StateType; typedef double ReliabilityType; // defining Range confidence auto 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)} }); Abstraction* Reliability = new LinearFunction(1,-1.0/9); auto ReliabilitySlope = new LinearFunction(1, -1.0/9); auto TimeConfidence = new LinearFunction(1, -1.0/9); auto lowlevel = new LowLevel (); 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 ---------------------------------------------------------------- */ for ( int a= 0 ; a <10 ; a++) std::cout <<"a: " << a << "\n" << (lowlevel->feedback({{0,0},{1,0.3},{2,0.5}}),lowlevel->operator()(a)) << "\n"; /* ----------------------------- Cleanup --------------------------------------------------------------------- */ std::cout << "------------------------------------------------------------------------------------------------\n"; std::cout << "------------------------------------High level Test---------------------------------------------\n"; auto 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)} }); Abstraction* Reliability2 = new LinearFunction(1,-1.0/9); auto ReliabilitySlope2 = new LinearFunction(1, -1.0/9); auto TimeConfidence2 = new LinearFunction(1, -1.0/9); auto lowlevel2 = new LowLevel (); 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); HighLevel* highlevel=new HighLevel(); CrossReliability* CrossReliability1= new CrossReliability(); Abstraction* func1=new PartialFunction({ {{0, 1}, std::make_shared> (1, 0)}, {{1,2}, std::make_shared> (2, -1.0)}, },0); CrossReliability1->addCrossReliabilityProfile(0,1,func1); CrossReliability1->setCrossReliabilityMethod(CrossReliability::AVERAGE); CrossReliability1->setCrossReliabilityParameter(1); CrossConfidence* CrossConfidence1= new CrossConfidence(); Abstraction* func2=new PartialFunction({ {{0, 1}, std::make_shared> (1, 0)}, {{1,2}, std::make_shared> (2, -1.0)}, },0); CrossConfidence1->addCrossReliabilityProfile(0,1,func2); CrossConfidence1->setCrossReliabilityMethod(CrossConfidence::AVERAGE); CrossConfidence1->setCrossReliabilityParameter(1); highlevel->setFunction(CrossConfidence1); highlevel->setFunction(CrossReliability1); highlevel->MaximumState=2; + highlevel->addStates(0,states); + highlevel->addStates(1,states); for ( int a= 0 ; a <21 ; a++) { auto out1=lowlevel->operator()(a),out2=lowlevel2->operator()(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"; - std::vector::ConfOrRel> tmp; + /* 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(tmp); + lowlevel->feedback(q.second); else - lowlevel2->feedback(tmp); + lowlevel2->feedback(q.second); } } delete lowlevel; delete lowlevel2; } \ No newline at end of file diff --git a/include/rosa/agent/Reliability.h b/include/rosa/agent/Reliability.h index 18998fd..94aaea3 100644 --- a/include/rosa/agent/Reliability.h +++ b/include/rosa/agent/Reliability.h @@ -1,433 +1,500 @@ //===-- rosa/agent/Reliability.h --------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/Reliability.h /// /// \author Daniel Schnoell (danielschnoell@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *reliability* *functionality*. /// /// \note All classes throw runtime errors if not all things are set /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_RELIABILITY_H #define ROSA_AGENT_RELIABILITY_H #include "rosa/agent/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/RangeConfidence.hpp" #include "rosa/agent/CrossReliability.h" #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" -#define __ostream_output true namespace rosa { namespace agent { + template< typename StateType,typename ReliabilityType> + struct ConfOrRel { + typedef StateType _StateType; + typedef ReliabilityType _ReliabilityType; + + StateType score; + ReliabilityType Reliability; + + ConfOrRel(StateType _score, ReliabilityType _Reliability) :score(_score), Reliability(_Reliability) {}; + ConfOrRel() {}; + + friend std::ostream& operator << (std::ostream& out, const ConfOrRel& c) + { + out << "Score: " << c.score << "\t Reliability: " << c.Reliability << " "; + return out; + } + + typedef std::map map; // needed or it throws an clang diagnosic erroor + 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; + } + + friend std::vector operator+=(std::vector &me, std::vector other) + { + static_assert(std::is_arithmetic::value); + for (auto tmp_me:me) + for (auto tmp_other:other) { + if (tmp_me.score == tmp_other.score) { + tmp_me.Reliability =tmp_me.Reliability + tmp_other.Reliability; + } + } + return me; + } + + 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; + } + }; + + 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 is the Reliability Functionality for a low level Agent /// \tparam SensorValueType Datatype of the Sensor value ( Typically double or float) /// \tparam StateType Datatype of the State ( Typically long or int) /// \tparam ReliabilityType Datatype of the Reliability ( Typically double or float) /// /// use the () operator to get the reliability and feed the information from the master back to this /// \note all pointer for the functionalities will be deleted when this is object ist destroyed template class LowLevel { public: - struct ConfOrRel { - StateType score; - ReliabilityType Reliability; - - ConfOrRel(StateType _score,ReliabilityType _Reliability):score(_score),Reliability(_Reliability){}; - ConfOrRel() {}; - #if __ostream_output - friend std::ostream & operator << (std::ostream &out, const ConfOrRel &c) - { - out << "Score: " << c.score << "\t Reliability: " << c.Reliability << " " ; - return out; - } - #endif - }; + + typedef ConfOrRel ConfOrRel; /// Calculates the Conf/ Reliability /// \param SensorValue The current Values of the Sensor /// /// \return Reliability of the current Value ConfOrRel operator()(SensorValueType SensorValue) { - std::map ActuallPosibleScores_tmp = Confidence->operator()(SensorValue); - - std::vector ActuallPossibleScores; - for (StateType state : States) - { - if(ActuallPosibleScores_tmp.find(state)!=ActuallPosibleScores_tmp.end()) - { - ConfOrRel val; - val.score=state; - val.Reliability=ActuallPosibleScores_tmp.find(state)->second; - ActuallPossibleScores.push_back(val); - } - - } - ReliabilityType inputReliability; +#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" + ) + <operator()(SensorValue); + std::vector ActuallPossibleScores; + std::vector possibleScores; + ReliabilityType inputReliability =getRelibility(SensorValue, previousSensorValue, valueSetCounter); - std::cout << "input Rel: " << inputReliability << "\n"; - for (std::size_t at = 0; at < ActuallPossibleScores.size(); at++) - ActuallPossibleScores.at(at).Reliability = std::min(ActuallPossibleScores.at(at).Reliability, inputReliability); +#if Reliability_trace_level<=trace_vectors + LOG_TRACE_STREAM << "\ninput Rel: " << inputReliability << trace_end; +#endif - for (std::size_t APS_at = 0; APS_at < ActuallPossibleScores.size(); APS_at++) - for (std::size_t VFM_at = 0; VFM_at < ValuesFromMaster.size(); VFM_at++) { - if (ActuallPossibleScores.at(APS_at).score == ValuesFromMaster.at(VFM_at).score) { - ActuallPossibleScores.at(APS_at).Reliability = ActuallPossibleScores.at(APS_at).Reliability + ValuesFromMaster.at(VFM_at).Reliability; - } - } + + ActuallPossibleScores << Confidence->operator()(SensorValue); + + + ActuallPossibleScores = min(ActuallPossibleScores,inputReliability); + + ActuallPossibleScores += ValuesFromMaster; saveInHistory(ActuallPossibleScores); - std::vector possibleScores; - possibleScores=getAllPossibleScoresBasedOnHistory(possibleScores); - std::sort(possibleScores.begin(), possibleScores.end(), [](ConfOrRel A, ConfOrRel B)-> bool {return A.Reliability > B.Reliability; }); + possibleScores = getAllPossibleScoresBasedOnHistory(possibleScores); + + std::sort(possibleScores.begin(), possibleScores.end(), + [](ConfOrRel A, ConfOrRel B)-> bool { + static_assert(std::is_arithmetic::value); + return A.Reliability > B.Reliability; } + ); previousSensorValue = SensorValue; PreviousSensorValueExists = true; - for(auto val:ActuallPossibleScores) - std::cout <<"inside APS:" << val << "\n"; - for(auto val:possibleScores) - std::cout <<"inside PS:" << val << "\n"; - +#if Reliability_trace_level<=trace_vectors + LOG_TRACE_STREAM << "\nActuallPossibleScores:\n" << ActuallPossibleScores << trace_end; + LOG_TRACE_STREAM << "\npossibleScores:\n" << possibleScores << trace_end; +#endif +#if Reliability_trace_level<=trace_outputs + LOG_TRACE_STREAM << "\noutput lowlevel: " << possibleScores.at(0) << trace_end; +#endif return possibleScores.at(0); } /// Needed feedback from the Master /// \param ValuesFromMaster The Scores + Reliability from the Master for this Agent void feedback(std::vector ValuesFromMaster) { this->ValuesFromMaster = ValuesFromMaster; } /// This is the setter for Confidence Function /// \param Confidence A pointer to the Functional for the Confidence void setConfidenceFunction(RangeConfidence* Confidence) { this->Confidence = Confidence; } /// This is the setter for Reliability Function /// \param Reliability A pointer to the Functional for the Reliability void setReliabilityFunction(Abstraction* Reliability) { this->Reliability = Reliability; } /// This is the setter for ReliabilitySlope Function /// \param ReliabilitySlope A pointer to the Functional for the ReliabilitySlope void setReliabilitySlopeFunction(Abstraction* ReliabilitySlope) { this->ReliabilitySlope = ReliabilitySlope; } /// This is the setter for TimeConfidence Function /// \param TimeConfidence A pointer to the Functional for the TimeConfidence void setTimeConfidenceFunction(Abstraction* TimeConfidence) { this->TimeConfidence = TimeConfidence; } /// This is the setter for all possible States /// \param states A vertor for all states void setStates(std::vector states) { this->States=states; } /// This sets the Maximum length of the Histpry /// \param length The length void setHistoryLength(std::size_t length) { this->HistoryMaxSize=length; } /// This sets the Value set Counter /// \param ValueSetCounter the new Value void setValueSetCounter(unsigned int ValueSetCounter) { this->valueSetCounter=ValueSetCounter; } /// deletes all given pointers ~LowLevel() { delete Confidence; Confidence = nullptr; delete Reliability; Reliability = nullptr; delete ReliabilitySlope; ReliabilitySlope = nullptr; delete TimeConfidence; TimeConfidence = nullptr; } private: std::vector> History; std::size_t HistoryMaxSize; std::vector ValuesFromMaster; SensorValueType previousSensorValue; unsigned int valueSetCounter; std::vector States; bool PreviousSensorValueExists = false; RangeConfidence* Confidence = nullptr; Abstraction* Reliability = nullptr; Abstraction* ReliabilitySlope = nullptr; Abstraction* TimeConfidence = nullptr; /*--------------------------------- needed Funktions -----------------------------------------------------*/ /// returns the Reliability /// \param actualValue The Value of the Sensor /// \param lastValue of the Sensor this is stored in the class /// \param valueSetCounter Todo - ReliabilityType getRelibility(SensorValueType actualValue, SensorValueType lastValue, unsigned int valueSetCounter) { - + ReliabilityType getRelibility(SensorValueType actualValue, SensorValueType lastValue, unsigned int valueSetCounter) + { + static_assert(std::is_arithmetic::value); ReliabilityType relAbs = Reliability->operator()(actualValue); if (PreviousSensorValueExists) { ReliabilityType relSlo = ReliabilitySlope->operator()((lastValue - actualValue) / (SensorValueType)valueSetCounter); // calculate signal input reliability // NOTE: options would be multiply, average, AND (best to worst: // average = AND > multiply) rel = relAbs * relSlo; rel = (relAbs + // relSlo)/2; return std::min(relAbs, relSlo); } else return relAbs; } /// adabts the possible Scores by checking the History and combines those values currently with max /// \param possibleScores This is returned from the Master - std::vector getAllPossibleScoresBasedOnHistory(std::vector possibleScores) { + std::vector getAllPossibleScoresBasedOnHistory(std::vector possibleScores) + { //iterate through all history entries std::size_t posInHistory = 0; for (auto pShE = History.begin(); pShE < History.end(); pShE++, posInHistory++) { //iterate through all possible scores of each history entry for (ConfOrRel& pSh : *pShE) { //printf("a3\n"); StateType historyScore = pSh.score; ReliabilityType historyConf = pSh.Reliability; //combine each history score with the confidence of time //NOTE: multiplication, AND, or average would be alternatives (best to worst: multiplication = AND = average) historyConf = historyConf * TimeConfidence->operator()(posInHistory); //historyConf = (historyConf + TimeConfidence(posInHistory)) / 2; //historyConf = std::min(historyConf, TimeConfidence(posInHistory)); //printf("a4\n"); bool foundScore = false; for (ConfOrRel& pS : possibleScores) { if (pS.score == historyScore) { //calculate confidence for score //NOTE: multiplication, AND, or average would be alternatives (best to worst: AND >> average = multiplication ) //pS->confOrRel = pS->confOrRel * historyConf; //pS->confOrRel = (pS->confOrRel + historyConf) / 2; pS.Reliability = std::max(pS.Reliability, historyConf); foundScore = true; } } if (foundScore == false) { ConfOrRel possibleScore; possibleScore.score = historyScore; possibleScore.Reliability = historyConf; possibleScores.push_back(possibleScore); } } } return possibleScores; } /// saves the Scores in the History /// \param actualPossibleScores The Scores which should be saved void saveInHistory(std::vector actualPossibleScores) { //check if the reliability of at least one possible score is high enough bool atLeastOneRelIsHigh = false; for (ConfOrRel pS : actualPossibleScores) { if (pS.Reliability > 0.5) { atLeastOneRelIsHigh = true; } } //save possible scores if at least one possible score is high enough (or if the history is empty) if (History.size() < 1 || atLeastOneRelIsHigh == true) { History.insert(History.begin(),actualPossibleScores); //if history size is higher than allowed, savo oldest element while (History.size() > HistoryMaxSize) { //delete possibleScoreHistory.back(); History.pop_back(); } } } }; /// This is the Reliability Functionality for the Highlevel Agent /// \tparam StateType Datatype of the State ( Typically double or float) /// \tparam ReliabilityType Datatype of the Reliability ( Typically long or int) /// /// use the () operator to calculate the Reliability and all cross confidences for all slaves /// \note all pouinter to Funcionalities get deleted upon termitation of the object template class HighLevel { public: - struct ConfOrRel { - StateType score; - ReliabilityType Reliability; - - ConfOrRel(StateType _score,ReliabilityType _Reliability):score(_score),Reliability(_Reliability){}; - ConfOrRel() {}; - #if __ostream_output - friend std::ostream & operator << (std::ostream &out, const ConfOrRel &c) - { - out << "Score: " << c.score << "\t Reliability: " << c.Reliability << " " ; - return out; - } - #endif - }; + typedef ConfOrRel ConfOrRel; struct returnType { ReliabilityType CrossReliability; - std::vector>> CrossConfidence; + std::map> CrossConfidence; }; StateType MaximumState; returnType operator()(std::vector> &Values) { StateType EWS = 0; ReliabilityType combinedInputRel = 1; ReliabilityType combinedCrossRel = 1; ReliabilityType outputReliability; std::vector> Agents; - std::vector>> output; - std::vector output_temporary; + std::map> output; + std::vector output_temporary; for (auto tmp : Values) { std::pair tmp2; tmp2.first = std::get<0>(tmp); tmp2.second = std::get<1>(tmp); Agents.push_back(tmp2); } for (auto Value : Values) { id_t id = std::get<0>(Value); StateType sc = std::get<1>(Value); ReliabilityType rel = std::get<2>(Value); EWS = EWS + sc; combinedInputRel = std::min(combinedInputRel, rel); //calculate the cross reliability for this slave agent ReliabilityType realCrossReliabilityOfSlaveAgent = CrossReliability->operator()({id,sc }, Agents); //AVERAGE, MULTIPLICATION, CONJUNCTION (best to worst: AVERAGE = CONJUNCTION > MULTIPLICATION >> ) output_temporary.clear(); - for (StateType theoreticalScore = 0; theoreticalScore <= MaximumState; theoreticalScore++) { + for (StateType thoScore:States[id]) { //calculate the cross reliability for this slave agent ConfOrRel data; - data.score = theoreticalScore; - data.Reliability = CrossConfidence->operator()(id, theoreticalScore, Agents); + data.score = thoScore; + data.Reliability = CrossConfidence->operator()(id, thoScore, Agents); output_temporary.push_back(data); } - output.push_back({ std::get<0>(Value),output_temporary }); + output.insert({ std::get<0>(Value),output_temporary }); combinedCrossRel = std::min(combinedCrossRel, realCrossReliabilityOfSlaveAgent); } //combine cross reliabilites and input reliabilites of all slave agents //NOTE: options would be multiply, average, AND (best to worst: ) //outputReliability = combinedInputRel * combinedCrossRel; //outputReliability = (combinedInputRel + combinedCrossRel) / 2; outputReliability = std::min(combinedInputRel, combinedCrossRel); return { outputReliability,output }; } /// This is the setter for CrossReliability Function - /// param A pointer to the Functional for the CrossReliability + /// \param CrossReliability A pointer to the Functional for the CrossReliability void setFunction(CrossReliability* CrossReliability) { this->CrossReliability = CrossReliability; } /// This is the setter for CrossConfidence Function - /// param A pointer to the Functional for the CrossConfidence + /// \param CrossConfidence A pointer to the Functional for the CrossConfidence void setFunction(CrossConfidence * CrossConfidence) { this->CrossConfidence = CrossConfidence; } + /// This the adder for the states + /// \param States id spezific states this will be copied + void addStates( id_t id, std::vector States) + { + this->States.insert({id,States}); + } + + /// deletes all given pointers ~HighLevel() { delete CrossReliability; CrossConfidence = nullptr; delete CrossConfidence; CrossConfidence = nullptr; } private: CrossReliability* CrossReliability = nullptr; CrossConfidence * CrossConfidence = nullptr; + std::map> States; + }; } // namespace agent }// namespace rosa #endif // !ROSA_AGENT_RELIABILITY_H