/****************************************************************************
 * 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: FlFRule --- Fuzzy rule
 *
 ****************************************************************************/

#include <FlArrayDouble.h>

#include "FlFRule.h"

#include <limits.h>
#include <float.h>

using std::endl;


/*
 * Add clause to LHS
 */
void FlFRule::add_lhs(FlFClause *clause)
{
    int n = lhs.get_size();
    
    lhs.set_size(n + 1);
    lhs[n] = clause;
}

void FlFRule::add_lhs(FlFClause &clause)
{
    add_lhs(&clause);
}



/*
 * Add clause to RHS
 */
void FlFRule::add_rhs(FlFClause *clause)
{
    int n = rhs.get_size();
    
    rhs.set_size(n + 1);
    rhs[n] = clause;
}

void FlFRule::add_rhs(FlFClause &clause)
{
    add_rhs(&clause);
}



/*
 * Get/set certainty
 */
double FlFRule::set_certainty(double x)
{
    double old = r_certainty;
    r_certainty = x;
    return old;
}

double FlFRule::certainty(double x)
{
    double old = r_certainty;
    r_certainty = x;
    return old;
}


double FlFRule::get_certainty() const
{
    return r_certainty;
}

double FlFRule::certainty() const
{
    return r_certainty;
}



/*
 * Get # of clauses
 */
int FlFRule::get_n_lhs() const
{
    return lhs.get_size();
}

int FlFRule::get_n_rhs() const
{
    return rhs.get_size();
}



/*
 * Get clause from LHS
 */
FlFClause *FlFRule::get_lhs(int i) const
{
    return (FlFClause *)( lhs.get(i) );
}



/*
 * Get clause from RHS
 */
FlFClause *FlFRule::get_rhs(int i) const
{
    return (FlFClause *)( rhs.get(i) );
}



/*
 * Aggregate LHS of rule
 */
double FlFRule::aggregate(/**Operator!**/)
{
    int i;
    int n = get_n_lhs();
    FlArrayDouble a(n);
    FlFVar *v;
    FlFSet *s;
    
    for(i=0; i<n; i++)
    {
        v = ((FlFClause *)( lhs[i] ))->var;
        s = ((FlFClause *)( lhs[i] ))->value;
       
        a[i] = s->get_membership( v->value() );
    }
    
    /**FIXME: Use operator instead of min()**/
    double min = DBL_MAX;
    for(i=0; i<n; i++)
        if(a[i] < min)
            min = a[i];
    
    agg_value = min * certainty();
    return agg_value;
}



/*
 * Get result of aggregate()
 */
double FlFRule::aggregate_value() const
{
    return agg_value;
}



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

// Normal output
void FlFRule::print(ostream &strm) const
{
    int i, l, r;
        
    l = get_n_lhs();
    r = get_n_rhs();
        
    strm << "if( ";
    for(i=0; i<l; i++)
    {
        if(i > 0)
            strm << "    ";
        ((FlFClause *)( lhs.get(i) ))->print_clause(strm, TRUE);
        if(i < l-1)
            strm << " &&" << endl;
        if(i == l-1)
            strm << " )" << endl;
    }
    strm << "{" << endl;
    strm << "\tcertainty=" << certainty() << ";" << endl;
    for(i=0; i<r; i++)
    {
        strm << "\t";
        ((FlFClause *)( rhs.get(i) ))->print_clause(strm, FALSE);
        strm << ";" << endl;
    }
    strm << "}" << endl;
}

// Debug output
void FlFRule::dump(ostream &strm) const
{
    strm << "FlFRule { $Revision: 1.4 $" << endl
         << "certainty=" << r_certainty << endl
         << "lhs=" << endl;
    lhs.dump(strm);
    strm << "rhs=" << endl;
    rhs.dump(strm);
    strm << "}" << endl;
}
