/*-------------------------------------------------------------------------------------*/
/*  NOMAD - Nonsmooth Optimization by Mesh Adaptive Direct search - version 3.0.0      */
/*                                                                                     */
/*  Copyright (C) 2001-2008  Mark Abramson        - the Boeing Company, Seattle        */
/*                           Charles Audet        - Ecole Polytechnique, Montreal      */
/*                           Gilles Couture       - Ecole Polytechnique, Montreal      */
/*                           John Dennis          - Rice University, Houston           */
/*                           Sebastien Le Digabel - Ecole Polytechnique, Montreal      */
/*                                                                                     */
/*  funded in part by AFOSR and Exxon Mobil                                            */
/*                                                                                     */
/*  Author: Sebastien Le Digabel                                                       */
/*                                                                                     */
/*  Contact information:                                                               */
/*    Ecole Polytechnique de Montreal - GERAD                                          */
/*    C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada                  */
/*    e-mail: Sebastien.Le.Digabel@gerad.ca                                            */
/*    phone : 1-514-340-6053 #6673                                                     */
/*    fax   : 1-514-340-5665                                                           */
/*                                                                                     */
/*  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, either version 3 of the License, or (at your option) any later         */
/*  version.                                                                           */
/*                                                                                     */
/*  This program 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 General Public License for more details.          */
/*                                                                                     */
/*  You should have received a copy of the GNU General Public License along with this  */
/*  program. If not, see <http://www.gnu.org/licenses/>.                               */
/*                                                                                     */
/*  You can find information on the NOMAD software at www.gerad.ca/nomad               */
/*-------------------------------------------------------------------------------------*/
#include "Parameters.hpp"
using namespace std;

/*----------------------------------------*/
/*               constructor              */
/*----------------------------------------*/
Parameters::Parameters ( ostream & out ) : _out(out) {
  init();
}

/*----------------------------------------*/
/*                destructor              */
/*----------------------------------------*/
Parameters::~Parameters (void) {
  delete_x0s();
  reset_variable_groups ( _var_groups      );
  reset_variable_groups ( _user_var_groups );
}

/*----------------------------------------*/
/*             initializations            */
/*----------------------------------------*/
void Parameters::init (void) {

  // Misc. and algorithm parameters:
  _to_be_checked      = true;
  _seed               = static_cast<int>(time(NULL));
  _max_eval           = -1;
  _max_sim_bb_eval    = -1;
  _max_bb_eval        = -1;
  _max_time           = -1;
  _max_iterations     = -1;
  _cache_save_period  = 25;
  _snap_to_bounds     = true;
  _f_target.clear();
  _stat_sum_target.clear();
  _cache_file.clear();
  _problem_dir.clear();
  _tmp_dir.clear();

  // output files:
  _add_seed_to_file_names = true;
  _solution_file.clear();
  _history_file.clear();

  set_EPSILON ( DEFAULT_EPSILON );

  // Searches:
  _speculative_search = true;
  _LH_search_p0       = 0;
  _LH_search_pi       = 0;

  // Mesh:
  _mesh_update_basis.clear();
  _mesh_coarsening_exponent = 1;
  _mesh_refining_exponent   =-1;
  _initial_mesh_index       = 0;
  _max_mesh_index           = UNDEFINED_L;
  _initial_mesh_size.clear();
  _min_mesh_size.clear();
  _min_poll_size.clear();
  
  // Directions:
  _direction_types.clear();
  _sec_poll_dir_types.clear();
  _halton_seed = -1;

  // X0:
  reset_X0();

  // Variables:
  _dimension = -1;
  _lb.clear();
  _ub.clear();
  _fixed_variables.clear();
  _bb_input_types.clear();
  _bb_input_include_tag  = false;
  _bb_input_include_seed = false;
  _bb_redirection        = true;
  _all_continuous        = true;
  reset_variable_groups ( _var_groups      );
  reset_variable_groups ( _user_var_groups );

  // Barrier:
  _rho                    = 0.1;
  _h_min                  = 0.0;
  _h_max_0                = INF;
  _h_norm                 = _L2_;
  _has_constraints        = false;
  _has_filter_constraints = false;
  _barrier_type           = _EB_;

  // outputs:
  _index_obj.clear();
  _bb_exe.clear();
  _bb_output_types.clear();
  _index_stat_sum = -1;
  _index_stat_avg = -1;

  // surrogates:
  _sgte_exe.clear();
  _sgte_cache_file.clear();
  _sgte_eval_sort = true;
  _sgte_cost      = -1;
  _sgte_max_eval  = -1;

  // opportunistic strategy:
  _opportunistic_eval           = true;
  _opportunistic_min_nb_success = -1;
  _opportunistic_min_eval       = -1;
  _opportunistic_lucky_eval     = false;
  _opportunistic_min_f_imprvmt.clear();

  // DISPLAY_DEGREE's set to max value for DEBUG:
#ifdef DEBUG
  _display_degree         = 4;
  _poll_display_degree    = 4;
  _search_display_degree  = 4;
  _updates_display_degree = 4;
  set_POINT_DISPLAY_LIMIT (-1);
#else
  _display_degree         = 2;
  _poll_display_degree    = 2;
  _search_display_degree  = 2;
  _updates_display_degree = 2;
  set_POINT_DISPLAY_LIMIT (DEFAULT_POINT_DISPLAY_LIMIT);
#endif

  _display_stats.clear();
  reset_stats_file();
}

/*----------------------------------------*/
/*      delete the list of x0 points      */
/*      (std::vector<Point *> _x0s)       */
/*----------------------------------------*/
void Parameters::delete_x0s ( void ) {
  size_t x0n = _x0s.size();
  for ( size_t i = 0 ; i < x0n ; ++i )
    delete _x0s[i];
  _x0s.clear();
}

/*----------------------------------------*/
/*           reset parameter X0           */
/*----------------------------------------*/
void Parameters::reset_X0 ( void ) {
  _to_be_checked = true;
  delete_x0s();
  _x0_cache_file.clear();
}

/*---------------------------*/
/*  Checks a directory name  */
/*---------------------------*/
bool Parameters::check_directory ( string & s ) {

  // step 1: remove spaces at the begining:
  size_t i = 0 , ns = s.size();
  while ( i < ns && s[i] == ' ' )
    ++i;
  string ss;
  while ( i < ns )
    ss.push_back(s[i++]);
  if ( ss.empty() )
    return false;
  s = ss;

  // step 2: replace '/' or '\' with DIR_SEP:
  i  = 0;
  ns = s.size();
  while ( i < ns ) {
    if ( s[i]=='/' || s[i]=='\\' )
      s[i] = DIR_SEP;
    ++i;
  }

  // step 3: add DIR_SEP at the end:
  if ( i >= 1 ) {
    if (s[i-1] != DIR_SEP) {
      s += DIR_SEP;
    }
  }
  else {
    s = ".";
    s.push_back(DIR_SEP);
  }

  return true;
}

