MobinMQL/Include/Math/Fuzzy/fuzzyrule.mqh
2025-07-22 14:47:41 +03:00

371 lines
17 KiB
MQL5

//+------------------------------------------------------------------+
//| fuzzyrule.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
//| |
//| The features of the library include: |
//| - Create Mamdani fuzzy model |
//| - Create Sugeno fuzzy model |
//| - Normal membership function |
//| - Triangular membership function |
//| - Trapezoidal membership function |
//| - Constant membership function |
//| - Defuzzification method of center of gravity (COG) |
//| - Defuzzification method of bisector of area (BOA) |
//| - Defuzzification method of mean of maxima (MeOM) |
//| |
//| This file is free software; you can redistribute it and/or |
//| modify it under the terms of the GNU General Public License as |
//| published by the Free Software Foundation (www.fsf.org); either |
//| version 2 of the License, or (at your option) any later version. |
//| |
//| This program is distributed in the hope that it will be useful, |
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
//| GNU General Public License for more details. |
//+------------------------------------------------------------------+
#include <Arrays\List.mqh>
#include "FuzzyVariable.mqh"
#include "InferenceMethod.mqh"
//+------------------------------------------------------------------+
//| Purpose: Creating fuzzy rules |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| And/Or operator type |
//+------------------------------------------------------------------+
enum OperatorType
{
And, // And operator
Or // Or operator
};
//+------------------------------------------------------------------+
//| Hedge modifiers |
//+------------------------------------------------------------------+
enum HedgeType
{
None, // None
Slightly, // Cube root
Somewhat, // Square root
Very, // Square
Extremely // Cube
};
//+------------------------------------------------------------------+
//| Class of CConditions used in the 'if' expression |
//+------------------------------------------------------------------+
class ICondition : public CObject
{
public:
//--- method to check type
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_ICondition); }
};
//+------------------------------------------------------------------+
//| Single condition |
//+------------------------------------------------------------------+
class CSingleCondition : public ICondition
{
private:
INamedVariable *m_var; // Type of variable
INamedValue *m_term; // Type of value
bool m_not; // Is MF inverted
public:
CSingleCondition(void);
CSingleCondition(INamedVariable *var,INamedValue *term);
CSingleCondition(INamedVariable *var,INamedValue *term,bool not);
~CSingleCondition(void);
//--- methods gets or sets the varriable
INamedVariable *Var(void) { return(m_var); }
void Var(INamedVariable *value) { m_var=value; }
//--- methods gets or sets mark "Is MF inverted"
bool Not(void) { return(m_not); }
void Not(bool not) { m_not=not; }
//--- methods gets or sets term in expression
INamedValue *Term(void) { return(m_term); }
void Term(INamedValue *value) { m_term=value; }
//--- method to check type
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_SingleCondition); }
};
//+------------------------------------------------------------------+
//| Constructor without parameters |
//+------------------------------------------------------------------+
CSingleCondition::CSingleCondition(void)
{
m_var = NULL;
m_not = false;
m_term=NULL;
};
//+------------------------------------------------------------------+
//| First constructor with parameters |
//+------------------------------------------------------------------+
CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term)
{
m_var=var;
m_term=term;
}
//+------------------------------------------------------------------+
//| Second constructor with parameters |
//+------------------------------------------------------------------+
CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term,bool not)
{
m_var=var;
m_term=term;
m_not=not;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSingleCondition::~CSingleCondition(void)
{
if(CheckPointer(m_var)==POINTER_DYNAMIC)
delete m_var;
if(CheckPointer(m_term)==POINTER_DYNAMIC)
delete m_term;
}
//+------------------------------------------------------------------+
//| Condition of fuzzy rule for the both Mamdani and Sugeno systems |
//+------------------------------------------------------------------+
class CFuzzyCondition : public CSingleCondition
{
private:
HedgeType m_hedge; // hedge type
public:
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not);
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge);
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term);
~CFuzzyCondition(void);
//--- methods gets or sets the hedge type
HedgeType Hedge(void) { return (m_hedge); }
void Hedge(HedgeType value) { m_hedge=value; }
//--- method to check type
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_FuzzyCondition); }
};
//+------------------------------------------------------------------+
//| First constructor with parameters |
//+------------------------------------------------------------------+
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not)
{
CSingleCondition::Var(var);
CSingleCondition::Term(term);
CSingleCondition::Not(not);
m_hedge=None;
}
//+------------------------------------------------------------------+
//| Second constructor with parameters |
//+------------------------------------------------------------------+
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge)
{
CSingleCondition::Var(var);
CSingleCondition::Term(term);
CSingleCondition::Not(not);
m_hedge=hedge;
}
//+------------------------------------------------------------------+
//| Thrid constructor with parameters |
//+------------------------------------------------------------------+
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term)
{
CSingleCondition::Var(var);
CSingleCondition::Term(term);
CSingleCondition::Not(false);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFuzzyCondition::~CFuzzyCondition(void)
{
}
//+------------------------------------------------------------------+
//| Several CConditions linked by or/and operators |
//+------------------------------------------------------------------+
class CConditions : public ICondition
{
private:
bool m_not; // Default : false
OperatorType m_op; // Type of operator. Default : And
CList *m_conditions; // List of CConditions
public:
CConditions(void);
~CConditions(void);
//--- methods gets or sets the mark "Is MF inverted"
bool Not(void) { return(m_not); }
void Not(bool value) { m_not=value; }
//--- methods gets or sets operator that links expressions (and/or)
OperatorType Op(void) { return (m_op); }
void Op(OperatorType value) { m_op=value; }
//--- method gets the list of CConditions (single or multiples)
CList *ConditionsList(void) { return(m_conditions); }
//--- method to check type
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_Conditions); }
};
//+------------------------------------------------------------------+
//| Constructor without parameters |
//+------------------------------------------------------------------+
CConditions::CConditions(void)
{
m_not=false;
m_op = And;
m_conditions=new CList;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CConditions::~CConditions(void)
{
delete m_conditions;
}
//+------------------------------------------------------------------+
//| Class used by rule parser |
//+------------------------------------------------------------------+
class IParsableRule : public CObject
{
public:
//--- methods gets or sets the condition (IF) part of the rule
virtual CConditions *Condition(void) { return(NULL); }
virtual void Condition(CConditions *value) { }
//--- methods gets or sets the conclusion (THEN) part of the rule
virtual CSingleCondition *Conclusion(void) { return(NULL); }
virtual void Conclusion(CSingleCondition *value) { }
//--- method to check type
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_IParsableRule); }
};
//+------------------------------------------------------------------+
//| Implements common functionality of fuzzy rules |
//+------------------------------------------------------------------+
class CGenericFuzzyRule : public IParsableRule
{
private:
CConditions *m_generic_condition; // Generic path of condition
public:
CGenericFuzzyRule(void);
~CGenericFuzzyRule(void);
//--- methods gets or sets the condition (IF) part of the rule
CConditions *Condition(void) { return(m_generic_condition); }
void Condition(CConditions *value) { m_generic_condition=value; }
//--- methods create a single condition
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term);
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not);
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge);
//--- methods gets or sets the conclusion (THEN) part of the rule
virtual CSingleCondition *Conclusion(void) { return(NULL); }
virtual void Conclusion(CSingleCondition *value) { }
//--- method to check type
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_GenericFuzzyRule); }
};
//+------------------------------------------------------------------+
//| Constructor without parameters |
//+------------------------------------------------------------------+
CGenericFuzzyRule::CGenericFuzzyRule(void)
{
m_generic_condition=new CConditions();
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CGenericFuzzyRule::~CGenericFuzzyRule(void)
{
delete m_generic_condition;
}
//+------------------------------------------------------------------+
//| Create a single condition(1) |
//+------------------------------------------------------------------+
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term)
{
//--- return fuzzy condition
return new CFuzzyCondition(var, term);
}
//+------------------------------------------------------------------+
//| Create a single condition(2) |
//+------------------------------------------------------------------+
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not)
{
//--- return fuzzy condition
return new CFuzzyCondition(var, term, not);
}
//+------------------------------------------------------------------+
//| Create a single condition(3) |
//+------------------------------------------------------------------+
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge)
{
//--- return fuzzy condition
return new CFuzzyCondition(var, term, not, hedge);
}
//+------------------------------------------------------------------+
//| Fuzzy rule for Mamdani fuzzy system. |
//| NOTE: a rule cannot be created directly, only via |
//| MamdaniFuzzySystem::EmptyRule or MamdaniFuzzySystem::ParseRule |
//+------------------------------------------------------------------+
class CMamdaniFuzzyRule : public CGenericFuzzyRule
{
private:
CSingleCondition *m_mamdani_conclusion; // Mamdani conclusion
double m_weight; // Weight of Mamdani rule
public:
CMamdaniFuzzyRule(void);
~CMamdaniFuzzyRule(void);
//--- methods gets or sets the conclusion (THEN) part of the rule
CSingleCondition *Conclusion(void) { return(m_mamdani_conclusion); }
void Conclusion(CSingleCondition *value) { m_mamdani_conclusion=value; }
//--- methods gets or sets the rule weight
double Weight(void) { return(m_weight); }
void Weight(const double value) { m_weight=value; }
//--- method to check type
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_MamdaniFuzzyRule); }
};
//+---------------------------------------------------------------+
//| Constructor without parameters |
//+---------------------------------------------------------------+
CMamdaniFuzzyRule::CMamdaniFuzzyRule(void)
{
m_weight=1.0;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CMamdaniFuzzyRule::~CMamdaniFuzzyRule(void)
{
if(CheckPointer(m_mamdani_conclusion)==POINTER_DYNAMIC)
delete m_mamdani_conclusion;
}
//+------------------------------------------------------------------+
//| Fuzzy rule for Sugeno fuzzy system |
//| NOTE: a rule cannot be created directly, only via |
//| SugenoFuzzySystem::EmptyRule or SugenoFuzzySystem::ParseRule |
//+------------------------------------------------------------------+
class CSugenoFuzzyRule : public CGenericFuzzyRule
{
private:
CSingleCondition *m_sugeno_conclusion; // Sugeno conclusion
public:
CSugenoFuzzyRule(void);
~CSugenoFuzzyRule(void);
//--- methods gets or sets the conclusion (THEN) part of the rule
CSingleCondition *Conclusion(void) { return(m_sugeno_conclusion); }
void Conclusion(CSingleCondition *value) { m_sugeno_conclusion=value; }
//--- method to check type
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_SugenoFuzzyRule); }
};
//+------------------------------------------------------------------+
//| Constructor without parameters |
//+-------------------------- ---------------------------------------+
CSugenoFuzzyRule::CSugenoFuzzyRule(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSugenoFuzzyRule::~CSugenoFuzzyRule(void)
{
if(CheckPointer(m_sugeno_conclusion)==POINTER_DYNAMIC)
delete m_sugeno_conclusion;
}
//+------------------------------------------------------------------+