contact_matrix.h Source File

CPP API: contact_matrix.h Source File
contact_matrix.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Martin J. Kuehn, 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_CONTACT_MATRIX_H
21 #define MIO_EPI_CONTACT_MATRIX_H
22 
25 #include "memilio/utils/stl_util.h"
26 
27 #include <numeric>
28 #include <ostream>
29 #include <vector>
30 
31 namespace mio
32 {
33 
44 template <typename FP, class D>
46 {
47 public:
48  using DampingsType = D;
49  using Shape = typename DampingsType::Shape;
50  using Matrix = typename Shape::Matrix;
51 
58  template <class M, class K>
59  DampingMatrixExpression(const Eigen::MatrixBase<M>& baseline, const Eigen::MatrixBase<K>& minimum)
60  : m_baseline(baseline)
61  , m_minimum(minimum)
62  , m_dampings(Shape::get_shape_of(m_baseline))
63  {
64  assert(Shape::get_shape_of(m_minimum) == Shape::get_shape_of(m_baseline));
65  }
66 
72  template <class M>
73  explicit DampingMatrixExpression(const Eigen::MatrixBase<M>& baseline)
75  baseline, Matrix::Zero(Shape::get_shape_of(baseline).rows(), Shape::get_shape_of(baseline).cols()))
76  {
77  }
78 
85  template <class... T>
86  requires std::is_constructible_v<Shape, T...>
87  explicit DampingMatrixExpression(T... shape_args)
88  : DampingMatrixExpression(Matrix::Zero(Shape(shape_args...).rows(), Shape(shape_args...).cols()))
89  {
90  }
91 
96  template <class... T>
97  void add_damping(T&&... t)
98  {
99  m_dampings.add(std::forward<T>(t)...);
100  }
101 
106  void remove_damping(size_t i)
107  {
108  m_dampings.remove(i);
109  }
110 
115  {
116  m_dampings.clear();
117  }
118 
122  auto get_dampings() const
123  {
124  return Range(m_dampings.begin(), m_dampings.end());
125  }
127  {
128  return Range(m_dampings.begin(), m_dampings.end());
129  }
130 
134  const Matrix& get_baseline() const
135  {
136  return m_baseline;
137  }
139  {
140  return m_baseline;
141  }
142 
146  const Matrix& get_minimum() const
147  {
148  return m_minimum;
149  }
151  {
152  return m_minimum;
153  }
154 
158  Shape get_shape() const
159  {
160  return Shape::get_shape_of(m_baseline);
161  }
162 
166  bool operator==(const DampingMatrixExpression& other) const
167  {
168  return m_baseline == other.m_baseline && m_minimum == other.m_minimum && m_dampings == other.m_dampings;
169  }
170  bool operator!=(const DampingMatrixExpression& other) const
171  {
172  return !(*this == other);
173  }
174 
180  {
181  m_dampings.set_automatic_cache_update(b);
182  }
183 
191  {
192  assert(Shape::get_shape_of(m_dampings.get_matrix_at(t)) == Shape::get_shape_of(m_baseline));
193  return m_baseline - (m_dampings.get_matrix_at(t).array() * (m_baseline - m_minimum).array()).matrix();
194  }
195 
199  friend void PrintTo(const DampingMatrixExpression& self, std::ostream* os)
200  {
201  *os << '\n' << self.m_baseline;
202  *os << '\n' << self.m_minimum;
203  PrintTo(self.m_dampings, os);
204  }
205 
210  template <class IOContext>
211  void serialize(IOContext& io) const
212  {
213  auto obj = io.create_object("DampingMatrixExpression");
214  obj.add_element("Baseline", get_baseline());
215  obj.add_element("Minimum", get_minimum());
216  obj.add_list("Dampings", get_dampings().begin(), get_dampings().end());
217  }
218 
219 protected:
223  template <class IOContext, class Derived>
225  {
226  auto obj = io.expect_object("DampingMatrixExpression");
227  auto b = obj.expect_element("Baseline", Tag<Matrix>{});
228  auto m = obj.expect_element("Minimum", Tag<Matrix>{});
229  auto d = obj.expect_list("Dampings", Tag<typename DampingsType::value_type>{});
230  return apply(
231  io,
232  [](auto&& b_, auto&& m_, auto&& d_) -> IOResult<Derived> {
233  if (Shape::get_shape_of(b_) != Shape::get_shape_of(m_)) {
234  return failure(StatusCode::InvalidValue, "Baseline and Minimum must have the same shape.");
235  }
236  auto r = Derived(b_, m_);
237  for (auto&& e : d_) {
238  if (e.get_shape() != Shape::get_shape_of(b_)) {
239  return failure(StatusCode::InvalidValue, "Dampings must have the same shape as the Baseline.");
240  }
241  r.add_damping(e);
242  }
243  return success(r);
244  },
245  b, m, d);
246  }
247 
248 public:
253  template <class IOContext>
255  {
257  }
258 
259 private:
263 };
264 
270 template <typename FP, class E>
272 {
273 public:
274  using value_type = E;
276  using const_reference = const value_type&;
277  using iterator = typename std::vector<value_type>::iterator;
278  using const_iterator = typename std::vector<value_type>::const_iterator;
279 
280  using Shape = typename value_type::Shape;
281  using Matrix = typename value_type::Matrix;
282  using DampingsType = typename value_type::DampingsType;
283 
289  template <class... T>
290  requires(std::is_constructible_v<Shape, T...>)
291  explicit DampingMatrixExpressionGroup(size_t num_matrices, T... shape_args)
292  : m_matrices(num_matrices, value_type{shape_args...})
293  {
294  assert(num_matrices > 0);
295  }
296 
301  DampingMatrixExpressionGroup(std::initializer_list<value_type> il)
302  : m_matrices(il)
303  {
304  assert(il.size() > 0);
305  }
306 
307  DampingMatrixExpressionGroup(const std::vector<value_type>& v)
308  : m_matrices(v)
309  {
310  assert(v.size() > 0);
311  }
312 
316  reference operator[](size_t i)
317  {
318  return m_matrices[i];
319  }
320  const_reference operator[](size_t i) const
321  {
322  return m_matrices[i];
323  }
324 
328  size_t get_num_matrices() const
329  {
330  return m_matrices.size();
331  }
332 
336  Shape get_shape() const
337  {
338  return m_matrices[0].get_shape();
339  }
340 
344  bool operator==(const DampingMatrixExpressionGroup& other) const
345  {
346  return m_matrices == other.m_matrices;
347  }
348  bool operator!=(const DampingMatrixExpressionGroup& other) const
349  {
350  return !(*this == other);
351  }
352 
357  template <class... T>
358  void add_damping(T&&... t)
359  {
360  for (auto& m : *this) {
361  m.add_damping(std::forward<T>(t)...);
362  }
363  }
364 
368  void clear_dampings()
369  {
370  for (auto& m : *this) {
371  m.clear_dampings();
372  }
373  }
374 
379  void set_automatic_cache_update(bool b)
380  {
381  for (auto& m : *this) {
382  m.set_automatic_cache_update(b);
383  }
384  }
385 
392  auto get_matrix_at(SimulationTime<FP> t) const
393  {
394  return Eigen::Matrix<FP, Eigen::Dynamic, Eigen::Dynamic>::NullaryExpr(
395  get_shape().rows(), get_shape().cols(), [t, this](Eigen::Index i, Eigen::Index j) {
396  return std::accumulate(m_matrices.begin(), m_matrices.end(), FP(0.0), [t, i, j](FP s, auto& m) {
397  return evaluate_intermediate<FP>(s + m.get_matrix_at(t)(i, j));
398  });
399  });
400  }
401 
405  iterator begin()
406  {
407  return m_matrices.begin();
408  }
409  iterator end()
410  {
411  return m_matrices.end();
412  }
413  const_iterator begin() const
414  {
415  return m_matrices.begin();
416  }
417  const_iterator end() const
418  {
419  return m_matrices.end();
420  }
421 
425  friend void PrintTo(const DampingMatrixExpressionGroup& self, std::ostream* os)
426  {
427  for (auto& m : self.m_matrices) {
428  PrintTo(m, os);
429  *os << '\n';
430  }
431  }
432 
437  template <class IOContext>
438  void serialize(IOContext& io) const
439  {
440  auto obj = io.create_object("DampingMatrixExpressionGroup");
441  obj.add_list("Matrices", begin(), end());
442  }
443 
444 protected:
449  template <class IOContext, class Derived>
450  static IOResult<Derived> deserialize(IOContext& io, Tag<Derived>)
451  {
452  auto obj = io.expect_object("DampingMatrixExpressionGroup");
453  auto m = obj.expect_list("Matrices", Tag<value_type>{});
454  return apply(
455  io,
456  [](auto&& m_) -> IOResult<Derived> {
457  //validation
458  if (m_.empty()) {
459  return failure(StatusCode::InvalidValue,
460  "DampingMatrixExpressionGroup must have at least one matrix.");
461  }
462  auto shape = m_[0].get_shape();
463  for (size_t i = 1; i < m_.size(); ++i) {
464  if (m_[i].get_shape() != shape) {
466  "Elements of DampingMatrixExpressionGroup must all have the same shape.");
467  }
468  }
469 
470  return success(Derived(m_));
471  },
472  m);
473  }
474 
475 public:
480  template <class IOContext>
482  {
484  }
485 
486 private:
487  std::vector<value_type> m_matrices;
488 };
489 
503 template <typename FP>
504 class ContactMatrix : public DampingMatrixExpression<FP, SquareDampings<FP>>
505 {
506 public:
508  using Base::Base;
509 
513  Eigen::Index get_num_groups() const
514  {
515  return Base::get_shape().rows();
516  }
517 
522  template <class IOContext>
523  static IOResult<ContactMatrix> deserialize(IOContext& io)
524  {
526  }
527 };
528 
534 template <typename FP>
535 class ContactMatrixGroup : public DampingMatrixExpressionGroup<FP, ContactMatrix<FP>>
536 {
537 public:
539  using Base::Base;
540 
544  Eigen::Index get_num_groups() const
545  {
546  return (*this)[0].get_num_groups();
547  }
548 
553  template <class IOContext>
555  {
557  }
558 };
559 
560 } // namespace mio
561 
562 #endif // MIO_EPI_CONTACT_MATRIX_H
represents a collection of contact frequency matrices that whose sum is the total number of contacts.
Definition: contact_matrix.h:536
static IOResult< ContactMatrixGroup > deserialize(IOContext &io)
deserialize an object of this class.
Definition: contact_matrix.h:554
Eigen::Index get_num_groups() const
get the number of groups.
Definition: contact_matrix.h:544
represents time dependent contact frequencies between groups.
Definition: contact_matrix.h:505
Eigen::Index get_num_groups() const
get the number of groups.
Definition: contact_matrix.h:513
static IOResult< ContactMatrix > deserialize(IOContext &io)
deserialize an object of this class.
Definition: contact_matrix.h:523
represents a collection of DampingMatrixExpressions that are summed up.
Definition: contact_matrix.h:272
typename std::vector< value_type >::const_iterator const_iterator
Definition: contact_matrix.h:278
const value_type & const_reference
Definition: contact_matrix.h:276
static IOResult< DampingMatrixExpressionGroup > deserialize(IOContext &io)
deserialize an object of this class.
Definition: contact_matrix.h:481
std::vector< value_type > m_matrices
Definition: contact_matrix.h:487
T class Derived static IOResult< Derived > deserialize(IOContext &io, Tag< Derived >)
Definition: contact_matrix.h:450
T shape_args
Definition: contact_matrix.h:292
typename std::vector< value_type >::iterator iterator
Definition: contact_matrix.h:277
requires(std::is_constructible_v< Shape, T... >) explicit DampingMatrixExpressionGroup(size_t num_matrices
create a collection.
typename value_type::Shape Shape
Definition: contact_matrix.h:280
typename value_type::DampingsType DampingsType
Definition: contact_matrix.h:282
typename value_type::Matrix Matrix
Definition: contact_matrix.h:281
E value_type
Definition: contact_matrix.h:274
value_type & reference
Definition: contact_matrix.h:275
represents the coefficient wise matrix (or vector) expression B - D * M where B is a baseline,...
Definition: contact_matrix.h:46
friend void PrintTo(const DampingMatrixExpression &self, std::ostream *os)
gtest printer.
Definition: contact_matrix.h:199
auto get_dampings()
Definition: contact_matrix.h:126
requires std::is_constructible_v< Shape, T... > DampingMatrixExpression(T... shape_args)
construct with shape.
Definition: contact_matrix.h:87
bool operator!=(const DampingMatrixExpression &other) const
Definition: contact_matrix.h:170
DampingMatrixExpression(const Eigen::MatrixBase< M > &baseline)
construct with only baseline, minimum and dampings is zero.
Definition: contact_matrix.h:73
Matrix & get_minimum()
Definition: contact_matrix.h:150
void clear_dampings()
remove all dampings.
Definition: contact_matrix.h:114
typename Shape::Matrix Matrix
Definition: contact_matrix.h:50
auto get_matrix_at(SimulationTime< FP > t) const
Applies dampings to compute the real contact frequency at a point in time.
Definition: contact_matrix.h:190
void add_damping(T &&... t)
adds a damping.
Definition: contact_matrix.h:97
const Matrix & get_minimum() const
get the minimum matrix.
Definition: contact_matrix.h:146
auto get_dampings() const
list of dampings.
Definition: contact_matrix.h:122
void remove_damping(size_t i)
remove a damping.
Definition: contact_matrix.h:106
const Matrix & get_baseline() const
get the baseline matrix.
Definition: contact_matrix.h:134
DampingsType m_dampings
Definition: contact_matrix.h:262
void serialize(IOContext &io) const
serialize this.
Definition: contact_matrix.h:211
static IOResult< DampingMatrixExpression > deserialize(IOContext &io)
deserialize an object of this class.
Definition: contact_matrix.h:254
DampingMatrixExpression(const Eigen::MatrixBase< M > &baseline, const Eigen::MatrixBase< K > &minimum)
construct with baseline and minimum contacts and zero dampings.
Definition: contact_matrix.h:59
Matrix m_minimum
Definition: contact_matrix.h:261
static IOResult< Derived > deserialize(IOContext &io, Tag< Derived >)
deserialize an object of a class derived from this.
Definition: contact_matrix.h:224
bool operator==(const DampingMatrixExpression &other) const
equality operators.
Definition: contact_matrix.h:166
typename DampingsType::Shape Shape
Definition: contact_matrix.h:49
Shape get_shape() const
dimensions of the matrix.
Definition: contact_matrix.h:158
Matrix m_baseline
Definition: contact_matrix.h:260
void set_automatic_cache_update(bool b)
Enable/disable automatic cache update of the dampings.
Definition: contact_matrix.h:179
Matrix & get_baseline()
Definition: contact_matrix.h:138
D DampingsType
Definition: contact_matrix.h:48
double simulation time.
Definition: damping.h:58
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires details::IsElementReference< M > RowMajorIterator< M, false > end(M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:449
Range(std::pair< I, S > iterator_pair) -> Range< I, S >
Deduction guide to correctly deduce range type when constructed from a pair.
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
void serialize(IOContext &io, const T &t)
Save data that describes an object in a format determined by the given context.
Definition: io.h:836
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
auto i
Definition: io.h:809
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
auto success()
Create an object that is implicitly convertible to a succesful IOResult<void>.
Definition: io.h:359
requires details::IsElementReference< M > RowMajorIterator< M, false > begin(M &m)
create a non-const iterator to first element of the matrix m.
Definition: eigen_util.h:421
bool operator!=(const Node< T > &n1, const Node< T > &n2)
Definition: graph.h:105
void PrintTo(const IOStatus &status, std::ostream *os)
gtest printer for IOStatus.
Definition: io.h:290
boost::outcome_v2::unchecked< T, IOStatus > IOResult
Value-or-error type for operations that return a value but can fail.
Definition: io.h:353