/*-------------------------------------------------------------------------*/
/*        interpretation of the Parameter_Entry for VARIABLE_GROUP         */
/*-------------------------------------------------------------------------*/
void Parameters::interpret_var_groups ( const Parameter_Entries & entries ) {

  int                          i , j , k;
  set<int>                     var_indexes;
  list<string>::const_iterator it , end;
  Parameter_Entry            * pe = entries.find ( "VARIABLE_GROUP" );

  while (pe) {      

    // just one variable index (can be '*' or a range of indexes 'i-j'):
    if ( pe->get_nb_values() == 1 ) {

      it = pe->get_values().begin();
      if ( !string_to_index_range ( *it , i , j , &_dimension ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: VARIABLE_GROUP" );

      for ( k = j ; k >= i ; --k )
	var_indexes.insert(k);
    }

    // list of variable indexes:
    else {
      end = pe->get_values().end();
      for ( it = pe->get_values().begin() ; it != end ; ++it ) {
	if ( !NOMAD::atoi ( *it , i ) )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
		"incorrect parameter: VARIABLE_GROUP" );
	var_indexes.insert(i);
      }
    }

    set_VARIABLE_GROUP ( var_indexes         ,
			 _direction_types    ,
			 _sec_poll_dir_types ,
			 -1                    );

    var_indexes.clear();

    pe->set_has_been_interpreted();
    pe = pe->get_next();
  }
}

/*-------------------------------------------------------------------------*/
/*   interpretation of the Parameter_Entry for bounds and fixed variables  */
/*     (param_name = "LOWER_BOUND" or "UPPER_BOUND" or "FIXED_VARIABLE")   */
/*-------------------------------------------------------------------------*/
void Parameters::interpret_bounds_and_fixed_vars ( const Parameter_Entries & entries    ,
						   const string            & param_name   ) {

  // param_name == LOWER_BOUND or UPPER_BOUND or FIXED_VARIABLE:
  if ( param_name != "LOWER_BOUND"    &&
       param_name != "UPPER_BOUND"    &&
       param_name != "FIXED_VARIABLE"    )
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "wrong use of Parameters::interpret_bounds_and_fixed_vars()" );
  
  Parameter_Entry              * pe = entries.find ( param_name );
  list<string>::const_iterator   it;
  int                            i, j, k;
  NOMAD::Double                  v;
  string                         err;
  string                         file_name;
  ifstream                       in;

  while (pe) {

    // file name or just one index:
    if ( pe->get_nb_values() == 1 ) {

      // special case for FIXED_VARIABLE without value
      // (the value will be taken from x0, if unique):
      if ( isdigit ( (*pe->get_values().begin())[0] ) || *pe->get_values().begin() == "*" ) {

	if ( param_name[0] != 'F' ) {
	  err =  "incorrect parameter: " + param_name
  	    + " (only one argument, which is not a file name)";
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}

	if ( _x0s.size() != 1 || !_x0_cache_file.empty() )
  	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
 		"FIXED_VARIABLE with only a variable index and no unique x0" );
	
  	if ( !string_to_index_range ( *pe->get_values().begin() , i , j , &_dimension ) )
  	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
  				      "incorrect parameter: FIXED_VARIABLE" );

  	for ( k = i ; k <= j ; ++k )
  	  set_FIXED_VARIABLE ( k , (*_x0s[0])[k] );
      }


      // file name:
      else {
	
	file_name = _problem_dir + *pe->get_values().begin();

	in.open ( file_name.c_str() );
	
	if ( in.fail() ) {
	  err = "incorrect parameter: " + param_name +
	    " (could not open file \'" + file_name + "\')";
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}

	try {
	  switch ( param_name[0] ) {
	  case 'L':
	    _lb.reset(_dimension);
	    in >> _lb;
	    break;
	  case 'U':
	    _ub.reset(_dimension);
	    in >> _ub;
	    break;
	  case 'F':
	    _fixed_variables.reset(_dimension);
	    in >> _fixed_variables;
	  }
	}
	catch ( Point::Bad_Input & ) {
	  err = "incorrect parameter: " + param_name +
	    " (could not read file \"" + file_name  + "\")";
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}

	in.close();
      }
    }

    // vector form: all values on one row:
    else if ( pe->get_nb_values() == _dimension + 2 ) {

      if (!pe->is_unique()) {
	err = "incorrect parameter: " + param_name +
	      " (has been given in vector form with [] or () and is not unique)";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      it = pe->get_values().begin();
      
      if ( *it != "[" && *it != "(" ) {
	err = "incorrect parameter: " + param_name +
	      " (error in vector form with () or [])";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      
      ++it;
      for ( k = 0 ; k < _dimension ; ++k ) {
	if ( !v.atof(*it) ) {
	  err = "incorrect parameter: " + param_name;
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}

	++it;
	switch(param_name[0]) {
	case 'L': set_LOWER_BOUND    ( k , v );
	  break;
	case 'U': set_UPPER_BOUND    ( k , v );
	  break;
	case 'F': set_FIXED_VARIABLE ( k , v );
	}
      }

      if ( *it != "]" && *it != ")" ) {
	err = "incorrect parameter: " + param_name +
	      " (error in vector form with () or [])";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      
    }

    // indexed values:
    else {

      if (pe->get_nb_values() != 2) {
	err = "incorrect parameter: " + param_name;
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      it = pe->get_values().begin();
      if ( !string_to_index_range ( *it , i , j , &_dimension ) ) {
	err = "incorrect parameter: " + param_name;
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      ++it;
      if ( !v.atof(*it) ) {
	err = "incorrect parameter: " + param_name;
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      for ( k = j ; k >= i ; --k )
	switch (param_name[0]) {
	case 'L': set_LOWER_BOUND (k, v);
	  break;
	case 'U': set_UPPER_BOUND (k, v);
	  break;
	case 'F': set_FIXED_VARIABLE (k, v);
	}
    }
    pe->set_has_been_interpreted();
    pe = pe->get_next();
  }
}

/*-------------------------------------------------------------*/
/*  interpretation of the Parameter_Entry for mesh/poll sizes  */
/*-------------------------------------------------------------*/
void Parameters::interpret_mesh_sizes ( const Parameter_Entries & entries    ,
					const string            & param_name   ) {

  // param_name == "INITIAL_MESH_SIZE" or "MIN_MESH_SIZE" or "MIN_POLL_SIZE":
  if ( param_name != "INITIAL_MESH_SIZE" &&
       param_name != "MIN_MESH_SIZE"     &&
       param_name != "MIN_POLL_SIZE"        )
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "wrong use of Parameters::interpret_mesh_sizes()" );

  int                          i , j , k;
  NOMAD::Double                v;
  bool                         relative;
  string                       err;
  list<string>::const_iterator it;
  Parameter_Entry            * pe = entries.find ( param_name );

  while (pe) {

    // just one value:
    if ( pe->get_nb_values() == 1 ) {

      if ( !pe->is_unique() ) {
	err = "incorrect parameter: " + param_name
	  + " (has been given with just one value and is not unique)";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      if ( !v.relative_atof ( *pe->get_values().begin() , relative ) ) {
	err = "incorrect parameter: " + param_name;
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      if ( param_name[0] == 'I' )
	set_INITIAL_MESH_SIZE ( v , relative );
      else if ( param_name[4] == 'M' )
	set_MIN_MESH_SIZE     ( v , relative );
      else
	set_MIN_POLL_SIZE     ( v , relative );
    }

    // indexed form:
    else if ( pe->get_nb_values() == 2 ) {
      
      it = pe->get_values().begin();
      if ( !string_to_index_range ( *it , i , j , &_dimension ) ) {
	err = "incorrect parameter: " + param_name;
 	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      ++it;

      if ( !v.relative_atof( *it , relative ) ) {
	err = "incorrect parameter: " + param_name;
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      for ( k = i ; k <= j ; ++k ) {
	if ( param_name[0] == 'I' )
	  set_INITIAL_MESH_SIZE ( k , v , relative );
	else if ( param_name[4] == 'M' )
	  set_MIN_MESH_SIZE     ( k , v , relative );
	else
	  set_MIN_POLL_SIZE     ( k , v , relative );
      }
    }

    // vector form: all values on one row:
    else if ( pe->get_nb_values() == _dimension + 2 ) {

      if (!pe->is_unique()) {
	err = "incorrect parameter: " + param_name
	  + " (has been given in vector form with [] or () and is not unique)";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }

      it = pe->get_values().begin();
      
      if ( *it != "[" && *it != "(" ) {
	err = "incorrect parameter: " + param_name + " (error in vector form with () or [])";
  	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      
      ++it;
      for ( k = 0 ; k < _dimension ; ++k ) {
  	if ( !v.relative_atof ( *it , relative ) ) {
	  err = "incorrect parameter: " + param_name;
  	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}
 	++it;
	if ( param_name[0] == 'I' )
	  set_INITIAL_MESH_SIZE ( k , v , relative );
	else if ( param_name[4] == 'M' )
	  set_MIN_MESH_SIZE     ( k , v , relative );
	else
	  set_MIN_POLL_SIZE     ( k , v , relative );
      }

      if ( *it != "]" && *it != ")" ) {
	err = "incorrect parameter: " + param_name + " (error in vector form with () or [])";
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
    }

    else {
      err = "incorrect parameter: " + param_name;
      throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
    }

    pe->set_has_been_interpreted();
    pe = pe->get_next();
  }
}

/*-----------------------------------------------------------*/
/*  interpretation of the Parameter_Entry for BB_INPUT_TYPE  */
/*-----------------------------------------------------------*/
//    BB_INPUT_TYPE [ t1 t2 ... tn ]   # black-box input types (one type/variable)
// or BB_INPUT_TYPE i   t              # ti in { R , C , B , I } or { Real , Cat , Bin , Int }
// or BB_INPUT_TYPE i-j t
void Parameters::interpret_bb_input_type ( const Parameter_Entries & entries ) {

  int                          i , j , k;
  bb_input_type                bbit;
  list<string>::const_iterator it;
  Parameter_Entry            * pe = entries.find ( "BB_INPUT_TYPE" );

  while (pe) {

    // indexed form:
    if ( pe->get_nb_values() == 2 ) {
      
      it = pe->get_values().begin();
      if ( !string_to_index_range ( *it , i , j , &_dimension ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: BB_INPUT_TYPE" );
      ++it;
      if ( !string_to_bb_input_type ( *it , bbit ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: BB_INPUT_TYPE" );

      for ( k = i ; k <= j ; ++k )
	set_BB_INPUT_TYPE ( k , bbit );
    }

    // vector form: all values on one row:
    else if ( pe->get_nb_values() == _dimension + 2 ) {

      if (!pe->is_unique())
 	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      string ( "incorrect parameter: BB_INPUT_TYPE ")
	             + "(has been given in vector form with [] or () and is not unique)" );

      it = pe->get_values().begin();
      
      if ( *it != "[" && *it != "(" )
 	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	"incorrect parameter: BB_INPUT_TYPE (error in vector form with () or [])" );
      
      ++it;
      for ( k = 0 ; k < _dimension ; ++k ) {
 	if ( !string_to_bb_input_type ( *it , bbit ) )
 	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameter: BB_INPUT_TYPE" );
	++it;
	set_BB_INPUT_TYPE ( k , bbit );
      }

      if ( *it != "]" && *it != ")" )
 	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	"incorrect parameter: BB_INPUT_TYPE (error in vector form with () ot [])" );
    }

    else
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: BB_INPUT_TYPE" );

    pe->set_has_been_interpreted();
    pe = pe->get_next();
  }
}

/*------------------------------------------------*/
/*  interpretation of the Parameter_Entry for x0  */
/*------------------------------------------------*/
void Parameters::interpret_x0 ( const Parameter_Entries & entries ) {

  Parameter_Entry              * pe = entries.find ( "X0" );
  list<string>::const_iterator   it;
  int                            i , j , k , l;
  NOMAD::Double                  v;
  Point                          tmp_x0;
  vector<int>                    indexes;

  while (pe) {

    tmp_x0.reset(_dimension);

    // File name:
    if ( pe->get_nb_values() == 1 )
      set_X0 ( *pe->get_values().begin() );

    // Vector form: all values on one row:
    else if ( pe->get_nb_values() == _dimension + 2 ) {
      
      it = pe->get_values().begin();
      
      if ( *it != "[" && *it != "(" ) {

	// particular case with n=1 and 3 entry values:
	// example: X0 1 0 4.0 (first coordinate of the 2nd x0 point put to 4.0)
	if ( _dimension == 1 ) {
	  
	  it = pe->get_values().begin();
	  
	  if ( !NOMAD::atoi ( *it , l ) )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );

	  i = static_cast<int> ( indexes.size() );
	  if ( l > i )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
	  else if ( l == i ) {
	    l = static_cast<int> ( _x0s.size() );
	    indexes.push_back ( l );
	    set_X0 ( tmp_x0 );
	  }
	  else
	    l = indexes[l];
      
	  ++it;
	  if ( !string_to_index_range ( *it , i , j , &_dimension ) )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
	  
	  if ( i != 0 && j != 0 )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );

	  ++it;
  	  if ( !v.atof(*it) )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
	  
	  (*_x0s[l])[0] = v;
	}
	
	else
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
		"incorrect parameter: X0 (error in vector form with () or [])" );
      }
      
      else {

	++it;
	for ( k = 0 ; k < _dimension ; ++k ) {
   	  if ( !v.atof(*it) )
	    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
	  ++it;
	  tmp_x0[k] = v;
	}
	
	if ( *it != "]" && *it != ")" )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
		"incorrect parameter: X0 (error in vector form with () or [])" );
	
	set_X0 ( tmp_x0 );
      }
    }

    // Indexed values without x0 index (must be unique)
    // (example: X0 0-5 1.0):
    else if ( pe->get_nb_values() == 2 ) {

      it = pe->get_values().begin();
      if ( !string_to_index_range ( *it , i , j , &_dimension ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
      ++it;
      if ( !v.atof(*it) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
      
      if ( indexes.empty() ) {
	l = static_cast<int> ( _x0s.size() );
	indexes.push_back ( l );
	set_X0 ( tmp_x0 );
      }
      else
	l = indexes[0];
      
      for ( k = j ; k >= i ; --k )
	(*_x0s[l])[k] = v;
    }

    // Indexed values with x0 index
    //  example: X0 0 0-5 1.0 --> first x0 point
    //           X0 1 0-5 2.0 --> 2nd x0 point
    else {
      
      if ( pe->get_nb_values() != 3 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );

      it = pe->get_values().begin();
	
      if ( !NOMAD::atoi ( *it , l ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );

      i = static_cast<int> ( indexes.size() );
      if ( l > i )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
      else if ( l == i ) {
	l = static_cast<int> ( _x0s.size() );
	indexes.push_back ( l );
	set_X0 ( tmp_x0 );
      }
      else
	l = indexes[l];
      
      ++it;
      if ( !string_to_index_range ( *it , i , j , &_dimension ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
      
      ++it;
      if ( !v.atof(*it) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: X0" );
      
      for ( k = j ; k >= i ; --k )
	(*_x0s[l])[k] = v;
      
    }
    pe->set_has_been_interpreted();
    pe = pe->get_next();
  }
}

/*---------------------------------------*/
/*  Converts a string into a hnorm_type  */
/*---------------------------------------*/
bool Parameters::get_hnorm_type ( const string & s , hnorm_type & hn ) {
  string ss = s;
  NOMAD::toupper(ss);
  if (ss == "L1") {
    hn = _L1_;
    return true;
  }
  if (ss == "L2") {
    hn = _L2_;
    return true;
  }
  if (ss == "LINF") {
    hn = _LINF_;
    return true;
  }
  return false;
}

/*-------------------------------------------*/
/*  Converts a string into a bb_output_type  */
/*-------------------------------------------*/
bool Parameters::get_bb_output_type ( const string & s , bb_output_type & bbot ) {
  string ss = s;
  NOMAD::toupper(ss);

  if ( ss == "OBJ" ) {
    bbot = _OBJ_;
    return true;
  }
  if ( ss == "EB" ) {
    bbot = _EB_;
    return true;
  }
  if ( ss == "PB" ) {
    bbot = _PB_;
    return true;
  }
  if ( ss == "PEB" ) {
    bbot = _PEB_P_;
    return true;
  }
  if ( ss == "F" ) {
    bbot = _F_;
    return true;
  }
  if ( ss == "STAT_AVG" ) {
    bbot = _STAT_AVG_;
    return true;
  }
  if ( ss == "STAT_SUM" ) {
    bbot = _STAT_SUM_;
    return true;
  }
  if ( ss == "NOTHING" || ss == "-" ) {
    bbot = _NOTHING_;
    return true;
  }
  return false;
}

/*----------------------------------------*/
/*         Reads a parameters file        */
/*----------------------------------------*/
void Parameters::read ( const string & param_file ) {

  // Parameters will have to be checked:
  _to_be_checked = true;

  // PROBLEM_DIR:
  // ------------
  _problem_dir.clear();
  size_t k = param_file.find_last_of ( DIR_SEP );
  if ( k >= 0 && k < param_file.size() )
    _problem_dir = param_file.substr (0,k) + DIR_SEP;
  else
    _problem_dir = string(".") + DIR_SEP;

  // open the parameters file:
  string   err = "could not open parameters file \"" + param_file + "\"";
  ifstream in;
  if ( NOMAD::check_read_file ( param_file ) ) {
    in.open ( param_file.c_str() );
    if ( !in.fail() )
      err.clear();
  }
  if ( !err.empty() ) {
    in.close();
    throw Wrong_Parameters_File ( __FILE__ , __LINE__ , err );
  }

  // the set of entries:
  Parameter_Entries entries;

  // the file is read: fill the set 'entries' of Parameter_Entry:
  Parameter_Entry * pe;
  string            s;
  while ( in.good() && !in.eof() ) {

    s.clear();
    
    getline ( in , s );

    if ( !in.fail() && !s.empty() ) {
      pe = new Parameter_Entry (s);
      if ( pe->is_ok() )
	entries.insert (pe); // pe will be deleted by ~Parameter_Entries()
      else {
	if ( pe->get_name() != "" && pe->get_nb_values() == 0 ) {
	  err = "incorrect parameter: " + pe->get_name();
	  delete pe;
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
	}
	delete pe;
      }
    }
  }

  // the file is closed:
  in.close();

  // entries display:
  if ( _display_degree >= 4 )
    _out << endl << "parsing of \"" << param_file << "\":\n"
	 << entries << endl;

  // interpret and set the entries using SET methods:
  list<string>::const_iterator it , end;
  int                          i , j , m;
  NOMAD::Double                d;

  /*----------------------------------------------*/

  // EPSILON:
  // --------
  {
    pe = entries.find ( "EPSILON" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: EPSILON not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: EPSILON" );
      set_EPSILON (d);
      pe->set_has_been_interpreted();     
    }
  }

  // MESH_UPDATE_BASIS:
  // ------------------
  {
    pe = entries.find ( "MESH_UPDATE_BASIS" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MESH_UPDATE_BASIS not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MESH_UPDATE_BASIS" );
      set_MESH_UPDATE_BASIS (d);
      pe->set_has_been_interpreted();     
    }
  }

  // INITIAL_MESH_INDEX:
  // -------------------
  {
    pe = entries.find ( "INITIAL_MESH_INDEX" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: INITIAL_MESH_INDEX not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: INITIAL_MESH_INDEX" );
      pe->set_has_been_interpreted();
      set_INITIAL_MESH_INDEX (i);
    }
  }

  // MESH_REFINING_EXPONENT:
  // -----------------------
  {
    pe = entries.find ( "MESH_REFINING_EXPONENT" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: MESH_REFINING_EXPONENT not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MESH_REFINING_EXPONENT" );
      pe->set_has_been_interpreted();
      set_MESH_REFINING_EXPONENT (i);
    }
  }

  // MESH_COARSENING_EXPONENT:
  // -------------------------
  {
    pe = entries.find ( "MESH_COARSENING_EXPONENT" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: MESH_COARSENING_EXPONENT not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MESH_COARSENING_EXPONENT" );
      pe->set_has_been_interpreted();
      set_MESH_COARSENING_EXPONENT (i);
    }
  }

  // MAX_MESH_INDEX:
  // ---------------
  {    
     pe = entries.find ( "MAX_MESH_INDEX" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_MESH_INDEX not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_MESH_INDEX" );
      pe->set_has_been_interpreted();
      set_MAX_MESH_INDEX (i);
    }
  }

  // HALTON_SEED:
  // ------------
  {
    pe = entries.find ( "HALTON_SEED" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: HALTON_SEED not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: HALTON_SEED" );
      pe->set_has_been_interpreted();
      set_HALTON_SEED (i);
    }
  }

  // POINT_DISPLAY_LIMIT:
  // --------------------
  {
    pe = entries.find ( "POINT_DISPLAY_LIMIT" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: POINT_DISPLAY_LIMIT not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: POINT_DISPLAY_LIMIT" );
      set_POINT_DISPLAY_LIMIT (i);
      pe->set_has_been_interpreted();     
    }
  }

  // DIMENSION:
  // ----------
  {
    _dimension = -1;
    pe = entries.find ( "DIMENSION" );
    
    if (!pe)
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: DIMENSION not found" );

    if (!pe->is_unique())
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: DIMENSION not unique" );

    int dim;
    if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), dim) )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: DIMENSION" );

    pe->set_has_been_interpreted();

    set_DIMENSION (dim);
  }
  
  // SNAP_TO_BOUNDS:
  // ---------------
  {
    pe = entries.find ( "SNAP_TO_BOUNDS" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SNAP_TO_BOUNDS not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SNAP_TO_BOUNDS" );
      set_SNAP_TO_BOUNDS (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // SPECULATIVE_SEARCH:
  // -------------------
  {
    pe = entries.find ( "SPECULATIVE_SEARCH" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SPECULATIVE_SEARCH not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SPECULATIVE_SEARCH" );
      set_SPECULATIVE_SEARCH (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // LH_SEARCH:
  // ----------
  {
    pe = entries.find ( "LH_SEARCH" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: LH_SEARCH not unique" );
      if ( pe->get_nb_values() != 2 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: LH_SEARCH" );
      it = pe->get_values().begin();

      if ( !NOMAD::atoi (*it++ , i) || i < 0 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: LH_SEARCH" );

      if ( !NOMAD::atoi (*it , j) || j < 0 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: LH_SEARCH" );

      set_LH_SEARCH ( i , j );
      pe->set_has_been_interpreted();
    }
  }

  // Opportunistic strategy:
  // -----------------------
  {
    // OPPORTUNISTIC_EVAL:
    pe = entries.find ( "OPPORTUNISTIC_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: OPPORTUNISTIC_EVAL not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: OPPORTUNISTIC_EVAL" );
      set_OPPORTUNISTIC_EVAL (i==1);
      pe->set_has_been_interpreted();
    }

    // OPPORTUNISTIC_MIN_NB_SUCCESS:
    pe = entries.find ( "OPPORTUNISTIC_MIN_NB_SUCCESS" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: OPPORTUNISTIC_MIN_NB_SUCCESS not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: OPPORTUNISTIC_MIN_NB_SUCCESS" );
      pe->set_has_been_interpreted();
      set_OPPORTUNISTIC_MIN_NB_SUCCESS (i);
    }

    // OPPORTUNISTIC_MIN_EVAL:
    pe = entries.find ( "OPPORTUNISTIC_MIN_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: OPPORTUNISTIC_MIN_EVAL not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: OPPORTUNISTIC_MIN_EVAL" );
      pe->set_has_been_interpreted();
      set_OPPORTUNISTIC_MIN_EVAL (i);
    }

    // OPPORTUNISTIC_MIN_F_IMPRVMT:
    pe = entries.find ( "OPPORTUNISTIC_MIN_F_IMPRVMT" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: OPPORTUNISTIC_MIN_F_IMPRVMT not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: OPPORTUNISTIC_MIN_F_IMPRVMT" );
      pe->set_has_been_interpreted();
      set_OPPORTUNISTIC_MIN_F_IMPRVMT (d);
    }

    // OPPORTUNISTIC_LUCKY_EVAL:
    pe = entries.find ( "OPPORTUNISTIC_LUCKY_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: OPPORTUNISTIC_LUCKY_EVAL not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: OPPORTUNISTIC_LUCKY_EVAL" );
      set_OPPORTUNISTIC_LUCKY_EVAL (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // Directions (DIRECTION_TYPE and SEC_POLL_DIRECTION_TYPE):
  // --------------------------------------------------------
  {
    direction_type dt;

    pe = entries.find ( "DIRECTION_TYPE" );
    while (pe) {

      if ( !interpret_direction_type ( pe->get_values() , dt ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: DIRECTION_TYPE" );
      set_DIRECTION_TYPE (dt);

      pe->set_has_been_interpreted();
      pe = pe->get_next();
    }

    pe = entries.find ( "SEC_POLL_DIRECTION_TYPE" );
    while (pe) {
      if ( !interpret_direction_type ( pe->get_values() , dt ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SEC_POLL_DIRECTION_TYPE" );
      set_SEC_POLL_DIRECTION_TYPE (dt);

      pe->set_has_been_interpreted();
      pe = pe->get_next();
    }
  }

  // MAX_ITERATIONS:
  // ---------------
  {
    pe = entries.find ( "MAX_ITERATIONS" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_ITERATIONS not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_ITERATIONS" );
      pe->set_has_been_interpreted();
      set_MAX_ITERATIONS (i);
    }
  }

  // MAX_EVAL:
  // ---------
  {
    pe = entries.find ( "MAX_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_EVAL not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: MAX_EVAL" );
      pe->set_has_been_interpreted();
      set_MAX_EVAL (i);
    }
  }

  // MAX_BB_EVAL:
  // ------------
  {
    pe = entries.find ( "MAX_BB_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_BB_EVAL not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_BB_EVAL" );
      pe->set_has_been_interpreted();
      set_MAX_BB_EVAL (i);
    }
  }

  // MAX_SIM_BB_EVAL:
  // ----------------
  {
    pe = entries.find ( "MAX_SIM_BB_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_SIM_BB_EVAL not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_SIM_BB_EVAL" );
      pe->set_has_been_interpreted();
      set_MAX_SIM_BB_EVAL (i);
    }
  }

  // MAX_SGTE_EVAL:
  // --------------
  {
    pe = entries.find ( "MAX_SGTE_EVAL" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_SGTE_EVAL not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_SGTE_EVAL" );
      pe->set_has_been_interpreted();
      set_MAX_SGTE_EVAL (i);
    }
  }

  // MAX_TIME:
  // ---------
  {
    pe = entries.find ( "MAX_TIME" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_TIME not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()), i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MAX_TIME" );

      pe->set_has_been_interpreted();
      set_MAX_TIME (i);
    }
  }

  // F_TARGET:
  // ---------
  {
    pe = entries.find ( "F_TARGET" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: F_TARGET not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: F_TARGET" );
      pe->set_has_been_interpreted();
      set_F_TARGET (d);
    }
  }

  // STAT_SUM_TARGET:
  // ----------------
  {
    pe = entries.find ( "STAT_SUM_TARGET" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: STAT_SUM_TARGET not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: STAT_SUM_TARGET" );
      pe->set_has_been_interpreted();
      set_STAT_SUM_TARGET (d);
    }
  }

  // RHO:
  // ----
  {
    pe = entries.find ( "RHO" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: RHO not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: RHO" );
      pe->set_has_been_interpreted();
      set_RHO(d);
    }
  }

  // H_MIN:
  // ------
  {
    pe = entries.find ( "H_MIN" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: H_MIN not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: H_MIN" );
      pe->set_has_been_interpreted();
      set_H_MIN(d);
    }
  }

  // H_MAX_0:
  // --------
  {
    pe = entries.find ( "H_MAX_0" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: H_MAX_0 not unique" );
      if ( pe->get_nb_values() != 1 || !d.atof ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "Incorrect parameter: H_MAX_0" );
      pe->set_has_been_interpreted();
      set_H_MAX_0(d);
    }
  }

  // H_NORM:
  // -------
  {
    pe = entries.find ( "H_NORM" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: H_NORM not unique" );
      hnorm_type hn;
      if ( pe->get_nb_values() != 1 || !get_hnorm_type ( *(pe->get_values().begin()) , hn ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "Incorrect parameter: H_NORM" );
      pe->set_has_been_interpreted();
      set_H_NORM (hn);
    }
  }

  // TMP_DIR:
  // --------
  {
    _tmp_dir.clear();
    pe = entries.find ( "TMP_DIR" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: TMP_DIR not unique" );

      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: TMP_DIR" );
      
      set_TMP_DIR ( *(pe->get_values().begin()) );

      pe->set_has_been_interpreted();
    }
  }

  // ADD_SEED_TO_FILE_NAMES:
  {
    pe = entries.find ( "ADD_SEED_TO_FILE_NAMES" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: ADD_SEED_TO_FILE_NAMES not unique" );

      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: ADD_SEED_TO_FILE_NAMES" );

      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: ADD_SEED_TO_FILE_NAMES" );
      set_ADD_SEED_TO_FILE_NAMES (i==1);

      pe->set_has_been_interpreted();
    }
  }

  // SOLUTION_FILE:
  // --------------
  {
    _solution_file.clear();
    pe = entries.find ( "SOLUTION_FILE" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SOLUTION_FILE not unique" );

      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SOLUTION_FILE" );
      
      set_SOLUTION_FILE ( *(pe->get_values().begin()) );

      pe->set_has_been_interpreted();
    }
  }

  // HISTORY_FILE:
  // -------------
  {
    _history_file.clear();
    pe = entries.find ( "HISTORY_FILE" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: HISTORY_FILE not unique" );

      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: HISTORY_FILE" );
      
      set_HISTORY_FILE ( *(pe->get_values().begin()) );

      pe->set_has_been_interpreted();
    }
  }

  // CACHE FILE:
  // -----------
  {
    _cache_file.clear();
    pe = entries.find ( "CACHE_FILE" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: CACHE_FILE not unique" );
      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: CACHE_FILE" );
      set_CACHE_FILE ( *(pe->get_values().begin()) );
      pe->set_has_been_interpreted();
    }
  }

  // SGTE_CACHE FILE:
  // ----------------
  {
    _sgte_cache_file.clear();
    pe = entries.find ( "SGTE_CACHE_FILE" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_CACHE_FILE not unique" );
      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_CACHE_FILE" );
      set_SGTE_CACHE_FILE ( *(pe->get_values().begin()) );
      pe->set_has_been_interpreted();
    }
  }


  // CACHE_SAVE_PERIOD:
  // ------------------
  {
    pe = entries.find ( "CACHE_SAVE_PERIOD" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: CACHE_SAVE_PERIOD not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: CACHE_SAVE_PERIOD" );
      set_CACHE_SAVE_PERIOD (i);
      pe->set_has_been_interpreted();
    }
  }

  // SGTE_COST:
  // ----------
  {
    pe = entries.find ( "SGTE_COST" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_COST not unique" );
      if ( pe->get_nb_values() != 1 || !NOMAD::atoi (*(pe->get_values().begin()) , i) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_COST" );
      set_SGTE_COST (i);
      pe->set_has_been_interpreted();
    }
  }

  // X0:
  // ---
  interpret_x0 ( entries );

  // FIXED_VARIABLE:
  // ---------------
  interpret_bounds_and_fixed_vars ( entries , "FIXED_VARIABLE");

  // LOWER_BOUND:
  // ------------
  interpret_bounds_and_fixed_vars ( entries , "LOWER_BOUND");

  // UPPER_BOUND:
  // ------------
  interpret_bounds_and_fixed_vars ( entries , "UPPER_BOUND");

  // BB_INPUT_TYPE:
  // --------------
  interpret_bb_input_type ( entries );

  // BB_INPUT_INCLUDE_TAG:
  // ---------------------
  {
    pe = entries.find ( "BB_INPUT_INCLUDE_TAG" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_INPUT_INCLUDE_TAG not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_INPUT_INCLUDE_TAG" );
      set_BB_INPUT_INCLUDE_TAG (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // BB_INPUT_INCLUDE_SEED:
  // ----------------------
  {
    pe = entries.find ( "BB_INPUT_INCLUDE_SEED" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_INPUT_INCLUDE_SEED not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_INPUT_INCLUDE_SEED" );
      set_BB_INPUT_INCLUDE_SEED (i==1);
      pe->set_has_been_interpreted();
    }
  }
  // BB_REDIRECTION:
  // ---------------
  {
    pe = entries.find ( "BB_REDIRECTION" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_REDIRECTION not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_REDIRECTION" );
      set_BB_REDIRECTION (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // INITIAL_MESH_SIZE, MIN_MESH_SIZE, and MIN_POLL_SIZE:
  // ----------------------------------------------------
  interpret_mesh_sizes ( entries , "INITIAL_MESH_SIZE" );
  interpret_mesh_sizes ( entries , "MIN_MESH_SIZE"     );
  interpret_mesh_sizes ( entries , "MIN_POLL_SIZE"     );
  
  // BB_OUTPUT_TYPE:
  // ---------------
  {
    pe = entries.find ( "BB_OUTPUT_TYPE" );

    if (!pe)
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				   "incorrect parameter: BB_OUTPUT_TYPE not found" );

    if (!pe->is_unique())
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				   "incorrect parameter: BB_OUTPUT_TYPE not unique" );

    m = pe->get_nb_values();

    if ( m <= 0 )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: BB_OUTPUT_TYPE" );

    bb_output_type       cur;
    list<bb_output_type> bbot;
    i   = 0;
    end = pe->get_values().end();
    for ( it = pe->get_values().begin() ; it != end ; ++it ) {
      if ( !Parameters::get_bb_output_type ( *it , cur ) ) {
	err = "incorrect parameter: BB_OUTPUT_TYPE (" + pe->get_name();
	throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
      }
      bbot.push_back (cur);
    }

    set_BB_OUTPUT_TYPE ( bbot );
  
    pe->set_has_been_interpreted();
  }

  // BB_EXE:
  // -------
  {
    pe = entries.find ( "BB_EXE" );
    if (pe) {

      if ( !pe->is_unique() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: BB_EXE not unique" );

      m = pe->get_nb_values();

      if ( m == 1 )
	set_BB_EXE ( *pe->get_values().begin() );

      else {

	if ( m != static_cast<int>(_bb_output_types.size()) )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameter: BB_EXE" );
      
	list<string> bbexe;
	end = pe->get_values().end();
	for ( it = pe->get_values().begin() ; it != end ; ++it )
	  bbexe.push_back (*it);

	set_BB_EXE ( bbexe );
      }

      pe->set_has_been_interpreted();
    }
  }

  // SGTE_EXE:
  // ---------
  {
    pe = entries.find ( "SGTE_EXE" );
    if (pe) {

      string bb_exe_name , sgte_name;
      
      if ( pe->get_nb_values() == 1 ) {
	if ( !pe->is_unique() )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	        "incorrect parameter: SGTE_EXE (with one arguement) not unique" );
	sgte_name = *pe->get_values().begin();
      }

      else if ( pe->get_nb_values() == 2 ) {
	bb_exe_name = *pe->get_values().begin();
	sgte_name   = *(++pe->get_values().begin());
      }

      else
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_EXE" );

      set_SGTE_EXE ( bb_exe_name , sgte_name );
      pe->set_has_been_interpreted();
    }
  }

  // SGTE_EVAL_SORT:
  // ---------------
  {
    pe = entries.find ( "SGTE_EVAL_SORT" );
    if (pe) {
      if (!pe->is_unique())
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_EVAL_SORT not unique" );
      i = string_to_bool ( *(pe->get_values().begin() ) );
      if ( pe->get_nb_values() != 1 ||  i == -1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SGTE_EVAL_SORT" );
      set_SGTE_EVAL_SORT (i==1);
      pe->set_has_been_interpreted();
    }
  }

  // DISPLAY_DEGREE:
  // ---------------
  {
    pe = entries.find ( "DISPLAY_DEGREE" );
    if (pe) {
      if ( !pe->is_unique() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: DISPLAY_DEGREE not unique" );
      if ( pe->get_nb_values() != 1 || !set_DISPLAY_DEGREE ( *(pe->get_values().begin()) ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: DISPLAY_DEGREE" );
      pe->set_has_been_interpreted();
    }
  }

  // DISPLAY_STATS:
  {
    pe = entries.find ( "DISPLAY_STATS" );
    if (pe) {
      if ( !pe->is_unique() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: DISPLAY_STATS not unique" );      
      list<string> ls;
      end = pe->get_values().end();
      for ( it = pe->get_values().begin() ; it != end ; ++it )
	ls.push_back(*it);
      ls.resize(ls.size()-1);
      set_DISPLAY_STATS (ls);
      pe->set_has_been_interpreted();
    }
  }

  // STATS_FILE:
  {
    pe = entries.find ( "STATS_FILE" );
    if (pe) {

      if ( !pe->is_unique() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: STATS_FILE not unique" );      

      end = pe->get_values().end();
      it  = pe->get_values().begin();
      string file_name = *it;
      ++it;

      list<string> ls;
      while ( it != end ) {
	ls.push_back(*it);
	++it;
      }

      ls.resize(ls.size()-1);

      set_STATS_FILE ( file_name , ls );
      pe->set_has_been_interpreted();
    }
  }

  // SEED:
  // -----
  {
    pe = entries.find ( "SEED" );

    if (pe) {

      if ( !pe->is_unique() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SEED not unique" );
      
      if ( pe->get_nb_values() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SEED" );

      s = *(pe->get_values().begin());
      NOMAD::toupper(s);


      if ( s=="DIFF" )
	i = -1;
      else if ( !NOMAD::atoi ( s , i ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: SEED" );
      
      set_SEED(i);

      pe->set_has_been_interpreted();
    }
  }

  // VARIABLE_GROUP:
  interpret_var_groups ( entries );
  
  /*----------------------------------------------*/

  // check the non-interpreted parameters:
  pe = entries.find_non_interpreted();
  if (pe) {
    err = "incorrect parameter: " + pe->get_name() + " (unknown)";
    throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
  }

  // The user (or the algo.) has to manually check the parameters with
  // Parameters::check().
}

/*---------------------------------------*/
/*                  display              */
/*---------------------------------------*/
void Parameters::display ( ostream & out ) const {

  list<string>::const_iterator it;

  if (_to_be_checked) {
    out << "Parameters not checked" << endl;
    return;
  }

  // poblem drectory:
  if ( !_problem_dir.empty() ) {
    out << "\tproblem directory     : " << _problem_dir << "\n";
    if ( _tmp_dir != _problem_dir )
      out << "\ttmp directory         : " << _tmp_dir << "\n";
  }

  // dimension:
  out << "\tdimension             : n=" << _dimension << endl;

  // bounds:
  if (_lb.is_defined()) {
    out << "\tlower bounds          : ( ";
    _lb.display ( out , " " , 4 , 10 );
    out << " )\n";
  }
  if (_ub.is_defined()) {
    out << "\tupper bounds          : ( ";
    _ub.display ( out , " " , 4 , 10 );
    out << " )\n";
  }

  // fxed variables:
  if (_fixed_variables.is_defined()) {
    out << "\tfixed variables       : ( ";
    _fixed_variables.display ( out , " " , 4 , 10 );
    out << " )\n";
  }

  // back-box input types:
  if ( _bb_input_include_tag )
    out << "\tblack-box input files : include tag\n";
  if ( _bb_input_include_seed )
    out << "\tblack-box input files : include seed\n";
  out << "\tblack-box input types : ";
  if ( _all_continuous )
    out << "all variables are continuous (R)" << endl;
  else
    out << "( " << _bb_input_types << ")" << endl;
  
  // variable groups:
  if ( _var_groups.size() > 1 ) {
    _out << "\tvariable groups:\n";
    int i = 0;
    set<Variable_Group *,VG_Comp>::const_iterator end2 = _var_groups.end();
    for ( set<Variable_Group *,VG_Comp>::const_iterator it2 = _var_groups.begin() ;
	  it2 != end2 ; ++it2 )
      _out << "\t\tgroup #" << i++ << ": " << **it2 << endl;
  }

  // black-box outputs:
  {
    bool                         display_bb_exe = !_bb_exe.empty();
    bool                         display_sgte   = !_sgte_exe.empty();
    int                          m              = static_cast<int>(_bb_output_types.size());
    int                          w              = 1+int(log(static_cast<double>(m))/LOG10);
    it = _bb_exe.begin();

    out << "\tblack-box outputs (m=" << m << "):\n";
    for ( int i = 0 ; i < m ; ++i ) {
      out << "\t\t#" << setw(w) << i << " " << setw(12) << _bb_output_types[i];
      if ( display_bb_exe ) {
	out << "\t" << *it;
	if ( display_sgte )
	  out << "\t" << get_sgte_exe(*it);
	++it;
      }
      out << endl;
    }
  }

  // BB_REDIRECTION:
  if ( !_bb_redirection ) {
    out << "\tblack-box output redirection      : ";
    display_yes_or_no ( _bb_redirection , out );
    out << endl;
  }

  // surrogates:
  if ( !_sgte_exe.empty() ) {

    // SGTE_EVAL_SORT:
    out << "\tsort trial points with surrogates : ";
    display_yes_or_no ( _sgte_eval_sort , out );
    out << endl;

    // SGTE_COST:
    if ( _sgte_cost > 0 )
      out << "\tsurrogate cost                    : " << _sgte_cost
	  << " surrogate evaluations count as one bb evaluation\n";
  }
  
  // barrier:
  if (_has_constraints) {

    out << "\tbarrier type                      : ";
    switch ( _barrier_type ) {
      case _EB_:
      out << "extreme\n";
      break;
    case _PEB_P_:
    case _PB_:
      out << "progressive\n";
      out << "\tprog. barrier trigger             : " << _rho << endl;
      break;
    default:
      out << "filter\n";
    }
    out << "\tbarrier h_min                     : " << _h_min    << endl
	<< "\tbarrier initial h_max             : " << _h_max_0  << endl;
  }
  if ( _has_filter_constraints )
    out << "\tbarrier h_norm                    : " << _h_norm << endl;

  // ADD_SEED_TO_FILE_NAMES:
  out << "\tadd seed to output file names     : ";
  display_yes_or_no ( _add_seed_to_file_names , out );
  out << endl;

  // SOLUTION_FILE:
  out << "\tsolution file                     : ";
  if ( !_solution_file.empty() )
    out << _solution_file << endl;
  else
    out << "no solution file\n";

  // HISTORY_FILE:
  out << "\thistory file                      : ";
  if ( !_history_file.empty() )
    out << _history_file << endl;
  else
    out << "no history file\n";

  // CACHE_FILE:
  out << "\tcache file                        : ";
  if ( !_cache_file.empty() ) {
    out << _cache_file << endl;
    out << "\tcache save period                 : ";
    if (_cache_save_period <= 0)
      out << "never";
    else if (_cache_save_period==1)
      out << "every iteration";
    else
      out << "every " << _cache_save_period << " iterations";
    out << endl;
  }
  else
    out << "no cache file\n";

  // surrogate cache file:
  if ( !_sgte_cache_file.empty() )
    out << "\tsrgte cache file                  : " << _sgte_cache_file << endl;
 
  // X0:
  if ( _x0s.empty() && _x0_cache_file.empty() )
    out << "\tx0                                : points in \'"
	<< _cache_file << "\'\n";
  else {
    bool first = true;
    if ( !_x0_cache_file.empty() ) {
      if (first) {
	out << "\tx0                                : ";
	first = false;
      }
      else
	out << "\t                                  : ";
      out << _x0_cache_file;
      if ( _x0_cache_file != _cache_file )
	out << " (read only)";
      out << endl;
    }
    if ( !_x0s.empty() ) {
      size_t x0n = _x0s.size();
      for ( size_t k = 0 ; k < x0n ; ++k ) {
	if (first) {
	  out << "\tx0                                : ";
	  first = false;
	}
	else
	  out << "\t                                  : ";
	out << "( ";
	_x0s[k]->display ( out , " " , 4 , 10 );
	out << " )\n";
      }
    }
  }

  // directions:
  {
    set<direction_type>::const_iterator it , end = _direction_types.end();
    if ( _direction_types.size() == 1 )
      out << "\tdirections                        : "
	  << *_direction_types.begin() << endl;
    else {
      out << "\tdirections:\n";
      for ( it = _direction_types.begin() ; it != end ; ++it )
 	out << "\t\t" << *it << endl;
    }
    if ( _barrier_type == _PB_ || _barrier_type == _PEB_P_ ) {
      out << "\tsec. poll dir. type";
      if ( _sec_poll_dir_types.empty() )
	out << "               : no secondary poll" << endl;
      else {
	if ( _sec_poll_dir_types.size() == 1 )
	  out << "               : " << *_sec_poll_dir_types.begin() << endl;
	else {
	  end = _sec_poll_dir_types.end();
	  out << "s:\n";
	  for ( it = _sec_poll_dir_types.begin() ; it != end ; ++it )
	    out << "\t\t" << *it << endl;
	}
      }
    }
 
    if ( _halton_seed > 0 )
      out << "\tuser halton seed                  : " << _halton_seed << endl;
  }

  // mesh:
  {
    out << "\tmesh:" << endl
	<< "\t\tupdate basis              : " << setw(3) << _mesh_update_basis
	<< "\n\t\tcoarsening exponent       : " << setw(3) << _mesh_coarsening_exponent
	<< "\n\t\trefining exponent         : " << setw(3) << _mesh_refining_exponent
	<< "\n\t\tinitial mesh index        : " << setw(3) << _initial_mesh_index << endl;
    if ( _max_mesh_index != UNDEFINED_L )
      out << "\t\tmax mesh index            : " << setw(3) << _max_mesh_index << endl;
    out << "\t\tinitial mesh size         : ( ";
    _initial_mesh_size.display ( out , " " , 4 , 10 );
    out << " )\n";
    if ( _min_mesh_size.is_defined() ) {
      out << "\t\tmin mesh size             : ( ";
      _min_mesh_size.display ( out , " " , 4 , 10 );
      out << " )\n";
    }
    if ( _min_poll_size.is_defined() ) {
      out << "\t\tmin poll size             : ( ";
      _min_poll_size.display ( out , " " , 4 , 10 );
      out << " )\n";
    }
  }

  // opportunistic strategy:
  {
    out << "\topportunistic evaluations         : ";
    display_yes_or_no ( _opportunistic_eval , out );
    out << endl;
    if ( _opportunistic_eval ) {
      if ( _opportunistic_min_nb_success > 0 )
	out << "\t\tmin nb success                       : "
	    << _opportunistic_min_nb_success << endl;
      if ( _opportunistic_min_eval > 0 )
	out << "\t\tmin nb eval                          : "
	    << _opportunistic_min_eval << endl;
      if ( _opportunistic_min_f_imprvmt.is_defined() )
	out << "\t\tmin objective improvement            : "
	    << _opportunistic_min_f_imprvmt << "%"
	    << endl;
      if ( _opportunistic_lucky_eval )
	out << "\t\topportunistic lucky eval             : "
	    << _opportunistic_lucky_eval << endl;
    }
  }

  // SNAP_TO_BOUNDS:
  out << "\tsnap to bounds                    : ";
  display_yes_or_no ( _snap_to_bounds , out );
  out << endl;

  // SPECULATIVE_SEARCH:
  out << "\tspeculative search                : ";
  display_yes_or_no ( _speculative_search , out );
  out << endl;

  // LH_SEARCH:
  if ( _LH_search_p0 > 0 || _LH_search_pi > 0 )
  out << "\tLatin-Hypercube (LH) search       : #init:"
      << _LH_search_p0 << ", #iter:" << _LH_search_pi << endl;
  
  // random seed / unique tag / run id:
  out << "\trandom seed / run id              : " << _seed << endl;

  // EPSILON:
  out << "\tepsilon                           : "
      << NOMAD::Double::get_epsilon() << endl;

  // DISPLAY_DEGREE's:
  out << "\tdisplay degrees                   : general : "
      << _display_degree << " (";
  display_display_degree ( _display_degree , out );
  out << " display)\n";
  out << "\t                                  : search  : "
      << _search_display_degree << " (";
  display_display_degree ( _search_display_degree , out );
  out << " display)\n";
  out << "\t                                  : poll    : "
      << _poll_display_degree << " (";
  display_display_degree ( _poll_display_degree , out );
  out << " display)\n";
  out << "\t                                  : updates : "
      << _updates_display_degree << " (";
  display_display_degree ( _updates_display_degree , out );
  out << " display)\n";

  // DISPLAY_STATS:
  out << "\tnormal display stats              : ";
  list<string>::const_iterator end = _display_stats.end();
  for ( it = _display_stats.begin() ; it != end ; ++it ) {
    if ( it->empty() )
      out << " ";
    else
      out << *it;
  }
  out << endl;

  // STATS_FILE:
  if ( !_stats_file_name.empty() ) {
    out << "\tstats file                       : ("
	<< _stats_file_name << ") ";
    list<string>::const_iterator end = _stats_file.end();
    for ( it = _stats_file.begin() ; it != end ; ++it ) {
      if ( it->empty() )
	out << " ";
      else
	out << *it;
    }
    out << endl;
  }

  // POINT_DISPLAY_LIMIT:
  out << "\tpoint display limit               : ";
  if ( Point::get_display_limit() > 0 )
    out << Point::get_display_limit() << endl;
  else
    out << "no limit\n";

  // MAX_EVAL:
  if ( _max_eval > 0 )
    out << "\tmax eval. (bb+cache)              : " << _max_eval << endl;

  // MAX_BB_EVAL:
  if ( _max_bb_eval >= 0 ) {
    out << "\tmax black-box eval.               : " << _max_bb_eval;
    if ( _max_bb_eval == 0 )
      out << " (no black-box eval. allowed)";
    out << endl;
  }

  // MAX_SIM_BB_EVAL:
  if ( _max_sim_bb_eval >= 0 )
    out << "\tmax simulated black-box eval.     : " << _max_sim_bb_eval << endl;

  // MAX_SGTE_EVAL:
  if ( _sgte_max_eval >= 0 ) {
    out << "\tmax surrogate eval.               : " << _sgte_max_eval;
    if ( _sgte_max_eval == 0 )
      out << " (no surrogate eval. allowed)";
    out << endl;
  }

  // MAX_ITERATIONS:
  if ( _max_iterations >= 0 ) {
    out << "\tmax iterations                    : " << _max_iterations;
    if ( _max_iterations == 0 )
      out << " (no iterations allowed)";
    out << endl;
  }

  // MAX_TIME:
  if ( _max_time > 0 )
    out << "\tmax wall-clock time               : " << _max_time << "s\n";

  // F_TARGET:
  if ( _f_target.is_defined() )
    out << "\tobjective target                  : "
	<< _f_target << endl;

  // STAT_SUM_TARGET:
  if ( _stat_sum_target.is_defined() )
    out << "\tstat sum target                   : "
	<< _stat_sum_target << endl;
}

/*---------------------------------------*/
/*            reset stats file           */
/*---------------------------------------*/
void Parameters::reset_stats_file ( void ) {
  _stats_file.clear();
  _stats_file_name.clear();
}

/*---------------------------------------*/
/*         reset variable groups         */
/*---------------------------------------*/
void Parameters::reset_variable_groups ( set<Variable_Group *,VG_Comp> & vg ) const {
  set<Variable_Group *,VG_Comp>::const_iterator end = vg.end();
  for ( set<Variable_Group *,VG_Comp>::const_iterator it = vg.begin() ;
	it != end ; ++it )
    delete *it;
  vg.clear();
}

/*----------------------------------------*/
/*           Checks the parameters        */
/*----------------------------------------*/
void Parameters::check ( bool remove_history_file ) {
  
  if ( !_to_be_checked )
    return;

  int i;

  /*-------------------------------------------*/
  /*  display degree and Point::display_limit  */
  /*-------------------------------------------*/
  if ( _display_degree > 3 )
    set_POINT_DISPLAY_LIMIT (-1);

  // DEBUG display:
  if ( _display_degree > 3 )
    _display_degree
      = _poll_display_degree
      = _search_display_degree
      = _updates_display_degree
      = 4;

  /*----------------------------*/
  /*          DIMENSION         */
  /*----------------------------*/
  if ( _dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: DIMENSION" );

  /*----------------------------*/
  /*        BB_INPUT_TYPE       */
  /*----------------------------*/
  if ( static_cast<int>(_bb_input_types.size()) != _dimension )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_INPUT_TYPE" );

  /*----------------------------*/
  /*           BOUNDS           */
  /*----------------------------*/
  {
    if ( _lb.size() > _dimension )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: LOWER_BOUND" );
    if ( _lb.size() < _dimension )
      _lb.resize ( _dimension );
    
    if ( _ub.size() > _dimension )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: UPPER_BOUND" );
    if ( _ub.size() < _dimension )
      _ub.resize ( _dimension );
    
    for ( i = 0 ; i < _dimension ; ++i ) {
      if ( _lb[i].is_defined() && _ub[i].is_defined() ) {
	if ( _lb[i] > _ub[i] )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				     "incorrect parameter: LOWER_BOUND or UPPER_BOUND" );
	if ( _lb[i] == _ub[i] )
	  set_FIXED_VARIABLE ( i , _lb[i] );
      }
      
      // integer, binary, and categorical variables:
      if ( _bb_input_types[i] != _CONTINUOUS_ ) {
	
	// binary variables:
	if ( _bb_input_types[i] == _BINARY_ ) {
	  _lb[i] = 0.0;
	  _ub[i] = 1.0;
	}

	// integer and categorical variables:
	else {
	  if ( _lb[i].is_defined() )	  
	    _lb[i] = ceil(_lb[i].value());
	  if ( _ub[i].is_defined() )
	    _ub[i] = floor(_ub[i].value());
	}
      }
    }
  }

  /*----------------------------*/
  /*             Mesh           */
  /*----------------------------*/
  {
    // mesh sizes:
    if ( _initial_mesh_size.size() != _dimension )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameter: INITIAL_MESH_SIZE" );

    // initial mesh size:
    for ( i = 0 ; i < _dimension ; ++i ) {

      // integer, binary, and categorical variables:
      if ( _bb_input_types[i] != _CONTINUOUS_ ) {
	if ( _initial_mesh_size[i].is_defined() ) {
	  if ( _initial_mesh_size[i] < 1.0 )
	    _initial_mesh_size[i] = 1.0;
	}
	else
	  _initial_mesh_size[i] = 1.0;
      }

      // continuous variables:
      else {

	// default value for initial mesh size (r0.1 if there are bounds, else 1.0):
	if ( !_initial_mesh_size[i].is_defined() ) {

	  if ( !_lb[i].is_defined() || !_ub[i].is_defined() )
	    _initial_mesh_size[i] = 1.0;
	  else
	    set_INITIAL_MESH_SIZE ( i , 0.1 , true );
	}

	else if ( _initial_mesh_size[i].value() <  NOMAD::Double::get_epsilon() || 
		  _initial_mesh_size[i].value() <= 0.0                             )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameter: INITIAL_MESH_SIZE" );
      }
    }

    // min mesh size \Delta^m_min:
    if ( _min_mesh_size.is_defined() ) {

      if ( _min_mesh_size.size() != _dimension )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MIN_MESH_SIZE" );
      
      for ( i = 0 ; i < _dimension ; ++i ) {

	// integer, binary, and categorical variables:
	if ( _bb_input_types[i] != _CONTINUOUS_ ) {
	  if ( _min_mesh_size[i].is_defined() ) {
	    if ( _min_mesh_size[i] < 1.0 )
	      _min_mesh_size[i] = 1.0;
	  }
	  else
	    _min_mesh_size[i] = 1.0;
	}

	// continuous variables:
	else if ( _min_mesh_size[i].is_defined() &&
		  (_min_mesh_size[i].value() <  NOMAD::Double::get_epsilon() ||
		   _min_mesh_size[i].value() <= 0.0                             ) )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameters: MIN_MESH_SIZE" );
      }
    }

    // min poll size \Delta^p_min:
    if ( _min_poll_size.is_defined() ) {

      if ( _min_poll_size.size() != _dimension )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: MIN_POLL_SIZE" );
      
      for ( i = 0 ; i < _dimension ; ++i ) {

	// integer, binary, and categorical variables:
	if ( _bb_input_types[i] != _CONTINUOUS_ ) {
	  if ( _min_poll_size[i].is_defined() ) {   
	    if ( _min_poll_size[i] < 1.0 )
	      _min_poll_size[i] = 1.0;
	  }
	  else
	    _min_poll_size[i] = 1.0;
	}

	// continuous variables:
	else if ( _min_poll_size[i].is_defined() &&
		  (_min_poll_size[i].value() <  NOMAD::Double::get_epsilon() ||
		   _min_poll_size[i].value() <= 0.0                             ) )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameters: MIN_POLL_SIZE" );
      }
    }

    // default value for _mesh_update_basis (tau):
    if ( !_mesh_update_basis.is_defined() )
      _mesh_update_basis = 4.0;
    else if ( _mesh_update_basis <= 0.0 )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				  "incorrect parameters: MESH_UPDATE_BASIS" );

    // compare l0 and lmax:
    if ( _max_mesh_index != UNDEFINED_L && _initial_mesh_index > _max_mesh_index )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	    "incorrect parameters: MAX_MESH_INDEX or INITIAL_MESH_INDEX" );
  }

  /*----------------------------*/
  /*         DISPLAY_STATS      */
  /*----------------------------*/
  if ( _display_stats.empty() ) {
    list<string> ls;
    ls.push_back ( get_display_stats_keyword ( _DS_BBE_ ) );
    ls.push_back ( string() );
    ls.push_back ( get_display_stats_keyword ( _DS_OBJ_ ) );
    set_DISPLAY_STATS(ls);
  }

  /*----------------------------*/
  /*          STATS_FILE        */
  /*----------------------------*/
  if ( !_stats_file_name.empty() && _stats_file.empty() ) {
    list<string> ls;
    ls.push_back ( get_display_stats_keyword ( _DS_BBE_ ) );
    ls.push_back ( string() );
    ls.push_back ( get_display_stats_keyword ( _DS_OBJ_ ) );
    set_STATS_FILE ( _stats_file_name , ls );
  }

  /*----------------------------*/
  /*       FIXED_VARIABLES      */
  /*----------------------------*/
  if ( _fixed_variables.size() > _dimension )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: FIXED_VARIABLE" );

  if ( _fixed_variables.size() < _dimension )
    _fixed_variables.resize(_dimension);

  int nb_fixed = 0;
  for ( i = 0; i < _dimension; ++i )
    if ( _fixed_variables[i].is_defined() ) {
      ++nb_fixed;
      if ( (_lb[i].is_defined() && _fixed_variables[i] < _lb[i]) ||
	   (_ub[i].is_defined() && _fixed_variables[i] > _ub[i]) ||
	   ( (_bb_input_types[i] == _INTEGER_ || _bb_input_types[i] == _CATEGORICAL_)
	     && !_fixed_variables[i].is_integer() )              ||
	   ( _bb_input_types[i]==_BINARY_ && !_fixed_variables[i].is_binary() ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: FIXED_VARIABLE" );
    }

  if ( nb_fixed == _dimension )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: FIXED_VARIABLE (all variables are fixed)" );

  /*----------------------------*/
  /*   opportunistic strategy   */
  /*----------------------------*/
  if ( !_opportunistic_eval ) {
    _opportunistic_min_nb_success = -1;
    _opportunistic_min_eval       = -1;
    _opportunistic_lucky_eval     = false;
    _opportunistic_min_f_imprvmt.clear();

    _sgte_eval_sort               = false;
  }  

  /*----------------------------*/
  /*      black-box outputs     */
  /*----------------------------*/
  if ( _bb_output_types.empty() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_OUTPUT_TYPE" );
  if ( _bb_output_types.empty() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_OUTPUT_TYPE (undefined)" );
  
  size_t m = _bb_output_types.size();
  
  if ( !_bb_exe.empty() && m != _bb_exe.size() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_EXE: wrong number of black-box executable names" );

  // surrogates:
  if ( !_sgte_exe.empty() ) {

    if ( _bb_exe.empty() )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
      "incorrect parameter: SGTE_EXE (no BB_EXE is defined)" );

    map<string,string>::const_iterator     it;
    map<string,string>::const_iterator    end = _sgte_exe.end();
    list<string>::const_iterator bb_exe_begin = _bb_exe.begin();
    list<string>::const_iterator   bb_exe_end = _bb_exe.end();

    // an empty string in _sgte_exe means that there is a unique
    // black-box with the associated surrogate
    // (SGTE_EXE parameter with only one argument):
    it = _sgte_exe.find("");
    if ( it != end ) {
      if ( _sgte_exe.size() != 1 )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
        "incorrect parameter: SGTE_EXE (impossible to interpret with one argument)" );

      string bb_exe_name = *bb_exe_begin;
      list<string>::const_iterator it2 = ++bb_exe_begin;
      while ( it2 != bb_exe_end ) {
	if ( *it2 != bb_exe_name )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: unique SGTE_EXE without unique black-box executable" );
	++it2;
      }

      string sgte_name = it->second;

      _sgte_exe.clear();
      _sgte_exe[bb_exe_name] = sgte_name;
    }
    else
      for ( it = _sgte_exe.begin() ; it != end ; ++it )
	if ( find ( bb_exe_begin , bb_exe_end , it->first ) == bb_exe_end )
	  throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				      "incorrect parameter: SGTE_EXE" );
  }
  else {
    _sgte_eval_sort = false;
    _sgte_cost      = -1;
  }

  // _STAT_SUM_ and _STAT_AVG_ checks (each one have to be unique):
  _index_stat_sum = _index_stat_avg = -1;
  for ( size_t k = 0 ; k < m ; ++k ) {
    if ( _bb_output_types[k] == _STAT_SUM_ ) {
      if ( _index_stat_sum >= 0 ) {
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_EXE: more than one STAT_SUM output" );
      }
      _index_stat_sum = static_cast<int>(k);
    }
    else if ( _bb_output_types[k] == _STAT_AVG_ ) {     
      if ( _index_stat_avg >= 0 ) {
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: BB_EXE: more than one STAT_AVG output" );
      }
      _index_stat_avg = static_cast<int>(k);
    }
  }

  /*----------------------------*/
  /*          Directions        */
  /*----------------------------*/
  bool use_ortho_mads = false;

  {
    bool use_mads = false;
    set<direction_type>::const_iterator it , end = _direction_types.end();

    // default value for primary poll directions:
    if ( _direction_types.empty() ) {
      set_DIRECTION_TYPE ( _ORTHO_2N_ );
      use_mads       = true;
      use_ortho_mads = true;
    }
    else
      for ( it = _direction_types.begin() ; it != end ; ++it ) {
	if ( dir_is_mads ( *it ) )
	  use_mads = true;
	if ( dir_is_orthomads ( *it ) )
	  use_ortho_mads = true;
      }
    
    // default value for secondary poll directions:
    if ( _barrier_type == _PB_ || _barrier_type == _PEB_P_ ) {

      if ( _sec_poll_dir_types.empty() ) {
	if ( use_mads )
	  set_SEC_POLL_DIRECTION_TYPE ( (use_ortho_mads) ? _ORTHO_2_ : _LT_2_ );
	else
	  set_SEC_POLL_DIRECTION_TYPE ( _GPS_NP1_STATIC_ );
      }

      else {
	bool old_uom = use_ortho_mads;
	bool old_um  = use_mads;
	end = _sec_poll_dir_types.end();
	for ( it = _sec_poll_dir_types.begin() ; it != end ; ++it ) {
	  if ( *it == _NO_DIRECTION_ ) {
	    _sec_poll_dir_types.clear();
	    use_ortho_mads = old_uom;
	    use_mads       = old_um;
	    break;
	  }
	  if ( dir_is_orthomads (*it) )
	    use_ortho_mads = true;
	  if ( dir_is_mads ( *it ) )
	    use_mads = true;
	}
      }
    }
    else
      _sec_poll_dir_types.clear();

    /*----------------------------*/
    /*     SPECULATIVE_SEARCH     */
    /*----------------------------*/
    if ( !use_mads )
      _speculative_search = false;
  }

  /*----------------------------*/
  /*        variable groups     */
  /*----------------------------*/
  {
    // reset variable groups:
    reset_variable_groups ( _var_groups );

    // the new groups:
    int halton_seed = _halton_seed;
    if ( halton_seed < 0 ) {   
      int * primes = new int [_dimension];
      construct_primes ( _dimension , primes );

      halton_seed = primes[_dimension-1];

      delete [] primes;
    }
    
    vector<bool> in_group (_dimension);
    for ( i = 0 ; i < _dimension ; i++ )
      in_group[i] = false;

    Variable_Group * vg;

    // 1. user groups:
    set<Variable_Group *,VG_Comp>::const_iterator end = _user_var_groups.end();
    for ( set<Variable_Group *,VG_Comp>::const_iterator it = _user_var_groups.begin() ;
	  it != end ; ++it ) {

      if ( !(*it)->check ( _fixed_variables     ,
			   _bb_input_types      ,
			   &_direction_types    ,
			   &_sec_poll_dir_types ,
			   &_barrier_type       ,
			   &in_group              ) )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	      "incorrect parameter: VARIABLE_GROUP" );
      
      vg = new Variable_Group ( **it );
      if ( (*it)->is_orthomads() && vg->get_halton_seed() < 0 )
	vg->set_halton_seed ( halton_seed++ );
      _var_groups.insert (vg);
    }
    
    // 2. 'automatic' groups for other variables:
    set<int> vi_cbi;  // list of cont./bin./int. variables
    set<int> vi_cat;  // list of categorical variables

    for ( i = 0 ; i < _dimension ; ++i ) {
      if ( !in_group[i] && !_fixed_variables[i].is_defined() ) {
	if (  _bb_input_types[i] != _CATEGORICAL_ )
	  vi_cbi.insert(i);
	else
	  vi_cat.insert(i);
      }
    }

    // creation of a group for cont./bin./int. variables:
    if ( !vi_cbi.empty() ) {
      vg = new Variable_Group ( vi_cbi              ,
				_direction_types    ,
				_sec_poll_dir_types ,
				-1                  ,
				_out                  );
      if ( use_ortho_mads )
	vg->set_halton_seed ( halton_seed++ );

      _var_groups.insert (vg);
    }

    // creation of a group for categorical variables:
    if ( !vi_cat.empty() ) {
      vg = new Variable_Group ( vi_cat              ,
				_direction_types    ,
				_sec_poll_dir_types ,
				-1                  ,
				_out                  );
      if ( use_ortho_mads )
	vg->set_halton_seed ( halton_seed++ );

      _var_groups.insert (vg);
    }
  }

  /*----------------------------*/
  /*           TMP_DIR          */
  /*----------------------------*/
  if ( _tmp_dir.empty() )
    _tmp_dir = _problem_dir;

  /*------------------------------------------------------*/
  /*        SOLUTION_FILE, HISTORY_FILE and STATS_FILE    */
  /*  (depending on the value of ADD_SEED_TO_FILE_NAMES,  */
  /*   the seed is added the file names)                  */
  /*------------------------------------------------------*/
  if ( _add_seed_to_file_names ) {

    string s_seed = NOMAD::itos(_seed);
    int    n_seed = static_cast<int>(s_seed.size());

    add_seed_to_file_name ( n_seed , s_seed , _solution_file   );
    add_seed_to_file_name ( n_seed , s_seed , _history_file    );
    add_seed_to_file_name ( n_seed , s_seed , _stats_file_name );
  }

  // remove old history and stats files:
  string old_file;
  if ( remove_history_file && !_history_file.empty() ) {
    old_file = _problem_dir + _history_file;
    remove ( old_file.c_str() );
  }
  if ( !_stats_file_name.empty() ) {
    old_file = _problem_dir + _stats_file_name;
    remove ( old_file.c_str() );
  }

  /*----------------------------*/
  /*              X0            */
  /*----------------------------*/
  if ( _x0s.empty() && _x0_cache_file.empty() && _LH_search_p0 <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: no starting point" );
  else {
    size_t x0n = _x0s.size();
    for ( size_t k = 0 ; k < x0n ; ++k )
      if ( !_x0s[k]->is_complete() )
	throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				    "incorrect parameter: x0 with missing coordinates" );
  }

  _to_be_checked = false;
}

/*-----------------------------------------------------------------*/
/*  add seed to a file name: file_name.ext --> file_name.seed.ext  */
/*-----------------------------------------------------------------*/
void Parameters::add_seed_to_file_name ( int            n_seed    ,
					 const string & s_seed    ,
					 string       & file_name   ) {

  int n_pn = static_cast<int>(file_name.size());

  if ( n_pn == 0 )
    return;

  int    k   = static_cast<int>(file_name.find_last_of("."));
  string ext = "";
  string fic = file_name;

  if ( k >= 0 && k < n_pn ) {
    fic  = file_name.substr ( 0 , k      );
    ext  = file_name.substr ( k , n_pn-k );
    n_pn = k;
  }
 
  if ( n_pn <= n_seed+1 ||
       fic.substr ( n_pn-n_seed , n_pn-1 ) != s_seed )
    file_name = fic + "." + s_seed + ext;
}

/*----------------------------------------*/
/*               GET methods              */
/*----------------------------------------*/

// get_dimension:
int Parameters::get_dimension ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_dimension(), Parameters::check() has to be invoked" );
  return _dimension;
}

// get_halton_seed:
int Parameters::get_halton_seed ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_halton_seed(), Parameters::check() has to be invoked" );
  return _halton_seed;
}

// get_snap_to_bounds:
bool Parameters::get_snap_to_bounds ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_snap_to_bounds(), Parameters::check() has to be invoked" );
  return _snap_to_bounds;
}

// get_speculative_search:
bool Parameters::get_speculative_search ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_speculative_search(), Parameters::check() has to be invoked" );
  return _speculative_search;
}

// get_LH_search_p0:
int Parameters::get_LH_search_p0 ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_LH_search_p0(), Parameters::check() has to be invoked" );
  return _LH_search_p0;
}

// get_LH_search_p0:
int Parameters::get_LH_search_pi ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_LH_search_pi(), Parameters::check() has to be invoked" );
  return _LH_search_pi;
}

// get_direction_types:
const set<direction_type> & Parameters::get_direction_types ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_direction_types(), Parameters::check() has to be invoked" );
  return _direction_types;
}

// get_sec_poll_dir_types:
const set<direction_type> & Parameters::get_sec_poll_dir_types ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_sec_poll_dir_types(), Parameters::check() has to be invoked" );
  return _sec_poll_dir_types;
}

// get_mesh_update_basis:
const NOMAD::Double & Parameters::get_mesh_update_basis ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_mesh_update_basis(), Parameters::check() has to be invoked" );
  return _mesh_update_basis;
}

// get_mesh_coarsening_exponent:
int Parameters::get_mesh_coarsening_exponent ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_mesh_coarsening_exponent(), Parameters::check() has to be invoked" );
  return _mesh_coarsening_exponent;
}

// get_mesh_refining_exponent:
int Parameters::get_mesh_refining_exponent ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_mesh_refining_exponent(), Parameters::check() has to be invoked" );
  return _mesh_refining_exponent;
}

// get_initial_mesh_index:
int Parameters::get_initial_mesh_index ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_initial_mesh_index(), Parameters::check() has to be invoked" );
  return _initial_mesh_index;
}

// get_max_mesh_index:
int Parameters::get_max_mesh_index ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_max_mesh_index(), Parameters::check() has to be invoked" );
  return _max_mesh_index;
}

// get_initial_mesh_size:
const Point & Parameters::get_initial_mesh_size ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_initial_mesh_size(), Parameters::check() has to be invoked" );
  return _initial_mesh_size;
}

// get_min_mesh_size:
const Point & Parameters::get_min_mesh_size ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_min_mesh_size(), Parameters::check() has to be invoked" );
  return _min_mesh_size;
}

// get_min_poll_size:
const Point & Parameters::get_min_poll_size ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_min_poll_size(), Parameters::check() has to be invoked" );
  return _min_poll_size;
}

// get_x0s:
const vector<Point *> & Parameters::get_x0s ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_x0s(), Parameters::check() has to be invoked" );
  return _x0s;
}

// get_x0_cache_file:
const string & Parameters::get_x0_cache_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_x0_cache_file(), Parameters::check() has to be invoked" );
  return _x0_cache_file;
}

// get_lb:
const Point & Parameters::get_lb (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_lb(), Parameters::check() has to be invoked" );
  return _lb;
}

// get_ub:
const Point & Parameters::get_ub (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_ub(), Parameters::check() has to be invoked" );
  return _ub;
}

// get_fixed_variables:
const Point & Parameters::get_fixed_variables (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_fixed_variables(), Parameters::check() has to be invoked" );
  return _fixed_variables;
}

// get_bb_nb_outputs:
int Parameters::get_bb_nb_outputs (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_bb_nb_outputs(), Parameters::check() has to be invoked" );
  return static_cast<int>(_bb_output_types.size());
}

// get_bb_exe:
const list<string> & Parameters::get_bb_exe ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
          "Parameters::get_bb_exe(), Parameters::check() has to be invoked" );
  return _bb_exe;
}

// get_sgte_eval_sort:
bool Parameters::get_sgte_eval_sort ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_sgte_eval_sort(), Parameters::check() has to be invoked" );
  return _sgte_eval_sort;
}

// get_sgte_cost:
int Parameters::get_sgte_cost ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_sgte_cost(), Parameters::check() has to be invoked" );
  return _sgte_cost;
}

// get_sgte_exe (returns an empty string if bb_exe has no surrogate):
string Parameters::get_sgte_exe ( const string & bb_exe ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_sgte_exe(), Parameters::check() has to be invoked" );
  map<string,string>::const_iterator it = _sgte_exe.find(bb_exe);
  string s;
  if ( it!=_sgte_exe.end() )
    s = it->second;
  return s;
}

// get_index_obj:
const list<int> & Parameters::get_index_obj ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_index_obj(), Parameters::check() has to be invoked" );
  return _index_obj;
}

// get_bb_input_include_tag:
bool Parameters::get_bb_input_include_tag ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_bb_input_include_tag(), Parameters::check() has to be invoked" );
  return _bb_input_include_tag;
}

// get_bb_input_include_seed:
bool Parameters::get_bb_input_include_seed ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_bb_input_include_seed(), Parameters::check() has to be invoked" );
  return _bb_input_include_seed;
}

// get_bb_redirection:
bool Parameters::get_bb_redirection ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_bb_redirection(), Parameters::check() has to be invoked" );
  return _bb_redirection;
}

// get_bb_input_types:
const vector<bb_input_type> & Parameters::get_bb_input_types (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_bb_input_types(), Parameters::check() has to be invoked" );
  return _bb_input_types;
}

// get_bb_output_types:
const vector<bb_output_type> & Parameters::get_bb_output_types (void) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_bb_output_types(), Parameters::check() has to be invoked" );
  return _bb_output_types;
}

// get_seed:
int Parameters::get_seed ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_seed(), Parameters::check() has to be invoked" );
  return _seed;
}

// get_display_stats:
const list<string> & Parameters::get_display_stats ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_display_stats(), Parameters::check() has to be invoked" );
  return _display_stats;
}

// get_stats_file_name:
const string & Parameters::get_stats_file_name ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_stats_file_name(), Parameters::check() has to be invoked" );
  return _stats_file_name;
}

// get_stats_file:
const list<string> & Parameters::get_stats_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_stats_file(), Parameters::check() has to be invoked" );
  return _stats_file;
}

// get_display_degree:
int Parameters::get_display_degree ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_display_degree(), Parameters::check() has to be invoked" );
  return _display_degree;
}

// get_search_display_degree:
int Parameters::get_search_display_degree ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_search_display_degree(), Parameters::check() has to be invoked" );
  return _search_display_degree;
}

// get_poll_display_degree:
int Parameters::get_poll_display_degree ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_poll_display_degree(), Parameters::check() has to be invoked" );
  return _poll_display_degree;
}

