diff --git a/include/rosa/agent/SystemState.hpp b/include/rosa/agent/SystemState.hpp index 7599e8e..9179139 100644 --- a/include/rosa/agent/SystemState.hpp +++ b/include/rosa/agent/SystemState.hpp @@ -1,223 +1,252 @@ //===-- 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 { 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 : StateInformation { /// TODO: describe CONFDATATYPE ConfidenceStateIsFunctioning; CONFDATATYPE ConfidenceStateIsMalfunctioning; CONFDATATYPE ConfidenceOfAllDecisions; }; // todo: do we need PROCDATATYPE? /// TODO TEXT template 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> SignalStateInfos; uint32_t NumberOfSignals; public: /// TODO: write description SystemState(uint32_t StateID, uint32_t NumberOfSignals) noexcept : 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? 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; + CONFDATATYPE CombinedConfidenceOfMatchingState = + _SignalStateInfos.front().ConfidenceOfMatchingState; + CONFDATATYPE CombinedConfidenceOfMismatchingState = + _SignalStateInfos.front().ConfidenceOfMismatchingState; + CONFDATATYPE CombinedConfidenceStateIsValid = + _SignalStateInfos.front().ConfidenceStateIsValid; + CONFDATATYPE CombinedConfidenceStateIsInvalid = + _SignalStateInfos.front().ConfidenceStateIsInvalid; + CONFDATATYPE CombinedConfidenceStateIsStable = + _SignalStateInfos.front().ConfidenceStateIsStable; + CONFDATATYPE CombinedConfidenceStateIsDrifting = + _SignalStateInfos.front().ConfidenceStateIsDrifting; + 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; + //@benedikt: instead of the initializing above and the and/or with itself, + // I could make here an if (counter == 0) + CombinedConfidenceOfMatchingState = fuzzyAND( + CombinedConfidenceOfMatchingState, SSI.ConfidenceOfMatchingState); + CombinedConfidenceOfMismatchingState = + fuzzyOR(CombinedConfidenceOfMismatchingState, + SSI.ConfidenceOfMismatchingState); + CombinedConfidenceStateIsValid = + fuzzyAND(CombinedConfidenceStateIsValid, SSI.ConfidenceStateIsValid); + CombinedConfidenceStateIsInvalid = fuzzyOR( + CombinedConfidenceStateIsInvalid, SSI.ConfidenceStateIsInvalid); + CombinedConfidenceStateIsStable = fuzzyAND( + CombinedConfidenceStateIsStable, SSI.ConfidenceStateIsStable); + CombinedConfidenceStateIsDrifting = fuzzyOR( + CombinedConfidenceStateIsDrifting, SSI.ConfidenceStateIsDrifting); + 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 { 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) { // 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 { // 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) { 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 2fe3f2c..9152dfa 100644 --- a/include/rosa/agent/SystemStateDetector.hpp +++ b/include/rosa/agent/SystemStateDetector.hpp @@ -1,221 +1,223 @@ //===-- 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 { +/* /// 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 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(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; 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 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 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