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:        ParamResponsePair
10 //- Description:  A container for a variables object, a response object,
11 //-               and interface and evaluation ids.
12 //-
13 //- Owner:        Mike Eldred
14 //- Version: $Id
15 
16 #ifndef PARAM_RESPONSE_PAIR_H
17 #define PARAM_RESPONSE_PAIR_H
18 
19 #include "dakota_data_types.hpp"
20 #include "dakota_data_io.hpp"
21 #include "DakotaVariables.hpp"
22 #include "DakotaResponse.hpp"
23 
24 namespace Dakota {
25 
26 
27 /// Container class for a variables object, a response object, and an
28 /// evaluation id.
29 
30 /** ParamResponsePair provides a container class for association of
31     the input for a particular function evaluation (a variables
32     object) with the output from this function evaluation (a response
33     object), along with an evaluation identifier.  This container
34     defines the basic unit used in the data_pairs cache, in restart
35     file operations, and in a variety of scheduling algorithm queues.
36     With the advent of STL, replacement of arrays of this class with
37     map<> and pair<> template constructs may be possible (using
38     map<pair<int,String>, pair<Variables,Response> >, for example),
39     assuming that deep copies, I/O, alternate constructors, etc., can
40     be adequately addressed.  Boost tuple<> may also be a candidate. */
41 
42 class ParamResponsePair
43 {
44   //
45   //- Heading: Friends
46   //
47 
48   /// equality operator
49   friend bool operator==(const ParamResponsePair& pair1,
50 			 const ParamResponsePair& pair2);
51   /// inequality operator
52   friend bool operator!=(const ParamResponsePair& pair1,
53 			 const ParamResponsePair& pair2);
54 
55   /// allow boost access to serialize this class
56   friend class boost::serialization::access;
57 
58 public:
59 
60   //
61   //- Heading: Constructors, destructor, assignment operator
62   //
63 
64   /// default constructor
65   ParamResponsePair();
66   /// alternate constructor for temporaries
67   ParamResponsePair(const Variables& vars, const String& interface_id,
68 		    const Response& response, bool deep_copy = false);
69   /// standard constructor for history uses
70   ParamResponsePair(const Variables& vars, const String& interface_id,
71 		    const Response& response, const int eval_id,
72 		    bool deep_copy = true);
73   /// copy constructor
74   ParamResponsePair(const ParamResponsePair& pair);
75 
76   /// destructor
77   ~ParamResponsePair();
78 
79   /// assignment operator
80   ParamResponsePair& operator=(const ParamResponsePair& pair);
81 
82   //
83   //- Heading: Member functions
84   //
85 
86   /// read a ParamResponsePair object from an std::istream
87   void read(std::istream& s);
88   /// write a ParamResponsePair object to an std::ostream
89   void write(std::ostream& s)           const;
90 
91   /// read a ParamResponsePair object in annotated format from an std::istream
92   void read_annotated(std::istream& s);
93   /// write a ParamResponsePair object in annotated format to an std::ostream
94   void write_annotated(std::ostream& s) const;
95 
96   /// write a ParamResponsePair object in tabular format (all
97   /// variables active/inactive) to an std::ostream
98   void write_tabular(std::ostream& s, unsigned short tabular_format) const;
99 
100   /// write PRP labels in tabular format to an std::ostream
101   void write_tabular_labels(std::ostream& s,
102 			    unsigned short tabular_format) const;
103 
104   /// read a ParamResponsePair object from a packed MPI buffer
105   void read(MPIUnpackBuffer& s);
106   /// write a ParamResponsePair object to a packed MPI buffer
107   void write(MPIPackBuffer& s)     const;
108 
109   //
110   //- Heading: Set and Inquire functions
111   //
112 
113   /// return the evaluation identifier
114   int eval_id() const;
115   /// set the evaluation identifier
116   void eval_id(int id);
117 
118   /// return the interface identifier from evalInterfaceIds
119   const String& interface_id() const;
120   /// set the interface identifier within evalInterfaceIds
121   void interface_id(const String& id);
122 
123   /// return the aggregate eval/interface identifier from the response object
124   const IntStringPair& eval_interface_ids() const;
125 
126   /// return the parameters object
127   const Variables& variables() const;
128   /// return the parameters object
129   Variables& variables();
130   /// set the parameters object
131   void variables(const Variables& vars);
132 
133   /// return the response object
134   const Response& response() const;
135   /// return the response object
136   Response& response();
137   /// set the response object
138   void response(const Response& resp);
139 
140   /// return the active set object from the response object
141   const ActiveSet& active_set() const;
142   /// set the active set object within the response object
143   void active_set(const ActiveSet& set);
144 
145 private:
146 
147   /// serialize the PRP: write and read are symmetric for this class
148   template<class Archive>
149   void serialize(Archive& ar, const unsigned int version);
150 
151   //
152   //- Heading: Data
153   //
154 
155   /// the set of parameters for the function evaluation
156   Variables prpVariables;
157   /// the response set for the function evaluation
158   Response  prpResponse;
159 
160   /// the evalInterfaceIds aggregate
161   /** the function evaluation identifier (assigned from Interface::evalIdCntr)
162       is paired with the interface used to generate the response object.  Used
163       in PRPCache id_vars_set_compare to prevent duplicate detection on results
164       from different interfaces.  evalInterfaceIds belongs here rather than in
165       Response since some Response objects involve consolidation of several fn
166       evals (e.g., Model::synchronize_derivatives()) that are not, in total,
167       generated by a single interface.  The prPair, on the other hand, is
168       used for storage of all low level fn evals that get evaluated in
169       ApplicationInterface::map(). */
170   IntStringPair evalInterfaceIds;
171 };
172 
173 
ParamResponsePair()174 inline ParamResponsePair::ParamResponsePair()
175 { }
176 
177 
178 /** Uses of this constructor often employ the standard Variables and
179     Response copy constructors to share representations since this
180     constructor is commonly used for search_pairs (which are local
181     instantiations that go out of scope prior to any changes to
182     values; i.e., they are not used for history). */
183 inline ParamResponsePair::
ParamResponsePair(const Variables & vars,const String & interface_id,const Response & response,bool deep_copy)184 ParamResponsePair(const Variables& vars, const String& interface_id,
185 		  const Response& response, bool deep_copy):
186   prpVariables( (deep_copy) ? vars.copy()     : vars     ),
187   prpResponse(  (deep_copy) ? response.copy() : response ),
188   evalInterfaceIds(0, interface_id)
189 { }
190 
191 
192 /** Uses of this constructor often do not share representations since
193     deep copies are used when history mechanisms (e.g., data_pairs and
194     beforeSynchCorePRPQueue) are involved. */
195 inline ParamResponsePair::
ParamResponsePair(const Variables & vars,const String & interface_id,const Response & response,const int eval_id,bool deep_copy)196 ParamResponsePair(const Variables& vars, const String& interface_id,
197 		  const Response& response, const int eval_id, bool deep_copy):
198   prpVariables( (deep_copy) ? vars.copy()     : vars     ),
199   prpResponse(  (deep_copy) ? response.copy() : response ),
200   evalInterfaceIds(eval_id, interface_id)
201 { }
202 
203 
ParamResponsePair(const ParamResponsePair & pair)204 inline ParamResponsePair::ParamResponsePair(const ParamResponsePair& pair):
205   prpVariables(pair.prpVariables), prpResponse(pair.prpResponse),
206   evalInterfaceIds(pair.evalInterfaceIds)
207 { }
208 
209 
210 inline ParamResponsePair&
operator =(const ParamResponsePair & pair)211 ParamResponsePair::operator=(const ParamResponsePair& pair)
212 {
213   prpVariables     = pair.prpVariables;
214   prpResponse      = pair.prpResponse;
215   evalInterfaceIds = pair.evalInterfaceIds;
216 
217   return *this;
218 }
219 
220 
~ParamResponsePair()221 inline ParamResponsePair::~ParamResponsePair()
222 { }
223 
224 
eval_id() const225 inline int ParamResponsePair::eval_id() const
226 { return evalInterfaceIds.first; }
227 
228 
eval_id(int id)229 inline void ParamResponsePair::eval_id(int id)
230 { evalInterfaceIds.first = id; }
231 
232 
interface_id() const233 inline const String& ParamResponsePair::interface_id() const
234 { return evalInterfaceIds.second; }
235 
236 
interface_id(const String & id)237 inline void ParamResponsePair::interface_id(const String& id)
238 { evalInterfaceIds.second = id; }
239 
240 
eval_interface_ids() const241 inline const IntStringPair& ParamResponsePair::eval_interface_ids() const
242 { return evalInterfaceIds; }
243 
244 
variables() const245 inline const Variables& ParamResponsePair::variables() const
246 { return prpVariables; }
247 
248 
variables()249 inline Variables& ParamResponsePair::variables()
250 { return prpVariables; }
251 
252 
variables(const Variables & vars)253 inline void ParamResponsePair::variables(const Variables& vars)
254 { prpVariables = vars; }
255 
256 
response() const257 inline const Response& ParamResponsePair::response() const
258 { return prpResponse; }
259 
260 
response()261 inline Response& ParamResponsePair::response()
262 { return prpResponse; }
263 
264 
response(const Response & resp)265 inline void ParamResponsePair::response(const Response& resp)
266 { prpResponse = resp; }
267 
268 
active_set() const269 inline const ActiveSet& ParamResponsePair::active_set() const
270 { return prpResponse.active_set(); }
271 
272 
active_set(const ActiveSet & set)273 inline void ParamResponsePair::active_set(const ActiveSet& set)
274 { prpResponse.active_set(set); }
275 
276 
277 // The binary read and write operators are used to read from and write to the
278 // binary restart file and the ASCII write operator is used to echo a pair
279 // read from the restart file to cout (in manage_restart() in main.cpp). The
280 // ASCII read operator is not currently used. The MPIPackBuffer/MPIUnpackBuffer
281 // operators are used to pass a source point for the continuation algorithm.
read(std::istream & s)282 inline void ParamResponsePair::read(std::istream& s)
283 { s >> prpVariables >> prpResponse; }
284 
285 
write(std::ostream & s) const286 inline void ParamResponsePair::write(std::ostream& s) const
287 {
288   s << "Parameters:\n" << prpVariables;
289   if (!(evalInterfaceIds.second.empty() || evalInterfaceIds.second == "NO_ID"))
290     s << "\nInterface identifier = " << evalInterfaceIds.second << '\n';
291   s << "\nActive response data:\n"<< prpResponse << std::endl;
292 }
293 
294 
295 /// std::istream extraction operator for ParamResponsePair
operator >>(std::istream & s,ParamResponsePair & pair)296 inline std::istream& operator>>(std::istream& s, ParamResponsePair& pair)
297 { pair.read(s); return s; }
298 
299 
300 /// std::ostream insertion operator for ParamResponsePair
operator <<(std::ostream & s,const ParamResponsePair & pair)301 inline std::ostream& operator<<(std::ostream& s, const ParamResponsePair& pair)
302 { pair.write(s); return s; }
303 
304 
305 /** interfaceId is omitted since master processor retains interface
306     ids and communicates asv and response data only with slaves. */
read(MPIUnpackBuffer & s)307 inline void ParamResponsePair::read(MPIUnpackBuffer& s)
308 { s >> prpVariables >> prpResponse >> evalInterfaceIds.first; }
309 
310 
311 /** interfaceId is omitted since master processor retains interface
312     ids and communicates asv and response data only with slaves. */
write(MPIPackBuffer & s) const313 inline void ParamResponsePair::write(MPIPackBuffer& s) const
314 { s << prpVariables << prpResponse << evalInterfaceIds.first; }
315 
316 
317 /// MPIUnpackBuffer extraction operator for ParamResponsePair
operator >>(MPIUnpackBuffer & s,ParamResponsePair & pair)318 inline MPIUnpackBuffer& operator>>(MPIUnpackBuffer& s, ParamResponsePair& pair)
319 { pair.read(s); return s; }
320 
321 
322 /// MPIPackBuffer insertion operator for ParamResponsePair
operator <<(MPIPackBuffer & s,const ParamResponsePair & pair)323 inline MPIPackBuffer& operator<<(MPIPackBuffer& s,const ParamResponsePair& pair)
324 { pair.write(s); return s; }
325 
326 
327 /// equality operator for ParamResponsePair
operator ==(const ParamResponsePair & pair1,const ParamResponsePair & pair2)328 inline bool operator==(const ParamResponsePair& pair1,
329 		       const ParamResponsePair& pair2)
330 {
331   // equality check includes interfaceId; evalId need not match
332   return (pair1.prpVariables            == pair2.prpVariables &&
333 	  pair1.evalInterfaceIds.second == pair2.evalInterfaceIds.second &&
334 	  pair1.prpResponse             == pair2.prpResponse);
335 }
336 
337 
338 /// inequality operator for ParamResponsePair
operator !=(const ParamResponsePair & pair1,const ParamResponsePair & pair2)339 inline bool operator!=(const ParamResponsePair& pair1,
340 		       const ParamResponsePair& pair2)
341 { return !(pair1 == pair2); }
342 
343 } // namespace Dakota
344 
345 
346 // Since we may serialize this class through a temporary, force
347 // serialization mode and no tracking
348 BOOST_CLASS_IMPLEMENTATION(Dakota::ParamResponsePair,
349 			   boost::serialization::object_serializable)
350 BOOST_CLASS_TRACKING(Dakota::ParamResponsePair,
351 		     boost::serialization::track_never)
352 
353 
354 #endif
355