Consolidate Python ignore rules into root gitignore
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| mandanifuzzysystem.mqh |
|
||||
//| Copyright 2000-2026, MetaQuotes Ltd. |
|
||||
//| 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 <Arrays\ArrayDouble.mqh>
|
||||
#include "GenericFuzzySystem.mqh"
|
||||
#include "InferenceMethod.mqh"
|
||||
#include "RuleParser.mqh"
|
||||
#include "FuzzyRule.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Creating Mamdani fuzzy system |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Mamdani fuzzy inference system |
|
||||
//+------------------------------------------------------------------+
|
||||
class CMamdaniFuzzySystem : public CGenericFuzzySystem
|
||||
{
|
||||
private:
|
||||
CList* m_output; // List of fuzzy variable
|
||||
CList* m_rules; // List of Mamdani fuzzy rule
|
||||
ImplicationMethod m_impl_method; // Implication method
|
||||
AggregationMethod m_aggr_method; // Aggregation method
|
||||
DefuzzificationMethod m_defuzz_method; // Defuzzification method
|
||||
|
||||
public:
|
||||
CMamdaniFuzzySystem(void);
|
||||
~CMamdaniFuzzySystem(void);
|
||||
//--- method gets the output linguistic variables
|
||||
CList* Output(void) { return(m_output); }
|
||||
//--- method gets the fuzzy rule
|
||||
CList* Rules(void) { return(m_rules); }
|
||||
//--- methods gets or sets the implication method
|
||||
ImplicationMethod GetImplicationMethod(void) const { return (m_impl_method); }
|
||||
void SetImplicationMethod(ImplicationMethod value) { m_impl_method=value; }
|
||||
//--- methods gets or sets the aggregation method
|
||||
AggregationMethod GetAggregationMethod(void) const { return (m_aggr_method); }
|
||||
void SetAggregationMethod(AggregationMethod value) { m_aggr_method=value; }
|
||||
//--- methods gets or sets the defuzzification method
|
||||
DefuzzificationMethod GetDefuzzificationMethod(void) const { return (m_defuzz_method); }
|
||||
void SetDefuzzificationMethod(DefuzzificationMethod value) { m_defuzz_method=value; }
|
||||
//--- maethod gets the variable by name
|
||||
CFuzzyVariable* OutputByName(const string name);
|
||||
//--- create a new rule
|
||||
CMamdaniFuzzyRule* EmptyRule(void);
|
||||
//--- parse rule
|
||||
CMamdaniFuzzyRule* ParseRule(const string rule);
|
||||
//--- method for calculate result
|
||||
CList* Calculate(CList *inputValues);
|
||||
CList* EvaluateConditions(CList *fuzzifiedInput);
|
||||
CList* Implicate(CList *conditions);
|
||||
CList* Aggregate(CList *conclusions);
|
||||
CList* Defuzzify(CList *fuzzyResult);
|
||||
double Defuzzify(IMembershipFunction *mf,const double min,const double max);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzySystem::CMamdaniFuzzySystem(void)
|
||||
{
|
||||
m_output = new CList;
|
||||
m_rules = new CList;
|
||||
m_impl_method = MinIpm; // Implication method default is Min
|
||||
m_aggr_method = MaxAgg; // Aggregation method default is Max
|
||||
m_defuzz_method = CentroidDef; // Defuzzification method default is Centroid
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzySystem::~CMamdaniFuzzySystem(void)
|
||||
{
|
||||
delete m_output;
|
||||
delete m_rules;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get output linguistic variable by its name |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyVariable *CMamdaniFuzzySystem::OutputByName(const string name)
|
||||
{
|
||||
for(int i=0; i<m_output.Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=m_output.GetNodeAtIndex(i);
|
||||
if(var.Name()==name)
|
||||
{
|
||||
//--- return varriable
|
||||
return (var);
|
||||
}
|
||||
}
|
||||
Print("Variable with that name is not found");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create new empty rule |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule *CMamdaniFuzzySystem::EmptyRule()
|
||||
{
|
||||
//--- return empty rule
|
||||
return new CMamdaniFuzzyRule();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Parse rule from the string |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule *CMamdaniFuzzySystem::ParseRule(const string rule)
|
||||
{
|
||||
//--- return Mamdani fuzzy rule
|
||||
return CRuleParser::Parse(rule, EmptyRule(), Input(), Output());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate output values |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Calculate(CList *inputValues)
|
||||
{
|
||||
//--- There should be one rule as minimum
|
||||
if(m_rules.Total()==0)
|
||||
{
|
||||
Print("There should be one rule as minimum.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//--- Fuzzification step
|
||||
CList *fuzzifiedInput=Fuzzify(inputValues);
|
||||
//--- Evaluate the conditions
|
||||
CList *evaluatedConditions=EvaluateConditions(fuzzifiedInput);
|
||||
//--- Do implication for each rule
|
||||
CList *implicatedConclusions=Implicate(evaluatedConditions);
|
||||
//--- Aggrerate the results
|
||||
CList *fuzzyResult=Aggregate(implicatedConclusions);
|
||||
//--- Defuzzify the result
|
||||
CList *result=Defuzzify(fuzzyResult);
|
||||
//---
|
||||
delete fuzzyResult;
|
||||
for(int i=0; i<implicatedConclusions.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=implicatedConclusions.GetNodeAtIndex(i);
|
||||
CCompositeMembershipFunction *composite=pair.Value();
|
||||
delete composite.MembershipFunctions().GetNodeAtIndex(0);
|
||||
delete composite;
|
||||
}
|
||||
delete implicatedConclusions;
|
||||
delete evaluatedConditions;
|
||||
for(int i=0; i<fuzzifiedInput.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=fuzzifiedInput.GetNodeAtIndex(i);
|
||||
delete pair.Value();
|
||||
}
|
||||
delete fuzzifiedInput;
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Evaluate conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::EvaluateConditions(CList *fuzzifiedInput)
|
||||
{
|
||||
CList *result=new CList;
|
||||
for(int i=0; i<Rules().Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_rd=new CDictionary_Obj_Double;
|
||||
CMamdaniFuzzyRule *rule=Rules().GetNodeAtIndex(i);
|
||||
p_rd.SetAll(rule,EvaluateCondition(rule.Condition(),fuzzifiedInput));
|
||||
result.Add(p_rd);
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implicate rule results |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Implicate(CList *conditions)
|
||||
{
|
||||
CList *conclusions=new CList;
|
||||
for(int i=0; i<conditions.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_rd=conditions.GetNodeAtIndex(i);
|
||||
CMamdaniFuzzyRule *rule=p_rd.Key();
|
||||
MfCompositionType compType;
|
||||
switch(m_impl_method)
|
||||
{
|
||||
case MinIpm :
|
||||
{
|
||||
compType=MinMF;
|
||||
break;
|
||||
}
|
||||
case ProductionImp :
|
||||
{
|
||||
compType=ProdMF;
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
Print("Internal error.");
|
||||
//---
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
CFuzzyTerm *val=rule.Conclusion().Term();
|
||||
IMembershipFunction *first_fun=new CConstantMembershipFunction(p_rd.Value());
|
||||
IMembershipFunction *second_fun=val.MembershipFunction();
|
||||
CCompositeMembershipFunction *resultMF=new CCompositeMembershipFunction(compType,first_fun,second_fun);
|
||||
CDictionary_Obj_Obj *p_rf=new CDictionary_Obj_Obj;
|
||||
p_rf.SetAll(rule,resultMF);
|
||||
conclusions.Add(p_rf);
|
||||
}
|
||||
//--- return conclusions
|
||||
return (conclusions);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Aggregate results |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Aggregate(CList *conclusions)
|
||||
{
|
||||
CList *fuzzyResult=new CList;
|
||||
for(int i=0; i<Output().Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=Output().GetNodeAtIndex(i);
|
||||
CList *mfList=new CList;
|
||||
for(int j=0; j<conclusions.Total(); j++)
|
||||
{
|
||||
CDictionary_Obj_Obj *p_rf=conclusions.GetNodeAtIndex(j);
|
||||
CMamdaniFuzzyRule *rule=p_rf.Key();
|
||||
if(rule.Conclusion().Var()==var)
|
||||
{
|
||||
mfList.Add(p_rf.Value());
|
||||
}
|
||||
}
|
||||
MfCompositionType composType;
|
||||
switch(m_aggr_method)
|
||||
{
|
||||
case MaxAgg:
|
||||
composType=MaxMF;
|
||||
break;
|
||||
case SumAgg:
|
||||
composType=SumMF;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Print("Internal exception.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
CDictionary_Obj_Obj *p_vf=new CDictionary_Obj_Obj;
|
||||
CCompositeMembershipFunction *func=new CCompositeMembershipFunction(composType,mfList);
|
||||
p_vf.SetAll(var,func);
|
||||
fuzzyResult.Add(p_vf);
|
||||
}
|
||||
//--- return result
|
||||
return (fuzzyResult);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate crisp result for each rule |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Defuzzify(CList *fuzzyResult)
|
||||
{
|
||||
CList *crispResult=new CList;
|
||||
for(int i=0; i<fuzzyResult.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=new CDictionary_Obj_Double;
|
||||
CDictionary_Obj_Obj *p_vf=fuzzyResult.GetNodeAtIndex(i);
|
||||
CFuzzyVariable *var=p_vf.Key();
|
||||
p_vd.SetAll(var,Defuzzify(p_vf.Value(),var.Min(),var.Max()));
|
||||
crispResult.Add(p_vd);
|
||||
}
|
||||
//--- return result
|
||||
return (crispResult);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Helpers |
|
||||
//+------------------------------------------------------------------+
|
||||
double CMamdaniFuzzySystem::Defuzzify(IMembershipFunction *mf,const double min,const double max)
|
||||
{
|
||||
if(m_defuzz_method==CentroidDef)
|
||||
{
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate a center of gravity as integral |
|
||||
//+------------------------------------------------------------------+
|
||||
double ptLeft=0.0;
|
||||
double ptCenter= 0.0;
|
||||
double ptRight = 0.0;
|
||||
double valLeft=0.0;
|
||||
double valCenter= 0.0;
|
||||
double valRight = 0.0;
|
||||
double val2Left=0.0;
|
||||
double val2Center= 0.0;
|
||||
double val2Right = 0.0;
|
||||
double numerator=0.0;
|
||||
double denominator=0.0;
|
||||
for(int i=0; i<k; i++)
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
ptRight=min;
|
||||
valRight=mf.GetValue(ptRight);
|
||||
val2Right=ptRight*valRight;
|
||||
}
|
||||
ptLeft=ptRight;
|
||||
ptCenter= min+step *((double)i+0.5);
|
||||
ptRight = min+step *(i+1);
|
||||
valLeft=valRight;
|
||||
valCenter= mf.GetValue(ptCenter);
|
||||
valRight = mf.GetValue(ptRight);
|
||||
val2Left=val2Right;
|
||||
val2Center= ptCenter * valCenter;
|
||||
val2Right = ptRight * valRight;
|
||||
numerator+=step *(val2Left+4*val2Center+val2Right)/3.0;
|
||||
denominator+=step *(valLeft+4*valCenter+valRight)/3.0;
|
||||
}
|
||||
delete mf;
|
||||
if(denominator!=0)
|
||||
{
|
||||
//--- return result
|
||||
return (numerator / denominator);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- return NAN
|
||||
return (MathLog(-1));
|
||||
}
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==BisectorDef)
|
||||
{
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
//| The method Bisector consists in finding the point on the abscissa, |
|
||||
//| which divides the area under the curve of the membership function in two equal parts|
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
double Area=0.0; // The area under the function
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
for(int i=0; i<k; i++)
|
||||
{
|
||||
Area+=mf.GetValue(now);
|
||||
now=now+(max-min)/k;
|
||||
}
|
||||
now=min;
|
||||
double halfArea=fabs(Area/2-mf.GetValue(min));
|
||||
Area=0.0;
|
||||
while(true)
|
||||
{
|
||||
Area+=mf.GetValue(now);
|
||||
if(Area>=halfArea)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now=now+(max-min)/k;
|
||||
}
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==AverageMaximumDef)
|
||||
{
|
||||
//+------------------------------------------------------------------------------------------+
|
||||
//| AverageMaximum method is the arithmetic mean of all the maxima of the membership function|
|
||||
//+------------------------------------------------------------------------------------------+
|
||||
double sum_max=0; // Sum of local maxima
|
||||
double count_max=0; // Count of local maxima
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
sum_max+=mf.GetValue(min);
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
sum_max+=mf.GetValue(max);
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
sum_max+=point_1;
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
if(count_max==0)
|
||||
{
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (sum_max/count_max);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==LargestMaximumDef)
|
||||
{
|
||||
CArrayDouble *local_max=new CArrayDouble; // Array of all local maximum
|
||||
double result; // Result of defuzzification method
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(min));
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(max));
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
local_max.Add(point_1);
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
result=local_max.At(0);
|
||||
for(int i=0; i<local_max.Total(); i++)
|
||||
{
|
||||
if(result<=local_max.At(i))
|
||||
{
|
||||
result=local_max.At(i);
|
||||
}
|
||||
}
|
||||
now=min;
|
||||
while(true)
|
||||
{
|
||||
if(mf.GetValue(now)==result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
delete local_max;
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==SmallestMaximumDef)
|
||||
{
|
||||
CArrayDouble *local_max=new CArrayDouble; // Array of all local maximum
|
||||
double result; // Result of defuzzification method
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(min));
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(max));
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
local_max.Add(point_1);
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
result=local_max.At(0);
|
||||
for(int i=0; i<local_max.Total(); i++)
|
||||
{
|
||||
if(result>=local_max.At(i))
|
||||
{
|
||||
result=local_max.At(i);
|
||||
}
|
||||
}
|
||||
now=min;
|
||||
while(true)
|
||||
{
|
||||
if(mf.GetValue(now)==result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
delete local_max;
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal exception.");
|
||||
delete mf;
|
||||
//--- return
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user