// get_updates_display_degree:
int Parameters::get_updates_display_degree ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_updates_display_degree(), Parameters::check() has to be invoked" );
  return _updates_display_degree;
}

// get_max_eval:
int Parameters::get_max_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_max_eval(), Parameters::check() has to be invoked" );
  return _max_eval;
}

// get_max_bb_eval:
int Parameters::get_max_bb_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_max_bb_eval(), Parameters::check() has to be invoked" );
  return _max_bb_eval;
}

// get_max_sim_bb_eval:
int Parameters::get_max_sim_bb_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_max_sim_bb_eval(), Parameters::check() has to be invoked" );
  return _max_sim_bb_eval;
}

// get_max_sgte_eval:
int Parameters::get_max_sgte_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_max_sgte_eval(), Parameters::check() has to be invoked" );
  return _sgte_max_eval;
}

// get_max_time:
int Parameters::get_max_time ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_max_time(), Parameters::check() has to be invoked" );
  return _max_time;
}

// get_max_iterations:
int Parameters::get_max_iterations ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_max_iterations(), Parameters::check() has to be invoked" );
  return _max_iterations;
}

// get_cache_save_period:
int Parameters::get_cache_save_period ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_cache_save_period(), Parameters::check() has to be invoked" );
  return _cache_save_period;
}

