diff --git a/include/rosa/agent/SignalStateDetector.hpp b/include/rosa/agent/SignalStateDetector.hpp index 4dd321a..1cfcfb1 100644 --- a/include/rosa/agent/SignalStateDetector.hpp +++ b/include/rosa/agent/SignalStateDetector.hpp @@ -1,350 +1,353 @@ //===-- 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*. /// //===----------------------------------------------------------------------===// // TODO: noexcept #ifndef ROSA_AGENT_STATEDETECTOR_HPP #define ROSA_AGENT_STATEDETECTOR_HPP #include "rosa/agent/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/State.hpp" #include namespace rosa { namespace agent { /// Implements \c rosa::agent::StateDetector as a functionality that detects /// states given on input samples. /// /// \note This implementation is supposed to be used for samples of an /// arithmetic type. /// /// \tparam INDATATYPE is the type of input data, \tparam CONFTYPE is type of /// data in that the confidence values are given 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"); private: // For the convinience to write a shorter data type name using PartFuncPointer = std::shared_ptr>; using StepFuncPointer = std::shared_ptr>; using StatePtr = std::shared_ptr>; using StateInfoPtr = std::shared_ptr>; /// The NextStateID is a counter variable which stores the ID which the next /// state shall have. unsigned int NextStateID; /// The StateHasChanged is a flag that show whether a state change has /// happened. bool StateHasChanged; /// The CurrentState is a pointer to the (saved) state in which the actual /// variable (signal) of the observed system is. StatePtr CurrentState; /// The DetectedStates is vector in that all detected states are saved. std::vector DetectedStates; /// 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; /// DABSize the size of a DAB (Discrete Average Block). unsigned int DABSize; /// DABHistorySize is the (maximum) size of the DAB history. unsigned int 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 /// State . /// /// \param DABSize Sets the DAB size which will be used by \c State . /// /// \param DABHistorySize Sets the size which will be used by \c State . /// StateDetector(PartFuncPointer FuzzyFunctionSampleMatches, PartFuncPointer FuzzyFunctionSampleMismatches, StepFuncPointer FuzzyFunctionNumOfSamplesMatches, StepFuncPointer FuzzyFunctionNumOfSamplesMismatches, PartFuncPointer FuzzyFunctionSignalIsDrifting, PartFuncPointer FuzzyFunctionSignalIsStable, unsigned int SampleHistorySize, unsigned int DABSize, unsigned int DABHistorySize) noexcept : NextStateID(1), StateHasChanged(false), CurrentState(NULL), FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches), FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches), FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches), FuzzyFunctionNumOfSamplesMismatches( FuzzyFunctionNumOfSamplesMismatches), FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting), FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable), SampleHistorySize(SampleHistorySize), DABSize(DABSize), DABHistorySize(DABHistorySize) {} /// Destroys \p this object. ~StateDetector(void) = default; /// Detects the state to which the new sample belongs or create a new 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 state ID as unsigned integer type. State IDs start with number /// 1; that means if there is no current state, the return value is 0. unsigned int detectState(INDATATYPE Sample) { StateInfoPtr StateInfo = detectState__debug(Sample); return StateInfo->StateID; } /// Gives information about the current state. /// /// \return a the State ID (as unsigned integer type) of the current state. /// State IDs start with number 1; that means if there is no current state, /// the return value is 0. unsigned int currentStateInformation(void) { StateInfoPtr StateInfo = currentStateInformation__debug(); if (StateInfo) { return StateInfo->StateID; } else { return 0; } } /// Gives information whether a state change has happened or not. /// /// \return true if a state change has happened, and false if not. bool stateHasChanged(void) { return StateHasChanged; } private: //@maxi \param is there to Document a specific parameter of a method/function // this method doesn't have any parameters. /// Creates a new state and adds this state to the state vector in which all /// known states are saved. /// /// \param SampleHistorySize the (maximum) size of the sample history. /// \param DABSize the size of a DAB. /// \param DABHistorySize the (maximum) size of the DAB history. /// \param FuzzyFunctionSampleMatches the /// \param FuzzyFunctionSampleMismatches /// \param FuzzyFunctionNumOfSamplesMatches /// \param FuzzyFunctionNumOfSamplesMismatches /// /// \return a pointer to the newly created state or NULL if no state could be /// created. StatePtr createNewState(void) { StatePtr S = new (std::nothrow) State( SampleHistorySize, DABSize, DABHistorySize, FuzzyFunctionSampleMatches, FuzzyFunctionSampleMismatches, FuzzyFunctionNumOfSamplesMatches, FuzzyFunctionNumOfSamplesMismatches); // TODO: maybe assert which checks if push_back worked (ask benedikt) DetectedStates.push_back(S); return S; } #ifdef STATEDETECTORDEBUGMODE public: #else private: #endif // STATEDETECTORDEBUGMODE // @maxi is this a debug method or is it a method that will be used and // you simply want to have access to it in debug mode? // debug -> extend the preprocessor around the function // access -> remove the __debug from the name ( it is confusing) // if you want to have it marked as a debug method for auto // complete you can do something like this : // //#ifdef STATEDETECTORDEBUGMODE // public: // StateInfoPtr debug_detectState(INDATATYPE Sample) { // return detectState(Sample); // } //#endif // STATEDETECTORDEBUGMODE // private : // StateInfoPtr detectState(INDATATYPE Sample) { ... // /// Detects the state to which the new sample belongs or create a new 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 actual state (state ID and other /// parameters). // TODO: return something const.. cannot remember exactly (ask benedikt) // // maby: you are returning a pointer to the state info so who ever has that // pointer can actually change the information if you want to return only the // *current info* return a copy of the state info // like this: // // StateInfoPtr detectState__debug(INDATATYPE Sample) -> // StateInformation detectState__debug(INDATATYPE Sample) // // return CurrentState->stateInformation(); -> // return *(CurrentState->stateInformation()); StateInfoPtr detectState__debug(INDATATYPE Sample) { if (!CurrentState) { ASSERT(DetectedStates.empty()); StatePtr S = createNewState(); CurrentState = S; } else { CONFTYPE ConfidenceSampleMatchesState = CurrentState->confSampleMatchesState(Sample); CONFTYPE ConfidenceSampleMismatchesState = CurrentState->confSampleMismatchesState(Sample); if (ConfidenceSampleMatchesState > ConfidenceSampleMismatchesState) { StateHasChanged = false; } else { StateHasChanged = true; if (CurrentState->stateInformation()->StateIsValid) { CurrentState->leaveState(); } else { DetectedStates.erase(std::find(DetectedStates.begin(), DetectedStates.end(), CurrentState)); } // TODO (future): additionally save averages to enable fast // iteration through recorded state vector (maybe sort vector based on // these average values) CurrentState = nullptr; for (auto &SavedState : DetectedStates) { if (SavedState != CurrentState) { CONFTYPE ConfidenceSampleMatchesState = SavedState->confSampleMatchesState(Sample); CONFTYPE ConfidenceSampleMismatchesState = SavedState->confSampleMismatchesState(Sample); if (ConfidenceSampleMatchesState > ConfidenceSampleMismatchesState) { // TODO (future): maybe it would be better to compare // ConfidenceSampleMatchesState of all states in the vector in // order to find the best matching state. CurrentState = SavedState; break; } } } if (!CurrentState) { StatePtr S = createNewState(); CurrentState = S; } } } // State::insertSample() current return type: void StateInfoPtr StateInfo = CurrentState->insertSample(Sample); + // maby?: + // CurrentState->insertSample(Sample); + // StateInfoPtr StateInfo = CurrentState->stateInformation(); if (StateInfo->StateJustGotValid) { NextStateID++; } return CurrentState->stateInformation(); } #ifdef STATEDETECTORDEBUGMODE public: #else private: #endif // STATEDETECTORDEBUGMODE //@maxi here again are you sure you want to return the pointer? /// Gives information about the current state. /// /// \return a pointer to a struct StateInformation that contains information /// about the current state or NULL if no current state exists. StateInfoPtr currentStateInformation__debug(void) { if (CurrentState) { return CurrentState->stateInformation(); } else { return NULL; } } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_STATEDETECTOR_HPP