/// <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> /// 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( )); } }