/// <summary> /// Executes the fuzzy inference, obtaining the <see cref="FuzzyOutput"/> of the system for the required /// <see cref="LinguisticVariable"/>. /// </summary> /// /// <param name="variableName">Name of the <see cref="LinguisticVariable"/> to evaluate.</param> /// /// <returns>A <see cref="FuzzyOutput"/> containing the fuzzy output of the system for the /// <see cref="LinguisticVariable"/> specified in <paramref name="variableName"/>.</returns> /// /// <exception cref="KeyNotFoundException">The variable indicated was not found in the database.</exception> /// public FuzzyOutput ExecuteInference(string variableName) { // gets the variable LinguisticVariable lingVar = database.GetVariable(variableName); // object to store the fuzzy output FuzzyOutput fuzzyOutput = new FuzzyOutput(lingVar); // select only rules with the variable as output Rule[] rules = rulebase.GetRules( ); foreach (Rule r in rules) { if (r.Output.Variable.Name == variableName) { string labelName = r.Output.Label.Name; float firingStrength = r.EvaluateFiringStrength( ); if (firingStrength > 0) { fuzzyOutput.AddOutput(labelName, firingStrength); } } } // returns the fuzzy output obtained return(fuzzyOutput); }
/// <summary> /// Initializes a new instance of the <see cref="FuzzyOutput"/> class. /// </summary> /// /// <param name="outputVar">A <see cref="LinguisticVariable"/> representing a Fuzzy Inference System's output.</param> /// internal FuzzyOutput(LinguisticVariable outputVar) { // instance of the constraints list this.outputList = new List <OutputConstraint>(20); // output linguistic variable this.outputVar = outputVar; }
/// <summary> /// Initializes a new instance of the <see cref="Clause"/> class. /// </summary> /// /// <param name="variable">Linguistic variable of the clause. </param> /// /// <param name="label">Label of the linguistic variable, a fuzzy set used as label into the linguistic variable.</param> /// /// <exception cref="KeyNotFoundException">The label indicated was not found in the linguistic variable.</exception> /// public Clause(LinguisticVariable variable, FuzzySet label) { // check if label belongs to var. variable.GetLabel(label.Name); // initializing attributes this.label = label; this.variable = variable; }
/// <summary> /// Adds a linguistic variable to the database. /// </summary> /// /// <param name="variable">A linguistic variable to add.</param> /// /// <exception cref="NullReferenceException">The linguistic variable was not initialized.</exception> /// <exception cref="ArgumentException">The linguistic variable name already exists in the database.</exception> /// public void AddVariable( LinguisticVariable variable ) { // checking for existing name if ( this.variables.ContainsKey( variable.Name ) ) throw new ArgumentException( "The linguistic variable name already exists in the database." ); // adding label this.variables.Add( variable.Name, variable ); }
/// <summary> /// Adds a linguistic variable to the database. /// </summary> /// /// <param name="variable">A linguistic variable to add.</param> /// /// <exception cref="NullReferenceException">The linguistic variable was not initialized.</exception> /// <exception cref="ArgumentException">The linguistic variable name already exists in the database.</exception> /// public void AddVariable(LinguisticVariable variable) { // checking for existing name if (this.variables.ContainsKey(variable.Name)) { throw new ArgumentException("The linguistic variable name already exists in the database."); } // adding label this.variables.Add(variable.Name, variable); }
// Testing basic functionality of linguistic variables private void runLingVarTestButton_Click(object sender, EventArgs e) { ClearDataSeries(); // create a linguistic variable to represent temperature LinguisticVariable lvTemperature = new LinguisticVariable("Temperature", 0, 80); // create the linguistic labels (fuzzy sets) that compose the temperature FuzzySet fsCold = new FuzzySet("Cold", new TrapezoidalFunction(10, 15, TrapezoidalFunction.EdgeType.Right)); FuzzySet fsCool = new FuzzySet("Cool", new TrapezoidalFunction(10, 15, 20, 25)); FuzzySet fsWarm = new FuzzySet("Warm", new TrapezoidalFunction(20, 25, 30, 35)); FuzzySet fsHot = new FuzzySet("Hot", new TrapezoidalFunction(30, 35, TrapezoidalFunction.EdgeType.Left)); // adding labels to the variable lvTemperature.AddLabel(fsCold); lvTemperature.AddLabel(fsCool); lvTemperature.AddLabel(fsWarm); lvTemperature.AddLabel(fsHot); // get membership of some points to the cool fuzzy set double[][,] chartValues = new double[4][,]; for (int i = 0; i < 4; i++) chartValues[i] = new double[160, 2]; // showing the shape of the linguistic variable - the shape of its labels memberships from start to end int j = 0; for (float x = 0; x < 80; x += 0.5f, j++) { double y1 = lvTemperature.GetLabelMembership("Cold", x); double y2 = lvTemperature.GetLabelMembership("Cool", x); double y3 = lvTemperature.GetLabelMembership("Warm", x); double y4 = lvTemperature.GetLabelMembership("Hot", x); chartValues[0][j, 0] = x; chartValues[0][j, 1] = y1; chartValues[1][j, 0] = x; chartValues[1][j, 1] = y2; chartValues[2][j, 0] = x; chartValues[2][j, 1] = y3; chartValues[3][j, 0] = x; chartValues[3][j, 1] = y4; } // plot membership to a chart chart.UpdateDataSeries("COLD", chartValues[0]); chart.UpdateDataSeries("COOL", chartValues[1]); chart.UpdateDataSeries("WARM", chartValues[2]); chart.UpdateDataSeries("HOT", chartValues[3]); }
/// <summary> /// Converts the Fuzzy Rule to RPN (Reverse Polish Notation). For debug proposes, the string representation of the /// RPN expression can be acessed by calling <see cref="GetRPNExpression"/> method. /// </summary> /// private void ParseRule( ) { // flag to incicate we are on consequent state bool consequent = false; // tokens like IF and THEN will be searched always in upper case string upRule = rule.ToUpper( ); // the rule must start with IF, and must have a THEN somewhere if (!upRule.StartsWith("IF")) { throw new ArgumentException("A Fuzzy Rule must start with an IF statement."); } if (upRule.IndexOf("THEN") < 0) { throw new ArgumentException("Missing the consequent (THEN) statement."); } // building a list with all the expression (rule) string tokens string spacedRule = rule.Replace("(", " ( ").Replace(")", " ) "); // getting the tokens list string[] tokensList = GetRuleTokens(spacedRule); // stack to convert to RPN Stack <string> s = new Stack <string>( ); // storing the last token string lastToken = "IF"; // linguistic var read, used to build clause LinguisticVariable lingVar = null; // verifying each token for (int i = 0; i < tokensList.Length; i++) { // removing spaces string token = tokensList[i].Trim( ); // getting upper case string upToken = token.ToUpper( ); // ignoring these tokens if (upToken == "" || upToken == "IF") { continue; } // if the THEN is found, the rule is now on consequent if (upToken == "THEN") { lastToken = upToken; consequent = true; continue; } // if we got a linguistic variable, an IS statement and a label is needed if (lastToken == "VAR") { if (upToken == "IS") { lastToken = upToken; } else { throw new ArgumentException("An IS statement is expected after a linguistic variable."); } } // if we got an IS statement, a label must follow it else if (lastToken == "IS") { try { FuzzySet fs = lingVar.GetLabel(token); Clause c = new Clause(lingVar, fs); if (consequent) { output = c; } else { rpnTokenList.Add(c); } lastToken = "LAB"; } catch (KeyNotFoundException) { throw new ArgumentException("Linguistic label " + token + " was not found on the variable " + lingVar.Name + "."); } } // not VAR and not IS statement else { // openning new scope if (upToken == "(") { // if we are on consequent, only variables can be found if (consequent) { throw new ArgumentException("Linguistic variable expected after a THEN statement."); } // if its a (, just push it s.Push(upToken); lastToken = upToken; } // operators else if (upToken == "AND" || upToken == "OR" || unaryOperators.IndexOf(upToken) >= 0) { // if we are on consequent, only variables can be found if (consequent) { throw new ArgumentException("Linguistic variable expected after a THEN statement."); } // pop all the higher priority operators until the stack is empty while ((s.Count > 0) && (Priority(s.Peek( )) > Priority(upToken))) { rpnTokenList.Add(s.Pop( )); } // pushing the operator s.Push(upToken); lastToken = upToken; } // closing the scope else if (upToken == ")") { // if we are on consequent, only variables can be found if (consequent) { throw new ArgumentException("Linguistic variable expected after a THEN statement."); } // if there is nothing on the stack, an oppening parenthesis is missing. if (s.Count == 0) { throw new ArgumentException("Openning parenthesis missing."); } // pop the tokens and copy to output until openning is found while (s.Peek( ) != "(") { rpnTokenList.Add(s.Pop( )); if (s.Count == 0) { throw new ArgumentException("Openning parenthesis missing."); } } s.Pop( ); // saving last token... lastToken = upToken; } // finally, the token is a variable else { // find the variable try { lingVar = database.GetVariable(token); lastToken = "VAR"; } catch (KeyNotFoundException) { throw new ArgumentException("Linguistic variable " + token + " was not found on the database."); } } } } // popping all operators left in stack while (s.Count > 0) { rpnTokenList.Add(s.Pop( )); } }
// Hardcode initializing the Fuzzy Inference System void InitFuzzyEngine() { // Linguistic labels (fuzzy sets) that compose the distances FuzzySet fsNear = new FuzzySet("Near", new TrapezoidalFunction(15, 50, TrapezoidalFunction.EdgeType.Right)); FuzzySet fsMedium = new FuzzySet("Medium", new TrapezoidalFunction(15, 50, 60, 100)); FuzzySet fsFar = new FuzzySet("Far", new TrapezoidalFunction(60, 100, TrapezoidalFunction.EdgeType.Left)); // Right Distance (Input) LinguisticVariable lvRight = new LinguisticVariable("RightDistance", 0, 120); lvRight.AddLabel(fsNear); lvRight.AddLabel(fsMedium); lvRight.AddLabel(fsFar); // Left Distance (Input) LinguisticVariable lvLeft = new LinguisticVariable("LeftDistance", 0, 120); lvLeft.AddLabel(fsNear); lvLeft.AddLabel(fsMedium); lvLeft.AddLabel(fsFar); // Front Distance (Input) LinguisticVariable lvFront = new LinguisticVariable("FrontalDistance", 0, 120); lvFront.AddLabel(fsNear); lvFront.AddLabel(fsMedium); lvFront.AddLabel(fsFar); // Linguistic labels (fuzzy sets) that compose the angle FuzzySet fsVN = new FuzzySet("VeryNegative", new TrapezoidalFunction(-40, -35, TrapezoidalFunction.EdgeType.Right)); FuzzySet fsN = new FuzzySet("Negative", new TrapezoidalFunction(-40, -35, -25, -20)); FuzzySet fsLN = new FuzzySet("LittleNegative", new TrapezoidalFunction(-25, -20, -10, -5)); FuzzySet fsZero = new FuzzySet("Zero", new TrapezoidalFunction(-10, 5, 5, 10)); FuzzySet fsLP = new FuzzySet("LittlePositive", new TrapezoidalFunction(5, 10, 20, 25)); FuzzySet fsP = new FuzzySet("Positive", new TrapezoidalFunction(20, 25, 35, 40)); FuzzySet fsVP = new FuzzySet("VeryPositive", new TrapezoidalFunction(35, 40, TrapezoidalFunction.EdgeType.Left)); // Angle LinguisticVariable lvAngle = new LinguisticVariable("Angle", -50, 50); lvAngle.AddLabel(fsVN); lvAngle.AddLabel(fsN); lvAngle.AddLabel(fsLN); lvAngle.AddLabel(fsZero); lvAngle.AddLabel(fsLP); lvAngle.AddLabel(fsP); lvAngle.AddLabel(fsVP); // The database Database fuzzyDB = new Database(); fuzzyDB.AddVariable(lvFront); fuzzyDB.AddVariable(lvLeft); fuzzyDB.AddVariable(lvRight); fuzzyDB.AddVariable(lvAngle); // Creating the inference system IS = new InferenceSystem(fuzzyDB, new CentroidDefuzzifier(1000)); // Going Straight IS.NewRule("Rule 1", "IF FrontalDistance IS Far THEN Angle IS Zero"); // Going Straight (if can go anywhere) IS.NewRule("Rule 2", "IF FrontalDistance IS Far AND RightDistance IS Far AND LeftDistance IS Far THEN Angle IS Zero"); // Near right wall IS.NewRule("Rule 3", "IF RightDistance IS Near AND LeftDistance IS Not Near THEN Angle IS LittleNegative"); // Near left wall IS.NewRule("Rule 4", "IF RightDistance IS Not Near AND LeftDistance IS Near THEN Angle IS LittlePositive"); // Near front wall - room at right IS.NewRule("Rule 5", "IF RightDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive"); // Near front wall - room at left IS.NewRule("Rule 6", "IF LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Negative"); // Near front wall - room at both sides - go right IS.NewRule("Rule 7", "IF RightDistance IS Far AND LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive"); }
/// <summary> /// Initializes a new instance of the <see cref="Clause"/> class. /// </summary> /// /// <param name="variable">Linguistic variable of the clause. </param> /// /// <param name="label">Label of the linguistic variable, a fuzzy set used as label into the linguistic variable.</param> /// /// <exception cref="KeyNotFoundException">The label indicated was not found in the linguistic variable.</exception> /// public Clause( LinguisticVariable variable, FuzzySet label ) { // check if label belongs to var. variable.GetLabel( label.Name ); // initializing attributes this.label = label; this.variable = variable; }
/// <summary> /// Initializes a new instance of the <see cref="FuzzyOutput"/> class. /// </summary> /// /// <param name="outputVar">A <see cref="LinguisticVariable"/> representing a Fuzzy Inference System's output.</param> /// internal FuzzyOutput( LinguisticVariable outputVar ) { // instance of the constraints list this.outputList = new List<OutputConstraint>( 20 ); // output linguistic variable this.outputVar = outputVar; }