/*-------------------------------------------------------------------------------------*/
/* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct search - version 3.6.1 */
/* */
/* Copyright (C) 2001-2012 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 */
/* Christophe Tribes - 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: nomad@gerad.ca */
/* phone : 1-514-340-6053 #6928 */
/* fax : 1-514-340-5665 */
/* */
/* This program is free software: you can redistribute it and/or modify it under the */
/* terms of the GNU Lesser 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 Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License along */
/* with this program. If not, see . */
/* */
/* You can find information on the NOMAD software at www.gerad.ca/nomad */
/*-------------------------------------------------------------------------------------*/
/**
\file Variable_Group.cpp
\brief Group of variables (implementation)
\author Sebastien Le Digabel
\date 2010-04-22
\see Variable_Group.hpp
*/
#include "Variable_Group.hpp"
/*-------------------------------------------------------------*/
/* check (also removes fixed variables from the group) */
/*-------------------------------------------------------------*/
bool NOMAD::Variable_Group::check
( const NOMAD::Point & fixed_vars ,
const std::vector & bbit ,
std::vector * in_group ,
bool & mod )
{
// initial checks:
if ( _var_indexes.empty() )
return false;
bool binary = true;
bool categorical = false;
bool reset_dirs = false;
// other checks + filling of vector in_group:
int n = static_cast(bbit.size());
std::set::const_iterator end = _var_indexes.end() ,
it = _var_indexes.begin();
while ( it != end )
{
if ( *it < 0 || *it >= n )
return false;
// check if the variable is fixed:
if ( fixed_vars[*it].is_defined() )
{
reset_dirs = true;
_var_indexes.erase ( it++ );
mod=true;
continue;
}
if ( bbit[*it] == NOMAD::CATEGORICAL )
{
categorical = true;
binary = false;
}
else
{
if ( categorical )
return false;
if ( bbit[*it] != NOMAD::BINARY )
binary = false;
}
if ( in_group )
(*in_group)[*it] = true;
++it;
}
// modify the directions if a fixed variable has been removed:
if ( reset_dirs )
{
int halton_seed = _directions->get_halton_seed();
std::set direction_types
= _directions->get_direction_types();
std::set sec_poll_dir_types
= _directions->get_sec_poll_dir_types();
delete _directions;
_directions = new Directions ( static_cast(_var_indexes.size()) ,
direction_types ,
sec_poll_dir_types ,
halton_seed ,
_out );
}
if ( binary )
_directions->set_binary();
else
{
// we check here that NOMAD::GPS_BINARY is not in
// dir_types nor in sec_poll_dir_types:
const std::set & direction_types
= _directions->get_direction_types();
const std::set & sec_poll_dir_types
= _directions->get_sec_poll_dir_types();
if ( direction_types.find ( NOMAD::GPS_BINARY ) != direction_types.end () ||
sec_poll_dir_types.find ( NOMAD::GPS_BINARY ) != sec_poll_dir_types.end() )
return false;
if ( categorical )
_directions->set_categorical();
}
return true;
}
/*---------------------------------------------------------*/
/* compute the directions */
/*---------------------------------------------------------*/
void NOMAD::Variable_Group::get_directions ( std::list & 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(_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::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 );
}
/*---------------------------------------------------------*/
/* comparison operator */
/*---------------------------------------------------------*/
bool NOMAD::Variable_Group::operator < ( const NOMAD::Variable_Group & vg ) const
{
// variable indexes:
if ( _var_indexes.size() < vg._var_indexes.size() )
return true;
if ( _var_indexes.size() > vg._var_indexes.size() )
return false;
std::set::const_iterator it1 ,
it2 = vg._var_indexes.begin() ,
end = _var_indexes.end();
for ( it1 = _var_indexes.begin() ; it1 != end ; ++it1 , ++it2 ) {
if ( *it1 < *it2 )
return true;
if ( *it1 > *it2 )
return false;
}
// directions:
return ( *_directions < *vg._directions );
}
/*---------------------------------------------------------*/
/* display */
/*---------------------------------------------------------*/
void NOMAD::Variable_Group::display ( const NOMAD::Display & out ) const
{
out << "indexes: { ";
std::set::const_iterator end = _var_indexes.end();
for ( std::set::const_iterator it = _var_indexes.begin() ; it != end ; ++it )
out << *it << " ";
out << "}" << std::endl;
if ( _directions->is_categorical() )
out << "no directions (categorical variables)" << std::endl;
else
out << NOMAD::open_block ( "directions" )
<< *_directions
<< NOMAD::close_block();
}