Page MenuHomePhorge

No OneTemporary

Size
57 KB
Referenced Files
None
Subscribers
None
diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp
index 91db629..b8d7a38 100644
--- a/apps/ccam/ccam.cpp
+++ b/apps/ccam/ccam.cpp
@@ -1,296 +1,292 @@
//===-- 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 <iostream>
#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 <fstream>
#include <limits>
#include <memory>
#include <streambuf>
#include "configuration.h"
#include "statehandlerutils.h"
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::deluxe;
using namespace rosa::terminal;
const std::string AppName = "CCAM";
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<DeluxeContext> C = DeluxeContext::create(AppName);
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction(
new PartialFunction<uint32_t, float>(
{{{0, AppConfig.BrokenCounter},
std::make_shared<LinearFunction<uint32_t, float>>(
0, 0.f, AppConfig.BrokenCounter, 1.f)},
{{AppConfig.BrokenCounter, std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(1.f, 0.f)}},
0.f));
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction(
new PartialFunction<uint32_t, float>(
{{{0, AppConfig.BrokenCounter},
std::make_shared<LinearFunction<uint32_t, float>>(
0, 1.f, AppConfig.BrokenCounter, 0.f)},
{{AppConfig.BrokenCounter, std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(0.f, 0.f)}},
1.f));
//
// Create a DeluxeAgent with SystemStateDetector functionality.
//
LOG_INFO("Create SystemStateDetector agent.");
AgentHandle SystemStateDetectorAgent = createSystemStateDetectorAgent(
C, "SystemStateDetector", AppConfig.SignalConfigurations.size(),
BrokenDelayFunction, OkDelayFunction);
C->setExecutionPolicy(SystemStateDetectorAgent,
DeluxeExecutionPolicy::awaitAll({}));
LOG_INFO("Creating sensors, SignalStateDetector functionalities and their "
"Abstractions.");
std::vector<AgentHandle> Sensors;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleMatchesFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleMismatchesFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SignalIsStableFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SignalIsDriftingFunctions;
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesMatchFunctions;
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesMismatchFunctions;
std::vector<std::shared_ptr<
SignalStateDetector<float, float, float, HistoryPolicy::FIFO>>>
SignalStateDetectors;
std::vector<AgentHandle> SignalStateDetectorAgents;
for (auto SignalConfiguration : AppConfig.SignalConfigurations) {
//
// Create deluxe sensors.
//
Sensors.emplace_back(C->createSensor<float>(SignalConfiguration.Name));
- C->setExecutionPolicy(Sensors.back(), DeluxeExecutionPolicy::decimation(1));
//
// Create functionalities for SignalStateDetector.
//
SampleMatchesFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 0.f,
-SignalConfiguration.InnerBound, 1.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(1.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 1.f,
SignalConfiguration.OuterBound, 0.f)},
},
0));
SampleMismatchesFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 1.f,
-SignalConfiguration.InnerBound, 0.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(0.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 0.f,
SignalConfiguration.OuterBound, 1.f)},
},
1));
SignalIsStableFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBoundDrift,
-SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBoundDrift, 0.f,
-SignalConfiguration.InnerBoundDrift, 1.f)},
{{-SignalConfiguration.InnerBoundDrift,
SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(1.f, 0.f)},
{{SignalConfiguration.InnerBoundDrift,
SignalConfiguration.OuterBoundDrift},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBoundDrift, 1.f,
SignalConfiguration.OuterBoundDrift, 0.f)},
},
0));
SignalIsDriftingFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBoundDrift,
-SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBoundDrift, 1.f,
-SignalConfiguration.InnerBoundDrift, 0.f)},
{{-SignalConfiguration.InnerBoundDrift,
SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(0.f, 0.f)},
{{SignalConfiguration.InnerBoundDrift,
SignalConfiguration.OuterBoundDrift},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBoundDrift, 0.f,
SignalConfiguration.OuterBoundDrift, 1.f)},
},
1));
NumOfSamplesMatchFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp));
NumOfSamplesMismatchFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown));
//
// Create SignalStateDetector functionality
//
SignalStateDetectors.emplace_back(
new SignalStateDetector<float, float, float, HistoryPolicy::FIFO>(
SignalConfiguration.Output ? SignalProperties::OUTPUT
: SignalProperties::INPUT,
std::numeric_limits<int>::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()));
- C->setExecutionPolicy(SignalStateDetectorAgents.back(),
- DeluxeExecutionPolicy::awaitAny({}));
//
- // Connect sensors to low-level agents.
+ // Open CSV files and register them for their corresponding sensors.
//
- LOG_INFO("Connect sensors to their corresponding low-level agents.");
-
- C->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(),
- SignalConfiguration.Name);
-
- C->connectAgents(SystemStateDetectorAgent, SignalStateDetectors.size() - 1,
- SignalStateDetectorAgents.back(),
- SignalConfiguration.Name);
-
std::ifstream SensorData(SignalConfiguration.InputPath);
if (!SensorData) {
LOG_ERROR_STREAM << "Cannot open Input File \""
<< SignalConfiguration.InputPath << "\" for Signal \""
<< SignalConfiguration.Name << "\"" << std::endl;
return 3;
}
C->registerSensorValues(Sensors.back(), csv::CSVIterator<float>(SensorData),
csv::CSVIterator<float>());
+
+ //
+ // Connect sensors to low-level agents.
+ //
+ LOG_INFO("Connect sensors to their corresponding low-level agents.");
+
+ C->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(),
+ SignalConfiguration.Name);
+
+ C->connectAgents(SystemStateDetectorAgent, SignalStateDetectors.size() - 1,
+ SignalStateDetectorAgents.back(),
+ SignalConfiguration.Name);
}
//
// 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 OutputCSV(AppConfig.OutputFilePath);
// The agent writes each new input value into a CSV file and produces nothing.
using Input = std::pair<SystemStateTuple, bool>;
using Result = Optional<DeluxeTuple<unit_t>>;
using Handler = std::function<Result(Input)>;
std::string Name = "Logger Agent";
AgentHandle LoggerAgent =
C->createAgent("Logger Agent", Handler([&OutputCSV](Input I) -> Result {
OutputCSV << std::get<0>(I.first) << std::endl;
return Result();
}));
C->setExecutionPolicy(LoggerAgent, DeluxeExecutionPolicy::awaitAny({}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO("Connect the high-level agent to the logger agent.");
C->connectAgents(LoggerAgent, 0, SystemStateDetectorAgent,
"SystemStateDetector 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(AppConfig.NumberOfSimulationCycles);
return 0;
}
diff --git a/apps/ccam/sample_data/.~lock.in1.csv# b/apps/ccam/sample_data/.~lock.in1.csv#
new file mode 100644
index 0000000..b94dc35
--- /dev/null
+++ b/apps/ccam/sample_data/.~lock.in1.csv#
@@ -0,0 +1 @@
+,benedikt,pc80-73.ICT.TUWIEN.AC.AT,11.07.2019 16:59,file:///home/benedikt/.config/libreoffice/4;
\ No newline at end of file
diff --git a/apps/ccam/sample_data/in1.csv b/apps/ccam/sample_data/in1.csv
new file mode 100644
index 0000000..591c18c
--- /dev/null
+++ b/apps/ccam/sample_data/in1.csv
@@ -0,0 +1,99 @@
+1.00092637855679
+1.0684190878191
+1.02810801913231
+0.919000276724945
+0.943251565157285
+1.0673083821227
+1.00478806202118
+1.03003739351774
+0.935803555791724
+0.915115988597241
+0.993705530463948
+1.01913848981603
+1.07575850547493
+1.09434496551336
+1.07517203808885
+0.934186505165392
+1.03597552982793
+0.946414558921609
+1.09077619397548
+0.937422306881499
+1.04025759458117
+0.953766068948048
+1.0220146735354
+0.945386311036124
+1.06874654600219
+1.08189482835294
+1.09471327339474
+0.997766816782878
+1.08249052586382
+0.980897423629193
+0.912525216564887
+1.01372830088446
+1.06301100164778
+0.954611398899798
+1.08882613398729
+0.929102332430527
+0.922853868564958
+0.916169223719992
+1.07542926597468
+0.952682775112019
+0.946923126637042
+1.02533001563823
+0.98000162285915
+0.943330241903967
+1.05670630068715
+1.00785095967723
+1.05878566260128
+1.08556887596959
+1.01674529482655
+0.961273507450319
+1.03264674265977
+1.06062171515438
+1.04551666887125
+1.08410951161761
+1.08402421925395
+0.987534405747127
+0.923876174437775
+0.972287310336838
+1.08312955950651
+0.985578427054398
+1.03558369622544
+1.04101672999734
+0.99352383758243
+0.99410500366067
+0.971399086444277
+0.925045641664989
+1.02935253874119
+1.00157578979235
+1.07471412992712
+1.07472627148258
+1.08713981155546
+1.00727502532395
+1.0280458178824
+0.93407010413228
+1.0037114548083
+1.00187148446296
+0.925961212840559
+1.07202022825656
+1.01071793991323
+1.0306490880833
+1.07436163529235
+0.95425466535745
+1.07385916085333
+0.92467285584664
+0.919083994601565
+1.05389817205938
+1.0945513132114
+0.929475954301933
+1.08572986354845
+1.06115342260273
+1.07016495486098
+1.03483066490236
+1.0282067965835
+1.04321565497961
+0.980982509875021
+0.923315546975167
+1.00066500619371
+1.07205423410099
+0.996924126125663
diff --git a/apps/ccam/sample_data/out.csv b/apps/ccam/sample_data/out.csv
new file mode 100644
index 0000000..e69de29
diff --git a/apps/ccam/sample_data/sample_config.json b/apps/ccam/sample_data/sample_config.json
new file mode 100644
index 0000000..bb2d3f9
--- /dev/null
+++ b/apps/ccam/sample_data/sample_config.json
@@ -0,0 +1,20 @@
+{
+ "OutputFilePath": "./out.csv",
+ "BrokenCounter": 10,
+ "NumberOfSimulationCycles": 100,
+ "SignalConfigurations":
+ [
+ {
+ "Name" : "Sig1",
+ "InputPath" : "./in1.csv",
+ "Output" : false,
+ "InnerBound" : 0.1,
+ "OuterBound" : 0.2,
+ "InnerBoundDrift" : 0.3,
+ "OuterBoundDrift" : 0.4,
+ "SampleHistorySize" : 10,
+ "DABSize" : 10,
+ "DABHistorySize" : 5
+ }
+ ]
+}
diff --git a/apps/ccam/statehandlerutils.h b/apps/ccam/statehandlerutils.h
index fb7b640..b95c737 100644
--- a/apps/ccam/statehandlerutils.h
+++ b/apps/ccam/statehandlerutils.h
@@ -1,184 +1,223 @@
#ifndef STATEHANDLERUTILS_H
#define STATEHANDLERUTILS_H
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/Confidence.hpp"
#include "rosa/agent/FunctionAbstractions.hpp"
#include <functional>
#include <iostream>
#include <tuple>
#include <vector>
#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 <fstream>
#include <limits>
#include <memory>
#include <streambuf>
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::deluxe;
using namespace rosa::terminal;
// Signal State
using SignalStateTuple =
DeluxeTuple<float, uint32_t, uint8_t, float, float, float, float, float,
float, uint8_t, uint32_t, uint8_t>;
AgentHandle createSignalStateDetectorAgent(
std::unique_ptr<DeluxeContext> &C, const std::string &Name,
std::shared_ptr<
SignalStateDetector<float, float, float, HistoryPolicy::FIFO>>
SigSD) {
using Input = std::pair<DeluxeTuple<float>, bool>;
using Result = Optional<SignalStateTuple>;
using Handler = std::function<Result(Input)>;
return C->createAgent(
Name, Handler([&Name, &SigSD](Input I) -> Result {
LOG_INFO_STREAM << "\n******\n"
<< Name << " " << (I.second ? "<New>" : "<Old>")
<< " value: " << std::get<0>(I.first) << "\n******\n";
auto StateInfo = SigSD->detectSignalState(std::get<0>(I.first));
if (I.second) {
SignalStateTuple Res = {
std::get<0>(I.first), StateInfo.StateID, StateInfo.SignalProperty,
//@benedikt: I changed this
// StateInfo.SignalStateConfidence,
StateInfo.ConfidenceOfMatchingState,
StateInfo.ConfidenceOfMismatchingState,
StateInfo.ConfidenceStateIsValid,
StateInfo.ConfidenceStateIsInvalid,
StateInfo.ConfidenceStateIsStable,
StateInfo.ConfidenceStateIsDrifting, StateInfo.StateCondition,
StateInfo.NumberOfInsertedSamplesAfterEntrance,
(uint8_t)((StateInfo.StateIsValid ? 4 : 0) +
(StateInfo.StateJustGotValid ? 2 : 0) +
(StateInfo.StateIsValidAfterReentrance ? 1 : 0))};
return Result(Res);
}
return Result();
}));
}
// System State
-
-using SystemStateTuple = DeluxeTuple<std::string, uint32_t, float, uint8_t,
- uint32_t, bool, bool, bool, bool>;
+using SystemStateTuple = DeluxeTuple<std::string>;
template <std::size_t size, typename ret, typename functype, typename... A>
struct Handler_helper;
template <typename B, typename func, typename A, typename... As>
struct function_helper {
static_assert(std::conjunction_v<std::is_same<A, As>...>,
"All types need to be identical");
static B function(A valA, As... valAs) {
std::vector<A> ar({valA, valAs...});
return func()(ar);
}
};
template <typename ret, typename typeA, typename functype, typename... B>
struct Handler_helper<0, ret, functype, typeA, B...> {
using handler = function_helper<ret, functype, B...>;
};
template <std::size_t size, typename ret, typename typeA, typename functype,
typename... B>
struct Handler_helper<size, ret, functype, typeA, B...> {
using handler =
typename Handler_helper<size - 1, ret, functype, typeA,
std::pair<typeA, bool>, B...>::handler;
};
template <std::size_t size, typename ret, typename functype, typename typeA>
using Handler = typename Handler_helper<size, ret, functype, typeA>::handler;
+// TODO: This is UGLY!
+std::shared_ptr<
+ SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>>
+ SysSD;
+
// todo: state-detector durschleifen
template <typename ret, typename A> struct function {
+
ret operator()(A a) {
- // std::vector<SystemStateInformation> out;
- for (auto tmp1 : a) {
+ std::vector<SignalStateInformation<float>> SignalStateInfos;
+ std::stringstream OutString;
+
+ for (auto _SignalStateTuple : a) {
// convert tuple to info struct out.push_back({});
- (void)tmp1;
- LOG_INFO_STREAM << "new SignalStateTuple!\n";
+ OutString << std::get<0>(_SignalStateTuple.first) << ",";
+ SignalStateInformation<float> Info;
+ Info.StateID = std::get<1>(_SignalStateTuple.first);
+ Info.SignalProperty =
+ static_cast<SignalProperties>(std::get<2>(_SignalStateTuple.first));
+ Info.ConfidenceOfMatchingState = std::get<3>(_SignalStateTuple.first);
+ Info.ConfidenceOfMismatchingState = std::get<4>(_SignalStateTuple.first);
+ Info.ConfidenceStateIsValid = std::get<5>(_SignalStateTuple.first);
+ Info.ConfidenceStateIsInvalid = std::get<6>(_SignalStateTuple.first);
+ Info.ConfidenceStateIsStable = std::get<7>(_SignalStateTuple.first);
+ Info.ConfidenceStateIsDrifting = std::get<8>(_SignalStateTuple.first);
+ Info.StateCondition =
+ static_cast<StateConditions>(std::get<9>(_SignalStateTuple.first));
+ Info.NumberOfInsertedSamplesAfterEntrance =
+ std::get<10>(_SignalStateTuple.first);
+ Info.StateIsValid = (std::get<11>(_SignalStateTuple.first) & 4) > 0;
+ Info.StateJustGotValid = (std::get<11>(_SignalStateTuple.first) & 2) > 0;
+ Info.StateIsValidAfterReentrance =
+ (std::get<11>(_SignalStateTuple.first) & 1) > 0;
+ SignalStateInfos.push_back(Info);
}
- // feed state detector
- // return result
- return ret();
+ SystemStateInformation<float> SystemStateInfo =
+ SysSD->detectSystemState(SignalStateInfos);
+
+ OutString << SystemStateInfo.StateID << ",";
+ OutString << SystemStateInfo.ConfidenceStateIsValid << ",";
+ OutString << SystemStateInfo.ConfidenceStateIsInvalid << ",";
+ OutString << SystemStateInfo.ConfidenceOfInputsMatchingState << ",";
+ OutString << SystemStateInfo.ConfidenceOfInputsMismatchingState << ",";
+ OutString << SystemStateInfo.ConfidenceOfOutputsMatchingState << ",";
+ OutString << SystemStateInfo.ConfidenceOfOutputsMismatchingState << ",";
+ OutString << SystemStateInfo.StateCondition << ",";
+ OutString << SystemStateInfo.ConfidenceSystemIsFunctioning << ",";
+ OutString << SystemStateInfo.ConfidenceSystemIsMalfunctioning << ",";
+ OutString << SystemStateInfo.ConfidenceOfAllDecisions << ",";
+
+ return ret(std::make_tuple<std::string>(OutString.str()));
}
};
using arr = std::vector<std::pair<SignalStateTuple, bool>>;
template <size_t NumOfSlaves>
AgentHandle createSystemStateDetectorAgent(
std::unique_ptr<DeluxeContext> &C, const std::string &Name,
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction,
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction) {
LOG_TRACE("Creating fixed SystemStateDetectorAgent");
using Input = SignalStateTuple;
using Result = Optional<SystemStateTuple>;
- auto HandlerFunction =
- Handler<NumOfSlaves, Result, function<Optional<SystemStateTuple>, arr>,
- Input>::function;
std::shared_ptr<
SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>>
- SysSD(new SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>(
+ _SysSD(new SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>(
std::numeric_limits<uint32_t>::max(), NumOfSlaves, BrokenDelayFunction,
OkDelayFunction));
+ SysSD = _SysSD;
+
+ auto HandlerFunction =
+ Handler<NumOfSlaves, Result, function<Optional<SystemStateTuple>, arr>,
+ Input>::function;
return C->createAgent(Name, std::function(HandlerFunction));
}
AgentHandle createSystemStateDetectorAgent(
std::unique_ptr<DeluxeContext> &C, const std::string &Name,
size_t NumOfSlaves,
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction,
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction) {
LOG_TRACE("Creating dynamic SystemStateDetectorAgent");
switch (NumOfSlaves) {
// clang-format off
case 2: return createSystemStateDetectorAgent< 2>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 3: return createSystemStateDetectorAgent< 3>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 4: return createSystemStateDetectorAgent< 4>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 5: return createSystemStateDetectorAgent< 5>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 6: return createSystemStateDetectorAgent< 6>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 7: return createSystemStateDetectorAgent< 7>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 8: return createSystemStateDetectorAgent< 8>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 9: return createSystemStateDetectorAgent< 9>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 10: return createSystemStateDetectorAgent<10>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 11: return createSystemStateDetectorAgent<11>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 12: return createSystemStateDetectorAgent<12>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 13: return createSystemStateDetectorAgent<13>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 14: return createSystemStateDetectorAgent<14>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 15: return createSystemStateDetectorAgent<15>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 16: return createSystemStateDetectorAgent<16>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 17: return createSystemStateDetectorAgent<17>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 18: return createSystemStateDetectorAgent<18>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 19: return createSystemStateDetectorAgent<19>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 20: return createSystemStateDetectorAgent<20>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 21: return createSystemStateDetectorAgent<21>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 22: return createSystemStateDetectorAgent<22>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 23: return createSystemStateDetectorAgent<23>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 24: return createSystemStateDetectorAgent<24>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 25: return createSystemStateDetectorAgent<25>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 1:
default: return createSystemStateDetectorAgent<1>(C, Name, BrokenDelayFunction, OkDelayFunction);
// clang-format on
}
}
#endif // STATEHANDLERUTILS_H
diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp
index ff09a42..9b86769 100644
--- a/include/rosa/agent/SignalState.hpp
+++ b/include/rosa/agent/SignalState.hpp
@@ -1,479 +1,481 @@
//===-- 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
};
/// TODO: write description
template <typename CONFDATATYPE>
struct SignalStateInformation : StateInformation<CONFDATATYPE> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<CONFDATATYPE>::value),
"confidence type is not to arithmetic");
/// TODO: describe
CONFDATATYPE ConfidenceOfMatchingState;
CONFDATATYPE ConfidenceOfMismatchingState;
/// The SignalProperty saves whether the monitored signal is an input our
/// output signal.
SignalProperties SignalProperty;
/// The SignalStateIsValid saves the number of samples which have been
/// inserted into the state after entering it.
uint32_t NumberOfInsertedSamplesAfterEntrance;
public:
SignalStateInformation(unsigned int SignalStateID,
SignalProperties _SignalProperty) {
this->StateID = SignalStateID;
this->SignalProperty = _SignalProperty;
this->StateCondition = StateConditions::UNKNOWN;
this->StateIsValid = false;
this->StateJustGotValid = false;
this->StateIsValidAfterReentrance = false;
this->ConfidenceStateIsValid = 0;
this->ConfidenceStateIsInvalid = 0;
this->ConfidenceStateIsStable = 0;
this->ConfidenceStateIsDrifting = 0;
}
+
+ SignalStateInformation() {}
};
/// \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 <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE>
class SignalState : public Functionality {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<INDATATYPE>::value),
"input data type not arithmetic");
STATIC_ASSERT((std::is_arithmetic<CONFDATATYPE>::value),
"confidence data type is not to arithmetic");
STATIC_ASSERT(
(std::is_arithmetic<PROCDATATYPE>::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<INDATATYPE, CONFDATATYPE> &;
using StepFuncReference = StepFunction<INDATATYPE, CONFDATATYPE> &;
private:
/// SignalStateInfo is a struct of SignalStateInformation that contains
/// information about the current signal state.
SignalStateInformation<CONFDATATYPE> 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<INDATATYPE, HistoryPolicy::FIFO> SampleHistory;
/// DAB is a (usually) small history of the last sample values of which a
/// average is calculated if the DAB is full.
DynamicLengthHistory<INDATATYPE, HistoryPolicy::SRWF> DAB;
/// DABHistory is a history in that the last DABs (to be exact, the averages
/// of the last DABs) are stored.
DynamicLengthHistory<PROCDATATYPE, HistoryPolicy::LIFO> DABHistory;
/// LowestConfidenceMatchingHistory is a history in that the lowest confidence
/// for the current sample matches all history samples are saved.
DynamicLengthHistory<INDATATYPE, HistoryPolicy::FIFO>
LowestConfidenceMatchingHistory;
/// HighestConfidenceMatchingHistory is a history in that the highest
/// confidence for the current sample matches all history samples are saved.
DynamicLengthHistory<INDATATYPE, HistoryPolicy::FIFO>
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
: //@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, SignalProperty},
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.StateIsValidAfterReentrance = false;
}
SignalStateInformation<CONFDATATYPE>
insertSample(INDATATYPE Sample) noexcept {
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance++;
validateSignalState(Sample);
SampleHistory.addEntry(Sample);
DAB.addEntry(Sample);
if (DAB.full()) {
PROCDATATYPE AvgOfDAB = DAB.template average<PROCDATATYPE>();
DABHistory.addEntry(AvgOfDAB);
DAB.clear();
}
FuzzyFunctionNumOfSamplesMatches.setRightLimit(
static_cast<INDATATYPE>(SampleHistory.numberOfEntries()));
FuzzyFunctionNumOfSamplesMismatches.setRightLimit(
static_cast<INDATATYPE>(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<PROCDATATYPE, HistoryPolicy::FIFO>
RelativeDistanceHistory(SampleHistory.maxLength());
// calculate distances to all history samples
for (auto &HistorySample : SampleHistory) {
PROCDATATYPE RelativeDistance =
relativeDistance<INDATATYPE, PROCDATATYPE>(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<CONFDATATYPE>(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<PROCDATATYPE, HistoryPolicy::FIFO>
RelativeDistanceHistory(SampleHistory.maxLength());
// calculate distances to all history samples
for (auto &HistorySample : SampleHistory) {
RelativeDistanceHistory.addEntry(
relativeDistance<INDATATYPE, PROCDATATYPE>(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<CONFDATATYPE>(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<CONFDATATYPE> 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<INDATATYPE, PROCDATATYPE>(
Sample, HistorySample)));
HighestConfidenceMismatching =
fuzzyOR(HighestConfidenceMismatching,
FuzzyFunctionSampleMismatches(
relativeDistance<INDATATYPE, PROCDATATYPE>(
Sample, HistorySample)));
}
LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching);
HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching);
LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry();
HighestConfidenceMismatching =
HighestConfidenceMismatchingHistory.highestEntry();
SignalStateInfo.ConfidenceStateIsValid =
fuzzyAND(LowestConfidenceMatching,
FuzzyFunctionNumOfSamplesMatches(static_cast<INDATATYPE>(
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
SignalStateInfo.ConfidenceStateIsInvalid =
fuzzyOR(HighestConfidenceMismatching,
FuzzyFunctionNumOfSamplesMismatches(static_cast<INDATATYPE>(
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
if (SignalStateInfo.ConfidenceStateIsValid >
SignalStateInfo.ConfidenceStateIsInvalid) {
if (SignalStateInfo.StateIsValid) {
SignalStateInfo.StateJustGotValid = false;
} else {
SignalStateInfo.StateJustGotValid = true;
}
SignalStateInfo.StateIsValid = true;
SignalStateInfo.StateIsValidAfterReentrance = true;
}
}
void checkSignalStability(void) {
if (DABHistory.numberOfEntries() >= 2) {
SignalStateInfo.ConfidenceStateIsStable = FuzzyFunctionSignalIsStable(
relativeDistance<INDATATYPE, PROCDATATYPE>(
DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0]));
SignalStateInfo.ConfidenceStateIsDrifting = FuzzyFunctionSignalIsDrifting(
relativeDistance<INDATATYPE, PROCDATATYPE>(
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.
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 (SignalStateInfo.ConfidenceStateIsStable >
SignalStateInfo.ConfidenceStateIsDrifting) {
SignalStateInfo.StateCondition = StateConditions::STABLE;
} else if (SignalStateInfo.ConfidenceStateIsStable <
SignalStateInfo.ConfidenceStateIsDrifting) {
SignalStateInfo.StateCondition = StateConditions::DRIFTING;
} else {
SignalStateInfo.StateCondition = StateConditions::UNKNOWN;
}
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SIGNALSTATE_HPP
diff --git a/include/rosa/agent/SystemState.hpp b/include/rosa/agent/SystemState.hpp
index 07841e0..34e52b7 100644
--- a/include/rosa/agent/SystemState.hpp
+++ b/include/rosa/agent/SystemState.hpp
@@ -1,272 +1,283 @@
//===-- 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 <vector>
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 <typename CONFDATATYPE>
struct SystemStateInformation : StateInformation<CONFDATATYPE> {
/// TODO: describe
CONFDATATYPE ConfidenceOfInputsMatchingState;
CONFDATATYPE ConfidenceOfInputsMismatchingState;
CONFDATATYPE ConfidenceOfOutputsMatchingState;
CONFDATATYPE ConfidenceOfOutputsMismatchingState;
CONFDATATYPE ConfidenceSystemIsFunctioning;
CONFDATATYPE ConfidenceSystemIsMalfunctioning;
CONFDATATYPE ConfidenceOfAllDecisions;
+
+public:
+ SystemStateInformation() {}
+
+ SystemStateInformation(unsigned int _SystemStateID,
+ StateConditions _StateCondition) {
+ this->StateID = _SystemStateID;
+ this->StateCondition = _StateCondition;
+ this->StateIsValid = false;
+ this->StateJustGotValid = false;
+ this->StateIsValidAfterReentrance = false;
+ this->ConfidenceOfInputsMatchingState = 0;
+ this->ConfidenceOfInputsMismatchingState = 0;
+ this->ConfidenceOfOutputsMatchingState = 0;
+ this->ConfidenceOfOutputsMismatchingState = 0;
+ this->ConfidenceSystemIsFunctioning = 0;
+ this->ConfidenceSystemIsMalfunctioning = 0;
+ this->ConfidenceOfAllDecisions = 0;
+ }
};
// todo: do we need PROCDATATYPE?
/// TODO TEXT
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE>
class SystemState : public State<INDATATYPE, CONFDATATYPE, PROCDATATYPE> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT(std::is_arithmetic<INDATATYPE>::value,
"input data type is not to arithmetic");
STATIC_ASSERT(std::is_arithmetic<CONFDATATYPE>::value,
"confidence abstraction type is not to arithmetic");
STATIC_ASSERT(std::is_arithmetic<PROCDATATYPE>::value,
"process data type is not to arithmetic");
private:
/// SignalStateInfo is a struct of SignalStateInformation that contains
/// information about the current signal state.
SystemStateInformation<CONFDATATYPE> SystemStateInfo;
std::vector<SignalStateInformation<CONFDATATYPE>> 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},
+ : SystemStateInfo(StateID, StateConditions::UNKNOWN),
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<CONFDATATYPE> insertSignalStateInformation(
const std::vector<SignalStateInformation<CONFDATATYPE>>
_SignalStateInfos) noexcept {
ASSERT(_SignalStateInfos.size() < NumberOfSignals);
bool AllSignalsAreValid = true;
bool AtLeastOneSignalJustGotValid = false;
bool AllSignalsAreValidAfterReentrance = true;
bool AtLeastOneSignalIsUnknown = false;
bool AllSignalsAreStable = true;
// TODO: change this
SystemStateInfo.ConfidenceOfInputsMatchingState = 1;
SystemStateInfo.ConfidenceOfInputsMismatchingState = 0;
SystemStateInfo.ConfidenceOfOutputsMatchingState = 1;
SystemStateInfo.ConfidenceOfOutputsMismatchingState = 0;
SystemStateInfo.ConfidenceStateIsValid = 1;
SystemStateInfo.ConfidenceStateIsInvalid = 0;
SystemStateInfo.ConfidenceStateIsStable = 1;
SystemStateInfo.ConfidenceStateIsDrifting = 0;
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::UNKNOWN)
AtLeastOneSignalIsUnknown = true;
if (SSI.StateCondition == StateConditions::DRIFTING)
AllSignalsAreStable = false;
if (SSI.SignalProperty == SignalProperties::INPUT) {
SystemStateInfo.ConfidenceOfInputsMatchingState =
fuzzyAND(SystemStateInfo.ConfidenceOfInputsMatchingState,
SSI.ConfidenceOfMatchingState);
SystemStateInfo.ConfidenceOfInputsMismatchingState =
fuzzyOR(SystemStateInfo.ConfidenceOfInputsMismatchingState,
SSI.ConfidenceOfMismatchingState);
} else {
SystemStateInfo.ConfidenceOfOutputsMatchingState =
fuzzyAND(SystemStateInfo.ConfidenceOfOutputsMatchingState,
SSI.ConfidenceOfMatchingState);
SystemStateInfo.ConfidenceOfOutputsMismatchingState =
fuzzyOR(SystemStateInfo.ConfidenceOfOutputsMismatchingState,
SSI.ConfidenceOfMismatchingState);
}
SystemStateInfo.ConfidenceStateIsValid = fuzzyAND(
SystemStateInfo.ConfidenceStateIsValid, SSI.ConfidenceStateIsValid);
SystemStateInfo.ConfidenceStateIsInvalid =
fuzzyOR(SystemStateInfo.ConfidenceStateIsInvalid,
SSI.ConfidenceStateIsInvalid);
SystemStateInfo.ConfidenceStateIsStable = fuzzyAND(
SystemStateInfo.ConfidenceStateIsStable, SSI.ConfidenceStateIsStable);
SystemStateInfo.ConfidenceStateIsDrifting =
fuzzyOR(SystemStateInfo.ConfidenceStateIsDrifting,
SSI.ConfidenceStateIsDrifting);
this->SignalStateInfos.at(counter) = SSI;
counter++;
}
SystemStateInfo.StateIsValid = AllSignalsAreValid;
SystemStateInfo.StateJustGotValid =
AllSignalsAreValid && AtLeastOneSignalJustGotValid;
SystemStateInfo.StateIsValidAfterReentrance =
AllSignalsAreValidAfterReentrance;
if (AtLeastOneSignalIsUnknown)
SystemStateInfo.StateCondition = StateConditions::UNKNOWN;
else if (AllSignalsAreStable)
SystemStateInfo.StateCondition = StateConditions::STABLE;
else
SystemStateInfo.StateCondition = StateConditions::DRIFTING;
return SystemStateInfo;
}
/// TODO: write description
// TODO (future): think about saving the state information in a history
SystemStateRelation compareSignalStateInformation(
const std::vector<SignalStateInformation<CONFDATATYPE>>
_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 <std::size_t size>
void insertSignalStateInformation(
const std::array<SystemStateInformation<CONFDATATYPE>, size>
&Data) noexcept {
ASSERT(size <= NumberOfSignals);
std::size_t counter = 0;
for (auto tmp : Data) {
Signals.at(counter) = tmp;
counter++;
}
}
/// TODO: write description
template <typename... Types>
std::enable_if_t<std::conjunction_v<std::is_same<
Types, SystemStateInformation<CONFDATATYPE>>...>,
void>
insertSignalStateInformation(Types... Data) {
// TODO (future): think about saving the state information in a history
insertSignalStateInfos(
std::array<SystemStateInformation<CONFDATATYPE>, sizeof...(Data)>(
{Data...}));
}
// returns true if they are identical
/// TODO: write description
template <std::size_t size>
bool compareSignalStateInformation(
const std::array<SystemStateInformation<CONFDATATYPE>, 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 <typename... Types>
std::enable_if_t<std::conjunction_v<std::is_same<
Types, SystemStateInformation<CONFDATATYPE>>...>,
bool>
compareSignalStateInformation(Types... Data) {
return compareSignalStateInfos(
std::array<SystemStateInformation<CONFDATATYPE>, sizeof...(Data)>(
{Data...}));
}
#endif
/// Gives information about the current signal state.
///
/// \return a struct SignalStateInformation that contains information about
/// the current signal state.
SystemStateInformation<CONFDATATYPE> systemStateInformation(void) noexcept {
return SystemStateInfo;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SYSTEMSTATE_HPP

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 3, 12:38 AM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157160
Default Alt Text
(57 KB)

Event Timeline