//    module ParaSet.h                                                        //
//                                                                            //
//    Base class for TParameter. Encapsulates only those parameters that are  //
//    chosen within the parameter tuning.                                     //
//    See source or http://www.newty.de/pnc2/sdocu.html for more information. //
//                                                                            //
//    copyright (c) 2001-2003 by Lars Haendel                                 //
//    home: www.newty.de                                                      //
//                                                                            //
//    This program is free software; you can redistribute it and/or modify    //
//    it under the terms of the GNU General Public License as published by    //
//    the Free Software Foundation as version 2 of the License.               //
//                                                                            //
//    This program is distributed in the hope that it will be useful,         //
//    but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//    GNU General Public License for more details.                            //
//                                                                            //
//    You should have received a copy of the GNU General Public License       //
//    along with this program; if not, write to the Free Software             //
//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               //
//                                                                            //

#ifndef PARA_SET_H
#define PARA_SET_H

#include <values>          // due to:  MAXFLOAT
#include <iostream>        //          ofstream ...

#include "stdlist.h"       //          simple single linked list
#include "data.h"          //          TData

#ifdef BUILDER
using namespace std;

// routines to get/calculate parameter maximum value
const int Max_P_Min(const TData*const& data);  // max is data->nTup()/2
const int Max_w_COD(const TData*const& data);  // max is data->nVar()-2

// parameter name, defaults, minima, maxima and integer flag
#define WNAME (int) 18     // # characters (width) used to write parameter names to file
#define PREC_PARA 3        // precision (counted from most significant digit) to display parameters sigma and w_COD
                           // note: used in messages and Gui but NOT on saving/loading

#define SZ_N_INT            "N_Int"
#define DEF_N_INT          (int)   10          // # output intervals
#define MIN_N_INT          (int)   2
#define MAX_N_INT          (int)   1024
#define INT_N_INT          (bool)  true

#define SZ_W_COD            "w_COD"
#define DEF_W_COD          (float) 0.0
#define MIN_W_COD          (float) 0.0          // max is data->nVar()-2
#define INT_W_COD          (bool)  false

#define SZ_ETA              "Eta"
#define DEF_ETA            (float) 0.2
#define MIN_ETA            (float) 0.0
#define MAX_ETA            (float) 1.0
#define INT_ETA            (bool)  false

#define SZ_W_KERNEL         "W_Kernel"
#define DEF_W_KERNEL       (float) 2            // classificaion only, used in prediction routines
#define MIN_W_KERNEL       (float) 1.0
#define MAX_W_KERNEL       (float) 100          // no hard maximum, may be changed to whatever you like
#define INT_W_KERNEL       (bool)  false

#ifndef RELEASE                                 // obsolete in release versions
#define SZ_W_KERNEL_MIN     "W_Kernel_Min"
#define DEF_W_KERNEL_MIN   (float) 0.0          // classification only, used in prediction routines
#define MIN_W_KERNEL_MIN   (float) 0.0
#define MAX_W_KERNEL_MIN   (float) 1.0
#define INT_W_KERNEL_MIN   (bool)  false

#define SZ_SIGMA            "Sigma"
#define DEF_SIGMA          (float) 0.01         // regression only, used in prediction routines
#define MIN_SIGMA          (float) 0.0001
#define MAX_SIGMA          (float) 0.5
#define INT_SIGMA          (bool)  false

#define SZ_P_MIN           "p_min"
#define DEF_P_MIN          (int)   2            // min. cuboid mass: ignore those with lower mass
#define MIN_P_MIN          (int)   0            // max is data->nTup()/2
#define INT_P_MIN          (bool)  true

#define SZ_PRUNE            "Prune"
#define DEF_PRUNE          (bool)  true         // flag: prune cuboids after learning
#define MIN_PRUNE          (int)   0
#define MAX_PRUNE          (int)   1
#define INT_PRUNE          (bool)  true

#define SZ_WEIGHTS          "Weights"
#define DEF_WEIGHTS        (bool)  true         // flag: use feature weights
#define MIN_WEIGHTS        (int)   0
#define MAX_WEIGHTS        (int)   1
#define INT_WEIGHTS        (bool)  true

#define SZ_METRIC          "Metric"
#define DEF_METRIC         (float) 1.0          // metric parameter (1=city block distance, 2=euclidean distance)
#define MIN_METRIC         (float) 0.0
#define MAX_METRIC         (float) 2.0
#define INT_METRIC         (bool)  false
#define DEF_EUCLID         (bool) false
#define SZ_EUCLID          "Euclid"

#ifndef RELEASE                                 // obsolete in release versions
#define SZ_DIF_MAX          "DifMax"
#define DEF_DIF_MAX        (float) 0
#define MIN_DIF_MAX        (float) 0
#define MAX_DIF_MAX        (float) 1
#define INT_DIF_MAX        (bool)  false

#define SZ_NOISE           "Noise"
#define DEF_NOISE          (float) 0
#define MIN_NOISE          (float) 0.0
#define MAX_NOISE          (float) 1.0
#define INT_NOISE          (bool)  false

// class encapsulates a parameter set for the PNC cluster/learn algorithm
class TParaSet

   // constructor: initialize standard values
   TParaSet() { SetStandardValues(); } ;

   // write (short) parameter names in one header line
   static void WriteDescription(ofstream& file, const bool& f_Regression=true);

   // write parameter values with or without their name
   void WriteParameters(ostream& file, const bool& f_Regression=true, const bool& f_Names=false) const;

   // initialize parameters with hard coded default values from para.h
   // note: if data object is passed, then the parameter 'w_COD' is initialized using a heuristic
   void SetStandardValues(const TData*const& data=NULL);

   const char* CheckParameters();   // check if parameter values are within valid range; returns non-empty string if not

   void Save(ofstream& file, const bool& f_Commented=false) const;               // save parameter to file (ofstream)
   bool Load(ifstream& file, int& line);                                         // load from file

// private:

   // parameters
   int   N_Int;            // # intervals/bins used for discretization of continous output values
   float w_COD;            // a tuple with different class is considered as negative example if less than w_COD
                           // variables (or their sum of weights) are outside
   float Eta;              // maximal acceptable ratio of negative examples

   float W_Kernel;         // (classification only) neighbourhood kernel in multiples of reference distance
   float Sigma;            // (regression only) width of fuzzy-membership fucntions outside the cuboids

   int   p_min;            // minimum cuboid mass
   bool  Prune;            // prune model after learning
   bool  Weights;          // use mutual information as feature weight
   float Metric;           // minkowski metric parameter: (sum |d^metric| )^1/metric

   #ifndef RELEASE      // obsolete in release versions
   float W_Kernel_Min;     // (classification only) minimum neighbourhood kernel
   int   DifMax;           // only tuples whose (quantized) output value differs more than <diffMax> are regarded as
                           // negative examples
   float Noise;            // shrink rectangles

   // tags used by the tuning routines
   bool Relearn, Skip;