1 /*-------------------------------------------------------------------------------------*/
2 /* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct search - version 3.7.2 */
3 /* */
4 /* Copyright (C) 2001-2015 Mark Abramson - the Boeing Company, Seattle */
5 /* Charles Audet - Ecole Polytechnique, Montreal */
6 /* Gilles Couture - Ecole Polytechnique, Montreal */
7 /* John Dennis - Rice University, Houston */
8 /* Sebastien Le Digabel - Ecole Polytechnique, Montreal */
9 /* Christophe Tribes - Ecole Polytechnique, Montreal */
10 /* */
11 /* funded in part by AFOSR and Exxon Mobil */
12 /* */
13 /* Author: Sebastien Le Digabel */
14 /* */
15 /* Contact information: */
16 /* Ecole Polytechnique de Montreal - GERAD */
17 /* C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada */
18 /* e-mail: nomad@gerad.ca */
19 /* phone : 1-514-340-6053 #6928 */
20 /* fax : 1-514-340-5665 */
21 /* */
22 /* This program is free software: you can redistribute it and/or modify it under the */
23 /* terms of the GNU Lesser General Public License as published by the Free Software */
24 /* Foundation, either version 3 of the License, or (at your option) any later */
25 /* version. */
26 /* */
27 /* This program is distributed in the hope that it will be useful, but WITHOUT ANY */
28 /* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A */
29 /* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */
30 /* */
31 /* You should have received a copy of the GNU Lesser General Public License along */
32 /* with this program. If not, see <http://www.gnu.org/licenses/>. */
33 /* */
34 /* You can find information on the NOMAD software at www.gerad.ca/nomad */
35 /*-------------------------------------------------------------------------------------*/
36 /**
37 \file SMesh.cpp
38 \brief Class for the MADS mesh (implementation)
39 \author Sebastien Le Digabel
40 \date 2010-04-06
41 \see SMesh.hpp
42 */
43 #include "SMesh.hpp"
44
45
46
47 /*-----------------------------------------------------------*/
48 /* update the mesh */
49 /*-----------------------------------------------------------*/
update(NOMAD::success_type success,const NOMAD::Direction * dir)50 void NOMAD::SMesh::update ( NOMAD::success_type success , const NOMAD::Direction *dir) // , const NOMAD::OrthogonalMesh * mesh )
51 {
52 // defaults:
53 // full success: lk = lk - 1
54 // failure : lk = lk + 1
55
56
57 if ( success == NOMAD::FULL_SUCCESS )
58 {
59 _mesh_index -= _coarsening_step;
60 if ( _mesh_index < -NOMAD::L_LIMITS )
61 _mesh_index = -NOMAD::L_LIMITS;
62 }
63 else if ( success == NOMAD::UNSUCCESSFUL )
64 _mesh_index -= _refining_step;
65
66 if ( _mesh_index > _max_mesh_index )
67 _max_mesh_index = _mesh_index;
68
69
70 if ( _mesh_index < _min_mesh_index )
71 _min_mesh_index = _mesh_index;
72 }
73
74 /*-----------------------------------------------------------*/
75 /* Update the provided mesh indices (the Mesh is unchanged). */
76 /*-----------------------------------------------------------*/
update(NOMAD::success_type success,NOMAD::Point & mesh_indices,const NOMAD::Direction * dir) const77 void NOMAD::SMesh::update ( NOMAD::success_type success , NOMAD::Point & mesh_indices, const NOMAD::Direction *dir ) const
78 {
79
80 if ( mesh_indices.is_defined() )
81 {
82 for (int i=0; i < mesh_indices.size() ; i++)
83 {
84 if ( success == NOMAD::FULL_SUCCESS )
85 {
86 mesh_indices[i] -= _coarsening_step;
87 if ( mesh_indices[i] < -NOMAD::L_LIMITS )
88 mesh_indices[i] = -NOMAD::L_LIMITS;
89 }
90 else if ( success == NOMAD::UNSUCCESSFUL )
91 mesh_indices[i] -= _refining_step;
92 }
93 }
94 }
95
96
97 /*-----------------------------------------------------------*/
98 /* manually set the mesh index */
99 /*-----------------------------------------------------------*/
set_mesh_indices(const NOMAD::Point & r)100 void NOMAD::SMesh::set_mesh_indices ( const NOMAD::Point & r )
101 {
102 if (!r.is_defined())
103 _mesh_index=0;
104 else
105 _mesh_index=r[0].NOMAD::Double::round();
106
107 if ( _mesh_index > _max_mesh_index )
108 _max_mesh_index = _mesh_index;
109 if ( _mesh_index < _min_mesh_index )
110 _min_mesh_index = _mesh_index;
111 }
112
113
114
115 /*-----------------------------------------------------------*/
116 /* set the limit mesh index (max value) */
117 /*-----------------------------------------------------------*/
set_limit_mesh_index(int l)118 void NOMAD::SMesh::set_limit_mesh_index ( int l )
119 {
120 _limit_mesh_index=l;
121 }
122
123
124
125 /*-----------------------------------------------------------*/
126 /* display */
127 /*-----------------------------------------------------------*/
display(const NOMAD::Display & out) const128 void NOMAD::SMesh::display ( const NOMAD::Display & out ) const
129 {
130 out << "n : " << get_n() << std::endl
131 << "mesh update basis : " << _update_basis << std::endl
132 << "mesh coarsening step: " << _coarsening_step << std::endl
133 << "mesh refining step : " << _refining_step << std::endl
134 << "initial mesh size : "
135 << "(" << _delta_0 << " )" << std::endl;
136 out << "minimal mesh size : ";
137 if ( _delta_min.is_defined() )
138 out << "(" << _delta_min << " )" << std::endl;
139 else
140 out << "none";
141 out << std::endl
142 << "minimal poll size : ";
143 if ( _Delta_min_is_defined )
144 out << "(" << _Delta_min << " )" << std::endl;
145 else
146 out << "none";
147 out << std::endl;
148 }
149
150 /*----------------------------------------------------------*/
151 /* check the stopping conditions on the minimal poll size */
152 /* and on the minimal mesh size */
153 /*----------------------------------------------------------*/
check_min_mesh_sizes(bool & stop,NOMAD::stop_type & stop_reason) const154 void NOMAD::SMesh::check_min_mesh_sizes ( bool & stop ,
155 NOMAD::stop_type & stop_reason ) const
156 {
157 if ( stop )
158 return;
159
160 // 1. mesh index tests:
161 if ( abs ( _mesh_index ) > NOMAD::L_LIMITS )
162 {
163 stop = true;
164 stop_reason = NOMAD::L_LIMITS_REACHED;
165 }
166
167 // 2. delta_k^p (poll size) tests:
168 if ( check_min_poll_size_criterion ( ) )
169 {
170 stop = true;
171 stop_reason = NOMAD::DELTA_P_MIN_REACHED;
172 }
173
174 // 3. delta_k^m (mesh size) tests:
175 if ( check_min_mesh_size_criterion ( ) )
176 {
177 stop = true;
178 stop_reason = NOMAD::DELTA_M_MIN_REACHED;
179 }
180 }
181
182 /*-----------------------------------------------------------*/
183 /* check the minimal poll size (private) */
184 /*-----------------------------------------------------------*/
check_min_poll_size_criterion() const185 bool NOMAD::SMesh::check_min_poll_size_criterion ( ) const
186 {
187 if ( !_Delta_min_is_defined )
188 return false;
189 NOMAD::Point Delta;
190 return get_Delta ( Delta );
191 }
192
193 /*-----------------------------------------------------------*/
194 /* check the minimal mesh size (private) */
195 /*-----------------------------------------------------------*/
check_min_mesh_size_criterion() const196 bool NOMAD::SMesh::check_min_mesh_size_criterion ( ) const
197 {
198 if ( !_delta_min.is_defined() )
199 return false;
200 NOMAD::Point delta;
201 return get_delta ( delta );
202 }
203
204 /*----------------------------------------------------------------*/
205 /* get delta (mesh size parameter) */
206 /* delta^k = delta^0 \tau^{ell_0^+ - ell_k^+} */
207 /*----------------------------------------------------------------*/
208 /* the function also returns true if one value is < delta_min */
209 /* (stopping criterion MIN_MESH_SIZE) */
210 /*----------------------------------------------------------------*/
get_delta(NOMAD::Point & delta) const211 bool NOMAD::SMesh::get_delta ( NOMAD::Point & delta ) const
212 {
213 delta.reset ( _n );
214
215 bool delta_min_is_defined=_delta_min.is_defined();
216
217
218 // power_of_tau = tau^{ max{0,l0} - max{0,lk} }:
219 NOMAD::Double power_of_tau
220 = pow ( _update_basis.value() ,
221 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
222 ( (_mesh_index > 0) ? _mesh_index : 0) );
223
224 bool stop = false;
225
226 // delta^k = power_of_tau * delta^0:
227 for ( int i = 0 ; i < _n ; ++i )
228 {
229 delta[i] = _delta_0[i] * power_of_tau;
230 if ( !stop && delta_min_is_defined && delta[i] < _delta_min[i] )
231 stop = true;
232
233 }
234
235 return stop;
236 }
237
238 /*----------------------------------------------------------------*/
239 /* get delta (mesh size parameter) */
240 /* delta^k = delta^0 \tau^{ell_0^+ - ell_k^+} */
241 /*----------------------------------------------------------------*/
get_delta(int i) const242 NOMAD::Double NOMAD::SMesh::get_delta ( int i ) const
243 {
244
245
246 // power_of_tau = tau^{ max{0,l0} - max{0,lk} }:
247 NOMAD::Double power_of_tau
248 = pow ( _update_basis.value() ,
249 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
250 ( (_mesh_index > 0) ? _mesh_index : 0) );
251
252
253 NOMAD::Double delta = _delta_0[i] * power_of_tau;
254
255 return delta;
256 }
257
258
259 /*----------------------------------------------------------------*/
260 /* get delta_max (the larget mesh size) */
261 /*----------------------------------------------------------------*/
get_delta_max() const262 NOMAD::Point NOMAD::SMesh::get_delta_max ( ) const
263 {
264
265 NOMAD::Point delta_max ( _n );
266
267 // power_of_tau = tau^{ max{0,l0} - max{0,lk} }:
268 NOMAD::Double power_of_tau
269 = pow ( _update_basis.value() ,
270 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
271 ( (_min_mesh_index > 0) ? _min_mesh_index : 0) );
272
273 // delta^k = power_of_tau * delta^0:
274 for ( int i = 0 ; i < _n ; ++i )
275 delta_max[i] = _delta_0[i] * power_of_tau;
276
277 return delta_max;
278 }
279
280
281 /*-------------------------------------------------------------------*/
282 /* get Delta (poll size parameter) */
283 /* Delta^k = Delta^m_k \tau^{ |ell_k|/2 } */
284 /* = delta^0 \tau^{ell_0^+ - ell_k^+ + |ell_k|/2} */
285 /*-------------------------------------------------------------------*/
286 /* the function also returns true if all values are < Delta_min */
287 /*-------------------------------------------------------------------*/
get_Delta(NOMAD::Point & Delta) const288 bool NOMAD::SMesh::get_Delta ( NOMAD::Point & Delta ) const
289 {
290
291 Delta.reset ( _n );
292
293 // power_of_tau = tau^{ max{0,l0} - max{0,lk} + |lk|/2}:
294 NOMAD::Double power_of_tau
295 = pow ( _update_basis.value() , abs(_mesh_index) / 2.0 +
296 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
297 ( (_mesh_index > 0) ? _mesh_index : 0) );
298
299 bool stop = true;
300
301 // Delta^k = power_of_tau * Delta^0:
302 for ( int i = 0 ; i < _n ; ++i )
303 {
304 Delta[i] = _Delta_0[i] * power_of_tau;
305 if ( !_Delta_min_is_complete || Delta[i] >= _Delta_min[i] )
306 stop = false;
307
308 if ( _Delta_min_is_defined && _Delta_min[i].is_defined() && Delta[i] < _Delta_min[i] )
309 Delta[i]=_Delta_min[i];
310 }
311
312 return stop;
313 }
314
315 /*-------------------------------------------------------------------*/
316 /* get Delta (poll size parameter) */
317 /* Delta^k = Delta^m_k \tau^{ |ell_k|/2 } */
318 /* = delta^0 \tau^{ell_0^+ - ell_k^+ + |ell_k|/2} */
319 /*--------------------------------------------------------------*/
320 /* the function returns Delta >= Delta_min */
321 /*--------------------------------------------------------------*/
get_Delta(int i) const322 NOMAD::Double NOMAD::SMesh::get_Delta ( int i ) const
323 {
324
325 // power_of_tau = tau^{ max{0,l0} - max{0,lk} + |lk|/2}:
326 NOMAD::Double power_of_tau
327 = pow ( _update_basis.value() , abs(_mesh_index) / 2.0 +
328 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
329 ( (_mesh_index > 0) ? _mesh_index : 0) );
330
331 NOMAD::Double Delta = _Delta_0[i] * power_of_tau;
332
333 if ( _Delta_min_is_defined && _Delta_min[i].is_defined() && Delta < _Delta_min[i] )
334 Delta=_Delta_min[i];
335
336 return Delta;
337 }
338
339
scale_and_project(int i,const NOMAD::Double & l) const340 NOMAD::Double NOMAD::SMesh::scale_and_project(int i, const NOMAD::Double & l) const
341 {
342 NOMAD::Double delta = get_delta ( i );
343 NOMAD::Double Delta = get_Delta ( i );
344
345
346 if ( delta.is_defined() && Delta.is_defined() && i <= _n)
347 {
348 NOMAD::Double d= Delta / delta * l;
349 return d.NOMAD::Double::round()*delta;
350 }
351 else
352 throw NOMAD::Exception ( "SMesh.cpp" , __LINE__ ,
353 "Mesh scaling and projection cannot be performed!" );
354
355 }
356
357
358
359
get_mesh_ratio_if_success(void) const360 NOMAD::Point NOMAD::SMesh::get_mesh_ratio_if_success ( void ) const
361 {
362
363 NOMAD::Double power_of_tau
364 = pow ( _update_basis.value() ,
365 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
366 ( (_mesh_index > 0) ? _mesh_index : 0) );
367
368 NOMAD::Double power_of_tau_if_success
369 = pow ( _update_basis.value() ,
370 ( (_initial_mesh_index > 0) ? _initial_mesh_index : 0) -
371 ( (_mesh_index - _coarsening_step > 0) ? _mesh_index - _coarsening_step : 0) );
372
373 try
374 {
375 NOMAD::Double ratio_scalaire = power_of_tau_if_success/power_of_tau;
376 return NOMAD::Point( _n , ratio_scalaire );
377 }
378 catch ( NOMAD::Double::Invalid_Value & )
379 {
380 return NOMAD::Point( _n,-1 );
381 }
382 }
383