// get_f_target:
const NOMAD::Double & Parameters::get_f_target ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_f_target(), Parameters::check() has to be invoked" );
  return _f_target;
}

// get_stat_sum_target:
const NOMAD::Double & Parameters::get_stat_sum_target ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_stat_sum_target(), Parameters::check() has to be invoked" );
  return _stat_sum_target;
}

// get_problem_dir:
const string & Parameters::get_problem_dir ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_problem_dir(), Parameters::check() has to be invoked" );
  return _problem_dir;
}

// get_tmp_dir:
const string & Parameters::get_tmp_dir ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_tmp_dir(), Parameters::check() has to be invoked" );
  return _tmp_dir;
}

// get_solution_file:
const string & Parameters::get_solution_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_solution_file(), Parameters::check() has to be invoked" );
  return _solution_file;
}

// get_history_file:
const string & Parameters::get_history_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_history_file(), Parameters::check() has to be invoked" );
  return _history_file;
}

// get_cache_file:
const string & Parameters::get_cache_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_cache_file(), Parameters::check() has to be invoked" );
  return _cache_file;
}

// get_sgte_cache_file:
const string & Parameters::get_sgte_cache_file ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_sgte_cache_file(), Parameters::check() has to be invoked" );
  return _sgte_cache_file;
}

