Page MenuHomePhorge

No OneTemporary

Size
67 KB
Referenced Files
None
Subscribers
None
diff --git a/apps/ccam/statehandlerutils.h b/apps/ccam/statehandlerutils.h
index 9bf7ee4..fb7b640 100644
--- a/apps/ccam/statehandlerutils.h
+++ b/apps/ccam/statehandlerutils.h
@@ -1,184 +1,184 @@
#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,
- (StateInfo.StateIsValid ? 4 : 0) +
- (StateInfo.StateJustGotValid ? 2 : 0) +
- (StateInfo.StateIsValidAfterReentrance ? 1 : 0)};
+ (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>;
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: state-detector durschleifen
template <typename ret, typename A> struct function {
ret operator()(A a) {
// std::vector<SystemStateInformation> out;
for (auto tmp1 : a) {
// convert tuple to info struct out.push_back({});
(void)tmp1;
LOG_INFO_STREAM << "new SignalStateTuple!\n";
}
// feed state detector
// return result
return ret();
}
};
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>(
std::numeric_limits<uint32_t>::max(), NumOfSlaves, BrokenDelayFunction,
OkDelayFunction));
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/examples/CSVFiles/main.cpp b/examples/CSVFiles/main.cpp
index 20df4cf..56ac98e 100644
--- a/examples/CSVFiles/main.cpp
+++ b/examples/CSVFiles/main.cpp
@@ -1,373 +1,373 @@
//===-- examples/CSVFiles/main.cpp ------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/basic-system/basic-system.cpp
///
/// \author Edwin Willegger (edwin.willegger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief A simple example on the basic \c rosa::csv, \c rosa::iterator and
/// \c rosa::writer classes. Focus is on the tuple impementations.
///
//===----------------------------------------------------------------------===//
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <istream>
#include <map>
#include <ostream>
#include <sstream>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <vector>
//#include <unistd.h>
// includes for an complete example to read and write
// with sensors and agents.
#include "rosa/deluxe/DeluxeContext.hpp"
#include "rosa/config/version.h"
// includes to test the basic functionality
// to read and write tuples.
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include "rosa/support/iterator/split_tuple_iterator.hpp"
#include "rosa/support/writer/split_tuple_writer.hpp"
/// the name of the example
const std::string ExampleName = "csvfiles";
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 10;
/// Paths for the CSV files for simulation.
/// input csv files
const std::string csvPath = "../examples/CSVFiles/";
const std::string csvFileWithHeader = csvPath + "HR-New.csv";
const std::string csvFileNoHeader = csvPath + "HR.csv";
const std::string csvFileHeaderSemi = csvPath + "HR-New-Semicolon.csv";
/// output csv files
const std::string csvFileWriteHea = csvPath + "csvwriter_noheader.csv";
const std::string csvFileWriteNoHeaSplit =
csvPath + "csvSplitwriter_noheader.csv";
using namespace rosa;
///
/// This function tests the basic CSVIterator capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVReader(void) {
// different streams to get the csv data out of the files
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data(csvFileWithHeader);
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_2(csvFileWithHeader);
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_3(csvFileWithHeader);
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_4(csvFileWithHeader);
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_5(csvFileWithHeader);
// file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_6(csvFileWithHeader);
// file contains no header an valid data entries, delimter = ','
std::ifstream file2(csvFileNoHeader);
// file contains header and valid data entries, delimter = ';'
std::ifstream file3(csvFileHeaderSemi);
csv::CSVIterator<int, std::string, std::string, int, int> it(
file_header_data);
- it.setDelimeter(',');
+ it.setDelimiter(',');
it++;
it++;
// if you iterate over the end of file, the last values
// of the file will remain in the data structure but no
// error occurs.
it++;
it++;
//-------------------------------------------------------------------
// a possiblity to get the data out of the iterator
std::tuple<int, std::string, std::string, int, int> value = *it;
//
// Show the value of one iterator
//
LOG_INFO("Values are: ");
LOG_INFO(std::get<0>(value));
LOG_INFO(std::get<1>(value));
//--------------------------------------------------------------------
// testing differnet parameters to the constructor
// uncomment to see that it is not possible to iterate over an vector in the
// tuple.
// rosa::csv::CSVIterator<double, std::vector<int>> it2(file, 1);
// try to skip a valid number of lines after the header
csv::CSVIterator<double, float, int, int, float> it2_0(file_header_data_2, 1);
// try to skip a valid number of lines after the header, but you assume that
// the file has no header
// uncomment this line to crash the programm
// csv::CSVIterator<double, float, int, int, float> it2_1(file_header_data_3,
// 0, csv::HeaderInformation::HasNoHeader);
// try to skip a valid number of lines after the header, but you assume that
// the file has no header
// uncomment this line to crash the program
// csv::CSVIterator<double, float, int, int, float> it2_2(file_header_data_4,
// 1, csv::HeaderInformation::HasNoHeader);
// try to skip a valid number of lines of a file without header
csv::CSVIterator<double, float, int, int, float> it2_3(
file2, 1, csv::HeaderInformation::HasNoHeader);
// try to skip a valid number of lines after the header, but with different
// delimeter
csv::CSVIterator<double, float, int, int, float> it2_4(
file3, 2, csv::HeaderInformation::HasHeader, ';');
// if you skip more lines than valid, you generate an infinte loop
// csv::CSVIterator<double, float, int, int, float> it3(file_header_data_5,
// 500);
// if you don't need data from all columns just select the number of columns
// you
// need. You get the data back from the first column (index 0) to the fourth
// column
// all values from the fifth column are ignored.
csv::CSVIterator<double, float, int, float> it4(file_header_data_6);
}
///
/// This function tests the basic CSVTupleWriter capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVWriter(void) {
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteHea);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
//
// Create test tuples
//
std::tuple<int, float, std::string> values(5, 8.3f, "hallo");
std::tuple<int, float, std::string> values2(3, 8.3f, "end");
//
// Create test header lines for the test tuples
//
std::array<std::string, 3> header{"zero column", "first column",
"second column"};
std::array<std::string, 4> headerWrong{"zero column", "first column",
"second column", "third column"};
std::array<std::string, 2> headerWrongShort{"zero column", "first column"};
// if you uncomment this line than it would be possible for you to write the
// header into the stream
// in the next line.
// wri.write(values);
wri.writeHeader(header);
wri.write(values);
wri.write(values);
// it is not possible to write an additional header into the stream.
wri.writeHeader(header);
wri.write(values);
wri << values;
wri << values2;
// uncomment this line to see, that you can't write a header with the too many
// elements.
// wri.writeHeader(headerWrong);
// uncomment this line to see, that you can't write a header with the too few
// elements.
// wri.writeHeader(headerWrongShort);
}
///
/// This function tests the basic splitTupleIterator capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVIterator in separate parts.
///
void testsplitTupleIterator(void) {
//
// Create deluxe context
//
std::unique_ptr<rosa::deluxe::DeluxeContext> C =
deluxe::DeluxeContext::create(ExampleName);
//
// Create deluxe sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
// Three different sensors were created, this is just a random number taken.
AgentHandle Elem0Sensor = C->createSensor<int>("Element1 Sensor");
AgentHandle Elem1Sensor = C->createSensor<float>("Element2 Sensor");
AgentHandle Elem2Sensor = C->createSensor<std::string>("Element3 Sensor");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
// Type aliases for iterators
using Iterator = rosa::csv::CSVIterator<int, float, std::string>;
using IteratorValue = std::tuple<int, float, std::string>;
static_assert(
std::is_same<typename Iterator::value_type, IteratorValue>::value,
"Iterator must provide tuples");
//
// Open CSV file and register the columns to the corresponding sensors.
//
std::ifstream TestCSV(csvFileWithHeader);
//
// Test data looks like:
// Element1, Element2, Element3, Element4, Element5 -- is the header line
// 3, 5, 8, 9.5, 17 -- first line of values
// 100, -8, 30, 18.8, 29 -- other line of values
// were also in the file
// 5, 20, -100, -200.1, -30 -- if you have less number
// of values than simulation rounds all values
// -- beyond your last value
// will be zero.
// get element iterator ranges
auto[Elem0Range, Elem1Range, Elem2Range] =
iterator::splitTupleIterator(Iterator(TestCSV), Iterator());
// dissect a range into begin and end iterators by structred bindings
auto[Elem0Begin, Elem0End] = Elem0Range;
// deissect a range with functions
auto Elem1Begin = iterator::begin(Elem1Range);
auto Elem1End = iterator::end(Elem1Range);
C->registerSensorValues(Elem0Sensor, std::move(Elem0Begin), Elem0End);
C->registerSensorValues(Elem1Sensor, std::move(Elem1Begin), Elem1End);
C->registerSensorValues(Elem2Sensor, std::move(iterator::begin(Elem2Range)),
iterator::end(Elem2Range));
//
// Simulate.
//
C->simulate(NumberOfSimulationCycles);
}
///
/// This function tests the basic splitTupleWriter capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVWriter in separate parts.
///
// NOTE (Maxi): I had to add an "f" to some numbers to declare them as float,
// otherwise: "C:\Users\maxgot\Source\SoC_RoSA\examples\CSVFiles\main.cpp:314:
// warning: C4305: 'argument': truncation from 'double' to 'const float'"
void testsplitTupleWriter(void) {
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteNoHeaSplit);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
// if you omit, the type definition in the template, than auto generated types
// were used,
// and they may not fit to the used CSVTupleWriter.
wri << std::make_tuple<int, float, std::string>(1000, 50.6f, "tuple_created");
auto[T0Writer, T1Writer, T2Writer] = writer::splitTupleWriter(
std::move(wri), writer::IncompleteTuplePolicy::Ignore);
// writing elements in sequential order into the writer classes, but you can
// write the values into the writers in
// a random order.
T0Writer << (500);
T1Writer << (3.0);
T2Writer << "splitted writter";
T2Writer << "splitting is cool";
T0Writer << (-30);
T1Writer << (-0.004f);
// you can also write more often values into a writer and later into the other
// writers
// all data will be processed correctly into the right order.
T0Writer << (1);
T0Writer << (2);
T1Writer << (-0.4f);
T0Writer << (3);
T2Writer << "again";
T0Writer << (4);
T1Writer << (-0.1f);
T1Writer << (-0.2f);
T2Writer << "and";
T1Writer << (-0.3f);
T2Writer << "splitting";
T2Writer << "once again";
// again writing data of one tuple entry to the different writers in a random
// fashion.
T1Writer << (-0.004f);
T2Writer << "splitting is cool";
T0Writer << (-30);
}
int main(void) {
LOG_INFO_STREAM << library_string() << " -- " << terminal::Color::Red
<< ExampleName << " example" << terminal::Color::Default
<< '\n';
//
// Testing CSVWriter.
//
LOG_INFO("Testing CSVWriter CSVTupleItrator implementation: ");
testtupleCSVWriter();
//
// Testing CSVReader.
//
LOG_INFO("Testing CSVReader CSVTupleIterator implementation: ");
testtupleCSVReader();
//
// Testing SplitTupleIterator.
//
LOG_INFO("Testing SplitTupleIterator: ");
testsplitTupleIterator();
//
// Testing SplitTupleWriter.
//
LOG_INFO("Testing SplitTupleWriter: ");
testsplitTupleWriter();
//
// info that user knows programm has finished.
//
LOG_INFO("All tests finished.");
return 0;
}
diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp
index a4b3cd8..0330201 100644
--- a/include/rosa/agent/SignalState.hpp
+++ b/include/rosa/agent/SignalState.hpp
@@ -1,469 +1,476 @@
//===-- 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;
};
/// \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,
StateConditions::UNKNOWN,
false,
false,
false,
0,
0,
0,
0,
0,
0,
SignalProperty,
0},
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/State.hpp b/include/rosa/agent/State.hpp
index 1e19ef5..d3568a3 100644
--- a/include/rosa/agent/State.hpp
+++ b/include/rosa/agent/State.hpp
@@ -1,90 +1,87 @@
//===-- 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/Functionality.h"
//#include "rosa/agent/FunctionAbstractions.hpp"
//#include "rosa/agent/History.hpp"
#include "rosa/support/debug.hpp"
#include <stdint.h>
//#include <vector>
namespace rosa {
namespace agent {
/// State conditions defining how the condition of a \c rosa::agent::State is
/// saved in \c rosa::agent::StateInformation.
enum StateConditions : uint8_t {
UNKNOWN = 0, ///< The state is unknown
STABLE = 1, ///< The state is stable
DRIFTING = 2, ///< The state is drifting
MALFUNCTIONING = 3 ///< Malfunction
};
template <typename CONFDATATYPE> struct StateInformation {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<CONFDATATYPE>::value),
"confidence type is not to arithmetic");
/// The StateID stores the ID of the state.
unsigned int StateID;
/// The StateCondition shows the condition of a state (stable, drifting, or
/// unknown)
StateConditions StateCondition;
/// The StateIsValid 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 StateIsValid;
/// The StateJustGotValid shows whether a state got valid (toggled from
/// invalid to valid) during the current inserted sample.
bool StateJustGotValid;
/// The StateIsValidAfterReentrance shows whether a state is valid after the
/// variable changed back to it again.
bool StateIsValidAfterReentrance;
/// TODO: describe
- CONFDATATYPE ConfidenceOfMatchingState;
- CONFDATATYPE ConfidenceOfMismatchingState;
-
CONFDATATYPE ConfidenceStateIsValid;
CONFDATATYPE ConfidenceStateIsInvalid;
CONFDATATYPE ConfidenceStateIsStable;
CONFDATATYPE ConfidenceStateIsDrifting;
};
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE>
class State : 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 abstraction type is not to arithmetic");
STATIC_ASSERT((std::is_arithmetic<PROCDATATYPE>::value),
"process type is not to arithmetic");
protected:
};
} // 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 9179139..07841e0 100644
--- a/include/rosa/agent/SystemState.hpp
+++ b/include/rosa/agent/SystemState.hpp
@@ -1,252 +1,272 @@
//===-- 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 ConfidenceStateIsFunctioning;
- CONFDATATYPE ConfidenceStateIsMalfunctioning;
+ CONFDATATYPE ConfidenceOfInputsMatchingState;
+ CONFDATATYPE ConfidenceOfInputsMismatchingState;
+ CONFDATATYPE ConfidenceOfOutputsMatchingState;
+ CONFDATATYPE ConfidenceOfOutputsMismatchingState;
+ CONFDATATYPE ConfidenceSystemIsFunctioning;
+ CONFDATATYPE ConfidenceSystemIsMalfunctioning;
CONFDATATYPE ConfidenceOfAllDecisions;
};
// 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},
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;
- CONFDATATYPE CombinedConfidenceOfMatchingState =
- _SignalStateInfos.front().ConfidenceOfMatchingState;
- CONFDATATYPE CombinedConfidenceOfMismatchingState =
- _SignalStateInfos.front().ConfidenceOfMismatchingState;
- CONFDATATYPE CombinedConfidenceStateIsValid =
- _SignalStateInfos.front().ConfidenceStateIsValid;
- CONFDATATYPE CombinedConfidenceStateIsInvalid =
- _SignalStateInfos.front().ConfidenceStateIsInvalid;
- CONFDATATYPE CombinedConfidenceStateIsStable =
- _SignalStateInfos.front().ConfidenceStateIsStable;
- CONFDATATYPE CombinedConfidenceStateIsDrifting =
- _SignalStateInfos.front().ConfidenceStateIsDrifting;
+ // 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;
- //@benedikt: instead of the initializing above and the and/or with itself,
- // I could make here an if (counter == 0)
- CombinedConfidenceOfMatchingState = fuzzyAND(
- CombinedConfidenceOfMatchingState, SSI.ConfidenceOfMatchingState);
- CombinedConfidenceOfMismatchingState =
- fuzzyOR(CombinedConfidenceOfMismatchingState,
- SSI.ConfidenceOfMismatchingState);
- CombinedConfidenceStateIsValid =
- fuzzyAND(CombinedConfidenceStateIsValid, SSI.ConfidenceStateIsValid);
- CombinedConfidenceStateIsInvalid = fuzzyOR(
- CombinedConfidenceStateIsInvalid, SSI.ConfidenceStateIsInvalid);
- CombinedConfidenceStateIsStable = fuzzyAND(
- CombinedConfidenceStateIsStable, SSI.ConfidenceStateIsStable);
- CombinedConfidenceStateIsDrifting = fuzzyOR(
- CombinedConfidenceStateIsDrifting, SSI.ConfidenceStateIsDrifting);
+ 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
diff --git a/include/rosa/agent/SystemStateDetector.hpp b/include/rosa/agent/SystemStateDetector.hpp
index bcff7b4..14139fd 100644
--- a/include/rosa/agent/SystemStateDetector.hpp
+++ b/include/rosa/agent/SystemStateDetector.hpp
@@ -1,222 +1,235 @@
//===-- rosa/agent/SystemStateDetector.hpp ----------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/SystemStateDetector.hpp
///
/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *system state detector* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP
#define ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/agent/SignalState.hpp"
#include "rosa/agent/StateDetector.hpp"
#include "rosa/agent/SystemState.hpp"
#include "rosa/support/debug.hpp"
namespace rosa {
namespace agent {
-/*
-/// System state conditions defining how the condition of a \c
-/// rosa::agent::SystemState is saved in \c rosa::agent::SystemStateInformation.
-// TODO: think about shifting this in SystemStateDetector and make a
-// StateCondition with only stable, drifting, unknown
-enum class SystemStateCondition : uint8_t {
- STABLE = 0, ///< The system state is stable
- DRIFTING = 1, ///< The system state is drifting
- MALFUNCTIONING = 2, ///< The system state is malfunctioning
- UNKNOWN = 3 ///< The system state is unknown
-};
-*/
-
/// TODO: write description
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE,
HistoryPolicy HP>
class SystemStateDetector
: public StateDetector<INDATATYPE, CONFDATATYPE, PROCDATATYPE, HP> {
using StateDetector =
StateDetector<INDATATYPE, CONFDATATYPE, PROCDATATYPE, HP>;
using PartFuncPointer = typename StateDetector::PartFuncPointer;
private:
// For the convinience to write a shorter data type name
using SystemStatePtr =
std::shared_ptr<SystemState<INDATATYPE, CONFDATATYPE, PROCDATATYPE>>;
/// TODO: description
uint32_t NumberOfSignals;
/// The CurrentSystemState is a pointer to the (saved) system state in which
/// the actual state of the observed system is.
SystemStatePtr CurrentSystemState;
/// The DetectedSystemStates is a history in that all detected system states
/// are saved.
DynamicLengthHistory<SystemStatePtr, HP> DetectedSystemStates;
/// TODO: description
unsigned int TimeOfDisparity;
- /// The FuzzyFunctionDelayTimeToGetBroken is the fuzzy function that gives
- /// the confidence whether the system is Broken because of an input change
- /// without an output change or vice versa. A small time gap between the two
- /// shall be allowed.
- PartFuncPointer FuzzyFunctionDelayTimeToGetBroken;
-
/// The FuzzyFunctionDelayTimeToBeWorking is the fuzzy function that gives
/// the
/// confidence whether the system is still OK allthough an input change
/// without an output change or vice versa.
- PartFuncPointer FuzzyFunctionDelayTimeToBeWorking;
+ PartFuncPointer FuzzyFunctionTimeSystemFunctioning;
+
+ /// The FuzzyFunctionDelayTimeToGetBroken is the fuzzy function that gives
+ /// the confidence whether the system is Broken because of an input change
+ /// without an output change or vice versa. A small time gap between the two
+ /// shall be allowed.
+ PartFuncPointer FuzzyFunctionTimeSystemMalfunctioning;
public:
// todo zwei parameter für variablen anzahl
/// TODO: write description
SystemStateDetector(
uint32_t MaximumNumberOfSystemStates, uint32_t NumberOfSignals,
- PartFuncPointer FuzzyFunctionDelayTimeToGetBroken,
- PartFuncPointer FuzzyFunctionDelayTimeToBeWorking) noexcept
+ PartFuncPointer FuzzyFunctionTimeSystemMalfunctioning,
+ PartFuncPointer FuzzyFunctionTimeSystemFunctioning) noexcept
: NumberOfSignals(NumberOfSignals), CurrentSystemState(nullptr),
DetectedSystemStates(MaximumNumberOfSystemStates), TimeOfDisparity(0),
- FuzzyFunctionDelayTimeToGetBroken(FuzzyFunctionDelayTimeToGetBroken),
- FuzzyFunctionDelayTimeToBeWorking(FuzzyFunctionDelayTimeToBeWorking) {
+ FuzzyFunctionTimeSystemMalfunctioning(
+ FuzzyFunctionTimeSystemMalfunctioning),
+ FuzzyFunctionTimeSystemFunctioning(FuzzyFunctionTimeSystemFunctioning) {
//@Benedikt: if I write "NextStateID(1), StateHasChanged(false)" before the
//{}-brackets, the compiler tells me: "SystemStateDetector.hpp:72:9: error:
// member initializer 'NextStateID'/'StateHasChanged' does not name a
// non-static data member or base class"
this->NextStateID = 1;
this->StateHasChanged = false;
}
/// Destroys \p this object.
~SystemStateDetector(void) = default;
/// TODO: write description
SystemStateInformation<CONFDATATYPE>
detectSystemState(std::vector<SignalStateInformation<CONFDATATYPE>>
SignalStateInfos) noexcept {
SystemStateInformation<CONFDATATYPE> SystemStateInfo;
if (!CurrentSystemState) {
ASSERT(DetectedSystemStates.empty());
SystemStatePtr S = createNewSystemState();
CurrentSystemState = S;
SystemStateInfo =
CurrentSystemState->insertSignalStateInformation(SignalStateInfos);
} else {
SystemStateRelation SysStateRel =
CurrentSystemState->compareSignalStateInformation(SignalStateInfos);
if (SysStateRel == SystemStateRelation::STATEISMATCHING) {
TimeOfDisparity = 0;
SystemStateInfo =
CurrentSystemState->insertSignalStateInformation(SignalStateInfos);
} else { // ONLYINPUTISMATCHING, ONLYOUTPUTISMATCHING, STATEISMISMATCHING
if (!CurrentSystemState->systemStateInformation().StateIsValid)
DetectedSystemStates.deleteEntry(CurrentSystemState);
CurrentSystemState = nullptr;
SystemStatePtr potentialSystemState = nullptr;
// search all saved system states
for (auto &SavedSystemState : DetectedSystemStates) {
SysStateRel =
SavedSystemState->compareSignalStateInformation(SignalStateInfos);
if (SysStateRel == SystemStateRelation::STATEISMATCHING) {
CurrentSystemState = SavedSystemState;
break;
} else if (SysStateRel == SystemStateRelation::ONLYINPUTISMATCHING ||
SysStateRel == SystemStateRelation::ONLYOUTPUTISMATCHING) {
+ // TODO: choose best matching
potentialSystemState = SavedSystemState;
}
}
// actions depending whether state is matchin fully or only half
if (CurrentSystemState) {
TimeOfDisparity = 0;
SystemStateInfo = CurrentSystemState->insertSignalStateInformation(
SignalStateInfos);
} else if (potentialSystemState) {
TimeOfDisparity++;
CurrentSystemState = potentialSystemState;
SystemStateInfo = CurrentSystemState->systemStateInformation();
} else {
SystemStatePtr S = createNewSystemState();
TimeOfDisparity = 0;
CurrentSystemState = S;
SystemStateInfo = CurrentSystemState->insertSignalStateInformation(
SignalStateInfos);
}
}
}
// TODO: is this right? if i don't insert if broke, it will never be valid?!
// right?
- if (!SystemStateInfo.StateIsValid ||
- !SystemStateInfo.StateIsValidAfterReentrance) {
+ if (!SystemStateInfo.StateIsValidAfterReentrance) {
TimeOfDisparity = 0;
}
// TODO: maybe make reference instead of pointer
- CONFDATATYPE ConfidenceSystemIsMalfunctioning =
- FuzzyFunctionDelayTimeToGetBroken->operator()(
+ SystemStateInfo.ConfidenceSystemIsFunctioning =
+ (*FuzzyFunctionTimeSystemFunctioning)(
static_cast<INDATATYPE>(TimeOfDisparity));
- CONFDATATYPE ConfidenceSystemIsFunctioning =
- FuzzyFunctionDelayTimeToBeWorking->operator()(
+ SystemStateInfo.ConfidenceSystemIsMalfunctioning =
+ (*FuzzyFunctionTimeSystemMalfunctioning)(
static_cast<INDATATYPE>(TimeOfDisparity));
- if (ConfidenceSystemIsMalfunctioning > ConfidenceSystemIsFunctioning)
+ if (SystemStateInfo.ConfidenceSystemIsMalfunctioning >
+ SystemStateInfo.ConfidenceSystemIsFunctioning)
SystemStateInfo.StateCondition = StateConditions::MALFUNCTIONING;
- // TODO: calculate overall confidence
+ if (SystemStateInfo.StateCondition == StateConditions::UNKNOWN)
+ // TODO: think about a Confidence calculation when system state is unkown
+ SystemStateInfo.ConfidenceOfAllDecisions = 0;
+ else if (SystemStateInfo.StateCondition == StateConditions::STABLE)
+ SystemStateInfo.ConfidenceOfAllDecisions = fuzzyAND(
+ fuzzyOR(
+ fuzzyAND(SystemStateInfo.ConfidenceOfInputsMatchingState,
+ SystemStateInfo.ConfidenceOfOutputsMatchingState),
+ fuzzyAND(SystemStateInfo.ConfidenceOfInputsMismatchingState,
+ SystemStateInfo.ConfidenceOfOutputsMismatchingState)),
+ SystemStateInfo.ConfidenceSystemIsFunctioning,
+ SystemStateInfo.ConfidenceStateIsStable,
+ SystemStateInfo.ConfidenceStateIsValid);
+ else if (SystemStateInfo.StateCondition == StateConditions::DRIFTING)
+ SystemStateInfo.ConfidenceOfAllDecisions =
+ fuzzyAND(SystemStateInfo.ConfidenceOfInputsMatchingState,
+ SystemStateInfo.ConfidenceOfOutputsMatchingState,
+ SystemStateInfo.ConfidenceStateIsDrifting,
+ SystemStateInfo.ConfidenceStateIsValid);
+ else if (SystemStateInfo.StateCondition == StateConditions::MALFUNCTIONING)
+ SystemStateInfo.ConfidenceOfAllDecisions =
+ fuzzyAND(SystemStateInfo.ConfidenceOfInputsMismatchingState,
+ SystemStateInfo.ConfidenceOfOutputsMismatchingState,
+ SystemStateInfo.ConfidenceSystemIsMalfunctioning,
+ SystemStateInfo.ConfidenceStateIsValid);
if (SystemStateInfo.StateJustGotValid) {
this->NextStateID++;
}
return SystemStateInfo;
}
private:
/// Creates a new system state and adds it to the system state vector in
/// which
/// all known states are saved.
///
/// \return a pointer to the newly created signal state or NULL if no state
/// could be created.
SystemStatePtr createNewSystemState(void) noexcept {
SystemStatePtr S(new SystemState<INDATATYPE, CONFDATATYPE, PROCDATATYPE>(
this->NextStateID, this->NumberOfSignals));
DetectedSystemStates.addEntry(S);
return S;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP

File Metadata

Mime Type
text/x-diff
Expires
Sun, May 31, 5:05 PM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
330956
Default Alt Text
(67 KB)

Event Timeline