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 //- Non-class:   PRPMultiIndex
10 //- Description: Global funcs, types, etc. for lookup of PRPairs in eval cache
11 //- Checked by:
12 //- Version: $Id$
13 
14 #ifndef PRP_MULTI_INDEX_H
15 #define PRP_MULTI_INDEX_H
16 
17 #include "dakota_system_defs.hpp"
18 #include "dakota_data_types.hpp"
19 #include "ParamResponsePair.hpp"
20 
21 #include <boost/multi_index_container.hpp>
22 #include <boost/multi_index/hashed_index.hpp>
23 #include <boost/multi_index/mem_fun.hpp>
24 #include <boost/multi_index/ordered_index.hpp>
25 
26 #include <algorithm>
27 
28 namespace bmi = boost::multi_index;
29 
30 namespace Dakota {
31 
32 // --------------------------------------------------------
33 // Comparison functions shared by PRPCache/PRPQueue
34 // --------------------------------------------------------
35 
36 /// search function for a particular ParamResponsePair within a PRPList based
37 /// on ActiveSet content (request vector and derivative variables vector)
38 
39 /** a global function to compare the ActiveSet of a particular database_pr
40     (presumed to be in the global history list) with a passed in ActiveSet
41     (search_set). */
42 inline bool
set_compare(const ParamResponsePair & database_pr,const ActiveSet & search_set)43 set_compare(const ParamResponsePair& database_pr, const ActiveSet& search_set)
44 {
45   // Check each entry of ASV for presence of all requests in the stored data.
46   // A match is now detected when the search_asv is a SUBSET of the stored_asv
47   // (only exact matches were interpreted as duplicates previously).  This
48   // extension is widely applicable, but was first implemented to eliminate
49   // duplication in Model::estimate_derivatives() when the gradient evaluation
50   // contains inactive fns. whereas a previous line search evaluation at the
51   // same X had no inactive fns.
52   const ActiveSet&  stored_set = database_pr.active_set();
53   const ShortArray& stored_asv = stored_set.request_vector();
54   const ShortArray& search_asv = search_set.request_vector();
55   size_t i, asv_len = search_asv.size();
56   if ( stored_asv.size() != asv_len )
57     return false;
58   bool deriv_flag = false;
59   for (i=0; i<asv_len; ++i) {
60     short search_bits = search_asv[i];
61     if (search_bits & 6)
62       deriv_flag = true;
63     // bit-wise AND used to check if each of the search bits is
64     // present in the stored_asv value
65     if ( (stored_asv[i] & search_bits) != search_bits )
66       return false;
67   }
68 
69   // check if each of the search derivative variables is present in stored_dvv
70   if (deriv_flag) {
71     const SizetArray& stored_dvv = stored_set.derivative_vector();
72     const SizetArray& search_dvv = search_set.derivative_vector();
73     size_t dvv_len = search_dvv.size();
74     for (i=0; i<dvv_len; ++i)
75       if ( std::find(stored_dvv.begin(), stored_dvv.end(), search_dvv[i])
76            == stored_dvv.end() )
77 	return false;
78   }
79 
80   return true;
81 }
82 
83 
84 // ------------------------------------------------------
85 // Comparison and hashing functions for PRPCache/PRPQueue
86 // ------------------------------------------------------
87 
88 /// search function for a particular ParamResponsePair within a PRPMultiIndex
89 
90 /** a global function to compare the interface id and variables of a
91     particular database_pr (presumed to be in the global history list) with
92     a passed in key of interface id and variables provided by search_pr. */
id_vars_exact_compare(const ParamResponsePair & database_pr,const ParamResponsePair & search_pr)93 inline bool id_vars_exact_compare(const ParamResponsePair& database_pr,
94 				  const ParamResponsePair& search_pr)
95 {
96   // First check interface id strings.  If a different interface was used, then
97   // we must assume that the results are not interchangeable (differing model
98   // fidelity).
99   if ( search_pr.interface_id()   != database_pr.interface_id() )
100     return false;
101 
102   // For Boost hashing, need exact binary equality (not tolerance-based)
103   if ( search_pr.variables() != database_pr.variables() )
104     return false;
105 
106   // For Boost hashing, a post-processing step is used to manage the ActiveSet
107   // logic as shown in set_compare()
108 
109   return true;
110 }
111 
112 
113 /// hash_value for ParamResponsePairs stored in a PRPMultiIndex
hash_value(const ParamResponsePair & prp)114 inline std::size_t hash_value(const ParamResponsePair& prp)
115 {
116   // hash using interface ID string.
117   std::size_t seed = 0;
118   boost::hash_combine(seed, prp.interface_id());
119 
120   // Now, hash values of variables using Variables hash_value friend function
121   boost::hash_combine(seed, prp.variables());
122 
123   return seed;
124 }
125 
126 
127 // --------------------------------------
128 // structs and typedefs for PRPMultiIndex
129 // --------------------------------------
130 // define structs used below in PRPMultiIndex typedef
131 
132 /// wrapper to delegate to the ParamResponsePair hash_value function
133 struct partial_prp_hash {
134   /// access operator
operator ()Dakota::partial_prp_hash135   std::size_t operator()(const ParamResponsePair& prp) const
136   { return hash_value(prp); } // ONLY interfaceId & Vars used for hash_value
137 };
138 
139 /// predicate for comparing ONLY the interfaceId and Vars attributes of PRPair
140 struct partial_prp_equality {
141   /// access operator
operator ()Dakota::partial_prp_equality142   bool operator()(const ParamResponsePair& database_pr,
143                   const ParamResponsePair& search_pr) const
144   { return id_vars_exact_compare(database_pr, search_pr); }
145 };
146 
147 
148 // tags
149 struct ordered {};
150 struct hashed  {};
151 //struct random  {};
152 
153 
154 /// Boost Multi-Index Container for globally caching ParamResponsePairs
155 
156 /** For a global cache, both evaluation and interface id's are used for
157     tagging ParamResponsePair records. */
158 typedef bmi::multi_index_container<Dakota::ParamResponsePair, bmi::indexed_by<
159   // sorted by increasing evalId/interfaceId value; can be non-unique due to
160   // restart database and restarted run having different evals with the same
161   // evalId/interfaceId (due to modified execution settings)
162   bmi::ordered_non_unique<bmi::tag<ordered>,
163 			  bmi::const_mem_fun<Dakota::ParamResponsePair,
164 			  const IntStringPair&,
165 			  &Dakota::ParamResponsePair::eval_interface_ids> >,
166   // hashed using partial_prp_hash and compared using partial_prp_equality;
167   // can be non-unique due to multiple evals with same interfaceId/variables
168   // but distinct active set
169   bmi::hashed_non_unique<bmi::tag<hashed>,
170 			 bmi::identity<Dakota::ParamResponsePair>,
171                          partial_prp_hash, partial_prp_equality> > >
172 PRPMultiIndexCache;
173 
174 typedef PRPMultiIndexCache PRPCache;
175 typedef PRPCache::index_iterator<ordered>::type       PRPCacheOIter;
176 typedef PRPCache::index_const_iterator<ordered>::type PRPCacheOCIter;
177 typedef PRPCache::index_iterator<hashed>::type        PRPCacheHIter;
178 typedef PRPCache::index_const_iterator<hashed>::type  PRPCacheHCIter;
179 typedef PRPCacheOIter  PRPCacheIter;  ///< default cache iterator <0>
180 typedef PRPCacheOCIter PRPCacheCIter; ///< default cache const iterator <0>
181 /// default cache const reverse iterator <0>
182 typedef boost::reverse_iterator<PRPCacheCIter> PRPCacheCRevIter;
183 
184 // begin()/end() default to index 0.  These macros support other indices.
185 
186 /// hashed definition of cache begin
hashedCacheBegin(PRPCache & prp_cache)187 inline PRPCacheHIter hashedCacheBegin(PRPCache& prp_cache)
188 { return prp_cache.get<hashed>().begin(); }
189 /// hashed definition of cache end
hashedCacheEnd(PRPCache & prp_cache)190 inline PRPCacheHIter hashedCacheEnd(PRPCache& prp_cache)
191 { return prp_cache.get<hashed>().end(); }
192 
193 
194 /// Boost Multi-Index Container for locally queueing ParamResponsePairs
195 
196 /** For a local queue, interface id's are expected to be consistent,
197     such that evaluation id's are sufficient for tracking particular
198     evaluations. */
199 typedef bmi::multi_index_container<Dakota::ParamResponsePair, bmi::indexed_by<
200   /* random access for index-based operator[] access
201   bmi::random_access<bmi::tag<random> >, */
202   // sorted by unique/increasing evaluation id for fast key-based lookups
203   bmi::ordered_unique<bmi::tag<ordered>,
204 		      bmi::const_mem_fun<Dakota::ParamResponsePair, int,
205 		      &Dakota::ParamResponsePair::eval_id> >,
206   // hashed using partial_prp_hash and compared using partial_prp_equality;
207   // can be non-unique due to multiple evals with same interfaceId/variables
208   // but distinct active set
209   bmi::hashed_non_unique<bmi::tag<hashed>,
210 			 bmi::identity<Dakota::ParamResponsePair>,
211                          partial_prp_hash, partial_prp_equality> > >
212 PRPMultiIndexQueue;
213 
214 typedef PRPMultiIndexQueue PRPQueue;
215 //typedef PRPQueue::index_iterator<random>::type        PRPQueueRIter;
216 //typedef PRPQueue::index_const_iterator<random>::type  PRPQueueRCIter;
217 typedef PRPQueue::index_iterator<ordered>::type       PRPQueueOIter;
218 typedef PRPQueue::index_const_iterator<ordered>::type PRPQueueOCIter;
219 typedef PRPQueue::index_iterator<hashed>::type        PRPQueueHIter;
220 typedef PRPQueue::index_const_iterator<hashed>::type  PRPQueueHCIter;
221 typedef PRPQueueOIter  PRPQueueIter;  // default queue iterator <0>
222 typedef PRPQueueOCIter PRPQueueCIter; // default queue const iterator <0>
223 
224 // begin()/end() default to index 0.  These macros support other indices.
225 
226 /// hashed definition of queue begin
hashedQueueBegin(PRPQueue & prp_queue)227 inline PRPQueueHIter hashedQueueBegin(PRPQueue& prp_queue)
228 { return prp_queue.get<hashed>().begin(); }
229 /// hashed definition of queue end
hashedQueueEnd(PRPQueue & prp_queue)230 inline PRPQueueHIter hashedQueueEnd(PRPQueue& prp_queue)
231 { return prp_queue.get<hashed>().end(); }
232 
233 
234 // ------------------------------------
235 // lookup_by_val for PRPMultiIndexCache
236 // ------------------------------------
237 
238 /// find a ParamResponsePair based on the interface id, variables, and
239 /// ActiveSet search data within search_pr.
240 
241 /** Lookup occurs in two steps: (1) PRPMultiIndexCache lookup based on
242     strict equality in interface id and variables, and (2) set_compare()
243     post-processing based on ActiveSet subset logic. */
244 inline PRPCacheHIter
lookup_by_val(PRPMultiIndexCache & prp_cache,const ParamResponsePair & search_pr)245 lookup_by_val(PRPMultiIndexCache& prp_cache, const ParamResponsePair& search_pr)
246 {
247   PRPCacheHIter prp_hash_it0, prp_hash_it1;
248   boost::tuples::tie(prp_hash_it0, prp_hash_it1)
249     = prp_cache.get<hashed>().equal_range(search_pr);
250 
251   // equal_range returns a small sequence of possibilities resulting from
252   // hashing with ONLY interfaceId and variables.  Post-processing is then
253   // applied to this sequence using set_compare().
254   while (prp_hash_it0 != prp_hash_it1) {
255     if (set_compare(*prp_hash_it0, search_pr.active_set()))
256       return prp_hash_it0;
257     ++prp_hash_it0;
258   }
259   return prp_cache.get<hashed>().end();
260 }
261 
262 
263 /// find a ParamResponsePair within a PRPMultiIndexCache based on the
264 /// interface id, variables, and ActiveSet search data
265 inline PRPCacheHIter
lookup_by_val(PRPMultiIndexCache & prp_cache,const String & search_interface_id,const Variables & search_vars,const ActiveSet & search_set)266 lookup_by_val(PRPMultiIndexCache& prp_cache, const String& search_interface_id,
267 	      const Variables& search_vars,  const ActiveSet& search_set)
268 {
269   Response search_resp(SIMULATION_RESPONSE, search_set);
270   ParamResponsePair search_pr(search_vars, search_interface_id, search_resp);
271   return lookup_by_val(prp_cache, search_pr);
272 }
273 
274 
275 /* Better to use cache iterators and avoid extra shallow copies if not needed
276 
277 /// alternate overloaded form returns bool and sets found_pr by wrapping
278 /// lookup_by_val(PRPMultiIndexCache&, ParamResponsePair&)
279 inline bool
280 lookup_by_val(PRPMultiIndexCache& prp_cache, const ParamResponsePair& search_pr,
281 	      ParamResponsePair& found_pr)
282 {
283   PRPCacheHIter prp_hash_it = lookup_by_val(prp_cache, search_pr);
284   if (prp_hash_it != prp_cache.get<hashed>().end()) {
285     found_pr = *prp_hash_it;
286     return true;
287   }
288   else
289     return false;
290 }
291 
292 
293 /// alternate overloaded form returns bool and sets found_pr by wrapping
294 /// lookup_by_val(PRPMultiIndexCache&, String&, Variables&, ActiveSet&)
295 inline bool
296 lookup_by_val(PRPMultiIndexCache& prp_cache, const String& search_interface_id,
297 	      const Variables& search_vars, const ActiveSet& search_set,
298 	      ParamResponsePair& found_pr)
299 {
300   PRPCacheHIter prp_hash_it
301     = lookup_by_val(prp_cache, search_interface_id, search_vars, search_set);
302   if (prp_hash_it != prp_cache.get<hashed>().end()) {
303     found_pr = *prp_hash_it;
304     return true;
305   }
306   else
307     return false;
308 }
309 
310 
311 /// find the response of a ParamResponsePair within a PRPMultiIndexCache
312 /// based on interface id, variables, and ActiveSet search data
313 inline bool
314 lookup_by_val(PRPMultiIndexCache& prp_cache, const String& search_interface_id,
315 	      const Variables& search_vars, const ActiveSet& search_set,
316 	      Response& found_resp)
317 {
318   PRPCacheHIter prp_hash_it
319     = lookup_by_val(prp_cache, search_interface_id, search_vars, search_set);
320   if (prp_hash_it != prp_cache.get<hashed>().end()) {
321     found_resp = prp_hash_it->response();
322     return true;
323   }
324   else
325     return false;
326 }
327 */
328 
329 
330 inline PRPCacheOIter
lookup_by_nearby_val(PRPMultiIndexCache & prp_cache,const String & search_interface_id,const Variables & search_vars,const ActiveSet & search_set,Real tol)331 lookup_by_nearby_val(PRPMultiIndexCache& prp_cache,
332 		     const String& search_interface_id,
333 		     const Variables& search_vars, const ActiveSet& search_set,
334 		     Real tol)
335 {
336   PRPCacheOIter cache_it;
337   for (cache_it=prp_cache.begin(); cache_it!=prp_cache.end(); ++cache_it)
338     if (cache_it->interface_id() == search_interface_id      && // exact
339 	nearby(cache_it->variables(), search_vars, tol) && // tolerance
340 	set_compare(*cache_it, search_set))                     // subset
341       return cache_it; // Duplication detected.
342   return prp_cache.end();
343 }
344 
345 
346 // ------------------------------------
347 // lookup_by_ids for PRPMultiIndexCache
348 // ------------------------------------
349 /// find a ParamResponsePair within a PRPMultiIndexCache based on search_ids
350 /// (i.e. std::pair<eval_id,interface_id>) search data
351 inline PRPCacheOIter
lookup_by_ids(PRPMultiIndexCache & prp_cache,const IntStringPair & search_ids)352 lookup_by_ids(PRPMultiIndexCache& prp_cache, const IntStringPair& search_ids)
353 {
354   // sign of eval id indicates different dataset sources:
355   //   eval id > 0 for unique evals from current execution (in data_pairs)
356   //   eval id = 0 for evals from file import (not in data_pairs)
357   //   eval id < 0 for non-unique evals from restart (in data_pairs)
358   if (search_ids.first > 0) // positive ids (evals from current exec) are unique
359     return prp_cache.get<ordered>().find(search_ids);
360   else { // negative (restart) and 0 (file import) ids are non-unique in general
361 
362     /*
363     // could allow lookup if only one item found, but still a misuse of the fn
364     PRPCacheOIter prp_it0, prp_it1;
365     boost::tuples::tie(prp_it0, prp_it1)
366       = prp_cache.get<ordered>().equal_range(search_ids);
367     switch (std::distance(prp_it0, prp_it1)) {
368     case 0: return prp_cache.get<ordered>().end(); break;
369     case 1: return prp_it0;                        break;
370     default:
371       Cerr << "Error: duplicate entries in PRPCache lookup_by_ids()."
372            << std::endl;
373       abort_handler(-1); break;
374     }
375     */
376 
377     Cerr << "Error: lookup_by_ids(PRPCache&) used for lookup with non-positive "
378 	 << "evaluation id, which may be non-unique." << std::endl;
379     abort_handler(-1);
380   }
381 }
382 
383 
384 inline PRPCacheOIter
lookup_by_ids(PRPMultiIndexCache & prp_cache,const IntStringPair & search_ids,const ParamResponsePair & search_pr)385 lookup_by_ids(PRPMultiIndexCache& prp_cache, const IntStringPair& search_ids,
386 	      const ParamResponsePair& search_pr)
387 {
388   // sign of eval id indicates different dataset sources:
389   //   eval id > 0 for unique evals from current execution (in data_pairs)
390   //   eval id = 0 for evals from file import (not in data_pairs)
391   //   eval id < 0 for non-unique evals from restart (in data_pairs)
392   if (search_ids.first > 0) // positive ids (evals from current exec) are unique
393     return prp_cache.get<ordered>().find(search_ids);
394   else { // negative (restart) and 0 (file import) ids are non-unique in general
395 
396     // equal_range returns a small sequence of possibilities resulting from
397     // ordered lookup with ONLY search_ids.  Post-processing can then be
398     // applied to this sequence if needed using vars_compare().
399     PRPCacheOIter prp_it0, prp_it1;
400     boost::tuples::tie(prp_it0, prp_it1)
401       = prp_cache.get<ordered>().equal_range(search_ids);
402     switch (std::distance(prp_it0, prp_it1)) {
403     case 0: return prp_cache.get<ordered>().end(); break;
404     case 1: return prp_it0;                        break;
405     default:
406       while (prp_it0 != prp_it1) {
407 	if (prp_it0->variables() == search_pr.variables() && // exact
408 	    set_compare(*prp_it0, search_pr.active_set()))   // subset
409 	  return prp_it0;
410 	++prp_it0;
411       }
412       return prp_cache.get<ordered>().end();       break;
413     }
414   }
415 }
416 
417 
418 /* Better to use cache iterators and avoid extra shallow copies if not needed
419 
420 /// find a ParamResponsePair within a PRPMultiIndexCache based on
421 /// eval_interface_ids
422 inline bool
423 lookup_by_ids(PRPMultiIndexCache& prp_cache,
424               const IntStringPair& search_eval_interface_ids,
425               ParamResponsePair& found_pr)
426 {
427   PRPCacheOIter prp_iter = lookup_by_ids(prp_cache, search_eval_interface_ids);
428   if (prp_iter != prp_cache.get<ordered>().end()) {
429     found_pr = *prp_iter;
430     return true;
431   }
432   else
433     return false;
434 }
435 
436 
437 /// find a ParamResponsePair within a PRPMultiIndexCache based on
438 /// eval_interface_ids from the ParamResponsePair search data
439 inline bool
440 lookup_by_ids(PRPMultiIndexCache& prp_cache, const ParamResponsePair& search_pr,
441               ParamResponsePair& found_pr)
442 { return lookup_by_ids(prp_cache, search_pr.eval_interface_ids(), found_pr); }
443 */
444 
445 
446 // ------------------------------------
447 // lookup_by_val for PRPMultiIndexQueue
448 // ------------------------------------
449 
450 /// find a ParamResponsePair based on the interface id, variables, and
451 /// ActiveSet search data within search_pr.
452 
453 /** Lookup occurs in two steps: (1) PRPMultiIndexQueue lookup based on
454     strict equality in interface id and variables, and (2) set_compare()
455     post-processing based on ActiveSet subset logic. */
456 inline PRPQueueHIter
lookup_by_val(PRPMultiIndexQueue & prp_queue,const ParamResponsePair & search_pr)457 lookup_by_val(PRPMultiIndexQueue& prp_queue, const ParamResponsePair& search_pr)
458 {
459   PRPQueueHIter prp_hash_it0, prp_hash_it1;
460   boost::tuples::tie(prp_hash_it0, prp_hash_it1)
461     = prp_queue.get<hashed>().equal_range(search_pr);
462 
463   // equal_range returns a small sequence of possibilities resulting from
464   // hashing with ONLY interfaceId and variables.  Post-processing is then
465   // applied to this sequence using set_compare().
466   while (prp_hash_it0 != prp_hash_it1) {
467     if (set_compare(*prp_hash_it0, search_pr.active_set()))
468       return prp_hash_it0;
469     ++prp_hash_it0;
470   }
471   return prp_queue.get<hashed>().end();
472 }
473 
474 
475 /// find a ParamResponsePair within a PRPMultiIndexQueue based on
476 /// interface id, variables, and ActiveSet search data
477 inline PRPQueueHIter
lookup_by_val(PRPMultiIndexQueue & prp_queue,const String & search_interface_id,const Variables & search_vars,const ActiveSet & search_set)478 lookup_by_val(PRPMultiIndexQueue& prp_queue, const String& search_interface_id,
479 	      const Variables& search_vars,  const ActiveSet& search_set)
480 {
481   Response search_resp(SIMULATION_RESPONSE, search_set);
482   ParamResponsePair search_pr(search_vars, search_interface_id, search_resp);
483   return lookup_by_val(prp_queue, search_pr);
484 }
485 
486 
487 /* Better to use cache iterators and avoid extra shallow copies if not needed
488 
489 /// alternate overloaded form returns bool and sets found_pr by wrapping
490 /// lookup_by_val(PRPMultiIndexQueue&, ParamResponsePair&)
491 inline bool
492 lookup_by_val(PRPMultiIndexQueue& prp_queue, const ParamResponsePair& search_pr,
493 	      ParamResponsePair& found_pr)
494 {
495   PRPQueueHIter prp_hash_it = lookup_by_val(prp_queue, search_pr);
496   if (prp_hash_it != prp_queue.get<hashed>().end()) {
497     found_pr = *prp_hash_it;
498     return true;
499   }
500   else
501     return false;
502 }
503 
504 
505 /// alternate overloaded form returns bool and sets found_pr by wrapping
506 /// lookup_by_val(PRPMultiIndexQueue&, String&, Variables&, ActiveSet&)
507 inline bool
508 lookup_by_val(PRPMultiIndexQueue& prp_queue, const String& search_interface_id,
509 	      const Variables& search_vars, const ActiveSet& search_set,
510 	      ParamResponsePair& found_pr)
511 {
512   PRPQueueHIter prp_hash_it
513     = lookup_by_val(prp_queue, search_interface_id, search_vars, search_set);
514   if (prp_hash_it != prp_queue.get<hashed>().end()) {
515     found_pr = *prp_hash_it;
516     return true;
517   }
518   else
519     return false;
520 }
521 
522 
523 /// find the response of a ParamResponsePair within a PRPMultiIndexQueue
524 /// based on interface id, variables, and ActiveSet search data
525 inline bool
526 lookup_by_val(PRPMultiIndexQueue& prp_queue, const String& search_interface_id,
527 	      const Variables& search_vars, const ActiveSet& search_set,
528 	      Response& found_resp)
529 {
530   PRPQueueHIter prp_hash_it
531     = lookup_by_val(prp_queue, search_interface_id, search_vars, search_set);
532   if (prp_hash_it != prp_queue.get<hashed>().end()) {
533     found_resp = prp_hash_it->response();
534     return true;
535   }
536   else
537     return false;
538 }
539 */
540 
541 
542 // ----------------------------------------
543 // lookup_by_eval_id for PRPMultiIndexQueue
544 // ----------------------------------------
545 /// find a ParamResponsePair within a PRPMultiIndexQueue based on search_id
546 /// (i.e. integer eval_id) search data
547 inline PRPQueueOIter
lookup_by_eval_id(PRPMultiIndexQueue & prp_queue,int search_id)548 lookup_by_eval_id(PRPMultiIndexQueue& prp_queue, int search_id)
549 { return prp_queue.get<ordered>().find(search_id); }
550 
551 
552 /* Better to use cache iterators and avoid extra shallow copies if not needed
553 
554 /// find a ParamResponsePair within a PRPMultiIndexQueue based on eval_id
555 inline bool
556 lookup_by_eval_id(PRPMultiIndexQueue& prp_queue, int search_id,
557 		  ParamResponsePair& found_pr)
558 {
559   PRPQueueOIter prp_iter = lookup_by_eval_id(prp_queue, search_id);
560   if (prp_iter != prp_queue.get<ordered>().end()) {
561     found_pr = *prp_iter;
562     return true;
563   }
564   else
565     return false;
566 }
567 
568 
569 /// find a ParamResponsePair within a PRPMultiIndexQueue based on
570 /// eval_id from the ParamResponsePair search data
571 inline bool
572 lookup_by_eval_id(PRPMultiIndexQueue& prp_queue,
573 		  const ParamResponsePair& search_pr,
574 		  ParamResponsePair& found_pr)
575 { return lookup_by_eval_id(prp_queue, search_pr.eval_id(), found_pr); }
576 */
577 
578 } // namespace Dakota
579 
580 #endif // PRP_MULTI_INDEX_H
581 
582