Page MenuHomePhorge

No OneTemporary

Size
47 KB
Referenced Files
None
Subscribers
None
diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp
index 7f8d206..7557729 100644
--- a/include/rosa/agent/SignalState.hpp
+++ b/include/rosa/agent/SignalState.hpp
@@ -1,462 +1,528 @@
//===-- 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/support/math.hpp"
namespace rosa {
namespace agent {
/// Signal state conditions defining how the condition of a \c
/// rosa::agent::SignalState is saved in \c rosa::agent::SignalStateInformation.
enum SignalStateCondition : uint8_t {
STABLE = 0, ///< The signal state is stable
DRIFTING = 1, ///< The signal state is drifting
UNKNOWN = 2 ///< The signal state is unknown
};
/// TODO: write description
template <typename CONFDATATYPE> struct SignalStateInformation {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<CONFDATATYPE>::value),
"confidence type is not to arithmetic");
/// The signal state ID saved as an uint32_teger number
uint32_t SignalStateID;
/// The SignalStateConfidence shows the overall confidence value of the signal
/// state.
CONFDATATYPE SignalStateConfidence;
/// The SignalStateCondition shows the condition of a signal state (stable,
/// drifting, or unknown)
SignalStateCondition SignalStateCondition;
/// The SignalStateIsValid saves the number of samples which have been
/// inserted into the state after entering it.
uint32_t NumberOfInsertedSamplesAfterEntrance;
/// The SignalStateIsValid shows whether a signal state is valid or invalid.
/// In this context, valid means that enough samples which are in close
/// proximitry have been inserted into the signal state.
bool SignalStateIsValid;
/// The SignalStateJustGotValid shows whether a signal state got valid
/// (toggled from invalid to valid) during the current inserted sample.
bool SignalStateJustGotValid;
/// The SignalStateIsValidAfterReentrance shows whether a signal state is
/// valid after the variable changed back to it again.
bool SignalStateIsValidAfterReentrance;
/// The SignalIsStableNotDrifting shows whether a signal is stable and not
/// drifting.
bool SignalIsStable;
};
/// \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");
private:
// For the convinience to write a shorter data type name
using PartFuncPointer =
std::shared_ptr<PartialFunction<INDATATYPE, CONFDATATYPE>>;
using StepFuncPointer =
std::shared_ptr<StepFunction<INDATATYPE, CONFDATATYPE>>;
/// SignalStateInfo is a struct SignalStateInformation that contains
/// information about the current 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.
PartFuncPointer FuzzyFunctionSampleMatches;
/// The FuzzyFunctionSampleMismatches is the fuzzy function that gives the
/// confidence how bad the new sample matches another sample in the sample
/// history.
PartFuncPointer FuzzyFunctionSampleMismatches;
/// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the
/// confidence how many samples from the sampe history match the new sample.
StepFuncPointer FuzzyFunctionNumOfSamplesMatches;
/// The FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives
/// the confidence how many samples from the sampe history mismatch the new
/// sample.
StepFuncPointer FuzzyFunctionNumOfSamplesMismatches;
/// The FuzzyFunctionSignalIsDrifting is the fuzzy function that gives the
/// confidence how likely it is that the signal (resp. the state of a signal)
/// is drifting.
PartFuncPointer 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).
PartFuncPointer 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;
public:
// @Maxi doxygen per default doesn't display private attributes of a class. So
// I copied them to the constructor. So the user has more information.
/// 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, uint32_t SampleHistorySize,
uint32_t DABSize, uint32_t DABHistorySize,
PartFuncPointer FuzzyFunctionSampleMatches,
PartFuncPointer FuzzyFunctionSampleMismatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMismatches,
PartFuncPointer FuzzyFunctionSignalIsDrifting,
PartFuncPointer FuzzyFunctionSignalIsStable) noexcept
: SignalStateInfo{SignalStateID, 0, SignalStateCondition::UNKNOWN, 0,
false, false,
false, //@maxi added the Signal is stable bool
true},
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.SignalStateIsValidAfterReentrance = false;
}
SignalStateInformation<CONFDATATYPE>
insertSample(INDATATYPE Sample) noexcept {
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();
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.
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
//@David: because we are using these operator functions, here I have to
// direference in a not (in my opionin) not so beautiful way
//("(*FuzzyFunctionSampleMatches)"), or I have to write
//"FuzzyFunctionSampleMatches->operator()(...)". Can we just write
// functions like "->getBlabla()" or something like that?
ConfidenceFromRelativeDistance = 0;
} else {
ConfidenceFromRelativeDistance =
(*FuzzyFunctionSampleMatches)(RelativeDistanceHistory[Case]);
}
+#if false
+ //@maxi why the 2?
+ ConfidenceOfWorstFittingSample =
+ fuzzyAND((CONFDATATYPE)2, ConfidenceOfWorstFittingSample,
+ ConfidenceFromRelativeDistance);
+
+ //@maxi you could also use it like this then you can define the type and the size
+ ConfidenceOfWorstFittingSample =
+ fuzzyAND<CONFDATATYPE,2>({ConfidenceOfWorstFittingSample,
+ ConfidenceFromRelativeDistance});
+#else
+ //@maxi is this what you wanted? you don't need to define the data type
+ // nor the size
+ ConfidenceOfWorstFittingSample = fuzzyAND(ConfidenceOfWorstFittingSample,
+ ConfidenceFromRelativeDistance);
+#endif
- ConfidenceOfWorstFittingSample = fuzzyAND<CONFDATATYPE>(
- 2, ConfidenceOfWorstFittingSample, ConfidenceFromRelativeDistance);
//@benedikt: same as before with "->operator()"
+ //@maxi the same as before
+#if false
ConfidenceOfBestCase = fuzzyOR<CONFDATATYPE>(
2, ConfidenceOfBestCase,
fuzzyAND<CONFDATATYPE>(2, ConfidenceOfWorstFittingSample,
FuzzyFunctionNumOfSamplesMatches->operator()(
static_cast<CONFDATATYPE>(Case) + 1)));
+#else
+ ConfidenceOfBestCase =
+ fuzzyOR(ConfidenceOfBestCase,
+ fuzzyAND(ConfidenceOfWorstFittingSample,
+ FuzzyFunctionNumOfSamplesMatches->operator()(
+ static_cast<CONFDATATYPE>(Case) + 1)));
+
+#endif
}
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;
// 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.
// TODO (future): to accelerate -> don't go until end. Confidences will only
// get higher. See comment in "CONFDATATYPE
// confidenceSampleMatchesSignalState(INDATATYPE Sample)".
for (uint32_t Case = 0; Case < RelativeDistanceHistory.numberOfEntries();
Case++) {
CONFDATATYPE ConfidenceFromRelativeDistance;
if (std::isinf(RelativeDistanceHistory[Case])) {
ConfidenceFromRelativeDistance = 1;
} else {
//@benedikt: I had to change the following line. The outcommented line
// was the original one. I think it is ugly like that (new line). Do you
// have an idea how to make it better/more beautiful?
ConfidenceFromRelativeDistance =
FuzzyFunctionSampleMismatches->operator()(
RelativeDistanceHistory[Case]);
}
+//@maxi you don't have to define the data type or the amount
+#if false
ConfidenceOfBestFittingSample = fuzzyOR<CONFDATATYPE>(
2, ConfidenceOfBestFittingSample, ConfidenceFromRelativeDistance);
//@benedikt: same as before with "->operator()"
ConfidenceOfWorstCase = fuzzyAND<CONFDATATYPE>(
2, ConfidenceOfWorstCase,
fuzzyOR<CONFDATATYPE>(2, ConfidenceOfBestFittingSample,
FuzzyFunctionNumOfSamplesMismatches->operator()(
static_cast<CONFDATATYPE>(Case) + 1)));
+#else
+ ConfidenceOfBestFittingSample = fuzzyOR(ConfidenceOfBestFittingSample,
+ ConfidenceFromRelativeDistance);
+
+ //@benedikt: same as before with "->operator()"
+ ConfidenceOfWorstCase =
+ fuzzyAND(ConfidenceOfWorstCase,
+ fuzzyOR(ConfidenceOfBestFittingSample,
+ FuzzyFunctionNumOfSamplesMismatches->operator()(
+ static_cast<CONFDATATYPE>(Case) + 1)));
+#endif
}
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.
//@benedikt: same with "->operator()"
+ //@maxi you don't have to deine the data type nor the amount
+#if false
LowestConfidenceMatching =
fuzzyAND<CONFDATATYPE>(2, LowestConfidenceMatching,
FuzzyFunctionSampleMatches->operator()(
relativeDistance<INDATATYPE, PROCDATATYPE>(
Sample, HistorySample)));
//@benedikt: same with "->operator()"
HighestConfidenceMismatching =
fuzzyOR<CONFDATATYPE>(2, HighestConfidenceMismatching,
FuzzyFunctionSampleMismatches->operator()(
relativeDistance<INDATATYPE, PROCDATATYPE>(
Sample, HistorySample)));
+#else
+ LowestConfidenceMatching =
+ fuzzyAND(LowestConfidenceMatching,
+ FuzzyFunctionSampleMatches->operator()(
+ relativeDistance<INDATATYPE, PROCDATATYPE>(
+ Sample, HistorySample)));
+ //@benedikt: same with "->operator()"
+ HighestConfidenceMismatching =
+ fuzzyOR(HighestConfidenceMismatching,
+ FuzzyFunctionSampleMismatches->operator()(
+ relativeDistance<INDATATYPE, PROCDATATYPE>(
+ Sample, HistorySample)));
+#endif
}
LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching);
HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching);
LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry();
HighestConfidenceMismatching =
HighestConfidenceMismatchingHistory.highestEntry();
+ //@maxi you don't have to define the data type or the amount
+#if false
//@benedikt: same with "->operator()"
CONFDATATYPE ConfidenceSignalStateIsValid = fuzzyAND<CONFDATATYPE>(
2, LowestConfidenceMatching,
FuzzyFunctionNumOfSamplesMatches->operator()(static_cast<INDATATYPE>(
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
//@benedikt: same with "->operator()"
CONFDATATYPE ConfidenceSignalStateIsInvalid = fuzzyOR<CONFDATATYPE>(
2, HighestConfidenceMismatching,
FuzzyFunctionNumOfSamplesMismatches->operator()(static_cast<INDATATYPE>(
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
+#else
+ //@benedikt: same with "->operator()"
+ CONFDATATYPE ConfidenceSignalStateIsValid = fuzzyAND(
+ LowestConfidenceMatching,
+ FuzzyFunctionNumOfSamplesMatches->operator()(static_cast<INDATATYPE>(
+ SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
+ //@benedikt: same with "->operator()"
+ CONFDATATYPE ConfidenceSignalStateIsInvalid = fuzzyOR(
+ HighestConfidenceMismatching,
+ FuzzyFunctionNumOfSamplesMismatches->operator()(static_cast<INDATATYPE>(
+ SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
+#endif
if (ConfidenceSignalStateIsValid > ConfidenceSignalStateIsInvalid) {
if (SignalStateInfo.SignalStateIsValid) {
SignalStateInfo.SignalStateJustGotValid = false;
} else {
SignalStateInfo.SignalStateJustGotValid = true;
}
SignalStateInfo.SignalStateIsValid = true;
SignalStateInfo.SignalStateIsValidAfterReentrance = true;
}
}
void checkSignalStability(void) {
CONFDATATYPE ConfidenceSignalIsStable;
CONFDATATYPE ConfidenceSignalIsDrifting;
if (DABHistory.numberOfEntries() >= 2) {
//@benedikt: same "->operator()"
ConfidenceSignalIsStable = FuzzyFunctionSignalIsStable->operator()(
relativeDistance<INDATATYPE, PROCDATATYPE>(
DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0]));
//@benedikt: same "->operator()"
ConfidenceSignalIsDrifting = FuzzyFunctionSignalIsDrifting->operator()(
relativeDistance<INDATATYPE, PROCDATATYPE>(
DABHistory[DABHistory.numberOfEntries() - 1], DABHistory[0]));
} else {
// TODO: change to enum
ConfidenceSignalIsStable = 1;
ConfidenceSignalIsDrifting = 0;
}
SignalStateInfo.SignalIsStable =
ConfidenceSignalIsStable >= ConfidenceSignalIsDrifting;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SIGNALSTATE_HPP
diff --git a/include/rosa/agent/SignalStateDetector.hpp b/include/rosa/agent/SignalStateDetector.hpp
index 99af791..d7b10e9 100644
--- a/include/rosa/agent/SignalStateDetector.hpp
+++ b/include/rosa/agent/SignalStateDetector.hpp
@@ -1,272 +1,278 @@
//===-- rosa/agent/SignalStateDetector.hpp ----------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/SignalStateDetector.hpp
///
/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *signal state detector* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_SIGNALSTATEDETECTOR_HPP
#define ROSA_AGENT_SIGNALSTATEDETECTOR_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/agent/SignalState.hpp"
#include "rosa/agent/StateDetector.hpp"
#include <vector>
namespace rosa {
namespace agent {
/// Implements \c rosa::agent::SignalStateDetector as a functionality that
/// detects signal states given on input samples.
///
/// \note This implementation is supposed to be used for samples of an
/// arithmetic type.
///
/// \tparam INDATATYPE type of input data, \tparam CONFDATATYPE type of
/// data in that the confidence values are given, \tparam PROCDATATYPE type of
/// the relative distance and the type of data in which DABs are saved.
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE,
HistoryPolicy HP>
class SignalStateDetector
: public StateDetector<INDATATYPE, CONFDATATYPE, PROCDATATYPE, HP> {
+ // @maxi added them so it is compilable is this what you intended?
+ using StateDetector =
+ StateDetector<INDATATYPE, CONFDATATYPE, PROCDATATYPE, HP>;
+ using PartFuncPointer = typename StateDetector::PartFuncPointer;
+ using StepFuncPointer = typename StateDetector::StepFuncPointer;
+
private:
// For the convinience to write a shorter data type name
using SignalStatePtr =
std::shared_ptr<SignalState<INDATATYPE, CONFDATATYPE, PROCDATATYPE>>;
/// The NextSignalStateID is a counter variable which stores the ID which the
/// next signal state shall have.
uint32_t NextSignalStateID;
/// The SignalStateHasChanged is a flag that show whether a signal has changed
/// its state.
bool SignalStateHasChanged;
/// The CurrentSignalState is a pointer to the (saved) signal state in which
/// the actual variable (signal) of the observed system is.
SignalStatePtr CurrentSignalState;
/// The DetectedSignalStates is a history in that all detected signal states
/// are saved.
DynamicLengthHistory<SignalStatePtr, HP> DetectedSignalStates;
/// The FuzzyFunctionSampleMatches is the fuzzy function that gives the
/// confidence how good the new sample matches another sample in the sample
/// history.
PartFuncPointer FuzzyFunctionSampleMatches;
/// The FuzzyFunctionSampleMismatches is the fuzzy function that gives the
/// confidence how bad the new sample matches another sample in the sample
/// history.
PartFuncPointer FuzzyFunctionSampleMismatches;
/// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the
/// confidence how many samples from the sampe history match the new sample.
StepFuncPointer FuzzyFunctionNumOfSamplesMatches;
/// The FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives
/// the confidence how many samples from the sampe history mismatch the new
/// sample.
StepFuncPointer FuzzyFunctionNumOfSamplesMismatches;
/// The FuzzyFunctionSignalIsDrifting is the fuzzy function that gives the
/// confidence how likely it is that the signal is drifting.
PartFuncPointer FuzzyFunctionSignalIsDrifting;
/// The FuzzyFunctionSignalIsStable is the fuzzy function that gives the
/// confidence how likely it is that the signal is stable (not drifting).
PartFuncPointer FuzzyFunctionSignalIsStable;
/// SampleHistorySize is the (maximum) size of the sample history.
uint32_t SampleHistorySize;
/// DABSize the size of a DAB (Discrete Average Block).
uint32_t DABSize;
/// DABHistorySize is the (maximum) size of the DAB history.
uint32_t DABHistorySize;
public:
/// Creates an instance by setting all parameters
/// \param FuzzyFunctionSampleMatches The FuzzyFunctionSampleMatches is the
/// fuzzy function that gives the confidence how good the new sample matches
/// another sample in the sample history.
///
/// \param FuzzyFunctionSampleMismatches The FuzzyFunctionSampleMismatches is
/// the fuzzy function that gives the confidence how bad the new sample
/// matches another sample in the sample history.
///
/// \param FuzzyFunctionNumOfSamplesMatches The
/// FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the
/// confidence how many samples from the sampe history match the new sample.
///
/// \param FuzzyFunctionNumOfSamplesMismatches The
/// FuzzyFunctionNumOfSamplesMismatches is the fuzzy function that gives the
/// confidence how many samples from the sampe history mismatch the new
/// sample.
///
/// \param FuzzyFunctionSignalIsDrifting The FuzzyFunctionSignalIsDrifting is
/// the fuzzy function that gives the confidence how likely it is that the
/// signal (resp. the state of a signal) is drifting.
///
/// \param FuzzyFunctionSignalIsStable The FuzzyFunctionSignalIsStable is the
/// fuzzy function that gives the confidence how likely it is that the signal
/// (resp. the state of a signal) is stable (not drifting).
///
/// \param SampleHistorySize Sets the History size which will be used by \c
/// SignalState.
///
/// \param DABSize Sets the DAB size which will be used by \c SignalState.
///
/// \param DABHistorySize Sets the size which will be used by \c SignalState.
///
SignalStateDetector(uint32_t MaximumNumberOfSignalStates,
PartFuncPointer FuzzyFunctionSampleMatches,
PartFuncPointer FuzzyFunctionSampleMismatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMismatches,
PartFuncPointer FuzzyFunctionSignalIsDrifting,
PartFuncPointer FuzzyFunctionSignalIsStable,
uint32_t SampleHistorySize, uint32_t DABSize,
uint32_t DABHistorySize) noexcept
: NextSignalStateID(1), SignalStateHasChanged(false),
CurrentSignalState(nullptr),
DetectedSignalStates(MaximumNumberOfSignalStates),
FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches),
FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches),
FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches),
FuzzyFunctionNumOfSamplesMismatches(
FuzzyFunctionNumOfSamplesMismatches),
FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting),
FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable),
SampleHistorySize(SampleHistorySize), DABSize(DABSize),
DABHistorySize(DABHistorySize) {}
/// Destroys \p this object.
~SignalStateDetector(void) = default;
/// Detects the signal state to which the new sample belongs or create a new
/// signal state if the new sample does not match to any of the saved states.
///
/// \param Sample is the actual sample of the observed signal.
///
/// \return the information of the current signal state (signal state ID and
/// other parameters).
// TODO (future): change to operator()
SignalStateInformation<CONFDATATYPE>
detectSignalState(INDATATYPE Sample) noexcept {
if (!CurrentSignalState) {
ASSERT(DetectedSignalStates.empty());
SignalStatePtr S = createNewSignalState();
CurrentSignalState = S;
} else {
CONFDATATYPE ConfidenceSampleMatchesSignalState =
CurrentSignalState->confidenceSampleMatchesSignalState(Sample);
CONFDATATYPE ConfidenceSampleMismatchesSignalState =
CurrentSignalState->confidenceSampleMismatchesSignalState(Sample);
if (ConfidenceSampleMatchesSignalState >
ConfidenceSampleMismatchesSignalState) {
SignalStateHasChanged = false;
} else {
SignalStateHasChanged = true;
if (CurrentSignalState->signalStateInformation().SignalStateIsValid) {
CurrentSignalState->leaveSignalState();
} else {
DetectedSignalStates.deleteEntry(CurrentSignalState);
}
// TODO (future): additionally save averages to enable fast iteration
// through recorded signl state history (maybe sort vector based on
// these average values)
CurrentSignalState = nullptr;
//@benedikt: same question
for (auto &SavedSignalState : DetectedSignalStates) {
if (SavedSignalState != CurrentSignalState) {
ConfidenceSampleMatchesSignalState =
SavedSignalState->confidenceSampleMatchesSignalState(Sample);
ConfidenceSampleMismatchesSignalState =
SavedSignalState->confidenceSampleMismatchesSignalState(Sample);
if (ConfidenceSampleMatchesSignalState >
ConfidenceSampleMismatchesSignalState) {
// TODO (future): maybe it would be better to compare
// ConfidenceSampleMatchesSignalState of all signal states in the
// vector in order to find the best matching signal state.
CurrentSignalState = SavedSignalState;
break;
}
}
}
if (!CurrentSignalState) {
SignalStatePtr S = createNewSignalState();
CurrentSignalState = S;
}
}
}
SignalStateInformation<CONFDATATYPE> SignalStateInfo =
CurrentSignalState->insertSample(Sample);
if (SignalStateInfo.SignalStateJustGotValid) {
NextSignalStateID++;
}
return SignalStateInfo;
}
/// Gives information about the current signal state.
///
/// \return a struct SignalStateInformation that contains information about
/// the current signal state or NULL if no current signal state exists.
SignalStateInformation<CONFDATATYPE>
currentSignalStateInformation(void) noexcept {
if (CurrentSignalState) {
return CurrentSignalState->signalStateInformation();
} else {
return NULL;
}
}
/// Gives information whether a signal state change has happened or not.
///
/// \return true if a signal state change has happened, and false if not.
bool signalStateHasChanged(void) noexcept { return SignalStateHasChanged; }
private:
/// Creates a new signal state and adds it to the signal state vector in which
/// all known states are saved.
///
/// \return a pointer to the newly created signal state or NULL if no state
/// could be created.
SignalStatePtr createNewSignalState(void) noexcept {
SignalStatePtr S(new SignalState<INDATATYPE, CONFDATATYPE, PROCDATATYPE>(
NextSignalStateID, SampleHistorySize, DABSize, DABHistorySize,
FuzzyFunctionSampleMatches, FuzzyFunctionSampleMismatches,
FuzzyFunctionNumOfSamplesMatches, FuzzyFunctionNumOfSamplesMismatches,
FuzzyFunctionSignalIsDrifting, FuzzyFunctionSignalIsStable));
DetectedSignalStates.addEntry(S);
return S;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SIGNALSTATEDETECTOR_HPP
diff --git a/include/rosa/agent/StateDetector.hpp b/include/rosa/agent/StateDetector.hpp
index aa341f6..9bd7430 100644
--- a/include/rosa/agent/StateDetector.hpp
+++ b/include/rosa/agent/StateDetector.hpp
@@ -1,56 +1,57 @@
//===-- rosa/agent/StateDetector.hpp ----------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/StateDetector.hpp
///
/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *state detector* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_STATEDETECTOR_HPP
#define ROSA_AGENT_STATEDETECTOR_HPP
#include "rosa/agent/FunctionAbstractions.hpp"
#include "rosa/agent/History.hpp"
#include <vector>
namespace rosa {
namespace agent {
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE,
HistoryPolicy HP>
class StateDetector : 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");
-protected:
+public:
using PartFuncPointer =
std::shared_ptr<PartialFunction<INDATATYPE, CONFDATATYPE>>;
using StepFuncPointer =
std::shared_ptr<StepFunction<INDATATYPE, CONFDATATYPE>>;
+protected:
/// The NextSignalStateID is a counter variable which stores the ID which the
/// next signal state shall have.
unsigned int NextStateID;
/// The SignalStateHasChanged is a flag that show whether a signal has changed
/// its state.
bool StateHasChanged;
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SIGNALSTATEDETECTOR_HPP
diff --git a/include/rosa/agent/SystemStateDetector.hpp b/include/rosa/agent/SystemStateDetector.hpp
index ac9072e..31335bf 100644
--- a/include/rosa/agent/SystemStateDetector.hpp
+++ b/include/rosa/agent/SystemStateDetector.hpp
@@ -1,141 +1,146 @@
//===-- 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/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.
enum class SystemStateCondition {
STABLE, ///< The system state is stable
DRIFTING, ///< The system state is drifting
MALFUNCTIONING, ///< The system state is malfunctioning
UNKNOWN ///< The system state is unknown
};
/// TODO: write description
template <typename CONFDATATYPE> struct SystemStateInformation {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<CONFDATATYPE>::value),
"confidence type is not to arithmetic");
/// The system state ID saved as an uint32_teger number
uint32_t SystemStateID;
/// The SystemStateConfidence shows the overall confidence value of the system
/// state.
CONFDATATYPE OverallDetectionConfidence;
/// The SystemStateCondition shows the condition of a system state (stable,
/// drifting, malfunctioning, or unknown)
//@David: is it ok to name the variable exactly as the type is named?
SystemStateCondition SystemStateCondition;
/// The SystemStateIsValid saves the number of samples which have been
/// inserted into the state after entering it.
uint32_t NumberOfInsertedSamplesAfterEntrance;
/// The SystemStateIsValid shows whether a state is valid or invalid.
/// In this context, valid means that enough samples which are in close
/// proximitry have been inserted into the state.
bool SystemStateIsValid;
/// The SystemStateJustGotValid shows whether a system state got valid
/// (toggled from invalid to valid) during the current inserted sample.
bool SystemStateJustGotValid;
/// The SystemStateIsValidAfterReentrance shows whether a system state is
/// valid after the variable changed back to it again.
bool SystemStateIsValidAfterReentrance;
/// The SystemIsStable shows whether a signa is stable and not
/// drifting.
bool SystemIsStable;
};
/// TODO: write description
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE,
HistoryPolicy HP, std::size_t NUMOFINPUTSIGNALS,
std::size_t NUMOFOUTPUTSIGNALS>
class SystemStateDetector
: public StateDetector<INDATATYPE, CONFDATATYPE, PROCDATATYPE, HP> {
+ //@maxi added them to make it compilable is this what you wanted?
+ 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,
NUMOFINPUTSIGNALS, NUMOFOUTPUTSIGNALS>>;
/// The NextSystemStateID is a counter variable which stores the ID which
/// the
/// next system state shall have.
uint32_t NextSystemStateID;
/// The SystemStateHasChanged is a flag that show whether the observed
/// system
/// has changed its state.
bool SystemStateHasChanged;
/// 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;
/// The FuzzyFunctionDelayTimeToGetBroken is the fuzzy function that gives
/// the confidence whether the system is Broken because of an input change
/// without an output change or vice versa. A small time gap between the two
/// shall be allowed.
PartFuncPointer FuzzyFunctionDelayTimeToGetBroken;
/// The FuzzyFunctionDelayTimeToBeWorking is the fuzzy function that gives
/// the
/// confidence whether the system is still OK allthough an input change
/// without an output change or vice versa.
PartFuncPointer FuzzyFunctionDelayTimeToBeWorking;
public:
/// TODO: write description
SystemStateDetector(
uint32_t MaximumNumberOfSystemStates,
PartFuncPointer FuzzyFunctionDelayTimeToGetBroken,
PartFuncPointer FuzzyFunctionDelayTimeToBeWorking) noexcept
: NextSystemStateID(1), SystemStateHasChanged(false),
CurrentSystemState(nullptr),
DetectedSystemStates(MaximumNumberOfSystemStates),
FuzzyFunctionDelayTimeToGetBroken(FuzzyFunctionDelayTimeToGetBroken),
FuzzyFunctionDelayTimeToBeWorking(FuzzyFunctionDelayTimeToBeWorking) {}
/// Destroys \p this object.
~SystemStateDetector(void) = default;
/// TODO: write description
SystemStateInformation<CONFDATATYPE>
detectSystemState(INDATATYPE Sample) noexcept {
// dummy line
Sample = 1;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SYSTEMSTATEDETECTOR_HPP
diff --git a/include/rosa/support/math.hpp b/include/rosa/support/math.hpp
index 30e11fb..95a7363 100644
--- a/include/rosa/support/math.hpp
+++ b/include/rosa/support/math.hpp
@@ -1,153 +1,153 @@
//===-- rosa/support/math.hpp -----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/math.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Math helpers.
///
//===----------------------------------------------------------------------===//
// !!!!!! Please check lines 60 - 180 forward !!!!!!!!!!!!!!
#ifndef ROSA_SUPPORT_MATH_HPP
#define ROSA_SUPPORT_MATH_HPP
#include "debug.hpp"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdarg>
#include <cstdlib>
#include <limits>
#include <type_traits>
namespace rosa {
/// Computes log base 2 of a number.
///
/// \param N the number to compute log base 2 for
///
/// \return log base 2 of \p N
constexpr size_t log2(const size_t N) {
return ((N < 2) ? 1 : 1 + log2(N / 2));
}
/// Tells the next representable floating point value.
///
/// \tparam T type to operate on
///
/// \note The second type argument enforces \p T being a floating point type,
/// always use the default value!
///
/// \param V value to which find the next representable one
///
/// \return the next representable value of type \p T after value \p V
///
/// \pre Type \p T must be a floating point type, which is enforced by
/// `std::enable_if` in the second type argument.
template <typename T,
typename = std::enable_if_t<std::is_floating_point<T>::value>>
T nextRepresentableFloatingPoint(const T V) {
return std::nextafter(V, std::numeric_limits<T>::infinity());
}
/// Conjuncts two or more values with each other.
///
/// \param Data an array of the data
///
/// \return the conjunction of the values given as parameter.
template <typename CONFDATATYPE, std::size_t size>
CONFDATATYPE fuzzyAND(const std::array<CONFDATATYPE, size> & Data) noexcept {
STATIC_ASSERT(std::is_arithmetic<CONFDATATYPE>::value,
"Type of FuzzyAnd is not arithmetic");
STATIC_ASSERT(size > 1, "Number of Arguments is to little");
for (auto tmp : Data)
ASSERT(tmp <= 1 && tmp >= 0);
return *std::min_element(Data.begin(), Data.end());
}
/// Conjuncts two or more values with each other. It's a wrapper for \c fuzzyAND() [array]
///
/// \param Data first data to get the type explicitly
///
/// \param Datan a package of data
///
/// \note the types of Datan must be the same type as Data
///
/// \return the conjunction of the values given as parameter.
template <typename CONFDATATYPE, typename... _CONFDATATYPE>
std::enable_if_t<
std::conjunction_v<std::is_same<CONFDATATYPE, _CONFDATATYPE>...>,
CONFDATATYPE>
-fuzzyAND(CONFDATATYPE & Data, _CONFDATATYPE&... Datan) noexcept {
+fuzzyAND(const CONFDATATYPE Data, const _CONFDATATYPE... Datan) noexcept {
return fuzzyAND(
std::array<CONFDATATYPE, sizeof...(Datan) + 1>{Data, Datan...});
}
/// Disjuncts two or more values with each other.
///
/// \param Data an array with the data.
///
/// \return the disjunction of the values given as parameter.
template <typename CONFDATATYPE, std::size_t size>
CONFDATATYPE fuzzyOR(const std::array<CONFDATATYPE, size> & Data) noexcept {
STATIC_ASSERT(std::is_arithmetic<CONFDATATYPE>::value,
"Type of FuzzyAnd is not arithmetic");
STATIC_ASSERT(size > 1, "Number of Arguments is to little");
ASSERT(std::all_of(Data.begin(), Data.end(),
[](const auto &v) { return v <= 1 && v >= 0; }));
return *std::max_element(Data.begin(), Data.end());
}
/// Disjuncts two or more values with each other. It's a wrapper for \c fuzzyOR() [array]
///
/// \param Data first data to get the type explicitly
///
/// \param Datan a package of data
///
/// \note the types of Datan must be the same type as Data
///
/// \return the disjunction of the values given as parameter.
template <typename CONFDATATYPE, typename... _CONFDATATYPE>
std::enable_if_t<
std::conjunction_v<std::is_same<CONFDATATYPE, _CONFDATATYPE>...>,
CONFDATATYPE>
-fuzzyOR(const CONFDATATYPE & Data, const _CONFDATATYPE&... Datan) noexcept {
+fuzzyOR(const CONFDATATYPE Data, const _CONFDATATYPE... Datan) noexcept {
return fuzzyOR(
std::array<CONFDATATYPE, sizeof...(Datan) + 1>{Data, Datan...});
}
template <typename INDATATYPE, typename PROCDATATYPE>
PROCDATATYPE relativeDistance(INDATATYPE NewValue,
INDATATYPE HistoryValue) noexcept {
PROCDATATYPE Dist = HistoryValue - NewValue;
if (Dist == 0) {
return 0;
} else {
Dist = Dist / NewValue;
if (Dist < 0) {
// TODO: I guess this multiplication here should not be done because
// it could be that the distance fuzzy functions are not symetrical
//(negative and positive side)
Dist = Dist * (-1);
}
return (Dist);
}
}
} // End namespace rosa
#endif // ROSA_SUPPORT_MATH_HPP

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 3, 11:10 PM (9 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157414
Default Alt Text
(47 KB)

Event Timeline