include/maths/common/CFuzzyLogic.h (61 lines of code) (raw):
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the following additional limitation. Functionality enabled by the
* files subject to the Elastic License 2.0 may only be used in production when
* invoked by an Elasticsearch process with a license key installed that permits
* use of machine learning features. You may not use this file except in
* compliance with the Elastic License 2.0 and the foregoing additional
* limitation.
*/
#ifndef INCLUDED_ml_maths_common_CFuzzyLogic_h
#define INCLUDED_ml_maths_common_CFuzzyLogic_h
#include <maths/common/ImportExport.h>
#include <maths/common/CTools.h>
#include <string>
namespace ml {
namespace maths {
namespace common {
//! \brief Fuzzy logical expression with multiplicative AND and OR.
//!
//! DESCRIPTION:\n
//! For more information see https://en.wikipedia.org/wiki/Fuzzy_logic#Fuzzy_logic_operators.
class MATHS_COMMON_EXPORT CFuzzyTruthValue {
public:
//! A value which satisfies (value || expression).boolean() == true.
static const CFuzzyTruthValue TRUE_VALUE;
//! A value which satisfies (value && expression).boolean() == false.
static const CFuzzyTruthValue FALSE_VALUE;
//! A value which satisfies value || expression == expression.
static const CFuzzyTruthValue OR_UNDETERMINED_VALUE;
//! A value which satisfies value && expression == expression.
static const CFuzzyTruthValue AND_UNDETERMINED_VALUE;
public:
CFuzzyTruthValue(double value = 0.5, double isTrueThreshold = 0.5)
: m_Value{value}, m_IsTrueThreshold{isTrueThreshold} {}
//! Check if this is less true than \p rhs.
bool operator<(const CFuzzyTruthValue& rhs) const {
return rhs.m_IsTrueThreshold * m_Value < m_IsTrueThreshold * rhs.m_Value;
}
//! Check if this is less true than or equal to \p rhs.
bool operator<=(const CFuzzyTruthValue& rhs) const {
return rhs.m_IsTrueThreshold * m_Value <= m_IsTrueThreshold * rhs.m_Value;
}
//! Get the decision.
bool boolean() const { return m_Value > m_IsTrueThreshold; }
//! Get the continuous truth value.
double value() const { return m_Value; }
//! Get the fuzzy AND of two expressions.
friend inline CFuzzyTruthValue operator&&(const CFuzzyTruthValue& lhs,
const CFuzzyTruthValue& rhs) {
return {lhs.m_Value * rhs.m_Value, lhs.m_IsTrueThreshold * rhs.m_IsTrueThreshold};
}
//! Get the fuzzy OR of two expressions.
friend inline CFuzzyTruthValue operator||(const CFuzzyTruthValue& lhs,
const CFuzzyTruthValue& rhs) {
// If possible rescale so both expressions have equal importance determining
// the expression truth value.
if (lhs.m_IsTrueThreshold < rhs.m_IsTrueThreshold && lhs.m_IsTrueThreshold > 0.0) {
double scale{lhs.m_IsTrueThreshold / rhs.m_IsTrueThreshold};
return {1.0 - (1.0 - lhs.m_Value) * (1.0 - scale * rhs.m_Value),
1.0 - (1.0 - lhs.m_IsTrueThreshold) * (1.0 - scale * rhs.m_IsTrueThreshold)};
}
if (rhs.m_IsTrueThreshold < lhs.m_IsTrueThreshold && rhs.m_IsTrueThreshold > 0.0) {
double scale{rhs.m_IsTrueThreshold / lhs.m_IsTrueThreshold};
return {1.0 - (1.0 - scale * lhs.m_Value) * (1.0 - rhs.m_Value),
1.0 - (1.0 - scale * lhs.m_IsTrueThreshold) * (1.0 - rhs.m_IsTrueThreshold)};
}
return {1.0 - (1.0 - lhs.m_Value) * (1.0 - rhs.m_Value),
1.0 - (1.0 - lhs.m_IsTrueThreshold) * (1.0 - rhs.m_IsTrueThreshold)};
}
//! Print the value.
std::string print() const {
return std::to_string(m_Value) + "/" + std::to_string(m_IsTrueThreshold);
}
private:
double m_Value;
double m_IsTrueThreshold;
};
//! Fuzzy check if \p value is greater than \p threshold.
//!
//! \param[in] value The value to compare to \p threshold.
//! \param[in] threshold The smallest true \p value.
//! \param[in] margin The fuzzyness expressed as the width of the logistic
//! function which defines the truth value of this expression.
inline CFuzzyTruthValue fuzzyGreaterThan(double value, double threshold, double margin) {
return {CTools::logisticFunction(value, margin, threshold, +1.0)};
}
//! Fuzzy check if \p value is less than \p threshold.
//!
//! \param[in] value The value to compare to \p threshold.
//! \param[in] threshold The smallest true \p value.
//! \param[in] margin The fuzzyness expressed as the width of the logistic
//! function which defines the truth value of this expression.
inline CFuzzyTruthValue fuzzyLessThan(double value, double threshold, double margin) {
return {CTools::logisticFunction(value, margin, threshold, -1.0)};
}
}
}
}
#endif // INCLUDED_ml_maths_common_CFuzzyLogic_h