Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386709
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
46 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/rosa/agent/FunctionAbstractions.hpp b/include/rosa/agent/FunctionAbstractions.hpp
index 0639568..cdeef0d 100644
--- a/include/rosa/agent/FunctionAbstractions.hpp
+++ b/include/rosa/agent/FunctionAbstractions.hpp
@@ -1,513 +1,514 @@
//===-- rosa/agent/FunctionAbstractions.hpp ---------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/FunctionAbstractions.hpp
///
/// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *FunctionAbstractions* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
#define ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/Functionality.h"
#include "rosa/support/debug.hpp"
#include <algorithm>
#include <cmath>
#include <memory>
#include <vector>
namespace rosa {
namespace agent {
//@benedikt: check if your partialfunctions can take infinity as
// argument
/// Implements \c rosa::agent::Abstraction as a linear function,
/// y = Coefficient * X + Intercept.
///
/// \note This implementation is supposed to be used to represent a linear
/// function from an arithmetic domain to an arithmetic range. This is enforced
/// statically.
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class LinearFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value),
"LinearFunction not arithmetic T");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"LinearFunction not to arithmetic");
protected:
/// The Intercept of the linear function
const R Intercept;
/// The Coefficient of the linear function
const R Coefficient;
public:
/// Creates an instance.
///
/// \param Intercept the intercept of the linear function
/// \param Coefficient the coefficient of the linear function
LinearFunction(R Intercept, R Coefficient) noexcept
: Abstraction<D, R>(Intercept), Intercept(Intercept),
Coefficient(Coefficient) {}
/// Creates an instance given the two points on a linear function.
///
/// \param x1 The x-value of the first point
/// \param y1 The x-value of the first point
/// \param x2 The y-value of the second point
/// \param y2 The y-value of the second point
LinearFunction(D x1, R y1, D x2, R y2) noexcept
- : LinearFunction<D, R>(y1 - static_cast<double>(x1) * (y1 - y2) /
- (static_cast<double>(x1) - static_cast<double>(x2)),
- (y1 - y2) /
- (static_cast<double>(x1) - static_cast<double>(x2))) {}
+ : LinearFunction<D, R>(
+ static_cast<R>(
+ y1 - static_cast<double>(x1) * (y1 - y2) /
+ (static_cast<double>(x1) - static_cast<double>(x2))),
+ static_cast<R>((y1 - y2) / (static_cast<double>(x1) -
+ static_cast<double>(x2)))) {}
/// Creates an instance given the two points on a linear function.
///
/// \param p1 The coordinates of the first point
/// \param p2 The coordinates of the second point
LinearFunction(std::pair<D, R> p1, std::pair<D, R> p2) noexcept
: LinearFunction<D, R>(p1.first, p1.second, p2.first, p2.second) {}
/// Destroys \p this object.
~LinearFunction(void) = default;
/// Checks wether the Abstraction evaluates to default at the given position
/// As LinearFunctions can be evaluated everythwere, this is always false
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false
bool isDefaultAt(const D &V) const noexcept override {
(void)V;
return false;
}
/// Getter for member variable Intercept
///
/// \return Intercept
D getIntercept() const { return Intercept; }
/// Setter for member variable Intercept
///
/// \param Intercept the new Intercept
void setIntercept(const D &Intercept) { this->Intercept = Intercept; }
/// Getter for member variable Coefficient
///
/// \return Coefficient
D getCoefficient() const { return Coefficient; }
/// Setter for member variable Coefficient
///
/// \param Coefficient the new Intercept
void setCoefficient(const D &Coefficient) { this->Coefficient = Coefficient; }
/// Set Intercept and Coefficient from two points on the linear function
///
/// \param x1 The x-value of the first point
/// \param y1 The x-value of the first point
/// \param x2 The y-value of the second point
/// \param y2 The y-value of the second point
void setFromPoints(D x1, R y1, D x2, R y2) {
Coefficient = (y1 - y2) / (x1 - x2);
Intercept = y1 - Coefficient * x1;
}
/// Set Intercept and Coefficient from two points on the linear function
///
/// \param p1 The coordinates of the first point
/// \param p2 The coordinates of the second point
inline void setFromPoints(std::pair<D, R> p1, std::pair<D, R> p2) {
setFromPoints(p1.first, p1.second, p2.first, p2.second);
}
/// Evaluates the linear function
///
/// \param X the value at which to evaluate the function
///
/// \return Coefficient*X + Intercept
virtual R operator()(const D &X) const noexcept override {
return Intercept + X * Coefficient;
}
};
/// Implements \c rosa::agent::Abstraction as a sine function,
/// y = Amplitude * sin(Frequency * X + Phase) + Average.
///
/// \note This implementation is supposed to be used to represent a sine
/// function from an arithmetic domain to an arithmetic range. This is enforced
/// statically.
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class SineFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value),
"SineFunction not arithmetic T");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"SineFunction not to arithmetic");
protected:
/// The frequency of the sine wave
const D Frequency;
/// The Ampiltude of the sine wave
const D Amplitude;
/// The Phase-shift of the sine wave
const D Phase;
/// The y-shift of the sine wave
const D Average;
public:
/// Creates an instance.
///
/// \param Frequency the frequency of the sine wave
/// \param Amplitude the amplitude of the sine wave
/// \param Phase the phase of the sine wave
/// \param Average the average of the sine wave
SineFunction(D Frequency, D Amplitude, D Phase, D Average) noexcept
: Abstraction<D, R>(Average), Frequency(Frequency), Amplitude(Amplitude),
Phase(Phase), Average(Average) {}
/// Destroys \p this object.
~SineFunction(void) = default;
/// Checks wether the Abstraction evaluates to default at the given position
/// As SineFunctions can be evaluated everythwere, this is always false
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false
bool isDefaultAt(const D &V) const noexcept override {
(void)V;
return false;
}
/// Evaluates the sine function
///
/// \param X the value at which to evaluate the function
/// \return the value of the sine-function at X
virtual R operator()(const D &X) const noexcept override {
return Amplitude * sin(Frequency * X + Phase) + Average;
}
};
enum StepDirection { StepUp, StepDown };
/// Implements \c rosa::agent::PartialFunction as a step function from 0 to 1
/// with a ramp in between
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class StepFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
private:
D Coefficient;
D RightLimit;
StepDirection Direction;
public:
/// Creates an instance by Initializing the underlying \c Abstraction.
///
/// \param Coefficient Coefficient of the ramp
/// \param Direction wether to step up or down
///
/// \pre Coefficient > 0
StepFunction(D Coefficient, StepDirection Direction = StepUp)
: Abstraction<D, R>(0), Coefficient(Coefficient),
RightLimit(1.0f / Coefficient), Direction(Direction) {
ASSERT(Coefficient > 0);
}
/// Destroys \p this object.
~StepFunction(void) = default;
/// Setter for Coefficient
///
/// \param Coefficient the new Coefficient
void setCoefficient(const D &Coefficient) {
ASSERT(Coefficient > 0);
this->Coefficient = Coefficient;
this->RightLimit = 1 / Coefficient;
}
/// Setter for RightLimit
///
/// \param _RightLimit the new RightLimit
void setRightLimit(const D &_RightLimit) {
ASSERT(_RightLimit > 0);
this->RightLimit = _RightLimit;
this->Coefficient = 1 / _RightLimit;
}
/// Checks wether the Abstraction evaluates to default at the given position
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false if the is negative, true otherwise
bool isDefaultAt(const D &V) const noexcept override { return V > 0; }
/// Executes the Abstraction
///
/// \param V value to abstract
///
/// \return the abstracted value
R operator()(const D &V) const noexcept override {
R ret = 0;
if (V <= 0)
ret = 0;
else if (V >= RightLimit)
ret = 1;
else
ret = V * Coefficient;
return Direction == StepDirection::StepUp ? ret : 1 - ret;
}
};
/// Implements \c rosa::agent::Abstraction as a typical (cross-)likeliness
/// function.
///
/// The function has a likeliness parameter \c P and implements \code
/// f(x) -> 1 / (P * x)
/// \endcode on the domain \code [0, Inf) \endcode with \code f(0) = 1 \endcode
/// .
///
/// \note This implementation is supposed to be used to represent a function
/// from an arithmetic domain to an arithmetic range. This is enforced
/// statically.
///
/// \note This function can be used as cross-likeliness profile in \c
/// rosa::agent::CrossCombinator for those input combinations that are not to be
/// assessed with the default \c crossLikelinessParameter.
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class LikelinessFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
private:
//// The likeliness parameter.
const R P;
public:
/// Creates an instance.
///
/// \param P likeliness parameter
LikelinessFunction(const R P) : Abstraction<D, R>(0), P(P) {}
/// Destroys \p this object.
~LikelinessFunction(void) = default;
/// Checks wether the Abstraction evaluates to default at the given position
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false if the value falls into a defined range and the Abstraction
/// defined for that range does not fall back to it's default value.
bool isDefaultAt(const D &V) const noexcept override { return V < 0; }
/// Evaluates the likeliness function at the given position.
///
/// \param V value to abstract
///
/// \return the abstracted value
R operator()(const D &V) const noexcept override {
if (V < 0) {
return this->Default;
} else if (V == 0) {
return static_cast<R>(1);
} else {
return static_cast<R>(1) / (P * V);
}
}
};
/// Implements \c rosa::agent::Abstraction as a partial function from a domain
/// to a range.
///
/// \note This implementation is supposed to be used to represent a partial
/// function from an arithmetic domain to an arithmetic range. This is enforced
/// statically.
///
/// A partial function is defined as a list of abstractions, where each
/// abstraction is associated a range in which it is defined. These ranges must
/// be mutually exclusive.
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class PartialFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
private:
/// A \c rosa::agent::RangeAbstraction RA is used to represent the association
/// from ranges to Abstractions.
/// This returns the Abstraction that is defined for any given value, or
/// a default Abstraction if no Abstraction is defined for that value.
RangeAbstraction<D, std::shared_ptr<Abstraction<D, R>>> RA;
public:
/// Creates an instance by Initializing the underlying \c Abstraction.
///
/// \param Map the mapping to do abstraction according to
/// \param Default abstraction to abstract to by default
///
/// \pre Each key defines a valid range such that `first <= second` and
/// there are no overlapping ranges defined by the keys.
PartialFunction(
const std::map<std::pair<D, D>, std::shared_ptr<Abstraction<D, R>>> &Map,
const R Default)
: Abstraction<D, R>(Default),
RA(Map,
std::shared_ptr<Abstraction<D, R>>(new Abstraction<D, R>(Default))) {
}
/// Destroys \p this object.
~PartialFunction(void) = default;
/// Checks wether the Abstraction evaluates to default at the given position
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false if the value falls into a defined range and the Abstraction
/// defined for that range does not fall back to it's default value.
bool isDefaultAt(const D &V) const noexcept override {
return RA.isDefaultAt(V) ? true : RA(V)->isDefaultAt(V);
}
/// Searches for an Abstraction for the given value and executes it for that
/// value, if such an Abstraction is found. The default Abstraction is
/// evaluated otherwise.
///
/// \param V value to abstract
///
/// \return the abstracted value based on the set mapping
R operator()(const D &V) const noexcept override {
R Ret = RA(V)->operator()(V);
//@TODO move to ClipperFunction
if (Ret < 0)
return 0;
if (Ret > 1)
return 1;
return Ret;
}
};
// Begrenzer!!!
/// Implements \c rosa::agent::Abstraction as a partial function from a domain
/// to a range.
///
/// \note This implementation is supposed to be used to represent a partial
/// function from an arithmetic domain to an arithmetic range. This is enforced
/// statically.
///
/// A partial function is defined as a list of abstractions, where each
/// abstraction is associated a range in which it is defined. These ranges must
/// be mutually exclusive.
///
/// \tparam D type of the functions domain
/// \tparam R type of the functions range
template <typename D, typename R>
class ClipperFunction : public Abstraction<D, R> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT((std::is_arithmetic<D>::value), "abstracting not arithmetic");
STATIC_ASSERT((std::is_arithmetic<R>::value),
"abstracting not to arithmetic");
private:
/// A \c rosa::agent::RangeAbstraction RA is used to represent the association
/// from ranges to Abstractions.
/// This returns the Abstraction that is defined for any given value, or
/// a default Abstraction if no Abstraction is defined for that value.
std::shared_ptr<Abstraction<D, R>> Function;
R Min;
R Max;
public:
/// Creates an instance by Initializing the underlying \c Abstraction.
///
/// \param Default abstraction to abstract to by default
/// \param Min min value to be returned
/// \param Max max value to be returned
///
/// \pre Each key defines a valid range such that `first <= second` and
/// there are no overlapping ranges defined by the keys.
- ClipperFunction(std::shared_ptr<Abstraction<D, R>> &Function, const R Default, const R Min, const R Max)
- : Abstraction<D, R>(Default),
- Function(Function), Min(Min), Max(Max) {
- }
+ ClipperFunction(std::shared_ptr<Abstraction<D, R>> &Function, const R Default,
+ const R Min, const R Max)
+ : Abstraction<D, R>(Default), Function(Function), Min(Min), Max(Max) {}
/// Destroys \p this object.
~ClipperFunction(void) = default;
/// Checks wether the Abstraction evaluates to default at the given position
///
/// \param V the value at which to check if the function falls back to it's
/// default value.
///
/// \return false if the value falls into a defined range and the Abstraction
/// defined for that range does not fall back to it's default value.
bool isDefaultAt(const D &V) const noexcept override {
return Function.isDefaultAt(V);
}
/// Searches for an Abstraction for the given value and executes it for that
/// value, if such an Abstraction is found. The default Abstraction is
/// evaluated otherwise.
///
/// \param V value to abstract
///
/// \return the abstracted value based on the set mapping
R operator()(const D &V) const noexcept override {
R Ret = Function(V);
if (Ret < Min)
return Min;
if (Ret > Max)
return Max;
return Ret;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_FUNCTIONABSTRACTIONS_HPP
diff --git a/include/rosa/agent/SignalState.hpp b/include/rosa/agent/SignalState.hpp
index 4a30d5f..63530a9 100644
--- a/include/rosa/agent/SignalState.hpp
+++ b/include/rosa/agent/SignalState.hpp
@@ -1,661 +1,681 @@
//===-- 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/DistanceMetrics.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");
/// ConfidenceOfMatchingState is the confidence how good the new sample
/// matches the state.
CONFDATATYPE ConfidenceOfMatchingState;
/// ConfidenceOfMatchingState is the confidence how bad the new sample
/// matches the state.
CONFDATATYPE ConfidenceOfMismatchingState;
/// The SignalProperty saves whether the monitored signal is an input our
/// output signal.
SignalProperties SignalProperty;
/// The SignalStateIsValid saves the number of samples which have been
/// inserted into the state after entering it.
uint32_t NumberOfInsertedSamplesAfterEntrance;
public:
SignalStateInformation(unsigned int SignalStateID,
SignalProperties _SignalProperty) {
this->StateID = SignalStateID;
this->SignalProperty = _SignalProperty;
this->StateCondition = StateConditions::UNKNOWN;
this->NumberOfInsertedSamplesAfterEntrance = 0;
this->StateIsValid = false;
this->StateJustGotValid = false;
this->StateIsValidAfterReentrance = false;
this->ConfidenceStateIsValid = 0;
this->ConfidenceStateIsInvalid = 0;
this->ConfidenceStateIsStable = 0;
this->ConfidenceStateIsDrifting = 0;
}
SignalStateInformation() = default;
};
/// \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:
// The metric to calculate the distance between two points
using DistanceMetricAbstraction =
Abstraction<std::pair<INDATATYPE, INDATATYPE>, PROCDATATYPE> &;
// For the convinience to write a shorter data type name
using PartFuncReference = PartialFunction<INDATATYPE, CONFDATATYPE> &;
// using PartFuncReference2 = ;
using StepFuncReference = StepFunction<INDATATYPE, CONFDATATYPE> &;
private:
/// SignalStateInfo is a struct of SignalStateInformation that contains
/// information about the current signal state.
SignalStateInformation<CONFDATATYPE> SignalStateInfo;
/// The metric to calculate the distance between two points
DistanceMetricAbstraction DistanceMetric;
/// 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 FuzzyFunctionSampleValid is the fuzzy function that gives the
/// confidence how good one matches another sample in the sample
/// history. This is done to evaluate whether a state is valid.
PartFuncReference FuzzyFunctionSampleValid;
/// The FuzzyFunctionSampleInvalid is the fuzzy function that gives the
/// confidence how bad one sample matches another sample in the sample
/// history. This is done to evaluate whether a state is invalid.
PartFuncReference FuzzyFunctionSampleInvalid;
/// The FuzzyFunctionNumOfSamplesValid is the fuzzy function that gives the
/// confidence how many samples from the sample history match another sample.
/// This is done to evaluate whether a state is valid.
StepFuncReference FuzzyFunctionNumOfSamplesValid;
/// The FuzzyFunctionNumOfSamplesInvalid is the fuzzy function that gives
/// the confidence how many samples from the sample history mismatch another
/// sample. This is done to evaluate whether a state is invalid.
StepFuncReference FuzzyFunctionNumOfSamplesInvalid;
/// 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;
/// TODO: description
PartialFunction<uint32_t, float> &FuzzyFunctionSignalConditionLookBack;
/// TODO: description
PartialFunction<uint32_t, float> &FuzzyFunctionSignalConditionHistoryDesicion;
/// TODO: description
uint32_t DriftLookbackRange;
/// 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;
/// TempConfidenceMatching is the confidence how good a sample matches the
/// state. However, the value of this variable is only needed temporarly.
CONFDATATYPE TempConfidenceMatching = 0;
/// TempConfidenceMatching is the confidence how bad a sample matches the
/// state. However, the value of this variable is only needed temporarly.
CONFDATATYPE TempConfidenceMismatching = 0;
public:
/// Creates an instance by setting all parameters
/// \param SignalStateID The Id of the SignalStateinfo \c
/// SignalStateInformation.
///
/// \param DistanceMetric the distance metric to calculate the distance
/// between two points
///
/// \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,
DistanceMetricAbstraction DistanceMetric,
PartFuncReference FuzzyFunctionSampleMatches,
PartFuncReference FuzzyFunctionSampleMismatches,
StepFuncReference FuzzyFunctionNumOfSamplesMatches,
StepFuncReference FuzzyFunctionNumOfSamplesMismatches,
PartFuncReference FuzzyFunctionSampleValid,
PartFuncReference FuzzyFunctionSampleInvalid,
StepFuncReference FuzzyFunctionNumOfSamplesValid,
StepFuncReference FuzzyFunctionNumOfSamplesInvalid,
// SAVE CHANGES
PartFuncReference FuzzyFunctionSignalIsDrifting,
PartFuncReference FuzzyFunctionSignalIsStable,
PartialFunction<uint32_t, float> &FuzzyFunctionSignalConditionLookBack,
// - SAVE CHANGES
PartialFunction<uint32_t, float>
&FuzzyFunctionSignalConditionHistoryDesicion,
uint32_t DriftLookbackRange) noexcept
: SignalStateInfo{SignalStateID, SignalProperty},
DistanceMetric(DistanceMetric),
FuzzyFunctionSampleMatches(FuzzyFunctionSampleMatches),
FuzzyFunctionSampleMismatches(FuzzyFunctionSampleMismatches),
FuzzyFunctionNumOfSamplesMatches(FuzzyFunctionNumOfSamplesMatches),
FuzzyFunctionNumOfSamplesMismatches(
FuzzyFunctionNumOfSamplesMismatches),
FuzzyFunctionSampleValid(FuzzyFunctionSampleValid),
FuzzyFunctionSampleInvalid(FuzzyFunctionSampleInvalid),
FuzzyFunctionNumOfSamplesValid(FuzzyFunctionNumOfSamplesValid),
FuzzyFunctionNumOfSamplesInvalid(FuzzyFunctionNumOfSamplesInvalid),
FuzzyFunctionSignalIsDrifting(FuzzyFunctionSignalIsDrifting),
FuzzyFunctionSignalIsStable(FuzzyFunctionSignalIsStable),
// SAVE CHANGES
FuzzyFunctionSignalConditionLookBack(
FuzzyFunctionSignalConditionLookBack),
FuzzyFunctionSignalConditionHistoryDesicion(
FuzzyFunctionSignalConditionHistoryDesicion),
DriftLookbackRange(DriftLookbackRange),
// - SAVE CHANGES
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()) {
// TODO: make soring inside of median
// TODO: make better outlier removal!
// std::sort(DAB.begin(), DAB.end());
// DAB.erase(DAB.begin(), DAB.begin() + 1);
// DAB.erase(DAB.end() - 1, DAB.end());
// PROCDATATYPE AvgOfDAB = DAB.template median<PROCDATATYPE>();
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();
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 =
DistanceMetric(std::make_pair(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)));
}
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(
DistanceMetric(std::make_pair(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)));
}
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(
DistanceMetric(std::make_pair(Sample, HistorySample))));
HighestConfidenceMismatching =
fuzzyOR(HighestConfidenceMismatching,
FuzzyFunctionSampleMismatches(
DistanceMetric(std::make_pair(Sample, HistorySample))));
}
LowestConfidenceMatchingHistory.addEntry(LowestConfidenceMatching);
HighestConfidenceMismatchingHistory.addEntry(HighestConfidenceMismatching);
LowestConfidenceMatching = LowestConfidenceMatchingHistory.lowestEntry();
HighestConfidenceMismatching =
HighestConfidenceMismatchingHistory.highestEntry();
SignalStateInfo.ConfidenceStateIsValid =
fuzzyAND(LowestConfidenceMatching,
FuzzyFunctionNumOfSamplesValid(static_cast<INDATATYPE>(
SignalStateInfo.NumberOfInsertedSamplesAfterEntrance)));
SignalStateInfo.ConfidenceStateIsInvalid =
fuzzyOR(HighestConfidenceMismatching,
FuzzyFunctionNumOfSamplesInvalid(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) {
/*
std::cout << "LookbackTest: " << std::endl;
for (unsigned int t = 1; t <= DriftLookbackRange + 5; t++) {
std::cout << "t=" << t
<< " -> c=" << FuzzyFunctionSignalConditionLookBack(t)
<< std::endl;
//(*FuzzyFunctionTimeSystemFunctioning)(
// static_cast<INDATATYPE>(TimeOfDisparity));
}
getchar();
*/
SignalStateInfo.ConfidenceStateIsStable = 0;
SignalStateInfo.ConfidenceStateIsDrifting = 0;
/*
std::cout << "ConfidenceStateIsStable (before): "
<< SignalStateInfo.ConfidenceStateIsStable << std::endl;
std::cout << "ConfidenceStateIsDrifting (before): "
<< SignalStateInfo.ConfidenceStateIsDrifting << std::endl;
*/
bool DriftDirectionIsUp = true;
if (DABHistory.numberOfEntries() >= 2) {
// SAVE CHANGES
INDATATYPE CurrentDAB = DABHistory[DABHistory.numberOfEntries() - 1];
INDATATYPE DAB2Compare = DABHistory[0];
// ########### TODO HERE: calculating up_down
uint32_t DriftDnCounter = 0;
uint32_t DriftUpCounter = 0;
// EXPERIMENTING
for (unsigned int t = 1;
t <= DriftLookbackRange && t < DABHistory.numberOfEntries(); t++) {
DAB2Compare = DABHistory[DABHistory.numberOfEntries() - (t + 1)];
// TODO: make the following also for distance measurement when comparing
// sample with state and validate state
-
+ /*
+ // sigma correction
if (NormalizedDistanceMetric<INDATATYPE, PROCDATATYPE>
*NormalizableDistanceMetric = dynamic_cast<
NormalizedDistanceMetric<INDATATYPE, PROCDATATYPE> *>(
DistanceMetric)) {
// old was safely casted to NewType
- // NormalizableDistanceMetric->setNorm(/* TODO: (1) Sigma von Sample
- // History(!) abholen, (2) irgendwas mit Sigma hier reinschreiben, und
- // (3) überlegen wegen zweiter History (länger) für Sigmaberechnung*/);
+ NormalizableDistanceMetric->setNorm(
+ // TODO: (1) Sigma von Sample
+ // History(!) abholen, (2) irgendwas mit Sigma hier reinschreiben,
+ // und (3) überlegen wegen zweiter History (länger) für
+ // Sigmaberechnung
+ );
}
+ */
float dist = DistanceMetric(std::make_pair(CurrentDAB, DAB2Compare));
+ // AVG
+ SignalStateInfo.ConfidenceStateIsStable +=
+ FuzzyFunctionSignalIsStable(dist);
+ SignalStateInfo.ConfidenceStateIsDrifting +=
+ FuzzyFunctionSignalIsDrifting(dist);
+ // TODO: move following outside of the loop with
+ // "if(DriftLookbackRange<=DABHistory.numberOfEntries())"
+ if (t == DriftLookbackRange) {
+ SignalStateInfo.ConfidenceStateIsStable /= DriftLookbackRange;
+ } else if (t == DABHistory.numberOfEntries() - 1) {
+ SignalStateInfo.ConfidenceStateIsStable /=
+ DABHistory.numberOfEntries();
+ }
+
+ /*
// AND
SignalStateInfo.ConfidenceStateIsStable =
fuzzyOR(SignalStateInfo.ConfidenceStateIsStable,
fuzzyAND(FuzzyFunctionSignalIsStable(dist),
FuzzyFunctionSignalConditionLookBack(t)));
SignalStateInfo.ConfidenceStateIsDrifting =
fuzzyOR(SignalStateInfo.ConfidenceStateIsDrifting,
fuzzyAND(FuzzyFunctionSignalIsDrifting(dist),
FuzzyFunctionSignalConditionLookBack(t)));
-
+ */
/*
// MULTI
SignalStateInfo.ConfidenceStateIsStable =
fuzzyOR(SignalStateInfo.ConfidenceStateIsStable,
FuzzyFunctionSignalIsStable(
relativeDistance<INDATATYPE, PROCDATATYPE>(
CurrentDAB, DAB2Compare)) *
FuzzyFunctionSignalConditionLookBack(t));
SignalStateInfo.ConfidenceStateIsDrifting =
fuzzyOR(SignalStateInfo.ConfidenceStateIsDrifting,
FuzzyFunctionSignalIsDrifting(
relativeDistance<INDATATYPE, PROCDATATYPE>(
CurrentDAB, DAB2Compare)) *
FuzzyFunctionSignalConditionLookBack(t));
*/
if (CurrentDAB > DAB2Compare)
DriftUpCounter++;
else if (CurrentDAB < DAB2Compare)
DriftDnCounter++;
}
// TODO: change something because it is biased if the are equal
DriftDirectionIsUp = DriftUpCounter > DriftDnCounter;
// following outcommented block was the published code
/*
SignalStateInfo.ConfidenceStateIsStable =
FuzzyFunctionSignalIsStable(
relativeDistance<INDATATYPE, PROCDATATYPE>(CurrentDAB,
DAB2Compare));
SignalStateInfo.ConfidenceStateIsDrifting =
FuzzyFunctionSignalIsDrifting(
relativeDistance<INDATATYPE, PROCDATATYPE>(CurrentDAB,
DAB2Compare));
// TODO: think about a better solution with different confidences
// (stable, up, down, ...)
DriftDirectionIsUp = CurrentDAB > DAB2Compare;
*/
// - SAVE CHANGES
}
/*
std::cout << "ConfidenceStateIsStable (after): "
<< SignalStateInfo.ConfidenceStateIsStable << std::endl;
std::cout << "ConfidenceStateIsDrifting (after): "
<< SignalStateInfo.ConfidenceStateIsDrifting << std::endl;
-*/
+ */
if (SignalStateInfo.ConfidenceStateIsStable >
SignalStateInfo.ConfidenceStateIsDrifting) {
SignalStateInfo.StateCondition = StateConditions::STABLE;
} else if (SignalStateInfo.ConfidenceStateIsStable <
SignalStateInfo.ConfidenceStateIsDrifting) {
if (DriftDirectionIsUp) {
SignalStateInfo.StateCondition = StateConditions::DRIFTING_UP;
} else {
SignalStateInfo.StateCondition = StateConditions::DRIFTING_DN;
}
/*
SignalStateInfo.StateCondition = StateConditions::DRIFTING;
*/
} else {
SignalStateInfo.StateCondition = StateConditions::UNKNOWN;
}
}
-};
+}; // namespace agent
-} // End namespace agent
+} // namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SIGNALSTATE_HPP
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jul 4, 5:37 AM (9 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157475
Default Alt Text
(46 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment