Utopia  2
Framework for studying models of complex & adaptive systems.
utils.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_MODELS_SIMPLEFLOCKING_UTILS_HH
2 #define UTOPIA_MODELS_SIMPLEFLOCKING_UTILS_HH
3 
4 #include <cmath>
5 #include <random>
6 #include <numeric>
7 #include <vector>
8 #include <limits>
9 
10 #include <armadillo>
11 #include <spdlog/spdlog.h>
12 
13 #include <utopia/core/types.hh>
14 
15 
17 
18 constexpr double TAU = 2*M_PI;
19 constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
20 
21 
22 // -- Angle-related tools -----------------------------------------------------
23 
25 template<class RNG, class T=double>
26 T random_angle (const std::shared_ptr<RNG>& rng) {
27  return std::uniform_real_distribution<T>(-M_PI, +M_PI)(*rng);
28 }
29 
31 template<class T>
32 T constrain_angle (T angle) {
33  angle = std::fmod(angle + M_PI, TAU);
34  while (angle < 0.) {
35  angle += TAU;
36  }
37  return angle - M_PI;
38 }
39 
41 template<class Container>
42 void constrain_angles (Container& angles) {
44  angles.begin(), angles.end(), angles.begin(),
45  [](auto angle){ return constrain_angle(angle); }
46  );
47 }
48 
49 
50 // -- Geometry ----------------------------------------------------------------
51 
53 
57 template<class Container>
58 double absolute_group_velocity (const Container& velocities) {
59  if (velocities.empty()) {
60  return std::numeric_limits<double>::quiet_NaN();
61  }
62 
63  using Vec = typename Container::value_type;
64  Vec zero = velocities[0];
65  zero.fill(0.);
66 
67  const Vec group_velocity = std::accumulate(
68  velocities.begin(), velocities.end(), zero
69  );
70  return arma::norm(group_velocity, 2) / velocities.size();
71 }
72 
73 
74 // -- Circular Statistics -----------------------------------------------------
75 
77 template<class Container>
78 auto _circular_sin_cos_sum (const Container& angles) {
79  static_assert(
80  std::is_floating_point<typename Container::value_type>::value,
81  "need angles specified as floating-point types!"
82  );
83 
84  const auto sin_sum = std::accumulate(
85  angles.begin(), angles.end(), 0.,
86  [](auto a1, auto a2){ return a1 + std::sin(a2); }
87  );
88  const auto cos_sum = std::accumulate(
89  angles.begin(), angles.end(), 0.,
90  [](auto a1, auto a2){ return a1 + std::cos(a2); }
91  );
92 
93  return std::make_pair(sin_sum, cos_sum);
94 }
95 
96 
98 
107 template<class Container = std::vector<double>>
108 auto circular_mean (const Container& angles) {
109  if (angles.empty()) {
110  return std::numeric_limits<double>::quiet_NaN();
111  }
112 
113  const auto&& [sin_sum, cos_sum] = _circular_sin_cos_sum(angles);
114  return constrain_angle(std::atan2(sin_sum, cos_sum));
115 }
116 
117 
119 
128 template<class Container = std::vector<double>>
129 auto circular_mean_and_std (const Container& angles) {
130  if (angles.empty()) {
131  return std::make_pair(NaN, NaN);
132  }
133 
134  const auto&& [sin_sum, cos_sum] = _circular_sin_cos_sum(angles);
135  const auto mean = constrain_angle(std::atan2(sin_sum, cos_sum));
136 
137  const auto r = std::min(
138  1., std::sqrt(sin_sum*sin_sum + cos_sum*cos_sum) / angles.size()
139  );
140  const auto std = std::sqrt(-2. * std::log(r));
141 
142  return std::make_pair(mean, std);
143 }
144 
145 
146 } // namespace Utopia::Models::SimpleFlocking
147 
148 #endif // UTOPIA_MODELS_SIMPLEFLOCKING_UTILS_HH
OutputIt transform(const Utopia::ExecPolicy policy, InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op)
Apply a unary operator to a range and store the result in a new range.
Definition: parallel.hh:368
std::mt19937 rng
– Type definitions ----------------------------------------------------—
Definition: test_revision.cc:17
Definition: SimpleFlocking.hh:15
double absolute_group_velocity(const Container &velocities)
Computes the absolute group velocity from a container of velocity vectors.
Definition: utils.hh:58
T random_angle(const std::shared_ptr< RNG > &rng)
Returns a uniformly random angle value in [-π, +π)
Definition: utils.hh:26
void constrain_angles(Container &angles)
In-place constrains all angles in a container to interval [-π, +π)
Definition: utils.hh:42
auto _circular_sin_cos_sum(const Container &angles)
Compute sum of sine and cosine values from angles in a container.
Definition: utils.hh:78
T constrain_angle(T angle)
Constrains an angle value to interval [-π, +π)
Definition: utils.hh:32
auto circular_mean_and_std(const Container &angles)
Computes the circular mean and std from a sample of (constrained) angles.
Definition: utils.hh:129
constexpr double NaN
Definition: utils.hh:19
auto circular_mean(const Container &angles)
Computes the circular mean from a sample of (constrained) angles.
Definition: utils.hh:108
constexpr double TAU
Definition: utils.hh:18
Definition: parallel.hh:235