/*
How to use it?
Probably you are wondering how to use this FuzzyLogic API. It's not so complicated. For making your life easier, I have made three simple examples. The first one is for a Fuzzy Cruise Control, the second for a basketball player, and the last one for a ski jumper. All examples are in the class called CExperiments. Let's see the simple basketball player example. We create three linguistic variables, then we add linguistic values to the linguistic variables. With the linguistic variables, we create two rules and add the rules to FuzzyLogic.
*/
void BuildBasketballPlayersRules()
{
//Method for building necessary rules for Basketball players
CLinguisticVariable *height = new CLinguisticVariable(false,"Height");
CLinguisticVariable *age = new CLinguisticVariable(false,"Age");
CLinguisticVariable *basketball_player =
new CLinguisticVariable(true,"Basketball_player");
//Add linguistic values to variable
height->AddLinguisticValue(new LinguisticValue("Low_height",150,150,170,180));
height->AddLinguisticValue(new LinguisticValue("Average_height",170,180,185,190));
height->AddLinguisticValue(new LinguisticValue("Tall",185,195,210,210));
age->AddLinguisticValue(new LinguisticValue("Young",10,10,25,30));
age->AddLinguisticValue(new LinguisticValue("Average_young",25,35,40,45));
age->AddLinguisticValue(new LinguisticValue("Old",50,60,80,80));
age->AddLinguisticValue(new LinguisticValue("Average_old",40,45,50,55));
basketball_player->AddLinguisticValue(new LinguisticValue("Suitable",0.5,0.6,1,1));
basketball_player->AddLinguisticValue(new LinguisticValue("Unsuitable ",0,0,0.4,0.5));
//Rule1
//IF age = Young AND height = Tall THEN basketball_player = "Suitable"
CFuzzyRule* rule1 = new CFuzzyRule();
rule1->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, age,"Young"));
rule1->AddTokenToRule(new CFuzzyRuleToken(false,AND, height,"Tall"));
rule1->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, basketball_player,"Suitable"));
//Rule2
//IF age = "Old" THEN basketball_player = "Unsuitable"
CFuzzyRule* rule2 = new CFuzzyRule();
rule2->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY, age,"Old"));
rule2->AddTokenToRule(new CFuzzyRuleToken(false,EMPTY,
basketball_player,"Unsuitable "));
//Add rules
fr->AddFuzzyRule(rule1);
fr->AddFuzzyRule(rule2);
//Add linguistic variables, if you want to obtain
//more informations about fuzzy calculations
AddLinguisticVariables(height);
AddLinguisticVariables(age);
AddLinguisticVariables(basketball_player);
}
/*
How to execute the example
With the next sample you should understand how to use the class CExperiment.
*/
int _tmain(int argc, _TCHAR* argv[])
{
//Create instance of CExperiments.
CExperiments* experiment = new CExperiments();
//Create rules
experiment->BuildCruiseControlRules();
//Hash_map for storing inputs
hash_map <string, CFuzzyInput*> h_fuzzyInputs;
//Put some values to inputs
CFuzzyInput* inputRazdalja = new CFuzzyInput("Distance", 1.

;
CFuzzyInput* inputPriblizevanje = new CFuzzyInput("Approaching", 15);
CFuzzyInput* inputHitrost = new CFuzzyInput("Speed", -8);
//Insert inputs to the hash_map
h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputRazdalja->GetVariableName(), inputRazdalja));
h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputPriblizevanje->GetVariableName(), inputPriblizevanje));
h_fuzzyInputs.insert(CFuzzyInput_Pairs(inputHitrost->GetVariableName(), inputHitrost));
//Calculate fuzzy Logic output signal
double outputSignal = experiment->CalculateFuzzyRules(h_fuzzyInputs);
//Get some additional informations from fuzzy logic
double t = experiment->GetC_ByName("Distance","Average");
double v1 = experiment->GetLinguisticVariableValue("Signal","Brake");
double v2 = experiment->GetLinguisticVariableValue("Signal","Maintain");
double v3 = experiment->GetLinguisticVariableValue("Signal","Accelerate");
double v4 = experiment->GetLinguisticVariableValue("Distance","Low");
double v5 = experiment->GetLinguisticVariableValue("Distance","Average");
double v6 = experiment->GetLinguisticVariableValue("Distance","High");
double v7 = experiment->GetLinguisticVariableValue("Approaching","Slow");
double v8 = experiment->GetLinguisticVariableValue("Approaching","Average");
double v9 = experiment->GetLinguisticVariableValue("Approaching","Fast");
double v10 = experiment->GetLinguisticVariableValue("Speed","Slow");
double v11 = experiment->GetLinguisticVariableValue("Speed","Acceptable");
double v12 = experiment->GetLinguisticVariableValue("Speed","Fast");
//YOU HAVE TO RESET TOKEN VALUES BEFORE NEW CALCULATIONS!!!
experiment->ResetTokenValues();
delete experiment;
return 0;
}
/*
Linguistic_Variable_Name Input/Output ValueName_0 (A,B,C,D) ValueName_N (A,B,C,D)
and rules:
*/
IF Linguistic_Variable_Name = Linguistic_Value_Name AND ...
AND Linguistic_Variable_Name NOT Linguistic_Value_Name THEN
Linguistic_Variable_Name = Linguistic_Value_Name
void Parse(char* filePath)
{
ifstream ifs(filePath);
string line;
while( getline( ifs, line ) )
{
vector<string> tokens = SplitBy(line,' ');
//Skip lines without text
if(tokens.size() > 0)
{
//Skip comments
if(!IsComment(tokens[0]))
{
if(IsRule(tokens[0]))
ParseFuzzyRule(tokens);
else
ParseFuzzyAtribute(tokens);
}
}
}
//Close stream
ifs.close();
}
bool IsRule(string token)
{
//Return true if is rule
if(token == "IF")
return true;
return false;
}
/*
How do we parse rules and attributes? Check the next two simple methods. ParseFuzzyRule just goes over all tokens (we don't need to process the first token, its should be "IF") and check if it is an operator token (AND / OR) and set the appropriate operation. Then we check if there is negation or we are on the "set" (token "="). If this condition is true, we just have to set the previous and next token, create a new CFuzzyRuleToken, and add it to the rule.
*/
void ParseFuzzyRule(vector<string> ruleTokens)
{
//Rule example
//IF distance = low AND approaching NOT slow THEN signal=breake
//SKIP IF token
bool negated = false;
string leftSide;
string rightSide;
Operation operation = EMPTY;
CFuzzyRule* rule = new CFuzzyRule();
for(unsigned int i = 1; i < ruleTokens.size(); i++)
{
//Check for operator
//OPERATORS =, Operator(AND, OR), NOT, THEN
if((ruleTokens
== "AND") || (ruleTokens == "OR"))
{
if(ruleTokens == "AND")
operation = AND;
else
operation = OR;
}
else if((ruleTokens == "=") || (ruleTokens == "NOT"))
{
leftSide = ruleTokens[i - 1];
//Next token is right side
if(ruleTokens == "NOT")
negated = true;
rightSide = ruleTokens[++i];
//ADD TOKEN TO RULE
CLinguisticVariable* linVar =
fuzzyInterface->FindLinguisticVariableByName(leftSide);
assert(linVar != NULL);
rule->AddTokenToRule(
new CFuzzyRuleToken(negated,operation,linVar,rightSide));
//RESET
operation = EMPTY;
negated = false;
}
}
fuzzyInterface->AddFuzzyRule(rule);
}
/*
Now, parsing the attributes. The first token is always the linguistic variable name, the second token should be information of the attribute. There can be N linguistic values. We have to go over all tokens and parsing is Input or Output. With that information, we can create CLinguisticVariable. Then we can start to parse the linguistic values. We have to go over all the remaining tokens. The next token has to be the linguistic value name, followed by the linguistic values (method ParseLinguisticValues). When all linguistic values are parsed, we can add LinguisticVariable to the list (in CExperiment).
*/
void ParseFuzzyAtribute(vector<string> attTokens)
{
//Distance Input Low (0,0,1,2) Average (1,2,3,4) High (3,4,5,5)
//Linguistic variable name
//Input or output
//Linguistic value name
//Values A,B,C,D
string linguisticVariableName = attTokens.at(0);
bool output = true;
if(attTokens.at(1) == "Input")
output = false;
//Creating new linguistic variable
CLinguisticVariable *linguisticVariable =
new CLinguisticVariable(output,linguisticVariableName);
//Adding linguistic values to variable
for(unsigned int i = 2; i < attTokens.size(); i++)
{
string linguisticValueName = attTokens.at(i++);
vector<double> linguisticValues = ParseLinguisticValues(attTokens.at(i));
//Check for error!
assert(linguisticValues.size() == 4);
LinguisticValue* linValue = new LinguisticValue(linguisticValueName,
linguisticValues[0],
linguisticValues[1],
linguisticValues[2],
linguisticValues[3]);
linguisticVariable->AddLinguisticValue(linValue);
}
fuzzyInterface->AddLinguisticVariables(linguisticVariable);
}
vector<double> ParseLinguisticValues(string token)
{
vector<double> linguisticValues;
//Remove first and last char
token = token.erase(0,1);
token = token.erase(token.size() - 1, 1);
vector<string> values = SplitBy(token, ',');
//Values size should be 4!
for(unsigned int i = 0; i < values.size(); i++)
linguisticValues.push_back(strtod(values.at(i).c_str(),NULL));
return linguisticValues;
}
//Input file example
%ATTRIBUTES
Distance Input Low (0,0,1,2) Average (1,2,3,4) High (3,4,5,5)
Approaching Input Slow (0,0,10,20) Average (10,20,30,40) Fast (30,40,50,50)
Speed Input Slow (-50,-50,-10,0) Acceptable (-10,0,0,10) Fast (0,10,50,50)
Signal Output Brake (-5,-5,-2,-1) Maintain (-2,-1,1,2) Accelerate (1,2,5,5)
%RULES
/*
IF Distance = Low AND Approaching NOT Slow THEN Signal = Brake
IF Distance = Average AND Approaching = Fast THEN Signal = Brake
IF Speed = Fast THEN Signal = Brake
IF Distance NOT Low AND Approaching = Average THEN Signal = Maintain
IF Distance = High AND Approaching NOT Fast AND Speed = Acceptable THEN Signal = Maintain
IF Distance = Average AND Speed = Slow THEN Signal = Maintain
IF Distance = High AND Speed = Slow THEN Signal = Acc
*/