1 /* _______________________________________________________________________
2
3 DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
4 Copyright 2014-2020 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Dakota directory.
7 _______________________________________________________________________ */
8
9 //- Class: NonDSampling
10 //- Description: Implementation code for NonDSampling class
11 //- Owner: Mike Eldred
12 //- Checked by:
13 //- Version:
14
15 #include "dakota_data_types.hpp"
16 #include "dakota_system_defs.hpp"
17 #include "DakotaModel.hpp"
18 #include "DakotaResponse.hpp"
19 #include "NonDSampling.hpp"
20 #include "ProblemDescDB.hpp"
21 #include "SensAnalysisGlobal.hpp"
22 #include "ProbabilityTransformation.hpp"
23 #include "dakota_stat_util.hpp"
24 #include "pecos_data_types.hpp"
25 #include "NormalRandomVariable.hpp"
26 #include <algorithm>
27
28 #include <boost/math/special_functions/beta.hpp>
29
30 static const char rcsId[]="@(#) $Id: NonDSampling.cpp 7036 2010-10-22 23:20:24Z mseldre $";
31
32
33 namespace Dakota {
34
35
36 /** This constructor is called for a standard letter-envelope iterator
37 instantiation. In this case, set_db_list_nodes has been called and
38 probDescDB can be queried for settings from the method specification. */
NonDSampling(ProblemDescDB & problem_db,Model & model)39 NonDSampling::NonDSampling(ProblemDescDB& problem_db, Model& model):
40 NonD(problem_db, model), seedSpec(probDescDB.get_int("method.random_seed")),
41 randomSeed(seedSpec), samplesSpec(probDescDB.get_int("method.samples")),
42 samplesRef(samplesSpec), numSamples(samplesSpec),
43 rngName(probDescDB.get_string("method.random_number_generator")),
44 sampleType(probDescDB.get_ushort("method.sample_type")), samplesIncrement(0),
45 statsFlag(true), allDataFlag(false), samplingVarsMode(ACTIVE),
46 sampleRanksMode(IGNORE_RANKS),
47 varyPattern(!probDescDB.get_bool("method.fixed_seed")),
48 backfillFlag(probDescDB.get_bool("method.backfill")),
49 wilksFlag(probDescDB.get_bool("method.wilks")), numLHSRuns(0)
50 {
51 // pushed down as some derived classes (MLMC) use a MC default
52 //if (!sampleType)
53 // sampleType = SUBMETHOD_LHS;
54
55 if (epistemicStats && totalLevelRequests) {
56 Cerr << "\nError: sampling does not support level requests for "
57 << "analyses containing epistemic uncertainties." << std::endl;
58 abort_handler(METHOD_ERROR);
59 }
60
61 // initialize finalStatistics using the default statistics set
62 initialize_final_statistics();
63
64 if ( wilksFlag ) {
65 // Only works with sample_type of random
66 // BMA: consider relaxing, despite no theory
67 if ( sampleType != SUBMETHOD_RANDOM ) {
68 Cerr << "Error: Wilks sample sizes require use of \"random\" sample_type."
69 << std::endl;
70 abort_handler(METHOD_ERROR);
71 }
72
73 // Check for conflicting samples spec. Note that this still allows
74 // a user to specify "samples = 0" alongside wilks
75 if ( numSamples > 0 ) {
76 Cerr << "Error: Cannot specify both \"samples\" and \"wilks\"."
77 << std::endl;
78 abort_handler(METHOD_ERROR);
79 }
80
81 // Wilks order statistics
82 wilksOrder = probDescDB.get_ushort("method.order");
83 // Wilks interval sidedness
84 wilksSidedness = probDescDB.get_short("method.wilks.sided_interval");
85 bool wilks_twosided = (wilksSidedness == TWO_SIDED);
86
87 // Support multiple probability_levels
88 Real max_prob_level = 0.0;
89 for (size_t i=0; i<numFunctions; ++i) {
90 size_t pl_len = requestedProbLevels[i].length();
91 for (size_t j=0; j<pl_len; ++j) {
92 if (requestedProbLevels[i][j] > max_prob_level)
93 max_prob_level = requestedProbLevels[i][j] ;
94 }
95 }
96 wilksAlpha = max_prob_level;
97 if (wilksAlpha <= 0.0) // Assign a default if probability_levels unspecified
98 wilksAlpha = 0.95;
99
100 wilksBeta = probDescDB.get_real("method.confidence_level");
101 if (wilksBeta <= 0.0) // Assign a default if probability_levels unspecified
102 wilksBeta = 0.95;
103 numSamples = compute_wilks_sample_size(wilksOrder, wilksAlpha,
104 wilksBeta, wilks_twosided);
105 samplesRef = numSamples;
106 }
107
108 // update concurrency
109 if (numSamples) // samples is optional (default = 0)
110 maxEvalConcurrency *= numSamples;
111 }
112
113
114 /** This alternate constructor is used for generation and evaluation
115 of on-the-fly sample sets. */
116 NonDSampling::
NonDSampling(unsigned short method_name,Model & model,unsigned short sample_type,int samples,int seed,const String & rng,bool vary_pattern,short sampling_vars_mode)117 NonDSampling(unsigned short method_name, Model& model,
118 unsigned short sample_type, int samples, int seed,
119 const String& rng, bool vary_pattern, short sampling_vars_mode):
120 NonD(method_name, model), seedSpec(seed), randomSeed(seed),
121 samplesSpec(samples), samplesRef(samples), numSamples(samples), rngName(rng),
122 sampleType(sample_type), wilksFlag(false), samplesIncrement(0),
123 statsFlag(false), allDataFlag(true), samplingVarsMode(sampling_vars_mode),
124 sampleRanksMode(IGNORE_RANKS), varyPattern(vary_pattern), backfillFlag(false),
125 numLHSRuns(0)
126 {
127 subIteratorFlag = true; // suppress some output
128
129 // override default epistemicStats setting from NonD ctor
130 const Variables& vars = iteratedModel.current_variables();
131 const SizetArray& ac_totals = vars.shared_data().active_components_totals();
132 bool euv = (ac_totals[TOTAL_CEUV] || ac_totals[TOTAL_DEUIV] ||
133 ac_totals[TOTAL_DEUSV] || ac_totals[TOTAL_DEURV]);
134 bool aleatory_mode = (samplingVarsMode == ALEATORY_UNCERTAIN ||
135 samplingVarsMode == ALEATORY_UNCERTAIN_UNIFORM);
136 epistemicStats = (euv && !aleatory_mode);
137
138 // enforce LHS as default sample type
139 if (!sampleType)
140 sampleType = SUBMETHOD_LHS;
141
142 // not used but included for completeness
143 if (numSamples) // samples is optional (default = 0)
144 maxEvalConcurrency *= numSamples;
145 }
146
147
148 /** This alternate constructor is used by ConcurrentStrategy for
149 generation of uniform, uncorrelated sample sets. */
150 NonDSampling::
NonDSampling(unsigned short sample_type,int samples,int seed,const String & rng,const RealVector & lower_bnds,const RealVector & upper_bnds)151 NonDSampling(unsigned short sample_type, int samples, int seed,
152 const String& rng, const RealVector& lower_bnds,
153 const RealVector& upper_bnds):
154 NonD(RANDOM_SAMPLING, lower_bnds, upper_bnds), seedSpec(seed),
155 randomSeed(seed), samplesSpec(samples), samplesRef(samples),
156 numSamples(samples), rngName(rng), sampleType(sample_type), wilksFlag(false),
157 samplesIncrement(0), statsFlag(false), allDataFlag(true),
158 samplingVarsMode(ACTIVE_UNIFORM), sampleRanksMode(IGNORE_RANKS),
159 varyPattern(true), backfillFlag(false), numLHSRuns(0)
160 {
161 subIteratorFlag = true; // suppress some output
162
163 // enforce LHS as default sample type
164 if (!sampleType)
165 sampleType = SUBMETHOD_LHS;
166
167 // not used but included for completeness
168 if (numSamples) // samples is optional (default = 0)
169 maxEvalConcurrency *= numSamples;
170 }
171
172
173 /** This alternate constructor is used by ConcurrentStrategy for
174 generation of normal, correlated sample sets. */
175 NonDSampling::
NonDSampling(unsigned short sample_type,int samples,int seed,const String & rng,const RealVector & means,const RealVector & std_devs,const RealVector & lower_bnds,const RealVector & upper_bnds,RealSymMatrix & correl)176 NonDSampling(unsigned short sample_type, int samples, int seed,
177 const String& rng, const RealVector& means,
178 const RealVector& std_devs, const RealVector& lower_bnds,
179 const RealVector& upper_bnds, RealSymMatrix& correl):
180 NonD(RANDOM_SAMPLING, lower_bnds, upper_bnds), seedSpec(seed),
181 randomSeed(seed), samplesSpec(samples), samplesRef(samples),
182 numSamples(samples), rngName(rng), sampleType(sample_type), wilksFlag(false),
183 samplesIncrement(0), statsFlag(false), allDataFlag(true),
184 samplingVarsMode(ACTIVE), sampleRanksMode(IGNORE_RANKS), varyPattern(true),
185 backfillFlag(false), numLHSRuns(0)
186 {
187 subIteratorFlag = true; // suppress some output
188
189 // enforce LHS as default sample type
190 if (!sampleType)
191 sampleType = SUBMETHOD_LHS;
192
193 // not used but included for completeness
194 if (numSamples) // samples is optional (default = 0)
195 maxEvalConcurrency *= numSamples;
196 }
197
198
199 /** This alternate constructor defines allSamples from an incoming
200 sample matrix. */
201 NonDSampling::
NonDSampling(Model & model,const RealMatrix & sample_matrix)202 NonDSampling(Model& model, const RealMatrix& sample_matrix):
203 NonD(LIST_SAMPLING, model), seedSpec(0), randomSeed(0),
204 samplesSpec(sample_matrix.numCols()), sampleType(SUBMETHOD_DEFAULT),
205 wilksFlag(false), samplesIncrement(0), statsFlag(true), allDataFlag(true),
206 samplingVarsMode(ACTIVE), sampleRanksMode(IGNORE_RANKS),
207 varyPattern(false), backfillFlag(false), numLHSRuns(0)
208 {
209 allSamples = sample_matrix; compactMode = true;
210 samplesRef = numSamples = samplesSpec;
211
212 subIteratorFlag = true; // suppress some output
213
214 // not used but included for completeness
215 if (numSamples)
216 maxEvalConcurrency *= numSamples;
217 }
218
219
~NonDSampling()220 NonDSampling::~NonDSampling()
221 { }
222
223
224 void NonDSampling::
transform_samples(Pecos::ProbabilityTransformation & nataf,RealMatrix & sample_matrix,int num_samples,bool x_to_u)225 transform_samples(Pecos::ProbabilityTransformation& nataf,
226 RealMatrix& sample_matrix, int num_samples, bool x_to_u)
227 {
228 if (num_samples == 0)
229 num_samples = sample_matrix.numCols();
230 else if (sample_matrix.numCols() != num_samples)
231 sample_matrix.shapeUninitialized(numContinuousVars, num_samples);
232
233 if (x_to_u)
234 for (size_t i=0; i<num_samples; ++i) {
235 RealVector x_samp(Teuchos::Copy, sample_matrix[i], numContinuousVars);
236 RealVector u_samp(Teuchos::View, sample_matrix[i], numContinuousVars);
237 nataf.trans_X_to_U(x_samp, u_samp);
238 }
239 else
240 for (size_t i=0; i<num_samples; ++i) {
241 RealVector u_samp(Teuchos::Copy, sample_matrix[i], numContinuousVars);
242 RealVector x_samp(Teuchos::View, sample_matrix[i], numContinuousVars);
243 nataf.trans_U_to_X(u_samp, x_samp);
244 }
245 }
246
247
get_parameter_sets(Model & model,const int num_samples,RealMatrix & design_matrix,bool write_msg)248 void NonDSampling::get_parameter_sets(Model& model, const int num_samples,
249 RealMatrix& design_matrix, bool write_msg)
250 {
251 initialize_lhs(write_msg, num_samples);
252
253 // Invoke LHSDriver to generate samples within the specified distributions
254
255 switch (samplingVarsMode) {
256 case ACTIVE_UNIFORM: case ALL_UNIFORM: case UNCERTAIN_UNIFORM:
257 case ALEATORY_UNCERTAIN_UNIFORM: case EPISTEMIC_UNCERTAIN_UNIFORM: {
258 short model_view = model.current_variables().view().first;
259 // Use LHSDriver::generate_uniform_samples() between lower/upper bounds
260 RealSymMatrix corr; // uncorrelated samples
261 if ( samplingVarsMode == ACTIVE_UNIFORM ||
262 ( samplingVarsMode == ALL_UNIFORM &&
263 ( model_view == RELAXED_ALL || model_view == MIXED_ALL ) ) ||
264 ( samplingVarsMode == UNCERTAIN_UNIFORM &&
265 ( model_view == RELAXED_UNCERTAIN ||
266 model_view == MIXED_UNCERTAIN ) ) ||
267 ( samplingVarsMode == ALEATORY_UNCERTAIN_UNIFORM &&
268 ( model_view == RELAXED_ALEATORY_UNCERTAIN ||
269 model_view == MIXED_ALEATORY_UNCERTAIN ) ) ||
270 ( samplingVarsMode == EPISTEMIC_UNCERTAIN_UNIFORM &&
271 ( model_view == RELAXED_EPISTEMIC_UNCERTAIN ||
272 model_view == MIXED_EPISTEMIC_UNCERTAIN ) ) ) {
273 // sample uniformly from ACTIVE lower/upper bounds (regardless of model
274 // view), from UNCERTAIN lower/upper bounds (with model in DISTINCT view),
275 // or from ALL lower/upper bounds (with model in ALL view).
276 // loss of sampleRanks control is OK since NonDIncremLHS uses ACTIVE mode.
277 // TO DO: add support for uniform discrete
278 lhsDriver.generate_uniform_samples(model.continuous_lower_bounds(),
279 model.continuous_upper_bounds(),
280 corr, num_samples, design_matrix);
281 }
282 else if (samplingVarsMode == ALL_UNIFORM) {
283 // sample uniformly from ALL lower/upper bnds with model in distinct view.
284 // loss of sampleRanks control is OK since NonDIncremLHS uses ACTIVE mode.
285 // TO DO: add support for uniform discrete
286 lhsDriver.generate_uniform_samples(model.all_continuous_lower_bounds(),
287 model.all_continuous_upper_bounds(),
288 corr, num_samples, design_matrix);
289 }
290 else { // A, E, A+E UNCERTAIN_UNIFORM
291 // sample uniformly from {A,E,A+E} UNCERTAIN lower/upper bounds
292 // with model using a non-corresponding view (corresponding views
293 // handled in first case above)
294 size_t start_acv, num_acv, dummy;
295 mode_counts(model.current_variables(), start_acv, num_acv,
296 dummy, dummy, dummy, dummy, dummy, dummy);
297 if (!num_acv) {
298 Cerr << "Error: no active continuous variables for sampling in "
299 << "uniform mode" << std::endl;
300 abort_handler(METHOD_ERROR);
301 }
302 const RealVector& all_c_l_bnds = model.all_continuous_lower_bounds();
303 const RealVector& all_c_u_bnds = model.all_continuous_upper_bounds();
304 RealVector uncertain_c_l_bnds(Teuchos::View,
305 const_cast<Real*>(&all_c_l_bnds[start_acv]), num_acv);
306 RealVector uncertain_c_u_bnds(Teuchos::View,
307 const_cast<Real*>(&all_c_u_bnds[start_acv]), num_acv);
308 // loss of sampleRanks control is OK since NonDIncremLHS uses ACTIVE mode
309 // TO DO: add support for uniform discrete
310 lhsDriver.generate_uniform_samples(uncertain_c_l_bnds, uncertain_c_u_bnds,
311 corr, num_samples, design_matrix);
312 }
313 break;
314 }
315
316 case ACTIVE: { // utilize model view to sample active variables
317 Pecos::MultivariateDistribution& mv_dist
318 = model.multivariate_distribution();
319 if (backfillFlag)
320 lhsDriver.generate_unique_samples(mv_dist.random_variables(),
321 mv_dist.correlation_matrix(), num_samples, design_matrix, sampleRanks,
322 mv_dist.active_variables(), mv_dist.active_correlations());
323 // sampleRanks remains empty. See LHSDriver::generate_unique_samples()
324 else
325 lhsDriver.generate_samples(mv_dist.random_variables(),
326 mv_dist.correlation_matrix(), num_samples, design_matrix, sampleRanks,
327 mv_dist.active_variables(), mv_dist.active_correlations());
328 break;
329 }
330
331 case DESIGN: case ALEATORY_UNCERTAIN: case EPISTEMIC_UNCERTAIN:
332 case UNCERTAIN: case STATE: case ALL: {
333 // override active model view to sample alternate subset/superset
334 BitArray active_vars, active_corr;
335 mode_bits(model.current_variables(), active_vars, active_corr);
336 Pecos::MultivariateDistribution& mv_dist
337 = model.multivariate_distribution();
338 if (backfillFlag)
339 lhsDriver.generate_unique_samples(mv_dist.random_variables(),
340 mv_dist.correlation_matrix(), num_samples, design_matrix, sampleRanks,
341 active_vars, active_corr);
342 // sampleRanks remains empty. See LHSDriver::generate_unique_samples()
343 else
344 lhsDriver.generate_samples(mv_dist.random_variables(),
345 mv_dist.correlation_matrix(), num_samples, design_matrix, sampleRanks,
346 active_vars, active_corr);
347 break;
348 }
349 }
350 }
351
352
353 /** This version of get_parameter_sets() does not extract data from the
354 user-defined model, but instead relies on the incoming bounded region
355 definition. It only support a UNIFORM sampling mode, where the
356 distinction of ACTIVE_UNIFORM vs. ALL_UNIFORM is handled elsewhere. */
357 void NonDSampling::
get_parameter_sets(const RealVector & lower_bnds,const RealVector & upper_bnds)358 get_parameter_sets(const RealVector& lower_bnds, const RealVector& upper_bnds)
359 {
360 initialize_lhs(true, numSamples);
361 RealSymMatrix correl; // uncorrelated
362 lhsDriver.generate_uniform_samples(lower_bnds, upper_bnds, correl,
363 numSamples, allSamples);
364 }
365
366
367 /** This version of get_parameter_sets() does not extract data from the
368 user-defined model, but instead relies on the incoming
369 definition. It only supports the sampling of normal variables. */
370 void NonDSampling::
get_parameter_sets(const RealVector & means,const RealVector & std_devs,const RealVector & lower_bnds,const RealVector & upper_bnds,RealSymMatrix & correl)371 get_parameter_sets(const RealVector& means, const RealVector& std_devs,
372 const RealVector& lower_bnds, const RealVector& upper_bnds,
373 RealSymMatrix& correl)
374 {
375 initialize_lhs(true, numSamples);
376 lhsDriver.generate_normal_samples(means, std_devs, lower_bnds, upper_bnds,
377 correl, numSamples, allSamples);
378 }
379
380
381 // Map the active variables from vars to sample_vars (a column in allSamples)
382 void NonDSampling::
sample_to_variables(const Real * sample_vars,Variables & vars,Model & model)383 sample_to_variables(const Real* sample_vars, Variables& vars, Model& model)
384 {
385 // sample_vars are in RandomVariable order, which mirrors the XML spec
386 // vars updates utilize all continuous,discrete {int,string,real} indexing
387
388 const SharedVariablesData& svd = vars.shared_data();
389 short vars_mode;
390 switch (samplingVarsMode) {
391 case ACTIVE:
392 switch (vars.view().first) {
393 case RELAXED_ALL: case MIXED_ALL: vars_mode = ALL; break;
394 case RELAXED_DESIGN: case MIXED_DESIGN: vars_mode = DESIGN; break;
395 case RELAXED_UNCERTAIN: case MIXED_UNCERTAIN: vars_mode = UNCERTAIN; break;
396 case RELAXED_ALEATORY_UNCERTAIN: case MIXED_ALEATORY_UNCERTAIN:
397 vars_mode = ALEATORY_UNCERTAIN; break;
398 case RELAXED_EPISTEMIC_UNCERTAIN: case MIXED_EPISTEMIC_UNCERTAIN:
399 vars_mode = EPISTEMIC_UNCERTAIN; break;
400 case RELAXED_STATE: case MIXED_STATE: vars_mode = STATE; break;
401 }
402 break;
403 case ACTIVE_UNIFORM:
404 switch (vars.view().first) {
405 case RELAXED_ALL: case MIXED_ALL: vars_mode = ALL_UNIFORM; break;
406 case RELAXED_DESIGN: case MIXED_DESIGN:
407 vars_mode = DESIGN/*_UNIFORM*/; break;
408 case RELAXED_UNCERTAIN: case MIXED_UNCERTAIN:
409 vars_mode = UNCERTAIN_UNIFORM; break;
410 case RELAXED_ALEATORY_UNCERTAIN: case MIXED_ALEATORY_UNCERTAIN:
411 vars_mode = ALEATORY_UNCERTAIN_UNIFORM; break;
412 case RELAXED_EPISTEMIC_UNCERTAIN: case MIXED_EPISTEMIC_UNCERTAIN:
413 vars_mode = EPISTEMIC_UNCERTAIN_UNIFORM; break;
414 case RELAXED_STATE: case MIXED_STATE:
415 vars_mode = STATE/*_UNIFORM*/; break;
416 }
417 break;
418 default: vars_mode = samplingVarsMode; break;
419 }
420
421 size_t cv_index, num_cv, div_index, num_div, dsv_index, num_dsv,
422 drv_index, num_drv, samp_index = 0;
423 switch (vars_mode) {
424 case DESIGN:
425 cv_index = div_index = dsv_index = drv_index = 0;
426 svd.design_counts(num_cv, num_div, num_dsv, num_drv);
427 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
428 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
429 break;
430 //case DESIGN_UNIFORM:
431 // cv_index = div_index = dsv_index = drv_index = 0;
432 // svd.design_counts(num_cv, num_div, num_dsv, num_drv);
433 // sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
434 // dsv_index, num_dsv, drv_index, num_drv, samp_index);
435 // break;
436 case ALEATORY_UNCERTAIN:
437 // design vars define starting indices
438 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
439 // aleatory uncertain vars define counts
440 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
441 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
442 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
443 break;
444 case ALEATORY_UNCERTAIN_UNIFORM:
445 // continuous design vars define starting indices
446 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
447 // continuous aleatory uncertain vars define counts
448 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
449 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
450 dsv_index, num_dsv, drv_index, num_drv, samp_index);
451 break;
452 case EPISTEMIC_UNCERTAIN:
453 // design + aleatory uncertain vars define starting indices
454 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
455 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
456 cv_index += num_cv; div_index += num_div;
457 dsv_index += num_dsv; drv_index += num_drv;
458 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
459 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
460 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
461 break;
462 case EPISTEMIC_UNCERTAIN_UNIFORM:
463 // continuous design + aleatory uncertain vars define starting indices
464 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
465 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
466 cv_index += num_cv; div_index += num_div;
467 dsv_index += num_dsv; drv_index += num_drv;
468 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
469 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
470 dsv_index, num_dsv, drv_index, num_drv, samp_index);
471 break;
472 case UNCERTAIN:
473 // aleatory
474 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
475 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
476 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
477 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
478 // epistemic
479 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
480 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
481 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
482 break;
483 case UNCERTAIN_UNIFORM:
484 // aleatory
485 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
486 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
487 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
488 dsv_index, num_dsv, drv_index, num_drv, samp_index);
489 // epistemic
490 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
491 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
492 dsv_index, num_dsv, drv_index, num_drv, samp_index);
493 break;
494 case STATE:
495 svd.design_counts(cv_index, div_index, dsv_index, drv_index);
496 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
497 cv_index += num_cv; div_index += num_div;
498 dsv_index += num_dsv; drv_index += num_drv;
499 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
500 cv_index += num_cv; div_index += num_div;
501 dsv_index += num_dsv; drv_index += num_drv;
502 svd.state_counts(num_cv, num_div, num_dsv, num_drv);
503 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
504 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
505 break;
506 //case STATE_UNIFORM:
507 // svd.design_counts(cv_index, div_index, dsv_index, drv_index);
508 // svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
509 // cv_index += num_cv; div_index += num_div;
510 // dsv_index += num_dsv; drv_index += num_drv;
511 // svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
512 // cv_index += num_cv; div_index += num_div;
513 // dsv_index += num_dsv; drv_index += num_drv;
514 // svd.state_counts(num_cv, num_div, num_dsv, num_drv);
515 // sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
516 // dsv_index, num_dsv, drv_index, num_drv, samp_index);
517 // break;
518 case ALL:
519 // design
520 cv_index = div_index = dsv_index = drv_index = 0;
521 svd.design_counts(num_cv, num_div, num_dsv, num_drv);
522 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
523 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
524 // aleatory
525 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
526 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
527 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
528 // epistemic
529 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
530 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
531 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
532 // state
533 svd.state_counts(num_cv, num_div, num_dsv, num_drv);
534 sample_to_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
535 dsv_index, num_dsv, drv_index, num_drv, samp_index, model);
536 break;
537 case ALL_UNIFORM:
538 // design
539 cv_index = div_index = dsv_index = drv_index = 0;
540 svd.design_counts(num_cv, num_div, num_dsv, num_drv);
541 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
542 dsv_index, num_dsv, drv_index, num_drv, samp_index);
543 // aleatory
544 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
545 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
546 dsv_index, num_dsv, drv_index, num_drv, samp_index);
547 // epistemic
548 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
549 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
550 dsv_index, num_dsv, drv_index, num_drv, samp_index);
551 // state
552 svd.state_counts(num_cv, num_div, num_dsv, num_drv);
553 sample_to_cv_type(sample_vars, vars, cv_index, num_cv, div_index, num_div,
554 dsv_index, num_dsv, drv_index, num_drv, samp_index);
555 break;
556 }
557 }
558
559
560 /*
561 // TO DO: avoid inefficiency from repeated lookups...
562 void NonDSampling::
563 sample_to_variables(const Real* sample_vars, Variables& vars, size_t acv_start,
564 size_t num_acv, size_t adiv_start, size_t num_adiv,
565 size_t adsv_start, size_t num_adsv, size_t adrv_start,
566 size_t num_adrv, const StringSetArray& dss_values)
567 {
568 const SharedVariablesData& svd = vars.shared_data();
569
570 // sampled continuous vars (by value)
571 size_t i, end = acv_start + num_acv;
572 for (i=acv_start; i<end; ++i)
573 vars.all_continuous_variable(sample_vars[svd.acv_index_to_all_index(i)], i);
574 // sampled discrete int vars (by value cast from Real)
575 end = adiv_start + num_adiv;
576 for (i=adiv_start; i<end; ++i)
577 vars.all_discrete_int_variable(
578 (int)sample_vars[svd.adiv_index_to_all_index(i)], i);
579 // sampled discrete string vars (by index cast from Real)
580 end = adsv_start + num_adsv;
581 for (i=adsv_start; i<end; ++i)
582 vars.all_discrete_string_variable(set_index_to_value(
583 (size_t)sample_vars[svd.adsv_index_to_all_index(i)], dss_values[i]),i);
584 // sampled discrete real vars (by value)
585 end = adrv_start + num_adrv;
586 for (i=adrv_start; i<end; ++i)
587 vars.all_discrete_real_variable(
588 sample_vars[svd.adrv_index_to_all_index(i)], i);
589 }
590 */
591
592
593 // Some inefficiency is acceptable here, as this is for one-time imports,
594 // so retain the compact approach of per-index conversion for now
595 void NonDSampling::
variables_to_sample(const Variables & vars,Real * sample_vars)596 variables_to_sample(const Variables& vars, Real* sample_vars)
597 {
598 size_t acv_start, num_acv, adiv_start, num_adiv, adsv_start, num_adsv,
599 adrv_start, num_adrv;
600 mode_counts(vars, acv_start, num_acv, adiv_start, num_adiv,
601 adsv_start, num_adsv, adrv_start, num_adrv);
602
603 const SharedVariablesData& svd = vars.shared_data();
604
605 // sampled continuous vars (by value)
606 size_t i, end = acv_start + num_acv;
607 for (i=acv_start; i<end; ++i)
608 sample_vars[svd.acv_index_to_all_index(i)]
609 = vars.all_continuous_variables()[i];
610 // sampled discrete int vars (cast value to Real)
611 end = adiv_start + num_adiv;
612 for (i=adiv_start; i<end; ++i)
613 sample_vars[svd.adiv_index_to_all_index(i)]
614 = (Real)vars.all_discrete_int_variables()[i];
615 // sampled discrete string vars (cast index to Real)
616 if (num_adsv) { // incur overhead of extracting DSS values
617 short active_view = vars.view().first;
618 bool relax = (active_view == RELAXED_ALL ||
619 ( active_view >= RELAXED_DESIGN && active_view <= RELAXED_STATE ) );
620 short all_view = (relax) ? RELAXED_ALL : MIXED_ALL;
621 const StringSetArray& dss_values
622 = iteratedModel.discrete_set_string_values(all_view);
623 end = adsv_start + num_adsv;
624 for (i=adsv_start; i<end; ++i)
625 sample_vars[svd.adsv_index_to_all_index(i)] = (Real)set_value_to_index(
626 vars.all_discrete_string_variables()[i], dss_values[i]);
627 }
628 // sampled discrete real vars (by value)
629 end = adrv_start + num_adrv;
630 for (i=adrv_start; i<end; ++i)
631 sample_vars[svd.adrv_index_to_all_index(i)]
632 = vars.all_discrete_real_variables()[i];
633 }
634
635
636 /** This function and its helpers to follow are needed since NonDSampling
637 supports a richer set of sampling modes than just the active variable
638 subset. mode_counts() manages the samplingVarsMode setting, while its
639 helper functions (view_{design,aleatory_uncertain,epistemic_uncertain,
640 uncertain,state}_counts) manage the active variables view. Similar
641 to the computation of starts and counts in creating active variable
642 views, the results of this function are starts and counts for use
643 within model.all_*() set/get functions. */
644 void NonDSampling::
mode_counts(const Variables & vars,size_t & cv_start,size_t & num_cv,size_t & div_start,size_t & num_div,size_t & dsv_start,size_t & num_dsv,size_t & drv_start,size_t & num_drv) const645 mode_counts(const Variables& vars, size_t& cv_start, size_t& num_cv,
646 size_t& div_start, size_t& num_div, size_t& dsv_start,
647 size_t& num_dsv, size_t& drv_start, size_t& num_drv) const
648 {
649 cv_start = div_start = dsv_start = drv_start = 0;
650 num_cv = num_div = num_dsv = num_drv = 0;
651 const SharedVariablesData& svd = vars.shared_data();
652 size_t dummy;
653 // Note: UNIFORM views do not currently support non-relaxed discrete
654 switch (samplingVarsMode) {
655 case DESIGN:
656 // design vars define counts
657 svd.design_counts(num_cv, num_div, num_dsv, num_drv);
658 break;
659 //case DESIGN_UNIFORM:
660 // // continuous design vars define counts
661 // svd.design_counts(num_cv, dummy, dummy, dummy);
662 // break;
663 case ALEATORY_UNCERTAIN:
664 // design vars define starting indices
665 svd.design_counts(cv_start, div_start, dsv_start, drv_start);
666 // aleatory uncertain vars define counts
667 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
668 break;
669 case ALEATORY_UNCERTAIN_UNIFORM:
670 // continuous design vars define starting indices
671 svd.design_counts(cv_start, dummy, dummy, dummy);
672 // continuous aleatory uncertain vars define counts
673 svd.aleatory_uncertain_counts(num_cv, dummy, dummy, dummy);
674 break;
675 case EPISTEMIC_UNCERTAIN:
676 // design + aleatory uncertain vars define starting indices
677 svd.design_counts(cv_start, div_start, dsv_start, drv_start);
678 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
679 cv_start += num_cv; div_start += num_div;
680 dsv_start += num_dsv; drv_start += num_drv;
681 // epistemic uncertain vars define counts
682 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
683 break;
684 case EPISTEMIC_UNCERTAIN_UNIFORM:
685 // continuous design + aleatory uncertain vars define starting indices
686 svd.design_counts(cv_start, dummy, dummy, dummy);
687 svd.aleatory_uncertain_counts(num_cv, dummy, dummy, dummy);
688 cv_start += num_cv;
689 // continuous epistemic uncertain vars define counts
690 svd.epistemic_uncertain_counts(num_cv, dummy, dummy, dummy);
691 break;
692 case UNCERTAIN:
693 // design vars define starting indices
694 svd.design_counts(cv_start, div_start, dsv_start, drv_start);
695 // aleatory+epistemic uncertain vars define counts
696 svd.uncertain_counts(num_cv, num_div, num_dsv, num_drv);
697 break;
698 case UNCERTAIN_UNIFORM:
699 // continuous design vars define starting indices
700 svd.design_counts(cv_start, dummy, dummy, dummy);
701 // continuous aleatory+epistemic uncertain vars define counts
702 svd.uncertain_counts(num_cv, dummy, dummy, dummy);
703 break;
704 case STATE:
705 // design + aleatory + epistemic vars define starting indices
706 svd.design_counts(cv_start, div_start, dsv_start, drv_start);
707 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
708 cv_start += num_cv; div_start += num_div;
709 dsv_start += num_dsv; drv_start += num_drv;
710 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
711 cv_start += num_cv; div_start += num_div;
712 dsv_start += num_dsv; drv_start += num_drv;
713 // state vars define counts
714 svd.state_counts(num_cv, num_div, num_dsv, num_drv);
715 break;
716 //case STATE_UNIFORM:
717 // // continuous design + aleatory + epistemic vars define starting indices
718 // svd.design_counts(cv_start, dummy, dummy, dummy);
719 // svd.aleatory_uncertain_counts(num_cv, dummy, dummy, dummy);
720 // cv_start += num_cv;
721 // svd.epistemic_uncertain_counts(num_cv, dummy, dummy, dummy);
722 // cv_start += num_cv;
723 // // continuous state vars define counts
724 // svd.state_counts(num_cv, dummy, dummy, dummy);
725 // break;
726 case ACTIVE:
727 cv_start = vars.cv_start(); num_cv = vars.cv();
728 div_start = vars.div_start(); num_div = vars.div();
729 dsv_start = vars.dsv_start(); num_dsv = vars.dsv();
730 drv_start = vars.drv_start(); num_drv = vars.drv(); break;
731 case ACTIVE_UNIFORM:
732 cv_start = vars.cv_start(); num_cv = vars.cv(); break;
733 case ALL:
734 num_cv = vars.acv(); num_div = vars.adiv();
735 num_dsv = vars.adsv(); num_drv = vars.adrv(); break;
736 case ALL_UNIFORM:
737 num_cv = vars.acv(); break;
738 }
739 }
740
741
742 void NonDSampling::
mode_bits(const Variables & vars,BitArray & active_vars,BitArray & active_corr) const743 mode_bits(const Variables& vars, BitArray& active_vars,
744 BitArray& active_corr) const
745 {
746 const SharedVariablesData& svd = vars.shared_data();
747 size_t num_v = vars.tv(), num_cv, num_div, num_dsv, num_drv,
748 num_dv, num_auv, num_euv;
749 svd.design_counts(num_cv, num_div, num_dsv, num_drv);
750 num_dv = num_cv + num_div + num_dsv + num_drv,
751 svd.aleatory_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
752 num_auv = num_cv + num_div + num_dsv + num_drv;
753 active_corr.resize(num_v, false);
754 assign_value(active_corr, true, num_dv, num_auv);
755
756 switch (samplingVarsMode) {
757 case DESIGN:
758 active_vars.resize(num_v, false);
759 assign_value(active_vars, true, 0, num_dv); break;
760 case ALEATORY_UNCERTAIN:
761 active_vars = active_corr; break;
762 case EPISTEMIC_UNCERTAIN:
763 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
764 active_vars.resize(num_v, false);
765 assign_value(active_vars, true, num_dv + num_auv,
766 num_cv + num_div + num_dsv + num_drv);
767 break;
768 case UNCERTAIN:
769 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
770 active_vars.resize(num_v, false);
771 assign_value(active_vars, true, num_dv,
772 num_auv + num_cv + num_div + num_dsv + num_drv);
773 break;
774 case STATE:
775 svd.epistemic_uncertain_counts(num_cv, num_div, num_dsv, num_drv);
776 num_euv = num_cv + num_div + num_dsv + num_drv;
777 svd.state_counts(num_cv, num_div, num_dsv, num_drv);
778 active_vars.resize(num_v, false);
779 assign_value(active_vars, true, num_dv + num_auv + num_euv,
780 num_cv + num_div + num_dsv + num_drv);
781 break;
782 case ALL:
783 active_vars.clear(); break; // no subset, all are active
784 //case ALEATORY_UNCERTAIN_UNIFORM:
785 //case EPISTEMIC_UNCERTAIN_UNIFORM:
786 //case UNCERTAIN_UNIFORM:
787 default:
788 Cerr << "Error: unsupported sampling mode in NonDSampling::mode_bits()."
789 << std::endl;
790 abort_handler(METHOD_ERROR); break;
791 }
792 }
793
794
initialize_lhs(bool write_message,int num_samples)795 void NonDSampling::initialize_lhs(bool write_message, int num_samples)
796 {
797 // keep track of number of LHS executions for this object
798 ++numLHSRuns;
799
800 //Cout << "numLHSRuns = " << numLHSRuns << " seedSpec = " << seedSpec
801 // << " randomSeed = " << randomSeed << " varyPattern = " << varyPattern
802 // << std::endl;
803
804 // Set seed value for input to LHS's RNG: a user-specified seed gives
805 // repeatable behavior but no specification gives random behavior based on
806 // querying a system clock. For cases where get_parameter_sets() may be
807 // called multiple times for the same sampling iterator (e.g., SBO), support
808 // a deterministic sequence of seed values to allow the sampling pattern to
809 // vary from one run to the next in a repeatable manner (required for RNG
810 // without a persistent state, such as rnum2).
811 bool seed_assigned = false, seed_advanced = false;
812 if (numLHSRuns == 1) { // set initial seed
813 lhsDriver.rng(rngName);
814 if (!seedSpec) { // no user specification --> nonrepeatable behavior
815 // Generate initial seed from a system clock. NOTE: the system clock
816 // should not used for multiple LHS calls since (1) clock granularity can
817 // be too coarse (can repeat on subsequent runs for inexpensive test fns)
818 // and (2) seed progression can be highly structured, which could induce
819 // correlation between sample sets. Instead, the clock-generated case
820 // varies the seed below using the same approach as the user-specified
821 // case. This has the additional benefit that a random run can be
822 // recreated by specifying the clock-generated seed in the input file.
823 randomSeed = generate_system_seed();
824 }
825 lhsDriver.seed(randomSeed); seed_assigned = true;
826 }
827 // We must distinguish two advancement use cases and allow them to co-exist:
828 // > an update to NonDSampling::randomSeed due to random_seed_sequence spec
829 // > an update to Pecos::LHSDriver::randomSeed using LHSDriver::
830 // advance_seed_sequence() in support of varyPattern for rnum2
831 else if (seedSpec && seedSpec != randomSeed) // random_seed_sequence advance
832 { seedSpec = randomSeed; lhsDriver.seed(randomSeed); seed_assigned = true; }
833 else if (varyPattern && rngName == "rnum2") // vary pattern by advancing seed
834 { lhsDriver.advance_seed_sequence(); seed_advanced = true; }
835 else if (!varyPattern) // reset orig / machine-generated (don't continue RNG)
836 { lhsDriver.seed(randomSeed); seed_assigned = true; }
837
838 // Needed a way to turn this off when LHS sampling is being used in
839 // NonDAdaptImpSampling because it gets written a _LOT_
840 String sample_string = submethod_enum_to_string(sampleType);
841 if (write_message) {
842 Cout << "\nNonD " << sample_string << " Samples = " << num_samples;
843 if (seed_assigned) {
844 if (seedSpec) Cout << " Seed (user-specified) = ";
845 else Cout << " Seed (system-generated) = ";
846 Cout << randomSeed << '\n';
847 }
848 else if (seed_advanced) {
849 if (seedSpec) Cout << " Seed (sequence from user-specified) = ";
850 else Cout << " Seed (sequence from system-generated) = ";
851 Cout << lhsDriver.seed() << '\n';
852 }
853 else // default Boost Mersenne twister
854 Cout << " Seed not reset from previous LHS execution\n";
855 }
856
857 lhsDriver.initialize(sample_string, sampleRanksMode, !subIteratorFlag);
858 }
859
860
861 /** Map ASV/DVV requests in final statistics into activeSet for use in
862 evaluate_parameter_sets() */
active_set_mapping()863 void NonDSampling::active_set_mapping()
864 {
865 // Adapted from NonDExpansion::compute_expansion()
866
867 // Note: the ASV within finalStatistics corresponds to the stats vector,
868 // not the QoI vector, but the DVV carries over.
869 const ShortArray& final_asv = finalStatistics.active_set_request_vector();
870 size_t num_final_stats = final_asv.size();
871 if (!num_final_stats) // finalStatistics not initialized
872 return; // leave activeSet as is; nothing to augment
873
874 // activeSet ASV/DVV can include active-variable derivatives for surrogate
875 // creation (use_derivatives spec option). Cannot easily support both this
876 // and moment gradients w.r.t. inactive variables without new logic for an
877 // aggregate DVV; however, the former case occurs in DataFitSurrModel
878 // contexts and the latter case occurs in NestedModel contexts:
879 // > for now, augment the incoming ASV (preserve the DataFitSurrModel case)
880 // with any moment grad requirements and only overwrite the incoming DVV
881 // when moment gradients are required (support the NestedModel case).
882 // > Model recursions that embed a derivative-enhanced DataFitSurrModel
883 // within a NestedModel may dictate additional care...
884 ShortArray sampler_asv = activeSet.request_vector();//(numFunctions, 0);
885 bool assign_dvv = false, qoi_fn, qoi_grad, moment1_grad, moment2_grad;
886 size_t i, j, rl_len, pl_len, bl_len, gl_len, total_i, cntr = 0,
887 moment_offset = (finalMomentsType) ? 2 : 0;
888 for (i=0; i<numFunctions; ++i) {
889
890 if (totalLevelRequests) {
891 rl_len = requestedRespLevels[i].length();
892 pl_len = requestedProbLevels[i].length();
893 bl_len = requestedRelLevels[i].length();
894 gl_len = requestedGenRelLevels[i].length();
895 }
896 else // requested level arrays may not be sized
897 rl_len = pl_len = bl_len = gl_len = 0;
898
899 // map final_asv value bits into qoi_fns requirements
900 qoi_fn = qoi_grad = moment1_grad = moment2_grad = false;
901 total_i = moment_offset + rl_len + pl_len + bl_len + gl_len;
902 for (j=0; j<total_i; ++j)
903 if (final_asv[cntr+j] & 1)
904 { qoi_fn = true; break; }
905
906 // map final_asv gradient bits into moment grad requirements
907 if (finalMomentsType) {
908 if (final_asv[cntr++] & 2) moment1_grad = true;
909 if (final_asv[cntr++] & 2) moment2_grad = true;
910 }
911 if (respLevelTarget == RELIABILITIES)
912 for (j=0; j<rl_len; ++j) // dbeta/ds requires mu,sigma,dmu/ds,dsigma/ds
913 if (final_asv[cntr+j] & 2)
914 { moment1_grad = moment2_grad = qoi_fn = true; break;}
915 cntr += rl_len + pl_len;
916 for (j=0; j<bl_len; ++j) // dz/ds requires dmu/ds, dsigma/ds
917 if (final_asv[cntr+j] & 2)
918 { moment1_grad = moment2_grad = true; break; }
919 cntr += bl_len + gl_len;
920 if (moment1_grad) assign_dvv = qoi_grad = true;
921 if (moment2_grad) assign_dvv = qoi_grad = qoi_fn = true;
922
923 // map qoi_{fn,grad} requirements into ASV settings
924 if (qoi_fn) sampler_asv[i] |= 1;
925 if (qoi_grad /*|| useDerivs*/) sampler_asv[i] |= 2; // future aggregation...
926 }
927 activeSet.request_vector(sampler_asv);
928
929 if (assign_dvv)
930 activeSet.derivative_vector(finalStatistics.active_set_derivative_vector());
931 //else leave DVV as default active cv's (from Iterator::update_from_model())
932 }
933
934
935 /** Default implementation generates allResponses from either allSamples
936 or allVariables. */
core_run()937 void NonDSampling::core_run()
938 {
939 bool log_resp_flag = (allDataFlag || statsFlag), log_best_flag = false;
940 evaluate_parameter_sets(iteratedModel, log_resp_flag, log_best_flag);
941 }
942
943
944 void NonDSampling::
compute_statistics(const RealMatrix & vars_samples,const IntResponseMap & resp_samples)945 compute_statistics(const RealMatrix& vars_samples,
946 const IntResponseMap& resp_samples)
947 {
948 StringMultiArrayConstView
949 acv_labels = iteratedModel.all_continuous_variable_labels(),
950 adiv_labels = iteratedModel.all_discrete_int_variable_labels(),
951 adsv_labels = iteratedModel.all_discrete_string_variable_labels(),
952 adrv_labels = iteratedModel.all_discrete_real_variable_labels();
953 size_t cv_start, num_cv, div_start, num_div, dsv_start, num_dsv,
954 drv_start, num_drv;
955 mode_counts(iteratedModel.current_variables(), cv_start, num_cv,
956 div_start, num_div, dsv_start, num_dsv, drv_start, num_drv);
957 StringMultiArrayConstView
958 cv_labels =
959 acv_labels[boost::indices[idx_range(cv_start, cv_start+num_cv)]],
960 div_labels =
961 adiv_labels[boost::indices[idx_range(div_start, div_start+num_div)]],
962 dsv_labels =
963 adsv_labels[boost::indices[idx_range(dsv_start, dsv_start+num_dsv)]],
964 drv_labels =
965 adrv_labels[boost::indices[idx_range(drv_start, drv_start+num_drv)]];
966
967 // archive the active variables with the results
968 if (resultsDB.active()) {
969 if (num_cv)
970 resultsDB.insert(run_identifier(), resultsNames.cv_labels, cv_labels);
971 if (num_div)
972 resultsDB.insert(run_identifier(), resultsNames.div_labels, div_labels);
973 if (num_dsv)
974 resultsDB.insert(run_identifier(), resultsNames.dsv_labels, dsv_labels);
975 if (num_drv)
976 resultsDB.insert(run_identifier(), resultsNames.drv_labels, drv_labels);
977 resultsDB.insert(run_identifier(), resultsNames.fn_labels,
978 iteratedModel.response_labels());
979 }
980
981 if (epistemicStats) // Epistemic/mixed
982 compute_intervals(resp_samples); // compute min/max response intervals
983 else { // Aleatory
984 // compute means and std deviations with confidence intervals
985 compute_moments(resp_samples);
986 // compute CDF/CCDF mappings of z to p/beta and p/beta to z
987 if (totalLevelRequests)
988 compute_level_mappings(resp_samples);
989 }
990
991 if (!subIteratorFlag) {
992 nonDSampCorr.compute_correlations(vars_samples, resp_samples);
993 // archive the correlations to the results DB
994 // nonDSampCorr.archive_correlations(run_identifier(), resultsDB, cv_labels,
995 // div_labels, dsv_labels, drv_labels,
996 // iteratedModel.response_labels());
997 }
998
999 // push results into finalStatistics
1000 update_final_statistics();
1001 }
1002
1003
1004 void NonDSampling::
compute_intervals(RealRealPairArray & extreme_fns,const IntResponseMap & samples)1005 compute_intervals(RealRealPairArray& extreme_fns, const IntResponseMap& samples)
1006 {
1007 // For the samples array, calculate min/max response intervals
1008
1009 size_t i, j, num_obs = samples.size(), num_samp;
1010 const StringArray& resp_labels = iteratedModel.response_labels();
1011
1012 extreme_fns.resize(numFunctions);
1013 IntRespMCIter it;
1014 for (i=0; i<numFunctions; ++i) {
1015 num_samp = 0;
1016 Real min = DBL_MAX, max = -DBL_MAX;
1017 for (it=samples.begin(); it!=samples.end(); ++it) {
1018 Real sample = it->second.function_value(i);
1019 if (std::isfinite(sample)) { // neither NaN nor +/-Inf
1020 if (sample < min) min = sample;
1021 if (sample > max) max = sample;
1022 ++num_samp;
1023 }
1024 }
1025 extreme_fns[i].first = min;
1026 extreme_fns[i].second = max;
1027 if (num_samp != num_obs)
1028 Cerr << "Warning: sampling statistics for " << resp_labels[i] << " omit "
1029 << num_obs-num_samp << " failed evaluations out of " << num_obs
1030 << " samples.\n";
1031 }
1032
1033 if (resultsDB.active()) {
1034 MetaDataType md;
1035 md["Row Labels"] = make_metadatavalue("Min", "Max");
1036 md["Column Labels"] = make_metadatavalue(resp_labels);
1037 resultsDB.insert(run_identifier(), resultsNames.extreme_values,
1038 extreme_fns, md);
1039 }
1040 }
1041
1042
1043 void NonDSampling::
compute_moments(const IntResponseMap & samples,RealMatrix & moment_stats,RealMatrix & moment_grads,RealMatrix & moment_conf_ints,short moments_type,const StringArray & labels)1044 compute_moments(const IntResponseMap& samples, RealMatrix& moment_stats,
1045 RealMatrix& moment_grads, RealMatrix& moment_conf_ints,
1046 short moments_type, const StringArray& labels)
1047 {
1048 // For the samples array, calculate 1st four moments and confidence intervals
1049
1050 // if subIteratorFlag, final_asv will be general. If not a sub-iterator, then
1051 // NonD::initialize_final_statistics() sets default request vector to 1's.
1052 const ShortArray& final_asv = finalStatistics.active_set_request_vector();
1053
1054 // if statsFlag, always compute moments for output regardless of final ASV.
1055 // else define moment requirements from final_asv and finalMomentsType.
1056 bool mom_fns = statsFlag, mom_grads = false;
1057 size_t i, l, m, cntr, num_lev, num_obs = samples.size();
1058 for (i=0, cntr=0; i<numFunctions; ++i) {
1059 if (finalMomentsType) { // only compute moments if needed
1060 for (m=0; m<2; ++m, ++cntr) {
1061 if (final_asv[cntr] & 1) mom_fns = true;
1062 if (final_asv[cntr] & 2) mom_grads = true;
1063 }
1064 }
1065 if (respLevelTarget == RELIABILITIES) {
1066 num_lev = requestedRespLevels[i].length();
1067 for (l=0; l<num_lev; ++l, ++cntr) {
1068 if (final_asv[cntr] & 1) mom_fns = true;
1069 // dbeta/ds requires mu,sigma,dmu/ds,dsigma/ds
1070 if (final_asv[cntr] & 2) mom_fns = mom_grads = true;
1071 }
1072 }
1073 else
1074 cntr += requestedRespLevels[i].length();
1075 cntr += requestedProbLevels[i].length();
1076 num_lev = requestedRelLevels[i].length();
1077 for (l=0; l<num_lev; ++l, ++cntr) {
1078 if (final_asv[cntr] & 1) mom_fns = true;
1079 // dz/ds requires dmu/ds, dsigma/ds
1080 if (final_asv[cntr] & 2) mom_grads = true;
1081 }
1082 cntr += requestedGenRelLevels[i].length();
1083 }
1084 if (!mom_fns && !mom_grads)
1085 return;
1086
1087 RealVectorArray fn_samples(num_obs);
1088 SizetArray sample_counts;
1089 IntRespMCIter it;
1090 for (it=samples.begin(), i=0; it!=samples.end(); ++it, ++i)
1091 fn_samples[i] = it->second.function_values_view();
1092
1093 if (mom_fns) {
1094 compute_moments(fn_samples,sample_counts,moment_stats,moments_type,labels);
1095 compute_moment_confidence_intervals(moment_stats, moment_conf_ints,
1096 sample_counts, moments_type);
1097 functionMomentsComputed = true;
1098 }
1099
1100 if (mom_grads) {
1101 RealMatrixArray grad_samples(num_obs);
1102 for (it=samples.begin(), i=0; it!=samples.end(); ++it, ++i)
1103 grad_samples[i] = it->second.function_gradients_view();
1104 compute_moment_gradients(fn_samples, grad_samples, moment_stats,
1105 moment_grads, moments_type);
1106 }
1107 }
1108
1109
1110 void NonDSampling::
compute_moments(const RealVectorArray & fn_samples,SizetArray & sample_counts,RealMatrix & moment_stats,short moments_type,const StringArray & labels)1111 compute_moments(const RealVectorArray& fn_samples, SizetArray& sample_counts,
1112 RealMatrix& moment_stats, short moments_type,
1113 const StringArray& labels)
1114 {
1115 size_t i, j, num_obs = fn_samples.size(), num_qoi;
1116 if (num_obs)
1117 num_qoi = fn_samples[0].length();
1118 else {
1119 Cerr << "Error: empty samples array in NonDSampling::compute_moments()."
1120 << std::endl;
1121 abort_handler(METHOD_ERROR);
1122 }
1123 Real sum, cm2, cm3, cm4, sample;
1124
1125 if (moment_stats.empty()) moment_stats.shapeUninitialized(4, num_qoi);
1126 sample_counts.resize(num_qoi);
1127
1128 for (i=0; i<num_qoi; ++i) {
1129 size_t& num_samp = sample_counts[i];
1130 Real* moments_i = moment_stats[i];
1131 accumulate_mean(fn_samples, i, num_samp, moments_i[0]);
1132 if (num_samp != num_obs)
1133 Cerr << "Warning: sampling statistics for " << labels[i] << " omit "
1134 << num_obs-num_samp << " failed evaluations out of " << num_obs
1135 << " samples.\n";
1136
1137 if (num_samp)
1138 accumulate_moments(fn_samples, i, moments_type, moments_i);
1139 else {
1140 Cerr << "Warning: Number of samples for " << labels[i]
1141 << " must be nonzero for moment calculation in NonDSampling::"
1142 << "compute_moments().\n";
1143 for (int j=0; j<4; ++j)
1144 moments_i[j] = std::numeric_limits<double>::quiet_NaN();
1145 }
1146 }
1147 }
1148
1149
1150 void NonDSampling::
compute_moments(const RealVectorArray & fn_samples,RealMatrix & moment_stats,short moments_type)1151 compute_moments(const RealVectorArray& fn_samples, RealMatrix& moment_stats,
1152 short moments_type)
1153 {
1154 size_t i, j, num_obs = fn_samples.size(), num_qoi, num_samp;
1155 if (num_obs)
1156 num_qoi = fn_samples[0].length();
1157 else {
1158 Cerr << "Error: empty samples array in NonDSampling::compute_moments()."
1159 << std::endl;
1160 abort_handler(METHOD_ERROR);
1161 }
1162
1163 if (moment_stats.empty()) moment_stats.shapeUninitialized(4, num_qoi);
1164
1165 for (i=0; i<num_qoi; ++i) {
1166
1167 Real* moments_i = moment_stats[i];
1168 accumulate_mean(fn_samples, i, num_samp, moments_i[0]);
1169 if (num_samp != num_obs)
1170 Cerr << "Warning: sampling statistics for quantity " << i+1 << " omit "
1171 << num_obs-num_samp << " failed evaluations out of " << num_obs
1172 << " samples.\n";
1173
1174 if (num_samp)
1175 accumulate_moments(fn_samples, i, moments_type, moments_i);
1176 else {
1177 Cerr << "Warning: Number of samples for quantity " << i+1
1178 << " must be nonzero in NonDSampling::compute_moments().\n";
1179 for (size_t j=0; j<4; ++j)
1180 moments_i[j] = std::numeric_limits<double>::quiet_NaN();
1181 }
1182 }
1183 }
1184
1185
1186 void NonDSampling::
compute_moments(const RealMatrix & fn_samples,RealMatrix & moment_stats,short moments_type)1187 compute_moments(const RealMatrix& fn_samples, RealMatrix& moment_stats,
1188 short moments_type)
1189 {
1190 int i, num_qoi = fn_samples.numRows(), num_obs = fn_samples.numCols();
1191 RealVectorArray rva_samples(num_obs);
1192 for (i=0; i<num_obs; ++i)
1193 rva_samples[i]
1194 = RealVector(Teuchos::View, const_cast<Real*>(fn_samples[i]), num_qoi);
1195 compute_moments(rva_samples, moment_stats, moments_type);
1196 }
1197
1198
1199 void NonDSampling::
compute_moment_confidence_intervals(const RealMatrix & moment_stats,RealMatrix & moment_conf_ints,const SizetArray & sample_counts,short moments_type)1200 compute_moment_confidence_intervals(const RealMatrix& moment_stats,
1201 RealMatrix& moment_conf_ints,
1202 const SizetArray& sample_counts,
1203 short moments_type)
1204 {
1205 size_t i, num_qoi = moment_stats.numCols();
1206 if (moment_conf_ints.empty())
1207 moment_conf_ints.shapeUninitialized(4, num_qoi);
1208
1209 Real mean, std_dev, var, qnan = std::numeric_limits<double>::quiet_NaN();
1210 for (i=0; i<num_qoi; ++i) {
1211 if (sample_counts[i] > 1) {
1212 const Real* moment_i = moment_stats[i];
1213 Real* moment_ci_i = moment_conf_ints[i];
1214 mean = moment_i[0];
1215 if (moments_type == CENTRAL_MOMENTS)
1216 { var = moment_i[1]; std_dev = std::sqrt(var); }
1217 else
1218 { std_dev = moment_i[1]; var = std_dev * std_dev; }
1219 if (mean == qnan || std_dev == qnan || var == qnan)
1220 for (size_t j=0; j<4; ++j)
1221 moment_ci_i[j] = qnan;
1222 else {
1223 // 95% confidence intervals (2-sided interval, not 1-sided limit)
1224 Real ns = (Real)sample_counts[i], dof = ns - 1.;
1225 // mean: the better formula does not assume known variance but requires
1226 // a function for the Student's t-distr. with (num_samp-1) degrees of
1227 // freedom (Haldar & Mahadevan, p. 127).
1228 Pecos::students_t_dist t_dist(dof);
1229 Real mean_ci_delta = std_dev*bmth::quantile(t_dist,0.975)/std::sqrt(ns);
1230 moment_ci_i[0] = mean - mean_ci_delta;
1231 moment_ci_i[1] = mean + mean_ci_delta;
1232 // std dev: chi-square distribution with (num_samp-1) degrees of freedom
1233 // (Haldar & Mahadevan, p. 132).
1234 Pecos::chi_squared_dist chisq(dof);
1235 Real z_975 = bmth::quantile(chisq, 0.975),
1236 z_025 = bmth::quantile(chisq, 0.025);
1237 if (moments_type == CENTRAL_MOMENTS) {
1238 moment_ci_i[2] = var*dof/z_975;
1239 moment_ci_i[3] = var*dof/z_025;
1240 }
1241 else {
1242 moment_ci_i[2] = std_dev*std::sqrt(dof/z_975);
1243 moment_ci_i[3] = std_dev*std::sqrt(dof/z_025);
1244 }
1245 }
1246 }
1247 else
1248 for (size_t j=0; j<4; ++j)
1249 moment_conf_ints(j,i) = 0.;
1250 }
1251 }
1252
1253
1254 void NonDSampling::
compute_moment_gradients(const RealVectorArray & fn_samples,const RealMatrixArray & grad_samples,const RealMatrix & moment_stats,RealMatrix & moment_grads,short moments_type)1255 compute_moment_gradients(const RealVectorArray& fn_samples,
1256 const RealMatrixArray& grad_samples,
1257 const RealMatrix& moment_stats,
1258 RealMatrix& moment_grads, short moments_type)
1259 {
1260 const ShortArray& final_asv = finalStatistics.active_set_request_vector();
1261 size_t q, cntr = 0;
1262 int m1_index, m2_index, num_mom = 2*numFunctions,
1263 num_deriv_vars = finalStatistics.active_set_derivative_vector().size();
1264 if (moment_grads.numRows() != num_deriv_vars ||
1265 moment_grads.numRows() != num_mom)
1266 moment_grads.shape(num_deriv_vars, num_mom); // init to 0.
1267 else
1268 moment_grads = 0.;
1269
1270 for (q=0; q<numFunctions; ++q) {
1271 m1_index = 2*q; m2_index = m1_index + 1;
1272 // Compute moment_grads
1273 accumulate_moment_gradients(fn_samples, grad_samples, q, moments_type,
1274 moment_stats(0,q), moment_stats(1,q),
1275 moment_grads[m1_index], moment_grads[m2_index]);
1276 // Assign moment_grads into finalStatistics (could do this in one step,
1277 // but retain API of moment_stats and moment_grads as their own matrices).
1278 // > NonDExpansion and NonDLocalReliability do not store moment grads as
1279 // member variables; they update finalStats directly in NonDExpansion::
1280 // compute_analytic_statistics() and NonDLocalRel::update_level_data().
1281 // Note: NonDExpansion::update_final_statistics_gradients() provides
1282 // post-processing for special cases (combined vars, insertion).
1283 // > NonDSampling could retain a class member or use a local variable for
1284 // moment_grads (currently a local, whereas momentStats is a member)
1285 if (moments_type) {
1286 if (final_asv[cntr] & 2) // moment 1 (mean) gradient
1287 finalStatistics.function_gradient(
1288 Teuchos::getCol(Teuchos::View, moment_grads, m1_index), cntr);
1289 ++cntr;
1290 if (final_asv[cntr] & 2) // moment 2 (var or stdev) gradient
1291 finalStatistics.function_gradient(
1292 Teuchos::getCol(Teuchos::View, moment_grads, m2_index), cntr);
1293 cntr += 1 +
1294 requestedRespLevels[q].length() + requestedProbLevels[q].length() +
1295 requestedRelLevels[q].length() + requestedGenRelLevels[q].length();
1296 }
1297 }
1298 }
1299
1300
1301 void NonDSampling::
accumulate_mean(const RealVectorArray & fn_samples,size_t q,size_t & num_samp,Real & mean)1302 accumulate_mean(const RealVectorArray& fn_samples, size_t q, size_t& num_samp,
1303 Real& mean)
1304 {
1305 num_samp = 0;
1306 Real sum = 0., sample;
1307 size_t s, num_obs = fn_samples.size();
1308 for (s=0; s<num_obs; ++s) {
1309 sample = fn_samples[s][q];
1310 if (std::isfinite(sample)) { // neither NaN nor +/-Inf
1311 sum += sample;
1312 ++num_samp;
1313 }
1314 }
1315
1316 if (num_samp)
1317 mean = sum / (Real)num_samp;
1318 }
1319
1320
1321 void NonDSampling::
accumulate_moments(const RealVectorArray & fn_samples,size_t q,short moments_type,Real * moments)1322 accumulate_moments(const RealVectorArray& fn_samples, size_t q,
1323 short moments_type, Real* moments)
1324 {
1325 // accumulate central moments (e.g., variance)
1326 size_t s, num_obs = fn_samples.size(), num_samp = 0;
1327 Real& mean = moments[0]; // already computed in accumulate_mean()
1328 Real sample, centered_fn, pow_fn, sum2 = 0., sum3 = 0., sum4 = 0.;
1329 for (s=0; s<num_obs; ++s) {
1330 sample = fn_samples[s][q];
1331 if (std::isfinite(sample)) { // neither NaN nor +/-Inf
1332 pow_fn = centered_fn = sample - mean;
1333 pow_fn *= centered_fn; sum2 += pow_fn; // variance
1334 pow_fn *= centered_fn; sum3 += pow_fn; // 3rd central moment
1335 pow_fn *= centered_fn; sum4 += pow_fn; // 4th central moment
1336 ++num_samp;
1337 }
1338 }
1339 Real ns = (Real)num_samp, nm1 = ns - 1., nm2 = ns - 2., ns_sq = ns * ns;
1340 // biased central moment estimators (bypass and use raw sums below):
1341 //biased_cm2 = sum2 / ns; biased_cm3 = sum3 / ns; biased_cm4 = sum4 / ns;
1342
1343 // unbiased moment estimators (central and standardized):
1344 bool central = (moments_type == CENTRAL_MOMENTS), pos_var = (sum2 > 0.);
1345 Real cm2 = sum2 / nm1;
1346 if (num_samp > 1 && pos_var)
1347 moments[1] = (central) ? cm2 : std::sqrt(cm2); // unbiased central : std dev
1348 else moments[1] = 0.;
1349
1350 if (num_samp > 2 && pos_var)
1351 moments[2] = (central) ?
1352 // unbiased central:
1353 sum3 * ns / (nm1 * nm2) :
1354 // unbiased standard: cm3 / sigma^3 = N / (nm1 nm2) sum3 / (cm2)^1.5
1355 sum3 * ns / (nm1 * nm2 * std::pow(cm2, 1.5));
1356 else moments[2] = 0.;
1357
1358 if (num_samp > 3 && pos_var)
1359 moments[3] = (central) ?
1360 // unbiased central (non-excess) from "Modeling with Data," Klemens 2009
1361 // (Appendix M): unbiased_cm4 =
1362 // ( N^3 biased_cm4 / (N-1) - (6N - 9) unbiased_cm2^2 ) / (N^2 - 3N + 3)
1363 //(ns * ns * sum4 / nm1 - (6.*ns - 9.) * cm2 * cm2) / (ns*(ns - 3.) + 3.) :
1364 //[fm] above estimator is not unbiased since cm2 * cm2 is biased, unbiased correction:
1365 (ns_sq * sum4 / nm1 - (6.*ns - 9.)*(ns_sq - ns)/(ns_sq - 2. * ns + 3) * cm2 * cm2) / ( (ns*(ns - 3.) + 3.) - ( (6.*ns - 9.)*(ns_sq - ns) )/( ns * (ns_sq - 2.*ns + 3) ) ) :
1366 // unbiased standard (excess kurtosis) from Wikipedia ("Estimators of
1367 // population kurtosis")
1368 nm1 * ((ns + 1.) * ns * sum4 / (sum2*sum2) - 3.*nm1) / (nm2*(ns - 3.));
1369 else moments[3] = (central) ? 0. : -3.;
1370 }
1371
1372
1373 void NonDSampling::
accumulate_moment_gradients(const RealVectorArray & fn_samples,const RealMatrixArray & grad_samples,size_t q,short moments_type,Real mean,Real mom2,Real * mean_grad,Real * mom2_grad)1374 accumulate_moment_gradients(const RealVectorArray& fn_samples,
1375 const RealMatrixArray& grad_samples, size_t q,
1376 short moments_type, Real mean, Real mom2,
1377 Real* mean_grad, Real* mom2_grad)
1378 {
1379 size_t s, v, num_deriv_vars,
1380 num_obs = std::min(fn_samples.size(), grad_samples.size());
1381 if (num_obs)
1382 num_deriv_vars = grad_samples[0].numRows(); // functionGradients = V x Q
1383 else {
1384 Cerr << "Error: emply samples array in NonDSampling::"
1385 << "accumulate_moment_gradients()" << std::endl;
1386 abort_handler(METHOD_ERROR);
1387 }
1388 //for (v=0; v<num_deriv_vars; ++v)
1389 // mean_grad[v] = mom2_grad[v] = 0.;
1390
1391 SizetArray num_samp(num_deriv_vars, 0);
1392 for (s=0; s<num_obs; ++s) {
1393 // manage faults hierarchically as in Pecos::SurrogateData::response_check()
1394 Real fn = fn_samples[s][q];
1395 if (std::isfinite(fn)) { // neither NaN nor +/-Inf
1396 const Real* grad = grad_samples[s][q];
1397 for (v=0; v<num_deriv_vars; ++v)
1398 if (std::isfinite(grad[v])) { // neither NaN nor +/-Inf
1399 mean_grad[v] += grad[v];
1400 mom2_grad[v] += fn * grad[v];
1401 ++num_samp[v];
1402 }
1403 }
1404 }
1405
1406 Real ns, nm1; size_t nsv;
1407 bool central_mom = (moments_type == CENTRAL_MOMENTS);
1408 for (v=0; v<num_deriv_vars; ++v) {
1409 nsv = num_samp[v];
1410 if (nsv) {
1411 ns = (Real)nsv;
1412 // dMean/ds = E[dQ/ds] --> unbiased estimator 1/N Sum(dQ/ds)
1413 mean_grad[v] /= ns;
1414 }
1415 if (nsv > 1) {
1416 nm1 = ns - 1.;
1417 // dVar/ds = 2 E[(Q - Mean)(dQ/ds - dMean/ds)] --> unbiased var estimator:
1418 // = 2/(N-1) [ Sum(Q dQ/ds) - Mean Sum(dQ/ds) -
1419 // dMean/ds Sum(Q) + N Mean Mean/ds ]
1420 // = 2/(N-1) [ Sum(Q dQ/ds) - Mean dMean/ds (N + N - N) ]
1421 // = 2/(N-1) [ Sum(Q dQ/ds) - N Mean dMean/ds ]
1422 // dVar/ds = 2 Sigma dSigma/ds -->
1423 // dSigma/ds = [ Sum(Q dQ/ds) - N Mean dMean/ds ] / (Sigma (N-1))
1424 mom2_grad[v] = (central_mom) ?
1425 2. * ( mom2_grad[v] - ns * mean * mean_grad[v] ) / nm1 :
1426 ( mom2_grad[v] - ns * mean * mean_grad[v] ) / (mom2 * nm1);
1427 }
1428 }
1429 }
1430
1431
1432 void NonDSampling::
archive_moments(size_t inc_id)1433 archive_moments(size_t inc_id)
1434 {
1435 if(!resultsDB.active()) return;
1436
1437 const StringArray &labels = iteratedModel.response_labels();
1438
1439 // archive the moments to results DB
1440 MetaDataType md_moments;
1441 md_moments["Row Labels"] = (finalMomentsType == CENTRAL_MOMENTS) ?
1442 make_metadatavalue("Mean", "Variance", "3rdCentral", "4thCentral") :
1443 make_metadatavalue("Mean", "Standard Deviation", "Skewness", "Kurtosis");
1444 md_moments["Column Labels"] = make_metadatavalue(labels);
1445 resultsDB.insert(run_identifier(), resultsNames.moments_std, momentStats,
1446 md_moments);
1447
1448 // send to prototype hdf5DB, too
1449 StringArray location;
1450 if(inc_id) location.push_back(String("increment:") + std::to_string(inc_id));
1451 location.push_back("moments");
1452 location.push_back("");
1453 for(int i = 0; i < numFunctions; ++i) {
1454 location.back() = labels[i];
1455 DimScaleMap scales;
1456 if(finalMomentsType == CENTRAL_MOMENTS)
1457 scales.emplace(0,
1458 StringScale("moments",
1459 {"mean", "variance", "third_central", "fourth_central"},
1460 ScaleScope::SHARED));
1461 else
1462 scales.emplace(0,
1463 StringScale("moments",
1464 {"mean", "std_deviation", "skewness", "kurtosis"},
1465 ScaleScope::SHARED));
1466 // extract column or row of moment_stats
1467 resultsDB.insert(run_identifier(), location,
1468 Teuchos::getCol<int,double>(Teuchos::View, *const_cast<RealMatrix*>(&momentStats), i), scales);
1469 }
1470 }
1471
1472
1473 void NonDSampling::
archive_moment_confidence_intervals(size_t inc_id)1474 archive_moment_confidence_intervals(size_t inc_id)
1475 {
1476 if(!resultsDB.active())
1477 return;
1478
1479 const StringArray &labels = iteratedModel.response_labels();
1480 // archive the confidence intervals to results DB
1481 MetaDataType md;
1482 md["Row Labels"] = (finalMomentsType == CENTRAL_MOMENTS) ?
1483 make_metadatavalue("LowerCI_Mean", "UpperCI_Mean",
1484 "LowerCI_Variance", "UpperCI_Variance") :
1485 make_metadatavalue("LowerCI_Mean", "UpperCI_Mean",
1486 "LowerCI_StdDev", "UpperCI_StdDev");
1487 md["Column Labels"] = make_metadatavalue(labels);
1488 resultsDB.insert(run_identifier(), resultsNames.moment_cis,
1489 momentCIs, md);
1490 // archive in HDF5. Store in a 2d dataset with mean and var/stdev on the 1st dimension
1491 // and lower and upper bounds on the 2nd dimension
1492 DimScaleMap scales;
1493 scales.emplace(0, StringScale("bounds", {"lower", "upper"}));
1494 if(finalMomentsType == CENTRAL_MOMENTS)
1495 scales.emplace(1, StringScale("moments", {"mean", "variance"}));
1496 else
1497 scales.emplace(1, StringScale("moments", {"mean", "std_deviation"}));
1498
1499 StringArray location;
1500 if(inc_id) location.push_back(String("increment:") + std::to_string(inc_id));
1501 location.push_back("moment_confidence_intervals");
1502 location.push_back("");
1503 for(int i = 0; i < numFunctions; ++i) { // loop over responses
1504 location.back() = labels[i];
1505 RealMatrix ci(2,2,false);
1506 ci(0,0) = momentCIs(0,i);
1507 ci(1,0) = momentCIs(1,i);
1508 ci(0,1) = momentCIs(2,i);
1509 ci(1,1) = momentCIs(3,i);
1510 resultsDB.insert(run_identifier(), location, ci, scales);
1511 }
1512 }
1513
1514 void NonDSampling::
archive_extreme_responses(size_t inc_id)1515 archive_extreme_responses(size_t inc_id) {
1516 const StringArray &labels = iteratedModel.response_labels();
1517 StringArray location;
1518 if(inc_id) location.push_back(String("increment:") + std::to_string(inc_id));
1519 location.push_back("extreme_responses");
1520 location.push_back("");
1521 DimScaleMap scales;
1522 scales.emplace(0, StringScale("extremes", {"minimum", "maximum"}));
1523 for(int i = 0; i < numFunctions; ++i) { // loop over responses
1524 location.back() = labels[i];
1525 RealVector extreme_values(2);
1526 extreme_values[0] = extremeValues[i].first;
1527 extreme_values[1] = extremeValues[i].second;
1528 resultsDB.insert(run_identifier(), location, extreme_values, scales);
1529 }
1530 }
1531
1532 int NonDSampling::
compute_wilks_sample_size(unsigned short order,Real alpha,Real beta,bool twosided)1533 compute_wilks_sample_size(unsigned short order, Real alpha, Real beta,
1534 bool twosided)
1535 {
1536 Real rorder = (Real) order;
1537
1538 if( !twosided && (order==1) )
1539 return std::ceil(std::log(1.0-beta)/std::log(alpha));
1540
1541 Real n = rorder + 1.0;
1542 if( twosided ) {
1543 n = 2.0*rorder;
1544 while( boost::math::ibeta<Real>(n-2.0*rorder+1.0, 2.0*rorder, alpha) >
1545 1.0-beta )
1546 n += 1.0;
1547 }
1548 else {
1549 while( boost::math::ibeta<Real>(rorder, n-rorder+1.0, 1-alpha) < beta )
1550 n += 1.0;
1551 }
1552
1553 return std::ceil(n);
1554 }
1555
1556
1557 Real NonDSampling::
compute_wilks_residual(unsigned short order,int nsamples,Real alpha,Real beta,bool twosided)1558 compute_wilks_residual(unsigned short order, int nsamples, Real alpha,
1559 Real beta, bool twosided)
1560 {
1561 Real rorder = (Real) order;
1562
1563 if( !twosided && (order==1) )
1564 return std::log(1.0-beta)/std::log(alpha) - (Real) nsamples;
1565
1566 if( twosided )
1567 return boost::math::ibeta<Real>((Real)nsamples-2.0*rorder+1.0, 2.0*rorder, alpha) - (1.0-beta);
1568 else
1569 return boost::math::ibeta<Real>(rorder, (Real)nsamples-rorder+1.0, 1-alpha) - beta;
1570 }
1571
1572
1573 Real NonDSampling::
compute_wilks_alpha(unsigned short order,int nsamples,Real beta,bool twosided)1574 compute_wilks_alpha(unsigned short order, int nsamples, Real beta,
1575 bool twosided)
1576 {
1577 Real rorder = (Real) order;
1578
1579 Real alpha_l = get_wilks_alpha_min(); // initial lower bound
1580 Real alpha_u = get_wilks_alpha_max(); // initial upper bound
1581 Real resid_l = compute_wilks_residual(order, nsamples, alpha_l, beta, twosided);
1582 Real resid_u = compute_wilks_residual(order, nsamples, alpha_u, beta, twosided);
1583 if( resid_l*resid_u > 0 )
1584 throw std::runtime_error("Cannot obtain valid bounds for wilks alpha bisection.");
1585
1586 //Cout << "\nalpha = " << alpha << ", resid = " << resid << std::endl;
1587 Real tol = 1.e-10;
1588 //Real eps = 1.e-8;
1589 Real alpha = alpha_l;
1590 Real resid = resid_l;
1591
1592 while( std::fabs(resid) > tol )
1593 {
1594 // Newton approach is too fragile - RWH
1595 //Real resid_plus = compute_wilks_residual(order, nsamples, alpha+eps, beta, twosided);
1596 //Real resid_minus = compute_wilks_residual(order, nsamples, alpha-eps, beta, twosided);
1597 //alpha -= resid/( (resid_plus-resid_minus)/(2.0*eps) );
1598 alpha = 0.5*(alpha_l+alpha_u);
1599 resid = compute_wilks_residual(order, nsamples, alpha, beta, twosided);
1600 if( resid*resid_u > 0 ) {
1601 alpha_u = alpha;
1602 resid_u = resid;
1603 }
1604 else {
1605 alpha_l = alpha;
1606 resid_l = resid;
1607 }
1608 //Cout << "alpha = " << alpha << ", resid = " << resid << std::endl;
1609 }
1610 //Cout << "Converged: alpha = " << alpha << ", resid = " << resid << std::endl;
1611
1612 return alpha;
1613 }
1614
1615
1616 Real NonDSampling::
compute_wilks_beta(unsigned short order,int nsamples,Real alpha,bool twosided)1617 compute_wilks_beta(unsigned short order, int nsamples, Real alpha,
1618 bool twosided)
1619 {
1620 Real rorder = (Real) order;
1621
1622 Real beta_l = get_wilks_beta_min(); // initial lower bound
1623 Real beta_u = get_wilks_beta_max(); // initial upper bound
1624 Real resid_l = compute_wilks_residual(order, nsamples, alpha, beta_l, twosided);
1625 Real resid_u = compute_wilks_residual(order, nsamples, alpha, beta_u, twosided);
1626 if( resid_l*resid_u > 0 )
1627 throw std::runtime_error("Cannot obtain valid bounds for wilks beta bisection.");
1628
1629 Real tol = 1.e-10;
1630 Real beta = beta_l;
1631 Real resid = resid_l;
1632
1633 while( std::fabs(resid) > tol )
1634 {
1635 beta = 0.5*(beta_l+beta_u);
1636 resid = compute_wilks_residual(order, nsamples, alpha, beta, twosided);
1637 if( resid*resid_u > 0 ) {
1638 beta_u = beta;
1639 resid_u = resid;
1640 }
1641 else {
1642 beta_l = beta;
1643 resid_l = resid;
1644 }
1645 //Cout << "beta = " << beta << ", resid = " << resid << std::endl;
1646 }
1647 //Cout << "Converged: beta = " << beta << ", resid = " << resid << std::endl;
1648
1649 return beta;
1650 }
1651
1652
1653 /** Computes CDF/CCDF based on sample binning. A PDF is inferred from a
1654 CDF/CCDF within compute_densities() after level computation. */
compute_level_mappings(const IntResponseMap & samples)1655 void NonDSampling::compute_level_mappings(const IntResponseMap& samples)
1656 {
1657 // Size the output arrays here instead of in the ctor in order to support
1658 // alternate sampling ctors.
1659 initialize_level_mappings();
1660 archive_allocate_mappings();
1661
1662 // For the samples array, calculate the following statistics:
1663 // > CDF/CCDF mappings of response levels to probability/reliability levels
1664 // > CDF/CCDF mappings of probability/reliability levels to response levels
1665 size_t i, j, k, num_obs = samples.size(), num_samp, bin_accumulator;
1666 const StringArray& resp_labels = iteratedModel.response_labels();
1667 std::multiset<Real> sorted_samples; // STL-based array for sorting
1668 SizetArray bins; Real min, max, sample;
1669
1670 // check if moments are required, and if so, compute them now
1671 if (momentStats.empty()) {
1672 bool need_moments = false;
1673 for (i=0; i<numFunctions; ++i)
1674 if ( !requestedRelLevels[i].empty() ||
1675 ( !requestedRespLevels[i].empty() &&
1676 respLevelTarget == RELIABILITIES ) )
1677 { need_moments = true; break; }
1678 if (need_moments) {
1679 Cerr << "Error: required moments not available in compute_distribution_"
1680 << "mappings(). Call compute_moments() first." << std::endl;
1681 abort_handler(METHOD_ERROR);
1682 // Issue with the following approach is that subsequent invocations of
1683 // compute_level_mappings() without compute_moments() would not be
1684 // detected and old moments would be used. Performing more rigorous
1685 // bookkeeping of moment updates is overkill for current use cases.
1686 //Cerr << "Warning: moments not available in compute_distribution_"
1687 // << "mappings(); computing them now." << std::endl;
1688 //compute_moments(samples);
1689 }
1690 }
1691
1692 if (pdfOutput) extremeValues.resize(numFunctions);
1693 IntRespMCIter s_it; std::multiset<Real>::iterator ss_it;
1694 const ShortArray& final_asv = finalStatistics.active_set_request_vector();
1695 bool extrapolated_mappings = false,
1696 central_mom = (finalMomentsType == CENTRAL_MOMENTS);
1697 size_t cntr = 0,
1698 num_deriv_vars = finalStatistics.active_set_derivative_vector().size(),
1699 moment_offset = (finalMomentsType) ? 2 : 0;
1700 RealVector mean_grad, mom2_grad;
1701 for (i=0; i<numFunctions; ++i) {
1702
1703 // CDF/CCDF mappings: z -> p/beta/beta* and p/beta/beta* -> z
1704 size_t rl_len = requestedRespLevels[i].length(),
1705 pl_len = requestedProbLevels[i].length(),
1706 bl_len = requestedRelLevels[i].length(),
1707 gl_len = requestedGenRelLevels[i].length();
1708
1709 // ----------------------------------------------------------------------
1710 // Preliminaries: define finite subset, sort (if needed), and bin samples
1711 // ----------------------------------------------------------------------
1712 num_samp = 0;
1713 if (pl_len || gl_len) { // sort samples array for p/beta* -> z mappings
1714 sorted_samples.clear();
1715 for (s_it=samples.begin(); s_it!=samples.end(); ++s_it) {
1716 sample = s_it->second.function_value(i);
1717 if (std::isfinite(sample))
1718 { ++num_samp; sorted_samples.insert(sample); }
1719 }
1720 // sort in ascending order
1721 if (pdfOutput)
1722 { min = *sorted_samples.begin(); max = *(--sorted_samples.end()); }
1723 // in case of rl_len mixed with pl_len/gl_len, bin using sorted array.
1724 if (rl_len && respLevelTarget != RELIABILITIES) {
1725 const RealVector& req_rl_i = requestedRespLevels[i];
1726 bins.assign(rl_len+1, 0); ss_it = sorted_samples.begin();
1727 for (j=0; j<rl_len; ++j)
1728 while (ss_it!=sorted_samples.end() && *ss_it <= req_rl_i[j])// p(g<=z)
1729 { ++bins[j]; ++ss_it; }
1730 bins[rl_len] += std::distance(ss_it, sorted_samples.end());
1731 }
1732 }
1733 else if (rl_len && respLevelTarget != RELIABILITIES) {
1734 // in case of rl_len without pl_len/gl_len, bin from original sample set
1735 const RealVector& req_rl_i = requestedRespLevels[i];
1736 bins.assign(rl_len+1, 0); min = DBL_MAX; max = -DBL_MAX;
1737 for (s_it=samples.begin(); s_it!=samples.end(); ++s_it) {
1738 sample = s_it->second.function_value(i);
1739 if (std::isfinite(sample)) {
1740 ++num_samp;
1741 if (pdfOutput) {
1742 if (sample < min) min = sample;
1743 if (sample > max) max = sample;
1744 }
1745 // 1st PDF bin from -inf to 1st resp lev; last PDF bin from last resp
1746 // lev to +inf.
1747 bool found = false;
1748 for (k=0; k<rl_len; ++k)
1749 if (sample <= req_rl_i[k]) // cumulative p(g<=z)
1750 { ++bins[k]; found = true; break; }
1751 if (!found)
1752 ++bins[rl_len];
1753 }
1754 }
1755 }
1756 if (pdfOutput)
1757 { extremeValues[i].first = min; extremeValues[i].second = max; }
1758
1759 cntr += moment_offset;
1760 // ----------------
1761 // Process mappings
1762 // ----------------
1763 if (rl_len) {
1764 switch (respLevelTarget) {
1765 case PROBABILITIES: case GEN_RELIABILITIES: // z -> p/beta* (from binning)
1766 bin_accumulator = 0;
1767 for (j=0; j<rl_len; ++j, ++cntr) { // compute CDF/CCDF p/beta*
1768 bin_accumulator += bins[j];
1769 Real cdf_prob = (Real)bin_accumulator/(Real)num_samp;
1770 Real computed_prob = (cdfFlag) ? cdf_prob : 1. - cdf_prob;
1771 if (respLevelTarget == PROBABILITIES)
1772 computedProbLevels[i][j] = computed_prob;
1773 else
1774 computedGenRelLevels[i][j]
1775 = -Pecos::NormalRandomVariable::inverse_std_cdf(computed_prob);
1776 }
1777 break;
1778 case RELIABILITIES: { // z -> beta (from moment projection)
1779 Real mean = momentStats(0,i);
1780 Real stdev = (central_mom) ?
1781 std::sqrt(momentStats(1,i)) : momentStats(1,i);
1782 if (!momentGrads.empty()) {
1783 int i2 = 2*i;
1784 mean_grad = Teuchos::getCol(Teuchos::View, momentGrads, i2);
1785 mom2_grad = Teuchos::getCol(Teuchos::View, momentGrads, i2+1);
1786 }
1787 for (j=0; j<rl_len; j++, ++cntr) {
1788 // *** beta
1789 Real z_bar = requestedRespLevels[i][j];
1790 if (stdev > Pecos::SMALL_NUMBER)
1791 computedRelLevels[i][j] = (cdfFlag) ?
1792 (mean - z_bar)/stdev : (z_bar - mean)/stdev;
1793 else
1794 computedRelLevels[i][j]
1795 = ( (cdfFlag && mean <= z_bar) || (!cdfFlag && mean > z_bar) )
1796 ? -Pecos::LARGE_NUMBER : Pecos::LARGE_NUMBER;
1797 // *** beta gradient
1798 if (final_asv[cntr] & 2) {
1799 RealVector beta_grad = finalStatistics.function_gradient_view(cntr);
1800 if (stdev > Pecos::SMALL_NUMBER) {
1801 for (k=0; k<num_deriv_vars; ++k) {
1802 Real stdev_grad = (central_mom) ?
1803 mom2_grad[k] / (2.*stdev) : mom2_grad[k];
1804 Real dratio_dx = (stdev*mean_grad[k] - (mean-z_bar)*stdev_grad)
1805 / std::pow(stdev, 2);
1806 beta_grad[k] = (cdfFlag) ? dratio_dx : -dratio_dx;
1807 }
1808 }
1809 else
1810 beta_grad = 0.;
1811 }
1812 }
1813 break;
1814 }
1815 }
1816 }
1817 for (j=0; j<pl_len+gl_len; j++, ++cntr) { // p/beta* -> z
1818 Real p = (j<pl_len) ? requestedProbLevels[i][j] : Pecos::
1819 NormalRandomVariable::std_cdf(-requestedGenRelLevels[i][j-pl_len]);
1820 Real p_cdf = (cdfFlag) ? p : 1. - p;
1821 // since each sample has 1/N probability, p can be directly converted
1822 // to an index within sorted_samples (id = p * N; index = id - 1)
1823 // Note 1: duplicate samples are not aggregated (separate id increments).
1824 // Note 2: since p_cdf(min_sample) = 1/N and p_cdf(max_sample) = 1, we
1825 // extrapolate to the left of min, but not to the right of max.
1826 // id < 1 indicates this extrapolation left of the min sample.
1827 // Note 3: we exclude any extrapolated z from extremeValues; should we
1828 // omit any out-of-bounds resp levels within NonD::compute_densities()?
1829 // --> PDF estimation based only on z->p binning or p->z interpolation
1830 // within the sample bounds.
1831 Real cdf_incr_id = p_cdf * (Real)num_samp, lo_id;
1832 ss_it = sorted_samples.begin();
1833 if (cdf_incr_id < 1.) { // extrapolate left of min sample using 1st slope
1834 lo_id = 1.; extrapolated_mappings = true;
1835 Cerr << "Warning: extrapolation required for response " << i+1;
1836 if (j<pl_len) Cerr << " for probability level " << j+1 <<".\n";
1837 else Cerr << " for generalized reliability level " << j+1-pl_len<<".\n";
1838 }
1839 else { // linear interpolation between closest neighbors in sequence
1840 lo_id = std::floor(cdf_incr_id);
1841 std::advance(ss_it, (size_t)lo_id - 1);
1842 }
1843 Real z, z_lo = *ss_it; ++ss_it;
1844 if (ss_it == sorted_samples.end()) z = z_lo;
1845 else z = z_lo + (cdf_incr_id - lo_id) * (*ss_it - z_lo);
1846 if (j<pl_len) computedRespLevels[i][j] = z;
1847 else computedRespLevels[i][j+bl_len] = z;
1848 }
1849 if (bl_len) {
1850 Real mean = momentStats(0,i);
1851 Real stdev = (finalMomentsType == CENTRAL_MOMENTS) ?
1852 std::sqrt(momentStats(1,i)) : momentStats(1,i);
1853 if (!momentGrads.empty()) {
1854 int i2 = 2*i;
1855 mean_grad = Teuchos::getCol(Teuchos::View, momentGrads, i2);
1856 mom2_grad = Teuchos::getCol(Teuchos::View, momentGrads, i2+1);
1857 }
1858 for (j=0; j<bl_len; j++, ++cntr) {
1859 // beta_bar -> z
1860 Real beta_bar = requestedRelLevels[i][j];
1861 computedRespLevels[i][j+pl_len] = (cdfFlag) ?
1862 mean - beta_bar * stdev : mean + beta_bar * stdev;
1863 // *** z gradient
1864 if (final_asv[cntr] & 2) {
1865 RealVector z_grad = finalStatistics.function_gradient_view(cntr);
1866 for (k=0; k<num_deriv_vars; ++k) {
1867 Real stdev_grad = (central_mom) ?
1868 mom2_grad[k] / (2.*stdev) : mom2_grad[k];
1869 z_grad[k] = (cdfFlag) ? mean_grad[k] - beta_bar * stdev_grad
1870 : mean_grad[k] + beta_bar * stdev_grad;
1871 }
1872 }
1873 }
1874 }
1875 }
1876
1877 if (extrapolated_mappings)
1878 Cerr << "Warning: extrapolations required to evaluate inverse mappings. "
1879 << "Consistent slope\n (uniform density) assumed for "
1880 << "extrapolation into distribution tail.\n\n";
1881
1882 // post-process computed z/p/beta* levels to form PDFs (prob_refined and
1883 // all_levels_computed default to false). embedding this call within
1884 // compute_level_mappings() simplifies management of min/max.
1885 compute_densities(extremeValues);
1886 }
1887
1888
update_final_statistics()1889 void NonDSampling::update_final_statistics()
1890 {
1891 if (finalStatistics.is_null()) // some ctor chains do not track final stats
1892 return;
1893
1894 if (epistemicStats) {
1895 size_t i, cntr = 0;
1896 for (i=0; i<numFunctions; ++i) {
1897 finalStatistics.function_value(extremeValues[i].first, cntr++);
1898 finalStatistics.function_value(extremeValues[i].second, cntr++);
1899 }
1900 }
1901 else // moments + level mappings
1902 NonD::update_final_statistics();
1903 }
1904
1905
print_statistics(std::ostream & s) const1906 void NonDSampling::print_statistics(std::ostream& s) const
1907 {
1908 if (epistemicStats) // output only min & max values in the epistemic case
1909 print_intervals(s);
1910 else {
1911 print_moments(s);
1912 if (totalLevelRequests) {
1913 print_level_mappings(s);
1914 print_system_mappings(s);
1915 }
1916 if( wilksFlag )
1917 print_wilks_stastics(s); //, "response function", iteratedModel.response_labels());
1918 }
1919 if (!subIteratorFlag) {
1920 StringMultiArrayConstView
1921 acv_labels = iteratedModel.all_continuous_variable_labels(),
1922 adiv_labels = iteratedModel.all_discrete_int_variable_labels(),
1923 adsv_labels = iteratedModel.all_discrete_string_variable_labels(),
1924 adrv_labels = iteratedModel.all_discrete_real_variable_labels();
1925 size_t cv_start, num_cv, div_start, num_div, dsv_start, num_dsv,
1926 drv_start, num_drv;
1927 mode_counts(iteratedModel.current_variables(), cv_start, num_cv,
1928 div_start, num_div, dsv_start, num_dsv, drv_start, num_drv);
1929 StringMultiArrayConstView
1930 cv_labels =
1931 acv_labels[boost::indices[idx_range(cv_start, cv_start+num_cv)]],
1932 div_labels =
1933 adiv_labels[boost::indices[idx_range(div_start, div_start+num_div)]],
1934 dsv_labels =
1935 adsv_labels[boost::indices[idx_range(dsv_start, dsv_start+num_dsv)]],
1936 drv_labels =
1937 adrv_labels[boost::indices[idx_range(drv_start, drv_start+num_drv)]];
1938 nonDSampCorr.print_correlations(s, cv_labels, div_labels, dsv_labels,
1939 drv_labels,iteratedModel.response_labels());
1940 }
1941 }
1942
1943
1944 void NonDSampling::
print_intervals(std::ostream & s,String qoi_type,const StringArray & interval_labels) const1945 print_intervals(std::ostream& s, String qoi_type,
1946 const StringArray& interval_labels) const
1947 {
1948 s << std::scientific << std::setprecision(write_precision)
1949 << "\nMin and Max samples for each " << qoi_type << ":\n";
1950 size_t i, num_qoi = extremeValues.size();
1951 for (size_t i=0; i<num_qoi; ++i)
1952 s << interval_labels[i] << ": Min = " << extremeValues[i].first
1953 << " Max = " << extremeValues[i].second << '\n';
1954 }
1955
1956
1957 void NonDSampling::
print_moments(std::ostream & s,const RealMatrix & moment_stats,const RealMatrix moment_cis,String qoi_type,short moments_type,const StringArray & moment_labels,bool print_cis)1958 print_moments(std::ostream& s, const RealMatrix& moment_stats,
1959 const RealMatrix moment_cis, String qoi_type, short moments_type,
1960 const StringArray& moment_labels, bool print_cis)
1961 {
1962 size_t i, j, width = write_precision+7, num_moments = moment_stats.numRows(),
1963 num_qoi = moment_stats.numCols();
1964
1965 s << "\nSample moment statistics for each " << qoi_type << ":\n"
1966 << std::scientific << std::setprecision(write_precision)
1967 << std::setw(width+15) << "Mean";
1968 if (moments_type == CENTRAL_MOMENTS)
1969 s << std::setw(width+1) << "Variance" << std::setw(width+1) << "3rdCentral"
1970 << std::setw(width+2) << "4thCentral\n";
1971 else
1972 s << std::setw(width+1) << "Std Dev" << std::setw(width+1) << "Skewness"
1973 << std::setw(width+2) << "Kurtosis\n";
1974 //<< std::setw(width+2) << "Coeff of Var\n";
1975 for (i=0; i<num_qoi; ++i) {
1976 const Real* moments_i = moment_stats[i];
1977 s << std::setw(14) << moment_labels[i];
1978 for (j=0; j<num_moments; ++j)
1979 s << ' ' << std::setw(width) << moments_i[j];
1980 s << '\n';
1981 }
1982 if (print_cis && !moment_cis.empty()) {
1983 // output 95% confidence intervals as (,) interval
1984 s << "\n95% confidence intervals for each " << qoi_type << ":\n"
1985 << std::setw(width+15) << "LowerCI_Mean" << std::setw(width+1)
1986 << "UpperCI_Mean" << std::setw(width+1);
1987 if (moments_type == CENTRAL_MOMENTS)
1988 s << "LowerCI_Variance" << std::setw(width+2) << "UpperCI_Variance\n";
1989 else
1990 s << "LowerCI_StdDev" << std::setw(width+2) << "UpperCI_StdDev\n";
1991 for (i=0; i<num_qoi; ++i)
1992 s << std::setw(14) << moment_labels[i]
1993 << ' ' << std::setw(width) << moment_cis(0, i)
1994 << ' ' << std::setw(width) << moment_cis(1, i)
1995 << ' ' << std::setw(width) << moment_cis(2, i)
1996 << ' ' << std::setw(width) << moment_cis(3, i) << '\n';
1997 }
1998 }
1999
2000
2001 void NonDSampling::
print_wilks_stastics(std::ostream & s) const2002 print_wilks_stastics(std::ostream& s) const
2003 {
2004 //std::multiset<Real> sorted_resp;
2005 //IntRespMCIter it2;
2006 //std::multiset<Real>::const_iterator cit2;
2007 //for (int i=0; i<numFunctions; ++i) {
2008 // sorted_resp.clear();
2009 // for( it2 = allResponses.begin(); it2!=allResponses.end(); ++it2)
2010 // {
2011 // Cout << "It #" << it2->first << "\t" << it2->second.function_value(i) << std::endl;
2012 // sorted_resp.insert(it2->second.function_value(i));
2013 // }
2014 // int count = 0;
2015 // for( it2 = allResponses.begin(), cit2 = sorted_resp.begin(); cit2 != sorted_resp.end(); ++cit2, ++count, ++it2 )
2016 // Cout << "It #" << count << "\t" << it2->second.function_value(i) << "\t" << *cit2 << std::endl;
2017 //}
2018
2019 bool wilks_twosided = (wilksSidedness == TWO_SIDED);
2020
2021 size_t j, width = write_precision+7, w2p2 = 2*width+2, w3p4 = 3*width+4;
2022
2023 std::multiset<Real> sorted_resp_subset;
2024 std::multiset<Real>::const_iterator cit;
2025 std::multiset<Real>::const_reverse_iterator crit;
2026 IntRespMCIter it;
2027 int n;
2028 Real min, max;
2029
2030 for (size_t fn_index=0; fn_index<numFunctions; ++fn_index) {
2031 s << "\n\n" << "Wilks Statistics for "
2032 << (wilks_twosided ? "Two-" : "One-") << "Sided "
2033 << 100.0*wilksBeta << "% Confidence Level, Order = " << wilksOrder
2034 << " for " << iteratedModel.response_labels()[fn_index] << ":\n\n";
2035
2036 if(wilks_twosided) {
2037 s << " Coverage Level Lower Bound Upper Bound Number of Samples\n"
2038 << " -------------- ----------------- ----------------- -----------------\n";
2039 } else {
2040 s << " Coverage Level " << (wilksSidedness == ONE_SIDED_UPPER ? "Upper" : "Lower")
2041 << " Bound Number of Samples\n"
2042 << " -------------- ----------------- -----------------\n";
2043 }
2044
2045 // Create a default probability level if none given
2046 RealVector prob_levels;
2047 size_t num_prob_levels = requestedProbLevels[fn_index].length();
2048 if( 0 == num_prob_levels ) {
2049 num_prob_levels = 1;
2050 prob_levels.resize(1);
2051 prob_levels[0] = 0.95; // default probability level
2052 }
2053 else
2054 prob_levels = requestedProbLevels[fn_index];
2055
2056 for (j=0; j<num_prob_levels; ++j)
2057 {
2058 Real prob_level = prob_levels[j];
2059 int num_samples = compute_wilks_sample_size(wilksOrder, prob_level, wilksBeta, wilks_twosided);
2060
2061 // Grab the first num_samples subset in sorted order (could also randomly sample) - RWH
2062 sorted_resp_subset.clear();
2063 for (n=0, it=allResponses.begin(); n<num_samples; ++n, ++it)
2064 {
2065 Real sample = it->second.function_value(fn_index);
2066 if (std::isfinite(sample)) // neither NaN nor +/-Inf
2067 sorted_resp_subset.insert(sample);
2068 }
2069 cit = sorted_resp_subset.begin();
2070 crit = sorted_resp_subset.rbegin();
2071 for( int i=0; i<wilksOrder-1; ++i, ++cit, ++crit ) continue;
2072 min = *cit;
2073 max = *crit;
2074
2075 s << " " << std::setw(width) << prob_levels[j];
2076 if( wilks_twosided )
2077 s << " " << min;
2078 s << " " << ( (wilks_twosided || wilksSidedness == ONE_SIDED_UPPER) ? max : min )
2079 << " " << num_samples
2080 << '\n';
2081 }
2082 }
2083 }
2084
2085 } // namespace Dakota
2086