// get_rho:
const NOMAD::Double & Parameters::get_rho ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_rho(), Parameters::check() has to be invoked" );
  return _rho;
}


// get_h_min:
const NOMAD::Double & Parameters::get_h_min ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_h_min(), Parameters::check() has to be invoked" );
  return _h_min;
}

// get_h_max_0:
const NOMAD::Double & Parameters::get_h_max_0 ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_h_max_0(), Parameters::check() has to be invoked" );
  return _h_max_0;
}

// get_h_norm:
hnorm_type Parameters::get_h_norm ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
		       "Parameters::get_h_norm(), Parameters::check() has to be invoked" );
  return _h_norm;
}

// use_sec_poll_center:
bool Parameters::use_sec_poll_center ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::use_second_poll_center(), Parameters::check() has to be invoked" );
  return _barrier_type == _PB_ || _barrier_type == _PEB_P_;
}

// get_barrier_type:
bb_output_type Parameters::get_barrier_type ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_filter_type(), Parameters::check() has to be invoked" );
  return _barrier_type;
}

// get_opportunistic_eval:
bool Parameters::get_opportunistic_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_opportunistic_eval(), Parameters::check() has to be invoked" );
  return _opportunistic_eval;
}

// get_opportunistic_min_nb_success
int Parameters::get_opportunistic_min_nb_success ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_opportunistic_min_nb_success(), Parameters::check() has to be invoked" );
  return _opportunistic_min_nb_success;
}

