1 /*  _______________________________________________________________________
2 
3     PECOS: Parallel Environment for Creation Of Stochastics
4     Copyright (c) 2011, Sandia National Laboratories.
5     This software is distributed under the GNU Lesser General Public License.
6     For more information, see the README file in the top Pecos directory.
7     _______________________________________________________________________ */
8 
9 #ifndef SURROGATE_DATA_HPP
10 #define SURROGATE_DATA_HPP
11 
12 #include "pecos_data_types.hpp"
13 #include "DiscrepancyCalculator.hpp"
14 #include <boost/math/special_functions/fpclassify.hpp> //for boostmath::isfinite
15 
16 
17 namespace Pecos {
18 
19 /// The representation of a SurrogateDataVars instance.  This representation,
20 /// or body, may be shared by multiple SurrogateDataVars handle instances.
21 
22 /** The SurrogateDataVars/SurrogateDataVarsRep pairs utilize a
23     handle-body idiom (Coplien, Advanced C++). */
24 
25 class SurrogateDataVarsRep
26 {
27   //
28   //- Heading: Friends
29   //
30 
31   /// the handle class can access attributes of the body class directly
32   friend class SurrogateDataVars;
33 
34 public:
35   /// destructor
36   ~SurrogateDataVarsRep();
37 
38 private:
39 
40   //
41   //- Heading: Private member functions
42   //
43 
44   /// constructor
45   SurrogateDataVarsRep(const RealVector& c_vars, const IntVector& di_vars,
46 		       const RealVector& dr_vars, short mode);
47   /// alternate constructor (data sizing only)
48   SurrogateDataVarsRep(size_t num_c_vars, size_t num_di_vars,
49 		       size_t num_dr_vars);
50 
51   /// lightweight constructor (common use case: continuous variables)
52   SurrogateDataVarsRep(const RealVector& c_vars, short mode);
53   /// alternate lightweight constructor (data sizing only)
54   SurrogateDataVarsRep(size_t num_c_vars);
55 
56 
57   //
58   //- Heading: Private data members
59   //
60 
61   RealVector continuousVars;   ///< continuous variables
62   IntVector  discreteIntVars;  ///< discrete integer variables
63   RealVector discreteRealVars; ///< discrete real variables
64 };
65 
66 
67 inline SurrogateDataVarsRep::
SurrogateDataVarsRep(const RealVector & c_vars,const IntVector & di_vars,const RealVector & dr_vars,short mode)68 SurrogateDataVarsRep(const RealVector& c_vars, const IntVector& di_vars,
69 		     const RealVector& dr_vars, short mode)
70 {
71   // Note: provided a way to query DataAccess mode for c_vars, could make
72   // greater use of operator= for {DEEP,SHALLOW}_COPY modes
73   if (mode == DEEP_COPY) {         // enforce deep vector copy
74     if (!c_vars.empty())  copy_data( c_vars, continuousVars);
75     if (!di_vars.empty()) copy_data(di_vars, discreteIntVars);
76     if (!dr_vars.empty()) copy_data(dr_vars, discreteRealVars);
77   }
78   else if (mode == SHALLOW_COPY) { // enforce shallow vector copy
79     if (!c_vars.empty())
80       continuousVars
81 	= RealVector(Teuchos::View,  c_vars.values(),  c_vars.length());
82     if (!di_vars.empty())
83       discreteIntVars
84 	= IntVector(Teuchos::View,  di_vars.values(), di_vars.length());
85     if (!dr_vars.empty())
86       discreteRealVars
87 	= RealVector(Teuchos::View, dr_vars.values(), dr_vars.length());
88   }
89   else {                           // default: assume existing Copy/View state
90     if (!c_vars.empty())    continuousVars = c_vars;
91     if (!di_vars.empty())  discreteIntVars = di_vars;
92     if (!dr_vars.empty()) discreteRealVars = dr_vars;
93   }
94 }
95 
96 
97 inline SurrogateDataVarsRep::
SurrogateDataVarsRep(size_t num_c_vars,size_t num_di_vars,size_t num_dr_vars)98 SurrogateDataVarsRep(size_t num_c_vars, size_t num_di_vars, size_t num_dr_vars)
99 {
100   continuousVars.sizeUninitialized(num_c_vars);
101   discreteIntVars.sizeUninitialized(num_di_vars);
102   discreteRealVars.sizeUninitialized(num_dr_vars);
103 }
104 
105 
106 inline SurrogateDataVarsRep::
SurrogateDataVarsRep(const RealVector & c_vars,short mode)107 SurrogateDataVarsRep(const RealVector& c_vars, short mode)
108 {
109   // Note: provided a way to query DataAccess mode for c_vars, could make
110   // greater use of operator= for {DEEP,SHALLOW}_COPY modes
111   if (!c_vars.empty())
112     switch (mode) {
113     case DEEP_COPY:
114       copy_data(c_vars, continuousVars); break;
115     case SHALLOW_COPY:
116       continuousVars
117 	= RealVector(Teuchos::View, c_vars.values(), c_vars.length());
118       break;
119     default: // assume existing Copy/View state
120       continuousVars = c_vars; break;
121     }
122 }
123 
124 
125 inline SurrogateDataVarsRep::
SurrogateDataVarsRep(size_t num_c_vars)126 SurrogateDataVarsRep(size_t num_c_vars)
127 { continuousVars.sizeUninitialized(num_c_vars); }
128 
129 
~SurrogateDataVarsRep()130 inline SurrogateDataVarsRep::~SurrogateDataVarsRep()
131 { }
132 
133 
134 /// Container class encapsulating basic parameter data for defining a
135 /// "truth" data point.
136 
137 /** A set of these input data points is contained in SurrogateData and
138     provides the data to build the approximation.  A handle-body idiom
139     is used to avoid excessive data copying overhead. */
140 
141 class SurrogateDataVars
142 {
143 public:
144 
145   //
146   //- Heading: Constructors, destructor, and operators
147   //
148 
149   /// default constructor
150   SurrogateDataVars();
151 
152   /// standard constructor
153   SurrogateDataVars(const RealVector& c_vars, const IntVector& di_vars,
154 		    const RealVector& dr_vars, short mode = DEFAULT_COPY);
155   /// alternate constructor (data sizing only)
156   SurrogateDataVars(size_t num_c_vars, size_t num_di_vars, size_t num_dr_vars);
157 
158   /// lightweight constructor
159   SurrogateDataVars(const RealVector& c_vars, short mode = DEFAULT_COPY);
160   /// alternate lightweight constructor (data sizing only)
161   SurrogateDataVars(size_t num_c_vars);
162 
163   /// copy constructor
164   SurrogateDataVars(const SurrogateDataVars& sdv);
165   /// destructor
166   ~SurrogateDataVars();
167 
168   /// assignment operator
169   SurrogateDataVars& operator=(const SurrogateDataVars& sdv);
170   // equality operator
171   //bool operator==(const SurrogateDataVars& sdv) const;
172 
173   //
174   //- Heading: member functions
175   //
176 
177   /// instantiate a sdvRep
178   void create_rep(size_t num_vars);
179 
180   /// return number of continuous variables
181   size_t cv() const;
182   /// return number of discrete integer variables
183   size_t div() const;
184   /// return number of discrete real variables
185   size_t drv() const;
186 
187   /// return deep copy of SurrogateDataVars instance
188   SurrogateDataVars copy() const;
189 
190   /// set i^{th} entry within continuousVars
191   void continuous_variable(Real c_var, size_t i);
192   /// set continuousVars
193   void continuous_variables(const RealVector& c_vars,
194 			    short mode = DEFAULT_COPY);
195   /// get continuousVars
196   const RealVector& continuous_variables() const;
197   /// get view of continuousVars for updating in place
198   RealVector continuous_variables_view();
199 
200   /// set i^{th} entry within discreteIntVars
201   void discrete_int_variable(int di_var, size_t i);
202   /// set discreteIntVars
203   void discrete_int_variables(const IntVector& di_vars,
204 			      short mode = DEFAULT_COPY);
205   /// get discreteIntVars
206   const IntVector& discrete_int_variables() const;
207   /// get view of discreteIntVars for updating in place
208   IntVector discrete_int_variables_view();
209 
210   /// set i^{th} entry within discreteRealVars
211   void discrete_real_variable(Real dr_var, size_t i);
212   /// set discreteRealVars
213   void discrete_real_variables(const RealVector& dr_vars,
214 			       short mode = DEFAULT_COPY);
215   /// get discreteRealVars
216   const RealVector& discrete_real_variables() const;
217   /// get view of discreteRealVars for updating in place
218   RealVector discrete_real_variables_view();
219 
220   /// function to check sdvRep (does this handle contain a body)
221   bool is_null() const;
222 
223 private:
224 
225   //
226   //- Heading: Private data members
227   //
228 
229   /// pointer to the body (handle-body idiom)
230   std::shared_ptr<SurrogateDataVarsRep> sdvRep;
231 };
232 
233 
SurrogateDataVars()234 inline SurrogateDataVars::SurrogateDataVars()
235 { }
236 
237 
238 // BMA NOTE: The following don't use make_shared<SurrogateDataVarsRep>()
239 // due to private ctors
240 
241 inline SurrogateDataVars::
SurrogateDataVars(const RealVector & c_vars,const IntVector & di_vars,const RealVector & dr_vars,short mode)242 SurrogateDataVars(const RealVector& c_vars, const IntVector& di_vars,
243 		  const RealVector& dr_vars, short mode):
244   sdvRep(new SurrogateDataVarsRep(c_vars, di_vars, dr_vars, mode))
245 { }
246 
247 
248 inline SurrogateDataVars::
SurrogateDataVars(size_t num_c_vars,size_t num_di_vars,size_t num_dr_vars)249 SurrogateDataVars(size_t num_c_vars, size_t num_di_vars, size_t num_dr_vars):
250   sdvRep(new SurrogateDataVarsRep(num_c_vars, num_di_vars, num_dr_vars))
251 { }
252 
253 
254 inline SurrogateDataVars::
SurrogateDataVars(const RealVector & c_vars,short mode)255 SurrogateDataVars(const RealVector& c_vars, short mode):
256   sdvRep(new SurrogateDataVarsRep(c_vars, mode))
257 { }
258 
259 
SurrogateDataVars(size_t num_c_vars)260 inline SurrogateDataVars::SurrogateDataVars(size_t num_c_vars):
261   sdvRep(new SurrogateDataVarsRep(num_c_vars))
262 { }
263 
264 
SurrogateDataVars(const SurrogateDataVars & sdv)265 inline SurrogateDataVars::SurrogateDataVars(const SurrogateDataVars& sdv):
266   sdvRep(sdv.sdvRep)
267 { }
268 
269 
~SurrogateDataVars()270 inline SurrogateDataVars::~SurrogateDataVars()
271 { }
272 
273 
274 inline SurrogateDataVars& SurrogateDataVars::
operator =(const SurrogateDataVars & sdv)275 operator=(const SurrogateDataVars& sdv)
276 {
277   sdvRep = sdv.sdvRep;
278   return *this;
279 }
280 
281 
282 //inline bool SurrogateDataVars::operator==(const SurrogateDataVars& sdv) const
283 //{
284 //  return (sdvRep->continuousVars   == sdv.sdvRep->continuousVars  &&
285 //          sdvRep->discreteIntVars  == sdv.sdvRep->discreteIntVars &&
286 //          sdvRep->discreteRealVars == sdv.sdvRep->discreteRealVars) ?
287 //    true : false;
288 //}
289 
290 
create_rep(size_t num_vars)291 inline void SurrogateDataVars::create_rep(size_t num_vars)
292 { sdvRep.reset(new SurrogateDataVarsRep(num_vars)); }
293 
294 
295 /// deep copy of SurrogateDataVars instance
copy() const296 inline SurrogateDataVars SurrogateDataVars::copy() const
297 {
298   SurrogateDataVars sdv(sdvRep->continuousVars,   sdvRep->discreteIntVars,
299 			sdvRep->discreteRealVars, DEEP_COPY);
300   return sdv;
301 }
302 
303 
continuous_variable(Real c_var,size_t i)304 inline void SurrogateDataVars::continuous_variable(Real c_var, size_t i)
305 { sdvRep->continuousVars[i] = c_var; }
306 
307 
308 inline void SurrogateDataVars::
continuous_variables(const RealVector & c_vars,short mode)309 continuous_variables(const RealVector& c_vars, short mode)
310 {
311   if (mode == DEEP_COPY)         // enforce deep vector copy
312     copy_data(c_vars, sdvRep->continuousVars);
313   else if (mode == SHALLOW_COPY) // enforce shallow vector copy
314     sdvRep->continuousVars
315       = RealVector(Teuchos::View, c_vars.values(), c_vars.length());
316   else                           // default: assume existing Copy/View state
317     sdvRep->continuousVars = c_vars;
318 }
319 
320 
cv() const321 inline size_t SurrogateDataVars::cv() const
322 { return sdvRep->continuousVars.length(); }
323 
324 
div() const325 inline size_t SurrogateDataVars::div() const
326 { return sdvRep->discreteIntVars.length(); }
327 
328 
drv() const329 inline size_t SurrogateDataVars::drv() const
330 { return sdvRep->discreteRealVars.length(); }
331 
332 
continuous_variables() const333 inline const RealVector& SurrogateDataVars::continuous_variables() const
334 { return sdvRep->continuousVars; }
335 
336 
continuous_variables_view()337 inline RealVector SurrogateDataVars::continuous_variables_view()
338 {
339   return RealVector(Teuchos::View, sdvRep->continuousVars.values(),
340 		    sdvRep->continuousVars.length());
341 }
342 
343 
discrete_int_variable(int di_var,size_t i)344 inline void SurrogateDataVars::discrete_int_variable(int di_var, size_t i)
345 { sdvRep->discreteIntVars[i] = di_var; }
346 
347 
348 inline void SurrogateDataVars::
discrete_int_variables(const IntVector & di_vars,short mode)349 discrete_int_variables(const IntVector& di_vars, short mode)
350 {
351   if (mode == DEEP_COPY)         // enforce deep vector copy
352     copy_data(di_vars, sdvRep->discreteIntVars);
353   else if (mode == SHALLOW_COPY) // enforce shallow vector copy
354     sdvRep->discreteIntVars
355       = IntVector(Teuchos::View, di_vars.values(), di_vars.length());
356   else                           // default: assume existing Copy/View state
357     sdvRep->discreteIntVars = di_vars;
358 }
359 
360 
discrete_int_variables() const361 inline const IntVector& SurrogateDataVars::discrete_int_variables() const
362 { return sdvRep->discreteIntVars; }
363 
364 
discrete_int_variables_view()365 inline IntVector SurrogateDataVars::discrete_int_variables_view()
366 {
367   return IntVector(Teuchos::View, sdvRep->discreteIntVars.values(),
368 		   sdvRep->discreteIntVars.length());
369 }
370 
371 
discrete_real_variable(Real dr_var,size_t i)372 inline void SurrogateDataVars::discrete_real_variable(Real dr_var, size_t i)
373 { sdvRep->discreteRealVars[i] = dr_var; }
374 
375 
376 inline void SurrogateDataVars::
discrete_real_variables(const RealVector & dr_vars,short mode)377 discrete_real_variables(const RealVector& dr_vars, short mode)
378 {
379   if (mode == DEEP_COPY)         // enforce deep vector copy
380     copy_data(dr_vars, sdvRep->discreteRealVars);
381   else if (mode == SHALLOW_COPY) // enforce shallow vector copy
382     sdvRep->discreteRealVars
383       = RealVector(Teuchos::View, dr_vars.values(), dr_vars.length());
384   else                           // default: assume existing Copy/View state
385     sdvRep->discreteRealVars = dr_vars;
386 }
387 
388 
discrete_real_variables() const389 inline const RealVector& SurrogateDataVars::discrete_real_variables() const
390 { return sdvRep->discreteRealVars; }
391 
392 
discrete_real_variables_view()393 inline RealVector SurrogateDataVars::discrete_real_variables_view()
394 {
395   return RealVector(Teuchos::View, sdvRep->discreteRealVars.values(),
396 		    sdvRep->discreteRealVars.length());
397 }
398 
399 
is_null() const400 inline bool SurrogateDataVars::is_null() const
401 { return (sdvRep) ? false : true; }
402 
403 
404 /// The representation of a surrogate data response.  This representation,
405 /// or body, may be shared by multiple SurrogateDataResp handle instances.
406 
407 /** The SurrogateDataResp/SurrogateDataRespRep pairs utilize a
408     handle-body idiom (Coplien, Advanced C++). */
409 
410 class SurrogateDataRespRep
411 {
412   //
413   //- Heading: Friends
414   //
415 
416   /// the handle class can access attributes of the body class directly
417   friend class SurrogateDataResp;
418 
419 public:
420   /// destructor
421   ~SurrogateDataRespRep();
422 
423 private:
424 
425   //
426   //- Heading: Private member functions
427   //
428 
429   /// constructor
430   SurrogateDataRespRep(Real fn_val, const RealVector& fn_grad,
431 		       const RealSymMatrix& fn_hess, short bits, short mode);
432   /// lightweight constructor (common use case)
433   SurrogateDataRespRep(Real fn_val);
434   /// alternate constructor (data sizing only)
435   SurrogateDataRespRep(short bits, size_t num_vars);
436 
437   //
438   //- Heading: Private data members
439   //
440 
441   short           activeBits; ///< active data bits: 1 (fn), 2 (grad), 4 (hess)
442   Real            responseFn; ///< truth response function value
443   RealVector    responseGrad; ///< truth response function gradient
444   RealSymMatrix responseHess; ///< truth response function Hessian
445 };
446 
447 
448 inline SurrogateDataRespRep::
SurrogateDataRespRep(Real fn_val,const RealVector & fn_grad,const RealSymMatrix & fn_hess,short bits,short mode)449 SurrogateDataRespRep(Real fn_val, const RealVector& fn_grad,
450 		     const RealSymMatrix& fn_hess, short bits, short mode):
451   responseFn(fn_val), // always deep copy for scalars
452   activeBits(bits)
453 {
454   // Note: provided a way to query incoming grad/hess DataAccess modes,
455   // could make greater use of operator= for {DEEP,SHALLOW}_COPY modes
456   if (mode == DEEP_COPY) {          // enforce vector/matrix deep copy
457     if (activeBits & 2) copy_data(fn_grad, responseGrad);
458     if (activeBits & 4) copy_data(fn_hess, responseHess);
459   }
460   else if (mode == SHALLOW_COPY) {  // enforce vector/matrix shallow copy
461     if (activeBits & 2)
462       responseGrad = RealVector(Teuchos::View, fn_grad.values(),
463 				fn_grad.length());
464     if (activeBits & 4)
465       responseHess = RealSymMatrix(Teuchos::View, fn_hess, fn_hess.numRows());
466   }
467   else {                            // default: assume existing Copy/View state
468     if (activeBits & 2) responseGrad = fn_grad;
469     if (activeBits & 4) responseHess = fn_hess;
470   }
471 }
472 
473 
SurrogateDataRespRep(Real fn_val)474 inline SurrogateDataRespRep::SurrogateDataRespRep(Real fn_val):
475   responseFn(fn_val), // always deep copy for scalars
476   activeBits(1)
477 { }
478 
479 
480 inline SurrogateDataRespRep::
SurrogateDataRespRep(short bits,size_t num_vars)481 SurrogateDataRespRep(short bits, size_t num_vars):
482   activeBits(bits)
483 {
484   if (bits & 2)
485     responseGrad.sizeUninitialized(num_vars);
486   if (bits & 4)
487     responseHess.shapeUninitialized(num_vars);
488 }
489 
490 
~SurrogateDataRespRep()491 inline SurrogateDataRespRep::~SurrogateDataRespRep()
492 { }
493 
494 
495 /// Container class encapsulating basic parameter and response data
496 /// for defining a "truth" data point.
497 
498 /** A list of these data points is contained in Approximation instances
499     (e.g., Dakota::Approximation::currentPoints) and provides the data
500     to build the approximation.  A handle-body idiom is used to avoid
501     excessive data copying overhead. */
502 
503 class SurrogateDataResp
504 {
505 public:
506 
507   //
508   //- Heading: Constructors, destructor, and operators
509   //
510 
511   /// default constructor
512   SurrogateDataResp();
513   /// standard constructor
514   SurrogateDataResp(Real fn_val, const RealVector& fn_grad,
515 		    const RealSymMatrix& fn_hess, short bits,
516 		    short mode = DEFAULT_COPY);
517   /// lightweight constructor
518   SurrogateDataResp(Real fn_val);
519   /// alternate constructor (data sizing only)
520   SurrogateDataResp(short bits, size_t num_vars);
521   /// copy constructor
522   SurrogateDataResp(const SurrogateDataResp& sdr);
523   /// destructor
524   ~SurrogateDataResp();
525 
526   /// assignment operator
527   SurrogateDataResp& operator=(const SurrogateDataResp& sdr);
528   // equality operator
529   //bool operator==(const SurrogateDataResp& sdr) const;
530 
531   //
532   //- Heading: member functions
533   //
534 
535   /// instantiate a sdvRep
536   void create_rep(short bits, size_t num_vars);
537 
538   /// return deep copy of SurrogateDataResp instance
539   SurrogateDataResp copy() const;
540 
541   /// set activeBits
542   void active_bits(short val);
543   /// get activeBits
544   short active_bits() const;
545 
546   /// size response{Grad,Hess}
547   void derivative_variables(size_t num_v);
548   /// return size of response{Grad,Hess} (0 if inactive)
549   size_t derivative_variables() const;
550 
551   /// set responseFn
552   void response_function(Real fn);
553   /// get responseFn
554   Real response_function() const;
555   /// get "view" of responseFn for updating in place
556   Real& response_function_view();
557 
558   /// set i^{th} entry within responseGrad
559   void response_gradient(Real grad_i, size_t i);
560   /// set responseGrad
561   void response_gradient(const RealVector& grad, short mode = DEFAULT_COPY);
562   /// get responseGrad
563   const RealVector& response_gradient() const;
564   /// get view of responseGrad for updating in place
565   RealVector response_gradient_view();
566 
567   /// set i-j^{th} entry within responseHess
568   void response_hessian(Real hess_ij, size_t i, size_t j);
569   /// set responseHess
570   void response_hessian(const RealSymMatrix& hess, short mode = DEFAULT_COPY);
571   /// get responseHess
572   const RealSymMatrix& response_hessian() const;
573   /// get view of responseHess for updating in place
574   RealSymMatrix response_hessian_view();
575 
576   /// function to check sdrRep (does this handle contain a body)
577   bool is_null() const;
578   /// output response function, gradient, and Hessian data
579   void write(std::ostream& s) const;
580 
581 private:
582 
583   //
584   //- Heading: Private data members
585   //
586 
587   /// pointer to the body (handle-body idiom)
588   std::shared_ptr<SurrogateDataRespRep> sdrRep;
589 };
590 
591 
SurrogateDataResp()592 inline SurrogateDataResp::SurrogateDataResp()
593 { }
594 
595 // BMA NOTE: The following don't use make_shared<SurrogateDataRespRep>()
596 // due to private ctors
597 
598 inline SurrogateDataResp::
SurrogateDataResp(Real fn_val,const RealVector & fn_grad,const RealSymMatrix & fn_hess,short bits,short mode)599 SurrogateDataResp(Real fn_val, const RealVector& fn_grad,
600 		  const RealSymMatrix& fn_hess, short bits, short mode):
601   sdrRep(new SurrogateDataRespRep(fn_val, fn_grad, fn_hess, bits, mode))
602 { }
603 
604 
SurrogateDataResp(Real fn_val)605 inline SurrogateDataResp::SurrogateDataResp(Real fn_val):
606   sdrRep(new SurrogateDataRespRep(fn_val))
607 { }
608 
609 
610 inline SurrogateDataResp::
SurrogateDataResp(short bits,size_t num_vars)611 SurrogateDataResp(short bits, size_t num_vars):
612   sdrRep(new SurrogateDataRespRep(bits, num_vars))
613 { }
614 
615 
SurrogateDataResp(const SurrogateDataResp & sdr)616 inline SurrogateDataResp::SurrogateDataResp(const SurrogateDataResp& sdr):
617   sdrRep(sdr.sdrRep)
618 { }
619 
620 
~SurrogateDataResp()621 inline SurrogateDataResp::~SurrogateDataResp()
622 { }
623 
624 
625 inline SurrogateDataResp& SurrogateDataResp::
operator =(const SurrogateDataResp & sdr)626 operator=(const SurrogateDataResp& sdr)
627 {
628   sdrRep = sdr.sdrRep;
629   return *this;
630 }
631 
632 
633 //inline bool SurrogateDataResp::operator==(const SurrogateDataResp& sdr) const
634 //{
635 //  return ( sdrRep->responseFn   == sdr.sdrRep->responseFn   &&
636 //	     sdrRep->responseGrad == sdr.sdrRep->responseGrad &&
637 //	     sdrRep->responseHess == sdr.sdrRep->responseHess ) ? true : false;
638 //}
639 
640 
create_rep(short bits,size_t num_vars)641 inline void SurrogateDataResp::create_rep(short bits, size_t num_vars)
642 { sdrRep.reset(new SurrogateDataRespRep(bits, num_vars)); }
643 
644 
645 /// deep copy of SurrogateDataResp instance
copy() const646 inline SurrogateDataResp SurrogateDataResp::copy() const
647 {
648   SurrogateDataResp sdr(sdrRep->responseFn,   sdrRep->responseGrad,
649 			sdrRep->responseHess, sdrRep->activeBits, DEEP_COPY);
650   return sdr;
651 }
652 
653 
active_bits(short val)654 inline void SurrogateDataResp::active_bits(short val)
655 { sdrRep->activeBits = val; }
656 
657 
active_bits() const658 inline short SurrogateDataResp::active_bits() const
659 { return sdrRep->activeBits; }
660 
661 
derivative_variables(size_t num_v)662 inline void SurrogateDataResp::derivative_variables(size_t num_v)
663 {
664   if (sdrRep->activeBits & 2)
665     sdrRep->responseGrad.sizeUninitialized(num_v);
666   if (sdrRep->activeBits & 4)
667     sdrRep->responseHess.shapeUninitialized(num_v);
668 }
669 
670 
derivative_variables() const671 inline size_t SurrogateDataResp::derivative_variables() const
672 {
673   return std::max(sdrRep->responseGrad.length(),
674 		  sdrRep->responseHess.numRows());
675 }
676 
677 
response_function(Real fn)678 inline void SurrogateDataResp::response_function(Real fn)
679 { sdrRep->responseFn = fn; }
680 
681 
response_function() const682 inline Real SurrogateDataResp::response_function() const
683 { return sdrRep->responseFn; }
684 
685 
response_function_view()686 inline Real& SurrogateDataResp::response_function_view()
687 { return sdrRep->responseFn; }
688 
689 
response_gradient(Real grad_i,size_t i)690 inline void SurrogateDataResp::response_gradient(Real grad_i, size_t i)
691 { sdrRep->responseGrad[i] = grad_i; }
692 
693 
694 inline void SurrogateDataResp::
response_gradient(const RealVector & grad,short mode)695 response_gradient(const RealVector& grad, short mode)
696 {
697   if (mode == DEEP_COPY)          // enforce vector deep copy
698     copy_data(grad, sdrRep->responseGrad);
699   else if (mode == SHALLOW_COPY)  // enforce vector shallow copy
700     sdrRep->responseGrad
701       = RealVector(Teuchos::View, grad.values(), grad.length());
702   else                            // default: assume existing Copy/View state
703     sdrRep->responseGrad = grad;
704 }
705 
706 
response_gradient() const707 inline const RealVector& SurrogateDataResp::response_gradient() const
708 { return sdrRep->responseGrad; }
709 
710 
response_gradient_view()711 inline RealVector SurrogateDataResp::response_gradient_view()
712 {
713   return RealVector(Teuchos::View, sdrRep->responseGrad.values(),
714 		    sdrRep->responseGrad.length());
715 }
716 
717 
718 inline void SurrogateDataResp::
response_hessian(Real hess_ij,size_t i,size_t j)719 response_hessian(Real hess_ij, size_t i, size_t j)
720 { sdrRep->responseHess(i,j) = hess_ij; }
721 
722 
723 inline void SurrogateDataResp::
response_hessian(const RealSymMatrix & hess,short mode)724 response_hessian(const RealSymMatrix& hess, short mode)
725 {
726   if (mode == DEEP_COPY)          // enforce matrix deep copy
727     copy_data(hess, sdrRep->responseHess);
728   else if (mode == SHALLOW_COPY)  // enforce matrix shallow copy
729     sdrRep->responseHess = RealSymMatrix(Teuchos::View, hess, hess.numRows());
730   else                            // default: assume existing Copy/View state
731     sdrRep->responseHess = hess;
732 }
733 
734 
response_hessian() const735 inline const RealSymMatrix& SurrogateDataResp::response_hessian() const
736 { return sdrRep->responseHess; }
737 
738 
response_hessian_view()739 inline RealSymMatrix SurrogateDataResp::response_hessian_view()
740 {
741   return RealSymMatrix(Teuchos::View, sdrRep->responseHess,
742 		       sdrRep->responseHess.numRows());
743 }
744 
745 
is_null() const746 inline bool SurrogateDataResp::is_null() const
747 { return (sdrRep) ? false : true; }
748 
749 
write(std::ostream & s) const750 inline void SurrogateDataResp::write(std::ostream& s) const
751 {
752   if (sdrRep->activeBits & 1)
753     s << "function value    =  " << std::setw(WRITE_PRECISION+7)
754       << sdrRep->responseFn << '\n';
755   if (sdrRep->activeBits & 2) {
756     s << "function gradient =\n";
757     write_data_trans(s, sdrRep->responseGrad, true, true, true);
758   }
759   if (sdrRep->activeBits & 4)
760     s << "function Hessian  =\n" << sdrRep->responseHess;
761 }
762 
763 
764 /// std::ostream insertion operator for SurrogateDataResp
operator <<(std::ostream & s,const SurrogateDataResp & sdr)765 inline std::ostream& operator<<(std::ostream& s, const SurrogateDataResp& sdr)
766 { sdr.write(s); return s; }
767 
768 
769 /// Representation of management class for surrogate data defined from
770 /// input variable data and output response data.
771 
772 /** Response sets are generally unique for each approximated response
773     function, but variable sets are often (but not always) replicated.
774     Thus the design accommodates the case where inputs and/or outputs
775     involve either shallow or deep copies. */
776 
777 class SurrogateDataRep
778 {
779   //
780   //- Heading: Friends
781   //
782 
783   /// the handle class can access attributes of the body class directly
784   friend class SurrogateData;
785 
786 public:
787   ~SurrogateDataRep(); ///< destructor
788 
789 private:
790 
791   //
792   //- Heading: Constructors and destructor
793   //
794 
795   SurrogateDataRep();  ///< constructor
796 
797   //
798   //- Heading: Member functions
799   //
800 
801   /// update {varsData,respData}Iter from activeKey
802   void update_active_iterators();
803 
804   //
805   //- Heading: Private data members
806   //
807 
808   /// database of reference variable data sets, with lookup by model/level index
809   std::map<UShortArray, SDVArray> varsData;
810   /// iterator to active entry within varsData
811   std::map<UShortArray, SDVArray>::iterator varsDataIter;
812   /// filtered database of variable data sets, a subset drawn from varsData
813   std::map<UShortArray, SDVArray> filteredVarsData;
814 
815   /// database of reference response data sets, with lookup by model/level index
816   std::map<UShortArray, SDRArray> respData;
817   /// iterator to active entry within respData
818   std::map<UShortArray, SDRArray>::iterator respDataIter;
819   /// filtered database of response data sets, a subset drawn from respData
820   std::map<UShortArray, SDRArray> filteredRespData;
821 
822   /// sets of popped variables data sets, with lookup by model/level index.
823   /// Each popped set is an SDVArray extracted from varsData.
824   std::map<UShortArray, SDVArrayDeque> poppedVarsData;
825   /// sets of popped response data sets, with lookup by model/level index.
826   /// Each popped set is an SDRArray extracted from respData.
827   std::map<UShortArray, SDRArrayDeque> poppedRespData;
828   /// a stack managing the number of points previously appended that
829   /// can be removed by calls to pop()
830   std::map<UShortArray, SizetArray> popCountStack;
831 
832   /// database key indicating the currently active {SDV,SDR}Arrays.
833   /// the key is a multi-index managing multiple modeling dimensions
834   /// such as model form, doscretization level, etc.
835   UShortArray activeKey;
836 
837   /// index of anchor point within {vars,resp}Data, _NPOS if none; for now,
838   /// we restrict anchor to reference data to simplify bookkeeping (assume
839   /// anchor does not migrate within pushed/popped data)
840   std::map<UShortArray, size_t> anchorIndex;
841 
842   /// map from failed respData indices to failed data bits; defined
843   /// in sample_checks() and used for fault tolerance
844   std::map<UShortArray, SizetShortMap> failedRespData;
845 };
846 
847 
SurrogateDataRep()848 inline SurrogateDataRep::SurrogateDataRep()
849 { }
850 
851 
~SurrogateDataRep()852 inline SurrogateDataRep::~SurrogateDataRep()
853 { }
854 
855 
update_active_iterators()856 inline void SurrogateDataRep::update_active_iterators()
857 {
858   varsDataIter = varsData.find(activeKey);
859   if (varsDataIter == varsData.end()) {
860     std::pair<UShortArray, SDVArray> sdv_pair(activeKey, SDVArray());
861     varsDataIter = varsData.insert(sdv_pair).first;
862   }
863   respDataIter = respData.find(activeKey);
864   if (respDataIter == respData.end()) {
865     std::pair<UShortArray, SDRArray> sdr_pair(activeKey, SDRArray());
866     respDataIter = respData.insert(sdr_pair).first;
867   }
868 }
869 
870 
871 /// Management class for surrogate data defined from input variable
872 /// data and output response data.
873 
874 /** Response sets are generally unique for each approximated response
875     function, but variable sets are often (but not always) replicated.
876     Thus the design accommodates the case where inputs and/or outputs
877     involve either shallow or deep copies. */
878 
879 class SurrogateData
880 {
881 public:
882 
883   //
884   //- Heading: Constructors, destructor, and operators
885   //
886 
887   SurrogateData();                        ///< default handle ctor (no body)
888   SurrogateData(bool handle);             ///< handle + body constructor
889   SurrogateData(const UShortArray& key);  ///< handle + body constructor
890   SurrogateData(const SurrogateData& sd); ///< copy constructor
891   ~SurrogateData();                       ///< destructor
892 
893   /// assignment operator
894   SurrogateData& operator=(const SurrogateData& sdv);
895 
896   //
897   //- Heading: Member functions
898   //
899 
900   /// copy incoming sd instance with options for shallow or deep copies
901   /// of the SurrogateData{Vars,Resp} objects
902   void copy(const SurrogateData& sd, short sdv_mode = DEEP_COPY,
903 	    short sdr_mode = DEEP_COPY) const;
904   /// returns a new SurrogateData instance with options for shallow or
905   /// deep copies of the SurrogateData{Vars,Resp} objects
906   SurrogateData copy(short sdv_mode = DEEP_COPY,
907 		     short sdr_mode = DEEP_COPY) const;
908   /// copy active data for incoming sd instance with options for
909   /// shallow or deep copies of the SurrogateData{Vars,Resp} objects
910   void copy_active(const SurrogateData& sd, short sdv_mode,
911 		   short sdr_mode) const;
912 
913   void size_active_sdv(const SurrogateData& sd) const;
914   void copy_active_sdv(const SurrogateData& sd, short sdv_mode) const;
915   void copy_active_pop_sdv(const SurrogateData& sd, short sdv_mode) const;
916   void size_active_sdr(const SDRArray& sdr_array) const;
917   void size_active_sdr(const SurrogateData& sd) const;
918   void copy_active_sdr(const SurrogateData& sd, short sdr_mode) const;
919   void copy_active_pop_sdr(const SurrogateData& sd, short sdr_mode) const;
920 
921   /// resize {vars,resp}Data
922   void resize(size_t num_pts, short bits, size_t num_vars);
923 
924   /// augment {vars,resp}Data and define anchorIndex
925   void anchor_point(const SurrogateDataVars& sdv, const SurrogateDataResp& sdr);
926   /// set {vars,resp}Data
927   void data_points(const SDVArray& sdv_array, const SDRArray& sdr_array);
928 
929   /// augment varsData and define anchorIndex
930   void anchor_variables(const SurrogateDataVars& sdv);
931   /// get varsData instance corresponding to anchorIndex
932   const SurrogateDataVars& anchor_variables() const;
933   /// augment respData and define anchorIndex
934   void anchor_response(const SurrogateDataResp& sdr);
935   /// get respData instance corresponding to anchorIndex
936   const SurrogateDataResp& anchor_response() const;
937 
938   /// set varsData[activeKey]
939   void variables_data(const SDVArray& sdv_array);
940   /// get varsData[activeKey]
941   const SDVArray& variables_data() const;
942   /// get varsData[key]
943   const SDVArray& variables_data(const UShortArray& key) const;
944   /// get varsData[activeKey]
945   SDVArray& variables_data();
946 
947   /// set respData[activeKey]
948   void response_data(const SDRArray& sdr_array);
949   /// get respData[activeKey]
950   const SDRArray& response_data() const;
951   /// get respData[key]
952   const SDRArray& response_data(const UShortArray& key) const;
953   /// get respData[activeKey]
954   SDRArray& response_data();
955 
956   /// get varsData
957   const std::map<UShortArray, SDVArray>& variables_data_map() const;
958   /// build/return filteredVarsData, pulling aggregated/nonaggregated
959   /// keys from varsData
960   const std::map<UShortArray, SDVArray>&
961     filtered_variables_data_map(short mode) const;
962   /// set varsData
963   void variables_data_map(const std::map<UShortArray, SDVArray>& vars_map);
964 
965   /// get respData
966   const std::map<UShortArray, SDRArray>& response_data_map() const;
967   /// build/return filteredRespData, pulling aggregated/synthetic/raw data
968   /// sets from respData
969   const std::map<UShortArray, SDRArray>&
970     filtered_response_data_map(short mode) const;
971   /// set respData
972   void response_data_map(const std::map<UShortArray, SDRArray>& resp_map);
973 
974   /// return a particular key instance present within the
975   /// aggregated/synthetic/raw data subset (respData is used)
976   const UShortArray& filtered_key(short mode, size_t index) const;
977 
978   /// push sdv onto end of varsData
979   void push_back(const SurrogateDataVars& sdv);
980   /// push sdr onto end of respData
981   void push_back(const SurrogateDataResp& sdr);
982   /// push {sdv,sdr} onto ends of {vars,resp}Data
983   void push_back(const SurrogateDataVars& sdv, const SurrogateDataResp& sdr);
984 
985   /// remove the first entry from {vars,resp}Data, managing anchorIndex
986   /// Note: inefficient for std::vector's, but needed in rare cases.
987   void pop_front(size_t num_pop = 1);
988   /// remove the last entry from {vars,resp}Data, managing anchorIndex
989   void pop_back(size_t num_pop = 1);
990 
991   /// remove num_pop_pts entries from ends of active entry in {vars,resp}Data
992   void pop(bool save_data = true);
993   /// remove num_pop_pts entries from ends of keyed entries in {vars,resp}Data
994   void pop(const UShort2DArray& keys, bool save_data);
995   /// return a previously popped data set (identified by index) to the
996   /// ends of active entry in {vars,resp}Data
997   void push(size_t index, bool erase_popped = true);
998   /// return previously popped data sets (identified by index) to the
999   /// ends of keyed entries in {vars,resp}Data
1000   void push(const UShort2DArray& keys, size_t index, bool erase_popped = true);
1001 
1002   /// append count to popCountStack[activeKey]
1003   void pop_count(size_t count) const;
1004   /// return popCountStack[activeKey].back()
1005   size_t pop_count() const;
1006   /// assign popCountStack[activeKey]
1007   void pop_count_stack(const SizetArray& pop_count) const;
1008   /// return popCountStack[key]
1009   const SizetArray& pop_count_stack(const UShortArray& key) const;
1010   /// return popCountStack[activeKey]
1011   const SizetArray& pop_count_stack() const;
1012   /// assign popCountStack
1013   void pop_count_stack_map(
1014     const std::map<UShortArray, SizetArray>& pcs_map) const;
1015   /// return popCountStack
1016   const std::map<UShortArray, SizetArray>& pop_count_stack_map() const;
1017 
1018   /// pop records from front of {vars,resp}Data to achieve target length,
1019   /// for each key in passed set
1020   void history_target(size_t target, const UShort2DArray& keys);
1021 
1022   /// query presence of anchor indexed within {vars,resp}Data
1023   bool anchor() const;
1024   /// assign anchorIndex[activeKey] to incoming index
1025   void anchor_index(size_t index) const;
1026   /// assign anchorIndex[key] to incoming index
1027   void anchor_index(size_t index, const UShortArray& key) const;
1028   /// return anchorIndex[activeKey], if defined
1029   size_t anchor_index() const;
1030   /// return anchorIndex[key], if defined
1031   size_t anchor_index(const UShortArray& key) const;
1032   /// assign anchorIndex
1033   void anchor_index_map(const std::map<UShortArray, size_t>& ai_map) const;
1034   /// return anchorIndex
1035   const std::map<UShortArray, size_t>& anchor_index_map() const;
1036   /// erase anchorIndex[activeKey]
1037   void clear_anchor_index();
1038   /// erase anchorIndex[key]
1039   void clear_anchor_index(const UShortArray& key);
1040   /// erase anchorIndex for each key within passed set
1041   void clear_anchor_index(const UShort2DArray& keys);
1042 
1043   /// return size of active key within {vars,resp}Data
1044   size_t points() const;
1045   /// return size of {vars,resp}Data instance corresponding to key
1046   size_t points(const UShortArray& key) const;
1047 
1048   /// return total number of available data components
1049   size_t response_size() const;
1050   /// return number of failed data components
1051   size_t failed_response_size() const;
1052   /// return net number of active data components (total minus failed)
1053   size_t active_response_size() const;
1054 
1055   /// return number of 1D arrays within popped{Vars,Resp}Data 2D arrays
1056   /// identified by key
1057   size_t popped_sets(const UShortArray& key) const;
1058   /// return number of 1D arrays within popped{Vars,Resp}Data 2D arrays
1059   /// identified by activeKey
1060   size_t popped_sets() const;
1061 
1062   /// return number of gradient variables from size of gradient arrays
1063   size_t num_gradient_variables() const;
1064   /// return number of Hessian variables from size of Hessian arrays
1065   size_t num_hessian_variables() const;
1066   /// return number of derivative variables as indicated by size of
1067   /// gradient/Hessian arrays
1068   size_t num_derivative_variables() const;
1069 
1070   /// convenience function used by data_checks() for respData
1071   void response_check(const SurrogateDataResp& sdr, short& failed_data) const;
1072   /// screen data sets for samples with Inf/Nan that should be excluded;
1073   /// defines failedRespData
1074   void data_checks() const;
1075   /// return failedRespData corresponding to active anchorIndex
1076   short failed_anchor_data() const;
1077   /// assign active failedRespData
1078   void failed_response_data(const SizetShortMap& fail_data) const;
1079   /// return failedRespData[key]
1080   const SizetShortMap& failed_response_data(const UShortArray& key) const;
1081   /// return failedRespData[activeKey]
1082   const SizetShortMap& failed_response_data() const;
1083 
1084   /// assign activeKey and update active iterators
1085   void active_key(const UShortArray& key) const;
1086   /// return activeKey
1087   const UShortArray& active_key() const;
1088   /// searches for key and updates {vars,resp}DataIter only if found
1089   bool contains(const UShortArray& key);
1090 
1091   /// clear active key within {vars,resp}Data
1092   void clear_active_data();
1093   /// clear a set of keys within {vars,resp}Data
1094   void clear_active_data(const UShort2DArray& keys);
1095   /// clear all inactive data within {vars,resp}Data
1096   void clear_inactive_data();
1097 
1098   /// clear filtered{Vars,Resp}Data (shallow copy subsets of {vars,resp}Data)
1099   void clear_filtered();
1100 
1101   /// clear active key within popped{Vars,Resp}Data
1102   void clear_active_popped();
1103   /// clear a set of keys within popped{Vars,Resp}Data
1104   void clear_active_popped(const UShort2DArray& keys);
1105   /// clear popped{Vars,Resp}Data and restore to initial popped state
1106   void clear_popped();
1107 
1108   /// clear {vars,resp}Data and restore to initial data state
1109   void clear_data(bool initialize = true);
1110 
1111   /// clear all keys for all maps and optionally restore to initial state
1112   void clear_all(bool initialize = true);
1113   /// invokes both clear_active_data() and clear_active_popped()
1114   void clear_all_active();
1115   /// invokes both clear_active_data(keys) and clear_active_popped(keys)
1116   void clear_all_active(const UShort2DArray& keys);
1117 
1118   /// return sdRep
1119   std::shared_ptr<SurrogateDataRep> data_rep() const;
1120 
1121   /// function to check sdRep (does this handle contain a body)
1122   bool is_null() const;
1123 
1124 private:
1125 
1126   //
1127   //- Heading: Member functions
1128   //
1129 
1130   /// define or update anchorIndex[activeKey]
1131   size_t assign_anchor_index();
1132   /// retrieve anchorIndex[activeKey]
1133   size_t retrieve_anchor_index(bool hard_fail = false) const;
1134   /// retrieve anchorIndex[key]
1135   size_t retrieve_anchor_index(const UShortArray& key,
1136 			       bool hard_fail = false) const;
1137 
1138   /// assign sdv within varsData[activeKey] at indicated index
1139   void assign_variables(const SurrogateDataVars& sdv, size_t index);
1140   /// assign sdr within respData[activeKey] at indicated index
1141   void assign_response(const SurrogateDataResp& sdr, size_t index);
1142 
1143   /// set failedRespData
1144   void failed_response_data_map(
1145     const std::map<UShortArray, SizetShortMap>&	fail_resp) const;
1146   /// get failedRespData
1147   const std::map<UShortArray, SizetShortMap>& failed_response_data_map() const;
1148 
1149   /// set active poppedVarsData
1150   void popped_variables(const SDVArrayDeque& popped_vars);
1151   /// get active poppedVarsData
1152   const SDVArrayDeque& popped_variables() const;
1153   /// set active poppedRespData
1154   void popped_response(const SDRArrayDeque& popped_resp);
1155   /// get active poppedRespData
1156   const SDRArrayDeque& popped_response() const;
1157 
1158   /// set poppedVarsData
1159   void popped_variables_map(
1160     const std::map<UShortArray, SDVArrayDeque>& popped_vars);
1161   /// get poppedVarsData
1162   const std::map<UShortArray, SDVArrayDeque>& popped_variables_map() const;
1163   /// set poppedRespData
1164   void popped_response_map(
1165     const std::map<UShortArray, SDRArrayDeque>& popped_resp);
1166   /// get poppedRespData
1167   const std::map<UShortArray, SDRArrayDeque>& popped_response_map() const;
1168 
1169   /// helper function for an individual key
1170   void pop(SDVArray& sdv_array_ref, SDRArray& sdr_array_ref,
1171 	   const UShortArray& key, bool save_data);
1172   /// helper function for an individual key
1173   void push(SDVArray& sdv_array_ref, SDRArray& sdr_array_ref,
1174 	    const UShortArray& key, size_t index, bool erase_popped);
1175 
1176   //
1177   //- Heading: Private data members
1178   //
1179 
1180   /// pointer to the body (handle-body idiom)
1181   std::shared_ptr<SurrogateDataRep> sdRep;
1182 };
1183 
1184 
SurrogateData()1185 inline SurrogateData::SurrogateData()
1186 { }
1187 
1188 
1189 // BMA NOTE: The following don't use make_shared<SurrogateDataRep>()
1190 // due to private ctors
1191 
SurrogateData(bool handle)1192 inline SurrogateData::SurrogateData(bool handle):
1193   sdRep(new SurrogateDataRep())
1194 { sdRep->update_active_iterators(); } // default activeKey is empty array
1195 
1196 
SurrogateData(const UShortArray & key)1197 inline SurrogateData::SurrogateData(const UShortArray& key):
1198   sdRep(new SurrogateDataRep())
1199 { active_key(key); }
1200 
1201 
SurrogateData(const SurrogateData & sd)1202 inline SurrogateData::SurrogateData(const SurrogateData& sd):
1203   sdRep(sd.sdRep)
1204 { }
1205 
1206 
~SurrogateData()1207 inline SurrogateData::~SurrogateData()
1208 { }
1209 
1210 
operator =(const SurrogateData & sd)1211 inline SurrogateData& SurrogateData::operator=(const SurrogateData& sd)
1212 {
1213   sdRep = sd.sdRep;
1214   return *this;
1215 }
1216 
1217 
active_key(const UShortArray & key) const1218 inline void SurrogateData::active_key(const UShortArray& key) const
1219 {
1220   if (sdRep->activeKey != key) {
1221     sdRep->activeKey = key;
1222     sdRep->update_active_iterators();
1223   }
1224 }
1225 
1226 
active_key() const1227 inline const UShortArray& SurrogateData::active_key() const
1228 { return sdRep->activeKey; }
1229 
1230 
contains(const UShortArray & key)1231 inline bool SurrogateData::contains(const UShortArray& key)
1232 {
1233   return (sdRep->varsData.find(key) == sdRep->varsData.end() ||
1234 	  sdRep->respData.find(key) == sdRep->respData.end()) ? false : true;
1235 }
1236 
1237 
1238 inline void SurrogateData::
data_points(const SDVArray & sdv_array,const SDRArray & sdr_array)1239 data_points(const SDVArray& sdv_array, const SDRArray& sdr_array)
1240 {
1241   sdRep->varsDataIter->second = sdv_array;
1242   sdRep->respDataIter->second = sdr_array;
1243 }
1244 
1245 
anchor_index(size_t index) const1246 inline void SurrogateData::anchor_index(size_t index) const
1247 {
1248   std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1249   const UShortArray& key = sdRep->activeKey;
1250   std::map<UShortArray, size_t>::iterator anchor_it = anchor_index.find(key);
1251   if (anchor_it == anchor_index.end()) { // conditionally insert new record
1252     if (index != _NPOS)
1253       anchor_index[key] = index;
1254   }
1255   else // update existing record
1256     anchor_it->second = index;
1257 }
1258 
1259 
1260 inline void SurrogateData::
anchor_index(size_t index,const UShortArray & key) const1261 anchor_index(size_t index, const UShortArray& key) const
1262 {
1263   std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1264   std::map<UShortArray, size_t>::iterator anchor_it = anchor_index.find(key);
1265   if (anchor_it == anchor_index.end()) { // conditionally insert new record
1266     if (index != _NPOS)
1267       anchor_index[key] = index;
1268   }
1269   else // update existing record
1270     anchor_it->second = index;
1271 }
1272 
1273 
anchor_index() const1274 inline size_t SurrogateData::anchor_index() const
1275 { return retrieve_anchor_index(false); }
1276 
1277 
anchor_index(const UShortArray & key) const1278 inline size_t SurrogateData::anchor_index(const UShortArray& key) const
1279 { return retrieve_anchor_index(key, false); }
1280 
1281 
1282 inline const std::map<UShortArray, size_t>& SurrogateData::
anchor_index_map() const1283 anchor_index_map() const
1284 { return sdRep->anchorIndex; }
1285 
1286 
1287 inline void SurrogateData::
anchor_index_map(const std::map<UShortArray,size_t> & ai_map) const1288 anchor_index_map(const std::map<UShortArray, size_t>& ai_map) const
1289 { sdRep->anchorIndex = ai_map; }
1290 
1291 
clear_anchor_index()1292 inline void SurrogateData::clear_anchor_index()
1293 { sdRep->anchorIndex.erase(sdRep->activeKey); }
1294 
1295 
clear_anchor_index(const UShortArray & key)1296 inline void SurrogateData::clear_anchor_index(const UShortArray& key)
1297 { sdRep->anchorIndex.erase(key); }
1298 
1299 
clear_anchor_index(const UShort2DArray & keys)1300 inline void SurrogateData::clear_anchor_index(const UShort2DArray& keys)
1301 {
1302   size_t k, num_k = keys.size();
1303   for (k=0; k<num_k; ++k)
1304     sdRep->anchorIndex.erase(keys[k]);
1305 }
1306 
1307 
assign_anchor_index()1308 inline size_t SurrogateData::assign_anchor_index()
1309 {
1310   // This is often called in sequence of assign_anchor_variables() and
1311   // assign_anchor_response() --> use points() for consistent indexing
1312   size_t index = points(); // push_back() to follow
1313   // This approach reassigns an existing anchor index to freshly appended
1314   // anchor data --> previous anchor data is preserved but demoted
1315   sdRep->anchorIndex[sdRep->activeKey] = index;
1316 
1317   /*
1318   // This approach preserves a previously assigned anchor index, which is good
1319   // for a pair of assign_anchor_{variables,response}() calls, but bad if a
1320   // previous sdv/sdr anchor assignment has not been cleared --> a subsequent
1321   // assign_{variables,response}() will overwrite the previous data, corrupting
1322   // the history for multipoint approximations.
1323   std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1324   const UShortArray& key = sdRep->activeKey;
1325   std::map<UShortArray, size_t>::iterator anchor_it = anchor_index.find(key);
1326   size_t index;
1327   if (anchor_it == anchor_index.end()) // no anchor defined
1328     anchor_index[key] = index = points();
1329   else {
1330     index = anchor_it->second;
1331     if (index == _NPOS) // reassign only if undefined, else preserve
1332       anchor_it->second = index = points();
1333   }
1334   */
1335 
1336   return index;
1337 }
1338 
1339 
retrieve_anchor_index(bool hard_fail) const1340 inline size_t SurrogateData::retrieve_anchor_index(bool hard_fail) const
1341 {
1342   std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1343   std::map<UShortArray, size_t>::iterator anchor_it
1344     = anchor_index.find(sdRep->activeKey);
1345   if (anchor_it == anchor_index.end() || anchor_it->second == _NPOS) {
1346     if (hard_fail) {
1347       PCerr << "Error: lookup failure in SurrogateData::retrieve_anchor_index"
1348 	    << "()." << std::endl;
1349       abort_handler(-1);
1350     }
1351     return _NPOS;
1352   }
1353   else
1354     return anchor_it->second;
1355 }
1356 
1357 
1358 inline size_t SurrogateData::
retrieve_anchor_index(const UShortArray & key,bool hard_fail) const1359 retrieve_anchor_index(const UShortArray& key, bool hard_fail) const
1360 {
1361   std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1362   std::map<UShortArray, size_t>::iterator anchor_it = anchor_index.find(key);
1363   if (anchor_it == anchor_index.end() || anchor_it->second == _NPOS) {
1364     if (hard_fail) {
1365       PCerr << "Error: lookup failure in SurrogateData::retrieve_anchor_index"
1366 	    << "()." << std::endl;
1367       abort_handler(-1);
1368     }
1369     return _NPOS;
1370   }
1371   else
1372     return anchor_it->second;
1373 }
1374 
1375 
1376 inline void SurrogateData::
assign_variables(const SurrogateDataVars & sdv,size_t index)1377 assign_variables(const SurrogateDataVars& sdv, size_t index)
1378 {
1379   SDVArray& sdv_array = sdRep->varsDataIter->second;
1380   if (index == sdv_array.size() || index == _NPOS) sdv_array.push_back(sdv);
1381   else sdv_array[index] = sdv;
1382 }
1383 
1384 
1385 inline void SurrogateData::
assign_response(const SurrogateDataResp & sdr,size_t index)1386 assign_response(const SurrogateDataResp& sdr, size_t index)
1387 {
1388   SDRArray& sdr_array = sdRep->respDataIter->second;
1389   if (index == sdr_array.size() || index == _NPOS) sdr_array.push_back(sdr);
1390   else sdr_array[index] = sdr;
1391 }
1392 
1393 
1394 inline void SurrogateData::
anchor_point(const SurrogateDataVars & sdv,const SurrogateDataResp & sdr)1395 anchor_point(const SurrogateDataVars& sdv, const SurrogateDataResp& sdr)
1396 {
1397   size_t index = assign_anchor_index();
1398   assign_variables(sdv, index);
1399   assign_response(sdr, index);
1400 }
1401 
1402 
anchor_variables(const SurrogateDataVars & sdv)1403 inline void SurrogateData::anchor_variables(const SurrogateDataVars& sdv)
1404 {
1405   size_t index = assign_anchor_index();
1406   assign_variables(sdv, index);
1407 }
1408 
1409 
anchor_variables() const1410 inline const SurrogateDataVars& SurrogateData::anchor_variables() const
1411 {
1412   size_t index = retrieve_anchor_index(true); // abort on index error
1413   return sdRep->varsDataIter->second[index];
1414 }
1415 
1416 
anchor_response(const SurrogateDataResp & sdr)1417 inline void SurrogateData::anchor_response(const SurrogateDataResp& sdr)
1418 {
1419   size_t index = assign_anchor_index();
1420   assign_response(sdr, index);
1421 }
1422 
1423 
anchor_response() const1424 inline const SurrogateDataResp& SurrogateData::anchor_response() const
1425 {
1426   size_t index = retrieve_anchor_index(true); // abort on index error
1427   return sdRep->respDataIter->second[index];
1428 }
1429 
1430 
variables_data(const SDVArray & sdv_array)1431 inline void SurrogateData::variables_data(const SDVArray& sdv_array)
1432 { sdRep->varsDataIter->second = sdv_array; }
1433 
1434 
variables_data() const1435 inline const SDVArray& SurrogateData::variables_data() const
1436 { return sdRep->varsDataIter->second; }
1437 
1438 
1439 inline const SDVArray& SurrogateData::
variables_data(const UShortArray & key) const1440 variables_data(const UShortArray& key) const
1441 { return sdRep->varsData[key]; }
1442 
1443 
variables_data()1444 inline SDVArray& SurrogateData::variables_data()
1445 { return sdRep->varsDataIter->second; }
1446 
1447 
response_data(const SDRArray & sdr_array)1448 inline void SurrogateData::response_data(const SDRArray& sdr_array)
1449 { sdRep->respDataIter->second = sdr_array; }
1450 
1451 
response_data() const1452 inline const SDRArray& SurrogateData::response_data() const
1453 { return sdRep->respDataIter->second; }
1454 
1455 
1456 inline const SDRArray& SurrogateData::
response_data(const UShortArray & key) const1457 response_data(const UShortArray& key) const
1458 { return sdRep->respData[key]; }
1459 
1460 
response_data()1461 inline SDRArray& SurrogateData::response_data()
1462 { return sdRep->respDataIter->second; }
1463 
1464 
1465 inline const std::map<UShortArray, SDVArray>& SurrogateData::
variables_data_map() const1466 variables_data_map() const
1467 { return sdRep->varsData; }
1468 
1469 
1470 inline const std::map<UShortArray, SDVArray>& SurrogateData::
filtered_variables_data_map(short mode) const1471 filtered_variables_data_map(short mode) const
1472 {
1473   const std::map<UShortArray, SDVArray>& vars_map = sdRep->varsData;
1474   std::map<UShortArray, SDVArray>&  filt_vars_map = sdRep->filteredVarsData;
1475   std::map<UShortArray, SDVArray>::const_iterator cit;
1476 
1477   filt_vars_map.clear();
1478   switch (mode) {
1479   case AGGREGATED_DATA_FILTER:
1480     for (cit=vars_map.begin(); cit!=vars_map.end(); ++cit)
1481       if (DiscrepancyCalculator::aggregated_key(cit->first))
1482 	filt_vars_map.insert(*cit);
1483     break;
1484   case SYNTHETIC_DATA_FILTER:
1485     for (cit=vars_map.begin(); cit!=vars_map.end(); ++cit)
1486       if (DiscrepancyCalculator::synthetic_key(cit->first))
1487 	filt_vars_map.insert(*cit);
1488     break;
1489   case RAW_DATA_FILTER:
1490     for (cit=vars_map.begin(); cit!=vars_map.end(); ++cit)
1491       if (DiscrepancyCalculator::raw_data_key(cit->first))
1492 	filt_vars_map.insert(*cit);
1493     break;
1494   case NO_FILTER:
1495     filt_vars_map = vars_map;
1496     break;
1497   }
1498   return filt_vars_map;
1499 }
1500 
1501 
1502 inline void SurrogateData::
variables_data_map(const std::map<UShortArray,SDVArray> & vars_map)1503 variables_data_map(const std::map<UShortArray, SDVArray>& vars_map)
1504 { sdRep->varsData = vars_map; }
1505 
1506 
1507 inline const std::map<UShortArray, SDRArray>& SurrogateData::
response_data_map() const1508 response_data_map() const
1509 { return sdRep->respData; }
1510 
1511 
1512 inline const std::map<UShortArray, SDRArray>& SurrogateData::
filtered_response_data_map(short mode) const1513 filtered_response_data_map(short mode) const
1514 {
1515   const std::map<UShortArray, SDRArray>& resp_map = sdRep->respData;
1516   std::map<UShortArray, SDRArray>&  filt_resp_map = sdRep->filteredRespData;
1517   std::map<UShortArray, SDRArray>::const_iterator cit;
1518 
1519   filt_resp_map.clear();
1520   switch (mode) {
1521   case AGGREGATED_DATA_FILTER:
1522     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit)
1523       if (DiscrepancyCalculator::aggregated_key(cit->first))
1524 	filt_resp_map.insert(*cit);
1525     break;
1526   case SYNTHETIC_DATA_FILTER:
1527     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit)
1528       if (DiscrepancyCalculator::synthetic_key(cit->first))
1529 	filt_resp_map.insert(*cit);
1530     break;
1531   case RAW_DATA_FILTER:
1532     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit)
1533       if (DiscrepancyCalculator::raw_data_key(cit->first))
1534 	filt_resp_map.insert(*cit);
1535     break;
1536   case NO_FILTER:
1537     filt_resp_map = resp_map;
1538     break;
1539   }
1540   return filt_resp_map;
1541 }
1542 
1543 
1544 inline void SurrogateData::
response_data_map(const std::map<UShortArray,SDRArray> & resp_map)1545 response_data_map(const std::map<UShortArray, SDRArray>& resp_map)
1546 { sdRep->respData = resp_map; }
1547 
1548 
1549 inline const UShortArray& SurrogateData::
filtered_key(short mode,size_t index) const1550 filtered_key(short mode, size_t index) const
1551 {
1552   const std::map<UShortArray, SDRArray>& resp_map = sdRep->respData;
1553   std::map<UShortArray, SDRArray>::const_iterator cit;
1554 
1555   size_t cntr = 0;
1556   switch (mode) {
1557   case AGGREGATED_DATA_FILTER:
1558     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit) {
1559       const UShortArray& key = cit->first;
1560       if (DiscrepancyCalculator::aggregated_key(key)) {
1561 	if (cntr == index) return key;
1562 	else               ++cntr;
1563       }
1564     }
1565     break;
1566   case SYNTHETIC_DATA_FILTER:
1567     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit) {
1568       const UShortArray& key = cit->first;
1569       if (DiscrepancyCalculator::synthetic_key(key)) {
1570 	if (cntr == index) return key;
1571 	else               ++cntr;
1572       }
1573     }
1574     break;
1575   case RAW_DATA_FILTER:
1576     for (cit=resp_map.begin(); cit!=resp_map.end(); ++cit) {
1577       const UShortArray& key = cit->first;
1578       if (DiscrepancyCalculator::raw_data_key(key)) {
1579 	if (cntr == index) return key;
1580 	else               ++cntr;
1581       }
1582     }
1583     break;
1584   case NO_FILTER:
1585     cit = resp_map.begin();
1586     std::advance(cit, index);
1587     return cit->first;
1588     break;
1589   }
1590 
1591   PCerr << "Error: index not reached in SurrogateData::filtered_key(mode,index)"
1592 	<< std::endl;
1593   abort_handler(-1);
1594   return resp_map.begin()->first; // dummy return for compiler
1595 }
1596 
1597 
push_back(const SurrogateDataVars & sdv)1598 inline void SurrogateData::push_back(const SurrogateDataVars& sdv)
1599 { sdRep->varsDataIter->second.push_back(sdv); }
1600 
1601 
push_back(const SurrogateDataResp & sdr)1602 inline void SurrogateData::push_back(const SurrogateDataResp& sdr)
1603 { sdRep->respDataIter->second.push_back(sdr); }
1604 
1605 
1606 inline void SurrogateData::
push_back(const SurrogateDataVars & sdv,const SurrogateDataResp & sdr)1607 push_back(const SurrogateDataVars& sdv, const SurrogateDataResp& sdr)
1608 {
1609   sdRep->varsDataIter->second.push_back(sdv);
1610   sdRep->respDataIter->second.push_back(sdr);
1611 }
1612 
1613 
pop_back(size_t num_pop)1614 inline void SurrogateData::pop_back(size_t num_pop)
1615 {
1616   SDVArray& sdv_array = sdRep->varsDataIter->second;
1617   SDRArray& sdr_array = sdRep->respDataIter->second;
1618   size_t len = std::min(sdv_array.size(), sdr_array.size());
1619   if (len < num_pop) {
1620     PCerr << "Error: insufficient size (" << len << ") for pop_back("
1621 	  << num_pop << ")." << std::endl;
1622     abort_handler(-1);
1623   }
1624 
1625   size_t start = len - num_pop;
1626   SDVArray::iterator v_it = sdv_array.begin() + start;
1627   SDRArray::iterator r_it = sdr_array.begin() + start;
1628   sdv_array.erase(v_it, sdv_array.end());
1629   sdr_array.erase(r_it, sdr_array.end());
1630 
1631   if (retrieve_anchor_index() >= start) // popped point was anchor
1632     clear_anchor_index();
1633 }
1634 
1635 
pop_front(size_t num_pop)1636 inline void SurrogateData::pop_front(size_t num_pop)
1637 {
1638   SDVArray& sdv_array = sdRep->varsDataIter->second;
1639   SDRArray& sdr_array = sdRep->respDataIter->second;
1640   size_t len = std::min(sdv_array.size(), sdr_array.size());
1641   if (len < num_pop) {
1642     PCerr << "Error: insufficient size (" << len << ") for pop_front("
1643 	  << num_pop << ")." << std::endl;
1644     abort_handler(-1);
1645   }
1646 
1647   SDVArray::iterator v_it = sdv_array.begin();
1648   SDRArray::iterator r_it = sdr_array.begin();
1649   sdv_array.erase(v_it, v_it + num_pop);
1650   sdr_array.erase(r_it, r_it + num_pop);
1651 
1652   size_t index = retrieve_anchor_index();
1653   if (index < num_pop)     // anchor has been popped
1654     clear_anchor_index();
1655   else if (index != _NPOS) // anchor (still) exists, decrement its index
1656     anchor_index(index - num_pop);
1657 }
1658 
1659 
1660 inline void SurrogateData::
history_target(size_t target,const UShort2DArray & keys)1661 history_target(size_t target, const UShort2DArray& keys)
1662 {
1663   size_t k, num_k = keys.size(), len, num_pops;
1664   SDVArray::iterator v_start, v_end;  SDRArray::iterator r_start, r_end;
1665   for (k=0; k<num_k; ++k) {
1666     const UShortArray& key_k = keys[k];
1667     SDVArray& sdv_array = sdRep->varsData[key_k];
1668     SDRArray& sdr_array = sdRep->respData[key_k];
1669     len = std::min(sdv_array.size(), sdr_array.size());
1670     if (len > target) {
1671       // erase oldest data (pop from front of array)
1672       num_pops  = len - target;
1673       v_start = v_end = sdv_array.begin();  std::advance(v_end, num_pops);
1674       r_start = r_end = sdr_array.begin();  std::advance(r_end, num_pops);
1675       sdv_array.erase(v_start, v_end);      sdr_array.erase(r_start, r_end);
1676 
1677       // Avoid multiple lookups
1678       std::map<UShortArray, size_t>& anchor_index = sdRep->anchorIndex;
1679       std::map<UShortArray, size_t>::iterator anchor_it
1680 	= anchor_index.find(key_k);
1681       if (anchor_it != anchor_index.end() && anchor_it->second != _NPOS) {
1682 	if (anchor_it->second < num_pops) // a popped point was anchor
1683 	  anchor_index.erase(anchor_it);//(key_k);
1684 	else // anchor still exists, decrement its index
1685 	  anchor_it->second -= num_pops;
1686       }
1687       /*
1688       anch_index = retrieve_anchor_index(key_k);
1689       if (anch_index < num_pops)    // a popped point was anchor
1690 	clear_anchor_index(key_k);
1691       else if (anch_index != _NPOS) // anchor still exists, decrement its index
1692 	anchor_index(anch_index - num_pops, key_k);
1693       */
1694     }
1695   }
1696 }
1697 
1698 
1699 inline void SurrogateData::
pop(SDVArray & sdv_array_ref,SDRArray & sdr_array_ref,const UShortArray & key,bool save_data)1700 pop(SDVArray& sdv_array_ref, SDRArray& sdr_array_ref, const UShortArray& key,
1701     bool save_data)
1702 {
1703   size_t num_ref_pts = std::min(sdv_array_ref.size(), sdr_array_ref.size());
1704 
1705   // harden logic for case of an empty SurrogateData (e.g.,
1706   // distinct discrepancy at level 0)
1707   std::map<UShortArray, SizetArray>::iterator it
1708     = sdRep->popCountStack.find(key);
1709   if (it == sdRep->popCountStack.end()) {
1710     if (num_ref_pts == 0)
1711       return; // assume inactive SurrogateData -> ignore pop request
1712     else {
1713       PCerr << "\nError: active count stack not found in SurrogateData::pop() "
1714 	    << "for key:\n" << key << std::flush;
1715       abort_handler(-1);
1716     }
1717   }
1718 
1719   SizetArray& pop_count_stack = it->second;
1720   if (pop_count_stack.empty()) {
1721     PCerr << "\nError: empty count stack in SurrogateData::pop() for key:\n"
1722 	  << key << std::flush;
1723     abort_handler(-1);
1724   }
1725   size_t num_pop_pts = pop_count_stack.back();
1726   if (num_pop_pts) {
1727     if (num_ref_pts < num_pop_pts) {
1728       PCerr << "Error: pop count (" << num_pop_pts << ") exceeds data size ("
1729 	    << num_ref_pts << ") in SurrogateData::pop(size_t) for key:\n"
1730 	    << key << std::flush;
1731       abort_handler(-1);
1732     }
1733     SDVArrayDeque& popped_sdv_arrays = sdRep->poppedVarsData[key];
1734     SDRArrayDeque& popped_sdr_arrays = sdRep->poppedRespData[key];
1735     if (save_data) {
1736       // append empty arrays and then update them in place
1737       popped_sdv_arrays.push_back(SDVArray());
1738       popped_sdr_arrays.push_back(SDRArray());
1739       SDVArray& last_popped_sdv_array = popped_sdv_arrays.back();
1740       SDRArray& last_popped_sdr_array = popped_sdr_arrays.back();
1741       SDVArray::iterator v_end = sdv_array_ref.end();
1742       SDRArray::iterator r_end = sdr_array_ref.end();
1743       last_popped_sdv_array.insert(last_popped_sdv_array.begin(),
1744 				   v_end - num_pop_pts, v_end);
1745       last_popped_sdr_array.insert(last_popped_sdr_array.begin(),
1746 				   r_end - num_pop_pts, r_end);
1747     }
1748     size_t new_size = num_ref_pts - num_pop_pts;
1749     sdv_array_ref.resize(new_size); sdr_array_ref.resize(new_size);
1750 
1751     // TO DO: prune failedRespData[key] or leave in map ?
1752     data_checks(); // from scratch for now...
1753   }
1754   pop_count_stack.pop_back();
1755 }
1756 
1757 
pop(bool save_data)1758 inline void SurrogateData::pop(bool save_data)
1759 {
1760   pop(sdRep->varsDataIter->second, sdRep->respDataIter->second,
1761       sdRep->activeKey, save_data);
1762 }
1763 
1764 
pop(const UShort2DArray & keys,bool save_data)1765 inline void SurrogateData::pop(const UShort2DArray& keys, bool save_data)
1766 {
1767   size_t k, num_k = keys.size();
1768   for (k=0; k<num_k; ++k) {
1769     const UShortArray& key_k = keys[k];
1770     pop(sdRep->varsData[key_k], sdRep->respData[key_k], key_k, save_data);
1771   }
1772 }
1773 
1774 
1775 inline void SurrogateData::
push(SDVArray & sdv_array_ref,SDRArray & sdr_array_ref,const UShortArray & key,size_t index,bool erase_popped)1776 push(SDVArray& sdv_array_ref, SDRArray& sdr_array_ref, const UShortArray& key,
1777      size_t index, bool erase_popped)
1778 {
1779   std::map<UShortArray, SDVArrayDeque>::iterator pvd_it
1780     = sdRep->poppedVarsData.find(key);
1781   std::map<UShortArray, SDRArrayDeque>::iterator prd_it
1782     = sdRep->poppedRespData.find(key);
1783   size_t num_popped
1784     = (pvd_it != sdRep->poppedVarsData.end() &&
1785        prd_it != sdRep->poppedRespData.end()) ?
1786     std::min(pvd_it->second.size(), prd_it->second.size()) : 0;
1787 
1788   // harden logic for case of an empty SurrogateData (e.g.,
1789   // distinct discrepancy at level 0)
1790   if (num_popped > index) {
1791     SDVArrayDeque& popped_sdv_arrays = pvd_it->second;
1792     SDRArrayDeque& popped_sdr_arrays = prd_it->second;
1793     SDVArrayDeque::iterator vit = popped_sdv_arrays.begin();
1794     SDRArrayDeque::iterator rit = popped_sdr_arrays.begin();
1795     std::advance(vit, index); std::advance(rit, index);
1796     size_t num_pts = std::min(vit->size(), rit->size());
1797 
1798     sdv_array_ref.insert(sdv_array_ref.end(), vit->begin(), vit->end());
1799     sdr_array_ref.insert(sdr_array_ref.end(), rit->begin(), rit->end());
1800 
1801     // TO DO: update failedRespData[activeKey] ?
1802     data_checks(); // from scratch for now...
1803 
1804     if (erase_popped)
1805       { popped_sdv_arrays.erase(vit); popped_sdr_arrays.erase(rit); }
1806 
1807     sdRep->popCountStack[key].push_back(num_pts);
1808   }
1809   else if (num_popped) { // not empty
1810     PCerr << "Error: index out of range for active popped arrays in "
1811 	  << "SurrogateData::push()." << std::endl;
1812     abort_handler(-1);
1813   }
1814   // else ignore push request for empty popped (SurrogateData assumed inactive)
1815 }
1816 
1817 
push(size_t index,bool erase_popped)1818 inline void SurrogateData::push(size_t index, bool erase_popped)
1819 {
1820   push(sdRep->varsDataIter->second, sdRep->respDataIter->second,
1821        sdRep->activeKey, index, erase_popped);
1822 }
1823 
1824 
1825 inline void SurrogateData::
push(const UShort2DArray & keys,size_t index,bool erase_popped)1826 push(const UShort2DArray& keys, size_t index, bool erase_popped)
1827 {
1828   size_t k, num_k = keys.size();
1829   for (k=0; k<num_k; ++k) {
1830     const UShortArray& key_k = keys[k];
1831     push(sdRep->varsData[key_k], sdRep->respData[key_k], key_k,
1832 	 index, erase_popped);
1833   }
1834 }
1835 
1836 
pop_count(size_t count) const1837 inline void SurrogateData::pop_count(size_t count) const
1838 { sdRep->popCountStack[sdRep->activeKey].push_back(count); }
1839 
1840 
pop_count() const1841 inline size_t SurrogateData::pop_count() const
1842 {
1843   std::map<UShortArray, SizetArray>::iterator pop_it
1844     = sdRep->popCountStack.find(sdRep->activeKey);
1845   return (pop_it == sdRep->popCountStack.end() || pop_it->second.empty()) ?
1846     _NPOS : pop_it->second.back();
1847 }
1848 
1849 
1850 inline const SizetArray& SurrogateData::
pop_count_stack(const UShortArray & key) const1851 pop_count_stack(const UShortArray& key) const
1852 { return sdRep->popCountStack[key]; }
1853 
1854 
pop_count_stack() const1855 inline const SizetArray& SurrogateData::pop_count_stack() const
1856 { return pop_count_stack(sdRep->activeKey); }
1857 
1858 
pop_count_stack(const SizetArray & pop_count) const1859 inline void SurrogateData::pop_count_stack(const SizetArray& pop_count) const
1860 { sdRep->popCountStack[sdRep->activeKey] = pop_count; }
1861 
1862 
1863 inline void SurrogateData::
pop_count_stack_map(const std::map<UShortArray,SizetArray> & pcs_map) const1864 pop_count_stack_map(const std::map<UShortArray, SizetArray>& pcs_map) const
1865 { sdRep->popCountStack = pcs_map; }
1866 
1867 
1868 inline const std::map<UShortArray, SizetArray>& SurrogateData::
pop_count_stack_map() const1869 pop_count_stack_map() const
1870 { return sdRep->popCountStack; }
1871 
1872 
anchor() const1873 inline bool SurrogateData::anchor() const
1874 {
1875   std::map<UShortArray, size_t>::iterator anchor_it
1876     = sdRep->anchorIndex.find(sdRep->activeKey);
1877   return (anchor_it == sdRep->anchorIndex.end() || anchor_it->second == _NPOS)
1878     ? false : true;
1879 }
1880 
1881 
points() const1882 inline size_t SurrogateData::points() const
1883 {
1884   return std::min(sdRep->varsDataIter->second.size(),
1885 		  sdRep->respDataIter->second.size());
1886 }
1887 
1888 
points(const UShortArray & key) const1889 inline size_t SurrogateData::points(const UShortArray& key) const
1890 {
1891   std::map<UShortArray, SDVArray>::const_iterator sdv_it
1892     = sdRep->varsData.find(key);
1893   std::map<UShortArray, SDRArray>::const_iterator sdr_it
1894     = sdRep->respData.find(key);
1895   return (sdv_it == sdRep->varsData.end() || sdr_it == sdRep->respData.end()) ?
1896     0 : std::min(sdv_it->second.size(), sdr_it->second.size());
1897 }
1898 
1899 
response_size() const1900 inline size_t SurrogateData::response_size() const
1901 {
1902   const SDRArray& sdr_array = sdRep->respDataIter->second;
1903   size_t i, data_size = 0, num_resp = sdr_array.size(), nh;
1904   short active_bits;
1905   for (i=0; i<num_resp; ++i) {
1906     const SurrogateDataResp& sdr = sdr_array[i];
1907     active_bits = sdr.active_bits();
1908     if (active_bits & 1) ++data_size;
1909     if (active_bits & 2) data_size += sdr.response_gradient().length();
1910     if (active_bits & 4) {
1911       nh = sdr.response_hessian().numRows();
1912       if (nh) data_size += nh * (nh + 1) / 2;
1913     }
1914   }
1915   return data_size;
1916 }
1917 
1918 
failed_response_size() const1919 inline size_t SurrogateData::failed_response_size() const
1920 {
1921   const SDRArray& sdr_array = sdRep->respDataIter->second;
1922   size_t failed_size = 0, nh; short fail_bits;
1923   const SizetShortMap& failed_resp = failed_response_data();
1924   for (StShMCIter cit=failed_resp.begin(); cit!=failed_resp.end(); ++cit) {
1925     fail_bits = cit->second;
1926     const SurrogateDataResp& sdr = sdr_array[cit->first];
1927     if (fail_bits & 1) ++failed_size;
1928     if (fail_bits & 2) failed_size += sdr.response_gradient().length();
1929     if (fail_bits & 4) {
1930       nh = sdr.response_hessian().numRows();
1931       if (nh) failed_size += nh * (nh + 1) / 2;
1932     }
1933   }
1934   return failed_size;
1935 }
1936 
1937 
active_response_size() const1938 inline size_t SurrogateData::active_response_size() const
1939 { return response_size() - failed_response_size(); }
1940 
1941 
popped_sets(const UShortArray & key) const1942 inline size_t SurrogateData::popped_sets(const UShortArray& key) const
1943 {
1944   return std::min(sdRep->poppedVarsData[key].size(),
1945 		  sdRep->poppedRespData[key].size());
1946 }
1947 
1948 
popped_sets() const1949 inline size_t SurrogateData::popped_sets() const
1950 { return popped_sets(sdRep->activeKey); }
1951 
1952 
num_gradient_variables() const1953 inline size_t SurrogateData::num_gradient_variables() const
1954 {
1955   const SDRArray& sdr_array = sdRep->respDataIter->second;
1956   return (sdr_array.empty()) ? 0 : sdr_array[0].response_gradient().length();
1957 }
1958 
1959 
num_hessian_variables() const1960 inline size_t SurrogateData::num_hessian_variables() const
1961 {
1962   const SDRArray& sdr_array = sdRep->respDataIter->second;
1963   return (sdr_array.empty()) ? 0 : sdr_array[0].response_hessian().numRows();
1964 }
1965 
1966 
num_derivative_variables() const1967 inline size_t SurrogateData::num_derivative_variables() const
1968 {
1969   size_t num_grad_vars = num_gradient_variables();
1970   if (num_grad_vars) return num_grad_vars;           // precedence
1971   else               return num_hessian_variables(); // fall-back
1972 }
1973 
1974 
1975 inline void SurrogateData::
response_check(const SurrogateDataResp & sdr,short & failed_data) const1976 response_check(const SurrogateDataResp& sdr, short& failed_data) const
1977 {
1978   // We take a conservative approach of rejecting all data of derivative
1979   // order greater than or equal to a detected failure:
1980 
1981   short resp_bits = sdr.active_bits();
1982   failed_data = 0;
1983   if (resp_bits & 1) {
1984     if (!boost::math::isfinite<Real>(sdr.response_function()))
1985       failed_data = resp_bits;       // all data for this & higher deriv orders
1986   }
1987   if ( (resp_bits & 2) && !failed_data ) {
1988     const RealVector& grad = sdr.response_gradient();
1989     size_t j, num_deriv_vars = grad.length();
1990     for (j=0; j<num_deriv_vars; ++j)
1991       if (!boost::math::isfinite<Real>(grad[j]))
1992 	{ failed_data = (resp_bits & 6); break; } // this & higher deriv orders
1993   }
1994   if ( (resp_bits & 4) && !failed_data ) {
1995     const RealSymMatrix& hess = sdr.response_hessian();
1996     size_t j, k, num_deriv_vars = hess.numRows();
1997     for (j=0; j<num_deriv_vars; ++j)
1998       for (k=0; k<=j; ++k)
1999 	if (!boost::math::isfinite<Real>(hess(j,k)))
2000 	  { failed_data = 4; break; }             // this & higher deriv orders
2001   }
2002 }
2003 
2004 
data_checks() const2005 inline void SurrogateData::data_checks() const
2006 {
2007   const SDRArray&  resp_data = sdRep->respDataIter->second;
2008   SizetShortMap& failed_resp = sdRep->failedRespData[sdRep->activeKey];
2009   failed_resp.clear();
2010   size_t i, num_resp = resp_data.size();  short failed_data;
2011   for (i=0; i<num_resp; ++i) {
2012     response_check(resp_data[i], failed_data);
2013     if (failed_data)
2014       failed_resp[i] = failed_data; // include in map
2015   }
2016 
2017 #ifdef DEBUG
2018   PCout << "failedRespData:\n";
2019   for (SizetShortMap::iterator it=failed_resp.begin();
2020        it!=failed_resp.end(); ++it)
2021     PCout << "index: " << std::setw(6) << it->first
2022 	  << " data: " << it->second << '\n';
2023 #endif // DEBUG
2024 }
2025 
2026 
failed_anchor_data() const2027 inline short SurrogateData::failed_anchor_data() const
2028 {
2029   std::map<UShortArray, SizetShortMap>::const_iterator cit1
2030     = sdRep->failedRespData.find(sdRep->activeKey);
2031   if (cit1 == sdRep->failedRespData.end()) return 0;
2032   else {
2033     const SizetShortMap& failed_resp_data = cit1->second;
2034     SizetShortMap::const_iterator cit2 = failed_resp_data.find(anchor_index());
2035     return (cit2 == failed_resp_data.end()) ? 0 : cit2->second;
2036   }
2037 }
2038 
2039 
2040 inline void SurrogateData::
failed_response_data(const SizetShortMap & fail_data) const2041 failed_response_data(const SizetShortMap& fail_data) const
2042 { sdRep->failedRespData[sdRep->activeKey] = fail_data; }
2043 
2044 
2045 inline const SizetShortMap& SurrogateData::
failed_response_data(const UShortArray & key) const2046 failed_response_data(const UShortArray& key) const
2047 { return sdRep->failedRespData[key]; }
2048 
2049 
failed_response_data() const2050 inline const SizetShortMap& SurrogateData::failed_response_data() const
2051 { return failed_response_data(sdRep->activeKey); }
2052 
2053 
2054 inline void SurrogateData::
failed_response_data_map(const std::map<UShortArray,SizetShortMap> & fail_resp) const2055 failed_response_data_map(const std::map<UShortArray, SizetShortMap>& fail_resp)
2056   const
2057 { sdRep->failedRespData = fail_resp; }
2058 
2059 
2060 inline const std::map<UShortArray, SizetShortMap>& SurrogateData::
failed_response_data_map() const2061 failed_response_data_map() const
2062 { return sdRep->failedRespData; }
2063 
2064 
popped_variables() const2065 inline const SDVArrayDeque& SurrogateData::popped_variables() const
2066 {
2067   std::map<UShortArray, SDVArrayDeque>& pop_vars = sdRep->poppedVarsData;
2068   const UShortArray& key = sdRep->activeKey;
2069   std::map<UShortArray, SDVArrayDeque>::iterator cit = pop_vars.find(key);
2070   if (cit == pop_vars.end()) {
2071     std::pair<UShortArray, SDVArrayDeque> sdv_pair(key, SDVArrayDeque());
2072     cit = pop_vars.insert(sdv_pair).first; // create empty array for key
2073   }
2074   return cit->second;
2075 }
2076 
2077 
popped_variables(const SDVArrayDeque & popped_vars)2078 inline void SurrogateData::popped_variables(const SDVArrayDeque& popped_vars)
2079 { sdRep->poppedVarsData[sdRep->activeKey] = popped_vars; }
2080 
2081 
popped_response() const2082 inline const SDRArrayDeque& SurrogateData::popped_response() const
2083 {
2084   std::map<UShortArray, SDRArrayDeque>& pop_resp = sdRep->poppedRespData;
2085   const UShortArray& key = sdRep->activeKey;
2086   std::map<UShortArray, SDRArrayDeque>::iterator cit = pop_resp.find(key);
2087   if (cit == pop_resp.end()) {
2088     std::pair<UShortArray, SDRArrayDeque> sdr_pair(key, SDRArrayDeque());
2089     cit = pop_resp.insert(sdr_pair).first; // create empty array for key
2090   }
2091   return cit->second;
2092 }
2093 
2094 
2095 inline void SurrogateData::
popped_response(const SDRArrayDeque & popped_resp)2096 popped_response(const SDRArrayDeque& popped_resp)
2097 { sdRep->poppedRespData[sdRep->activeKey] = popped_resp; }
2098 
2099 
2100 inline const std::map<UShortArray, SDVArrayDeque>& SurrogateData::
popped_variables_map() const2101 popped_variables_map() const
2102 { return sdRep->poppedVarsData; }
2103 
2104 
2105 inline void SurrogateData::
popped_variables_map(const std::map<UShortArray,SDVArrayDeque> & popped_vars)2106 popped_variables_map(const std::map<UShortArray, SDVArrayDeque>& popped_vars)
2107 { sdRep->poppedVarsData = popped_vars; }
2108 
2109 
2110 inline const std::map<UShortArray, SDRArrayDeque>& SurrogateData::
popped_response_map() const2111 popped_response_map() const
2112 { return sdRep->poppedRespData; }
2113 
2114 
2115 inline void SurrogateData::
popped_response_map(const std::map<UShortArray,SDRArrayDeque> & popped_resp)2116 popped_response_map(const std::map<UShortArray, SDRArrayDeque>& popped_resp)
2117 { sdRep->poppedRespData = popped_resp; }
2118 
2119 
2120 inline void SurrogateData::
copy(const SurrogateData & sd,short sdv_mode,short sdr_mode) const2121 copy(const SurrogateData& sd, short sdv_mode, short sdr_mode) const
2122 {
2123   if (sdv_mode == DEEP_COPY) {
2124     size_t i, j, num_pts, num_sdva;
2125     const std::map<UShortArray, SDVArray>& vars_map = sd.variables_data_map();
2126     std::map<UShortArray, SDVArray>::const_iterator v_cit;
2127     std::map<UShortArray, SDVArray>& new_vars_map = sdRep->varsData;
2128     new_vars_map.clear();
2129     for (v_cit = vars_map.begin(); v_cit != vars_map.end(); ++v_cit) {
2130       const SDVArray& sdv_array = v_cit->second;
2131       num_pts = sdv_array.size();
2132       SDVArray new_sdv_array(num_pts);
2133       for (i=0; i<num_pts; ++i)
2134 	new_sdv_array[i] = sdv_array[i].copy();
2135       new_vars_map[v_cit->first] = sdv_array;
2136     }
2137 
2138     const std::map<UShortArray, SDVArrayDeque>& popped_vars_map
2139       = sd.popped_variables_map();
2140     std::map<UShortArray, SDVArrayDeque>::const_iterator v2_cit;
2141     std::map<UShortArray, SDVArrayDeque>& new_popped_vars_map
2142       = sdRep->poppedVarsData;
2143     new_popped_vars_map.clear();
2144     for (v2_cit = popped_vars_map.begin(); v2_cit != popped_vars_map.end();
2145 	 ++v2_cit) {
2146       const SDVArrayDeque& sdv_2d_array = v2_cit->second;
2147       num_sdva = sdv_2d_array.size();
2148       SDVArrayDeque new_popped_sdv_2d(num_sdva);
2149       for (i=0; i<num_sdva; ++i) {
2150 	const SDVArray& sdva_i = sdv_2d_array[i];
2151 	num_pts = sdva_i.size();
2152 	new_popped_sdv_2d[i].resize(num_pts);
2153 	for (j=0; j<num_pts; ++j)
2154 	  new_popped_sdv_2d[i][j] = sdva_i[j].copy();
2155       }
2156       new_popped_vars_map[v2_cit->first] = new_popped_sdv_2d;
2157     }
2158   }
2159   else { // shallow SDV copies based on operator=
2160     sdRep->varsData       = sd.variables_data_map();
2161     sdRep->poppedVarsData = sd.popped_variables_map();
2162   }
2163 
2164   if (sdr_mode == DEEP_COPY) {
2165     size_t i, j, num_pts, num_sdra;
2166     const std::map<UShortArray, SDRArray>& resp_map = sd.response_data_map();
2167     std::map<UShortArray, SDRArray>::const_iterator r_cit;
2168     std::map<UShortArray, SDRArray>& new_resp_map = sdRep->respData;
2169     new_resp_map.clear();
2170     for (r_cit = resp_map.begin(); r_cit != resp_map.end(); ++r_cit) {
2171       const SDRArray& sdr_array = r_cit->second;
2172       num_pts = sdr_array.size();
2173       SDRArray new_sdr_array(num_pts);
2174       for (i=0; i<num_pts; ++i)
2175 	new_sdr_array[i] = sdr_array[i].copy();
2176       new_resp_map[r_cit->first] = new_sdr_array;
2177     }
2178 
2179     const std::map<UShortArray, SDRArrayDeque>& popped_resp_map
2180       = sd.popped_response_map();
2181     std::map<UShortArray, SDRArrayDeque>::const_iterator r2_cit;
2182     std::map<UShortArray, SDRArrayDeque>& new_popped_resp_map
2183       = sdRep->poppedRespData;
2184     new_popped_resp_map.clear();
2185     for (r2_cit = popped_resp_map.begin(); r2_cit != popped_resp_map.end();
2186 	 ++r2_cit) {
2187       const SDRArrayDeque& sdr_2d_array = r2_cit->second;
2188       num_sdra = sdr_2d_array.size();
2189       SDRArrayDeque new_popped_sdr_2d(num_sdra);
2190       for (i=0; i<num_sdra; ++i) {
2191 	const SDRArray& sdra_i = sdr_2d_array[i];
2192 	num_pts = sdra_i.size();
2193 	new_popped_sdr_2d[i].resize(num_pts);
2194 	for (j=0; j<num_pts; ++j)
2195 	  new_popped_sdr_2d[i][j] = sdra_i[j].copy();
2196       }
2197       new_popped_resp_map[r2_cit->first] = new_popped_sdr_2d;
2198     }
2199   }
2200   else { // shallow SDR copies based on operator=
2201     sdRep->respData       = sd.response_data_map();
2202     sdRep->poppedRespData = sd.popped_response_map();
2203   }
2204 
2205   active_key(sd.active_key());
2206   pop_count_stack_map(sd.pop_count_stack_map());
2207   anchor_index_map(sd.anchor_index_map());
2208   failed_response_data_map(sd.failed_response_data_map());
2209 }
2210 
2211 
copy(short sdv_mode,short sdr_mode) const2212 inline SurrogateData SurrogateData::copy(short sdv_mode, short sdr_mode) const
2213 {
2214   SurrogateData sd;
2215   sd.copy(*this, sdv_mode, sdr_mode);
2216   return sd;
2217 }
2218 
2219 
2220 inline void SurrogateData::
copy_active(const SurrogateData & sd,short sdv_mode,short sdr_mode) const2221 copy_active(const SurrogateData& sd, short sdv_mode, short sdr_mode) const
2222 {
2223   const UShortArray& key = sd.active_key();
2224   if (sdRep->activeKey != key) active_key(key);
2225   copy_active_sdv(sd, sdv_mode);
2226   copy_active_pop_sdv(sd, sdv_mode);
2227   copy_active_sdr(sd, sdr_mode);
2228   copy_active_pop_sdr(sd, sdr_mode);
2229 
2230   // deep copies of bookkeeping arrays
2231   anchor_index(sd.anchor_index());
2232   pop_count_stack(sd.pop_count_stack());
2233   failed_response_data(sd.failed_response_data());
2234 }
2235 
2236 
size_active_sdv(const SurrogateData & sd) const2237 inline void SurrogateData::size_active_sdv(const SurrogateData& sd) const
2238 {
2239   const UShortArray& key = sd.active_key();
2240   if (sdRep->activeKey != key) active_key(key);
2241 
2242   const SDVArray& sdv_array = sd.variables_data();
2243   size_t num_pts = sdv_array.size();
2244   if (num_pts) {
2245     const SurrogateDataVars& sdv0 = sdv_array[0];
2246     size_t i, num_cv = sdv0.cv(), num_div = sdv0.div(), num_drv = sdv0.drv();
2247     SDVArray& new_sdv_array = sdRep->varsDataIter->second;
2248     new_sdv_array.resize(num_pts);
2249     for (i=0; i<num_pts; ++i)
2250       new_sdv_array[i] = SurrogateDataVars(num_cv, num_div, num_drv);
2251   }
2252 }
2253 
2254 
2255 inline void SurrogateData::
copy_active_sdv(const SurrogateData & sd,short sdv_mode) const2256 copy_active_sdv(const SurrogateData& sd, short sdv_mode) const
2257 {
2258   const UShortArray& key = sd.active_key();
2259   if (sdRep->activeKey != key) active_key(key);
2260 
2261   SDVArray& new_sdv_array = sdRep->varsDataIter->second;
2262   if (sdv_mode == DEEP_COPY) {
2263     const SDVArray& sdv_array = sd.variables_data();
2264     size_t i, num_pts = sdv_array.size();
2265     new_sdv_array.resize(num_pts);
2266     for (i=0; i<num_pts; ++i)
2267       new_sdv_array[i] = sdv_array[i].copy();
2268   }
2269   else // shallow SDV copies based on operator=
2270     new_sdv_array = sd.variables_data();
2271 }
2272 
2273 
2274 inline void SurrogateData::
copy_active_pop_sdv(const SurrogateData & sd,short sdv_mode) const2275 copy_active_pop_sdv(const SurrogateData& sd, short sdv_mode) const
2276 {
2277   const UShortArray& key = sd.active_key();
2278   if (sdRep->activeKey != key) active_key(key);
2279 
2280   SDVArrayDeque& new_pop_sdv_array = sdRep->poppedVarsData[key];
2281   if (sdv_mode == DEEP_COPY) {
2282     const SDVArrayDeque& pop_sdv_array = sd.popped_variables();
2283     size_t i, j, num_pts, num_sdva = pop_sdv_array.size();
2284     new_pop_sdv_array.resize(num_sdva);
2285     for (i=0; i<num_sdva; ++i) {
2286       const SDVArray& sdva_i = pop_sdv_array[i];
2287       num_pts = sdva_i.size();
2288       new_pop_sdv_array[i].resize(num_pts);
2289       for (j=0; j<num_pts; ++j)
2290 	new_pop_sdv_array[i][j] = sdva_i[j].copy();
2291     }
2292   }
2293   else // shallow SDV copies based on operator=
2294     new_pop_sdv_array = sd.popped_variables();
2295 }
2296 
2297 
size_active_sdr(const SDRArray & sdr_array) const2298 inline void SurrogateData::size_active_sdr(const SDRArray& sdr_array) const
2299 {
2300   size_t num_pts = sdr_array.size();
2301   SDRArray& new_sdr_array = sdRep->respDataIter->second;
2302   new_sdr_array.resize(num_pts);
2303   if (num_pts) {
2304     const SurrogateDataResp& sdr0 = sdr_array[0];
2305     short bits = sdr0.active_bits(); // assume homogeneity in deriv data
2306     size_t i, num_deriv_v = sdr0.derivative_variables();
2307     for (i=0; i<num_pts; ++i)
2308       new_sdr_array[i] = SurrogateDataResp(bits, num_deriv_v);
2309   }
2310 }
2311 
2312 
size_active_sdr(const SurrogateData & sd) const2313 inline void SurrogateData::size_active_sdr(const SurrogateData& sd) const
2314 {
2315   const UShortArray& key = sd.active_key();
2316   if (sdRep->activeKey != key) active_key(key);
2317   size_active_sdr(sd.response_data());
2318 }
2319 
2320 
2321 inline void SurrogateData::
copy_active_sdr(const SurrogateData & sd,short sdr_mode) const2322 copy_active_sdr(const SurrogateData& sd, short sdr_mode) const
2323 {
2324   const UShortArray& key = sd.active_key();
2325   if (sdRep->activeKey != key) active_key(key);
2326 
2327   SDRArray& new_sdr_array = sdRep->respDataIter->second;
2328   if (sdr_mode == DEEP_COPY) {
2329     const SDRArray& sdr_array = sd.response_data();
2330     size_t i, num_pts = sdr_array.size();
2331     new_sdr_array.resize(num_pts);
2332     for (i=0; i<num_pts; ++i)
2333       new_sdr_array[i] = sdr_array[i].copy();
2334   }
2335   else // shallow SDR copies based on operator=
2336     new_sdr_array = sd.response_data();
2337 }
2338 
2339 
2340 inline void SurrogateData::
copy_active_pop_sdr(const SurrogateData & sd,short sdr_mode) const2341 copy_active_pop_sdr(const SurrogateData& sd, short sdr_mode) const
2342 {
2343   const UShortArray& key = sd.active_key();
2344   if (sdRep->activeKey != key) active_key(key);
2345 
2346   SDRArrayDeque& new_pop_sdr_array = sdRep->poppedRespData[key];
2347   if (sdr_mode == DEEP_COPY) {
2348     const SDRArrayDeque& pop_sdr_array = sd.popped_response();
2349     size_t i, j, num_pts, num_sdra = pop_sdr_array.size();
2350     new_pop_sdr_array.resize(num_sdra);
2351     for (i=0; i<num_sdra; ++i) {
2352       const SDRArray& sdra_i = pop_sdr_array[i];
2353       num_pts = sdra_i.size();
2354       new_pop_sdr_array[i].resize(num_pts);
2355       for (j=0; j<num_pts; ++j)
2356 	new_pop_sdr_array[i][j] = sdra_i[j].copy();
2357     }
2358   }
2359   else // shallow SDR copies based on operator=
2360     new_pop_sdr_array = sd.popped_response();
2361 }
2362 
2363 
resize(size_t new_pts,short bits,size_t num_vars)2364 inline void SurrogateData::resize(size_t new_pts, short bits, size_t num_vars)
2365 {
2366   size_t i, pts = points();
2367   SDVArray& sdv_array = sdRep->varsDataIter->second;
2368   SDRArray& sdr_array = sdRep->respDataIter->second;
2369 
2370   sdv_array.resize(new_pts);  sdr_array.resize(new_pts);
2371   for (i=pts; i<new_pts; ++i) {
2372     // minimal ctors that define a rep and size arrays
2373     sdv_array[i].create_rep(num_vars);
2374     sdr_array[i].create_rep(bits, num_vars);
2375   }
2376 }
2377 
2378 
clear_active_data()2379 inline void SurrogateData::clear_active_data()
2380 {
2381   /*
2382   // Too aggressive due to DataFitSurrModel::build_approximation() call to
2383   // approxInterface.clear_current_active_data();
2384   const UShortArray& key = sdRep->activeKey;
2385   sdRep->varsData.erase(key);
2386   sdRep->varsDataIter = sdRep->varsData.end();
2387   sdRep->respData.erase(key);
2388   sdRep->respDataIter = sdRep->respData.end();
2389   sdRep->anchorIndex.erase(key);
2390   sdRep->failedRespData.erase(key);
2391   */
2392 
2393   // Retain valid {vars,Resp}DataIter when clearing {vars,resp}Data:
2394   sdRep->varsDataIter->second.clear();
2395   sdRep->respDataIter->second.clear();
2396   // anchorIndex and failedRespData can be pruned:
2397   const UShortArray& key = sdRep->activeKey;
2398   sdRep->anchorIndex.erase(key);   //sdRep->anchorIndex[key] = _NPOS;
2399   sdRep->failedRespData.erase(key);//sdRep->failedRespData[key].clear();
2400 }
2401 
2402 
clear_active_data(const UShort2DArray & keys)2403 inline void SurrogateData::clear_active_data(const UShort2DArray& keys)
2404 {
2405   // clear each passed key without disturbing the active key
2406   size_t k, num_k = keys.size();
2407   for (k=0; k<num_k; ++k) {
2408     const UShortArray& key_k = keys[k];
2409     // clear instead of erase
2410     sdRep->varsData[key_k].clear();
2411     sdRep->respData[key_k].clear();
2412     // can erase
2413     sdRep->anchorIndex.erase(key_k);
2414     sdRep->failedRespData.erase(key_k);
2415   }
2416 }
2417 
2418 
clear_inactive_data()2419 inline void SurrogateData::clear_inactive_data()
2420 {
2421   std::map<UShortArray, SDVArray>::iterator vd_it = sdRep->varsData.begin();
2422   std::map<UShortArray, SDRArray>::iterator rd_it = sdRep->respData.begin();
2423   while (vd_it != sdRep->varsData.end())
2424     if (vd_it == sdRep->varsDataIter) // preserve active
2425       { ++vd_it; ++rd_it; }
2426     else {                            //  clear inactive
2427       const UShortArray& key = vd_it->first;
2428       // anchorIndex and failedRespData can be pruned:
2429       sdRep->anchorIndex.erase(key);    // if it exists
2430       sdRep->failedRespData.erase(key); // if it exists
2431       // Be more conservative with clearing {vars,resp}Data:
2432       vd_it->second.clear(); ++vd_it;
2433       rd_it->second.clear(); ++rd_it;
2434       // Too aggressive. Note: postfix increments manage iterator invalidations
2435       //sdRep->varsData.erase(vd_it++); sdRep->respData.erase(rd_it++);
2436     }
2437 }
2438 
2439 
clear_filtered()2440 inline void SurrogateData::clear_filtered()
2441 {
2442   sdRep->filteredVarsData.clear();
2443   sdRep->filteredRespData.clear();
2444 }
2445 
2446 
clear_active_popped()2447 inline void SurrogateData::clear_active_popped()
2448 {
2449   const UShortArray& key = sdRep->activeKey;
2450   // can erase as will be recreated in pop() if needed:
2451   sdRep->poppedVarsData.erase(key);//sdRep->poppedVarsData[key].clear();
2452   sdRep->poppedRespData.erase(key);//sdRep->poppedRespData[key].clear();
2453   sdRep->popCountStack.erase(key); //sdRep->popCountStack[key].clear();
2454 }
2455 
2456 
clear_active_popped(const UShort2DArray & keys)2457 inline void SurrogateData::clear_active_popped(const UShort2DArray& keys)
2458 {
2459   // clear each passed key without disturbing the active key
2460   size_t k, num_k = keys.size();
2461   for (k=0; k<num_k; ++k) {
2462     const UShortArray& key_k = keys[k];
2463     // can erase as will be recreated in pop() if needed
2464     sdRep->poppedVarsData.erase(key_k);
2465     sdRep->poppedRespData.erase(key_k);
2466     sdRep->popCountStack.erase(key_k);
2467   }
2468 }
2469 
2470 
clear_popped()2471 inline void SurrogateData::clear_popped()
2472 {
2473   sdRep->poppedVarsData.clear();
2474   sdRep->poppedRespData.clear();
2475   sdRep->popCountStack.clear();
2476 }
2477 
2478 
clear_data(bool initialize)2479 inline void SurrogateData::clear_data(bool initialize)
2480 {
2481   sdRep->varsData.clear();
2482   sdRep->respData.clear();
2483   clear_filtered();
2484 
2485   sdRep->anchorIndex.clear();
2486   sdRep->failedRespData.clear();
2487 
2488   if (initialize) // preserve activeKey and restore to initialization state
2489     sdRep->update_active_iterators();
2490   else {
2491     sdRep->activeKey.clear();
2492     sdRep->varsDataIter = sdRep->varsData.end();
2493     sdRep->respDataIter = sdRep->respData.end();
2494   }
2495 }
2496 
2497 
clear_all(bool initialize)2498 inline void SurrogateData::clear_all(bool initialize)
2499 { clear_data(initialize); clear_popped(); }
2500 
2501 
clear_all_active()2502 inline void SurrogateData::clear_all_active()
2503 { clear_active_data(); clear_active_popped(); }
2504 
2505 
clear_all_active(const UShort2DArray & keys)2506 inline void SurrogateData::clear_all_active(const UShort2DArray& keys)
2507 { clear_active_data(keys); clear_active_popped(keys); }
2508 
2509 
data_rep() const2510 inline std::shared_ptr<SurrogateDataRep> SurrogateData::data_rep() const
2511 { return sdRep; }
2512 
2513 
is_null() const2514 inline bool SurrogateData::is_null() const
2515 { return (sdRep) ? false : true; }
2516 
2517 } // namespace Pecos
2518 
2519 #endif
2520