uncertain_value.h Source File

CPP API: uncertain_value.h Source File
uncertain_value.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Martin J. Kuehn, Martin Siggel, Daniel Abele
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef UNCERTAINVALUE_H
21 #define UNCERTAINVALUE_H
22 
23 #include "memilio/config.h"
24 #include "memilio/utils/memory.h"
27 #include <memory>
28 #include <ostream>
29 
30 namespace mio
31 {
32 
44 template <typename FP = ScalarType>
46 {
47 public:
48  using Type = FP;
49 
51  : m_value(v)
52  , m_dist(dist.clone())
53  {
54  }
55 
56  UncertainValue(FP v = static_cast<FP>(0.0))
57  : m_value(v)
58  {
59  }
60 
61  UncertainValue(UncertainValue&& other) = default;
62 
68  : m_value(other.m_value)
69  {
70  if (other.m_dist) {
71  m_dist.reset(other.m_dist->clone());
72  }
73  }
74 
80  {
81  UncertainValue tmp(other);
82  m_value = tmp.m_value;
83  std::swap(m_dist, tmp.m_dist);
84  return *this;
85  }
86 
94  template <typename T>
95  requires std::is_convertible_v<T, FP>
97  : m_value(static_cast<FP>(v))
98  {
99  }
100 
107  template <typename T>
108  requires std::is_convertible_v<T, FP>
110  {
111  m_value = static_cast<FP>(v);
112  return *this;
113  }
114 
118  FP value() const
119  {
120  return m_value;
121  }
122 
126  operator FP&()
127  {
128  return m_value;
129  }
130  operator const FP&() const
131  {
132  return m_value;
133  }
134 
139  {
140  m_value = v;
141  return *this;
142  }
143 
151  {
152  m_dist.reset(dist.clone());
153  }
154 
161  {
162  return m_dist.get();
163  }
164 
171  {
172  return m_dist.get();
173  }
174 
182  {
183  if (m_dist) {
184  m_value = m_dist->get_sample(mio::thread_local_rng());
185  }
186 
187  return m_value;
188  }
189 
194  template <class IOContext>
195  void serialize(IOContext& io) const
196  {
197  auto obj = io.create_object("UncertainValue");
198  if (!(io.flags() & IOF_OmitValues)) {
199  obj.add_element("Value", value());
200  }
201  if (!(io.flags() & IOF_OmitDistributions)) {
202  obj.add_optional("Distribution", get_distribution().get());
203  }
204  }
205 
210  template <class IOContext>
211  static IOResult<UncertainValue> deserialize(IOContext& io)
212  {
213  auto obj = io.expect_object("UncertainValue");
214  if (!(io.flags() & IOF_OmitValues) && !(io.flags() & IOF_OmitDistributions)) {
215  auto v = obj.expect_element("Value", Tag<FP>{});
216  auto d = obj.expect_optional("Distribution", Tag<std::shared_ptr<ParameterDistribution>>{});
217  return apply(
218  io,
219  [](auto&& v_, auto&& d_) {
220  auto uv = UncertainValue(v_);
221  if (d_) {
222  uv.set_distribution(**d_);
223  }
224  return uv;
225  },
226  v, d);
227  }
228  else if (!(io.flags() & IOF_OmitValues) && (io.flags() & IOF_OmitDistributions)) {
229  auto v = obj.expect_element("Value", Tag<FP>{});
230  return apply(
231  io,
232  [](auto&& v_) {
233  return UncertainValue(v_);
234  },
235  v);
236  }
237  else if ((io.flags() & IOF_OmitValues) && !(io.flags() & IOF_OmitDistributions)) {
238  auto d = obj.expect_optional("Distribution", Tag<std::shared_ptr<ParameterDistribution>>{});
239  return apply(
240  io,
241  [](auto&& d_) {
242  auto uv = UncertainValue();
243  if (d_) {
244  uv.set_distribution(**d_);
245  }
246  return uv;
247  },
248  d);
249  }
250  else {
252  "Incompatible Flags in IO Context: IOF_OmitValues & IOF_OmitDistributions.");
253  }
254  }
255 
256 private:
258  std::unique_ptr<ParameterDistribution> m_dist;
259 };
260 
264 template <class FP>
265 const FP& format_as(const UncertainValue<FP>& uv)
266 {
267  // uses UncertainValue<FP>::operator const FP&() const
268  return uv;
269 }
270 
271 // gtest printer
272 // TODO: should be extended when UncertainValue gets operator== that compares distributions as well
273 template <typename FP>
274 inline void PrintTo(const UncertainValue<FP>& uv, std::ostream* os)
275 {
276  (*os) << uv.value();
277 }
278 
300 template <typename FP, typename T>
301 inline bool operator>(const UncertainValue<FP>& lhs, const T& rhs)
302 {
303  return lhs.value() > rhs;
304 }
305 template <typename FP, typename T>
306 inline bool operator<(const UncertainValue<FP>& lhs, const T& rhs)
307 {
308  return lhs.value() < rhs;
309 }
310 template <typename FP, typename T>
311 inline bool operator>=(const UncertainValue<FP>& lhs, const T& rhs)
312 {
313  return lhs.value() >= rhs;
314 }
315 template <typename FP, typename T>
316 inline bool operator<=(const UncertainValue<FP>& lhs, const T& rhs)
317 {
318  return lhs.value() <= rhs;
319 }
320 template <typename FP, typename T>
321 inline bool operator==(const UncertainValue<FP>& lhs, const T& rhs)
322 {
323  return lhs.value() == rhs;
324 }
325 template <typename FP, typename T>
326 inline bool operator!=(const UncertainValue<FP>& lhs, const T& rhs)
327 {
328  return lhs.value() != rhs;
329 }
331 
334 template <typename FP, typename T>
335 inline bool operator>(const T& lhs, const UncertainValue<FP>& rhs)
336 {
337  return lhs > rhs.value();
338 }
339 template <typename FP, typename T>
340 inline bool operator<(const T& lhs, const UncertainValue<FP>& rhs)
341 {
342  return lhs < rhs.value();
343 }
344 template <typename FP, typename T>
345 inline bool operator>=(const T& lhs, const UncertainValue<FP>& rhs)
346 {
347  return lhs >= rhs.value();
348 }
349 template <typename FP, typename T>
350 inline bool operator<=(const T& lhs, const UncertainValue<FP>& rhs)
351 {
352  return lhs <= rhs.value();
353 }
354 template <typename FP, typename T>
355 inline bool operator==(const T& lhs, const UncertainValue<FP>& rhs)
356 {
357  return lhs == rhs.value();
358 }
359 template <typename FP, typename T>
360 inline bool operator!=(const T& lhs, const UncertainValue<FP>& rhs)
361 {
362  return lhs != rhs.value();
363 }
365 
368 template <typename FP>
369 inline bool operator>(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
370 {
371  return lhs.value() > rhs.value();
372 }
373 template <typename FP>
374 inline bool operator<(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
375 {
376  return lhs.value() < rhs.value();
377 }
378 template <typename FP>
379 inline bool operator>=(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
380 {
381  return lhs.value() >= rhs.value();
382 }
383 template <typename FP>
384 inline bool operator<=(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
385 {
386  return lhs.value() <= rhs.value();
387 }
388 template <typename FP>
389 inline bool operator==(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
390 {
391  return lhs.value() == rhs.value();
392 }
393 template <typename FP>
394 inline bool operator!=(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
395 {
396  return lhs.value() != rhs.value();
397 }
399 
402 template <typename FP>
403 inline FP operator*(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
404 {
405  return lhs.value() * rhs.value();
406 }
407 template <typename FP>
408 inline FP operator/(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
409 {
410  return lhs.value() / rhs.value();
411 }
412 template <typename FP>
413 inline FP operator+(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
414 {
415  return lhs.value() + rhs.value();
416 }
417 template <typename FP>
418 inline FP operator-(const UncertainValue<FP>& lhs, const UncertainValue<FP>& rhs)
419 {
420  return lhs.value() - rhs.value();
421 }
423 
426 template <typename FP, typename T>
427 inline FP operator*(const UncertainValue<FP>& lhs, const T& rhs)
428 {
429  return lhs.value() * rhs;
430 }
431 template <typename FP, typename T>
432 inline FP operator/(const UncertainValue<FP>& lhs, const T& rhs)
433 {
434  return lhs.value() / rhs;
435 }
436 template <typename FP, typename T>
437 inline FP operator+(const UncertainValue<FP>& lhs, const T& rhs)
438 {
439  return lhs.value() + rhs;
440 }
441 template <typename FP, typename T>
442 inline FP operator-(const UncertainValue<FP>& lhs, const T& rhs)
443 {
444  return lhs.value() - rhs;
445 }
447 
450 template <typename FP, typename T>
451 inline FP operator*(const T& lhs, const UncertainValue<FP>& rhs)
452 {
453  return lhs * rhs.value();
454 }
455 template <typename FP, typename T>
456 inline FP operator/(const T& lhs, const UncertainValue<FP>& rhs)
457 {
458  return lhs / rhs.value();
459 }
460 template <typename FP, typename T>
461 inline FP operator+(const T& lhs, const UncertainValue<FP>& rhs)
462 {
463  return lhs + rhs.value();
464 }
465 template <typename FP, typename T>
466 inline FP operator-(const T& lhs, const UncertainValue<FP>& rhs)
467 {
468  return lhs - rhs.value();
469 }
471 
474 template <typename FP>
475 FP& operator+=(FP& lhs, const UncertainValue<FP>& rhs)
476 {
477  lhs += rhs.value();
478  return lhs;
479 }
480 template <typename FP>
481 FP& operator-=(FP& lhs, const UncertainValue<FP>& rhs)
482 {
483  lhs -= rhs.value();
484  return lhs;
485 }
486 template <typename FP>
487 FP& operator*=(FP& lhs, const UncertainValue<FP>& rhs)
488 {
489  lhs *= rhs.value();
490  return lhs;
491 }
492 template <typename FP>
493 FP& operator/=(FP& lhs, const UncertainValue<FP>& rhs)
494 {
495  lhs /= rhs.value();
496  return lhs;
497 }
499 
503 template <typename FP>
504 inline std::ostream& operator<<(std::ostream& os, const UncertainValue<FP>& uv)
505 {
506  return os << uv.value();
507 }
508 
509 } // namespace mio
510 
511 #endif // UNCERTAINVALUE_H
Definition: parameter_distributions.h:75
virtual ParameterDistribution * clone() const =0
The UncertainValue class consists of a scalar value and a Distribution object.
Definition: uncertain_value.h:46
A non-owning pointer.
Definition: memory.h:37
FP & operator*=(FP &lhs, const UncertainValue< FP > &rhs)
Print statement for UncertainValue<FP> (required for AD types)
Definition: uncertain_value.h:487
std::unique_ptr< ParameterDistribution > m_dist
Definition: uncertain_value.h:258
FP operator*(const UncertainValue< FP > &lhs, const UncertainValue< FP > &rhs)
Definition: uncertain_value.h:403
requires std::is_convertible_v< T, FP > UncertainValue(T v)
Create an UncertainValue from a scalar of any type convertible to FP.
Definition: uncertain_value.h:96
UncertainValue & operator=(FP v)
Set an UncertainValue from a scalar, distribution remains unchanged.
Definition: uncertain_value.h:138
FP Type
Definition: uncertain_value.h:48
FP & operator+=(FP &lhs, const UncertainValue< FP > &rhs)
Print statement for UncertainValue<FP> (required for AD types)
Definition: uncertain_value.h:475
bool operator>=(const UncertainValue< FP > &lhs, const T &rhs)
Definition: uncertain_value.h:311
UncertainValue & operator=(const UncertainValue &other)
Set an UncertainValue from another UncertainValue containing a scalar and a distribution.
Definition: uncertain_value.h:79
UncertainValue(FP v, const ParameterDistribution &dist)
Definition: uncertain_value.h:50
FP operator/(const UncertainValue< FP > &lhs, const UncertainValue< FP > &rhs)
Definition: uncertain_value.h:408
void set_distribution(const ParameterDistribution &dist)
Sets the distribution of the value.
Definition: uncertain_value.h:150
static IOResult< UncertainValue > deserialize(IOContext &io)
deserialize an object of this class.
Definition: uncertain_value.h:211
FP value() const
Conversion to scalar by returning the scalar contained in UncertainValue.
Definition: uncertain_value.h:118
bool operator>(const UncertainValue< FP > &lhs, const T &rhs)
Definition: uncertain_value.h:301
FP operator+(const UncertainValue< FP > &lhs, const UncertainValue< FP > &rhs)
Definition: uncertain_value.h:413
FP draw_sample()
Sets the value by sampling from the distribution and returns the new value.
Definition: uncertain_value.h:181
FP & operator/=(FP &lhs, const UncertainValue< FP > &rhs)
Print statement for UncertainValue<FP> (required for AD types)
Definition: uncertain_value.h:493
FP & operator-=(FP &lhs, const UncertainValue< FP > &rhs)
Print statement for UncertainValue<FP> (required for AD types)
Definition: uncertain_value.h:481
FP operator-(const UncertainValue< FP > &lhs, const UncertainValue< FP > &rhs)
Definition: uncertain_value.h:418
FP m_value
Definition: uncertain_value.h:257
observer_ptr< const ParameterDistribution > get_distribution() const
Returns the parameter distribution.
Definition: uncertain_value.h:160
bool operator<=(const UncertainValue< FP > &lhs, const T &rhs)
Definition: uncertain_value.h:316
observer_ptr< ParameterDistribution > get_distribution()
Returns the parameter distribution.
Definition: uncertain_value.h:170
void serialize(IOContext &io) const
serialize this.
Definition: uncertain_value.h:195
UncertainValue(UncertainValue &&other)=default
UncertainValue(const UncertainValue &other)
Create an UncertainValue by cloning scalar value and distribution of another UncertainValue.
Definition: uncertain_value.h:67
bool operator<(const UncertainValue< FP > &lhs, const T &rhs)
Definition: uncertain_value.h:306
UncertainValue(FP v=static_cast< FP >(0.0))
Definition: uncertain_value.h:56
requires std::is_convertible_v< T, FP > UncertainValue< FP > & operator=(T v)
Assign a scalar of any type convertible to FP to this UncertainValue.
Definition: uncertain_value.h:109
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires HasOstreamOperator< T > std::ostream & operator<<(std::ostream &os, const Edge< T > &e)
out stream operator for edges if edge property type has stream operator defined
Definition: graph.h:129
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
bool operator==(const Node< T > &n1, const Node< T > &n2)
comparison operator if node property type is equality comparable
Definition: graph.h:100
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
details::ApplyResultT< F, T... > apply(IOContext &io, F f, const IOResult< T > &... rs)
Evaluate a function with zero or more unpacked IOResults as arguments.
Definition: io.h:481
requires(!std::is_trivial_v< T >) void BinarySerializerObject
Definition: binary_serializer.h:333
std::string format_as(const mio::Date &d)
Format date objects using the ISO notation for logging with spdlog.
Definition: date.h:180
bool operator!=(const Node< T > &n1, const Node< T > &n2)
Definition: graph.h:105
RandomNumberGenerator & thread_local_rng()
Definition: random_number_generator.cpp:25
@ IOF_OmitDistributions
Don't serialize distributions for types that contain both a specific value and a distribution from wh...
Definition: io.h:76
@ IOF_OmitValues
Don't serialize the current value for types that contain both a specific value and a distribution fro...
Definition: io.h:82
void PrintTo(const IOStatus &status, std::ostream *os)
gtest printer for IOStatus.
Definition: io.h:290
constexpr std::tuple_element< I, std::tuple< Index< CategoryTags >... > >::type & get(Index< CategoryTags... > &i) noexcept
Retrieves the Index (by reference) at the Ith position of a MultiIndex.
Definition: index.h:294
boost::outcome_v2::unchecked< T, IOStatus > IOResult
Value-or-error type for operations that return a value but can fail.
Definition: io.h:353