// Copyright (C) 2000 Dominic Letourneau (doumdi@yahoo.com) // FuzzyModel.cc: implementation of the FuzzyModel class. // ////////////////////////////////////////////////////////////////////// #include "FuzzyModel.h" #include "Exception.h" #include #include #include #include using namespace std; namespace FD { ////////////////////////////////////////////////////////////////////// // Constants ////////////////////////////////////////////////////////////////////// const int FuzzyModel::FUZZY_INPUT_SET = 0; const int FuzzyModel::FUZZY_OUTPUT_SET = 1; ////////////////////////////////////////////////////////////////////// // Construction ////////////////////////////////////////////////////////////////////// FuzzyModel::FuzzyModel() : BufferedNode("INVALID",ParameterSet()) { } FuzzyModel::FuzzyModel(const FuzzyModel &model) : BufferedNode("INVALID",ParameterSet()) { //inserting input set //cerr<<"copying input set"<clone()); } //inserting output set //cerr<<"copying output set"<clone()); } //readding rules //cerr<<"copying rules"<clone()); } } FuzzyModel::FuzzyModel(string nodeName, ParameterSet params) : BufferedNode(nodeName,params) { m_RuleID = addInput("RULES");; m_ASetID = addInput("ANTECEDENT_SETS"); m_CSetID = addInput("CONSEQUENT_SETS"); m_InputID = addInput("INPUT"); m_OutputID = addOutput("OUTPUT"); m_ModelID = addOutput("MODEL"); } ////////////////////////////////////////////////////////////////////// // Destruction ////////////////////////////////////////////////////////////////////// FuzzyModel::~FuzzyModel() { int i; //resizing vectors m_rules.resize(0); m_input_set.resize(0); m_output_set.resize(0); } ////////////////////////////////////////////////////////////////////// // Add a fuzzy rule to the model ////////////////////////////////////////////////////////////////////// void FuzzyModel::add_fuzzy_rule(ObjectRef ruleValue) { FuzzySet *set = NULL; FuzzyFunction *function = NULL; FuzzyRule &rule = object_cast(ruleValue); int i; //int rule_number = rule->get_rule_number(); int rule_number = m_rules.size() + 1; rule.set_rule_number(rule_number); //rule->print_rule(cerr); //let's verify this rule vector >&consequent = rule.get_consequent_part(); vector >&antecedant = rule.get_antecedant_part(); //rule number verification if (m_input_functions.size() < rule_number) { m_input_functions.resize(rule_number); } else { if (!m_input_functions[rule_number -1].empty()) { char message[256]; sprintf(message,"RULE %i ALREADY EXISTS",rule_number); throw new GeneralException(message,__FILE__,__LINE__); } } if (m_output_functions.size() < rule_number) { m_output_functions.resize(rule_number); } else { if (!m_output_functions[rule_number -1].empty()) { char message[256]; sprintf(message,"RULE %i ALREADY EXISTS",rule_number); throw new GeneralException(message,__FILE__,__LINE__); } } //antecedant verification for (i = 0; i < antecedant.size(); i++) { set = find_set_named(antecedant[i].first, FuzzyModel::FUZZY_INPUT_SET); if (!set) { char message[256]; sprintf(message,"SET NOT FOUND (%s)",antecedant[i].first.c_str()); throw new GeneralException(message,__FILE__,__LINE__); } else { function = set->find_function_by_name(antecedant[i].second); if (!function) { char message[256]; sprintf(message,"SET VARIABLE NOT FOUND (%s)(%s)", antecedant[i].first.c_str(),antecedant[i].second.c_str()); throw new GeneralException(message,__FILE__,__LINE__); } else { //keeping the name of the antecedant m_input_functions[rule_number -1].push_back(function); } } } //cout<<"antecedant verification OK"<find_function_by_name(consequent[i].second); if (!function) { char message[256]; sprintf(message,"SET VARIABLE NOT FOUND (%s)(%s)", consequent[i].first.c_str(),consequent[i].second.c_str()); throw new GeneralException(message,__FILE__,__LINE__); } else { //keeping a pointer to this function for rule evaluation m_output_functions[rule_number - 1].push_back(function); } } } //cout<<"consequent verification OK"<(setValue.get()); if (!set) { throw new GeneralException("NULL SET",__FILE__,__LINE__); } switch (type) { case FUZZY_INPUT_SET: m_input_set.push_back(setValue); break; case FUZZY_OUTPUT_SET: m_output_set.push_back(setValue); break; default: throw new GeneralException("UNKNOWN SET TYPE",__FILE__,__LINE__); break; } } ////////////////////////////////////////////////////////////////////// // Print all the rules ////////////////////////////////////////////////////////////////////// void FuzzyModel::print_rules(ostream &out) { for (int i = 0; i < m_rules.size(); i++) { object_cast(m_rules[i]).print_rule(out); } } ////////////////////////////////////////////////////////////////////// // verification of rule consistency ////////////////////////////////////////////////////////////////////// void FuzzyModel::verify_rules() { //verification of the number of rules //and the antecedant/consequent part of the rules //to be implemented int count = 1; for (int i = 0; i < m_input_set.size(); i++) { count *= object_cast(m_input_set[i]).get_function_count(); } if (count != m_rules.size()) { char message[256]; sprintf(message,"NUMBER OF RULES INCORRECT %i INSTEAD OF %i",m_rules.size(),count); throw new GeneralException(message,__FILE__,__LINE__); } } ////////////////////////////////////////////////////////////////////// // Find a set with a given name ////////////////////////////////////////////////////////////////////// FuzzySet* FuzzyModel::find_set_named(const string &name, int type) { int i; switch(type) { case FUZZY_INPUT_SET: for (i =0; i < m_input_set.size(); i++) { if (object_cast(m_input_set[i]).get_name() == name) { return dynamic_cast(m_input_set[i].get()); } } break; case FUZZY_OUTPUT_SET: for (i =0; i < m_output_set.size(); i++) { if (object_cast(m_output_set[i]).get_name() == name) { return dynamic_cast(m_output_set[i].get()); } } break; default: throw new GeneralException("UNKNOWN SET TYPE",__FILE__,__LINE__); break; } return NULL; } ////////////////////////////////////////////////////////////////////// // Evaluation/inference ////////////////////////////////////////////////////////////////////// Vector& FuzzyModel::evaluate(Vector &input_values) { Vector inputs; if (input_values.size() != m_input_set.size()) { throw new GeneralException("NOT ENOUGH INPUT VARIABLES",__FILE__,__LINE__); } //we must reset every output and input set int i; for (i = 0; i < m_input_set.size(); i++) { object_cast(m_input_set[i]).reset(); } for (i =0; i < m_output_set.size(); i++) { object_cast(m_output_set[i]).reset(); } //assuming that values are ordered like the rules for (int i = 0; i < m_input_set.size(); i++) { inputs.push_back(input_values[i]); //m_input_set[i]->get_all_membership_evaluation(input_values[i]); } //we are assuming that the input variables are in the same order than the rules Vector conjunction_values(m_input_set.size()); for (int x = 0; x < m_rules.size(); x++) { list::iterator iter_input; int y = 0; for (iter_input = m_input_functions[x].begin(); iter_input != m_input_functions[x].end(); iter_input++) { //conjunction_values[y] = m_input_set[y]->get_value_with_name((*iter_input)); conjunction_values[y] = (*iter_input)->evaluate(inputs[y]); /* cerr<<"input set "<get_name()<get_name()<::iterator iter; //applying conjunction operator for (iter = m_output_functions[x].begin(); iter != m_output_functions[x].end(); iter++) { /* cerr<<"Pushing inference value of "<get_name()<push_inference_value(conjunction(conjunction_values)); } }//for every rules //applying disjunction (once per output function) float disjunction_value; for (i = 0; i < m_output_set.size(); i++) { Vector &funct = object_cast(m_output_set[i]).get_member_functions(); for (int j = 0; j < funct.size(); j++) { disjunction_value = disjunction(object_cast(funct[j]).get_inference_values()); object_cast(funct[j]).reset_inference_values(); object_cast(funct[j]).push_inference_value(disjunction_value); /* printf("Final value for (%s,%s) : %f\n",m_output_set[i]->get_name().c_str(), funct[j]->get_name().c_str(),disjunction_value); */ } } //defuzzification return defuzzification(); } ////////////////////////////////////////////////////////////////////// // Printing the membership functions ////////////////////////////////////////////////////////////////////// void FuzzyModel::print_sets(ostream &out) { out<<"INPUT SETS"< &vect_sets1 = object_cast >(ASets); for (int i = 0; i < vect_sets1.size(); i++) { //vect_sets1[i]->printOn(cerr); add_fuzzy_set(vect_sets1[i]->clone(),FuzzyModel::FUZZY_INPUT_SET); } //Then add consequent sets Vector &vect_sets2 = object_cast >(CSets); for (int i = 0; i < vect_sets2.size(); i++) { //vect_sets2[i]->printOn(cerr); add_fuzzy_set(vect_sets2[i]->clone(),FuzzyModel::FUZZY_OUTPUT_SET); } //Finally add rules Vector &vect_rules = object_cast >(Rules); for (int i = 0; i < vect_rules.size(); i++) { //vect_rules[i]->printOn(cerr); add_fuzzy_rule(vect_rules[i]->clone()); } //verify rule consistency verify_rules(); //calculate output Vector &vect_value = object_cast >(Input); Vector& calc_output = evaluate(vect_value); Vector *my_output = new Vector(calc_output.size()); for (int i = 0; i < calc_output.size(); i++) { (*my_output)[i] = calc_output[i]; } if (output_id == m_OutputID) { out[count] = ObjectRef(my_output); } if (output_id == m_ModelID) { out[count] = clone(); } }//try catch (BaseException *e) { throw e->add (new GeneralException("Exception caught while processing FuzzyModel", __FILE__, __LINE__)); } } }//namespace FD