| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- /* Copyright 2010 Juan Rada-Vilela
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- #include "DescriptiveAntecedent.h"
- #include "StrOp.h"
- #include <stack>
- #include "FuzzyRule.h"
- namespace fl {
- DescriptiveAntecedent::DescriptiveAntecedent() : FuzzyAntecedent(),
- _left(NULL), _right(NULL), _operation(O_NONE), _term(NULL) {
- }
- DescriptiveAntecedent::DescriptiveAntecedent(const FuzzyOperator& fuzzy_op) :
- FuzzyAntecedent(fuzzy_op), _left(NULL), _right(NULL), _operation(O_NONE),
- _term(NULL) {
- }
- DescriptiveAntecedent::~DescriptiveAntecedent() {
- if (_left) {
- delete _left;
- }
- if (_right) {
- delete _right;
- }
- }
- void DescriptiveAntecedent::setLeft(DescriptiveAntecedent* l_antecedent) {
- this->_left = l_antecedent;
- }
- DescriptiveAntecedent* DescriptiveAntecedent::left() const {
- return this->_left;
- }
- void DescriptiveAntecedent::setRight(DescriptiveAntecedent* r_antecedent) {
- this->_right = r_antecedent;
- }
- DescriptiveAntecedent* DescriptiveAntecedent::right() const {
- return this->_right;
- }
- void DescriptiveAntecedent::setOperation(OPERATION operation) {
- this->_operation = operation;
- }
- DescriptiveAntecedent::OPERATION DescriptiveAntecedent::operation() const {
- return this->_operation;
- }
- void DescriptiveAntecedent::addHedge(Hedge* hedge) {
- this->_hedges.push_back(hedge);
- }
- int DescriptiveAntecedent::numberOfHedges() const {
- return this->_hedges.size();
- }
- Hedge* DescriptiveAntecedent::hedge(int index) const {
- return this->_hedges[index];
- }
- void DescriptiveAntecedent::setTerm(const LinguisticTerm* term) {
- this->_term = term;
- }
- const LinguisticTerm* DescriptiveAntecedent::term() const {
- return this->_term;
- }
- bool DescriptiveAntecedent::isTerminal() const {
- return operation() == O_NONE;
- }
- flScalar DescriptiveAntecedent::degreeOfTruth() const {
- if (!isTerminal()) {
- if (left() == NULL || right() == NULL) {
- throw NullPointerException(FL_AT, toString());
- }
- switch (operation()) {
- case O_AND:
- return fuzzyOperator().tnorm().execute(left()->degreeOfTruth(),
- right()->degreeOfTruth());
- case O_OR:
- return fuzzyOperator().snorm().execute(left()->degreeOfTruth(),
- right()->degreeOfTruth());
- default:
- throw InvalidArgumentException(FL_AT, "Operation " + StrOp::IntToString(operation()) + " not available");
- }
- }
- flScalar result = term()->membership(inputLVar()->input());
- for (int i = 0; i < numberOfHedges(); ++i) {
- result = hedge(i)->hedge(result);
- }
- return result;
- }
- std::string DescriptiveAntecedent::toString() const {
- std::stringstream ss;
- if (isTerminal()) {
- ss << inputLVar()->name() + " " + FuzzyRule::FR_IS + " ";
- for (int i = 0; i < numberOfHedges(); ++i) {
- ss << hedge(i)->name() << " ";
- }
- ss << term()->name();
- } else {
- ss << " ( " + (left() ? left()->toString() : "NULL");
- ss << " " + (operation() == O_AND ? FuzzyRule::FR_AND : FuzzyRule::FR_OR);
- ss << " " + (right() ? right()->toString() : "NULL") + " ) ";
- }
- return ss.str();
- }
- void DescriptiveAntecedent::parse(const std::string& antecedent,
- const FuzzyEngine& engine) throw (ParsingException) {
- enum e_state {
- //e.g. Posfix antecedent: Energy is LOW Distance is FAR_AWAY and
- S_LVAR = 1, S_IS, S_HEDGE, S_TERM, S_OPERATOR
- };
- e_state current_state = S_LVAR;
- std::string postfix_antecedent = InfixToPostfix(antecedent);
- std::stringstream ss(postfix_antecedent);
- std::string token;
- InputLVar* input = NULL;
- std::vector<Hedge*> hedges;
- Hedge* hedge = NULL;
- LinguisticTerm* term = NULL;
- std::stack<DescriptiveAntecedent*> f_antecedents;
- DescriptiveAntecedent* tmp_antecedent = NULL;
- // <editor-fold desc="State Machine">
- while (ss >> token) {
- switch (current_state) {
- //e.g.Postfix: Energy is LOW Distance is FAR_AWAY and. After term follows Operator or LVar
- case S_LVAR:
- case S_OPERATOR:
- input = engine.inputLVar(token);
- if (input) {
- current_state = S_IS;
- break;
- }
- if (token != FuzzyRule::FR_AND && token != FuzzyRule::FR_OR) {
- //if it is not and InputLVar and not an Operator then exception
- throw ParsingException(FL_AT, "Input variable <" +
- token + "> not registered in fuzzy engine");
- // throw RuleParsingException(FL_AT,
- // "Operator expected but found <" + token +
- // ">. Antecedent: " + antecedent);
- }
- //A is a B is b and
- if (isTerminal()) {
- setLeft(f_antecedents.top());
- f_antecedents.pop();
- setRight(f_antecedents.top());
- f_antecedents.pop();
- setOperation(token == FuzzyRule::FR_AND ? DescriptiveAntecedent::O_AND :
- DescriptiveAntecedent::O_OR); //I am not terminal anymore
- } else {
- setLeft(new DescriptiveAntecedent(*this));
- setRight(f_antecedents.top());
- f_antecedents.pop();
- setOperation(token == FuzzyRule::FR_AND ? DescriptiveAntecedent::O_AND :
- DescriptiveAntecedent::O_OR); //I am not terminal anymore
- }
- break;
- case S_IS:
- if (token == FuzzyRule::FR_IS) {
- current_state = S_HEDGE;
- } else {
- throw ParsingException(FL_AT, "<is> expected but found <" +
- token + ">");
- }
- break;
- case S_HEDGE:
- hedge = engine.hedgeSet().get(token);
- if (hedge) {
- hedges.push_back(hedge); //And check for more hedges
- break;
- }
- //intentional fall-through in case there are no hedges
- case S_TERM:
- term = input->term(token);
- if (!term) {
- throw ParsingException(FL_AT, "Term <" + token +
- "> not found in input variable <" + input->name() +
- ">");
- }
- current_state = S_OPERATOR;
- tmp_antecedent = new DescriptiveAntecedent(engine.fuzzyOperator());
- tmp_antecedent->setInputLVar(input);
- tmp_antecedent->setTerm(term);
- for (size_t i = 0; i < hedges.size(); ++i) {
- tmp_antecedent->addHedge(hedges[i]);
- }
- f_antecedents.push(tmp_antecedent);
- tmp_antecedent = NULL;
- hedges.clear();
- break;
- }
- }
- //</editor-fold>
- if (!f_antecedents.empty()) { //e.g. Rule: if A is a then X is x (one antecedent only)
- FL_ASSERT(f_antecedents.size() == 1);
- DescriptiveAntecedent* me = f_antecedents.top();
- setInputLVar(me->inputLVar());
- for (int i = 0; i < me->numberOfHedges(); ++i) {
- addHedge(me->hedge(i));
- }
- setTerm(me->term());
- delete me;
- }
- }
- std::string DescriptiveAntecedent::Preprocess(const std::string& infix) {
- std::string result;
- for (size_t i = 0; i < infix.size(); ++i) {
- if (infix[i] == '(') {
- result += " ( ";
- } else if (infix[i] == ')') {
- result += " ) ";
- } else {
- result += infix[i];
- }
- }
- return result;
- }
- std::string DescriptiveAntecedent::InfixToPostfix(const std::string& infix) {
- std::string p_infix = Preprocess(infix);
- std::stringstream ss(p_infix);
- std::string token;
- std::string tmp;
- std::string result;
- std::stack<std::string> stack;
- while (ss >> token) {
- if (token == "(") {
- stack.push(token);
- } else if (token == ")") {
- FL_ASSERT(!stack.empty());
- tmp = stack.top();
- stack.pop();
- while (tmp != "(") {
- result += tmp + " ";
- FL_ASSERT(!stack.empty());
- tmp = stack.top();
- stack.pop();
- }
- } else if (token == FuzzyRule::FR_AND || token == FuzzyRule::FR_OR) {
- if (stack.empty()) {
- stack.push(token);
- } else {
- FL_ASSERT(!stack.empty())
- tmp = stack.top();
- stack.pop();
- while (tmp != FuzzyRule::FR_AND && tmp != FuzzyRule::FR_OR && tmp != "(") {
- result += tmp + " ";
- FL_ASSERT(!stack.empty())
- tmp = stack.top();
- stack.pop();
- }
- stack.push(tmp);
- stack.push(token);
- }
- } else {
- result += token + " ";
- }
- }
- while (!stack.empty()) {
- FL_ASSERT(!stack.empty())
- token = stack.top();
- stack.pop();
- result += token + " ";
- }
- return result;
- }
- }
|