creativity  v1.3.0
Agent-based model of creativity and piracy
util.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <limits>
3 #include <string>
4 #include <sstream>
5 #include <vector>
6 #include <Eigen/Core>
7 
12 namespace creativity { namespace data {
13 
28 std::string double_str(double d, unsigned precision = std::numeric_limits<double>::max_digits10);
29 
43 template<typename RAIter, typename = typename std::enable_if<
44  std::is_same<
45  std::random_access_iterator_tag,
46  typename std::iterator_traits<RAIter>::iterator_category
47  >::value and
48  std::is_arithmetic<typename std::iterator_traits<RAIter>::value_type>::value
49 >::type>
50 double quantile(RAIter begin, RAIter end, double prob) {
51  if (prob < 0 or prob > 1) throw std::logic_error("Requested quantile probability is invalid");
52  if (begin == end) return std::numeric_limits<double>::quiet_NaN();
53  double index = prob * (std::distance(begin, end) - 1);
54  unsigned below = std::floor(index), above = std::ceil(index);
55  if (below == above) return begin[above];
56  return (above - index) * begin[below] + (index - below) * begin[above];
57 }
58 
60 double quantile(const std::vector<double> &vals, double prob);
61 
63 double quantile(const Eigen::Ref<const Eigen::VectorXd> &vals, double prob);
64 
69 double variance(const std::vector<double> &vals, double mean = std::numeric_limits<double>::quiet_NaN());
70 
72 enum class OverlapReducer {
73  None,
74  Prefix,
75  Suffix,
76  Equalize,
78 };
79 
107 template <typename InputIt>
108 typename std::enable_if<
109  // InputIt must be an input iterator:
110  std::is_base_of<std::input_iterator_tag, typename std::iterator_traits<InputIt>::iterator_category>::value
111  and
112  // The value_type of InputIt must itself be bidirectional-iterable
113  std::is_base_of<
114  std::bidirectional_iterator_tag,
115  typename std::iterator_traits<typename InputIt::value_type::iterator>::iterator_category
116  >::value,
117  std::pair<size_t, size_t>
118 >::type
119 common_ends(InputIt it, InputIt last,
120  bool prefix = true, bool suffix = true,
122  if (it == last) return {0,0};
123  const auto &ref_0 = *it;
124  std::pair<size_t, size_t> common(0, 0);
125  // Use the first element as our reference element, using its length as the initial
126  // prefix/suffix values.
127  auto shortest = std::distance(it->begin(), it->end());
128  if (prefix) common.first = shortest;
129  if (suffix) common.second = shortest;
130 
131  // Now, starting from the second element, check how much of the prefix/suffix matches
132  for (it++; it != last and (common.first > 0 or common.second > 0); it++) {
133  if (common.first > 0) {
134  // Iterate from the beginning, and keep iterating as long as each element is equal along
135  // the way
136  auto ref_it = ref_0.begin();
137  auto new_it = it->begin();
138  // NB: don't need to check ref_it != ref_0.end() here (because the i < common.first will
139  // ensure we can't go past the end).
140  for (size_t i = 0; i < common.first and new_it != it->end(); i++, ref_it++, new_it++) {
141  if (not (*new_it == *ref_it)) {
142  // We found two unequal elements at [i], so reduce the common prefix length to i
143  common.first = i;
144  break;
145  }
146  }
147  }
148  if (common.second > 0) {
149  // Iterate backwards from the end
150  auto ref_it = ref_0.rbegin();
151  auto new_it = it->rbegin();
152  for (size_t i = 0; i < common.second and new_it != it->rend(); i++, ref_it++, new_it++) {
153  // We found two unequal elements at i from the end, so reduce the common suffix
154  // length to i
155  if (not (*new_it == *ref_it)) {
156  common.second = i;
157  break;
158  }
159  }
160  }
161 
162  if (common.first > 0 and common.second > 0) {
163  shortest = std::min(shortest, std::distance(it->begin(), it->end()));
164  }
165  }
166 
167  if (common.first + common.second > (size_t) shortest) {
168  switch (reducer) {
170  break;
172  common.first = shortest - common.second;
173  break;
175  common.second = shortest - common.first;
176  break;
178  while (common.first + common.second > (size_t) shortest) {
179  if (common.second >= common.first) common.second--;
180  else common.first--;
181  }
182  break;
184  if (common.second <= common.first) common.second = shortest - common.first;
185  else common.first = shortest - common.second;
186  break;
187  }
188  }
189 
190  return common;
191 }
192 
193 }}
std::string double_str(double d, unsigned precision=std::numeric_limits< double >::max_digits10)
Converts a double value to a string, use as much precision is required (but no more).
double variance(const std::vector< double > &vals, double mean=std::numeric_limits< double >::quiet_NaN())
Calculates and returns the sample variance of the given vector of values.
Primary namespace for all Creativity library code.
Definition: config.hpp:4
Reduce the prefix by the minimum amount needed to eliminate the overlap.
Apply reductions to whichever of the prefix/suffix is smaller.
OverlapReducer
enum of the different strategies for dealing with prefix/suffix overlap in common_ends().
Definition: util.hpp:72
Don&#39;t reduce the prefix/suffix: the returned prefix and suffix may overlap.
std::enable_if< std::is_base_of< std::input_iterator_tag, typename std::iterator_traits< InputIt >::iterator_category >::value and std::is_base_of< std::bidirectional_iterator_tag, typename std::iterator_traits< typename InputIt::value_type::iterator >::iterator_category >::value, std::pair< size_t, size_t >>::type common_ends(InputIt it, InputIt last, bool prefix=true, bool suffix=true, OverlapReducer reducer=OverlapReducer::Disequalize)
Determines the number of equal (by ==) front and/or back elements in a range of random-access iterabl...
Definition: util.hpp:119
double quantile(RAIter begin, RAIter end, double prob)
Returns a sample quantile from a pair of random access iterators over the range of sorted values [beg...
Definition: util.hpp:50
Apply reductions to the prefix/suffix values that make the values closer to equal.
Reduce the suffix by the minimum amount needed to eliminate the overlap.