// get_opportunistic_min_eval
int Parameters::get_opportunistic_min_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
	  "Parameters::get_opportunistic_min_eval(), Parameters::check() has to be invoked" );
  return _opportunistic_min_eval;
}

// get_opportunistic_min_f_imprvmt
const NOMAD::Double & Parameters::get_opportunistic_min_f_imprvmt ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_opportunistic_min_f_imprvmt(), Parameters::check() has to be invoked" );
  return _opportunistic_min_f_imprvmt;
}

// get_opportunistic_lucky_eval:
bool Parameters::get_opportunistic_lucky_eval ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_opportunistic_lucky_eval(), Parameters::check() has to be invoked" );
  return _opportunistic_lucky_eval;
}

// check_stat_sum:
bool Parameters::check_stat_sum ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::check_stat_sum(), Parameters::check() has to be invoked" );
  return (_index_stat_sum >= 0);
}

// check_stat_avg:
bool Parameters::check_stat_avg ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::check_stat_avg(), Parameters::check() has to be invoked" );
  return (_index_stat_avg >= 0);
}

// get_index_stat_sum:
int Parameters::get_index_stat_sum ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_index_stat_sum(), Parameters::check() has to be invoked" );
  return _index_stat_sum;
}

// get_index_stat_avg:
int Parameters::get_index_stat_avg ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_index_stat_avg(), Parameters::check() has to be invoked" );
  return _index_stat_avg;
}

