/****************************************************************************
 * This file was derived from the CNCL library by the Pablo research group.
 *
 * The complete CNCL library is available at:
 *       http://www.comnets.rwth-aachen.de/doc/cncl.html
 *
 * The CNCL copyright notice is included here:
 *
 * |_|_|_  |_|_    |_    |_|_|_  |_               C O M M U N I C A T I O N
 *|_       |_  |_  |_  |_        |_                         N E T W O R K S
 *|_       |_  |_  |_  |_        |_                               C L A S S
 * |_|_|_  |_    |_|_    |_|_|_  |_|_|_|_                     L I B R A R Y
 *
 *
 *
 * Copyright (C) 1992-1998   Communication Networks
 *                           Aachen University of Technology
 *                           D-52056 Aachen
 *                           Germany
 *                           Email: cncl-adm@comnets.rwth-aachen.de
 *
 *
 * This library is free  software; you can  redistribute it and/or modify
 * it  under   the terms  of the GNU   Library  General Public License as
 * published by the  Free Software Foundation;  either  version 2 of  the
 * License, or  (at  your option)  any  later  version.  This  library is
 * distributed  in the  hope  that  it  will  be useful,  but WITHOUT ANY
 * WARRANTY;  without even the   implied  warranty of MERCHANTABILITY  or
 * FITNESS FOR A PARTICULAR PURPOSE.   See the GNU Library General Public
 * Library General Public License along with  this library; if not, write
 * to the Free Software Foundation,  675  Mass Ave, Cambridge, MA  02139,
 * USA.
 ****************************************************************************/

//   -*- C++ -*-
/*****************************************************************************
 *
 * Class: FlFVar --- Fuzzy variable
 *
 *****************************************************************************/

#include "FlFVar.h"
//#include <FlPipe.h>

using std::endl;
using std::cin;
using std::istream;
using std::ofstream;
using std::ifstream;

/*
 * Constructors
 */
FlFVar::FlFVar()
    : FlNamed(""), varvalue(0), varfvalue(NIL),
      varxmin(0), varxmax(1), varsets((size_t)0)
{}

    
FlFVar::FlFVar(double min, double max)
    : FlNamed(""), varvalue(0), varfvalue(NIL), 
      varxmin(min), varxmax(max), varsets((size_t)0)
{}


FlFVar::FlFVar(FlStringR xname, double min, double max)
    : FlNamed(xname), varvalue(0), varfvalue(NIL),
      varxmin(min), varxmax(max), varsets((size_t)0)
{}



/*
 * Initialize
 */
void FlFVar::init(FlStringR xname, double min, double max)
{
    set_name(xname);
    varxmin = min;
    varxmax = max;
}



/*
 * Add fuzzy set to array
 */
void FlFVar::add_value_set(FlFSet *fset)
{
    int n = varsets.get_size();
    
    varsets.set_size(n + 1);
    varsets[n] = fset;
}

void FlFVar::add_value_set(FlFSet &fset)
{
    add_value_set(&fset);
}


void FlFVar::add_value_set(int i, FlFSet *fset)
{
    int n = varsets.get_size();

    if(i < 0)
    {
      fatal(NIL, "FlFVar ", name(), ": illegal index < 0");
    }
    else
    {
        if(i >= n)
            varsets.set_size(i + 1);
        varsets[i] = fset;
    }
}

void FlFVar::add_value_set(int i, FlFSet &fset)
{
    add_value_set(i, &fset);
}



/*
 * Get fuzzy set from array
 */
FlFSet *FlFVar::get_value_set(int i)
{
    int n = varsets.get_size();
    
    if(i < 0)
        fatal(NIL, "FlFVar ", name(), ": illegal index < 0");
    else
        return i>=n ? NIL : (FlFSet *)( varsets[i] );
    /**NOT REACHED**/
    return NIL;
}



/*
 * Get membership value from indexed fuzzy set
 */
double FlFVar::get_membership(int i)
{
    int n = varsets.get_size();
    FlFSet *set;
    
    if(i < 0)
        fatal(NIL, "FlFVar ", name(), ": illegal index < 0");
    else
    {
        set = i>=n ? NIL : (FlFSet *)( varsets[i] );
        return set ? set->get_membership( value() ) : 0. ;
    }
    /**NOT REACHED**/
    return 0.;
}
    


/*
 * Get/set value
 */
double FlFVar::set_value(double x)
{
    double old = varvalue;
    varvalue = x;
    return old;
}

double FlFVar::value(double x)
{
    double old = varvalue;
    varvalue = x;
    return old;
}


double FlFVar::get_value() const
{
    return varvalue;
}

double FlFVar::value() const
{
    return varvalue;
}


/*
 * Get/set fuzzy value
 */
