populations.h Source File

CPP API: populations.h Source File
populations.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Jan Kleinert, 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 MIO_EPI_POPULATIONS_H
21 #define MIO_EPI_POPULATIONS_H
22 
23 #include "memilio/config.h" // IWYU pragma: keep
24 #include "memilio/math/eigen.h" // IWYU pragma: keep
28 
29 #include <concepts>
30 #include <numeric>
31 
32 namespace mio
33 {
34 
53 template <typename FP, class... Categories>
54 class Populations : public CustomIndexArray<UncertainValue<FP>, Categories...>
55 {
56 public:
57  using Base = CustomIndexArray<UncertainValue<FP>, Categories...>;
58  using Index = typename Base::Index;
59 
60  template <class... Ts>
61  requires std::is_constructible_v<UncertainValue<FP>, Ts...>
62  explicit Populations(Index const& sizes, Ts... args)
63  : Base(sizes, args...)
64  {
65  }
66 
68  explicit Populations(Base&& array)
69  : Base(std::move(array))
70  {
71  }
72 
78  template <class OtherType>
79  requires std::convertible_to<typename Base::Type::Type, OtherType>
80  Populations<OtherType, Categories...> convert() const
81  {
82  return Populations<OtherType, Categories...>(
83  Base::template convert<typename Base::Type::Type>().template convert<UncertainValue<OtherType>>());
84  }
85 
93  size_t get_num_compartments() const
94  {
95  return this->numel();
96  }
97 
103  inline Eigen::VectorX<FP> get_compartments() const
104  {
105  return this->array().template cast<FP>();
106  }
107 
122  template <class Arr>
123  decltype(auto) get_from(Arr&& y, Index const& cats) const
124  {
125  static_assert(std::is_lvalue_reference_v<Arr>, "get_from is disabled for temporary arrays.");
126  return y[this->get_flat_index(cats)];
127  }
128 
135  template <class T>
136  FP get_group_total(mio::Index<T> group_idx) const
137  {
138  auto const s = this->template slice<T>({(size_t)group_idx, 1});
139  return std::accumulate(s.begin(), s.end(), FP(0.0), [](const FP& a, const UncertainValue<FP>& b) {
140  return evaluate_intermediate<FP>(a + b);
141  });
142  }
143 
155  template <class T>
156  void set_group_total(mio::Index<T> group_idx, FP value)
157  {
158  using std::fabs;
159  FP current_population = get_group_total(group_idx);
160  auto s = this->template slice<T>({(size_t)group_idx, 1});
161 
162  if (fabs(current_population) < 1e-12) {
163  for (auto& v : s) {
164  v = value / s.numel();
165  }
166  }
167  else {
168  for (auto& v : s) {
169  v *= value / current_population;
170  }
171  }
172  }
173 
178  FP get_total() const
179  {
180  return this->array().template cast<FP>().sum();
181  }
182 
193  template <class T>
194  void set_difference_from_group_total(Index const& midx, FP total_group_population)
195 
196  {
197  auto group_idx = mio::get<T>(midx);
198  FP current_population = get_group_total(group_idx);
199  size_t idx = this->get_flat_index(midx);
200  current_population -= this->array()[idx];
201 
202  assert(current_population <= total_group_population + 1e-10);
203 
204  this->array()[idx] = total_group_population - current_population;
205  }
206 
216  void set_total(FP value)
217  {
218  using std::fabs;
219  FP current_population = get_total();
220  if (fabs(current_population) < 1e-12) {
221  FP ysize = static_cast<FP>(this->array().size());
222  for (size_t i = 0; i < this->get_num_compartments(); i++) {
223  this->array()[(Eigen::Index)i] = value / ysize;
224  }
225  }
226  else {
227  for (size_t i = 0; i < this->get_num_compartments(); i++) {
228  this->array()[(Eigen::Index)i] *= value / current_population;
229  }
230  }
231  }
232 
240  void set_difference_from_total(Index midx, FP total_population)
241  {
242  FP current_population = get_total();
243  size_t idx = this->get_flat_index(midx);
244  current_population -= this->array()[idx];
245 
246  assert(current_population <= total_population);
247 
248  this->array()[idx] = total_population - current_population;
249  }
250 
265  {
266  bool corrected = false;
267  for (int i = 0; i < this->array().size(); i++) {
268  if (this->array()[i] < 0.0) {
269  if (this->array()[i] > -1e-10) {
270  log_warning("Constraint check: Compartment number {} changed from {} to {}", i, this->array()[i],
271  0);
272  }
273  else {
274  log_error("Constraint check: Compartment number {} changed from {} to {}", i, this->array()[i], 0);
275  }
276  this->array()[i] = 0.0;
277  corrected = true;
278  }
279  }
280  return corrected;
281  }
282 
287  bool check_constraints() const
288  {
289  for (int i = 0; i < this->array().size(); i++) {
290  FP value = this->array()[i];
291  if (value < 0.0) {
292  log_error("Constraint check: Compartment number {} is {} and smaller {}", i, value, 0);
293  return true;
294  }
295  }
296  return false;
297  }
298 
303  template <class IOContext>
304  static IOResult<Populations> deserialize(IOContext& io)
305  {
306  return Base::deserialize(io, Tag<Populations>{});
307  }
308 };
309 
316 template <typename FP, class... Categories>
317 class Populations<FP, Index<Categories...>> : public Populations<FP, Categories...>
318 {
319  using Populations<FP, Categories...>::Populations;
320 };
321 
322 } // namespace mio
323 
324 #endif // MIO_EPI_POPULATIONS_H
A class template for an array with custom indices.
Definition: custom_index_array.h:136
requires(std::is_constructible_v< Type, Ts... >) CustomIndexArray(Index const &dims
CustomIndexArray constructor, that initializes the array to constant instances of CustsomIndexArray::...
size_t get_flat_index(Index const &index) const
get_flat_index returns the flat index into the stored array, given the indices of each category
Definition: custom_index_array.h:309
constexpr size_t numel() const
numel returns the number of elements
Definition: custom_index_array.h:193
static IOResult< Derived > deserialize(IOContext &io, Tag< Derived >)
deserialize an object of a class derived from this class.
Definition: custom_index_array.h:758
::mio::Index< Tags... > Index
Definition: custom_index_array.h:139
Ts && args
Definition: custom_index_array.h:164
auto const & array() const
array returns a reference to the internally stored flat array.
Definition: custom_index_array.h:250
An Index with more than one template parameter combines several Index objects.
Definition: index.h:181
A class template for compartment populations.
Definition: populations.h:55
void set_total(FP value)
set_total sets the total population
Definition: populations.h:216
FP get_total() const
get_total returns the total population of all compartments
Definition: populations.h:178
decltype(auto) get_from(Arr &&y, Index const &cats) const
get_from returns the value of a flat container at the flat index corresponding to set of enum values.
Definition: populations.h:123
bool apply_constraints()
Checks whether all compartments have non-negative values.
Definition: populations.h:264
FP get_group_total(mio::Index< T > group_idx) const
get_group_total returns the total population of a group in one category
Definition: populations.h:136
bool check_constraints() const
Checks whether all compartments have non-negative values and logs an error if constraint is not satis...
Definition: populations.h:287
size_t get_num_compartments() const
get_num_compartments returns the number of compartments
Definition: populations.h:93
void set_difference_from_group_total(Index const &midx, FP total_group_population)
set_difference_from_group_total sets the total population for a given group from a difference
Definition: populations.h:194
void set_difference_from_total(Index midx, FP total_population)
set_difference_from_total takes a total population as input and sets the compartment of a given index...
Definition: populations.h:240
typename Base::Index Index
Definition: populations.h:58
Eigen::VectorX< FP > get_compartments() const
get_compartments returns an Eigen copy of the vector of populations.
Definition: populations.h:103
requires std::is_constructible_v< UncertainValue< FP >, Ts... > Populations(Index const &sizes, Ts... args)
Definition: populations.h:62
void set_group_total(mio::Index< T > group_idx, FP value)
set_group_total sets the total population for a given group
Definition: populations.h:156
requires std::convertible_to< typename Base::Type::Type, OtherType > Populations< OtherType, Categories... > convert() const
Convert internally stored data to OtherType and save into new Populations.
Definition: populations.h:80
Populations(Base &&array)
Create populations by taking ownership of a CustomIndexArray.
Definition: populations.h:68
static IOResult< Populations > deserialize(IOContext &io)
deserialize an object of this class.
Definition: populations.h:304
ad::internal::unary_intermediate< AD_TAPE_REAL, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::operations::ad_fabs< AD_TAPE_REAL > > fabs(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x1)
Definition: ad.hpp:1133
trait_value< T >::RETURN_TYPE & value(T &x)
Definition: ad.hpp:3308
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
auto i
Definition: io.h:809
void log_warning(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:112
void log_error(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:100
boost::outcome_v2::unchecked< T, IOStatus > IOResult
Value-or-error type for operations that return a value but can fail.
Definition: io.h:353
Definition: io.h:94