/*----------------------------------------------------------------*/ bool NOMAD::Directions::compute_one_direction ( NOMAD::Direction & dir, int mesh_index, int halton_index ) { dir.clear(); // categorical variables: do nothing: if ( _is_categorical ) return false; /*-------------------------------*/ /* binary variables */ /* (we use a random direction) */ /*-------------------------------*/ if ( _is_binary ) { dir.reset ( _nc , 0.0 ); dir.set_type ( NOMAD::GPS_BINARY ); dir[NOMAD::RNG::rand()%_nc] = (NOMAD::RNG::rand()%2) ? -1.0 : 1.0; } /*----------------*/ /* Ortho-MADS */ /*----------------*/ else if ( _is_orthomads ) { if ( !_primes ) ortho_mads_init ( _halton_seed ); dir.reset ( _nc , 0.0 ); dir.set_type ( NOMAD::ORTHO_1 ); NOMAD::Double alpha_t_l; if ( !compute_halton_dir ( halton_index , mesh_index , alpha_t_l , dir ) ) return false; // } } /*-------------*/ /* LT-MADS 1 */ /*-------------*/ else { if ( !_lt_initialized) lt_mads_init(); int hat_i; dir = *get_bl ( mesh_index , NOMAD::LT_1 , hat_i ); } return true; }
/*-----------------------------------------------------------------------------*/ bool NOMAD::Directions::compute_dir_on_unit_sphere ( NOMAD::Direction & random_dir ) const { int i; NOMAD::Double norm,d; for ( i = 0 ; i < _nc ; ++i ) random_dir[i]=NOMAD::RNG::normal_rand(0,1); norm=random_dir.norm(); if ( norm==0 ) return false; for ( i = 0 ; i < _nc ; ++i ) random_dir[i]/=norm; return true; }
/*----------------------------------------------------------------*/ void NOMAD::Directions::householder ( const NOMAD::Direction & halton_dir , bool complete_to_2n , NOMAD::Direction ** H ) const { int i , j; NOMAD::Double norm2 = halton_dir.squared_norm() , v , h2i; for ( i = 0 ; i < _nc ; ++i ) { h2i = 2 * halton_dir[i]; for ( j = 0 ; j < _nc ; ++j ) { // H[i]: (*H[i])[j] = v = (i==j) ? norm2 - h2i * halton_dir[j] : - h2i * halton_dir[j]; // -H[i]: if ( complete_to_2n ) (*H[i+_nc])[j] = -v; } } }
/*---------------------------------------------------------*/ bool NOMAD::Directions::compute_halton_dir ( int halton_index , int mesh_index , NOMAD::Double & alpha_t_l , NOMAD::Direction & halton_dir ) const { alpha_t_l.clear(); int i; NOMAD::Double d , norm = 0.0; NOMAD::Point b ( _nc ); for ( i = 0 ; i < _nc ; ++i ) { d = Directions::get_phi ( halton_index , _primes[i] ); b[i] = 2*d - 1.0; norm += b[i].pow2(); } norm = norm.sqrt(); // desired squared norm for q: NOMAD::direction_type hdt = halton_dir.get_type(); NOMAD::Double target = ( hdt == NOMAD::ORTHO_2N || hdt == NOMAD::ORTHO_NP1_QUAD || hdt == NOMAD::ORTHO_NP1_NEG ) ? pow ( NOMAD::Mesh::get_mesh_update_basis() , abs(mesh_index) / 2.0 ) : pow ( NOMAD::Mesh::get_mesh_update_basis() , abs(mesh_index) ); NOMAD::Double x = target.sqrt(); NOMAD::Double fx = eval_ortho_norm ( x , norm , b , halton_dir ); NOMAD::Double y = 1.0 , fy , delta_x , abs_dx , min , delta_min , diff , eps; bool inc , possible , set_eps = false; int cnt = 0; while ( fx != target ) { // safety test: if ( ++cnt > 1000 ) { #ifdef DEBUG _out << std::endl << "Warning (" << "Directions.cpp" << ", " << __LINE__ << "): could not compute Halton direction for (t=" << halton_index << ", ell=" << mesh_index << ")" << std::endl << std::endl; #endif alpha_t_l.clear(); halton_dir.clear(); return false; } if ( set_eps ) { eps = 1e-8; set_eps = false; } else eps = 0.0; inc = ( fx < target ); possible = false; min = 1e+20; for ( i = 0 ; i < _nc ; ++i ) { if ( b[i] != 0.0 ) { if ( b[i] > 0.0 ) { if ( inc ) diff = 0.5+eps; else diff = -0.5-eps; } else { if ( inc ) diff = -0.5-eps; else diff = 0.5+eps; } delta_x = norm * ( halton_dir[i] + diff) / b[i] - x; y = x + delta_x; if ( y > 0 ) { abs_dx = delta_x.abs(); if ( abs_dx < min ) { min = abs_dx; delta_min = delta_x; possible = true; } } } } if ( !possible ) { #ifdef DEBUG _out << std::endl << "Warning (" << "Directions.cpp" << ", " << __LINE__ << "): could not compute Halton direction for (t=" << halton_index << ", ell=" << mesh_index << ")" << std::endl << std::endl; #endif alpha_t_l.clear(); halton_dir.clear(); return false; } y = x + delta_min; fy = eval_ortho_norm ( y , norm , b , halton_dir ); if ( fx == fy ) { set_eps = true; continue; } if ( fy==target ) break; if ( inc && fy > target && fx > 0 ) { eval_ortho_norm ( x , norm , b , halton_dir ); break; } if ( !inc && fy < target && fy > 0 ) break; x = y; fx = fy; } alpha_t_l = y; return true; }
/// Reset the infeasible successful direction. void reset_infeas_success_dir ( void ) const { _infeas_success_dir.clear(); }
/*---------------------------------------------------------*/ void NOMAD::Variable_Group::get_directions ( std::list<NOMAD::Direction> & dirs , NOMAD::poll_type poll , const NOMAD::Point & poll_center , int mesh_index , const NOMAD::Direction & feas_success_dir , const NOMAD::Direction & infeas_success_dir ) { int nc = static_cast<int>(_var_indexes.size()); // vectors are of size nc : // ------------------------ if ( nc == poll_center.size() ) { _directions->compute ( dirs , poll , poll_center , mesh_index , -1 , feas_success_dir , infeas_success_dir ); return; } // construct vectors of size nc from vectors of size < nc : // -------------------------------------------------------- std::set<int>::const_iterator it ; int i = 0; NOMAD::Point new_poll_center ( nc ); NOMAD::Direction new_fsd , new_isd; if ( feas_success_dir.is_defined() ) new_fsd = NOMAD::Direction ( nc , 0.0 , feas_success_dir.get_type() ); if ( infeas_success_dir.is_defined() ) new_isd = NOMAD::Direction ( nc , 0.0 , infeas_success_dir.get_type() ); for ( it = _var_indexes.begin() ; it != _var_indexes.end() ; ++it ) { new_poll_center[i] = poll_center[*it]; if ( feas_success_dir.is_defined() ) new_fsd[i] = feas_success_dir [*it]; if ( infeas_success_dir.is_defined() ) new_isd[i] = infeas_success_dir[*it]; ++i; } _directions->compute ( dirs , poll , new_poll_center , mesh_index , -1 , new_fsd , new_isd ); }