NOMAD Source  Version 4.0.0 Beta
RunParameters.cpp
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------------*/
2 /* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct Search - */
3 /* */
4 /* NOMAD - Version 4.0.0 has been created by */
5 /* Viviane Rochon Montplaisir - Polytechnique Montreal */
6 /* Christophe Tribes - Polytechnique Montreal */
7 /* */
8 /* The copyright of NOMAD - version 4.0.0 is owned by */
9 /* Charles Audet - Polytechnique Montreal */
10 /* Sebastien Le Digabel - Polytechnique Montreal */
11 /* Viviane Rochon Montplaisir - Polytechnique Montreal */
12 /* Christophe Tribes - Polytechnique Montreal */
13 /* */
14 /* NOMAD v4 has been funded by Rio Tinto, Hydro-Québec, NSERC (Natural */
15 /* Sciences and Engineering Research Council of Canada), InnovÉÉ (Innovation */
16 /* en Énergie Électrique) and IVADO (The Institute for Data Valorization) */
17 /* */
18 /* NOMAD v3 was created and developed by Charles Audet, Sebastien Le Digabel, */
19 /* Christophe Tribes and Viviane Rochon Montplaisir and was funded by AFOSR */
20 /* and Exxon Mobil. */
21 /* */
22 /* NOMAD v1 and v2 were created and developed by Mark Abramson, Charles Audet, */
23 /* Gilles Couture, and John E. Dennis Jr., and were funded by AFOSR and */
24 /* Exxon Mobil. */
25 /* */
26 /* Contact information: */
27 /* Polytechnique Montreal - GERAD */
28 /* C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada */
29 /* e-mail: nomad@gerad.ca */
30 /* */
31 /* This program is free software: you can redistribute it and/or modify it */
32 /* under the terms of the GNU Lesser General Public License as published by */
33 /* the Free Software Foundation, either version 3 of the License, or (at your */
34 /* option) any later version. */
35 /* */
36 /* This program is distributed in the hope that it will be useful, but WITHOUT */
37 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
38 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License */
39 /* for more details. */
40 /* */
41 /* You should have received a copy of the GNU Lesser General Public License */
42 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
43 /* */
44 /* You can find information on the NOMAD software at www.gerad.ca/nomad */
45 /*---------------------------------------------------------------------------------*/
46 
47 #include "../Math/RNG.hpp" // for setSeed()
48 #include "../Param/RunParameters.hpp"
49 #include "../Util/fileutils.hpp"
50 
51 #include "../nomad_version.hpp"
52 
53 
54 // Static members initialization
55 bool NOMAD::RunParameters::_warningUnknownParamShown = false;
56 
57 /*----------------------------------------*/
58 /* initializations (private) */
59 /*----------------------------------------*/
60 void NOMAD::RunParameters::init()
61 {
62  _typeName = "Run";
63 
64  try
65  {
66  #include "../Attribute/runAttributesDefinition.hpp"
67  registerAttributes( _definition );
68 
69  // Registered attributes using defined keywords (not in preprocessed special header file)
70  registerAttribute<NOMAD::Double>("EPSILON", NOMAD::DEFAULT_EPSILON, false,
71  " NOMAD precision for comparison of values ",
72  " \n \n . NOMAD precision for comparison of values \n "," advanced precision double(s) value(s) number(s) ");
73  registerAttribute<std::string>("UNDEF_STR", NOMAD::DEFAULT_UNDEF_STR, false,
74  "String for undefined values ",
75  " \n \n String for undefined values \n "," advanced undef(ined) value(s) string(s) ");
76  registerAttribute<std::string>("NOMAD_VERSION", NOMAD_VERSION_NUMBER, true,
77  " NOMAD version number (for runner) ",
78  " \n \n . NOMAD version number (optional) \n . If not compatible with current version will trigger exception \n " ," advanced nomad version(s) release(s) revision(s) " );
79  registerAttribute<std::string>("INF_STR", NOMAD::DEFAULT_INF_STR, false,
80  "String for infinite values",
81  " \n \n . String for infinite values \n "," advanced string(s) inf(inite) value(s) ");
82  registerAttribute<std::string>("PROBLEM_DIR", std::string(".") + NOMAD::DIR_SEP , false,
83  "Problem directory " ,
84  "\n \n . Problem directory \n . To complete \n "," problem dir(ectory) folder(s) ");
85  // Note: we cannot call checkAndComply() here, the default values
86  // are not valid.
87  }
88  catch (NOMAD::Exception & e)
89  {
90  std::string errorMsg = "Attribute registration failed: ";
91  errorMsg += e.what();
92  throw NOMAD::Exception(__FILE__,__LINE__, errorMsg);
93  }
94 }
95 
96 
97 /*----------------------------------------*/
98 /* check the parameters */
99 /*----------------------------------------*/
100 void NOMAD::RunParameters::checkAndComply(
101  const std::shared_ptr<NOMAD::EvaluatorControlGlobalParameters>& evaluatorControlGlobalParams,
102  const std::shared_ptr<NOMAD::PbParameters>& pbParams)
103 {
104  std::string err;
105  checkInfo();
106 
107  if (!toBeChecked())
108  {
109  // Early out
110  return;
111  }
112 
113  // check the non-interpreted parameters:
114  //const std::shared_ptr<NOMAD::ParameterEntry> pe = getNonInterpretedParamEntry();
115  std::vector<std::shared_ptr<NOMAD::ParameterEntry>> allNonInterp = getAllNonInterpretedParamEntries();
116  if (allNonInterp.size() > 0)
117  {
118  err = "Unrecognized parameters in file " + allNonInterp[0]->getParamFile() + ":\n";
119  for (auto pe : allNonInterp)
120  {
121  err += "line " + std::to_string(pe->getLine());
122  err += ": Unrecognized parameter: " + pe->getName() + "\n";
123  }
124  if (getAttributeValueProtected<bool>("REJECT_UNKNOWN_PARAMETERS", false))
125  {
126  throw NOMAD::Exception(__FILE__,__LINE__, err);
127  }
128  else
129  {
130  if (!_warningUnknownParamShown)
131  {
132  std::cerr << "Warning: " << err << "Ignoring unknown parameters." << std::endl;
133  }
134  }
135  }
136 
137  auto problemDir = getAttributeValueProtected<std::string>("PROBLEM_DIR", false);
138 
139  auto seed = getAttributeValueProtected<int>("SEED" ,false);
140  if ( seed < 0)
141  {
142  throw NOMAD::Exception(__FILE__,__LINE__, "Parameters check: SEED must be non-negative" );
143  }
144 
145  auto version_number = getAttributeValueProtected<std::string>("NOMAD_VERSION", false);
146  if ( version_number != NOMAD_VERSION_NUMBER )
147  {
148  err = "Parameters check: NOMAD_VERSION is not compatible with registered version " + std::string(NOMAD_VERSION_NUMBER) + "\n";
149  throw NOMAD::Exception(__FILE__,__LINE__, err );
150  }
151 
152  auto anisotropyFactor = getAttributeValueProtected<NOMAD::Double>("ANISOTROPY_FACTOR", false);
153  if ( anisotropyFactor <= 0)
154  {
155  throw NOMAD::Exception(__FILE__,__LINE__, "Parameters check: ANISOTROPY_FACTOR must be positive" );
156  }
157 
158  setStaticParameters();
159 
160  /*-------------------*/
161  /* Disable parameter */
162  /*-------------------*/
163  // Convert all disabled entries (MODELS, EVAL_SORT, ...) to upper case.
164  auto disabledConst = getAttributeValueProtected<NOMAD::ArrayOfString>("DISABLE", false);
165  NOMAD::ArrayOfString disabled;
166  for (size_t i = 0; i < disabledConst.size(); i++)
167  {
168  std::string disabledI = disabledConst[i];
169  NOMAD::toupper(disabledI);
170  disabled.add(disabledI);
171  }
172  setAttributeValue("DISABLE", disabled);
173 
174  /*---------------------------*/
175  /* Sgtelib Search parameters */
176  /*---------------------------*/
177  const size_t bigDim = 50;
178  size_t n = pbParams->getAttributeValue<size_t>("DIMENSION");
179 #ifdef USE_SGTELIB
180  bool showDisableWarn = true;
181 #endif
182  // If dimension is too large, disable models.
183  disabled = getAttributeValueProtected<NOMAD::ArrayOfString>("DISABLE", false);
184  if (n >= bigDim)
185  {
186  if (-1 == disabled.find("MODELS"))
187  {
188  disabled.add(std::string("MODELS"));
189  setAttributeValue("DISABLE", disabled);
190  std::cerr << "Warning: Dimension " << n << " is greater than (or equal to) " << bigDim << ". Models are disabled." << std::endl;
191 #ifdef USE_SGTELIB
192  showDisableWarn = false;
193 #endif
194  }
195  }
196 #ifdef USE_SGTELIB
197  // If models are disabled, set SGTELIB_SEARCH to false.
198  disabled = getAttributeValueProtected<NOMAD::ArrayOfString>("DISABLE", false);
199  if (disabled.find("MODELS") >= 0)
200  {
201  if (getAttributeValueProtected<bool>("SGTELIB_SEARCH", false))
202  {
203  if (showDisableWarn)
204  {
205  std::cerr << "Warning: Models are disabled. SGTELIB_SEARCH set to false." << std::endl;
206  }
207  setAttributeValue("SGTELIB_SEARCH", false);
208  }
209  if (getAttributeValueProtected<bool>("QUAD_MODEL_SEARCH", false))
210  {
211  if (showDisableWarn)
212  {
213  std::cerr << "Warning: Models are disabled. QUAD_MODEL_SEARCH set to false." << std::endl;
214  }
215  setAttributeValue("QUAD_MODEL_SEARCH", false);
216  }
217  }
218 #endif
219 
220  // Set default value, if the parameter is not set.
221  // Default value: TYPE LOWESS DEGREE 1 KERNEL_SHAPE OPTIM KERNEL_COEF OPTIM RIDGE 0 METRIC AOECV
222  auto sgtelibModelDefinition = getAttributeValueProtected<NOMAD::ArrayOfString>("SGTELIB_MODEL_DEFINITION",false);
223  if (sgtelibModelDefinition.size() == 0)
224  {
225  //NOMAD::ArrayOfString aos("TYPE LOWESS DEGREE 1 KERNEL_SHAPE OPTIM KERNEL_COEF OPTIM RIDGE 0 METRIC AOECV");
226  NOMAD::ArrayOfString aos("TYPE PRS DEGREE 2");
227  setAttributeValue("SGTELIB_MODEL_DEFINITION", aos );
228  }
229 
230  auto sgtelibModelTrials = getAttributeValueProtected<size_t>("SGTELIB_MODEL_TRIALS", false);
231  if (0 == sgtelibModelTrials)
232  {
233  throw NOMAD::Exception(__FILE__, __LINE__, "Parameter SGTELIB_MODEL_TRIALS must be positive");
234  }
235 
236  /*--------------------------------*/
237  /* Parallelism related parameters */
238  /*--------------------------------*/
239  // Ensure we can get value for BB_MAX_BLOCK_SIZE without throwing an exception.
240  if (evaluatorControlGlobalParams->toBeChecked())
241  {
242  evaluatorControlGlobalParams->checkAndComply();
243  }
244  auto bbBlockSize = evaluatorControlGlobalParams->getAttributeValue<size_t>("BB_MAX_BLOCK_SIZE");
245  if (0 == bbBlockSize)
246  {
247  throw NOMAD::Exception(__FILE__, __LINE__, "Parameter BB_MAX_BLOCK_SIZE must be positive");
248  }
249  auto sgteBlockSize = evaluatorControlGlobalParams->getAttributeValue<size_t>("SGTE_MAX_BLOCK_SIZE");
250  if (0 == sgteBlockSize)
251  {
252  throw NOMAD::Exception(__FILE__, __LINE__, "Parameter SGTE_MAX_BLOCK_SIZE must be positive");
253  }
254 
255 #ifndef USE_SGTELIB
256  // Look for SgtelibModel parameters that are set but cannot be used
257  if (getAttributeValueProtected<bool>("SGTELIB_MODEL_EVAL", false))
258  {
259  err = "Sgtelib Model sampling cannot be used. Either set parameter ";
260  err += "SGTELIB_MODEL_EVAL to false, or recompile NOMAD using option USE_SGTELIB=1.";
261  throw NOMAD::Exception(__FILE__,__LINE__, err);
262  }
263  if (getAttributeValueProtected<bool>("SGTELIB_SEARCH", false))
264  {
265  err = "Warning: Parameter SGTELIB_SEARCH is set to true, but ";
266  err += "Sgtelib Model sampling cannot be used. To be able to use Sgtelib Model ";
267  err += "search method, NOMAD must be recompiled using option USE_SGTELIB=1.";
268  std::cerr << err << std::endl;
269  }
270  if (getAttributeValueProtected<bool>("QUAD_MODEL_SEARCH", false))
271  {
272  err = "Warning: Parameter QUAD_MODEL_SEARCH is set to true, but ";
273  err += "Quad Model sampling cannot be used. To be able to use Quad Model Search ";
274  err += "search method, NOMAD must be recompiled using option USE_SGTELIB=1.";
275  std::cerr << err << std::endl;
276  }
277 #endif
278 
279  // PSD-Mads and SSD-Mads parameters
280  bool useAlgoPSDMads = getAttributeValueProtected<bool>("PSD_MADS_OPTIMIZATION", false);
281 
282 #ifndef _OPENMP
283  if (useAlgoPSDMads)
284  {
285  err = "Error: PSD_MADS_OPTIMIZATION can only be used when OpenMP is available. If that is not the case, use SSD_MADS_OPTIMIZATION.";
286  throw NOMAD::Exception(__FILE__,__LINE__, err);
287  }
288 #endif // _OPENMP
289 
290  bool useAlgoSSDMads = getAttributeValueProtected<bool>("SSD_MADS_OPTIMIZATION", false);
291  if (useAlgoPSDMads || useAlgoSSDMads)
292  {
293  std::string nbVarParamName = (useAlgoPSDMads ? "PSD_MADS_NB_VAR_IN_SUBPROBLEM" : "SSD_MADS_NB_VAR_IN_SUBPROBLEM");
294  const size_t nbVariablesInSubproblem = getAttributeValueProtected<size_t>(nbVarParamName, false);
295  if (0 == nbVariablesInSubproblem || nbVariablesInSubproblem > n)
296  {
297  err = "Parameter " + nbVarParamName + " must be between 1 and " + NOMAD::itos(n);
298  err += ". Value provided: " + NOMAD::itos(nbVariablesInSubproblem);
299  throw NOMAD::InvalidParameter(__FILE__,__LINE__, err);
300  }
301 
302  size_t nbMadsSubproblem = getAttributeValueProtected<size_t>((useAlgoPSDMads ? "PSD_MADS_NB_SUBPROBLEM" : "SSD_MADS_NB_SUBPROBLEM"), false);
303  // Distribute all the variables between subproblems of reduced dimension.
304  bool nbMadsSubproblemSetByUser = true;
305  if (nbMadsSubproblem == INF_SIZE_T)
306  {
307  nbMadsSubproblem = std::round(n/nbVariablesInSubproblem)+1; // Add an additional mads for the pollster
308  nbMadsSubproblemSetByUser = false;
309  }
310  if (useAlgoPSDMads)
311  {
312  // Cannot have more subproblems than the number of threads
313  size_t nbThreads = (size_t)getAttributeValueProtected<int>("NB_THREADS_OPENMP", false);
314  if (nbMadsSubproblem > nbThreads)
315  {
316  nbMadsSubproblem = nbThreads;
317  if (nbMadsSubproblemSetByUser)
318  {
319  // Warn the user
320  std::cerr << "Warning: parameter PSD_MADS_NB_SUBPROBLEM reset to number of available threads (" << nbThreads << ")" << std::endl;
321  }
322  }
323  }
324  setAttributeValue((useAlgoPSDMads ? "PSD_MADS_NB_SUBPROBLEM" : "SSD_MADS_NB_SUBPROBLEM"), nbMadsSubproblem);
325 
326  // Check parameter for coverage
327  if (useAlgoPSDMads)
328  {
329  std::string covParamName = "PSD_MADS_SUBPROBLEM_PCT_COVERAGE";
330  auto coverage = getAttributeValueProtected<NOMAD::Double>(covParamName, false);
331  if (coverage < 0.0 || coverage > 100.0)
332  {
333  err = "Parameter " + covParamName + " must be between 0.0 and 100.0";
334  throw NOMAD::InvalidParameter(__FILE__,__LINE__, err);
335  }
336  }
337  }
338 
339  // Algorithm parameters: use an algorithm other than MADS.
340  // They are mutually-exclusive.
341  bool useAlgoLH = (getAttributeValueProtected<size_t>("LH_EVAL", false) > 0);
342  bool useAlgoNM = getAttributeValueProtected<bool>("NM_OPTIMIZATION", false);
343  bool useAlgoQuadOpt = getAttributeValueProtected<bool>("QUAD_MODEL_OPTIMIZATION", false);
344  bool useAlgoSgtelibModel = getAttributeValueProtected<bool>("SGTELIB_MODEL_EVAL", false);
345  int totalAlgoSet = (int)useAlgoLH + (int)useAlgoNM + (int)useAlgoQuadOpt
346  + (int)useAlgoPSDMads + (int)useAlgoSgtelibModel + (int)useAlgoSSDMads;
347 
348  if (totalAlgoSet >= 2)
349  {
350  err = "Multiple parameters for algorithms are set. ";
351  err += "These parameters are mutually exclusive:";
352  if (useAlgoLH)
353  {
354  err += " LH_EVAL";
355  }
356  if (useAlgoNM)
357  {
358  err += " NM_OPTIMIZATION";
359  }
360  if (useAlgoPSDMads)
361  {
362  err += " PSD_MADS_OPTIMIZATION";
363  }
364  if (useAlgoQuadOpt)
365  {
366  err += " QUAD_MODEL_OPTIMIZATION";
367  }
368  if (useAlgoSgtelibModel)
369  {
370  err += " SGTELIB_MODEL_EVAL";
371  }
372  if (useAlgoSSDMads)
373  {
374  err += " SSD_MADS_OPTIMIZATION";
375  }
376  err += ". Please review parameters settings and choose only one algorithm.";
377  throw NOMAD::Exception(__FILE__,__LINE__, err);
378  }
379 
380  /*------------------------*/
381  /* Hot restart parameters */
382  /* Update file names */
383  /*------------------------*/
384  std::string hotRestartFileName = getAttributeValueProtected<std::string>("HOT_RESTART_FILE",false);
385  if (!hotRestartFileName.empty())
386  {
387  NOMAD::completeFileName(hotRestartFileName, problemDir);
388  setAttributeValue("HOT_RESTART_FILE", hotRestartFileName);
389  }
390 
391 
392  auto hMax = getAttributeValueProtected<NOMAD::Double>("H_MAX_0", false);
393  if (hMax <= 0)
394  {
395  throw NOMAD::Exception(__FILE__,__LINE__, "Parameters check: H_MAX_0 must be positive");
396  }
397 
398  _warningUnknownParamShown = true;
399 
400  _toBeChecked = false;
401 }
402 // End checkAndComply()
403 
404 
405 void NOMAD::RunParameters::setStaticParameters()
406 {
407  // Sub-method of checkAndComply() to set static variables of some classes.
408  NOMAD::RNG::setSeed ( getAttributeValueProtected<int>("SEED",false) );
409  NOMAD::Double::setEpsilon ( getAttributeValueProtected<NOMAD::Double>("EPSILON",false).todouble() );
410  NOMAD::Double::setUndefStr ( getAttributeValueProtected<std::string>("UNDEF_STR",false) );
411  NOMAD::Double::setInfStr ( getAttributeValueProtected<std::string>("INF_STR",false) );
412 
413  // Reset parameter values from these static values, to ensure coherence.
414  // This is bad because we have twice the same value for some parameters.
415  setAttributeValue ( "SEED", NOMAD::RNG::getSeed() );
416  setAttributeValue ( "EPSILON", NOMAD::Double(NOMAD::Double::getEpsilon()) );
417  setAttributeValue ( "UNDEF_STR", NOMAD::Double::getUndefStr() );
418  setAttributeValue ( "INF_STR", NOMAD::Double::getInfStr() );
419 }
420 
NOMAD_VERSION_NUMBER
#define NOMAD_VERSION_NUMBER
Define version number.
Definition: nomad_version.hpp:53
_definition
_definition
Definition: cacheAttributesDefinition.hpp:7
DEFAULT_UNDEF_STR
const std::string DEFAULT_UNDEF_STR
Default undefined value string used by Double.
Definition: defines.hpp:120
toupper
void toupper(std::string &s)
Put a string into upper cases.
Definition: utils.cpp:84
DEFAULT_INF_STR
const std::string DEFAULT_INF_STR
Default infinity string used by Double.
Definition: defines.hpp:114
DEFAULT_EPSILON
const double DEFAULT_EPSILON
Default epsilon used by Double.
Definition: defines.hpp:108
completeFileName
void completeFileName(std::string &filename, const std::string &problemDir, bool addSeed=false, int seed=0)
Definition: fileutils.cpp:298
INF_SIZE_T
const size_t INF_SIZE_T
The infinity for size_t.
Definition: defines.hpp:129
DIR_SEP
const char DIR_SEP
Directory separator.
Definition: defines.hpp:98
itos
std::string itos(const int i)
Transform an integer into a string.
Definition: utils.cpp:63