FlFSet *FlFVar::set_fuzzy_value(FlFSet *x)
{
    FlFSet *old = varfvalue;
    varfvalue = x;
    return old;
}

FlFSet *FlFVar::fuzzy_value(FlFSet *x)
{
    FlFSet *old = varfvalue;
    varfvalue = x;
    return old;
}


FlFSet *FlFVar::get_fuzzy_value() const
{
    return varfvalue;
}

FlFSet *FlFVar::fuzzy_value() const
{
    return varfvalue;
}


/*
 * Get xmin/xmax
 */
double FlFVar::get_xmin() const
{
    return varxmin;
}

double FlFVar::get_xmax() const
{
    return varxmax;
}

double FlFVar::xmin() const
{
    return varxmin;
}

double FlFVar::xmax() const
{
    return varxmax;
}



/*
 * Print fuzzy sets membership with value
 */
void FlFVar::print_membership()
{
    int n = varsets.get_size();
    FlFSet *fset;
    
    cout << "Variable \"" << name() << "\":  " << value() << endl;
    
    for(int i=0; i<n; i++)
    {
        fset = (FlFSet *)(varsets[i]);
        cout << "  \"" << fset->name()
             << "\"  " << fset->get_membership(value()) << endl;
    }
}

/*
 * 
 */
void FlFVar::generatePlotFiles(int steps, FlStringR tag) 
{
//   int n = varsets.get_size();
//   FlFSet *fset;
//   double x,y;
//   int i;
//   for( i=0; i<n; i++)
//     {
//       fset = (FlFSet *)(varsets[i]);
//       fset->generatePlotFiles(xmin(), xmax(), steps, "." + name() + tag);
//     }
  
//   ofstream gPlotFile(name() + tag + ".gp" );

//   gPlotFile << "#set term fig" << endl;
//   gPlotFile << "#set out \"" + name() + tag + ".fig\"" << endl;
//   gPlotFile << "set title" << endl;
//   gPlotFile << "set size 0.7, 0.7" << endl;
//   gPlotFile << "set nokey" << endl;
//   gPlotFile << "set yrange [0:1.4]" << endl;
//   gPlotFile << "set ytics 0,.2,1" << endl;
//   gPlotFile << "set ylabel \"Membership Value\" 3" << endl;
//   gPlotFile << "set xlabel \"" + name() + "\"" << endl;
//   gPlotFile << "" << endl;

//   for(i=0; i<n; i++)
//     {
//       fset = (FlFSet *)(varsets[i]);
//       gPlotFile << "set label \"" + fset->name() + "\" at " 
//         << fset->highestPoint(x,y) <<  "," << 1.06 + 0.06*i<< endl;
//     }

//   gPlotFile << "set arrow 1 from " << value() << ",0.0 to " 
//     << value() << ",1.4" << endl;

//   gPlotFile << "#set noarrow" << endl;
//   gPlotFile << "plot ";

//   for(i=0; i<n; i++)
//     {
//       fset = (FlFSet *)(varsets[i]);
//       gPlotFile << "\"" + fset->name() + "." + name() + tag + ".dat\" with lines " << i+1;
//       if (i != (n-1))
//         gPlotFile << ", ";
//     }

//   gPlotFile << endl;

//   gPlotFile.close();

}

/*
 * Plot
 */
void FlFVar::plot(int steps, FlStringR tag) 
{
//   int n = varsets.get_size();
//   FlPipe p;
    
//   generatePlotFiles(steps, tag);

//   ifstream gPlotFile(name() + tag + ".gp" );
    
//   p.open("gnuplot");
//   ostream &gPlot = p.out();
//   istream &in  = p.in();
  
//   gPlot << gPlotFile.rdbuf() << endl;

//   cout << "Press RETURN to continue.";
//   cin.get(); 

//   gPlot << "exit" << endl;
    
//   gPlotFile.close();
//   p.close();

}
    

/***** Default I/O member function for FuzzyLib classes **************************/

// FlNormal output
void FlFVar::print(ostream &strm) const
{
    strm << "var " << name() << "(" << xmin() << ", " << xmax() << ")" << endl
         << "{" << endl;
    int n = varsets.get_size();
    for(int i=0; i<n; i++)
        strm << "\t" << varsets.get(i) << endl;
    strm << "};" << endl;
}

// Debug output
void FlFVar::dump(ostream &strm) const
{
    strm << "FlFVar { $Revision: 1.6 $" << endl
         << "\"" << name() << "\": value=" << value() 
         << " xmin=" << xmin() << " xmax=" << xmax() << endl
         << "fuzzy sets:" << endl;
    int n = varsets.get_size();
    for(int i=0; i<n; i++)
         varsets.get(i)->dump(strm);
    strm << "}" << endl;
}

FlArrayObject* FlFVar::get_varsets() 
{
   return &varsets;
}
