diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp index 983a106..07623fb 100644 --- a/apps/ccam/ccam.cpp +++ b/apps/ccam/ccam.cpp @@ -1,386 +1,387 @@ //===-- apps/ccam/ccam.cpp --------------------------------------*- C++ -*-===// // // The RoSA Framework -- Application CCAM // //===----------------------------------------------------------------------===// /// /// \file apps/ccam/ccam.cpp /// /// \author Maximilian Goetzinger (maximilian.goetzinger@tuwien.ac.at) /// \author Benedikt Tutzer (benedikt.tutzer@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/Abstraction.hpp" #include "rosa/agent/Confidence.hpp" #include "rosa/agent/FunctionAbstractions.hpp" #include #include "rosa/config/version.h" #include "rosa/agent/SignalStateDetector.hpp" #include "rosa/agent/SystemStateDetector.hpp" #include "rosa/deluxe/DeluxeContext.hpp" #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" #include #include #include #include #include "configuration.h" using namespace rosa; using namespace rosa::agent; using namespace rosa::deluxe; using namespace rosa::terminal; const std::string AppName = "CCAM"; //@maxi I don't know what you want to do but if you want to have the agent be a //"lowlevel" agent which gives its master a tuple with all of that info you have // to do it as it is done in the #else. To be fair I don't know if the return // SignalStateTuple(); is allowed /* #if false using SignalStateTuple = std::tuple, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional>; AgentHandle createSignalStateDetectorAgent( std::unique_ptr &C, const std::string &Name, std::shared_ptr< SignalStateDetector> SigSD) { (void)SigSD; using Handler = std::function)>; return C->createAgent( Name, Handler([&Name, &SigSD](std::pair I) -> SignalStateTuple { LOG_INFO_STREAM << "\n******\n" << Name << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; auto StateInfo = SigSD->detectSignalState(I.first); if (I.second) return std::make_tuple( Optional(I.first), Optional(StateInfo.SignalStateID), Optional(StateInfo.SignalStateConfidence), Optional(StateInfo.SignalStateCondition), Optional( StateInfo.NumberOfInsertedSamplesAfterEntrance), Optional(StateInfo.SignalStateIsValid), Optional(StateInfo.SignalStateJustGotValid), Optional(StateInfo.SignalStateIsValidAfterReentrance), Optional(StateInfo.SignalIsStable)); return SignalStateTuple(); })); } #else using tup = DeluxeTuple; using SignalStateTuple = Optional; AgentHandle createSignalStateDetectorAgent( std::unique_ptr &C, const std::string &Name, std::shared_ptr< SignalStateDetector> SigSD) { (void)SigSD; using Handler = std::function, bool>)>; return C->createAgent( Name, Handler([&Name, &SigSD]( std::pair, bool> I) -> SignalStateTuple { LOG_INFO_STREAM << "\n******\n" << Name << " " << (I.second ? "" : "") << " value: " << std::get<0>(I.first) << "\n******\n"; auto StateInfo = SigSD->detectSignalState(std::get<0>(I.first)); if (I.second) return {tup( std::get<0>(I.first), StateInfo.SignalStateID, StateInfo.SignalStateConfidence, StateInfo.SignalStateCondition, StateInfo.NumberOfInsertedSamplesAfterEntrance, StateInfo.SignalStateIsValid, StateInfo.SignalStateJustGotValid, StateInfo.SignalStateIsValidAfterReentrance, StateInfo.SignalIsStable)}; return SignalStateTuple(); })); } #endif */ int main(int argc, char **argv) { LOG_INFO_STREAM << '\n' << library_string() << " -- " << Color::Red << AppName << "app" << Color::Default << '\n'; if (argc < 2) { LOG_ERROR("Specify config File!\nUsage:\n\tccam config.json"); return 1; } std::string ConfigPath = argv[1]; if (!readConfigFile(ConfigPath)) { LOG_ERROR_STREAM << "Could not read config from \"" << ConfigPath << "\"\n"; return 2; } std::string InputFilePath, OutputFilePath; LOG_INFO("Creating Context"); std::unique_ptr C = DeluxeContext::create(AppName); LOG_INFO("Creating sensors, SignalStateDetector functionalities and their " "Abstractions."); std::vector Sensors; std::vector>> SampleMatchesFunctions; std::vector>> SampleMismatchesFunctions; std::vector>> SignalIsStableFunctions; std::vector>> SignalIsDriftingFunctions; std::vector>> NumOfSamplesMatchFunctions; std::vector>> NumOfSamplesMismatchFunctions; std::vector> SignalStateDetectors; std::vector SignalStateDetectorAgents; for (auto SignalConfiguration : AppConfig.SignalConfigurations) { // // Create deluxe sensors. // Sensors.emplace_back(C->createSensor(SignalConfiguration.Name)); // // Create functionalities for SignalStateDetector. // SampleMatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 0.f, -SignalConfiguration.InnerBound, 1.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 1.f, SignalConfiguration.OuterBound, 0.f)}, }, 0)); SampleMismatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 1.f, -SignalConfiguration.InnerBound, 0.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 0.f, SignalConfiguration.OuterBound, 1.f)}, }, 1)); SignalIsStableFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 0.f, -SignalConfiguration.InnerBoundDrift, 1.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 1.f, SignalConfiguration.OuterBoundDrift, 0.f)}, }, 0)); SignalIsDriftingFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 1.f, -SignalConfiguration.InnerBoundDrift, 0.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 0.f, SignalConfiguration.OuterBoundDrift, 1.f)}, }, 1)); NumOfSamplesMatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp)); NumOfSamplesMismatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown)); // // Create SignalStateDetector functionality // - SignalStateDetectors.emplace_back( + SignalStateDetectors.emplace_back(// es fehlt SignaProperties + SignalProperties(), std::numeric_limits::max(), SampleMatchesFunctions.back(), SampleMismatchesFunctions.back(), NumOfSamplesMatchFunctions.back(), NumOfSamplesMismatchFunctions.back(), SignalIsDriftingFunctions.back(), SignalIsStableFunctions.back(), SignalConfiguration.SampleHistorySize, SignalConfiguration.DABSize, SignalConfiguration.DABHistorySize); // // Create low-level deluxe agents // // SignalStateDetectorAgents.push_back(createSignalStateDetectorAgent( // C, SignalConfiguration.Name, SignalStateDetectors.back())); // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); C->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(), "HR Sensor Channel"); } std::shared_ptr> BrokenDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 0.f, AppConfig.BrokenCounter, 1.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(1.f, 0.f)}}, 0.f)); std::shared_ptr> OkDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 1.f, AppConfig.BrokenCounter, 0.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(0.f, 0.f)}}, 1.f)); std::shared_ptr< SystemStateDetector> SystemStateDetectorF( new SystemStateDetector( std::numeric_limits::max(), BrokenDelayFunction, OkDelayFunction)); // // Create a high-level deluxe agent. // LOG_INFO("Create high-level agent."); // The new agent logs its input values and results in the the sum of them. /** AgentHandle BodyAgent = C->createAgent( "Body Agent", DeluxeAgent::D( [](std::pair HR, std::pair BR, std::pair SpO2, std::pair BPSys, std::pair BodyTemp) -> Optional { LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n" << (HR.second ? "" : "") << " HR warning score: " << HR.first << "\n" << (BR.second ? "" : "") << " BR warning score: " << BR.first << "\n" << (SpO2.second ? "" : "") << " SpO2 warning score: " << SpO2.first << "\n" << (BPSys.second ? "" : "") << " BPSys warning score: " << BPSys.first << "\n" << (BodyTemp.second ? "" : "") << " BodyTemp warning score: " << BodyTemp.first << "\n******\n"; return {HR.first + BR.first + SpO2.first + BPSys.first + BodyTemp.first}; })); */ // // Connect low-level agents to the high-level agent. // LOG_INFO("Connect low-level agents to the high-level agent."); /// C->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel"); // // For simulation output, create a logger agent writing the output of the // high-level agent into a CSV file. // LOG_INFO("Create a logger agent."); // Create CSV writer. /// std::ofstream ScoreCSV(ScoreCSVPath); /// csv::CSVWriter ScoreWriter(ScoreCSV); // The agent writes each new input value into a CSV file and produces nothing. /** AgentHandle LoggerAgent = C->createAgent( "Logger Agent", DeluxeAgent::D( [&ScoreWriter](std::pair Score) -> Optional { if (Score.second) { // The state of \p ScoreWriter is not checked, expecting good. ScoreWriter << Score.first; } return {}; })); */ // // Connect the high-level agent to the logger agent. // LOG_INFO("Connect the high-level agent to the logger agent."); /// C->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel"); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // // Initialize deluxe context for simulation. // // C->initializeSimulation(); // // Open CSV files and register them for their corresponding sensors. // // // Simulate. // /// C->simulate(NumberOfSimulationCycles); return 0; } diff --git a/include/rosa/agent/SignalStateDetector.hpp b/include/rosa/agent/SignalStateDetector.hpp index 2e580cd..2dbcdf3 100644 --- a/include/rosa/agent/SignalStateDetector.hpp +++ b/include/rosa/agent/SignalStateDetector.hpp @@ -1,283 +1,284 @@ //===-- rosa/agent/SignalStateDetector.hpp ----------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SignalStateDetector.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *signal state detector* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SIGNALSTATEDETECTOR_HPP #define ROSA_AGENT_SIGNALSTATEDETECTOR_HPP #include "rosa/agent/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 - : NextSignalStateID(1), SignalStateHasChanged(false), - CurrentSignalState(nullptr), SignalProperty(SignalProperty), + : // needed to be reorderd + SignalProperty(SignalProperty), NextSignalStateID(1), + SignalStateHasChanged(false), CurrentSignalState(nullptr), DetectedSignalStates(MaximumNumberOfSignalStates), FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches), FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches), FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches), FuzzyFunctionNumOfSamplesMismatches( FuzzyFunctionNumOfSamplesMismatches), FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting), FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable), SampleHistorySize(SampleHistorySize), DABSize(DABSize), DABHistorySize(DABHistorySize) {} /// Destroys \p this object. ~SignalStateDetector(void) = default; /// Detects the signal state to which the new sample belongs or create a new /// signal state if the new sample does not match to any of the saved states. /// /// \param Sample is the actual sample of the observed signal. /// /// \return the information of the current signal state (signal state ID and /// other parameters). // 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; if (CurrentSignalState->signalStateInformation().SignalStateIsValid) { CurrentSignalState->leaveSignalState(); } 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; } } } if (!CurrentSignalState) { SignalStatePtr S = createNewSignalState(); CurrentSignalState = S; } } } SignalStateInformation SignalStateInfo = CurrentSignalState->insertSample(Sample); if (SignalStateInfo.SignalStateJustGotValid) { NextSignalStateID++; } return SignalStateInfo; } /// Gives information about the current signal state. /// /// \return a struct SignalStateInformation that contains information about /// the current signal state or NULL if no current signal state exists. SignalStateInformation currentSignalStateInformation(void) noexcept { if (CurrentSignalState) { return CurrentSignalState->signalStateInformation(); } else { return NULL; } } /// Gives information whether a signal state change has happened or not. /// /// \return true if a signal state change has happened, and false if not. bool signalStateHasChanged(void) noexcept { return SignalStateHasChanged; } private: /// Creates a new signal state and adds it to the signal state vector in which /// all known states are saved. /// /// \return a pointer to the newly created signal state or NULL if no state /// could be created. SignalStatePtr createNewSignalState(void) noexcept { SignalStatePtr S(new SignalState( NextSignalStateID, SampleHistorySize, DABSize, DABHistorySize, *FuzzyFunctionSampleMatches, *FuzzyFunctionSampleMismatches, *FuzzyFunctionNumOfSamplesMatches, *FuzzyFunctionNumOfSamplesMismatches, *FuzzyFunctionSignalIsDrifting, *FuzzyFunctionSignalIsStable)); DetectedSignalStates.addEntry(S); return S; } }; } // 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 e73c62a..808c7c0 100644 --- a/include/rosa/agent/SystemState.hpp +++ b/include/rosa/agent/SystemState.hpp @@ -1,146 +1,131 @@ //===-- 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/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 { STABLE, ///< The system state is stable DRIFTING, ///< The system state is drifting MALFUNCTIONING, ///< The system state is malfunctioning UNKNOWN ///< The system state is unknown }; /// TODO: write description template struct SystemStateInformation { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT((std::is_arithmetic::value), "confidence type is not to arithmetic"); /// The system state ID saved as an 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; }; // todo: do we need PROCDATATYPE? /// TODO TEXT template class SystemState : public Functionality { // 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: SystemStateInformation SystemStateInfo; std::vector> Signals; + uint32_t NumberOfSignals; + public: /// TODO write SystemState(uint32_t SignalStateID, uint32_t NumberOfSignals) noexcept - : SystemStateInfo{ - SignalStateID, 0, SystemStateCondition::UNKNOWN, 0, false, - false, false} { + : SystemStateInfo{SignalStateID, + 0, + SystemStateCondition::UNKNOWN, + 0, + false, + false, + false}, + NumberOfSignals(NumberOfSignals) { Signals.resize(NumberOfSignals); } /// Destroys \p this object. ~SystemState(void) = default; -#if false - //@Daniel: I try to insert system state infos with these two functions (copied - //from fuzzyOR) into the vector Signals. However, I do not know how to do - //that. - /// TODO: describe - template - CONFDATATYPE - insertSignalStateInfos(const std::array &Data) noexcept { - STATIC_ASSERT(std::is_arithmetic::value, - "Type of FuzzyAnd is not arithmetic"); - STATIC_ASSERT(size > 1, "Number of Arguments is to little"); - ASSERT(std::all_of(Data.begin(), Data.end(), - [](const auto &v) { return v <= 1 && v >= 0; })); - return *std::max_element(Data.begin(), Data.end()); - } - /// TODO: describe - template - std::enable_if_t< - std::conjunction_v...>, - CONFDATATYPE> - insertSignalStateInfos(const CONFDATATYPE Data, - const _CONFDATATYPE... Datan) noexcept { - return insertSignalStateInfos( - std::array{Data, Datan...}); - } -#endif - template void insertSignalStateInfos(const std::array, size> &Data) noexcept { - Signals.insert(Signals.end(), Data.begin(), Data.end()); + ASSERT(size <= NumberOfSignals); + std::size_t counter = 0; + for (auto tmp : Data) { + Signals.at(counter) = tmp; + counter++; + } } template std::enable_if_t>...>, - void> + void> insertSignalStateInfos(Types... Data) { insertSignalStateInfos( std::array, sizeof...(Data)>( {Data...})); } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATE_HPP