/*-----------------------------------------------------------*/
void NOMAD::LH_Search::values_for_var_i ( int                          p           ,
                                         const NOMAD::Double        & delta     ,
                                         const NOMAD::Double        & delta_max ,
                                         const NOMAD::bb_input_type & bbit        ,
                                         const NOMAD::Double        & lb          ,
                                         const NOMAD::Double        & ub          ,
                                         NOMAD::Point               & x      ) const
{
    // categorical variables have already been treated as fixed variables:
    if ( bbit == NOMAD::CATEGORICAL )
        return;
    
    int                  i;
    NOMAD::Double        v;
    NOMAD::Random_Pickup rp (p);
    bool                 rounding = ( bbit != NOMAD::CONTINUOUS );
    bool                 lb_def   = lb.is_defined();
    bool                 ub_def   = ub.is_defined();
    double               w        = ( ( lb_def && ub_def ) ?
                                     ub.value()-lb.value() : 1.0 ) / p;
    // main loop:
    for ( i = 0 ; i < p ; ++i )
    {

        // both bounds exist:
        if ( lb_def && ub_def )
            v = lb + ( i + NOMAD::RNG::rand()/NOMAD::D_INT_MAX ) * w;
        // one of the bounds does not exist:
        else
        {
            
            // lb exists, and ub not: mapping [0;1] --> [lb;+INF[
            if ( lb_def )
                v = lb + 10 * delta_max * sqrt ( - log ( NOMAD::DEFAULT_EPSILON +
                                                          ( i + NOMAD::RNG::rand()/NOMAD::D_INT_MAX ) * w ) );
            
            // lb does not exist:
            else
            {
                
                // ub exists, and lb not: mapping [0;1] --> ]-INF;ub]
                if ( ub_def )
                    v = ub - delta_max * 10 *
                    sqrt ( -log ( NOMAD::DEFAULT_EPSILON +
                                 ( i +NOMAD::RNG::rand()/NOMAD::D_INT_MAX ) * w ) );
                
                // there are no bounds: mapping [0;1] --> ]-INF;+INF[
                else
                    v = (NOMAD::RNG::rand()%2 ? -1.0 : 1.0) * delta_max * 10 *
                    sqrt ( - log ( NOMAD::DEFAULT_EPSILON +
                                  ( i + NOMAD::RNG::rand()/NOMAD::D_INT_MAX ) * w ) );
            }
        }
        
        // rounding:
        if ( rounding )
            v = v.round();
        
        // projection to mesh (with ref=0):
        v.project_to_mesh ( 0.0 , delta , lb , ub );
        
        // affectation + permutation:
        x[rp.pickup()] = v;
    }
}
Example #2
0
/*---------------------------------------------------------*/
void NOMAD::Directions::compute ( std::list<NOMAD::Direction> & dirs               ,
				  NOMAD::poll_type              poll               ,
				  const NOMAD::Point          & poll_center        ,
				  int                           mesh_index         ,
				  int                           halton_index       ,
				  const NOMAD::Direction      & feas_success_dir   ,
				  const NOMAD::Direction      & infeas_success_dir   )
{
	
	dirs.clear();
	
	// categorical variables: do nothing:
	if ( _is_categorical )
		return;
	
	// binary variables: we use special directions:
	if ( _is_binary )
	{
		compute_binary_directions ( dirs );
		return;
	}
	
	NOMAD::Double                               pow_gps , cst;
	const NOMAD::Direction                    * bl;
	NOMAD::Direction                          * pd;
	int                                         i , j , k , hat_i;
	std::list<NOMAD::Direction>::const_iterator it2 , end2;
	
	/*-----------------------------------*/
	/*  loop on the types of directions  */
	/*-----------------------------------*/
	const std::set<NOMAD::direction_type> & dir_types =
    (poll == NOMAD::PRIMARY) ? _direction_types : _sec_poll_dir_types;
	
	std::set<NOMAD::direction_type>::const_iterator it , end = dir_types.end() ;
	for ( it = dir_types.begin() ; it != end ; ++it )
	{
		
		if ( *it == NOMAD::UNDEFINED_DIRECTION ||
			*it == NOMAD::NO_DIRECTION        ||
			*it == NOMAD::MODEL_SEARCH_DIR       )
			continue;
		
		/*--------------*/
		/*  Ortho-MADS  */
		/*--------------*/
		if ( NOMAD::dir_is_orthomads (*it) )
		{
			
			// Ortho-MADS initializations:
			if ( !_primes )
				ortho_mads_init ( _halton_seed );
			
			// halton index:
			if ( halton_index < 0 )
			{	
				int max_halton_index = NOMAD::Mesh::get_max_halton_index();
				
				// mesh_index+ _halton_seed -> used to make sure that the sequence of strictly increasing mesh_index produces a non biased sequence of halton_index 
				halton_index = ( mesh_index >= NOMAD::Mesh::get_max_mesh_index() ) ? mesh_index + _halton_seed : max_halton_index + 1;  
				if ( halton_index > max_halton_index )
					NOMAD::Mesh::set_max_halton_index ( halton_index );
			}
			
			NOMAD::Direction halton_dir ( _nc , 0.0 , *it );
			NOMAD::Double    alpha_t_l;
			
			if ( compute_halton_dir ( halton_index ,
									 mesh_index   ,
									 alpha_t_l    ,
									 halton_dir     ) ) 
			{
				
#ifdef DEBUG
				_out << std::endl
				<< NOMAD::open_block ( "compute Ortho-MADS directions with" )
				<< "type              = " << *it          << std::endl
				<< "Halton index (tk) = " << halton_index << std::endl
				<< "mesh index   (lk) = " << mesh_index   << std::endl
				<< "alpha     (tk,lk) = " << alpha_t_l    << std::endl
				<< "Halton direction  = ( ";
				halton_dir.NOMAD::Point::display ( _out , " " , -1 , -1 );
				_out << " )" << std::endl << NOMAD::close_block();
#endif
				
				
				
				// Ortho-MADS 2n and n+1:
				// ----------------------
				if ( *it == NOMAD::ORTHO_2N || *it == NOMAD::ORTHO_NP1_QUAD || *it == NOMAD::ORTHO_NP1_NEG )
				{
					
					// creation of the 2n directions:
					// For ORTHO_NP1 the reduction from 2N to N+1 is done in MADS::POLL
					NOMAD::Direction ** H = new NOMAD::Direction * [2*_nc];
					
					// Ordering D_k alternates Hk and -Hk instead of [H_k -H_k] 
					for ( i = 0 ; i < _nc ; ++i )
					{
						dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
						H[i    ] = &(*(--dirs.end()));
						dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
						H[i+_nc] = &(*(--dirs.end()));
					}
					
					// Householder transformations on the 2n directions:
					householder ( halton_dir ,
								 true       ,     // complete_to_2n = true
								 H            );
					
					delete [] H;
					
					
				}
				
				// Ortho-MADS 1 or Ortho-MADS 2:
				// -----------------------------
				else
				{
					dirs.push_back ( halton_dir );
					if ( *it == NOMAD::ORTHO_2 )
						dirs.push_back ( -halton_dir );
				}
			}
		}
		
		/*-----------*/
		/*  LT-MADS  */
		/*-----------*/
		else if ( NOMAD::dir_is_ltmads (*it) ) {
			
			if ( !_lt_initialized)
				lt_mads_init();
			
			bl = get_bl ( mesh_index , *it , hat_i );
			
			// LT-MADS 1 or LT-MADS 2: -b(l) and/or b(l):
			// ------------------------------------------
			if ( *it == NOMAD::LT_1 || *it == NOMAD::LT_2 ) {
				dirs.push_back ( - *bl );
				if ( *it == NOMAD::LT_2 )
					dirs.push_back ( *bl );
			}
			
			// LT-MADS 2n or LT-MADS n+1:
			// --------------------------
			else {
				
				// row permutation vector:
				int * row_permutation_vector  = new int [_nc];
				row_permutation_vector[hat_i] = hat_i;
				
				NOMAD::Random_Pickup rp ( _nc );
				
				for ( i = 0 ; i < _nc ; ++i )
					if ( i != hat_i ) {
						j = rp.pickup();
						if ( j == hat_i )
							j = rp.pickup();
						row_permutation_vector[i] = j;
					}
				
				rp.reset();
				
				for ( j = 0 ; j < _nc ; ++j ) {
					
					i = rp.pickup();
					
					if ( i != hat_i ) {
						
						dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
						pd = &(*(--dirs.end()));
						
						create_lt_direction ( mesh_index , *it , i , hat_i , pd );
						
						permute_coords ( *pd , row_permutation_vector );
					}
					else
						dirs.push_back ( *bl );
					
					// completion to maximal basis:
					if ( *it == NOMAD::LT_2N )
						dirs.push_back ( NOMAD::Direction ( - *(--dirs.end()) , NOMAD::LT_2N ) );
				}
				
				delete [] row_permutation_vector;
				
				// completion to minimal basis:
				if ( *it == NOMAD::LT_NP1 ) {
					
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::LT_NP1 ) );
					pd = &(*(--dirs.end()));
					
					end2 = --dirs.end();
					for ( it2 = dirs.begin() ; it2 != end2 ; ++it2 ) {
						for ( i = 0 ; i < _nc ; ++i )
							(*pd)[i] -= (*it2)[i];
					}
				}
			}
		}
		
		/*-------*/
		/*  GPS  */
		/*-------*/
		else {
			
			// GPS for binary variables: should'nt be here:
			if ( *it == NOMAD::GPS_BINARY ) {
#ifdef DEBUG
				_out << std::endl << "Warning (" << "Directions.cpp" << ", " << __LINE__
				<< "): tried to generate binary directions at the wrong place)"
				<< std::endl << std::endl;
#endif
				dirs.clear();
				return;
			}
			
			// this value represents the non-zero values in GPS directions
			// (it is tau^{|ell_k|/2}, and it is such that Delta^m_k * pow_gps = Delta^p_k):
			if ( !pow_gps.is_defined() )
				pow_gps = pow ( NOMAD::Mesh::get_mesh_update_basis() , abs(mesh_index) / 2.0 );
			
			// GPS 2n, static:
			// ---------------
			if ( *it == NOMAD::GPS_2N_STATIC ) {
				
				for ( i = 0 ; i < _nc ; ++i ) {
					
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_STATIC ) );
					pd = &(*(--dirs.end()));
					(*pd)[i] = pow_gps;
					
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_STATIC ) );
					pd = &(*(--dirs.end()));
					(*pd)[i] = -pow_gps;
				}
			}
			
			// GPS 2n, random:
			// ---------------
			else if ( *it == NOMAD::GPS_2N_RAND ) {
				
				int v , cnt;
				
				std::list  <int>::const_iterator end3;
				std::list  <int>::iterator       it3;
				std::list  <int> rem_cols;
				std::vector<int> rem_col_by_row ( _nc );
				
				// creation of the 2n directions:
				std::vector<NOMAD::Direction *> pdirs ( 2 * _nc );
				
				for ( i = 0 ; i < _nc ; ++i ) {
					
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_RAND ) );
					pdirs[i] = &(*(--dirs.end()));
					(*pdirs[i])[i] = pow_gps;
					
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_RAND ) );
					pdirs[i+_nc] = &(*(--dirs.end()));
					(*pdirs[i+_nc])[i] = -pow_gps;
					
					rem_cols.push_back(i);
					rem_col_by_row[i] = i;
				}
				
				// random perturbations:
				for ( i = 1 ; i < _nc ; ++i ) {
					if ( rem_col_by_row[i] > 0 ) { 
						v = NOMAD::RNG::rand()%3 - 1; // v in { -1 , 0 , 1 }  
						if ( v ) {
							
							// we decide a (i,j) couple:
							k    = NOMAD::RNG::rand()%(rem_col_by_row[i]); 
							cnt  = 0;
							end3 = rem_cols.end();
							it3  = rem_cols.begin();
							while ( cnt != k ) {
								++it3;
								++cnt;
							}
							j = *it3;
							
							// the perturbation:
							(*pdirs[i])[j] = (*pdirs[j+_nc])[i] = -v * pow_gps;
							(*pdirs[j])[i] = (*pdirs[i+_nc])[j] =  v * pow_gps;
							
							// updates:
							rem_cols.erase(it3);      
							it3 = rem_cols.begin();
							while ( *it3 != i )
								++it3;
							rem_cols.erase(it3);
							for ( k = i+1 ; k < _nc ; ++k )
								rem_col_by_row[k] -= j<k ? 2 : 1;
						}       
					}
				}
			}
			
			// GPS n+1, static:
			// ----------------
			else if ( *it == NOMAD::GPS_NP1_STATIC ) {
				
				// (n+1)^st direction:
				dirs.push_back ( NOMAD::Direction ( _nc , -pow_gps , NOMAD::GPS_NP1_STATIC ) );
				
				// first n directions:
				for ( i = 0 ; i < _nc ; ++i ) {
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC ) );
					pd = &(*(--dirs.end()));
					(*pd)[i] = pow_gps;
				}
			}
			
			// GPS n+1, random:
			// ----------------
			else if ( *it == NOMAD::GPS_NP1_RAND )
			{
				
				// (n+1)^st direction:
				dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_RAND ) );
				NOMAD::Direction * pd1 = &(*(--dirs.end()));
				
				NOMAD::Double d;
				
				// first n directions:
				for ( i = 0 ; i < _nc ; ++i ) 
				{
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_RAND ) );
					pd = &(*(--dirs.end()));
					
					d = NOMAD::RNG::rand()%2 ? -pow_gps : pow_gps;  
					(*pd )[i] =  d;
					(*pd1)[i] = -d;
				}
			}
			
			// GPS n+1, static, uniform angles:
			// --------------------------------
			else if ( *it == NOMAD::GPS_NP1_STATIC_UNIFORM ) 
			{
				
				cst = pow_gps * sqrt(static_cast<double>(_nc)*(_nc+1))/_nc;
				
				// n first directions:
				for ( j = _nc-1 ; j >= 0 ; --j )
				{
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
					pd = &(*(--dirs.end()));
					
					k = _nc-j-1;
					
					for ( i = 0 ; i < k ; ++i )
						(*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
					
					(*pd)[k] = (cst * (j+1)) / sqrt(static_cast<double>(j+1)*(j+2));
					
				}
				
				// (n+1)^st direction:
				dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
				pd = &(*(--dirs.end()));
				for ( i = 0 ; i < _nc ; ++i )
					(*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
				
			}
			
			// GPS n+1, random, uniform angles:
			// --------------------------------
			// (we apply the procedure defined in
			// "Pattern Search Methods for user-provided points:
			// application to molecular geometry problems",
			// by Alberto, Nogueira, Rocha and Vicente,
			// SIOPT 14-4, 1216-1236, 2004, doi:10.1137/S1052623400377955)
			else if ( *it == NOMAD::GPS_NP1_RAND_UNIFORM ) 
			{
				
				cst = pow_gps * sqrt(static_cast<double>(_nc)*(_nc+1))/_nc;
				
				// n first directions:
				for ( j = _nc-1 ; j >= 0 ; --j )
				{
					dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
					pd = &(*(--dirs.end()));
					
					k = _nc-j-1;
					
					for ( i = 0 ; i < k ; ++i )
						(*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
					
					(*pd)[k] = (cst * (j+1)) / sqrt(static_cast<double>(j+1)*(j+2));
					
				}
				
				// (n+1)^st direction:
				dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
				pd = &(*(--dirs.end()));
				for ( i = 0 ; i < _nc ; ++i )
					(*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
				
				// random perturbations:
				NOMAD::Random_Pickup                  rp   ( _nc );
				std::vector<bool>                     done ( _nc );
				bool                                  chg_sgn;
				std::list<NOMAD::Direction>::iterator it;
				NOMAD::Double                         tmp;
				
				end2 = dirs.end();
				for ( i = 0 ; i < _nc ; ++i )
					done[i] = false;
				
				for ( i = 0 ; i < _nc ; ++i ) 
				{
					
					k = rp.pickup();
					
					if ( i != k && !done[i] ) 
					{
						
						chg_sgn = ( NOMAD::RNG::rand()%2 != 0 );  
						
						for ( it = dirs.begin() ; it != end2 ; ++it ) 
						{
							tmp      = (*it)[i];
							(*it)[i] = ( chg_sgn ? -1.0 : 1.0 ) * (*it)[k];
							(*it)[k] = tmp;
						}
						
						done[i] = done[k] = true;
					}
					else
						if ( NOMAD::RNG::rand()%2 )   
							for ( it = dirs.begin() ; it != end2 ; ++it )
								(*it)[i] = -(*it)[i];
				}
			}
		}
	} // end of loop on the types of directions
}