diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp index b6149a4..a4b3cd8 100644 --- a/include/rosa/agent/SignalState.hpp +++ b/include/rosa/agent/SignalState.hpp @@ -1,470 +1,469 @@ //===-- 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/agent/State.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 { +template +struct SignalStateInformation : StateInformation { // 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; }; /// \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"); public: // For the convinience to write a shorter data type name using PartFuncReference = PartialFunction &; using StepFuncReference = StepFunction &; private: - /// SignalStateInfo is a struct SignalStateInformation that contains - /// information about the current state. + /// SignalStateInfo is a struct of SignalStateInformation that contains + /// information about the current signal 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. PartFuncReference FuzzyFunctionSampleMatches; /// The FuzzyFunctionSampleMismatches is the fuzzy function that gives the /// confidence how bad the new sample matches another sample in the sample /// history. PartFuncReference FuzzyFunctionSampleMismatches; /// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the /// confidence how many samples from the sampe history match the new sample. StepFuncReference FuzzyFunctionNumOfSamplesMatches; /// The FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives /// the confidence how many samples from the sampe history mismatch the new /// sample. 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. 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). 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; + //@benedikt: neu (passt das so?) + CONFDATATYPE TempConfidenceMatching; + CONFDATATYPE TempConfidenceMismatching; + public: /// 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, 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, + : //@benedikt/@david: I don't know if i am allowed to initialize it like + // that because the struct is a derivate of another struct + SignalStateInfo{SignalStateID, + StateConditions::UNKNOWN, + false, false, false, - false}, + 0, + 0, + 0, + 0, + 0, + 0, + SignalProperty, + 0}, 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; + SignalStateInfo.StateIsValidAfterReentrance = 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( static_cast(SampleHistory.numberOfEntries())); FuzzyFunctionNumOfSamplesMismatches.setRightLimit( static_cast(SampleHistory.numberOfEntries())); checkSignalStability(); + //@benedikt (das gehört dazu) + SignalStateInfo.ConfidenceOfMatchingState = TempConfidenceMatching; + SignalStateInfo.ConfidenceOfMismatchingState = TempConfidenceMismatching; + 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. // // 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 ConfidenceFromRelativeDistance = 0; } else { ConfidenceFromRelativeDistance = FuzzyFunctionSampleMatches(RelativeDistanceHistory[Case]); } ConfidenceOfWorstFittingSample = fuzzyAND(ConfidenceOfWorstFittingSample, ConfidenceFromRelativeDistance); ConfidenceOfBestCase = fuzzyOR(ConfidenceOfBestCase, fuzzyAND(ConfidenceOfWorstFittingSample, FuzzyFunctionNumOfSamplesMatches( static_cast(Case) + 1))); } + //@benedikt (das gehört dazu) + TempConfidenceMatching = ConfidenceOfBestCase; + 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; // 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 { ConfidenceFromRelativeDistance = FuzzyFunctionSampleMismatches(RelativeDistanceHistory[Case]); } ConfidenceOfBestFittingSample = fuzzyOR(ConfidenceOfBestFittingSample, ConfidenceFromRelativeDistance); ConfidenceOfWorstCase = fuzzyAND(ConfidenceOfWorstCase, fuzzyOR(ConfidenceOfBestFittingSample, FuzzyFunctionNumOfSamplesMismatches( static_cast(Case) + 1))); } + //@benedikt (das gehört dazu) + TempConfidenceMismatching = ConfidenceOfWorstCase; + 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. LowestConfidenceMatching = fuzzyAND( LowestConfidenceMatching, FuzzyFunctionSampleMatches(relativeDistance( Sample, HistorySample))); HighestConfidenceMismatching = fuzzyOR(HighestConfidenceMismatching, FuzzyFunctionSampleMismatches( relativeDistance( Sample, HistorySample))); } LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching); HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching); LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry(); HighestConfidenceMismatching = HighestConfidenceMismatchingHistory.highestEntry(); - CONFDATATYPE ConfidenceSignalStateIsValid = + SignalStateInfo.ConfidenceStateIsValid = fuzzyAND(LowestConfidenceMatching, FuzzyFunctionNumOfSamplesMatches(static_cast( SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); - CONFDATATYPE ConfidenceSignalStateIsInvalid = + SignalStateInfo.ConfidenceStateIsInvalid = fuzzyOR(HighestConfidenceMismatching, FuzzyFunctionNumOfSamplesMismatches(static_cast( SignalStateInfo.NumberOfInsertedSamplesAfterEntrance))); - if (ConfidenceSignalStateIsValid > ConfidenceSignalStateIsInvalid) { - if (SignalStateInfo.SignalStateIsValid) { - SignalStateInfo.SignalStateJustGotValid = false; + if (SignalStateInfo.ConfidenceStateIsValid > + SignalStateInfo.ConfidenceStateIsInvalid) { + if (SignalStateInfo.StateIsValid) { + SignalStateInfo.StateJustGotValid = false; } else { - SignalStateInfo.SignalStateJustGotValid = true; + SignalStateInfo.StateJustGotValid = true; } - SignalStateInfo.SignalStateIsValid = true; - SignalStateInfo.SignalStateIsValidAfterReentrance = true; + SignalStateInfo.StateIsValid = true; + SignalStateInfo.StateIsValidAfterReentrance = true; } } void checkSignalStability(void) { - CONFDATATYPE ConfidenceSignalIsStable; - CONFDATATYPE ConfidenceSignalIsDrifting; if (DABHistory.numberOfEntries() >= 2) { - ConfidenceSignalIsStable = FuzzyFunctionSignalIsStable( + SignalStateInfo.ConfidenceStateIsStable = FuzzyFunctionSignalIsStable( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); - ConfidenceSignalIsDrifting = FuzzyFunctionSignalIsDrifting( + SignalStateInfo.ConfidenceStateIsDrifting = FuzzyFunctionSignalIsDrifting( relativeDistance( DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0])); } else { // @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.ConfidenceStateIsStable = 0; + SignalStateInfo.ConfidenceStateIsDrifting = 0; } //@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; + if (SignalStateInfo.ConfidenceStateIsStable > + SignalStateInfo.ConfidenceStateIsDrifting) { + SignalStateInfo.StateCondition = StateConditions::STABLE; + } else if (SignalStateInfo.ConfidenceStateIsStable < + SignalStateInfo.ConfidenceStateIsDrifting) { + SignalStateInfo.StateCondition = StateConditions::DRIFTING; } else { - SignalStateInfo.SignalStateCondition = SignalStateCondition::UNKNOWN; + SignalStateInfo.StateCondition = StateConditions::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 207a094..b5b6d71 100644 --- a/include/rosa/agent/SignalStateDetector.hpp +++ b/include/rosa/agent/SignalStateDetector.hpp @@ -1,285 +1,272 @@ //===-- rosa/agent/SignalStateDetector.hpp ----------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SignalStateDetector.hpp /// -/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) +/// \author Maximilian Götzinger (maximilian.goet5zinger@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; 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(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 - : // needed to be reorderd - SignalProperty(SignalProperty), NextSignalStateID(1), - SignalStateHasChanged(false), CurrentSignalState(nullptr), + : SignalProperty(SignalProperty), CurrentSignalState(nullptr), DetectedSignalStates(MaximumNumberOfSignalStates), FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches), FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches), FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches), FuzzyFunctionNumOfSamplesMismatches( FuzzyFunctionNumOfSamplesMismatches), FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting), FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable), SampleHistorySize(SampleHistorySize), DABSize(DABSize), - DABHistorySize(DABHistorySize) {} + DABHistorySize(DABHistorySize) { + this->NextStateID = 1; + this->StateHasChanged = false; + } /// 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; + this->StateHasChanged = ConfidenceSampleMatchesSignalState <= + ConfidenceSampleMismatchesSignalState; + + if (this->StateHasChanged) { - if (CurrentSignalState->signalStateInformation().SignalStateIsValid) { + if (CurrentSignalState->signalStateInformation().StateIsValid) CurrentSignalState->leaveSignalState(); - } else { + 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; - } + 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++; + if (SignalStateInfo.StateJustGotValid) { + this->NextStateID++; } 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; } + bool stateHasChanged(void) noexcept { return this->StateHasChanged; } 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, SignalProperty, SampleHistorySize, DABSize, + this->NextStateID, SignalProperty, SampleHistorySize, DABSize, DABHistorySize, *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/State.hpp b/include/rosa/agent/State.hpp new file mode 100644 index 0000000..1e19ef5 --- /dev/null +++ b/include/rosa/agent/State.hpp @@ -0,0 +1,90 @@ +//===-- rosa/agent/State.hpp ------------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +//===----------------------------------------------------------------------===// +/// +/// \file rosa/agent/State.hpp +/// +/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) +/// +/// \date 2019 +/// +/// \brief Definition of *state* *functionality*. +/// +//===----------------------------------------------------------------------===// + +#ifndef ROSA_AGENT_STATE_HPP +#define ROSA_AGENT_STATE_HPP + +#include "rosa/agent/Functionality.h" +//#include "rosa/agent/FunctionAbstractions.hpp" +//#include "rosa/agent/History.hpp" + +#include "rosa/support/debug.hpp" + +#include + +//#include + +namespace rosa { +namespace agent { + +/// State conditions defining how the condition of a \c rosa::agent::State is +/// saved in \c rosa::agent::StateInformation. +enum StateConditions : uint8_t { + UNKNOWN = 0, ///< The state is unknown + STABLE = 1, ///< The state is stable + DRIFTING = 2, ///< The state is drifting + MALFUNCTIONING = 3 ///< Malfunction +}; + +template struct StateInformation { + // Make sure the actual type arguments are matching our expectations. + STATIC_ASSERT((std::is_arithmetic::value), + "confidence type is not to arithmetic"); + /// The StateID stores the ID of the state. + unsigned int StateID; + /// The StateCondition shows the condition of a state (stable, drifting, or + /// unknown) + StateConditions StateCondition; + /// The StateIsValid 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 StateIsValid; + /// The StateJustGotValid shows whether a state got valid (toggled from + /// invalid to valid) during the current inserted sample. + bool StateJustGotValid; + /// The StateIsValidAfterReentrance shows whether a state is valid after the + /// variable changed back to it again. + bool StateIsValidAfterReentrance; + + /// TODO: describe + CONFDATATYPE ConfidenceOfMatchingState; + CONFDATATYPE ConfidenceOfMismatchingState; + + CONFDATATYPE ConfidenceStateIsValid; + CONFDATATYPE ConfidenceStateIsInvalid; + + CONFDATATYPE ConfidenceStateIsStable; + CONFDATATYPE ConfidenceStateIsDrifting; +}; + +template +class State : 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"); + STATIC_ASSERT((std::is_arithmetic::value), + "process type is not to arithmetic"); + +protected: +}; + +} // End namespace agent +} // End namespace rosa + +#endif // ROSA_AGENT_SIGNALSTATEDETECTOR_HPP diff --git a/include/rosa/agent/StateDetector.hpp b/include/rosa/agent/StateDetector.hpp index aa341f6..34b5298 100644 --- a/include/rosa/agent/StateDetector.hpp +++ b/include/rosa/agent/StateDetector.hpp @@ -1,56 +1,58 @@ //===-- rosa/agent/StateDetector.hpp ----------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/StateDetector.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *state detector* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_STATEDETECTOR_HPP #define ROSA_AGENT_STATEDETECTOR_HPP #include "rosa/agent/FunctionAbstractions.hpp" #include "rosa/agent/History.hpp" #include namespace rosa { namespace agent { template class StateDetector : 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"); + STATIC_ASSERT((std::is_arithmetic::value), + "process type is not to arithmetic"); protected: using PartFuncPointer = std::shared_ptr>; using StepFuncPointer = std::shared_ptr>; /// The NextSignalStateID is a counter variable which stores the ID which the /// next signal state shall have. - unsigned int NextStateID; + uint32_t NextStateID; /// The SignalStateHasChanged is a flag that show whether a signal has changed /// its state. bool StateHasChanged; }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SIGNALSTATEDETECTOR_HPP diff --git a/include/rosa/agent/SystemState.hpp b/include/rosa/agent/SystemState.hpp index d1b8920..7599e8e 100644 --- a/include/rosa/agent/SystemState.hpp +++ b/include/rosa/agent/SystemState.hpp @@ -1,173 +1,223 @@ //===-- rosa/agent/SystemState.hpp ------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SystemState.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *system state* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SYSTEMSTATE_HPP #define ROSA_AGENT_SYSTEMSTATE_HPP #include "rosa/agent/Functionality.h" #include "rosa/agent/SignalState.hpp" +#include "rosa/agent/State.hpp" #include "rosa/support/debug.hpp" #include 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 : uint8_t { - STABLE = 0, ///< The system state is stable - DRIFTING = 1, ///< The system state is drifting - MALFUNCTIONING = 2, ///< The system state is malfunctioning - UNKNOWN = 3 ///< The system state is unknown +enum class SystemStateRelation : uint8_t { + STATEISMATCHING = 0, ///< The system state is matching + ONLYINPUTISMATCHING = 1, ///< Only inputs of the system state are matching + ONLYOUTPUTISMATCHING = 2, ///< Only outputs of the system state are matching + STATEISMISMATCHING = 3 ///< The system state is mismatching }; /// 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 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) - SystemStateCondition SystemStateCondition; - /// The SystemStateIsValid saves the number of samples which have been - /// inserted into the state after entering it. - 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; +template +struct SystemStateInformation : StateInformation { + /// TODO: describe + CONFDATATYPE ConfidenceStateIsFunctioning; + CONFDATATYPE ConfidenceStateIsMalfunctioning; + CONFDATATYPE ConfidenceOfAllDecisions; }; // todo: do we need PROCDATATYPE? /// TODO TEXT template -class SystemState : public Functionality { +class SystemState : public State { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT(std::is_arithmetic::value, "input data type is not to arithmetic"); STATIC_ASSERT(std::is_arithmetic::value, "confidence abstraction type is not to arithmetic"); STATIC_ASSERT(std::is_arithmetic::value, "process data type is not to arithmetic"); private: + /// SignalStateInfo is a struct of SignalStateInformation that contains + /// information about the current signal state. SystemStateInformation SystemStateInfo; - std::vector> Signals; + std::vector> SignalStateInfos; uint32_t NumberOfSignals; public: /// TODO: write description SystemState(uint32_t StateID, uint32_t NumberOfSignals) noexcept - : SystemStateInfo{StateID, 0, SystemStateCondition::UNKNOWN, 0, false, - false, false}, + : SystemStateInfo{StateID, StateConditions::UNKNOWN, + false, false, + false, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}, NumberOfSignals(NumberOfSignals) { //@benedikt: there is now possibility to not doing the resize within these //{}-brackets, right? - Signals.resize(NumberOfSignals); + SignalStateInfos.resize(NumberOfSignals); } /// Destroys \p this object. ~SystemState(void) = default; + /// TODO: write description + SystemStateInformation insertSignalStateInformation( + const std::vector> + _SignalStateInfos) noexcept { + ASSERT(_SignalStateInfos.size() < NumberOfSignals); + + bool AllSignalsAreValid = true; + bool AtLeastOneSignalJustGotValid = false; + bool AllSignalsAreValidAfterReentrance = true; + + bool AllSignalsAreStable = true; + + std::size_t counter = 0; + for (auto SSI : _SignalStateInfos) { + + if (!SSI.StateIsValid) + AllSignalsAreValid = false; + + if (SSI.StateJustGotValid) + AtLeastOneSignalJustGotValid = true; + + if (!SSI.StateIsValidAfterReentrance) + AllSignalsAreValidAfterReentrance = false; + + if (SSI.StateCondition == StateConditions::DRIFTING) + AllSignalsAreStable = false; + + this->SignalStateInfos.at(counter) = SSI; + counter++; + } + + SystemStateInfo.StateIsValid = AllSignalsAreValid; + SystemStateInfo.StateJustGotValid = + AllSignalsAreValid && AtLeastOneSignalJustGotValid; + SystemStateInfo.StateIsValidAfterReentrance = + AllSignalsAreValidAfterReentrance; + + return SystemStateInfo; + } + + /// TODO: write description + // TODO (future): think about saving the state information in a history + SystemStateRelation compareSignalStateInformation( + const std::vector> + _SignalStateInfos) noexcept { + bool inputsAreMatching = true; + bool outputsAreMatching = true; + std::size_t counter = 0; + for (auto SSI : _SignalStateInfos) { + if (this->SignalStateInfos.at(counter).StateID != SSI.StateID) { + if (SSI.SignalProperty == SignalProperties::INPUT) + inputsAreMatching = false; + else // SignalProperties::OUTPUT + outputsAreMatching = false; + } + counter++; + } + + if (inputsAreMatching && outputsAreMatching) + return SystemStateRelation::STATEISMATCHING; + else if (inputsAreMatching && !outputsAreMatching) + return SystemStateRelation::ONLYINPUTISMATCHING; + else if (!inputsAreMatching && outputsAreMatching) + return SystemStateRelation::ONLYOUTPUTISMATCHING; + else + return SystemStateRelation::STATEISMISMATCHING; + } + +#ifdef ADDITIONAL_FUNCTIONS /// TODO: write description template void insertSignalStateInformation( const std::array, size> &Data) noexcept { - //@Daniel: is it possible to check with a ASSERT/STATIC_ASSERT whether the - // number of parameter is the same as NumberOfSignals (which is the length - // of the vectror)? ASSERT(size <= NumberOfSignals); std::size_t counter = 0; for (auto tmp : Data) { Signals.at(counter) = tmp; counter++; } } /// TODO: write description template std::enable_if_t>...>, void> insertSignalStateInformation(Types... Data) { - //@Daniel: is it possible to check with a ASSERT/STATIC_ASSERT whether the - // number of parameter is the same as NumberOfSignals (which is the length - // of the vectror)? - // // TODO (future): think about saving the state information in a history insertSignalStateInfos( std::array, sizeof...(Data)>( {Data...})); } // returns true if they are identical /// TODO: write description template bool compareSignalStateInformation( const std::array, size> &Data) noexcept { - //@Daniel: is it possible to check with a ASSERT/STATIC_ASSERT whether the - // number of parameter is the same as NumberOfSignals (which is the length - // of the vectror)? - // // TODO (future): think about saving the state information in a history std::size_t counter = 0; for (auto tmp : Data) { if (Signals.at(counter) != tmp) return false; counter++; } return true; } // checks only the given amount /// TODO: write description template std::enable_if_t>...>, bool> compareSignalStateInformation(Types... Data) { - //@Daniel: is it possible to check with a ASSERT/STATIC_ASSERT whether the - // number of parameter is the same as NumberOfSignals (which is the length - // of the vectror)? return compareSignalStateInfos( std::array, sizeof...(Data)>( {Data...})); } +#endif + + /// Gives information about the current signal state. + /// + /// \return a struct SignalStateInformation that contains information about + /// the current signal state. + SystemStateInformation systemStateInformation(void) noexcept { + return SystemStateInfo; + } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATE_HPP diff --git a/include/rosa/agent/SystemStateDetector.hpp b/include/rosa/agent/SystemStateDetector.hpp index b3fc125..2fe3f2c 100644 --- a/include/rosa/agent/SystemStateDetector.hpp +++ b/include/rosa/agent/SystemStateDetector.hpp @@ -1,114 +1,221 @@ //===-- 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/SignalState.hpp" #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 +/// System state conditions defining how the condition of a \c +/// rosa::agent::SystemState is saved in \c rosa::agent::SystemStateInformation. +// TODO: think about shifting this in SystemStateDetector and make a +// StateCondition with only stable, drifting, unknown +enum class SystemStateCondition : uint8_t { + STABLE = 0, ///< The system state is stable + DRIFTING = 1, ///< The system state is drifting + MALFUNCTIONING = 2, ///< The system state is malfunctioning + UNKNOWN = 3 ///< The system state is unknown +}; + /// TODO: write description template class SystemStateDetector : public StateDetector { using StateDetector = StateDetector; using PartFuncPointer = typename StateDetector::PartFuncPointer; private: // For the convinience to write a shorter data type name using SystemStatePtr = std::shared_ptr>; + /// TODO: description + uint32_t NumberOfSignals; + /// 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; + /// TODO: description + unsigned int TimeOfDisparity; + /// 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, + uint32_t MaximumNumberOfSystemStates, uint32_t NumberOfSignals, PartFuncPointer FuzzyFunctionDelayTimeToGetBroken, PartFuncPointer FuzzyFunctionDelayTimeToBeWorking) noexcept : CurrentSystemState(nullptr), DetectedSystemStates(MaximumNumberOfSystemStates), + NumberOfSignals(NumberOfSignals), TimeOfDisparity(0), FuzzyFunctionDelayTimeToGetBroken(FuzzyFunctionDelayTimeToGetBroken), FuzzyFunctionDelayTimeToBeWorking(FuzzyFunctionDelayTimeToBeWorking) { //@Benedikt: if I write "NextStateID(1), StateHasChanged(false)" before the //{}-brackets, the compiler tells me: "SystemStateDetector.hpp:72:9: error: // member initializer 'NextStateID'/'StateHasChanged' does not name a // non-static data member or base class" this->NextStateID = 1; this->StateHasChanged = false; } /// Destroys \p this object. ~SystemStateDetector(void) = default; /// TODO: write description SystemStateInformation - detectSystemState(INDATATYPE Sample) noexcept { + detectSystemState(std::vector> + SignalStateInfos) noexcept { + + SystemStateInformation SystemStateInfo; + + if (!CurrentSystemState) { + ASSERT(DetectedSystemStates.empty()); + SystemStatePtr S = createNewSystemState(); + CurrentSystemState = S; + + SystemStateInfo = + CurrentSystemState->insertSignalStateInformation(SignalStateInfos); + } else { + + SystemStateRelation SysStateRel = + CurrentSystemState->compareSignalStateInformation(SignalStateInfos); + + if (SysStateRel == SystemStateRelation::STATEISMATCHING) { + TimeOfDisparity = 0; + + SystemStateInfo = + CurrentSystemState->insertSignalStateInformation(SignalStateInfos); + } else { // ONLYINPUTISMATCHING, ONLYOUTPUTISMATCHING, STATEISMISMATCHING + + if (!CurrentSystemState->systemStateInformation().StateIsValid) + DetectedSystemStates.deleteEntry(CurrentSystemState); + CurrentSystemState = nullptr; + + SystemStatePtr potentialSystemState = nullptr; + + // search all saved system states + for (auto &SavedSystemState : DetectedSystemStates) { + SysStateRel = + SavedSystemState->compareSignalStateInformation(SignalStateInfos); + if (SysStateRel == SystemStateRelation::STATEISMATCHING) { + CurrentSystemState = SavedSystemState; + break; + } else if (SysStateRel == SystemStateRelation::ONLYINPUTISMATCHING || + SysStateRel == SystemStateRelation::ONLYOUTPUTISMATCHING) { + potentialSystemState = SavedSystemState; + } + } + + // actions depending whether state is matchin fully or only half + if (CurrentSystemState) { + TimeOfDisparity = 0; - // dummy line - Sample = 1; + SystemStateInfo = CurrentSystemState->insertSignalStateInformation( + SignalStateInfos); + + } else if (potentialSystemState) { + TimeOfDisparity++; + + CurrentSystemState = potentialSystemState; + + SystemStateInfo = CurrentSystemState->systemStateInformation(); + + } else { + SystemStatePtr S = createNewSystemState(); + TimeOfDisparity = 0; + + CurrentSystemState = S; + + SystemStateInfo = CurrentSystemState->insertSignalStateInformation( + SignalStateInfos); + } + } + } + + // TODO: is this right? if i don't insert if broke, it will never be valid?! + // right? + if (!SystemStateInfo.StateIsValid || + !SystemStateInfo.StateIsValidAfterReentrance) { + TimeOfDisparity = 0; + } + + // TODO: maybe make reference instead of pointer + CONFDATATYPE ConfidenceSystemIsMalfunctioning = + FuzzyFunctionDelayTimeToGetBroken->operator()( + static_cast(TimeOfDisparity)); + CONFDATATYPE ConfidenceSystemIsFunctioning = + FuzzyFunctionDelayTimeToBeWorking->operator()( + static_cast(TimeOfDisparity)); + + if (ConfidenceSystemIsMalfunctioning > ConfidenceSystemIsFunctioning) + SystemStateInfo.StateCondition = StateConditions::MALFUNCTIONING; + + // TODO: calculate overall confidence + + if (SystemStateInfo.StateJustGotValid) { + this->NextStateID++; + } + + return SystemStateInfo; } private: - /// Creates a new signal state and adds it to the signal state vector in which + /// Creates a new system state and adds it to the system 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. - SystemStatePtr createNewSignalState(void) noexcept { - SystemStatePtr S(new SignalState( + SystemStatePtr createNewSystemState(void) noexcept { + SystemStatePtr S(new SystemState( this->NextStateID, this->NumberOfSignals)); - DetectedSystemStates.addEntry(S); - return S; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP diff --git a/lib/agent/CMakeLists.txt b/lib/agent/CMakeLists.txt index 1c59f8e..70457fd 100644 --- a/lib/agent/CMakeLists.txt +++ b/lib/agent/CMakeLists.txt @@ -1,28 +1,30 @@ set(LIB_INCLUDE_DIR ${ROSA_MAIN_INCLUDE_DIR}/rosa/agent) add_library(ROSAAgent ${LIB_INCLUDE_DIR}/namespace.h namespace.cpp ${LIB_INCLUDE_DIR}/Functionality.h Functionality.cpp ${LIB_INCLUDE_DIR}/Abstraction.hpp Abstraction.cpp ${LIB_INCLUDE_DIR}/FunctionAbstractions.hpp FunctionAbstractions.cpp ${LIB_INCLUDE_DIR}/RangeConfidence.hpp RangeConfidence.cpp ${LIB_INCLUDE_DIR}/History.hpp History.cpp ${LIB_INCLUDE_DIR}/Confidence.hpp Confidence.cpp ${LIB_INCLUDE_DIR}/SignalState.hpp SignalState.cpp ${LIB_INCLUDE_DIR}/SignalStateDetector.hpp SignalStateDetector.cpp + ${LIB_INCLUDE_DIR}/State.hpp + State.cpp ${LIB_INCLUDE_DIR}/StateDetector.hpp StateDetector.cpp ${LIB_INCLUDE_DIR}/SystemState.hpp SystemState.cpp ${LIB_INCLUDE_DIR}/SystemStateDetector.hpp SystemStateDetector.cpp ) diff --git a/lib/agent/State.cpp b/lib/agent/State.cpp new file mode 100644 index 0000000..c3ae669 --- /dev/null +++ b/lib/agent/State.cpp @@ -0,0 +1,20 @@ +//===-- agent/State.cpp -----------------------------------------*- C++ -*-===// +// +// The RoSA Framework +// +//===----------------------------------------------------------------------===// +/// +/// \file agent/State.cpp +/// +/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) +/// +/// \date 2019 +/// +/// \brief Implementation for rosa/agent/State.hpp. +/// +/// \note Empty implementation, source file here to have a compile database +/// entry for rosa/agent/State.hpp. +/// +//===----------------------------------------------------------------------===// + +#include "rosa/agent/State.hpp"