Page MenuHomePhorge

No OneTemporary

Size
16 KB
Referenced Files
None
Subscribers
None
diff --git a/include/rosa/agent/State.hpp b/include/rosa/agent/State.hpp
index 2afd52f..aee717d 100644
--- a/include/rosa/agent/State.hpp
+++ b/include/rosa/agent/State.hpp
@@ -1,370 +1,415 @@
//===-- rosa/agent/State.hpp ----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/State.hpp
///
/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *state* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_STATE_HPP
#define ROSA_AGENT_STATE_HPP
#include "rosa/agent/FunctionAbstractions.hpp"
#include "rosa/agent/Functionality.h"
#include "rosa/agent/History.hpp"
#include <cstdarg>
namespace rosa {
namespace agent {
/// State conditions defining how the condition of a \c rosa::agent::State is
/// saved in \c rosa::agent::StateInformation.
enum class VariableStateCondition {
STABLE, ///< The state is stable
DRIFTING, ///< The state is drifting
UNKNOWN ///< The state is unknown
};
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 state ID saved as an unsigned integer number
unsigned int StateID;
/// The StateConfidence shows the overall confidence value of the state.
CONFDATATYPE StateConfidence;
/// The VariableStateCondition shows the condition of a state (stable or
/// drifting)
VariableStateCondition VariableStateCondition;
/// 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;
};
// @Benedikt: now there are 4 datatypes. Do you think we can merge PROCDATATYPE
// and PROCDATATYPE somehow?
/// \tparam INDATATYPE type of input data, \tparam CONFDATATYPE type of
/// data in that the confidence values are given, \param PROCDATATYPEtype of
/// the relative distance and the type of data in which DABs are saved.
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),
"DAB storage type 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>>;
using StateInfoPtr = std::shared_ptr<StateInformation<CONFDATATYPE>>;
/// StateInfo is a struct StateInformation that contains information about the
/// current state.
StateInfoPtr StateInfo;
/// 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 FuzzyFunctionSampleMatches is the fuzzy function that gives the
+
+ /// 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 FuzzyFunctionSampleMatches is the fuzzy function that gives the
+
+ /// The FuzzyFunctionNumOfSamplesMatches is the fuzzy function that gives the
/// confidence how many samples from the sampe history match the new sample.
StepFuncPointer FuzzyFunctionNumOfSamplesMatches;
- /// The FuzzyFunctionSampleMatches is the fuzzy function that gives the
- /// confidence how many samples from the sampe history mismatch the new
+
+ /// 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;
/// 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 StateIsValidAfterReentrance shows whether a state is valid after the
/// variable changed back to it again.
bool StateIsValidAfterReentrance;
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 StateID The Id of the Stateinfo \c StateInformation
+ ///
+ /// \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.
+ ///
State(unsigned int StateID, PartFuncPointer FuzzyFunctionSampleMatches,
PartFuncPointer FuzzyFunctionSampleMismatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMatches,
StepFuncPointer FuzzyFunctionNumOfSamplesMismatches,
PartFuncPointer FuzzyFunctionSignalIsDrifting,
PartFuncPointer FuzzyFunctionSignalIsStable,
unsigned int sampleHistorySize, unsigned int DABSize,
unsigned int DABHistorySize) noexcept
: StateInfo(StateID, 0, VariableStateCondition::UNKNOWN, false, false),
SampleHistory(sampleHistorySize), DAB(DABSize),
DABHistory(DABHistorySize),
FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches),
FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches),
FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches),
FuzzyFunctionNumOfSamplesMismatches(
FuzzyFunctionNumOfSamplesMismatches),
FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting),
FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable) {}
/// Destroys \p this object.
~State(void) = default;
void leaveState(void) {
DAB.clear();
StateIsValidAfterReentrance = false;
}
void insertSample(INDATATYPE Sample) {
SampleHistory.addEntry(Sample);
DAB.addEntry(Sample);
if (DAB.full()) {
PROCDATATYPE AvgOfDAB = DAB.template average<PROCDATATYPE>();
DABHistory.addEntry(AvgOfDAB);
DAB.clear();
}
FuzzyFunctionNumOfSamplesMatches->setRightLimit(
SampleHistory->numberOfEntries());
FuzzyFunctionNumOfSamplesMismatches->setRightLimit(
SampleHistory->numberOfEntries());
// TODO: calculate whether state is valid and properly set StateIsValid,
// StateJustGotValid, StateIsValidAfterReentrance
// TODO: check actual state whether it drifts
// TODO: write in StateInfo
}
/// Gives the confidence how likely the new sample matches the state.
///
/// \param Sample is the actual sample of the observed signal.
///
/// \return the confidence of the new sample is matching the state.
CONFDATATYPE
confSampleMatchesState(INDATATYPE Sample) {
CONFDATATYPE ConfidenceOfBestCase = 0;
// TODO: history
std::vector<PROCDATATYPE> RelativeDistanceHistory;
// calculate distances to all history samples
for (auto &HistorySample : SampleHistory) {
PROCDATATYPE RelativeDistance = relativeDistance(Sample, HistorySample);
RelativeDistanceHistory.push_back(RelativeDistance);
}
// sort all calculated distances so that the lowest distance (will get the
// highest confidence) is at the beginning.
sort(RelativeDistanceHistory.begin(), RelativeDistanceHistory.end());
CONFDATATYPE ConfidenceOfWorstFittingSample = 1;
unsigned int Case = 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.
// TODO: history
// TODO: iterate thorugh case and use []
// TODO:
for (auto RelativeDistance = RelativeDistanceHistory.cbegin();
RelativeDistance != RelativeDistanceHistory.cend();
RelativeDistance++, Case++) {
CONFDATATYPE ConfidenceFromRelativeDistance;
// CHECK if I should use * for RelativeDistance
if (std::isinf(RelativeDistance)) {
// TODO (future) if fuzzy is defined in a way that infinity is not 0 it
// would be a problem
//@benedikt: check if your partialfunctions can take infinity as
// argument
ConfidenceFromRelativeDistance = 0;
} else {
ConfidenceFromRelativeDistance =
FuzzyFunctionSampleMatches(RelativeDistance);
}
ConfidenceOfWorstFittingSample = fuzzyAND(ConfidenceOfWorstFittingSample,
ConfidenceFromRelativeDistance);
// @benedikt: change old-style cast to one of these: reinterpret_cast,
// static_cast, dynamic_cast or const_cast. Which should I use? Or should
// the HistSampleCounter variable already be CONFDATATYPE type?
ConfidenceOfBestCase = fuzzyOR(
ConfidenceOfBestCase,
fuzzyAND(ConfidenceOfWorstFittingSample,
FuzzyFunctionNumOfSamplesMatches((CONFDATATYPE)Case)));
}
return ConfidenceOfBestCase;
}
/// Gives the confidence how likely the new sample mismatches the state.
///
/// \param Sample is the actual sample of the observed signal.
///
/// \return the confidence of the new sample is mismatching the state.
CONFDATATYPE
confSampleMismatchesState(INDATATYPE Sample) {
float ConfidenceOfWorstCase = 1;
// TODO: history!
std::vector<PROCDATATYPE> RelativeDistanceHistory;
// calculate distances to all history samples
for (auto &HistorySample : SampleHistory) {
RelativeDistanceHistory.push_back(
relativeDistance(Sample, HistorySample));
}
// sort all calculated distances so that the highest distance (will get the
// lowest confidence) is at the beginning.
sort(RelativeDistanceHistory.rbegin(), RelativeDistanceHistory.rend());
CONFDATATYPE ConfidenceOfBestFittingSample = 0;
unsigned int Case = 1;
// 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
// confSampleMatchesState(INDATATYPE Sample)".
for (unsigned int RelativeDistance = RelativeDistanceHistory.cbegin();
RelativeDistance != RelativeDistanceHistory.cend();
RelativeDistance++, Case++) {
CONFDATATYPE ConfidenceFromRelativeDistance;
if (std::isinf(RelativeDistance)) {
ConfidenceFromRelativeDistance = 1;
} else {
ConfidenceFromRelativeDistance =
FuzzyFunctionSampleMismatches(RelativeDistance);
}
ConfidenceOfBestFittingSample = fuzzyOR(ConfidenceOfBestFittingSample,
ConfidenceFromRelativeDistance);
// @benedikt: change old-style cast to one of these: reinterpret_cast,
// static_cast, dynamic_cast or const_cast. Which should I use? Or should
// the HistSampleCounter variable already be CONFDATATYPE type?
ConfidenceOfWorstCase = fuzzyAND(
ConfidenceOfWorstCase,
fuzzyOR(ConfidenceOfBestFittingSample,
FuzzyFunctionNumOfSamplesMismatches((CONFDATATYPE)Case)));
}
return ConfidenceOfWorstCase;
}
/// Gives information about the current state.
///
/// \return a struct StateInformation that contains information about the
/// current state.
StateInfoPtr stateInformation(void) { return StateInfo; }
private:
// @David: Where should these next functions (fuzzyAND, fuzzyOR,
// relativeDistance) moved to (I guess we will use them also somewhere else)?
// copied from the internet and adapted
// (https://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c)
CONFDATATYPE fuzzyAND(int n_args, ...) {
va_list ap;
va_start(ap, n_args);
CONFDATATYPE min = va_arg(ap, CONFDATATYPE);
for (int i = 2; i <= n_args; i++) {
CONFDATATYPE a = va_arg(ap, CONFDATATYPE);
min = std::min(a, min);
}
va_end(ap);
return min;
}
// copied from the internet
// (https://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c)
CONFDATATYPE fuzzyOR(int n_args, ...) {
va_list ap;
va_start(ap, n_args);
CONFDATATYPE max = va_arg(ap, CONFDATATYPE);
for (int i = 2; i <= n_args; i++) {
CONFDATATYPE a = va_arg(ap, CONFDATATYPE);
std::max(a, max);
}
va_end(ap);
return max;
}
PROCDATATYPE relativeDistance(INDATATYPE SampleValue,
INDATATYPE HistoryValue) {
PROCDATATYPE Dist = HistoryValue - SampleValue;
if (Dist == 0) {
return 0;
} else {
Dist = Dist / SampleValue;
if (Dist < 0) {
//@benedikt: 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 agent
} // End namespace rosa
#endif // ROSA_AGENT_STATE_HPP

File Metadata

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

Event Timeline