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: DataTransformModel
10 //- Description: Specialization of a RecastModel that manages the mapping from
11 //- a simulation model to residuals based on data differencing.
12 //- Owner: Brian Adams
13 //- Checked by:
14 //- Version: $Id$
15
16 #ifndef DATA_TRANSFORM_MODEL_H
17 #define DATA_TRANSFORM_MODEL_H
18
19 #include "RecastModel.hpp"
20 #include "dakota_results_types.hpp"
21 namespace Dakota {
22
23 /// forward declarations
24 class ExperimentData;
25 class ResultsManager;
26
27 // BMA TODO: Consider using separate RecastModel to include hyper-parameters
28
29 /// Data transformation specialization of RecastModel
30
31 /** Specialization of RecastModel to create a residual model that maps
32 (1) from an augmented set of calibration parameters (including
33 hyper-parameters) to those needed by the underlying simulation
34 model and (2) from the simulation model response to a set of
35 residuals, whose overall size may differ from the simulation
36 (sub-model) response. The residuals may be scaled by experiment
37 covariance information. This class provides a simple constructor
38 that forwards to the more complicated RecastModel API */
39 class DataTransformModel: public RecastModel
40 {
41 public:
42
43 //
44 //- Heading: Constructor and destructor
45 //
46
47 /// standard constructor
48 DataTransformModel(const Model& sub_model, const ExperimentData& exp_data,
49 size_t num_hyper = 0,
50 unsigned short mult_mode = CALIBRATE_NONE,
51 short recast_resp_deriv_order = 1);
52
53 /// destructor
54 ~DataTransformModel();
55
56 /// Convenience function to help recover a residual response from the submodel
57 void data_transform_response(const Variables& sub_model_vars,
58 const Response& sub_model_resp,
59 Response& residual_resp);
60
61 /// The size of the ExperimentData changed; update the residualModel size
62 void data_resize();
63
64
65 /// manage best responses including residuals and model responses per config
66 void print_best_responses(std::ostream& s,
67 const Variables& best_submodel_vars,
68 const Response& best_submodel_resp,
69 size_t num_best, size_t best_ind);
70
71 /// archive best responses
72 void archive_best_responses(const ResultsManager &results_db,
73 const StrStrSizet iterator_id,
74 const Variables& best_submodel_vars,
75 const Response& best_submodel_resp,
76 size_t num_best, size_t best_ind);
77
78 /// return number of configuration variables
79 int num_config_vars() const;
80
81 protected:
82
83 void assign_instance();
84
85 void update_from_subordinate_model(size_t depth =
86 std::numeric_limits<size_t>::max());
87
88 // ---
89 // Construct time convenience functions
90 // ---
91
92 /// expand the variable counts to account for hyper-parameters
93 static SizetArray variables_expand(const Model& sub_model, size_t num_hyper);
94
95 /// determine the index into vc_totals corresponding to where the
96 /// hyper-parameters go
97 static int get_hyperparam_vc_index(const Model& sub_model);
98
99 /// helper to compute the recast response order during member
100 /// initialization; recast_resp_order passed is the minimum request
101 /// client needs
102 static short response_order(const Model& sub_model,
103 short recast_resp_order = 1);
104
105 /// compute the primary response map for a data transform RecastModel
106 void gen_primary_resp_map(const SharedResponseData& srd,
107 Sizet2DArray& primary_resp_map_indices,
108 BoolDequeArray& nonlinear_resp_map) const;
109
110 /// specialization of evaluate that iterates over configuration variables
111 void derived_evaluate(const ActiveSet& set);
112 /// specialization of evaluate that iterates over configuration variables
113 void derived_evaluate_nowait(const ActiveSet& set);
114
115 /// synchronize all evaluations (all residuals for all experiment
116 /// configurations)
117 const IntResponseMap& derived_synchronize();
118
119 /// return any evaluations for which all experiment configurations
120 /// have completed
121 const IntResponseMap& derived_synchronize_nowait();
122
123 // Synchronize the subModel and filter the IntResponseMap in-place,
124 // caching any that we didn't schedule.
125 const IntResponseMap& filter_submodel_responses();
126
127 /// cache the subModel responses into a per-RecastModel eval ID map
128 void cache_submodel_responses(const IntResponseMap& sm_resp_map,
129 bool deep_copy);
130
131 /// collect any (or force all) completed subModel evals and populate
132 /// recastResponseMap with residuals for those that are fully completed
133 void collect_residuals(bool collect_all);
134
135 /// transform a set of per-configuration subModel Responses to a
136 /// single evaluation's residuals
137 void transform_response_map(const IntResponseMap& submodel_resp,
138 const Variables& recast_vars,
139 Response& residual_resp) ;
140
141 // ---
142 // Callback functions that perform data transform during the Recast operations
143 // ---
144
145 /// map the inbound expanded variables to the sub-model, discarding
146 /// hyperparams (assumes hyper-parameters are at end of active
147 /// continuous variables)
148 static void vars_mapping(const Variables& recast_vars,
149 Variables& submodel_vars);
150
151 // BMA TODO: inverse isn't well-defined, but may need for active vars...
152
153 /// map the inbound ActiveSet to the sub-model (map derivative variables)
154 static void set_mapping(const Variables& recast_vars,
155 const ActiveSet& recast_set,
156 ActiveSet& sub_model_set);
157
158 // BMA TODO: shouldn't need static in this context; find another way
159 /// Recast callback function to difference residuals with observed data
160 static void primary_resp_differencer(const Variables& submodel_vars,
161 const Variables& recast_vars,
162 const Response& submodel_response,
163 Response& recast_response);
164
165 /// scale the populated residual response by any covariance
166 /// information, including hyper-parameter multipliers
167 void scale_response(const Variables& submodel_vars,
168 const Variables& recast_vars,
169 Response& recast_response);
170
171 // NOTE: Shouldn't need non-default active set or secondary response
172 // recast; default based on indices should suffice.
173
174 /// Initialize continuous variable values/labels
175 void init_continuous_vars();
176
177 // TODO: Update comments
178
179 /// (if non-empty) expand submodel_array by replicates to populate a
180 /// recast_array
181
182 /// If size greater than 1, expand submodel_array by replicates to
183 /// populate a pre-sized recast_array, otherwise copy
184
185 template<typename T>
186 void expand_primary_array(size_t submodel_size, const T& submodel_array,
187 size_t recast_size, T& recast_array) const;
188
189 void print_residual_response(const Response& resid_resp);
190
191 void recover_submodel_responses(std::ostream& s,
192 const Variables& best_submodel_vars,
193 size_t num_best, size_t best_ind,
194 Response& residual_resp);
195
196 /// archive original model responses
197 void archive_submodel_responses(const ResultsManager &results_db,
198 const StrStrSizet &iterator_id,
199 const Variables& best_submodel_vars,
200 size_t num_best, size_t best_ind,
201 Response& residual_resp);
202
203
204 /// Archive the best model reponses (undifferenced with experimental data) for
205 /// experiment exp_index and final solution soln_index.
206 void archive_best_original(const ResultsManager &results_db,
207 const StrStrSizet &iterator_id,
208 const RealVector &function_values,
209 const int &exp_index, const int &num_best,
210 const int &best_index);
211
212 /// Archive the best configuration variables associated with each model response
213 void archive_best_config_variables(const ResultsManager &results_db,
214 const StrStrSizet &iterator_id,
215 const Variables &vars,
216 const int &exp_index, const int &num_best,
217 const int &best_index);
218
219 /// Archive the best residuals
220 void archive_best_residuals(const ResultsManager &results_db,
221 const StrStrSizet &iterator_id,
222 const int num_fns,
223 const RealVector &best_terms,
224 const Real wssr, const int num_points,
225 const int point_index);
226 /// Reference to the experiment data used to construct this Model
227 const ExperimentData& expData;
228
229 /// static pointer to this class for use in static callbacks
230 static DataTransformModel* dtModelInstance;
231
232 /// Number of calibrated variance multipliers
233 size_t numHyperparams;
234
235 /// Calibration mode for the hyper-parameters
236 unsigned short obsErrorMultiplierMode;
237
238 // BMA TODO: fix this terrible typedef
239 typedef std::map<int, IntResponseMap> IntIntResponseMapMap;
240 IntIntResponseMapMap cachedResp;
241
242 };
243
244
assign_instance()245 inline void DataTransformModel::assign_instance()
246 { dtModelInstance = this; }
247
248
update_from_subordinate_model(size_t depth)249 inline void DataTransformModel::update_from_subordinate_model(size_t depth)
250 {
251 // data flows from the bottom-up, so recurse first
252 if (depth == std::numeric_limits<size_t>::max())
253 subModel.update_from_subordinate_model(depth); // retain special value (inf)
254 else if (depth)
255 subModel.update_from_subordinate_model(depth - 1); // decrement
256 //else depth exhausted --> update this level only
257
258 // Instead of RecastModel::update_from_model(subModel), manage pieces
259 // of the base implementation to avoid indexing inconsistencies due to
260 // hyper-parameter insertion:
261
262 bool update_active_complement = update_variables_from_model(subModel);
263 // Can't do this due if complement variables are re-indexed due to
264 // hyper-parameter insertion.
265 // *** TO DO: write new update fns for this type of variable growth -> don't
266 // *** break chain of updates for additional Model recursions above this one.
267 if (update_active_complement && !numHyperparams)
268 update_variables_active_complement_from_model(subModel);
269 update_response_from_model(subModel);
270 }
271
272 } // namespace Dakota
273
274 #endif
275