371 lines
17 KiB
MQL5
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;
| |||
}
| |||
//+------------------------------------------------------------------+
|