// get_variable_groups:
const set<Variable_Group *,VG_Comp> & Parameters::get_variable_groups ( void ) const {
  if (_to_be_checked)
    throw Bad_Access ( __FILE__ , __LINE__ ,
    "Parameters::get_variable_groups(), Parameters::check() has to be invoked" );
  return _var_groups;
}

/*----------------------------------------*/
/*               SET methods              */
/*----------------------------------------*/

// set_EPSILON:
void Parameters::set_EPSILON ( const NOMAD::Double & e ) {
  NOMAD::Double::set_epsilon ( e.value() );
}

// set_POINT_DISPLAY_LIMIT:
void Parameters::set_POINT_DISPLAY_LIMIT ( int dl ) {
  Point::set_display_limit(dl);
}

// set_DIMENSION:
bool Parameters::set_DIMENSION ( int dim ) {
  _to_be_checked = true;
  _dimension     = dim;
  if (_dimension < 0) {
    _dimension = -1;
    throw Incorrect_Parameter ( __FILE__ , __LINE__ , "incorrect parameter: DIMENSION" );
    return false;
  }

  // all variables are initially considered continuous:
  _all_continuous = true;
  _bb_input_types.resize ( _dimension );
  for ( int i = 0 ; i < _dimension ; ++i )
    _bb_input_types[i] = _CONTINUOUS_;

  // resize of _initial_mesh_size:
  _initial_mesh_size.reset ( _dimension );

  return true;
}

// set_HALTON_SEED:
void Parameters::set_HALTON_SEED ( int hs ) {
  _to_be_checked = true;
  if ( hs <= 0 )
    hs = -1;
  _halton_seed = hs;
}

// set_SNAP_TO_BOUNDS:
void Parameters::set_SNAP_TO_BOUNDS ( bool stb ) {
  _to_be_checked  = true;
  _snap_to_bounds = stb;
}

// set_SPECULATIVE_SEARCH:
void Parameters::set_SPECULATIVE_SEARCH ( bool ss ) {
  _to_be_checked      = true;
  _speculative_search = ss;
}

// set_LH_SEARCH:
void Parameters::set_LH_SEARCH ( int p0 , int pi ) {
  _to_be_checked = true;
  _LH_search_p0  = p0;
  _LH_search_pi  = pi;
}

// set_DIRECTION_TYPE:
void Parameters::set_DIRECTION_TYPE ( direction_type dt ) {
  _to_be_checked = true;
  if ( dt == _UNDEFINED_DIRECTION_ || dt == _NO_DIRECTION_ )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: DIRECTION_TYPE" );
  _direction_types.insert(dt);
}

// set_SEC_POLL_DIRECTION_TYPE:
void Parameters::set_SEC_POLL_DIRECTION_TYPE ( direction_type dt ) {
  _to_be_checked = true;
  if ( dt == _UNDEFINED_DIRECTION_ )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: SEC_POLL_DIRECTION_TYPE" );
  _sec_poll_dir_types.insert(dt);
}

// set_RHO:
void Parameters::set_RHO ( const NOMAD::Double & rho ) {
  _to_be_checked = true;
  _rho           = rho;
}

// set_H_MIN:
void Parameters::set_H_MIN ( const NOMAD::Double & h_min ) {
  _to_be_checked = true;
  _h_min         = h_min;
}

// set_H_MAX_0:
void Parameters::set_H_MAX_0 ( const NOMAD::Double & h_max ) {
  _to_be_checked = true;
  _h_max_0       = h_max;
}

// set_H_NORM:
void Parameters::set_H_NORM ( hnorm_type h_norm ) {
  _to_be_checked = true;
  _h_norm        = h_norm;
}

// set_FIXED_VARIABLE:
void Parameters::set_FIXED_VARIABLE ( int index, const NOMAD::Double & value ) {
  _to_be_checked = true;
  if (index < 0)
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: FIXED_VARIABLE" );
  if ( index >= _fixed_variables.size() )
    _fixed_variables.resize (index +1 );
  
  _fixed_variables[index] = value;
}

// set_LOWER_BOUND (1/2):
void Parameters::set_LOWER_BOUND ( int index, const NOMAD::Double & value ) {
  _to_be_checked = true;
  if (index < 0)
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: LOWER_BOUND" );
  if ( index >= _lb.size() )
    _lb.resize(index+1);
  if ( !_lb[index].is_defined() || value > _lb[index] )
    _lb[index] = value;
}

// set_LOWER_BOUND (2/2):
void Parameters::set_LOWER_BOUND ( const Point & lb ) {
  _to_be_checked = true;
  _lb            = lb;
}

// set_UPPER_BOUND (1/2):
void Parameters::set_UPPER_BOUND ( int index, const NOMAD::Double & value ) {
  _to_be_checked = true;
  if (index < 0)
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: UPPER_BOUND" );
  if ( index >= _ub.size() )
    _ub.resize (index + 1);
  if ( !_ub[index].is_defined() || value < _ub[index] )
    _ub[index] = value;
}

// set_UPPER_BOUND (2/2):
void Parameters::set_UPPER_BOUND ( const Point & ub ) {
  _to_be_checked = true;
  _ub            = ub;
}

// set_SGTE_COST:
void Parameters::set_SGTE_COST ( int c ) {
  _to_be_checked = true;
  if ( c > 0 )
    _sgte_cost = c;
}

// set_SGTE_EVAL_SORT:
void Parameters::set_SGTE_EVAL_SORT ( bool ses ) {
  _to_be_checked  = true;
  _sgte_eval_sort = ses;
}

// set_SGTE_EXE:
void Parameters::set_SGTE_EXE ( const string & bb_exe   ,
				const string & sgte_exe   ) {
  _to_be_checked     = true;
  _sgte_exe[bb_exe]  = sgte_exe;
}

