diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp index f477ac6..ba19135 100644 --- a/apps/ccam/ccam.cpp +++ b/apps/ccam/ccam.cpp @@ -1,24 +1,26 @@ //===-- apps/ccam/ccam.cpp --------------------------------------*- C++ -*-===// // // The RoSA Framework -- Application CCAM // //===----------------------------------------------------------------------===// /// /// \file apps/ccam/ccam.cpp /// /// \author Maximilian Goetzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief The application CCAM implements the case study from the paper: /// M. Goetzinger, N. TaheriNejad, H. A. Kholerdi, A. Jantsch, E. Willegger, /// T. Glatzl, A.M. Rahmani, T.Sauter, P. Liljeberg: Model - Free Condition /// Monitoring with Confidence //===----------------------------------------------------------------------===// +#include "rosa/agent/StateDetector.hpp" + #include int main(void) { - std::cout << "Test 123"; + std::cout << "Test 123\n"; return 0; } diff --git a/include/rosa/agent/State.hpp b/include/rosa/agent/State.hpp index 2d926c2..04b8584 100644 --- a/include/rosa/agent/State.hpp +++ b/include/rosa/agent/State.hpp @@ -1,130 +1,128 @@ //===-- 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/FunctionAbstractions.hpp" #include "rosa/agent/Functionality.h" #include "rosa/agent/History.hpp" +namespace rosa { +namespace agent { +// QUESTION: I think a global variable is not fine, I think it would be better +// to have that in private in the class. However, I have no idea how to +// initialize it then. +static unsigned int StateIdCounter = 0; +/// \tparam INDATATYPE type of input data, \tparam DABSTORETYPE type of data +/// in which DABs are saved, +template +class State : public Functionality { -namespace rosa { -namespace agent { - -using PartFuncPointer = std::shared_ptr>; + // 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), + "DAB storage type is not to arithmetic"); -/// \tparam DIN type of data of input, \tparam DDAB type of data in which DABs are saved, -template class State : public Functionality { - private: + using PartFuncPointer = + std::shared_ptr>; - unsigned int StateId; - - //counter static und nur raufzählen, wenn sprung von invalid auf valid + unsigned int StateId; + + DynamicLengthHistory SampleHistory; + DynamicLengthHistory DAB; + DynamicLengthHistory DABHistory; - DynamicHistory SampleHistory; - DynamicHistory DAB; - DynamicHistory DABHistory; - PartFuncPointer PartialFunctionSampleMatches; PartFuncPointer PartialFunctionSampleMismatches; PartFuncPointer PartialFunctionNumOfSamplesMatches; PartFuncPointer PartialFunctionNumOfSamplesMismatches; - + bool StateIsValid; bool StateIsValidAfterReentrance; - + public: - - State(unsigned int StateId, unsigned int sampleHistorySize, unsigned int DABSize, - unsigned int DABHistorySize, PartFuncPointer PartialFunctionSampleMatches, - PartialFunction* PartialFunctionSampleMismatches, - PartialFunction* PartialFunctionNumOfSamplesMatches, - PartialFunction* PartialFunctionNumOfSamplesMismatches) noexcept : - SampleHistory(sampleHistorySize), - DAB(DABSize), - DABHistory(DABHistorySize) { - this->StateId = StateId; //TODO: oben machen - this->PartialFunctionSampleMatches = PartialFunctionSampleMatches; - this->PartialFunctionSampleMismatches = PartialFunctionSampleMismatches; - this->PartialFunctionNumOfSamplesMatches = PartialFunctionNumOfSamplesMatches; - this->PartialFunctionNumOfSamplesMismatches = PartialFunctionNumOfSamplesMismatches; - StateIsValid = false; - StateIsValidAfterReentrance = false; - } - - //TODO: static assert -> check: - // 1) if DIN == arithmetic, - // 2) if DDAB == float, double, ...? (vielleicht annäherung mit int) - + State(unsigned int sampleHistorySize, unsigned int DABSize, + unsigned int DABHistorySize, + PartFuncPointer PartialFunctionSampleMatches, + PartFuncPointer PartialFunctionSampleMismatches, + PartFuncPointer PartialFunctionNumOfSamplesMatches, + PartFuncPointer PartialFunctionNumOfSamplesMismatches) noexcept + : SampleHistory(sampleHistorySize), DAB(DABSize), + DABHistory(DABHistorySize), + PartialFunctionSampleMatches(PartialFunctionSampleMatches), + PartialFunctionSampleMismatches(PartialFunctionSampleMismatches), + PartialFunctionNumOfSamplesMatches(PartialFunctionNumOfSamplesMatches), + PartialFunctionNumOfSamplesMismatches( + PartialFunctionNumOfSamplesMismatches) { + /* + StateIsValid = false; + StateIsValidAfterReentrance = false; + */ + } + ~State(void) = default; - + void leaveState(void) { - DAB.clear(); - StateIsValidAfterReentrance = false; + DAB.clear(); + StateIsValidAfterReentrance = false; } - - bool insertSample(D Sample) { - - bool workedForAll; //maybe ignor that //auc hnicht abchecken einfach kübeln - - - workedForAll = SampleHistory.addEntry(Sample); - - //QUESTION: is it important to have this flag (workedForAll). What should I do if it does not work at some point? - if (workedForAll) { - workedForAll &= DAB.addEntry(Sample); - if (workedForAll) { - if (DAB.full()) { - DDAB AvgOfDAB = DAB.average(); - - workedForAll &= DABHistory.addEntry(AvgOfDAB); - - if(workedForAll) { - DAB.clear(); - } //QUESTION: - what should be done if it has not worked? + + bool insertSample(INDATATYPE Sample) { + + bool workedForAll; // maybe ignor that //auc hnicht abchecken einfach kübeln + + workedForAll = SampleHistory.addEntry(Sample); + + // QUESTION: is it important to have this flag (workedForAll). What should I + // do if it does not work at some point? + if (workedForAll) { + workedForAll &= DAB.addEntry(Sample); + if (workedForAll) { + if (DAB.full()) { + DABSTORETYPE AvgOfDAB = DAB.average(); + + workedForAll &= DABHistory.addEntry(AvgOfDAB); + + if (workedForAll) { + DAB.clear(); + } // QUESTION: - what should be done if it has not worked? } - - if(workedForAll) { - //TODO: calculate whether state is valid - } - } - } - - return workedForAll; - } - - DDAB confSampleMatchesState (DIN sample) { - - - } - DDAB confSampleMismatchesState () { - - + + if (workedForAll) { + // TODO: calculate whether state is valid + } + } + } + + return workedForAll; } - + + // DDAB confSampleMatchesState(DIN sample) { return NULL; } + + // DDAB confSampleMismatchesState() {} + unsigned int stateId(void) { return StateId; } - - - }; - + } // End namespace agent } // End namespace rosa -#endif // ROSA_AGENT_STATE_HPP \ No newline at end of file +#endif // ROSA_AGENT_STATE_HPP diff --git a/include/rosa/agent/StateDetector.hpp b/include/rosa/agent/StateDetector.hpp index 87856e4..fc1ee37 100644 --- a/include/rosa/agent/StateDetector.hpp +++ b/include/rosa/agent/StateDetector.hpp @@ -1,226 +1,208 @@ //===-- 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 detection* *functionality*. /// //===----------------------------------------------------------------------===// #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 +#include + namespace rosa { namespace agent { - -//maybe using - - + template struct StateInformation { unsigned int statenumber; CONFTYPE confidences; - bool stable; //maybe: conf - bool drift; //maybe: conf - bool stateUnchanged; //check name -} - - -//DIN = Input Datatype, CONF = Confidence Datatype -template class StateDetector : public Functionality { - -//TODO: STATIC_ASSERT (maybe auch integer) - + bool stable; // maybe: conf + bool drift; // maybe: conf + bool stateUnchanged; // check name +}; + +// DIN = Input Datatype, CONF = Confidence Datatype +/// \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: + using partFuncPointer = + std::shared_ptr>; + using statePtr = std::shared_ptr>; + unsigned int discreteAveragePartitionCounter; - - vector DetectedStates; - + + std::shared_ptr ActualState; + std::vector DetectedStates; + bool stateIsValid; bool stateIsValidAfterReentrance; - - PartialFunction ConfidenceSimilarToSample; - - State *ActualState; - + + partFuncPointer PartialFunctionSampleMatches; + partFuncPointer PartialFunctionSampleMismatches; + partFuncPointer PartialFunctionNumOfSamplesMatches; + partFuncPointer PartialFunctionNumOfSamplesMismatches; + unsigned int SampleHistorySize; unsigned int DABSize; unsigned int DABHistorySize; - + //@Benedikt: partialfunction/linearfunction: steigung/domain ändern //@Benedikt: linearfunction set k,d or x1/y1 and x2/y2 - std::shared_ptr> PartialFunctionSampleMatches; - std::shared_ptr> PartialFunctionSampleMismatches; - std::shared_ptr> PartialFunctionNumOfSamplesMatches; - std::shared_ptr> PartialFunctionNumOfSamplesMismatches; - - //QUESTION: Do we need the following to flag + + // QUESTION: Do we need the following to flag bool StateHasChanged; - - //QUESTION: Would this be better as a static variable in State.hpp (there would be the problem when deleting a state) - unsigned int StateIdCounter = 1; public: - - //TODO: finish constructor + // TODO: finish constructor StateDetector() noexcept { - - ActualState = NULL; //MAYBE CHANGE TO CURRENT oder Active - - } - - - - - - - - std::shared_ptr detectState (DIN Sample) { //return tuple oder struct (statenumber, confidences, stable, drift, changed/unchanged) - - std::shared_ptr StateInfo; - - if(ActualState == NULL) { - ASSERT(DetectedStates.empty()); - - if(State *S = createNewState()) { - - ActualState = S; - - } //QUESTION: should there an output (log) when it was not successfull? - } - else { - CONF ConfidenceSampleMatchesState = - ActualState->confSampleMatchesState(Sample); - CONF ConfidenceSampleMismatchesState = - ActualState->confSampleMismatchesState(Sample); - - if(ConfidenceSampleMatchesState > ConfidenceSampleMismatchesState) { - - StateHasChanged = false; - - } - else { - - StateHasChanged = true; - - - //TODO: check whether ActiveState is valid - //TODO: if invalid -> deleteState (einfach pop weil shared pointer) - //TODO: else leaveState - - - //TODO FAR AWAY FUTURE: additionally save averages to enable fast iteration through recorded state vector - //- maybe sort vector based on these average values - ActualState = NULL; - for(auto &SavedState : DetectedStates) { - - if(SavedState != ActualState) { - CONF ConfidenceSampleMatchesState = - SavedState->confSampleMatchesState(Sample); - CONF ConfidenceSampleMismatchesState = - SavedState->confSampleMismatchesState(Sample); - - if(ConfidenceSampleMatchesState > ConfidenceSampleMismatchesState) { - - //QUESTION: maybe it would be better to compare ConfidenceSampleMatchesState - //of all states in the vector - ActualState = SavedState; - - break; - } - } - } - - if(!ActualState) { - if(State *S = createNewState()) { - - ActualState = S; - - } //QUESTION: should there an output (log) when it was not successfull? - } - } - } - - ActualState->insertSample(Sample); - - //TODO: check actual state whether it drifts - //TODO: write in StateInfo - - - return StateInfo; - - } - - - - - - bool stateHasChanged(void) { - return StateHasChanged; + + ActualState = NULL; // MAYBE CHANGE TO CURRENT oder Active } - - - bool stateIsUnchanged(void) { - return !StateHasChanged; + + /// A sample is input of the function, state detector is looking for a + /// matching state. If it finds a matching one, it inserts the sample, + /// otherwiese it creates a new state. + std::shared_ptr> + detectState(INDATATYPE Sample) { // return tuple oder struct (statenumber, + // confidences, stable, drift, changed/unchanged) + + std::shared_ptr> StateInfo; + + if (ActualState == NULL) { + ASSERT(DetectedStates.empty()); + + if (statePtr S = createNewState()) { + + ActualState = S; + + } // QUESTION: should there an output (log) when it was not successfull? + } else { + CONFTYPE ConfidenceSampleMatchesState = + ActualState->confSampleMatchesState(Sample); + CONFTYPE ConfidenceSampleMismatchesState = + ActualState->confSampleMismatchesState(Sample); + + if (ConfidenceSampleMatchesState > ConfidenceSampleMismatchesState) { + + StateHasChanged = false; + + } else { + + StateHasChanged = true; + + // TODO: check whether ActiveState is valid + // TODO: if invalid -> deleteState (einfach pop weil shared pointer) + // TODO: else leaveState + + // TODO FAR AWAY FUTURE: additionally save averages to enable fast + // iteration through recorded state vector + //- maybe sort vector based on these average values + ActualState = NULL; + for (auto &SavedState : DetectedStates) { + + if (SavedState != ActualState) { + CONFTYPE ConfidenceSampleMatchesState = + SavedState->confSampleMatchesState(Sample); + CONFTYPE ConfidenceSampleMismatchesState = + SavedState->confSampleMismatchesState(Sample); + + if (ConfidenceSampleMatchesState > + ConfidenceSampleMismatchesState) { + + // QUESTION: maybe it would be better to compare + // ConfidenceSampleMatchesState + // of all states in the vector + ActualState = SavedState; + + break; + } + } + } + + if (!ActualState) { + if (statePtr S = createNewState()) { + + ActualState = S; + + } // QUESTION: should there an output (log) when it was not + // successfull? + } + } + } + + ActualState->insertSample(Sample); + + // TODO: check actual state whether it drifts + // TODO: write in StateInfo + + return StateInfo; } - - //TODO: get confidences, get drift/stable get, get active state number, - //TODO: maybe just return struct with everything - - - + + bool stateHasChanged(void) { return StateHasChanged; } + + bool stateIsUnchanged(void) { return !StateHasChanged; } + + // TODO: get confidences, get drift/stable get, get active state number, + // TODO: maybe just return struct with everything + private: - - std::shared_ptr createNewState(){ - - bool CreatingWorked; - - std::shared_ptr = new (nothrow) State(StateIdCounter, SampleHistorySize, DABSize, - DABHistorySize, PartialFunctionSampleMatches, - PartialFunctionSampleMismatches, - PartialFunctionNumOfSamplesMatches, - PartialFunctionNumOfSamplesMismatches); - - if(S) { - DetectedStates.push_back(S); //QUESTION: how to make this without any exception? - - CreatingWorked = true; - //TODO: if push_back did not work -> CreatingWorked = false; - } - else { - //delete S; - - CreatingWorked = false; - } - - if(CreatingWorked) { - - StateIdCounter++; - - return S; - } - else { - return NULL; - } + statePtr createNewState() { + + bool CreatingWorked; + + statePtr S = new (std::nothrow) + State(StateIdCounter, SampleHistorySize, DABSize, DABHistorySize, + PartialFunctionSampleMatches, PartialFunctionSampleMismatches, + PartialFunctionNumOfSamplesMatches, + PartialFunctionNumOfSamplesMismatches); + + if (S) { + DetectedStates.push_back( + S); // QUESTION: how to make this without any exception? + + CreatingWorked = true; + // TODO: if push_back did not work -> CreatingWorked = false; + } else { + // delete S; + + CreatingWorked = false; + } + + if (CreatingWorked) { + + StateIdCounter++; + + return S; + } else { + return NULL; + } } - - - - - -}; - - +}; + } // End namespace agent } // End namespace rosa -#endif // ROSA_AGENT_STATEDETECTOR_HPP \ No newline at end of file +#endif // ROSA_AGENT_STATEDETECTOR_HPP