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 // Results database supporting definitions
10 // * Data type definitions for keys and meta data
11 // * Free helper functions to create and manage data entries
12
13 #ifndef DAKOTA_RESULTS_TYPES_H
14 #define DAKOTA_RESULTS_TYPES_H
15
16 #include <map>
17 #include <vector>
18 #include <algorithm>
19 #include <boost/tuple/tuple.hpp>
20 #include "dakota_data_types.hpp"
21 #include <boost/any.hpp>
22 #include <boost/variant.hpp>
23 #include <iostream>
24
25 namespace Dakota {
26
27 // TODO: Using a tokenized string "instance::execution::result_key" or
28 // a list of keys might be more flexible going forward, instead of tuple.
29
30 // -----------
31 // Results Key
32 // -----------
33
34 /// Data type for results key (instance name / id, unique run, label),
35 /// where data_key is a valid colon-delimited string from ResultsNames
36 /// tuple<method_name, method_id, execution_number, data_key>
37 typedef
38 boost::tuple<std::string, std::string, size_t, std::string> ResultsKeyType;
39
40
41 // -----------
42 // Results Data
43 // -----------
44
45 // NOTE: the ResultsDataType varies by underlying database
46
47
48 // ----------------
49 // Results Metadata
50 // ----------------
51
52 /// Data type for metadata key
53 typedef std::string MetaDataKeyType;
54
55 /// Data type for metadata value
56 typedef std::vector<std::string> MetaDataValueType;
57
58 /// A single MetaData entry is map<string, vector<string> > Example:
59 /// pair( "Column labels", ["Mean", "Std Dev", "Skewness", "Kurtosis"] )
60 typedef std::map<MetaDataKeyType, MetaDataValueType> MetaDataType;
61
62
63 // --------------
64 // Other Typedefs
65 // --------------
66
67 // TODO: This can probably go away
68 //typedef std::pair<std::string, size_t> StringSizetPair;
69
70 /// Iterator unique ID: <method_name, method_id, exec_num>
71 typedef boost::tuple<std::string, std::string, size_t> StrStrSizet;
72
73 /// Make a full ResultsKeyType from the passed iterator_id and data_name
74 ResultsKeyType make_key(const StrStrSizet& iterator_id,
75 const std::string& data_name);
76
77 /// create MetaDataValueType from the passed strings
78 MetaDataValueType
79 make_metadatavalue(StringMultiArrayConstView labels);
80
81 /// create MetaDataValueType from the passed strings
82 MetaDataValueType
83 make_metadatavalue(StringMultiArrayConstView cv_labels,
84 StringMultiArrayConstView div_labels,
85 StringMultiArrayConstView drv_labels,
86 const StringArray& resp_labels);
87
88 /// create MetaDataValueType from the passed strings
89 MetaDataValueType
90 make_metadatavalue(const StringArray& resp_labels);
91
92 /// create MetaDataValueType from the passed strings
93 MetaDataValueType
94 make_metadatavalue(const std::string&);
95
96 /// create MetaDataValueType from the passed strings
97 MetaDataValueType
98 make_metadatavalue(const std::string&, const std::string&);
99
100 /// create MetaDataValueType from the passed strings
101 MetaDataValueType
102 make_metadatavalue(const std::string&, const std::string&,
103 const std::string&);
104
105 /// create MetaDataValueType from the passed strings
106 MetaDataValueType
107 make_metadatavalue(const std::string&, const std::string&,
108 const std::string&, const std::string&);
109
110
111
112 // Inline definitions of helper functions
113
114 inline MetaDataValueType
make_metadatavalue(StringMultiArrayConstView labels)115 make_metadatavalue(StringMultiArrayConstView labels)
116 {
117 MetaDataValueType mdv;
118 for (size_t i=0; i<labels.size(); ++i)
119 mdv.push_back(labels[i]);
120 return mdv;
121 }
122
123
124 inline MetaDataValueType
make_metadatavalue(StringMultiArrayConstView cv_labels,StringMultiArrayConstView div_labels,StringMultiArrayConstView dsv_labels,StringMultiArrayConstView drv_labels,const StringArray & resp_labels)125 make_metadatavalue(StringMultiArrayConstView cv_labels,
126 StringMultiArrayConstView div_labels,
127 StringMultiArrayConstView dsv_labels,
128 StringMultiArrayConstView drv_labels,
129 const StringArray& resp_labels)
130 {
131 // could use iterators for some of these
132 MetaDataValueType mdv;
133 for (size_t i=0; i<cv_labels.size(); ++i)
134 mdv.push_back(cv_labels[i]);
135 for (size_t i=0; i<div_labels.size(); ++i)
136 mdv.push_back(div_labels[i]);
137 for (size_t i=0; i<dsv_labels.size(); ++i)
138 mdv.push_back(dsv_labels[i]);
139 for (size_t i=0; i<drv_labels.size(); ++i)
140 mdv.push_back(drv_labels[i]);
141 for (size_t i=0; i<resp_labels.size(); ++i)
142 mdv.push_back(resp_labels[i]);
143
144 return mdv;
145 }
146
147 inline MetaDataValueType
make_metadatavalue(const StringArray & resp_labels)148 make_metadatavalue(const StringArray& resp_labels)
149 {
150 // could use iterators for some of these
151 MetaDataValueType mdv;
152 for (size_t i=0; i<resp_labels.size(); ++i)
153 mdv.push_back(resp_labels[i]);
154
155 return mdv;
156 }
157
158 inline MetaDataValueType
make_metadatavalue(const std::string & s1)159 make_metadatavalue(const std::string& s1)
160 {
161 MetaDataValueType mdv;
162 mdv.push_back(s1);
163 return mdv;
164 }
165
166 inline MetaDataValueType
make_metadatavalue(const std::string & s1,const std::string & s2)167 make_metadatavalue(const std::string& s1, const std::string& s2)
168 {
169 MetaDataValueType mdv;
170 mdv.push_back(s1);
171 mdv.push_back(s2);
172 return mdv;
173 }
174
175 inline MetaDataValueType
make_metadatavalue(const std::string & s1,const std::string & s2,const std::string & s3)176 make_metadatavalue(const std::string& s1, const std::string& s2,
177 const std::string& s3)
178 {
179 MetaDataValueType mdv;
180 mdv.push_back(s1);
181 mdv.push_back(s2);
182 mdv.push_back(s3);
183 return mdv;
184 }
185
186 inline MetaDataValueType
make_metadatavalue(const std::string & s1,const std::string & s2,const std::string & s3,const std::string & s4)187 make_metadatavalue(const std::string& s1, const std::string& s2,
188 const std::string& s3, const std::string& s4)
189 {
190 MetaDataValueType mdv;
191 mdv.push_back(s1);
192 mdv.push_back(s2);
193 mdv.push_back(s3);
194 mdv.push_back(s4);
195 return mdv;
196 }
197
make_key(const StrStrSizet & iterator_id,const std::string & data_name)198 inline ResultsKeyType make_key(const StrStrSizet& iterator_id,
199 const std::string& data_name)
200 {
201 return ResultsKeyType(iterator_id.get<0>(),
202 iterator_id.get<1>(),
203 iterator_id.get<2>(),
204 data_name);
205 }
206
207 // The following structs and typedefs are used to insert
208 // results into the results database using the
209 // ResultsManager interface.
210 //
211 // The first set of items are for specifying dimension
212 // scales, which are labels (strings or reals) for each
213 // axis of a set of data (vector or matrix, currently).
214 //
215 // Dimension scales are of type multimap<int, boost::variant>
216 // (typedef'ed to DimScaleMap), with the integer indicating the
217 // dimenions of the dataset that the scale is associated with,
218 // and the boost::variant containing the scale
219 // itself, either a RealScale or a StringScale. These latter
220 // types are structs that contain a label, which is like a
221 // heading for the scale, the items in the scale, and a
222 // ScaleScope enum, which determines whether the scale is
223 // SHARED among multiple responses or is unique to a particular
224 // response (UNHSARED).
225
226 /// Enum to specify whether a scale shared among responses
227 enum class ScaleScope {SHARED, UNSHARED};
228
229 // RealScale and StringScale avoid making copies of data to
230 // save memory, which may be important for large results.
231 // For HDF5, the scales are immediately written to disk, and so
232 // it's not necessary for the client to preserve objects in
233 // memory after using a RealScale or StringScale in a call
234 // to ResultsManager.insert(...).
235
236 /// Data structure for storing real-valued dimension scale
237 struct RealScale {
238
239 /// Constructor that takes a RealVector
RealScaleDakota::RealScale240 RealScale(const std::string &label, const RealVector &in_items,
241 ScaleScope scope = ScaleScope::UNSHARED) :
242 label(label), scope(scope) {
243 items = RealVector(Teuchos::View, *const_cast<RealVector*>(&in_items));
244 numCols = items.length();
245 isMatrix = false;
246 }
247
248 /// Constructor that takes a RealArray
RealScaleDakota::RealScale249 RealScale(const std::string &label, const RealArray &in_items,
250 ScaleScope scope = ScaleScope::UNSHARED) :
251 label(label), scope(scope) {
252 items = RealVector(Teuchos::View, const_cast<Real*>(in_items.data()),
253 in_items.size());
254 numCols = items.length();
255 isMatrix = false;
256 }
257
258 /// Constructor that takes a pointer to Real and length
RealScaleDakota::RealScale259 RealScale(const std::string &label, const Real *in_items, const int len,
260 ScaleScope scope = ScaleScope::UNSHARED) :
261 label(label), scope(scope) {
262 items = RealVector(Teuchos::View,
263 const_cast<Real*>(in_items), len);
264 numCols = items.length();
265 isMatrix = false;
266 }
267
268 /// Constructor that takes an initializer_list.
RealScaleDakota::RealScale269 RealScale(const std::string & in_label,
270 std::initializer_list<Real> in_items,
271 ScaleScope in_scope = ScaleScope::UNSHARED) {
272 label = in_label;
273 int len = in_items.size();
274 items = RealVector(len);
275 // make a copy. Typically initializer_lists should be short, so this
276 // is excusable.
277 std::copy(in_items.begin(), in_items.end(), &items[0]);
278 scope = in_scope;
279 numCols = len;
280 isMatrix = false;
281 }
282
283 /// Constructor that takes a RealVectorArray
RealScaleDakota::RealScale284 RealScale(const std::string & in_label,
285 const RealVectorArray &in_items,
286 ScaleScope in_scope = ScaleScope::UNSHARED) {
287 label = in_label;
288 int num_rows = in_items.size();
289 numCols = in_items[0].length(); // assume all "rows" are the same length
290 items = RealVector(num_rows*numCols);
291 // impossible to avoid making a copy in this case.
292 for(int i = 0; i < num_rows; ++i)
293 for(int j = 0; j < numCols; ++j)
294 items[j*num_rows+i] = in_items[i][j]; // deliberately transposed. See AttachScaleVisitor in ResultsDBHDF5.hpp.
295 scope = in_scope;
296 isMatrix = true;
297 }
298
299 // Name of the scale
300 std::string label;
301 // Scope of the scale (whether it is shared among responses)
302 ScaleScope scope;
303 // Items in the scale; column-major when isMatrix is true
304 RealVector items;
305 /// Number of columns; equals length of scale when 1D
306 int numCols;
307 /// 2d or 1d?
308 bool isMatrix;
309 };
310
311 /// Data structure for storing int-valued dimension scale
312 struct IntegerScale {
313
314 /// Constructor that takes an IntVector
IntegerScaleDakota::IntegerScale315 IntegerScale(const std::string &label, const IntVector &in_items,
316 ScaleScope scope = ScaleScope::UNSHARED) :
317 label(label), scope(scope) {
318 items = IntVector(Teuchos::View, *const_cast<IntVector*>(&in_items));
319 numCols = items.length();
320 isMatrix = false;
321 }
322
323 /// Constructor that takes an IntArray
IntegerScaleDakota::IntegerScale324 IntegerScale(const std::string &label, const IntArray &in_items,
325 ScaleScope scope = ScaleScope::UNSHARED) :
326 label(label), scope(scope) {
327 items = IntVector(Teuchos::View, const_cast<int*>(in_items.data()),
328 in_items.size());
329 numCols = items.length();
330 isMatrix = false;
331 }
332
333 /// Constructor that takes a pointer to int and length
IntegerScaleDakota::IntegerScale334 IntegerScale(const std::string &label, const int *in_items, const int len,
335 ScaleScope scope = ScaleScope::UNSHARED) :
336 label(label), scope(scope) {
337 items = IntVector(Teuchos::View,
338 const_cast<int*>(in_items), len);
339 numCols = items.length();
340 isMatrix = false;
341 }
342
343 /// Constructor that takes an initializer_list.
IntegerScaleDakota::IntegerScale344 IntegerScale(const std::string & in_label,
345 std::initializer_list<int> in_items,
346 ScaleScope in_scope = ScaleScope::UNSHARED) {
347 label = in_label;
348 int len = in_items.size();
349 items = IntVector(len);
350 // make a copy. Typically initializer_lists should be short, so this
351 // is excusable.
352 std::copy(in_items.begin(), in_items.end(), &items[0]);
353 scope = in_scope;
354 numCols = len;
355 isMatrix = false;
356 }
357
358 // Name of the scale
359 std::string label;
360 // Scope of the scale (whether it is shared among responses)
361 ScaleScope scope;
362 // Items in the scale
363 IntVector items;
364 /// Number of columns; equals length of scale when 1D
365 int numCols;
366 /// 2d or 1d?
367 bool isMatrix;
368 };
369
370
371
372 /// Data structure for storing string-valued dimension scale
373 struct StringScale {
374 /// Constructor that takes a C-style array of C-strings
StringScaleDakota::StringScale375 StringScale(const std::string& in_label, const char * const in_items[],
376 const int &len, ScaleScope in_scope = ScaleScope::UNSHARED) {
377 label = in_label;
378 items.resize(len);
379 std::copy(in_items, in_items + len, items.begin());
380 scope = in_scope;
381 numCols = len;
382 isMatrix = false;
383 }
384
385 /// Constructor that takes and initializer list of string literals
StringScaleDakota::StringScale386 StringScale(const std::string & in_label,
387 std::initializer_list<const char *> in_items,
388 ScaleScope in_scope = ScaleScope::UNSHARED) {
389 label = in_label;
390 items.resize(in_items.size());
391 std::copy(in_items.begin(), in_items.end(), items.begin());
392 scope = in_scope;
393 numCols = items.size();
394 isMatrix = false;
395 }
396
397 /// Constructor that takes a vector of strings
StringScaleDakota::StringScale398 StringScale(const std::string& in_label, const std::vector<String> &in_items,
399 ScaleScope in_scope = ScaleScope::UNSHARED) {
400 label = in_label;
401 scope = in_scope;
402 items.resize(in_items.size());
403 std::transform(in_items.begin(), in_items.end(), items.begin(),
404 [](const String &s) { return s.c_str();});
405 numCols = items.size();
406 isMatrix = false;
407 }
408
409 /// Constructor that takes a vector of C-style strings
StringScaleDakota::StringScale410 StringScale(const std::string & in_label,
411 std::vector<const char *> in_items,
412 ScaleScope in_scope = ScaleScope::UNSHARED) {
413 label = in_label;
414 items.resize(in_items.size());
415 std::copy(in_items.begin(), in_items.end(), items.begin());
416 scope = in_scope;
417 numCols = items.size();
418 isMatrix = false;
419 }
420
421 /// Constructor that takes a StringMultiArrayConstView
StringScaleDakota::StringScale422 StringScale(const std::string & in_label,
423 const StringMultiArrayConstView in_items,
424 ScaleScope in_scope = ScaleScope::UNSHARED) {
425 label = in_label;
426 for( const auto & s: in_items)
427 items.push_back(s.c_str());
428 scope = in_scope;
429 numCols = items.size();
430 isMatrix = false;
431 }
432
433 /// Constructor that takes indexes into a StringArray
StringScaleDakota::StringScale434 StringScale(const std::string& in_label, const std::vector<String> &in_items,
435 const size_t first, const size_t num,
436 ScaleScope in_scope = ScaleScope::UNSHARED) {
437 label = in_label;
438 scope = in_scope;
439 items.resize(num);
440 for(int i = first, j = 0; i < first+num; ++i, ++j)
441 items[j] = in_items[i].c_str();
442 numCols = items.size();
443 isMatrix = false;
444 }
445
446
447 /// Constructor that takes a vector<vector<const char *> > to produce a 2D scale
StringScaleDakota::StringScale448 StringScale(const std::string & in_label,
449 std::vector<std::vector<const char *> > in_items,
450 ScaleScope in_scope = ScaleScope::UNSHARED) {
451 label = in_label;
452 int num_rows = in_items.size();
453 numCols = in_items[0].size(); // TODO: error checking to confirm a "square matrix"
454 items.resize(num_rows*numCols);
455 int offset = 0;
456 for(auto &v : in_items) {
457 std::copy(v.begin(), v.end(), items.begin() + offset);
458 offset += numCols;
459 }
460 scope = in_scope;
461 isMatrix = true;
462 }
463
464
465
466 /// Scale label
467 std::string label;
468 /// Scale scope (whether the scaled is shared among responses)
469 ScaleScope scope;
470 /// Pointers to the strings that make up the scale
471 std::vector<const char *> items;
472 /// Number of columns; equals length of scale when 1D
473 int numCols;
474 /// 2d or 1d?
475 bool isMatrix;
476 };
477
478 /// Datatype to communicate scales (stored in boost::variant) and their
479 /// associated dimension (the int) to the ResultsManager instance.
480 typedef std::multimap<int, boost::variant<StringScale, RealScale, IntegerScale> > DimScaleMap;
481
482
483 // HDF5 objects can have key:value metadata attached to them. These
484 // are called attributes. We support integer, real, and string valued
485 // metadata using these type defintions.
486
487 /// Data structure for a single Real, String, or int valued attribute
488 template <typename T>
489 struct ResultAttribute {
490 /// Construct an attribute
ResultAttributeDakota::ResultAttribute491 ResultAttribute(const String &label, const T &value) :
492 label(label), value(value) {};
493 /// Key for the attribute
494 String label;
495 /// Value for the attribute
496 T value;
497 };
498
499 /// Datatype to communcate metadata (attributes) to the ResultsManager
500 /// instance.
501 typedef std::vector<boost::variant< ResultAttribute<int>,
502 ResultAttribute<String>,
503 ResultAttribute<Real> > > AttributeArray;
504
505 /// enum for setting type on allocted matrix for Results Output
506 enum class ResultsOutputType { REAL, INTEGER, UINTEGER, STRING};
507
508 struct VariableParametersField {
VariableParametersFieldDakota::VariableParametersField509 VariableParametersField(const String &in_name, ResultsOutputType in_type,
510 const SizetArray &in_dims = SizetArray()) : name(in_name), dims(in_dims), type(in_type) {};
511 String name;
512 SizetArray dims;
513 ResultsOutputType type;
514 };
515
516 } // namespace Dakota
517
518 #endif // DAKOTA_RESULTS_TYPES_H
519