// set_BB_EXE (1/3):
void Parameters::set_BB_EXE ( const string & bbexe ) {
  _to_be_checked = true;
  if ( _bb_output_types.empty() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_EXE (BB_OUTPUT_TYPE has to be defined first)" );
  _bb_exe.clear();
  size_t nk = _bb_output_types.size();
  for ( size_t k = 0 ; k < nk ; ++k )
    _bb_exe.push_back(bbexe);
}

// set_BB_EXE (2/3):
void Parameters::set_BB_EXE ( int m , const string * bbexe ) {

  _to_be_checked = true;

  if ( m <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_EXE" );

  if ( m != static_cast<int>(_bb_output_types.size()) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_EXE (number of names or BB_OUTPUT_TYPE undefined)" );

  size_t nk = _bb_output_types.size();
  for ( size_t k = 0 ; k < nk ; ++k )
    _bb_exe.push_back ( bbexe[k] );
}

// set_BB_EXE (3/3):
void Parameters::set_BB_EXE ( const list<string> & bbexe ) {

  _to_be_checked = true;

  if ( bbexe.empty() || bbexe.size() != _bb_output_types.size() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_EXE (number of names or BB_OUTPUT_TYPE undefined)" );
  _bb_exe = bbexe;
}

// set_BB_INPUT_INCLUDE_TAG:
void Parameters::set_BB_INPUT_INCLUDE_TAG ( bool bbiit ) {
  _to_be_checked        = true;
  _bb_input_include_tag = bbiit;
}

// set_BB_INPUT_INCLUDE_SEED:
void Parameters::set_BB_INPUT_INCLUDE_SEED ( bool bbiis ) {
  _to_be_checked         = true;
  _bb_input_include_seed = bbiis;
}

// set_BB_REDIRECTION:
void Parameters::set_BB_REDIRECTION ( bool bbr ) {
  _to_be_checked  = true;
  _bb_redirection = bbr;
}

// set_BB_INPUT_TYPE:
void  Parameters::set_BB_INPUT_TYPE ( int index , bb_input_type  bbit  ) {
  _to_be_checked  = true;
  if ( index < 0 || index >= _dimension ||
       static_cast<int>(_bb_input_types.size()) != _dimension )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
			       "incorrect parameter: BB_INPUT_TYPE" );
  _bb_input_types[index] = bbit;
  if ( bbit != _CONTINUOUS_ )
    _all_continuous = false;
}

// reset_PEB_changes:
void Parameters::reset_PEB_changes ( void ) const {
  size_t nk = _bb_output_types.size();
  for ( size_t k = 0 ; k < nk ; ++k )
    if ( _bb_output_types[k] == _PEB_E_ )
      _bb_output_types[k] = _PEB_P_;
}

// change_PEB_constraint_status:
void Parameters::change_PEB_constraint_status ( int index ) const {
  if ( index < 0 || index >= static_cast<int>(_bb_output_types.size()) ||
       _bb_output_types[index] != _PEB_P_ )
    throw NOMAD::Exception ( __FILE__ , __LINE__ ,
	  "error in Parameters::change_PEB_constraint_status(i): bad i" );
  _bb_output_types[index] = _PEB_E_;
}

// set_BB_OUTPUT_TYPE (1/2):
void Parameters::set_BB_OUTPUT_TYPE ( const list<bb_output_type> & bbot ) {
  int i = 0;
  vector<bb_output_type> bbot_vector ( bbot.size() );
  list<bb_output_type>::const_iterator end = bbot.end();
  for ( list<bb_output_type>::const_iterator it = bbot.begin() ; it != end ; ++it )
    bbot_vector[i++] = *it;
  set_BB_OUTPUT_TYPE ( bbot_vector );
}

// set_BB_OUTPUT_TYPE (2/2):
void Parameters::set_BB_OUTPUT_TYPE ( const vector<bb_output_type> & bbot ) {

  _to_be_checked          = true;

  _barrier_type           = _EB_;
  _has_constraints        = false;
  _has_filter_constraints = false;

  _bb_output_types.clear();

  int m = static_cast<int>(bbot.size());

  if ( m <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_OUTPUT_TYPE" );
  if ( !_bb_output_types.empty() &&
       m != static_cast<int>(_bb_output_types.size()) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_OUTPUT_TYPE (number of types)" );

  _bb_output_types.resize (m);

  bool filter_used = false;
  bool pb_used     = false;
  bool peb_used    = false;

  _index_obj.clear();

  for ( int i = 0 ; i < m ; ++i ) {

    _bb_output_types[i] = bbot[i];

    switch(bbot[i]) {

    case _OBJ_:
      _index_obj.push_back(i);
      break;

    case _EB_:
      _has_constraints = true;
      break;

    case _F_:
      _has_constraints      = true;
      _has_filter_constraints = true;
      filter_used   = true;
      break;

    case _PB_:
      _has_constraints        = true;
      _has_filter_constraints = true;
      pb_used                 = true;
      break;
      
    case _PEB_P_:
    case _PEB_E_:
      _has_constraints        = true;
      _has_filter_constraints = true;
      pb_used                 = true;
      peb_used                = true;
      _bb_output_types[i]     = _PEB_P_;
      break;
    default:
      break;
    }
  }

  if ( _index_obj.empty() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: BB_OUTPUT_TYPE (OBJ not given)" );

  if ( filter_used && pb_used )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: BB_OUTPUT_TYPE (F and PB/PEB used together)" );

  if ( filter_used )
    _barrier_type = _F_;
  else if ( pb_used )
    _barrier_type = (peb_used) ? _PEB_P_ : _PB_;
}

// set_PROBLEM_DIR:
void Parameters::set_PROBLEM_DIR ( const string & dir ) {
  _to_be_checked = true;
  _problem_dir   = dir;
  if ( !Parameters::check_directory ( _problem_dir ) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: PROBLEM_DIR" );
}

// set_TMP_DIR:
void Parameters::set_TMP_DIR ( const string & dir ) {
  _to_be_checked = true;
  _tmp_dir       = dir;
  if ( !Parameters::check_directory ( _tmp_dir ) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: TMP_DIR" );
}

// set_ADD_SEED_TO_FILE_NAMES:
void Parameters::set_ADD_SEED_TO_FILE_NAMES ( bool astfn ) {
  _to_be_checked = true;
  _add_seed_to_file_names = astfn;
}

// set_SOLUTION_FILE:
void Parameters::set_SOLUTION_FILE ( const string & sf ) {
  _to_be_checked = true;
  _solution_file = sf;
  if ( sf.empty() )
    return;
  if ( !Parameters::check_directory ( _solution_file ) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: SOLUTION_FILE" );
  _solution_file.resize ( _solution_file.size()-1 );
}

// set_HISTORY_FILE:
void Parameters::set_HISTORY_FILE ( const string & hf ) {
  _to_be_checked = true;
  _history_file  = hf;
  if ( hf.empty() )
    return;
  if ( !Parameters::check_directory ( _history_file ) )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: HISTORY_FILE" );
  _history_file.resize ( _history_file.size()-1 );
}

// set_CACHE_FILE:
void Parameters::set_CACHE_FILE  ( const string & cf ) {
  _to_be_checked = true;
  _cache_file    = cf;
  if ( cf.empty() )
    return;
  if ( !Parameters::check_directory ( _cache_file ) ) {
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: CACHE_FILE" );
  }
  _cache_file.resize ( _cache_file.size()-1 );
}

// set_SGTE_CACHE_FILE:
void Parameters::set_SGTE_CACHE_FILE  ( const string & cf ) {
  _to_be_checked   = true;
  _sgte_cache_file = cf;
  if ( cf.empty() )
    return;
  if ( !Parameters::check_directory ( _sgte_cache_file ) ) {
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: SGTE_CACHE_FILE");
  }
  _sgte_cache_file.resize ( _sgte_cache_file.size()-1 );
}

// set_X0:
// add a new point in the list of starting points:
void Parameters::set_X0 ( const Point & x0 ) {
  _to_be_checked = true;
  _x0s.push_back ( new Point(x0) );
}

// indicate a x0 file or a cache file containing starting points:
void Parameters::set_X0 ( const string & file_name ) {

  _to_be_checked = true;

  if ( _dimension < 0 ) {
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "Parameters::set_X0() has been used before setting DIMENSION" );
  }
  
  Point tmp_x0 ( _dimension );

  string complete_file_name = _problem_dir + file_name;

  ifstream in ( complete_file_name.c_str() );
	
  if ( in.fail() ) {
    string err = "incorrect parameter: X0 (could not open file \'" +
                 complete_file_name + "\')";
    in.close();
    throw Incorrect_Parameter ( __FILE__ , __LINE__ , err );
  }

  bool flag = true;
  try {
    in >> tmp_x0;
  }
  catch ( Point::Bad_Input & ) {
    flag = false;

    // we suppose that the file name corresponds to a cache file:
    _x0_cache_file = file_name;
   
  }

  in.close();

  if (flag)
    set_X0 ( tmp_x0 );
}

// set_DISPLAY_STATS:
void Parameters::set_DISPLAY_STATS ( const list<string> & ls ) {
  _display_stats = ls;
}

// set_STATS_FILE (1/2):
void Parameters::set_STATS_FILE ( const string & file_name , const list<string> & ls ) {
  _stats_file_name = file_name;
  _stats_file      = ls;
}

// set_STATS_FILE (2/2):
void Parameters::set_STATS_FILE ( const string & file_name , const string & stats ) {

  string          s = "STATS_FILE " + file_name + " " + stats;
  Parameter_Entry pe ( s );

  list<string>::const_iterator end = pe.get_values().end() , it = pe.get_values().begin();

  list<string> ls;
  ++it;
  while ( it != end ) {
    ls.push_back(*it);
    ++it;
  }

  ls.resize ( ls.size()-1 );

  set_STATS_FILE ( file_name , ls );
}

// set_DISPLAY_DEGREE:
bool Parameters::set_DISPLAY_DEGREE ( int dd ) {
#ifndef DEBUG
  return set_DISPLAY_DEGREE ( NOMAD::itos(dd) );
#endif
  return true;
}

// set_DISPLAY_DEGREE:
bool Parameters::set_DISPLAY_DEGREE ( const string & dd ) {
#ifndef DEBUG

  int i;

  if ( dd.size() == 1 ) {
    if ( !NOMAD::atoi ( dd[0] , i ) )
      return false;
    i = ( i < 0 ) ? 0 : i;
    if ( i > 4 )
      i = 4;
    _display_degree = _search_display_degree
      = _poll_display_degree = _updates_display_degree = i;
    return true;
  }

  if (dd.size() != 4 )
    return false;
  
  // general display:
  if ( !NOMAD::atoi ( dd[0] , i ) )
    return false;
  _display_degree = ( i < 0 ) ? 0 : i;
  if ( _display_degree > 4 )
    _display_degree = 4;

  // search display:
  if ( !NOMAD::atoi ( dd[1] , i ) )
    return false;
  _search_display_degree = ( i < 0 ) ? 0 : i;
  if ( _search_display_degree > 4 )
    _search_display_degree = 4;

  // poll display:
  if ( !NOMAD::atoi ( dd[2] , i ) )
    return false;
  _poll_display_degree = ( i < 0 ) ? 0 : i;
  if ( _poll_display_degree > 4 )
    _poll_display_degree = 4;

  // updates display:
  if ( !NOMAD::atoi ( dd[3] , i ) )
    return false;
  _updates_display_degree = ( i < 0 ) ? 0 : i;
  if ( _updates_display_degree > 4 )
    _updates_display_degree = 4;
#endif
  return true;
}

// set_SEED:
void Parameters::set_SEED ( int t ) {
  _to_be_checked = true;
  _seed          = ( t < 0 ) ? static_cast<int>(time(NULL)) : t;
}

// set_MAX_EVAL:
void Parameters::set_MAX_EVAL ( int e ) {
  _to_be_checked = true;
  _max_eval      = e;
  if ( _max_eval <= 0 )
    _max_eval = -1;
}

// set_MAX_BB_EVAL:
void Parameters::set_MAX_BB_EVAL ( int bbe ) {
  _to_be_checked = true;
  _max_bb_eval  = bbe;
  if ( _max_bb_eval < 0 )
    _max_bb_eval = -1;
}

// set_MAX_SIM_BB_EVAL:
void Parameters::set_MAX_SIM_BB_EVAL ( int bbe ) {
  _to_be_checked   = true;
  _max_sim_bb_eval = bbe;
  if ( _max_sim_bb_eval <= 0 )
    _max_sim_bb_eval = -1;
}

// set_MAX_SGTE_EVAL:
void Parameters::set_MAX_SGTE_EVAL ( int bbe ) {
  _to_be_checked  = true;
  _sgte_max_eval = bbe;
  if ( _sgte_max_eval < 0 )
    _sgte_max_eval = -1;
}

// set_MAX_TIME:
void Parameters::set_MAX_TIME ( int t ) {
  _to_be_checked = true;
  _max_time      = t;
  if ( _max_time <= 0 )
    _max_time = -1;
}

// set_MAX_ITERATIONS:
void Parameters::set_MAX_ITERATIONS ( int it ) {
  _to_be_checked  = true;
  _max_iterations = it;
  if ( _max_iterations < 0 )
    _max_iterations = -1;
}

// set_CACHE_SAVE_PERIOD:
void Parameters::set_CACHE_SAVE_PERIOD ( int csp ) {
  _to_be_checked     = true;
  _cache_save_period = csp;
  if ( _cache_save_period <= 0 )
    _cache_save_period = -1;
}

// set_F_TARGET:
void Parameters::set_F_TARGET ( const NOMAD::Double & f ) {
  _to_be_checked = true;
  _f_target      = f;
}

// set_STAT_SUM_TARGET:
void Parameters::set_STAT_SUM_TARGET ( const NOMAD::Double & sst ) {
  _to_be_checked   = true;
  _stat_sum_target = sst;
}

// set_MESH_UPDATE_BASIS:
void Parameters::set_MESH_UPDATE_BASIS ( const NOMAD::Double & mub ) {
  _to_be_checked     = true;
  _mesh_update_basis = mub;
}

// set_INITIAL_MESH_INDEX:
void Parameters::set_INITIAL_MESH_INDEX ( int l0 ) {
  _to_be_checked = true;
  if ( l0 > L_LIMITS )
    l0 = L_LIMITS;
  else if ( l0 < - L_LIMITS )
    l0 = -L_LIMITS;
  _initial_mesh_index = l0;
}

// set_MESH_COARSENING_EXPONENT:
void Parameters::set_MESH_COARSENING_EXPONENT ( int mce ) {
  _to_be_checked = true;
  if ( mce < 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: MESH_COARSENING_EXPONENT");
  _mesh_coarsening_exponent = mce;
}

// set_MESH_REFINING_EXPONENT:
void Parameters::set_MESH_REFINING_EXPONENT ( int mre ) {
  _to_be_checked = true;
  if ( mre >= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: MESH_REFINING_EXPONENT");
  _mesh_refining_exponent = mre;
}

// set_MAX_MESH_INDEX:
void  Parameters::set_MAX_MESH_INDEX ( int lmax ) {
  _to_be_checked = true;
  if ( lmax > L_LIMITS )
    lmax = L_LIMITS;
  _max_mesh_index = lmax;
}

// set_INITIAL_MESH_SIZE (1/3):
void Parameters::set_INITIAL_MESH_SIZE ( int                   index    ,
					 const NOMAD::Double & d        ,
					 bool                  relative   ) {
  if ( index < 0 || index >= _initial_mesh_size.size() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: INITIAL_MESH_INDEX" );
  _to_be_checked = true;
  if ( relative ) {
    if ( !_lb[index].is_defined()  || !_ub[index].is_defined() ||
	 !d.is_defined() || d <= 0.0 || d > 1.0 )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	    "incorrect parameter: INITIAL_MESH_INDEX (relative value)" );
    NOMAD::Double d2 = d;
    d2 *= _ub[index] - _lb[index];
    _initial_mesh_size[index] = d2;
  }
  else
    _initial_mesh_size[index] = d;
}

// set_INITIAL_MESH_SIZE (2/3):
void Parameters::set_INITIAL_MESH_SIZE ( const Point & delta_m_0 , bool relative ) {
  _to_be_checked = true;
  if ( relative ) {
    int nd = delta_m_0.size();
    for ( int i = 0 ; i < nd ; ++i )
      set_INITIAL_MESH_SIZE ( i , delta_m_0[i] , true );
  }
  else
    _initial_mesh_size = delta_m_0;
}

// set_INITIAL_MESH_SIZE (3/3):
void Parameters::set_INITIAL_MESH_SIZE ( const NOMAD::Double & d , bool relative ) {
  if ( _dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: INITIAL_MESH_INDEX (undefined dimension)" );
  _to_be_checked = true;
  if ( relative )
    for ( int i = 0 ; i < _dimension ; ++i )
      set_INITIAL_MESH_SIZE ( i , d , true );
  else
    _initial_mesh_size = Point ( _dimension , d );
}

// set_MIN_MESH_SIZE (1/3):
void Parameters::set_MIN_MESH_SIZE ( int                   index    ,
				     const NOMAD::Double & d        ,
				     bool                  relative   ) {
  if (_dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: MIN_MESH_SIZE (undefined dimension)" );
  
  if ( !_min_mesh_size.is_defined() )
    _min_mesh_size = Point(_dimension);

  if ( index < 0 || index >= _min_mesh_size.size() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: MIN_MESH_SIZE" );
  _to_be_checked = true;
  if ( relative ) {
    if ( !_lb[index].is_defined()  || !_ub[index].is_defined() ||
 	 !d.is_defined() || d <= 0.0 || d > 1.0 )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	    "incorrect parameter: MIN_MESH_SIZE (relative value)" );
    NOMAD::Double d2 = d;
    d2 *= _ub[index] - _lb[index];
    _min_mesh_size[index] = d2;  
  }
  else
    _min_mesh_size[index] = d;
}

// set_MIN_MESH_SIZE (2/3):
void Parameters::set_MIN_MESH_SIZE ( const Point & delta_p_min , bool relative ) {
  _to_be_checked = true;
  if ( relative ) {
    int nd = delta_p_min.size();
    for ( int i = 0 ; i < nd ; ++i )
      set_MIN_MESH_SIZE ( i , delta_p_min[i] , true );
  }
  else
    _min_mesh_size = delta_p_min;
}

// set_MIN_MESH_SIZE (3/3):
void Parameters::set_MIN_MESH_SIZE ( const NOMAD::Double & d , bool relative ) {
  if ( _dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: MIN_MESH_SIZE (undefined dimension)" );
  _to_be_checked = true;
  if ( relative )
    for ( int i = 0 ; i < _dimension ; ++i )
      set_MIN_MESH_SIZE ( i , d , true );
  else
    _min_mesh_size = Point ( _dimension , d );
}

// set_MIN_POLL_SIZE (1/3):
void Parameters::set_MIN_POLL_SIZE ( int                   index    ,
				     const NOMAD::Double & d        ,
				     bool                  relative   ) {
  if (_dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: MIN_POLL_SIZE (undefined dimension)" );
  
  if ( !_min_poll_size.is_defined() )
    _min_poll_size = Point(_dimension);

  if ( index < 0 || index >= _min_poll_size.size() )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
				"incorrect parameter: MIN_POLL_SIZE" );
  _to_be_checked = true;
  if ( relative ) {
    if ( !_lb[index].is_defined()  || !_ub[index].is_defined() ||
 	 !d.is_defined() || d <= 0.0 || d > 1.0 )
      throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	    "incorrect parameter: MIN_POLL_SIZE (relative value)" );
    NOMAD::Double d2 = d;
    d2 *= _ub[index] - _lb[index];
    _min_poll_size[index] = d2;  
  }
  else
    _min_poll_size[index] = d;
}

// set_MIN_POLL_SIZE (2/3):
void Parameters::set_MIN_POLL_SIZE ( const Point & delta_p_min , bool relative ) {
  _to_be_checked = true;
  if ( relative ) {
    int nd = delta_p_min.size();
    for ( int i = 0 ; i < nd ; ++i )
      set_MIN_POLL_SIZE ( i , delta_p_min[i] , true );
  }
  else
    _min_poll_size = delta_p_min;
}

// set_MIN_POLL_SIZE (3/3):
void Parameters::set_MIN_POLL_SIZE ( const NOMAD::Double & d , bool relative ) {
  if ( _dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: MIN_POLL_SIZE (undefined dimension)" );
  _to_be_checked = true;
  if ( relative )
    for ( int i = 0 ; i < _dimension ; ++i )
      set_MIN_POLL_SIZE ( i , d , true );
  else
    _min_poll_size = Point ( _dimension , d );
}

// set_OPPORTUNISTIC_EVAL:
void Parameters::set_OPPORTUNISTIC_EVAL ( bool oe ) {
  _to_be_checked      = true;
  _opportunistic_eval = oe;
}

// set_OPPORTUNISTIC_MIN_NB_SUCCESS:
void Parameters::set_OPPORTUNISTIC_MIN_NB_SUCCESS ( int mns ) {
  _to_be_checked = true;
  if ( mns <= 0 )
    mns = -1;
  _opportunistic_min_nb_success = mns;  
}

// set_OPPORTUNISTIC_MIN_EVAL:
void Parameters::set_OPPORTUNISTIC_MIN_EVAL ( int me ) {
  _to_be_checked = true;
  if ( me <= 0 )
    me = -1;
  _opportunistic_min_eval = me;
}

// set_OPPORTUNISTIC_MIN_F_IMPRVMT:
void Parameters::set_OPPORTUNISTIC_MIN_F_IMPRVMT ( const NOMAD::Double & mfi ) {
  _to_be_checked               = true;
  if ( mfi <= 0.0 )
    _opportunistic_min_f_imprvmt.clear();
  else
    _opportunistic_min_f_imprvmt = mfi;
}

// set_OPPORTUNISTIC_LUCKY_EVAL:
void Parameters::set_OPPORTUNISTIC_LUCKY_EVAL ( bool le ) {
  _to_be_checked            = true;
  _opportunistic_lucky_eval = le;
}

// set_VARIABLE_GROUP:
void Parameters::set_VARIABLE_GROUP ( const set<int>            & var_indexes         ,
				      const set<direction_type> & prim_poll_dir_types ,
				      const set<direction_type> & sec_poll_dir_types  ,
				      int                         halton_seed           ) {
  if ( _dimension <= 0 )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: VARIABLE_GROUP (undefined dimension)" );

  if ( _bb_input_types.empty() ||
       static_cast<int>(_bb_input_types.size()) != _dimension )
    throw Incorrect_Parameter ( __FILE__ , __LINE__ ,
	  "incorrect parameter: VARIABLE_GROUP (undefined black-box input types)" );

  _to_be_checked = true;
  _user_var_groups.insert ( new Variable_Group ( var_indexes         ,
						 prim_poll_dir_types ,
						 sec_poll_dir_types  ,
						 halton_seed         ,
						 _out                  ) );
}
