| //+------------------------------------------------------------------+
|
| //| 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;
|
| }
|
| //+------------------------------------------------------------------+
|