diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp index 5a3d014..8dd450e 100644 --- a/include/rosa/agent/SignalState.hpp +++ b/include/rosa/agent/SignalState.hpp @@ -1,471 +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 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 unsigned integer number - unsigned int SignalStateID; + /// The signal state ID saved as an uint32_teger number + uint32_t SignalStateID; /// 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. - unsigned int NumberOfInsertedSamplesAfterEntrance; + 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 signa 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: // For the convinience to write a shorter data type name using PartFuncPointer = std::shared_ptr>; // @Benedikt: are INDATATYPE, CONFDATATYPE right here? using StepFuncPointer = std::shared_ptr>; /// 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; /// 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 (resp. the state of a signal) /// is drifting. PartFuncPointer 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; /// 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(unsigned int SignalStateID, unsigned int SampleHistorySize, - unsigned int DABSize, unsigned int DABHistorySize, + 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 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(); } //@Benedikt: Do I really have to cast here? FuzzyFunctionNumOfSamplesMatches->setRightLimit( static_cast(SampleHistory.numberOfEntries())); 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 // number because a low number (i guess lower than 5) will definetely lead // to a low confidence. except the history is not full. - for (unsigned int Case = 0; - Case < RelativeDistanceHistory.numberOfEntries(); Case++) { + 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 //@benedikt: check if your partialfunctions can take infinity as // argument //@benedikt: same as before "->operator()" ConfidenceFromRelativeDistance = 0; } else { ConfidenceFromRelativeDistance = FuzzyFunctionSampleMatches->operator()( RelativeDistanceHistory[Case]); } ConfidenceOfWorstFittingSample = fuzzyAND( 2, ConfidenceOfWorstFittingSample, ConfidenceFromRelativeDistance); //@benedikt: do i have to pass the number 2 to tell the function how many // arguments are following? //@benedikt: same as before with "->operator()" ConfidenceOfBestCase = fuzzyOR( 2, ConfidenceOfBestCase, fuzzyAND(2, ConfidenceOfWorstFittingSample, FuzzyFunctionNumOfSamplesMatches->operator()( static_cast(Case) + 1))); } 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)". - for (unsigned int Case = 0; - Case < RelativeDistanceHistory.numberOfEntries(); Case++) { + 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]); } //@benedikt: do i have to pass the number 2 to tell the function how many // arguments are following? ConfidenceOfBestFittingSample = fuzzyOR( 2, ConfidenceOfBestFittingSample, ConfidenceFromRelativeDistance); //@benedikt: do i have to pass the number 2 to tell the function how many // arguments are following? //@benedikt: same as before with "->operator()" ConfidenceOfWorstCase = fuzzyAND( 2, ConfidenceOfWorstCase, fuzzyOR(2, ConfidenceOfBestFittingSample, FuzzyFunctionNumOfSamplesMismatches->operator()( static_cast(Case) + 1))); } 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()" LowestConfidenceMatching = fuzzyAND(2, LowestConfidenceMatching, FuzzyFunctionSampleMatches->operator()( relativeDistance( Sample, HistorySample))); //@benedikt: same with "->operator()" HighestConfidenceMismatching = fuzzyOR(2, HighestConfidenceMismatching, FuzzyFunctionSampleMismatches->operator()( relativeDistance( Sample, HistorySample))); } LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching); HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching); LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry(); HighestConfidenceMismatching = HighestConfidenceMismatchingHistory.highestEntry(); //@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))); 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()( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); //@benedikt: same "->operator()" ConfidenceSignalIsDrifting = FuzzyFunctionSignalIsDrifting->operator()( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); } else { // QUESTION: is it ok to say stable = 1 and drift = 0, when I simply don't // know because the state is so new. Is there an option for saying don't // know? ConfidenceSignalIsStable = 1; ConfidenceSignalIsDrifting = 0; } SignalStateInfo.SignalIsStable = ConfidenceSignalIsStable >= ConfidenceSignalIsDrifting; } }; } // 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 7923b49..6de4b9a 100644 --- a/include/rosa/agent/SignalStateDetector.hpp +++ b/include/rosa/agent/SignalStateDetector.hpp @@ -1,285 +1,285 @@ //===-- 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/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/History.hpp" #include "rosa/agent/SignalState.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 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 abstraction type is not to arithmetic"); private: // For the convinience to write a shorter data type name using PartFuncPointer = std::shared_ptr>; using StepFuncPointer = std::shared_ptr>; using SignalStatePtr = std::shared_ptr>; /// The NextSignalStateID is a counter variable which stores the ID which the /// next signal state shall have. - unsigned int NextSignalStateID; + 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. - unsigned int SampleHistorySize; + uint32_t SampleHistorySize; /// DABSize the size of a DAB (Discrete Average Block). - unsigned int DABSize; + uint32_t DABSize; /// DABHistorySize is the (maximum) size of the DAB history. - unsigned int DABHistorySize; + 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(unsigned int MaximumNumberOfSignalStates, + SignalStateDetector(uint32_t MaximumNumberOfSignalStates, PartFuncPointer FuzzyFunctionSampleMatches, PartFuncPointer FuzzyFunctionSampleMismatches, StepFuncPointer FuzzyFunctionNumOfSamplesMatches, StepFuncPointer FuzzyFunctionNumOfSamplesMismatches, PartFuncPointer FuzzyFunctionSignalIsDrifting, PartFuncPointer FuzzyFunctionSignalIsStable, - unsigned int SampleHistorySize, unsigned int DABSize, - unsigned int DABHistorySize) noexcept + uint32_t SampleHistorySize, uint32_t DABSize, + uint32_t DABHistorySize) noexcept : NextSignalStateID(1), SignalStateHasChanged(false), CurrentSignalState(nullptr), 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). 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 { //@benedikt: changed from vector to history. can i still do the next // line? 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)); // @benedikt: todo: assert in history, which checks if push_back worked 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 316e51e..b12d2f7 100644 --- a/include/rosa/agent/SystemStateDetector.hpp +++ b/include/rosa/agent/SystemStateDetector.hpp @@ -1,152 +1,152 @@ //===-- 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/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/History.hpp" #include "rosa/agent/SystemState.hpp" #include "rosa/support/debug.hpp" namespace rosa { namespace agent { /// System state conditions defining how the condition of a \c /// rosa::agent::SystemState is saved in \c rosa::agent::SystemStateInformation. enum class SystemStateCondition { STABLE, ///< The system state is stable DRIFTING, ///< The system state is drifting MALFUNCTIONING, ///< The system state is malfunctioning UNKNOWN ///< The system state is unknown }; /// TODO: write description template struct SystemStateInformation { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "confidence type is not to arithmetic"); - /// The system state ID saved as an unsigned integer number - unsigned int SystemStateID; + /// The system state ID saved as an uint32_teger number + uint32_t SystemStateID; /// The SystemStateConfidence shows the overall confidence value of the system /// state. CONFDATATYPE OverallDetectionConfidence; /// The SystemStateCondition shows the condition of a system state (stable, /// drifting, malfunctioning, or unknown) //@David: is it ok to name the variable exactly as the type is named? SystemStateCondition SystemStateCondition; /// The SystemStateIsValid saves the number of samples which have been /// inserted into the state after entering it. - unsigned int NumberOfInsertedSamplesAfterEntrance; + uint32_t NumberOfInsertedSamplesAfterEntrance; /// The SystemStateIsValid shows whether a state is valid or invalid. /// In this context, valid means that enough samples which are in close /// proximitry have been inserted into the state. bool SystemStateIsValid; /// The SystemStateJustGotValid shows whether a system state got valid /// (toggled from invalid to valid) during the current inserted sample. bool SystemStateJustGotValid; /// The SystemStateIsValidAfterReentrance shows whether a system state is /// valid after the variable changed back to it again. bool SystemStateIsValidAfterReentrance; /// The SystemIsStable shows whether a signa is stable and not /// drifting. bool SystemIsStable; }; /// TODO: write description template class SystemStateDetector : 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 abstraction type is not to arithmetic"); private: // For the convinience to write a shorter data type name using PartFuncPointer = std::shared_ptr>; using SystemStatePtr = std::shared_ptr>; /// The NextSystemStateID is a counter variable which stores the ID which /// the /// next system state shall have. - unsigned int NextSystemStateID; + 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: write description SystemStateDetector( - unsigned int MaximumNumberOfSystemStates, + 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 detectSignalState(INDATATYPE Sample) noexcept { // dummy line Sample = 1; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP