/// <summary> /// Adds a linguistic label to the variable. /// </summary> /// /// <param name="label">A <see cref="FuzzySet"/> that will be a linguistic label of the linguistic variable.</param> /// /// <remarks>Linguistic labels are fuzzy sets (<see cref="FuzzySet"/>). Each /// label of the variable must have a unique name. The range of the label /// (left and right limits) cannot be greater than /// the linguistic variable range (start/end).</remarks> /// /// <exception cref="NullReferenceException">The fuzzy set was not initialized.</exception> /// <exception cref="ArgumentException">The linguistic label name already exists in the linguistic variable.</exception> /// <exception cref="ArgumentException">The left limit of the fuzzy set can not be lower than the linguistic variable's starting point.</exception> /// <exception cref="ArgumentException">"The right limit of the fuzzy set can not be greater than the linguistic variable's ending point."</exception> /// public void AddLabel(FuzzySet label) { // checking for existing name if (this.labels.ContainsKey(label.Name)) { throw new ArgumentException("The linguistic label name already exists in the linguistic variable."); } // checking ranges if (label.LeftLimit < this.start) { throw new ArgumentException("The left limit of the fuzzy set can not be lower than the linguistic variable's starting point."); } if (label.RightLimit > this.end) { throw new ArgumentException("The right limit of the fuzzy set can not be greater than the linguistic variable's ending point."); } // adding label this.labels.Add(label.Name, label); }
/// <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( )); } }
/// <summary> /// Calculate the membership of a given value to a given label. Used to evaluate linguistics clauses like /// "X IS A", where X is a value and A is a linguistic label. /// </summary> /// /// <param name="labelName">Label (fuzzy set) to evaluate value's membership.</param> /// <param name="value">Value which label's membership will to be calculated.</param> /// /// <returns>Degree of membership [0..1] of the value to the label (fuzzy set).</returns> /// /// <exception cref="KeyNotFoundException">The label indicated in labelName was not found in the linguistic variable.</exception> /// public float GetLabelMembership(string labelName, float value) { FuzzySet fs = labels[labelName]; return(fs.GetMembership(value)); }