diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp index b130bbd..9d7cba7 100644 --- a/include/rosa/agent/SignalState.hpp +++ b/include/rosa/agent/SignalState.hpp @@ -1,528 +1,471 @@ //===-- rosa/agent/SignalState.hpp ------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SignalState.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *signal state* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SIGNALSTATE_HPP #define ROSA_AGENT_SIGNALSTATE_HPP #include "rosa/agent/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/History.hpp" #include "rosa/support/math.hpp" namespace rosa { namespace agent { +/// Signal properties defining the properties of the signal which is monitored +/// by \c rosa::agent::SignalStateDetector and is saved in \c +/// rosa::agent::SignalStateInformation. +enum SignalProperties : uint8_t { + INPUT = 0, ///< The signal is an input signal + OUTPUT = 1 ///< The signal is an output signal +}; + /// Signal state conditions defining how the condition of a \c /// rosa::agent::SignalState is saved in \c rosa::agent::SignalStateInformation. enum SignalStateCondition : uint8_t { STABLE = 0, ///< The signal state is stable DRIFTING = 1, ///< The signal state is drifting UNKNOWN = 2 ///< The signal state is unknown }; /// TODO: write description template struct SignalStateInformation { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "confidence type is not to arithmetic"); /// The signal state ID saved as an uint32_teger number uint32_t SignalStateID; + /// The SignalProperty saves whether the monitored signal is an input our + /// output signal. + SignalProperties SignalProperty; /// The SignalStateConfidence shows the overall confidence value of the signal /// state. CONFDATATYPE SignalStateConfidence; /// The SignalStateCondition shows the condition of a signal state (stable, /// drifting, or unknown) SignalStateCondition SignalStateCondition; /// The SignalStateIsValid saves the number of samples which have been /// inserted into the state after entering it. uint32_t NumberOfInsertedSamplesAfterEntrance; /// The SignalStateIsValid shows whether a signal state is valid or invalid. /// In this context, valid means that enough samples which are in close /// proximitry have been inserted into the signal state. bool SignalStateIsValid; /// The SignalStateJustGotValid shows whether a signal state got valid /// (toggled from invalid to valid) during the current inserted sample. bool SignalStateJustGotValid; /// The SignalStateIsValidAfterReentrance shows whether a signal state is /// valid after the variable changed back to it again. bool SignalStateIsValidAfterReentrance; - /// The SignalIsStableNotDrifting shows whether a signal is stable and not - /// drifting. - bool SignalIsStable; }; /// \tparam INDATATYPE type of input data, \tparam CONFDATATYPE type of /// data in that the confidence values are given, \tparam PROCDATATYPE type of /// the relative distance and the type of data in which DABs are saved. template class SignalState : public Functionality { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "input data type not arithmetic"); STATIC_ASSERT((std::is_arithmetic::value), "confidence data type is not to arithmetic"); STATIC_ASSERT( (std::is_arithmetic::value), "process data type (DAB and Relative Distance) is not to arithmetic"); -private: +public: // For the convinience to write a shorter data type name - using PartFuncPointer = - std::shared_ptr>; - using StepFuncPointer = - std::shared_ptr>; + using PartFuncReference = PartialFunction &; + using StepFuncReference = StepFunction &; +private: /// SignalStateInfo is a struct SignalStateInformation that contains /// information about the current state. SignalStateInformation SignalStateInfo; /// The FuzzyFunctionSampleMatches is the fuzzy function that gives the /// confidence how good the new sample matches another sample in the sample /// history. - PartFuncPointer FuzzyFunctionSampleMatches; + PartFuncReference FuzzyFunctionSampleMatches; /// The FuzzyFunctionSampleMismatches is the fuzzy function that gives the /// confidence how bad the new sample matches another sample in the sample /// history. - PartFuncPointer FuzzyFunctionSampleMismatches; + PartFuncReference FuzzyFunctionSampleMismatches; /// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the /// confidence how many samples from the sampe history match the new sample. - StepFuncPointer FuzzyFunctionNumOfSamplesMatches; + StepFuncReference FuzzyFunctionNumOfSamplesMatches; /// The FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives /// the confidence how many samples from the sampe history mismatch the new /// sample. - StepFuncPointer FuzzyFunctionNumOfSamplesMismatches; + StepFuncReference FuzzyFunctionNumOfSamplesMismatches; /// The FuzzyFunctionSignalIsDrifting is the fuzzy function that gives the /// confidence how likely it is that the signal (resp. the state of a signal) /// is drifting. - PartFuncPointer FuzzyFunctionSignalIsDrifting; + PartFuncReference FuzzyFunctionSignalIsDrifting; /// The FuzzyFunctionSignalIsStable is the fuzzy function that gives the /// confidence how likely it is that the signal (resp. the state of a signal) /// is stable (not drifting). - PartFuncPointer FuzzyFunctionSignalIsStable; + PartFuncReference FuzzyFunctionSignalIsStable; /// SampleHistory is a history in that the last sample values are stored. DynamicLengthHistory SampleHistory; /// DAB is a (usually) small history of the last sample values of which a /// average is calculated if the DAB is full. DynamicLengthHistory DAB; /// DABHistory is a history in that the last DABs (to be exact, the averages /// of the last DABs) are stored. DynamicLengthHistory DABHistory; /// LowestConfidenceMatchingHistory is a history in that the lowest confidence /// for the current sample matches all history samples are saved. DynamicLengthHistory LowestConfidenceMatchingHistory; /// HighestConfidenceMatchingHistory is a history in that the highest /// confidence for the current sample matches all history samples are saved. DynamicLengthHistory HighestConfidenceMismatchingHistory; public: - // @Maxi doxygen per default doesn't display private attributes of a class. So - // I copied them to the constructor. So the user has more information. /// Creates an instance by setting all parameters /// \param SignalStateID The Id of the SignalStateinfo \c /// SignalStateInformation. /// /// \param FuzzyFunctionSampleMatches The FuzzyFunctionSampleMatches is the /// fuzzy function that gives the confidence how good the new sample matches /// another sample in the sample history. /// /// \param FuzzyFunctionSampleMismatches The FuzzyFunctionSampleMismatches is /// the fuzzy function that gives the confidence how bad the new sample /// matches another sample in the sample history. /// /// \param FuzzyFunctionNumOfSamplesMatches The /// FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the /// confidence how many samples from the sampe history match the new sample. /// /// \param FuzzyFunctionNumOfSamplesMismatches The /// FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives the /// confidence how many samples from the sampe history mismatch the new /// sample. /// /// \param FuzzyFunctionSignalIsDrifting The FuzzyFunctionSignalIsDrifting is /// the fuzzy function that gives the confidence how likely it is that the /// signal (resp. the state of a signal) is drifting. /// /// \param FuzzyFunctionSignalIsStable The FuzzyFunctionSignalIsStable is the /// fuzzy function that gives the confidence how likely it is that the signal /// (resp. the state of a signal) is stable (not drifting). /// /// \param SampleHistorySize Size of the Sample History \c /// DynamicLengthHistory . SampleHistory is a history in that the last sample /// values are stored. /// /// \param DABSize Size of DAB \c DynamicLengthHistory . DAB is a (usually) /// small history of the last sample values of which a average is calculated /// if the DAB is full. /// /// \param DABHistorySize Size of the DABHistory \c DynamicLengthHistory . /// DABHistory is a history in that the last DABs (to be exact, the averages /// of the last DABs) are stored. /// - SignalState(uint32_t SignalStateID, uint32_t SampleHistorySize, - uint32_t DABSize, uint32_t DABHistorySize, - PartFuncPointer FuzzyFunctionSampleMatches, - PartFuncPointer FuzzyFunctionSampleMismatches, - StepFuncPointer FuzzyFunctionNumOfSamplesMatches, - StepFuncPointer FuzzyFunctionNumOfSamplesMismatches, - PartFuncPointer FuzzyFunctionSignalIsDrifting, - PartFuncPointer FuzzyFunctionSignalIsStable) noexcept - : SignalStateInfo{SignalStateID, 0, SignalStateCondition::UNKNOWN, 0, - false, false, - false, //@maxi added the Signal is stable bool + SignalState(uint32_t SignalStateID, SignalProperties SignalProperty, + uint32_t SampleHistorySize, uint32_t DABSize, + uint32_t DABHistorySize, + PartFuncReference FuzzyFunctionSampleMatches, + PartFuncReference FuzzyFunctionSampleMismatches, + StepFuncReference FuzzyFunctionNumOfSamplesMatches, + StepFuncReference FuzzyFunctionNumOfSamplesMismatches, + PartFuncReference FuzzyFunctionSignalIsDrifting, + PartFuncReference FuzzyFunctionSignalIsStable) noexcept + : SignalStateInfo{SignalStateID, + SignalProperty, + 0, + SignalStateCondition::UNKNOWN, + 0, + false, + false, true}, FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches), FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches), FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches), FuzzyFunctionNumOfSamplesMismatches( FuzzyFunctionNumOfSamplesMismatches), FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting), FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable), SampleHistory(SampleHistorySize), DAB(DABSize), DABHistory(DABHistorySize), LowestConfidenceMatchingHistory(SampleHistorySize), HighestConfidenceMismatchingHistory(SampleHistorySize) {} /// Destroys \p this object. ~SignalState(void) = default; void leaveSignalState(void) noexcept { DAB.clear(); SignalStateInfo.NumberOfInsertedSamplesAfterEntrance = 0; SignalStateInfo.SignalStateIsValidAfterReentrance = false; } SignalStateInformation insertSample(INDATATYPE Sample) noexcept { validateSignalState(Sample); SampleHistory.addEntry(Sample); DAB.addEntry(Sample); if (DAB.full()) { PROCDATATYPE AvgOfDAB = DAB.template average(); DABHistory.addEntry(AvgOfDAB); DAB.clear(); } - FuzzyFunctionNumOfSamplesMatches->setRightLimit( + FuzzyFunctionNumOfSamplesMatches.setRightLimit( static_cast(SampleHistory.numberOfEntries())); - FuzzyFunctionNumOfSamplesMismatches->setRightLimit( + FuzzyFunctionNumOfSamplesMismatches.setRightLimit( static_cast(SampleHistory.numberOfEntries())); checkSignalStability(); return SignalStateInfo; } /// Gives the confidence how likely the new sample matches the signal state. /// /// \param Sample is the actual sample of the observed signal. /// /// \return the confidence of the new sample is matching the signal state. CONFDATATYPE confidenceSampleMatchesSignalState(INDATATYPE Sample) noexcept { CONFDATATYPE ConfidenceOfBestCase = 0; DynamicLengthHistory RelativeDistanceHistory(SampleHistory.maxLength()); // calculate distances to all history samples for (auto &HistorySample : SampleHistory) { PROCDATATYPE RelativeDistance = relativeDistance(Sample, HistorySample); RelativeDistanceHistory.addEntry(RelativeDistance); } // sort all calculated distances so that the lowest distance (will get the // highest confidence) is at the beginning. RelativeDistanceHistory.sortAscending(); CONFDATATYPE ConfidenceOfWorstFittingSample = 1; // Case 1 means that one (the best fitting) sample of the history is // compared with the new sample. Case 2 means the two best history samples // are compared with the new sample. And so on. - // TODO (future): to accelerate -> don't start with 1 start with some higher + // TODO (future): to accelerate . don't start with 1 start with some higher // number because a low number (i guess lower than 5) will definetely lead // to a low confidence. except the history is not full. - + // + // Case 1 means that one (the best fitting) sample of the history is + // compared with the new sample. Case 2 means the two best history samples + // are compared with the new sample. And so on. for (uint32_t Case = 0; Case < RelativeDistanceHistory.numberOfEntries(); Case++) { CONFDATATYPE ConfidenceFromRelativeDistance; if (std::isinf(RelativeDistanceHistory[Case])) { // TODO (future) if fuzzy is defined in a way that infinity is not 0 it // would be a problem - //@David: because we are using these operator functions, here I have to - // direference in a not (in my opionin) not so beautiful way - //("(*FuzzyFunctionSampleMatches)"), or I have to write - //"FuzzyFunctionSampleMatches->operator()(...)". Can we just write - // functions like "->getBlabla()" or something like that? ConfidenceFromRelativeDistance = 0; } else { ConfidenceFromRelativeDistance = - (*FuzzyFunctionSampleMatches)(RelativeDistanceHistory[Case]); + FuzzyFunctionSampleMatches(RelativeDistanceHistory[Case]); } -#if false - //@maxi why the 2? - ConfidenceOfWorstFittingSample = - fuzzyAND((CONFDATATYPE)2, ConfidenceOfWorstFittingSample, - ConfidenceFromRelativeDistance); - - //@maxi you could also use it like this then you can define the type and the size - ConfidenceOfWorstFittingSample = - fuzzyAND({ConfidenceOfWorstFittingSample, - ConfidenceFromRelativeDistance}); -#else - //@maxi is this what you wanted? you don't need to define the data type - // nor the size ConfidenceOfWorstFittingSample = fuzzyAND(ConfidenceOfWorstFittingSample, ConfidenceFromRelativeDistance); -#endif - -//@benedikt: same as before with "->operator()" -//@maxi the same as before -#if false - ConfidenceOfBestCase = fuzzyOR( - 2, ConfidenceOfBestCase, - fuzzyAND(2, ConfidenceOfWorstFittingSample, - FuzzyFunctionNumOfSamplesMatches->operator()( - static_cast(Case) + 1))); -#else + ConfidenceOfBestCase = fuzzyOR(ConfidenceOfBestCase, fuzzyAND(ConfidenceOfWorstFittingSample, - FuzzyFunctionNumOfSamplesMatches->operator()( + FuzzyFunctionNumOfSamplesMatches( static_cast(Case) + 1))); - -#endif } return ConfidenceOfBestCase; } /// Gives the confidence how likely the new sample mismatches the signal /// state. /// /// \param Sample is the actual sample of the observed signal. /// /// \return the confidence of the new sample is mismatching the signal state. CONFDATATYPE confidenceSampleMismatchesSignalState(INDATATYPE Sample) noexcept { float ConfidenceOfWorstCase = 1; DynamicLengthHistory RelativeDistanceHistory(SampleHistory.maxLength()); // calculate distances to all history samples for (auto &HistorySample : SampleHistory) { RelativeDistanceHistory.addEntry( relativeDistance(Sample, HistorySample)); } // sort all calculated distances so that the highest distance (will get the // lowest confidence) is at the beginning. RelativeDistanceHistory.sortDescending(); CONFDATATYPE ConfidenceOfBestFittingSample = 0; - // Case 1 means that one (the worst fitting) sample of the history is - // compared with the new sample. Case 2 means the two worst history samples - // are compared with the new sample. And so on. // TODO (future): to accelerate -> don't go until end. Confidences will only // get higher. See comment in "CONFDATATYPE // confidenceSampleMatchesSignalState(INDATATYPE Sample)". + // + // Case 1 means that one (the worst fitting) sample of the history is + // compared with the new sample. Case 2 means the two worst history samples + // are compared with the new sample. And so on. for (uint32_t Case = 0; Case < RelativeDistanceHistory.numberOfEntries(); Case++) { CONFDATATYPE ConfidenceFromRelativeDistance; if (std::isinf(RelativeDistanceHistory[Case])) { ConfidenceFromRelativeDistance = 1; } else { - //@benedikt: I had to change the following line. The outcommented line - // was the original one. I think it is ugly like that (new line). Do you - // have an idea how to make it better/more beautiful? ConfidenceFromRelativeDistance = - FuzzyFunctionSampleMismatches->operator()( - RelativeDistanceHistory[Case]); + FuzzyFunctionSampleMismatches(RelativeDistanceHistory[Case]); } -//@maxi you don't have to define the data type or the amount -#if false - ConfidenceOfBestFittingSample = fuzzyOR( - 2, ConfidenceOfBestFittingSample, ConfidenceFromRelativeDistance); - - //@benedikt: same as before with "->operator()" - ConfidenceOfWorstCase = fuzzyAND( - 2, ConfidenceOfWorstCase, - fuzzyOR(2, ConfidenceOfBestFittingSample, - FuzzyFunctionNumOfSamplesMismatches->operator()( - static_cast(Case) + 1))); -#else ConfidenceOfBestFittingSample = fuzzyOR(ConfidenceOfBestFittingSample, ConfidenceFromRelativeDistance); - //@benedikt: same as before with "->operator()" ConfidenceOfWorstCase = fuzzyAND(ConfidenceOfWorstCase, fuzzyOR(ConfidenceOfBestFittingSample, - FuzzyFunctionNumOfSamplesMismatches->operator()( + FuzzyFunctionNumOfSamplesMismatches( static_cast(Case) + 1))); -#endif } return ConfidenceOfWorstCase; } /// Gives information about the current signal state. /// /// \return a struct SignalStateInformation that contains information about /// the current signal state. SignalStateInformation signalStateInformation(void) noexcept { return SignalStateInfo; } private: void validateSignalState(INDATATYPE Sample) { // TODO (future): WorstConfidenceDistance and BestConfidenceDistance could // be set already in "CONFDATATYPE // confidenceSampleMatchesSignalState(INDATATYPE Sample)" and "CONFDATATYPE // confidenceSampleMismatchesSignalState(INDATATYPE Sample)" when the new // sample is compared to all history samples. This would save a lot time // because the comparisons are done only once. However, it has to be asured // that the these two functions are called before the insertation, and the // FuzzyFunctions for validation and matching have to be the same! CONFDATATYPE LowestConfidenceMatching = 1; CONFDATATYPE HighestConfidenceMismatching = 0; for (auto &HistorySample : SampleHistory) { -// TODO (future): think about using different fuzzy functions for -// validation and matching. -//@benedikt: same with "->operator()" -//@maxi you don't have to deine the data type nor the amount -#if false - LowestConfidenceMatching = - fuzzyAND(2, LowestConfidenceMatching, - FuzzyFunctionSampleMatches->operator()( - relativeDistance( - Sample, HistorySample))); - //@benedikt: same with "->operator()" - HighestConfidenceMismatching = - fuzzyOR(2, HighestConfidenceMismatching, - FuzzyFunctionSampleMismatches->operator()( - relativeDistance( - Sample, HistorySample))); -#else - LowestConfidenceMatching = - fuzzyAND(LowestConfidenceMatching, - FuzzyFunctionSampleMatches->operator()( - relativeDistance( - Sample, HistorySample))); - //@benedikt: same with "->operator()" + // TODO (future): think about using different fuzzy functions for + // validation and matching. + LowestConfidenceMatching = fuzzyAND( + LowestConfidenceMatching, + FuzzyFunctionSampleMatches(relativeDistance( + Sample, HistorySample))); + HighestConfidenceMismatching = fuzzyOR(HighestConfidenceMismatching, - FuzzyFunctionSampleMismatches->operator()( + FuzzyFunctionSampleMismatches( relativeDistance( Sample, HistorySample))); -#endif } LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching); HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching); LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry(); HighestConfidenceMismatching = HighestConfidenceMismatchingHistory.highestEntry(); -//@maxi you don't have to define the data type or the amount -#if false - //@benedikt: same with "->operator()" - CONFDATATYPE ConfidenceSignalStateIsValid = fuzzyAND( - 2, LowestConfidenceMatching, - FuzzyFunctionNumOfSamplesMatches->operator()(static_cast( - SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); - //@benedikt: same with "->operator()" - CONFDATATYPE ConfidenceSignalStateIsInvalid = fuzzyOR( - 2, HighestConfidenceMismatching, - FuzzyFunctionNumOfSamplesMismatches->operator()(static_cast( - SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); -#else - //@benedikt: same with "->operator()" - CONFDATATYPE ConfidenceSignalStateIsValid = fuzzyAND( - LowestConfidenceMatching, - FuzzyFunctionNumOfSamplesMatches->operator()(static_cast( - SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); - //@benedikt: same with "->operator()" - CONFDATATYPE ConfidenceSignalStateIsInvalid = fuzzyOR( - HighestConfidenceMismatching, - FuzzyFunctionNumOfSamplesMismatches->operator()(static_cast( - SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); -#endif + CONFDATATYPE ConfidenceSignalStateIsValid = + fuzzyAND(LowestConfidenceMatching, + FuzzyFunctionNumOfSamplesMatches(static_cast( + SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); + + CONFDATATYPE ConfidenceSignalStateIsInvalid = + fuzzyOR(HighestConfidenceMismatching, + FuzzyFunctionNumOfSamplesMismatches(static_cast( + SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); if (ConfidenceSignalStateIsValid > ConfidenceSignalStateIsInvalid) { if (SignalStateInfo.SignalStateIsValid) { SignalStateInfo.SignalStateJustGotValid = false; } else { SignalStateInfo.SignalStateJustGotValid = true; } SignalStateInfo.SignalStateIsValid = true; SignalStateInfo.SignalStateIsValidAfterReentrance = true; } } void checkSignalStability(void) { CONFDATATYPE ConfidenceSignalIsStable; CONFDATATYPE ConfidenceSignalIsDrifting; if (DABHistory.numberOfEntries() >= 2) { - //@benedikt: same "->operator()" - ConfidenceSignalIsStable = FuzzyFunctionSignalIsStable->operator()( + ConfidenceSignalIsStable = FuzzyFunctionSignalIsStable( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); - //@benedikt: same "->operator()" - ConfidenceSignalIsDrifting = FuzzyFunctionSignalIsDrifting->operator()( + ConfidenceSignalIsDrifting = FuzzyFunctionSignalIsDrifting( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); } else { - // TODO: change to enum - ConfidenceSignalIsStable = 1; + // @benedikt: I do not know if this "initializing" is the best, but I + // think it makes sense because we do not know if it is stable or + // drifting. + ConfidenceSignalIsStable = 0; ConfidenceSignalIsDrifting = 0; } - SignalStateInfo.SignalIsStable = - ConfidenceSignalIsStable >= ConfidenceSignalIsDrifting; + //@benedikt: before it was "ConfidenceSignalIsStable >= + // ConfidenceSignalIsDrifting" -> stable. However, I think like that it + // makes + // more sense. What do you mean? + if (ConfidenceSignalIsStable > ConfidenceSignalIsDrifting) { + SignalStateInfo.SignalStateCondition = SignalStateCondition::STABLE; + } else if (ConfidenceSignalIsStable < ConfidenceSignalIsDrifting) { + SignalStateInfo.SignalStateCondition = SignalStateCondition::DRIFTING; + } else { + SignalStateInfo.SignalStateCondition = SignalStateCondition::UNKNOWN; + } } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SIGNALSTATE_HPP diff --git a/include/rosa/agent/SignalStateDetector.hpp b/include/rosa/agent/SignalStateDetector.hpp index 3293a6b..2e580cd 100644 --- a/include/rosa/agent/SignalStateDetector.hpp +++ b/include/rosa/agent/SignalStateDetector.hpp @@ -1,278 +1,283 @@ //===-- rosa/agent/SignalStateDetector.hpp ----------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SignalStateDetector.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *signal state detector* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SIGNALSTATEDETECTOR_HPP #define ROSA_AGENT_SIGNALSTATEDETECTOR_HPP #include "rosa/agent/Functionality.h" #include "rosa/agent/SignalState.hpp" #include "rosa/agent/StateDetector.hpp" #include namespace rosa { namespace agent { /// Implements \c rosa::agent::SignalStateDetector as a functionality that /// detects signal states given on input samples. /// /// \note This implementation is supposed to be used for samples of an /// arithmetic type. /// /// \tparam INDATATYPE type of input data, \tparam CONFDATATYPE type of /// data in that the confidence values are given, \tparam PROCDATATYPE type of /// the relative distance and the type of data in which DABs are saved. template class SignalStateDetector : public StateDetector { // @maxi added them so it is compilable is this what you intended? using StateDetector = StateDetector; - // using PartFuncPointer = typename StateDetector::PartFuncPointer; - // using StepFuncPointer = typename StateDetector::StepFuncPointer; + using PartFuncPointer = typename StateDetector::PartFuncPointer; + using StepFuncPointer = typename StateDetector::StepFuncPointer; private: // For the convinience to write a shorter data type name using SignalStatePtr = std::shared_ptr>; + /// The SignalProperty saves whether the monitored signal is an input our + /// output signal. + SignalProperties SignalProperty; + /// The NextSignalStateID is a counter variable which stores the ID which the /// next signal state shall have. uint32_t NextSignalStateID; /// The SignalStateHasChanged is a flag that show whether a signal has changed /// its state. bool SignalStateHasChanged; /// The CurrentSignalState is a pointer to the (saved) signal state in which /// the actual variable (signal) of the observed system is. SignalStatePtr CurrentSignalState; /// The DetectedSignalStates is a history in that all detected signal states /// are saved. DynamicLengthHistory DetectedSignalStates; /// The FuzzyFunctionSampleMatches is the fuzzy function that gives the /// confidence how good the new sample matches another sample in the sample /// history. PartFuncPointer FuzzyFunctionSampleMatches; /// The FuzzyFunctionSampleMismatches is the fuzzy function that gives the /// confidence how bad the new sample matches another sample in the sample /// history. PartFuncPointer FuzzyFunctionSampleMismatches; /// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the /// confidence how many samples from the sampe history match the new sample. StepFuncPointer FuzzyFunctionNumOfSamplesMatches; /// The FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives /// the confidence how many samples from the sampe history mismatch the new /// sample. StepFuncPointer FuzzyFunctionNumOfSamplesMismatches; /// The FuzzyFunctionSignalIsDrifting is the fuzzy function that gives the /// confidence how likely it is that the signal is drifting. PartFuncPointer FuzzyFunctionSignalIsDrifting; /// The FuzzyFunctionSignalIsStable is the fuzzy function that gives the /// confidence how likely it is that the signal is stable (not drifting). PartFuncPointer FuzzyFunctionSignalIsStable; /// SampleHistorySize is the (maximum) size of the sample history. uint32_t SampleHistorySize; /// DABSize the size of a DAB (Discrete Average Block). uint32_t DABSize; /// DABHistorySize is the (maximum) size of the DAB history. uint32_t DABHistorySize; public: /// Creates an instance by setting all parameters /// \param FuzzyFunctionSampleMatches The FuzzyFunctionSampleMatches is the /// fuzzy function that gives the confidence how good the new sample matches /// another sample in the sample history. /// /// \param FuzzyFunctionSampleMismatches The FuzzyFunctionSampleMismatches is /// the fuzzy function that gives the confidence how bad the new sample /// matches another sample in the sample history. /// /// \param FuzzyFunctionNumOfSamplesMatches The /// FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the /// confidence how many samples from the sampe history match the new sample. /// /// \param FuzzyFunctionNumOfSamplesMismatches The /// FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives the /// confidence how many samples from the sampe history mismatch the new /// sample. /// /// \param FuzzyFunctionSignalIsDrifting The FuzzyFunctionSignalIsDrifting is /// the fuzzy function that gives the confidence how likely it is that the /// signal (resp. the state of a signal) is drifting. /// /// \param FuzzyFunctionSignalIsStable The FuzzyFunctionSignalIsStable is the /// fuzzy function that gives the confidence how likely it is that the signal /// (resp. the state of a signal) is stable (not drifting). /// /// \param SampleHistorySize Sets the History size which will be used by \c /// SignalState. /// /// \param DABSize Sets the DAB size which will be used by \c SignalState. /// /// \param DABHistorySize Sets the size which will be used by \c SignalState. /// - SignalStateDetector(uint32_t MaximumNumberOfSignalStates, + SignalStateDetector(SignalProperties SignalProperty, + uint32_t MaximumNumberOfSignalStates, PartFuncPointer FuzzyFunctionSampleMatches, PartFuncPointer FuzzyFunctionSampleMismatches, StepFuncPointer FuzzyFunctionNumOfSamplesMatches, StepFuncPointer FuzzyFunctionNumOfSamplesMismatches, PartFuncPointer FuzzyFunctionSignalIsDrifting, PartFuncPointer FuzzyFunctionSignalIsStable, uint32_t SampleHistorySize, uint32_t DABSize, uint32_t DABHistorySize) noexcept : NextSignalStateID(1), SignalStateHasChanged(false), - CurrentSignalState(nullptr), + CurrentSignalState(nullptr), SignalProperty(SignalProperty), DetectedSignalStates(MaximumNumberOfSignalStates), FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches), FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches), FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches), FuzzyFunctionNumOfSamplesMismatches( FuzzyFunctionNumOfSamplesMismatches), FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting), FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable), SampleHistorySize(SampleHistorySize), DABSize(DABSize), DABHistorySize(DABHistorySize) {} /// Destroys \p this object. ~SignalStateDetector(void) = default; /// Detects the signal state to which the new sample belongs or create a new /// signal state if the new sample does not match to any of the saved states. /// /// \param Sample is the actual sample of the observed signal. /// /// \return the information of the current signal state (signal state ID and /// other parameters). // TODO (future): change to operator() SignalStateInformation detectSignalState(INDATATYPE Sample) noexcept { if (!CurrentSignalState) { ASSERT(DetectedSignalStates.empty()); SignalStatePtr S = createNewSignalState(); CurrentSignalState = S; } else { CONFDATATYPE ConfidenceSampleMatchesSignalState = CurrentSignalState->confidenceSampleMatchesSignalState(Sample); CONFDATATYPE ConfidenceSampleMismatchesSignalState = CurrentSignalState->confidenceSampleMismatchesSignalState(Sample); if (ConfidenceSampleMatchesSignalState > ConfidenceSampleMismatchesSignalState) { SignalStateHasChanged = false; } else { SignalStateHasChanged = true; if (CurrentSignalState->signalStateInformation().SignalStateIsValid) { CurrentSignalState->leaveSignalState(); } else { DetectedSignalStates.deleteEntry(CurrentSignalState); } // TODO (future): additionally save averages to enable fast iteration // through recorded signl state history (maybe sort vector based on // these average values) CurrentSignalState = nullptr; //@benedikt: same question for (auto &SavedSignalState : DetectedSignalStates) { if (SavedSignalState != CurrentSignalState) { ConfidenceSampleMatchesSignalState = SavedSignalState->confidenceSampleMatchesSignalState(Sample); ConfidenceSampleMismatchesSignalState = SavedSignalState->confidenceSampleMismatchesSignalState(Sample); if (ConfidenceSampleMatchesSignalState > ConfidenceSampleMismatchesSignalState) { // TODO (future): maybe it would be better to compare // ConfidenceSampleMatchesSignalState of all signal states in the // vector in order to find the best matching signal state. CurrentSignalState = SavedSignalState; break; } } } if (!CurrentSignalState) { SignalStatePtr S = createNewSignalState(); CurrentSignalState = S; } } } SignalStateInformation SignalStateInfo = CurrentSignalState->insertSample(Sample); if (SignalStateInfo.SignalStateJustGotValid) { NextSignalStateID++; } return SignalStateInfo; } /// Gives information about the current signal state. /// /// \return a struct SignalStateInformation that contains information about /// the current signal state or NULL if no current signal state exists. SignalStateInformation currentSignalStateInformation(void) noexcept { if (CurrentSignalState) { return CurrentSignalState->signalStateInformation(); } else { return NULL; } } /// Gives information whether a signal state change has happened or not. /// /// \return true if a signal state change has happened, and false if not. bool signalStateHasChanged(void) noexcept { return SignalStateHasChanged; } private: /// Creates a new signal state and adds it to the signal state vector in which /// all known states are saved. /// /// \return a pointer to the newly created signal state or NULL if no state /// could be created. SignalStatePtr createNewSignalState(void) noexcept { SignalStatePtr S(new SignalState( NextSignalStateID, SampleHistorySize, DABSize, DABHistorySize, - FuzzyFunctionSampleMatches, FuzzyFunctionSampleMismatches, - FuzzyFunctionNumOfSamplesMatches, FuzzyFunctionNumOfSamplesMismatches, - FuzzyFunctionSignalIsDrifting, FuzzyFunctionSignalIsStable)); + *FuzzyFunctionSampleMatches, *FuzzyFunctionSampleMismatches, + *FuzzyFunctionNumOfSamplesMatches, *FuzzyFunctionNumOfSamplesMismatches, + *FuzzyFunctionSignalIsDrifting, *FuzzyFunctionSignalIsStable)); DetectedSignalStates.addEntry(S); return S; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SIGNALSTATEDETECTOR_HPP diff --git a/include/rosa/agent/SystemStateDetector.hpp b/include/rosa/agent/SystemStateDetector.hpp index 0a1a9e6..a255e0b 100644 --- a/include/rosa/agent/SystemStateDetector.hpp +++ b/include/rosa/agent/SystemStateDetector.hpp @@ -1,104 +1,106 @@ //===-- rosa/agent/SystemStateDetector.hpp ----------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SystemStateDetector.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *system state detector* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP #define ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP #include "rosa/agent/Functionality.h" #include "rosa/agent/StateDetector.hpp" #include "rosa/agent/SystemState.hpp" #include "rosa/support/debug.hpp" namespace rosa { namespace agent { +// todo: löschen , std::size_t NUMOFINPUTSIGNALS, std::size_t NUMOFOUTPUTSIGNALS /// TODO: write description template class SystemStateDetector : public StateDetector { //@maxi added them to make it compilable is this what you wanted? using StateDetector = StateDetector; using PartFuncPointer = typename StateDetector::PartFuncPointer; private: // For the convinience to write a shorter data type name using SystemStatePtr = std::shared_ptr>; /// The NextSystemStateID is a counter variable which stores the ID which /// the /// next system state shall have. uint32_t NextSystemStateID; /// The SystemStateHasChanged is a flag that show whether the observed /// system /// has changed its state. bool SystemStateHasChanged; /// The CurrentSystemState is a pointer to the (saved) system state in which /// the actual state of the observed system is. SystemStatePtr CurrentSystemState; /// The DetectedSystemStates is a history in that all detected system states /// are saved. DynamicLengthHistory DetectedSystemStates; /// The FuzzyFunctionDelayTimeToGetBroken is the fuzzy function that gives /// the confidence whether the system is Broken because of an input change /// without an output change or vice versa. A small time gap between the two /// shall be allowed. PartFuncPointer FuzzyFunctionDelayTimeToGetBroken; /// The FuzzyFunctionDelayTimeToBeWorking is the fuzzy function that gives /// the /// confidence whether the system is still OK allthough an input change /// without an output change or vice versa. PartFuncPointer FuzzyFunctionDelayTimeToBeWorking; public: + // todo zwei parameter für variablen anzahl /// TODO: write description SystemStateDetector( uint32_t MaximumNumberOfSystemStates, PartFuncPointer FuzzyFunctionDelayTimeToGetBroken, PartFuncPointer FuzzyFunctionDelayTimeToBeWorking) noexcept : NextSystemStateID(1), SystemStateHasChanged(false), CurrentSystemState(nullptr), DetectedSystemStates(MaximumNumberOfSystemStates), FuzzyFunctionDelayTimeToGetBroken(FuzzyFunctionDelayTimeToGetBroken), FuzzyFunctionDelayTimeToBeWorking(FuzzyFunctionDelayTimeToBeWorking) {} /// Destroys \p this object. ~SystemStateDetector(void) = default; /// TODO: write description SystemStateInformation detectSystemState(INDATATYPE Sample) noexcept { // dummy line Sample = 1; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP