// Copyright (C) 2000 Dominic Letourneau (doumdi@yahoo.com)

// FuzzySet.cc: implementation of the FuzzySet class.
//
//////////////////////////////////////////////////////////////////////

#include "FuzzySet.h"
#include "Exception.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include "Vector.h"
#include "FuzzyOperators.h"

using namespace std;

namespace FD {

DECLARE_NODE(FuzzySet)
DECLARE_TYPE(FuzzySet)
/*Node
 *
 * @name FuzzySet
 * @category Fuzzy
 * @description A FuzzySet containing functions associated with names
 *
 * @input_name FUNCTIONS
 * @input_description The Fuzzy Functions
 * @input_type Vector<ObjectRef>
 *
 * @output_name SET
 * @output_description The FuzzySet with multiple Fuzzy Functions
 * @output_type Vector<ObjectRef>
 *
 * @parameter_name NAME
 * @parameter_description The name of the set
 * @parameter_type string
 *
END*/


//////////////////////////////////////////////////////////////////////
// Construction
//////////////////////////////////////////////////////////////////////

FuzzySet::FuzzySet(const string &name)
  : BufferedNode("INVALID", ParameterSet()), m_name(name) {

}

FuzzySet::FuzzySet(istream &in) 
  : BufferedNode("INVALID", ParameterSet()), m_name("INVALID") {
  readFrom(in);
}


FuzzySet::FuzzySet() 
  : BufferedNode("INVALID", ParameterSet()), m_name("INVALID") {
}

FuzzySet::FuzzySet(string nodeName, ParameterSet params) 
  : BufferedNode(nodeName,params) {
  
  
  m_name = object_cast<String>(parameters.get("NAME"));
  
  //the inputID
  m_functionID = addInput("FUNCTIONS");

  //the outputID
  m_setID = addOutput("SET");
}

//////////////////////////////////////////////////////////////////////
// Destruction
//////////////////////////////////////////////////////////////////////

FuzzySet::~FuzzySet() {
  
  m_functions.resize(0);
}
//////////////////////////////////////////////////////////////////////
// add a trapezoid function
//////////////////////////////////////////////////////////////////////

void FuzzySet::add_trapezoidal_function(const string &name, float a, 
					float b, float c, float d) {

  m_functions.push_back(ObjectRef(new TrapezoidalFunction(name,a,b,c,d)));	
  m_evaluation.resize(m_functions.size());
}

//////////////////////////////////////////////////////////////////////
// add a triangulare function
//////////////////////////////////////////////////////////////////////

void FuzzySet::add_triangular_function(const string &name, float a, float b, float c) {

  m_functions.push_back(ObjectRef(new TriangularFunction(name,a,b,c)));

  m_evaluation.resize(m_functions.size());

}

//////////////////////////////////////////////////////////////////////
// evaluate all membership function
//////////////////////////////////////////////////////////////////////

Vector<float> & FuzzySet::get_all_membership_evaluation(float x) {
  
  //updating evaluation vector
  m_evaluation.resize(m_functions.size());
  
  
  for (int i = 0; i < m_functions.size(); i++) {
    m_evaluation[i] = object_cast<FuzzyFunction>(m_functions[i]).evaluate(x);

  }
  
  return m_evaluation;
  
}

//////////////////////////////////////////////////////////////////////
// Returns the evaluation of the given named function
//////////////////////////////////////////////////////////////////////

float FuzzySet::get_membership_evaluation(const string &name, float x) {
  
  
  int index = find_function_by_index(name);
  
  m_evaluation[index] = object_cast<FuzzyFunction>(m_functions[index]).evaluate(x);
  
  return m_evaluation[index];
}


//////////////////////////////////////////////////////////////////////
// Returns the index of a given function name
//////////////////////////////////////////////////////////////////////

int FuzzySet::find_function_by_index(const string &name) {
  
  for (int i = 0; i < m_functions.size(); i++) {
    
    if (object_cast<FuzzyFunction>(m_functions[i]).get_name() == name) return i;
    
  }
  
  char message[256];
  
  sprintf(message,"CANNOT GET MEMBERSHIP FUNCTION CALLED : %s",name.c_str());
  
  throw new GeneralException(message,__FILE__,__LINE__);
  
  return -1;
}

//////////////////////////////////////////////////////////////////////
// Returns the pointer of a given function name
//////////////////////////////////////////////////////////////////////

FuzzyFunction* FuzzySet::find_function_by_name (const string &name) {
  
  for (int i = 0; i < m_functions.size(); i++) {
    
    if (object_cast<FuzzyFunction>(m_functions[i]).get_name() == name) 
      return dynamic_cast<FuzzyFunction*>(m_functions[i].get());
    
  }
  
  char message[256];
  
  sprintf(message,"CANNOT GET MEMBERSHIP FUNCTION CALLED : %s",name.c_str());
  
  throw new GeneralException(message,__FILE__,__LINE__);
  
  return NULL;
  
}
//////////////////////////////////////////////////////////////////////
// Printing the functions (graphics)
//////////////////////////////////////////////////////////////////////

void FuzzySet::print_functions(ostream &out) {
  
  if (m_functions.size() > 0) {
    float min = object_cast<FuzzyFunction>(m_functions[0]).get_lower_bound(); 
    float max = object_cast<FuzzyFunction>(m_functions[0]).get_upper_bound();
    int i;
    
    //finding limits
    for (i = 0; i < m_functions.size(); i++) {
      
      if (min > object_cast<FuzzyFunction>(m_functions[i]).get_lower_bound()) {
	min = object_cast<FuzzyFunction>(m_functions[i]).get_lower_bound();
      }
      
      if (max < object_cast<FuzzyFunction>(m_functions[i]).get_upper_bound()) {
	max = object_cast<FuzzyFunction>(m_functions[i]).get_upper_bound();
      }
      
      
    }
    
    //printing membership values
    for (float index = min; index <= max; index++) {
      
      //printing membership function names
      for (i = 0; i < m_functions.size(); i++) {
	out<<object_cast<FuzzyFunction>(m_functions[i]).get_name()<<"\t";	
      }
      
      out<<index<<"\t";
      
      
      //printing membership function values
      for (i = 0; i < m_functions.size(); i++) {
	out<<object_cast<FuzzyFunction>(m_functions[i]).evaluate(index)<<"\t";
      }
      
      
      out<<endl;
    }
    
  }
}

//////////////////////////////////////////////////////////////////////
// calculate
//////////////////////////////////////////////////////////////////////

void FuzzySet::calculate(int output_id, int count, Buffer &out) {


  //cerr<<"FuzzySet Calculate"<<endl;
  m_functions.resize(0);


  //getting functions 
  ObjectRef Functions = getInput(m_functionID, count);
  Vector<ObjectRef> &funct_vect = object_cast<Vector<ObjectRef> >(Functions);

  
  for (int i = 0 ; i < funct_vect.size(); i++) {
    m_functions.push_back(funct_vect[i]->clone());
  }

  out[count] = ObjectRef(new Vector<ObjectRef>(1,clone()));

}

ObjectRef FuzzySet::clone() {

  FuzzySet* my_set = new FuzzySet(m_name);

  for (int i = 0; i < m_functions.size(); i++) {
    my_set->m_functions.push_back(m_functions[i]->clone());
  }

  return ObjectRef(my_set);
}

void FuzzySet::printOn(ostream &out) const {

  out << "<FuzzySet "<<endl; 
  out << "<Name "<<m_name<<" >"<<endl;
  out << "<Size "<<m_functions.size()<<" >"<<endl;

  for (int i = 0; i < m_functions.size(); i++) {
    out<<"<Function "<<m_functions[i]<<" >"<<endl;
  }
  out <<" >\n";
}

void FuzzySet::readFrom(istream &in) {

   string tag;
   int size;

   while (1)
   {
      char ch;
      in >> ch;
      if (ch == '>') break;

      else if (ch != '<') {
       throw new ParsingException ("FuzzySet::readFrom : Parse error: '<' expected");
      }
      in >> tag;

      if (tag == "Name") {
         in >> m_name;
      }
      else if (tag == "Size") {
         in >> size;
	 m_evaluation.resize(size);
      }
      else if (tag == "Function") {
	//reading function
	ObjectRef value;
	in>>value;
	m_functions.push_back(value);
      }
      else {
	throw new ParsingException ("FuzzySet::readFrom : unknown argument: " + tag);
      }

      if (!in) throw new ParsingException ("FuzzySet::readFrom : Parse error trying to build " + tag);

      in >> tag;
      if (tag != ">") 
         throw new ParsingException ("FuzzySet::readFrom : Parse error: '>' expected ");
   }
}
}//namespace FD


syntax highlighted by Code2HTML, v. 0.9.1