1 /* _______________________________________________________________________
2
3 DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
4 Copyright 2014-2020 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Dakota directory.
7 _______________________________________________________________________ */
8
9 //- Class: NomadOptimizer
10 //- Description: Implementation of the NOMADOptimizer class, including
11 // derived subclasses used by the NOMAD Library.
12 //- Owner: Patty Hough
13 //- Checked by:
14 //- Version: $Id$
15
16 #include <ProblemDescDB.hpp>
17
18 #include <algorithm>
19 #include <sstream>
20
21 #include <nomad.hpp>
22 #include "NomadOptimizer.hpp"
23
24
25 using namespace std;
26
27 namespace Dakota {
28
29 // Main Class: NomadOptimizer
30
NomadOptimizer(ProblemDescDB & problem_db,Model & model)31 NomadOptimizer::NomadOptimizer(ProblemDescDB& problem_db, Model& model):
32 Optimizer(problem_db, model, std::shared_ptr<TraitsBase>(new NomadTraits()))
33 {
34 // Set initial mesh size
35 initMesh = probDescDB.get_real("method.mesh_adaptive_search.initial_delta");
36
37 // Set minimum mesh size
38 minMesh = probDescDB.get_real("method.mesh_adaptive_search.variable_tolerance");
39
40 // Set Rnd Seed
41 randomSeed = probDescDB.get_int("method.random_seed");
42
43 // Set Max # of BB Evaluations
44 maxBlackBoxEvals = probDescDB.get_int("method.max_function_evaluations");
45
46 // STATS_FILE -- File Output
47 outputFormat =
48 probDescDB.get_string("method.mesh_adaptive_search.display_format");
49
50 // DISPLAY_ALL_EVAL -- If set, shows all evaluation points during
51 // Outputs, instead of just improvements
52 displayAll =
53 probDescDB.get_bool("method.mesh_adaptive_search.display_all_evaluations");
54
55 // Expected precision of the function. Any differences less than
56 // this are noise.
57 epsilon = probDescDB.get_real("method.function_precision");
58
59 // Maximum number of iterations.
60 maxIterations = probDescDB.get_int("method.max_iterations");
61
62 // VNS = Variable Neighbor Search, it is used to escape local minima
63 // if VNS >0.0, the NOMAD Parameter must be set with a Real number.
64 vns =
65 probDescDB.get_real("method.mesh_adaptive_search.variable_neighborhood_search");
66
67 // Number of dimensions up to which should be perturbed (according
68 // to adjacency matrices) to determine categorical neighbors.
69 numHops = probDescDB.get_int("method.mesh_adaptive_search.neighbor_order");
70
71 // Set the History File, which will contain all the evaluations history
72 historyFile =
73 probDescDB.get_string("method.mesh_adaptive_search.history_file");
74
75 // Identify which integer set variables are categorical.
76 discreteSetIntCat =
77 probDescDB.get_ba("variables.discrete_design_set_int.categorical");
78
79 // Identify which real set variables are categorical.
80 discreteSetRealCat =
81 probDescDB.get_ba("variables.discrete_design_set_real.categorical");
82
83 // Adjacency matrices for integer categorical variables.
84 discreteSetIntAdj =
85 probDescDB.get_rma("variables.discrete_design_set_int.adjacency_matrix");
86
87 // Adjacency matrices for real categorical variables.
88 discreteSetRealAdj =
89 probDescDB.get_rma("variables.discrete_design_set_real.adjacency_matrix");
90
91 // Adjacency matrices for string variables.
92 discreteSetStrAdj =
93 probDescDB.get_rma("variables.discrete_design_set_str.adjacency_matrix");
94
95 // Definition for how to use surrogate model.
96 useSurrogate = probDescDB.get_string("method.mesh_adaptive_search.use_surrogate");
97 }
98
NomadOptimizer(Model & model)99 NomadOptimizer::NomadOptimizer(Model& model):
100 Optimizer(MESH_ADAPTIVE_SEARCH, model, std::shared_ptr<TraitsBase>(new NomadTraits()))
101 {
102 }
103
104 // Driver, this class runs the Mads algorithm. This is the stuff that
105 // normally went into the main of the sample programs
106
core_run()107 void NomadOptimizer::core_run()
108 {
109 // Set up Output (NOMAD::Display)
110 NOMAD::Display out (std::cout);
111 out.precision (NOMAD::DISPLAY_PRECISION_STD);
112
113 // This is only used when using NOMAD with MPI
114 NOMAD::begin ( 0 , NULL );
115
116 // Create parameters
117 NOMAD::Parameters p (out);
118
119 // Verify that user has requested surrogate model construction
120 // when use_surrogate is defined.
121 if ((iteratedModel.model_type() != "surrogate") &&
122 ((useSurrogate.compare("inform_search") == 0) || (useSurrogate.compare("optimize") == 0))) {
123 Cerr << "Error: Specified use_surrogate without requesting surrogate model "
124 << "construction." << std::endl;
125 abort_handler(-1);
126 }
127
128 // Overwriting dummy default needed for error catching
129 if (useSurrogate.compare("none") == 0){
130 useSurrogate = "optimize";
131 }
132
133 // If model is a surrogate, build it. Subsequently, tell NOMAD to make
134 // use of it if use_surrogate is set to inform_search
135 if (iteratedModel.model_type() == "surrogate") {
136 iteratedModel.build_approximation();
137
138 if (useSurrogate.compare("inform_search") == 0){
139 p.set_HAS_SGTE(true);
140 }
141 }
142
143 // Map dakota output levels to NOMAD's four different levels
144 // of display. Default is set to normal NOMAD output level
145 // (see NORMAL_DISPLAY setting in NOMAD manual)
146 switch (outputLevel)
147 {
148 case SILENT_OUTPUT: p.set_DISPLAY_DEGREE ( 0 ); break;
149 case QUIET_OUTPUT: p.set_DISPLAY_DEGREE ( 1 ); break;
150 case NORMAL_OUTPUT: p.set_DISPLAY_DEGREE ( 2 ); break;
151 case DEBUG_OUTPUT: p.set_DISPLAY_DEGREE ( 3 ); break;
152 case VERBOSE_OUTPUT: p.set_DISPLAY_DEGREE ( 3 ); break;
153 default: p.set_DISPLAY_DEGREE ( 1 );
154 }
155
156 // Load Input Parameters
157 numTotalVars = numContinuousVars + numDiscreteIntVars
158 + numDiscreteRealVars + numDiscreteStringVars;
159 p.set_DIMENSION(this->numTotalVars);
160 this->load_parameters(iteratedModel, p);
161
162 // Set up response types
163 vector<NOMAD::bb_output_type>
164 bb_responses(1+numNomadNonlinearIneqConstraints+numNonlinearEqConstraints);
165 bb_responses[0] = NOMAD::OBJ;
166 for(int i=0; i<this->numNomadNonlinearIneqConstraints;i++)
167 bb_responses[i+1] = NOMAD::PB;
168 for(int i=0; i<this->numNonlinearEqConstraints;i++)
169 bb_responses[i+1+this->numNomadNonlinearIneqConstraints] = NOMAD::EB;
170
171 // Set output and inputs.
172 p.set_BB_OUTPUT_TYPE (bb_responses);
173 p.set_X0 (this->initialPoint);
174 p.set_LOWER_BOUND(this->lowerBound);
175 p.set_UPPER_BOUND(this->upperBound);
176
177 // Set Max # of BB Evaluations
178 p.set_MAX_BB_EVAL (maxBlackBoxEvals);
179
180 // DISPLAY_STATS -- Standard Output
181 // STATS_FILE -- File Output
182 // These two format the information displayed using keywords to indicate
183 // how the information is displayed in their respective output media.
184 // Keywords:
185 // BBE BB Evaluation
186 // BBO BB Output
187 // EVAL Evaluations
188 // MESH_INDEX Mesh Index
189 // MESH_SIZE Mesh Size Parameter
190 // OBJ Objective Function Value
191 // POLL_SIZE Poll Size pParameter
192 // SGTE # of Surrogate Evals
193 // SIM_BBE Simulated BB evaluations (when using cache)
194 // SOL Solution, format is iSOLj, i and j are optional strings
195 // STAT_AVG AVG statistic, defined in BB_OUTPUT_TYPE
196 // STAT_SUM SUM statistic, defined in BB_OUTPUT_TYPE
197 // TIME Wall clock time
198 // VARi Value of Variable i (0-based)
199
200 p.set_DISPLAY_STATS(outputFormat);
201 p.set_DISPLAY_ALL_EVAL(displayAll);
202
203 // Set method control parameters.
204 p.set_INITIAL_MESH_SIZE(initMesh);
205 p.set_MIN_MESH_SIZE(minMesh);
206 p.set_EPSILON(epsilon);
207 p.set_MAX_ITERATIONS(maxIterations);
208 p.set_SEED(randomSeed);
209
210 // VNS = Variable Neighbor Search, it is used to escape local minima
211 // if VNS >0.0, the NOMAD Parameter must be set with a Real number.
212 if(vns>0.0) {
213 if (vns > 1.0) {
214 Cerr << "\nWarning: variable_neighborhood_search outside acceptable "
215 << "range of (0,1].\nUsing default value of 0.75.\n\n";
216 vns = 0.75;
217 }
218 p.set_VNS_SEARCH(vns);
219 }
220
221 // Set the History File, which will contain all the evaluations history
222 p.set_HISTORY_FILE( historyFile );
223
224 // Allow as many simultaneous evaluations as NOMAD wishes and let Dakota schedule
225 if (iteratedModel.asynch_flag())
226 p.set_BB_MAX_BLOCK_SIZE(INT_MAX);
227
228 // Check the parameters -- Required by NOMAD for execution
229 p.check();
230
231 // Create Evaluator object and communicate constraint mapping and surrogate usage.
232 NomadOptimizer::Evaluator ev (p, iteratedModel);
233
234 //PDH: May be able to get rid of setting the constraint map once we
235 //have something in place that everyone can access.
236
237 ev.set_constraint_map(numNomadNonlinearIneqConstraints, numNonlinearEqConstraints, constraintMapIndices, constraintMapMultipliers, constraintMapOffsets);
238 ev.set_surrogate_usage(useSurrogate);
239
240 // Construct Extended Poll object to form categorical neighbors.
241 NomadOptimizer::Extended_Poll ep (p,categoricalAdjacency,numHops);
242
243 // Create Algorithm ( NOMAD::Mads mads ( params, &evaluator ) )
244 NOMAD::Mads mads (p,&ev,&ep,NULL,NULL);
245 // Use Dakota's recast model for multi-objective for now. Enable
246 // NOMAD's native support for multi-objective later.
247 NOMAD::Mads::set_flag_check_bimads(false);
248
249 // Run!
250 mads.run();
251
252 // Retrieve best iterate and convert from NOMAD to DAKOTA
253 // vector.
254
255 const NOMAD::Eval_Point * bestX;
256 bestX = mads.get_best_feasible();
257 if (!bestX) {
258 Cout << "WARNING: No feasible solution was found. "
259 << "Best point shown is best infeasible point.\n" << std::endl;
260 bestX = mads.get_best_infeasible();
261 }
262
263 //PDH: Set final solution.
264 // Includes mappings of discrete variables.
265 // Similar to APPSPACK but need to look into NOMAD's Point more.
266 // Think the code from here to the end of the method
267 // can be greatly simplified with data adapters built
268 // on top of data tranfers.
269 // Would like to just do something like
270 // setBestVariables(...)
271 // setBestResponses(...)
272
273 RealVector contVars(numContinuousVars);
274 IntVector discIntVars(numDiscreteIntVars);
275 RealVector discRealVars(numDiscreteRealVars);
276
277 const BitArray& int_set_bits = iteratedModel.discrete_int_sets();
278 const IntSetArray& set_int_vars = iteratedModel.discrete_set_int_values();
279 const RealSetArray& set_real_vars = iteratedModel.discrete_set_real_values();
280 const StringSetArray& set_string_vars = iteratedModel.discrete_set_string_values();
281
282 size_t j, dsi_cntr;
283
284 for(j=0; j<numContinuousVars; j++)
285 contVars[j] = (*bestX)[j].value();
286 bestVariablesArray.front().continuous_variables(contVars);
287
288 for(j=0, dsi_cntr=0; j<numDiscreteIntVars; j++)
289 {
290 // This active discrete int var is a set type
291 // Map from index back to value.
292 if (int_set_bits[j]) {
293 discIntVars[j] =
294 set_index_to_value((*bestX)[j+numContinuousVars].value(), set_int_vars[dsi_cntr]);
295 ++dsi_cntr;
296 }
297 // This active discrete int var is a range type
298 else
299 discIntVars[j] = (*bestX)[j+numContinuousVars].value();
300 }
301
302 // For real sets and strings, map from index back to value.
303 bestVariablesArray.front().discrete_int_variables(discIntVars);
304 for (j=0; j<numDiscreteRealVars; j++)
305 discRealVars =
306 set_index_to_value((*bestX)[j+numContinuousVars+numDiscreteIntVars].value(), set_real_vars[j]);
307 bestVariablesArray.front().discrete_real_variables(discRealVars);
308
309 for (j=0; j<numDiscreteStringVars; j++)
310 bestVariablesArray.front().discrete_string_variable(set_index_to_value((*bestX)[j+numContinuousVars+numDiscreteIntVars+numDiscreteRealVars].value(), set_string_vars[j]), j);
311
312 //PDH: Similar to APPSPACK but need to look into NOMAD's Point more.
313 // Has to respect Dakota's ordering of inequality and equality constraints.
314 // Has to map format of constraints.
315 // Then populate bestResponseArray.
316
317 // Retrieve the best responses and convert from NOMAD to
318 // DAKOTA vector.h
319 if (!localObjectiveRecast) {
320 // else local_objective_recast_retrieve() is used in Optimizer::post_run()
321 const NOMAD::Point & bestFs = bestX->get_bb_outputs();
322 RealVector best_fns(numFunctions);
323 std::vector<double> bestIneqs(constraintMapIndices.size()-numNonlinearEqConstraints);
324 std::vector<double> bestEqs(numNonlinearEqConstraints);
325 const BoolDeque& max_sense = iteratedModel.primary_response_fn_sense();
326
327 // Map objective appropriately based on minimizing or maximizing.
328 best_fns[0] = (!max_sense.empty() && max_sense[0]) ?
329 -bestFs[0].value() : bestFs[0].value();
330
331 // Map linear and nonlinear constraints according to constraint map.
332 if (numNonlinearIneqConstraints > 0) {
333 for (int i=0; i<numNomadNonlinearIneqConstraints; i++) {
334 best_fns[constraintMapIndices[i]+1] = (bestFs[i+1].value() -
335 constraintMapOffsets[i]) / constraintMapMultipliers[i];
336 }
337 }
338 if (numNonlinearEqConstraints > 0) {
339 for (int i=0; i<numNonlinearEqConstraints; i++)
340 best_fns[constraintMapIndices[i+numNomadNonlinearIneqConstraints]+1] =
341 (bestFs[i+numNomadNonlinearIneqConstraints+1].value() -
342 constraintMapOffsets[i+numNomadNonlinearIneqConstraints]) /
343 constraintMapMultipliers[i+numNomadNonlinearIneqConstraints];
344 }
345 bestResponseArray.front().function_values(best_fns);
346 }
347
348 // Stop NOMAD output. Required.
349 NOMAD::Slave::stop_slaves ( out );
350 NOMAD::end();
351 }
352
353 // Sub Class: EvaluatorCreator, this class creates an Evaluator
354 // using a Dakota Model
355
356 // Sub Class: Evaluator, this class bridges NOMAD-style inputs with
357 // DAKOTA style communication w/Black Box program.
358
Evaluator(const NOMAD::Parameters & p,Model & model)359 NomadOptimizer::Evaluator::Evaluator(const NOMAD::Parameters &p, Model& model)
360 : NOMAD::Evaluator (p),_model(model)
361 {
362 // Here we should take the parameters and get the problem information
363 // Like # of variables and types, # and types of constrs
364 /*
365 p.get_bb_nb_outputs(); // Get # of BB Outputs
366 p.get_bb_input_type(); // Returns a vector<NOMAD::bb_input_type>
367 p.get_bb_output_type(); // same, but with output_type
368 p.get_index_obj(); // get indices of obj fn, it's a list
369 */
370 // We can also access the parameters through _p
371 vector<NOMAD::bb_input_type> input_types;
372 input_types = _p.get_bb_input_type();
373
374 n_cont = 0;
375 n_disc_int = 0;
376 n_disc_real = 0;
377
378 for(int i=0;i<input_types.size();i++)
379 {
380 if(input_types[i]==NOMAD::CONTINUOUS)
381 {
382 n_cont++;
383 }
384 else
385 {
386 n_disc_int++;
387 }
388 }
389 }
390
~Evaluator(void)391 NomadOptimizer::Evaluator::~Evaluator(void){};
392
eval_x(std::list<NOMAD::Eval_Point * > & x,const NOMAD::Double & h_max,std::list<bool> & count_eval) const393 bool NomadOptimizer::Evaluator::eval_x ( std::list<NOMAD::Eval_Point *>& x,
394 const NOMAD::Double& h_max,
395 std::list<bool>& count_eval ) const
396 {
397 for (auto xi : x) {
398 set_variables(*xi);
399 bool allow_asynch = true;
400 eval_model(allow_asynch, *xi); // calls evaluate() or evaluate_nowait()
401 // collect and store if blocking
402 if (!_model.asynch_flag())
403 get_responses(_model.current_response().function_values(), *xi);
404 }
405
406 // block, collect, and store asynch responses
407 if (_model.asynch_flag()) {
408 const IntResponseMap& resp_map = _model.synchronize();
409 if (x.size() != resp_map.size() || x.size() != count_eval.size()) {
410 Cerr << "\nError: Incompatible container sizes in NOMAD batch eval_x()\n";
411 abort_handler(METHOD_ERROR);
412 }
413 IntRespMCIter evalid_resp = resp_map.begin();
414 auto xi = x.begin();
415 auto cnt_eval = count_eval.begin();
416 for ( ; xi != x.end(); ++evalid_resp, ++xi, ++cnt_eval) {
417 get_responses(evalid_resp->second.function_values(), **xi);
418 *cnt_eval = true;
419 }
420 }
421
422 return true;
423 }
424
425
eval_x(NOMAD::Eval_Point & x,const NOMAD::Double & h_max,bool & count_eval) const426 bool NomadOptimizer::Evaluator::eval_x ( NOMAD::Eval_Point &x,
427 const NOMAD::Double &h_max,
428 bool &count_eval) const
429 {
430 set_variables(x);
431 // Compute the Response using Dakota Interface
432 // if single point eval is called, always want to block
433 bool allow_asynch = false;
434 eval_model(allow_asynch, x);
435 get_responses(_model.current_response().function_values(), x);
436 count_eval = true;
437
438 return true;
439 }
440
441
set_variables(const NOMAD::Eval_Point & x) const442 void NomadOptimizer::Evaluator::set_variables(const NOMAD::Eval_Point &x) const
443 {
444 //PDH: Set current iterate values for evaluation.
445 // Similar to APPSPACK but need to look into NOMAD Point more.
446 // Think this code can be greatly simplified with data adapters
447 // built on top of data transfers. Would like to just do
448 // something like
449 // setEvalVariables(...)
450
451 int n_cont_vars = _model.cv();
452 int n_disc_int_vars = _model.div();
453 int n_disc_real_vars = _model.drv();
454 int n_disc_string_vars = _model.dsv();
455
456 // Prepare Vectors for Dakota model.
457 RealVector contVars(n_cont_vars);
458 IntVector discIntVars(n_disc_int_vars);
459 RealVector discRealVars(n_disc_real_vars);
460
461 const BitArray& int_set_bits = _model.discrete_int_sets();
462 const IntSetArray& set_int_vars = _model.discrete_set_int_values();
463 const RealSetArray& set_real_vars = _model.discrete_set_real_values();
464 const StringSetArray& set_string_vars = _model.discrete_set_string_values();
465
466 size_t i, dsi_cntr;
467
468 // Parameters contain Problem Information (variable: _p)
469
470 // Here we are going to fetch the input information in x in a format that can be read by DAKOTA
471 // Transform values in x into something DAKOTA can read...
472
473 // In the NOMAD parameters model:
474 // 1. Continuous Variables = NOMAD::CONTINUOUS
475 // 2. Discrete Integer Variables = NOMAD::INTEGER and NOMAD::BINARY
476 // 3. Discrete Real Variables = NOMAD::CATEGORICAL (??)
477
478 // x.get_n() = # of BB Inputs
479 // x.get_m() = # of BB Outputs
480 for(i=0; i<n_cont_vars; i++)
481 {
482 _model.continuous_variable(x[i].value(), i);
483 }
484
485 for(i=0, dsi_cntr=0; i<n_disc_int_vars; i++)
486 {
487 // This active discrete int var is a set type
488 // Map from index to value.
489 if (int_set_bits[i]) {
490 int dakota_value = set_index_to_value(x[i+n_cont_vars].value(),
491 set_int_vars[dsi_cntr]);
492 _model.discrete_int_variable(dakota_value, i);
493 ++dsi_cntr;
494 }
495 // This active discrete int var is a range type
496 else {
497 _model.discrete_int_variable(x[i+n_cont_vars].value(), i);
498 }
499 }
500
501 // For real set and strings, map from index to value.
502 for (i=0; i<n_disc_real_vars; i++) {
503 Real dakota_value = set_index_to_value(x[i+n_cont_vars+n_disc_int_vars].value(), set_real_vars[i]);
504 _model.discrete_real_variable(dakota_value, i);
505 }
506
507 for (i=0; i<n_disc_string_vars; i++) {
508 _model.discrete_string_variable(set_index_to_value(x[i+n_cont_vars+n_disc_int_vars+n_disc_real_vars].value(), set_string_vars[i]), i);
509 }
510
511 }
512
513
eval_model(bool allow_asynch,const NOMAD::Eval_Point & x) const514 void NomadOptimizer::Evaluator::eval_model(bool allow_asynch, const NOMAD::Eval_Point& x) const
515 {
516 // Compute the Response using Dakota Interface
517 if ((_model.model_type() == "surrogate") && (x.get_eval_type() != NOMAD::SGTE) &&
518 (useSgte.compare("inform_search") == 0)) {
519 short orig_resp_mode = _model.surrogate_response_mode();
520 _model.surrogate_response_mode(BYPASS_SURROGATE);
521 // hierarchical surrogates can be asynchronous
522 if (allow_asynch && _model.asynch_flag())
523 _model.evaluate_nowait();
524 else
525 _model.evaluate();
526 _model.surrogate_response_mode(orig_resp_mode);
527 }
528 else {
529 if (allow_asynch && _model.asynch_flag())
530 _model.evaluate_nowait();
531 else
532 _model.evaluate();
533 }
534 }
535
536
get_responses(const RealVector & ftn_vals,NOMAD::Eval_Point & x) const537 void NomadOptimizer::Evaluator::get_responses(const RealVector& ftn_vals,
538 NOMAD::Eval_Point &x) const
539 {
540 //PDH: NOMAD response values set one at a time.
541 // Has to respect ordering of inequality and equality constraints.
542 // Has to map format of constraints.
543
544 // Map objective according to minimizing or maximizing.
545 const BoolDeque& sense = _model.primary_response_fn_sense();
546 bool max_flag = (!sense.empty() && sense[0]);
547 Real obj_fcn = (max_flag) ? -ftn_vals[0] : ftn_vals[0];
548 x.set_bb_output ( 0 , NOMAD::Double(obj_fcn) );
549
550 // Map constraints according to constraint map.
551 int numTotalConstr = numNomadNonlinearIneqConstr+numNomadNonlinearEqConstr;
552 for(int i=1;i<=numTotalConstr;i++)
553 {
554 Real constr_value = constrMapOffsets[i-1] +
555 constrMapMultipliers[i-1]*ftn_vals[constrMapIndices[i-1]+1];
556 x.set_bb_output ( i , NOMAD::Double(constr_value) );
557 }
558
559 }
560
561
562 // Called by NOMAD to provide a list of categorical neighbors.
563 void NomadOptimizer::Extended_Poll::
construct_extended_points(const NOMAD::Eval_Point & nomad_point)564 construct_extended_points(const NOMAD::Eval_Point &nomad_point)
565 {
566 NOMAD::Point current_point = nomad_point;
567 NOMAD::Signature *nomad_signature = nomad_point.get_signature();
568
569 // Call this recursive function for multi-dimensional neighbors.
570 construct_multihop_neighbors(current_point, *nomad_signature,
571 adjacency_matrix.begin(), -1, nHops);
572 }
573
574 // Recursive helper function to determine multi-dimensional neighbors.
575 void NomadOptimizer::Extended_Poll::
construct_multihop_neighbors(NOMAD::Point & base_point,NOMAD::Signature point_signature,RealMatrixArray::iterator rma_iter,size_t last_cat_index,int num_hops)576 construct_multihop_neighbors(NOMAD::Point &base_point,
577 NOMAD::Signature point_signature, RealMatrixArray::iterator
578 rma_iter, size_t last_cat_index, int num_hops)
579 {
580 size_t i, j, k;
581
582 RealMatrixArray::iterator pass_through_iter(rma_iter), tmp_iter;
583 const std::vector<NOMAD::bb_input_type>& input_types = point_signature.get_input_types();
584
585 // Iterate through point from last categorical variable.
586 for (i=last_cat_index+1, tmp_iter=rma_iter; i<point_signature.get_n(); i++)
587 {
588 if (input_types[i] == NOMAD::CATEGORICAL)
589 {
590 NOMAD::Point neighbor = base_point;
591 j = (size_t) base_point[i].value();
592 pass_through_iter++;
593 for (k=0; k<(*tmp_iter).numCols(); k++)
594 {
595 if ((*tmp_iter)[j][k]>0 && j!=k)
596 {
597 neighbor[i] = k;
598 add_extended_poll_point(neighbor, point_signature);
599 if (num_hops > 1)
600 {
601 construct_multihop_neighbors(neighbor, point_signature, pass_through_iter, i, num_hops-1);
602 }
603 }
604 }
605 tmp_iter++;
606 }
607 }
608 }
609
load_parameters(Model & model,NOMAD::Parameters & p)610 void NomadOptimizer::load_parameters(Model &model, NOMAD::Parameters &p)
611 {
612 //PDH: This initializes everything for NOMAD.
613 // Similar to APPSPACK but need to look into NOMAD Point more.
614 // Don't want any references to iteratedModel.
615 // Need to handle discrete variable mapping.
616 // Need to respect equality, inequality constraint ordering.
617 // Need to handle constraint mapping.
618
619 // numTotalVars = numContinuousVars +
620 // numDiscreteIntVars + numDiscreteRealVars;
621
622 // Define Input Types and Bounds
623
624 NOMAD::Point _initial_point (numTotalVars);
625 NOMAD::Point _upper_bound (numTotalVars);
626 NOMAD::Point _lower_bound (numTotalVars);
627
628 const RealVector& initial_point_cont = model.continuous_variables();
629 const RealVector& lower_bound_cont = model.continuous_lower_bounds();
630 const RealVector& upper_bound_cont = model.continuous_upper_bounds();
631
632 const IntVector& initial_point_int = model.discrete_int_variables();
633 const IntVector& lower_bound_int = model.discrete_int_lower_bounds();
634 const IntVector& upper_bound_int = model.discrete_int_upper_bounds();
635
636 const RealVector& initial_point_real = model.discrete_real_variables();
637 const RealVector& lower_bound_real = model.discrete_real_lower_bounds();
638 const RealVector& upper_bound_real = model.discrete_real_upper_bounds();
639
640 const StringMultiArrayConstView initial_point_string =
641 model.discrete_string_variables();
642
643 const BitArray& int_set_bits = iteratedModel.discrete_int_sets();
644 const IntSetArray& initial_point_set_int =
645 iteratedModel.discrete_set_int_values();
646 const RealSetArray& initial_point_set_real =
647 iteratedModel.discrete_set_real_values();
648 const StringSetArray& initial_point_set_string =
649 iteratedModel.discrete_set_string_values();
650
651 RealMatrix tmp_categorical_adjacency;
652
653 size_t i, j, k, index, dsi_cntr;
654
655 for(i=0;i<numContinuousVars;i++)
656 {
657 _initial_point[i] = initial_point_cont[i];
658 if (lower_bound_cont[i] > -bigRealBoundSize)
659 _lower_bound[i] = lower_bound_cont[i];
660 else {
661 Cerr << "\nError: NomadOptimizer::load_parameters\n"
662 << "mesh_adaptive_search requires lower bounds "
663 << "for all continuous variables" << std::endl;
664 abort_handler(-1);
665 }
666 if (upper_bound_cont[i] < bigRealBoundSize)
667 _upper_bound[i] = upper_bound_cont[i];
668 else {
669 Cerr << "\nError: NomadOptimizer::load_parameters\n"
670 << "mesh_adaptive_search requires upper bounds "
671 << "for all continuous variables" << std::endl;
672 abort_handler(-1);
673 }
674 p.set_BB_INPUT_TYPE(i,NOMAD::CONTINUOUS);
675 }
676 for(i=0, dsi_cntr=0; i<numDiscreteIntVars; i++)
677 {
678 if (int_set_bits[i]) {
679 index = set_value_to_index(initial_point_int[i],
680 initial_point_set_int[dsi_cntr]);
681 if (index == _NPOS) {
682 Cerr << "\nError: failure in discrete integer set lookup within "
683 << "NomadOptimizer::load_parameters(Model &model)" << std::endl;
684 abort_handler(-1);
685 }
686 else {
687 _initial_point[i+numContinuousVars] = (int)index;
688 }
689 if (!discreteSetIntCat.empty() && discreteSetIntCat[dsi_cntr] == 1)
690 {
691 p.set_BB_INPUT_TYPE(i+numContinuousVars,NOMAD::CATEGORICAL);
692 if (!discreteSetIntAdj.empty())
693 categoricalAdjacency.push_back(discreteSetIntAdj[dsi_cntr]);
694 else
695 {
696 tmp_categorical_adjacency.reshape(initial_point_set_int[dsi_cntr].size(),
697 initial_point_set_int[dsi_cntr].size());
698 for (j=0; j<initial_point_set_int[dsi_cntr].size(); j++)
699 {
700 for (k=0; k<initial_point_set_int[dsi_cntr].size(); k++)
701 {
702 if (k==j-1 || k==j || k==j+1)
703 tmp_categorical_adjacency[j][k] = 1;
704 else
705 tmp_categorical_adjacency[j][k] = 0;
706 }
707 }
708 categoricalAdjacency.push_back(tmp_categorical_adjacency);
709 }
710 }
711 else
712 {
713 p.set_BB_INPUT_TYPE(i+numContinuousVars,NOMAD::INTEGER);
714 _lower_bound[i+numContinuousVars] = 0;
715 _upper_bound[i+numContinuousVars] =
716 initial_point_set_int[dsi_cntr].size() - 1;
717 }
718 ++dsi_cntr;
719 }
720 else
721 {
722 _initial_point[i+numContinuousVars] = initial_point_int[i];
723 if (lower_bound_int[i] > -bigIntBoundSize)
724 _lower_bound[i+numContinuousVars] = lower_bound_int[i];
725 else
726 {
727 Cerr << "\nError: NomadOptimizer::load_parameters\n"
728 << "mesh_adaptive_search requires lower bounds "
729 << "for all discrete range variables" << std::endl;
730 abort_handler(-1);
731 }
732 if (upper_bound_int[i] < bigIntBoundSize)
733 _upper_bound[i+numContinuousVars] = upper_bound_int[i];
734 else
735 {
736 Cerr << "\nError: NomadOptimizer::load_parameters\n"
737 << "mesh_adaptive_search requires upper bounds "
738 << "for all discrete range variables" << std::endl;
739 abort_handler(-1);
740 }
741 p.set_BB_INPUT_TYPE(i+numContinuousVars,NOMAD::INTEGER);
742 }
743 }
744 for (i=0; i<numDiscreteRealVars; i++) {
745 index = set_value_to_index(initial_point_real[i],
746 initial_point_set_real[i]);
747 if (index == _NPOS) {
748 Cerr << "\nError: failure in discrete real set lookup within "
749 << "NomadOptimizer::load_parameters(Model &model)" << std::endl;
750 abort_handler(-1);
751 }
752 else {
753 _initial_point[i+numContinuousVars+numDiscreteIntVars] = (int)index;
754 }
755 if (!discreteSetRealCat.empty() && discreteSetRealCat[i] == 1)
756 {
757 p.set_BB_INPUT_TYPE(i+numContinuousVars+numDiscreteIntVars,
758 NOMAD::CATEGORICAL);
759 if (!discreteSetRealAdj.empty())
760 categoricalAdjacency.push_back(discreteSetRealAdj[i]);
761 else
762 {
763 tmp_categorical_adjacency.reshape(initial_point_set_real[i].size(),
764 initial_point_set_real[i].size());
765 for (j=0; j<initial_point_set_real[i].size(); j++)
766 {
767 for (k=0; k<initial_point_set_real[i].size(); k++)
768 {
769 if (k==j-1 || k==j || k==j+1)
770 tmp_categorical_adjacency[j][k] = 1;
771 else
772 tmp_categorical_adjacency[j][k] = 0;
773 }
774 }
775 categoricalAdjacency.push_back(tmp_categorical_adjacency);
776 }
777 }
778 else
779 {
780 p.set_BB_INPUT_TYPE(i+numContinuousVars+numDiscreteIntVars,
781 NOMAD::INTEGER);
782 _lower_bound[i+numContinuousVars+numDiscreteIntVars] = 0;
783 _upper_bound[i+numContinuousVars+numDiscreteIntVars] =
784 initial_point_set_real[i].size() - 1;
785 }
786 }
787 for (i=0; i<numDiscreteStringVars; i++) {
788 index = set_value_to_index(initial_point_string[i],
789 initial_point_set_string[i]);
790 if (index == _NPOS) {
791 Cerr << "\nError: failure in discrete string set lookup within "
792 << "NomadOptimizer::load_parameters(Model &model)" << std::endl;
793 abort_handler(-1);
794 }
795 else {
796 _initial_point[i+numContinuousVars+numDiscreteIntVars+numDiscreteRealVars] =
797 (int)index;
798 }
799 p.set_BB_INPUT_TYPE(i+numContinuousVars+numDiscreteIntVars+
800 numDiscreteRealVars,NOMAD::CATEGORICAL);
801 if (!discreteSetStrAdj.empty())
802 categoricalAdjacency.push_back(discreteSetStrAdj[i]);
803 else
804 {
805 tmp_categorical_adjacency.reshape(initial_point_set_string[i].size(),
806 initial_point_set_string[i].size());
807 for (j=0; j<initial_point_set_string[i].size(); j++)
808 {
809 for (k=0; k<initial_point_set_string[i].size(); k++)
810 {
811 if (k==j-1 || k==j || k==j+1)
812 tmp_categorical_adjacency[j][k] = 1;
813 else
814 tmp_categorical_adjacency[j][k] = 0;
815 }
816 }
817 categoricalAdjacency.push_back(tmp_categorical_adjacency);
818 }
819 }
820
821 initialPoint = _initial_point;
822 lowerBound = _lower_bound;
823 upperBound = _upper_bound;
824
825 // Define Output Types
826 // responses.
827 // objective_functions
828 // nonlinear_inequality_constraints
829 // nonlinear_equality_constraints
830
831 const RealVector& nln_eq_targets
832 = iteratedModel.nonlinear_eq_constraint_targets();
833
834 numNomadNonlinearIneqConstraints = numNonlinearIneqConstraintsFound;
835
836 configure_equality_constraints(CONSTRAINT_TYPE::NONLINEAR, numNonlinearIneqConstraints);
837 }
838
~NomadOptimizer()839 NomadOptimizer::~NomadOptimizer() {};
840
841 }
842
843
844