github.com/RhysU/ar
Autoregressive process modeling tools in header-only C++
ar.hpp
Go to the documentation of this file.
1 // Copyright (C) 2012, 2013, 2026 Rhys Ulerich
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef AR_HPP
8 #define AR_HPP
9 
10 #ifndef AR_SUPPRESS_DOXYGEN_MAINPAGE
11 
29 #endif /* AR_SUPPRESS_DOXYGEN_MAINPAGE */
30 
35 #include <algorithm>
36 #include <cassert>
37 #include <cmath>
38 #include <functional>
39 #include <iterator>
40 #include <limits>
41 #include <numeric>
42 #include <stdexcept>
43 #include <string>
44 #include <vector>
45 
71 namespace ar
72 {
73 
77 
85 #define AR_GCC_VERSION \
86  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
87 
89 #define AR_STRINGIFY_HELPER(x) #x
90 
92 #define AR_STRINGIFY(x) AR_STRINGIFY_HELPER(x)
93 
102 #define AR_ENSURE_MSGEXCEPT(expr, msg, except) \
103  if (!(expr)) throw except(msg)
104 
113 #define AR_ENSURE_MSG(expr, msg) \
114  AR_ENSURE_MSGEXCEPT(expr, msg, std::logic_error)
115 
123 #define AR_ENSURE(expr) \
124  AR_ENSURE_MSG(expr, AR_STRINGIFY(expr)" false")
125 
134 #define AR_ENSURE_ARG(expr) \
135  AR_ENSURE_MSGEXCEPT(expr, AR_STRINGIFY(expr)" false", std::invalid_argument)
136 
144 #define AR_ENSURE_EXCEPT(expr, except) \
145  AR_ENSURE_MSGEXCEPT(expr, AR_STRINGIFY(expr)" false", except)
146 
151 
175 template <typename InputIterator,
176  typename OutputType1,
177  typename OutputType2>
178 std::size_t welford_nvariance(InputIterator first,
179  InputIterator last,
180  OutputType1& mean,
181  OutputType2& nvar)
182 {
183  using std::iterator_traits;
184  using std::size_t;
185  typedef typename iterator_traits<InputIterator>::value_type value;
186 
187  size_t N = 1; // Running next sample number
188  value m = 0; // Running mean of data thus far
189  value nv = 0; // Running variance times the number of samples
190 
191  while (first != last)
192  {
193  value x = *first++;
194  value d = x - m;
195  m += d / N++;
196  nv += d*(x - m);
197  }
198 
199  mean = m;
200  nvar = nv;
201  return N-1;
202 }
203 
214 template <typename InputIterator,
215  typename OutputType1,
216  typename OutputType2>
217 std::size_t welford_variance_population(InputIterator first,
218  InputIterator last,
219  OutputType1& mean,
220  OutputType2& var)
221 {
222  using std::size_t;
223  size_t N = welford_nvariance(first, last, mean, var);
224  var /= N;
225  return N;
226 }
227 
238 template <typename InputIterator,
239  typename OutputType1,
240  typename OutputType2>
241 std::size_t welford_variance_sample(InputIterator first,
242  InputIterator last,
243  OutputType1& mean,
244  OutputType2& var)
245 {
246  using std::size_t;
247  size_t N = welford_nvariance(first, last, mean, var);
248  var /= (N - 1);
249  return N;
250 }
251 
266 template <typename InputIterator1,
267  typename InputIterator2,
268  typename OutputType1,
269  typename OutputType2,
270  typename OutputType3>
271 std::size_t welford_ncovariance(InputIterator1 first1,
272  InputIterator1 last1,
273  InputIterator2 first2,
274  OutputType1& mean1,
275  OutputType2& mean2,
276  OutputType3& ncovar)
277 {
278  using std::iterator_traits;
279  using std::size_t;
280  typedef typename iterator_traits<InputIterator1>::value_type value1;
281  typedef typename iterator_traits<InputIterator2>::value_type value2;
282 
283  size_t N = 1; // Running next sample number
284  value1 m1 = 0; // Running mean of first data set thus far
285  value2 m2 = 0; // Running mean of second data set thus far
286  OutputType3 nc = 0; // Running covariance times the number of samples
287 
288  while (first1 != last1)
289  {
290  value1 x1 = *first1++;
291  value1 d1 = x1 - m1;
292  m1 += d1 / N;
293 
294  value2 x2 = *first2++;
295  value2 d2 = x2 - m2;
296  m2 += d2 / N;
297 
298  nc += d1*(x2 - m2);
299 
300  ++N;
301  }
302 
303  mean1 = m1;
304  mean2 = m2;
305  ncovar = nc;
306  return N-1;
307 }
308 
321 template <typename InputIterator1,
322  typename InputIterator2,
323  typename OutputType1,
324  typename OutputType2,
325  typename OutputType3>
326 std::size_t welford_covariance_population(InputIterator1 first1,
327  InputIterator1 last1,
328  InputIterator2 first2,
329  OutputType1& mean1,
330  OutputType2& mean2,
331  OutputType3& covar)
332 {
333  using std::size_t;
334  size_t N = welford_ncovariance(first1, last1, first2, mean1, mean2, covar);
335  covar /= N;
336  return N;
337 }
338 
351 template <typename InputIterator1,
352  typename InputIterator2,
353  typename OutputType1,
354  typename OutputType2,
355  typename OutputType3>
356 std::size_t welford_covariance_sample(InputIterator1 first1,
357  InputIterator1 last1,
358  InputIterator2 first2,
359  OutputType1& mean1,
360  OutputType2& mean2,
361  OutputType3& covar)
362 {
363  using std::size_t;
364  size_t N = welford_ncovariance(first1, last1, first2, mean1, mean2, covar);
365  covar /= (N - 1);
366  return N;
367 }
368 
381 template <typename InputIterator,
382  typename ValueType>
383 ValueType welford_inner_product(InputIterator first,
384  InputIterator last,
385  ValueType init)
386 {
387  typename std::iterator_traits<InputIterator>::value_type mean;
388  ValueType nvar;
389  const std::size_t N = welford_nvariance(first, last, mean, nvar);
390  return init + (nvar + N*(mean*mean));
391 }
392 
408 template <typename InputIterator1,
409  typename InputIterator2,
410  typename ValueType>
411 ValueType welford_inner_product(InputIterator1 first1,
412  InputIterator1 last1,
413  InputIterator2 first2,
414  ValueType init)
415 {
416  typename std::iterator_traits<InputIterator1>::value_type mean1;
417  typename std::iterator_traits<InputIterator2>::value_type mean2;
418  ValueType ncovar;
419  const std::size_t N = welford_ncovariance(
420  first1, last1, first2, mean1, mean2, ncovar);
421  return init + (ncovar + N*(mean1*mean2));
422 }
423 
428 
438 #if _MSC_VER > 1400
439 # pragma float_control(push)
440 # pragma float_control(precise, on)
441 #endif
442 
463 template <typename ValueType,
464  typename InputIterator1,
465  typename InputIterator2>
466 ValueType
467 #if (AR_GCC_VERSION > 40305)
468  __attribute__((__optimize__("no-associative-math")))
469 #endif
471  InputIterator1 a_last,
472  InputIterator2 b_first)
473 #if (AR_GCC_VERSION > 40305) || (_MSC_VER > 1400)
474 {
475  ValueType ns = 0, nt, nc = 0, ny; // Kahan numerator accumulation
476  ValueType ds = 0, dt, dc = 0, dy; // Kahan denominator accumulation
477 
478  while (a_first != a_last)
479  {
480  ValueType xa = *a_first++; // Denominator: \vec{a}\cdot\vec{a}
481  dy = (xa * xa) - dc;
482  dt = ds + dy;
483  dc = (dt - ds) - dy;
484  ds = dt;
485 
486  ValueType xb = *b_first++; // Denominator: \vec{b}\cdot\vec{b}
487  dy = (xb * xb) - dc;
488  dt = ds + dy;
489  dc = (dt - ds) - dy;
490  ds = dt;
491 
492  ny = (xa * xb) - nc; // Numerator: \vec{a}\cdot\vec{b}
493  nt = ns + ny;
494  nc = (nt - ns) - ny;
495  ns = nt;
496  }
497 
498  return ns + nc == 0 // Does special zero case apply?
499  ? 0 // Yes, to avoid NaN from 0 / 0
500  : (ns + nc) / (ds + dc); // No, correct final sums and form ratio
501 }
502 #else
503 #warning Using Non-Kahan version of ar::negative_half_reflection_coefficient.
504 {
505  ValueType ns = 0;
506  ValueType ds = 0;
507 
508  while (a_first != a_last)
509  {
510  ValueType xa = *a_first++;
511  ValueType xb = *b_first++;
512  ns += xa * xb; // Numerator
513  ds += xa * xa + xb * xb; // Denominator
514  }
515 
516  return ns == 0 // Does special zero case apply?
517  ? 0 // Yes, to avoid NaN from 0 / 0
518  : ns / ds; // No, form ratio
519 }
520 #endif
521 
522 #if _MSC_VER > 1400
523 # pragma float_control(pop)
524 #endif
525 
535 template <class InputIterator,
536  class Value,
537  class OutputIterator1,
538  class OutputIterator2,
539  class OutputIterator3,
540  class OutputIterator4,
541  class Vector>
542 std::size_t burg_method(InputIterator data_first,
543  InputIterator data_last,
544  Value& mean,
545  std::size_t& maxorder,
546  OutputIterator1 params_first,
547  OutputIterator2 sigma2e_first,
548  OutputIterator3 gain_first,
549  OutputIterator4 autocor_first,
550  const bool subtract_mean,
551  const bool hierarchy,
552  Vector& f,
553  Vector& b,
554  Vector& Ak,
555  Vector& ac)
556 {
557  using std::bind2nd;
558  using std::copy;
559  using std::distance;
560  using std::fill;
561  using std::inner_product;
562  using std::min;
563  using std::minus;
564  using std::size_t;
565 
566  // Initialize f from [data_first, data_last) and fix number of samples
567  f.assign(data_first, data_last);
568  const size_t N = f.size();
569 
570  // Stably compute the incoming data's mean and population variance
571  mean = 0;
572  Value sigma2e = 0;
573  welford_variance_population(f.begin(), f.end(), mean, sigma2e);
574 
575  // When requested, subtract the just-computed mean from the data.
576  // Adjust, if necessary, to make sigma2e the second moment.
577  if (subtract_mean)
578  {
579  for (typename Vector::iterator it = f.begin(); it != f.end(); ++it) {
580  *it -= mean;
581  }
582  }
583  else
584  {
585  sigma2e += mean*mean;
586  }
587 
588  // At most maxorder N-1 can be fit from N samples. Beware N is unsigned.
589  maxorder = (N == 0) ? 0 : min(static_cast<size_t>(maxorder), N-1);
590 
591  // Output sigma2e and gain for a zeroth order model, if requested.
592  Value gain = 1;
593  if (hierarchy || maxorder == 0)
594  {
595  *sigma2e_first++ = sigma2e;
596  *gain_first++ = gain;
597  }
598 
599  // Initialize and perform Burg recursion
600  if (maxorder) b = f; // Copy iff non-trivial work required
601  Ak.assign(maxorder + 1, Value(0));
602  Ak[0] = 1;
603  ac.clear();
604  ac.reserve(maxorder);
605  for (size_t kp1 = 1; kp1 <= maxorder; ++kp1)
606  {
607  // Compute mu from f, b, and Dk and then update sigma2e and Ak using mu
608  // Afterwards, Ak[1:kp1] contains AR(k) coefficients by the recurrence
609  // Must treat mu result of 0 / 0 as 0 to avoid NaNs on constant signals
610  // By the recurrence, Ak[kp1] will also be the reflection coefficient
611  Value mu = -2 * negative_half_reflection_coefficient<Value>(
612  f.begin() + kp1, f.end(), b.begin());
613 
614  sigma2e *= (1 - mu*mu);
615  for (size_t n = 0; n <= kp1/2; ++n)
616  {
617  Value t1 = Ak[n] + mu*Ak[kp1 - n];
618  Value t2 = Ak[kp1 - n] + mu*Ak[n];
619  Ak[n] = t1;
620  Ak[kp1 - n] = t2;
621  }
622 
623  // Update the gain per Broersen 2006 equation (5.25)
624  gain *= 1 / (1 - Ak[kp1]*Ak[kp1]);
625 
626  // Compute and output the next autocorrelation coefficient
627  // See Broersen 2006 equations (5.28) and (5.31) for details
628  ac.push_back(-inner_product(ac.rbegin(), ac.rend(),
629  Ak.begin() + 1, Ak[kp1]));
630 
631  // Output parameters and the input and output variances when requested
632  if (hierarchy || kp1 == maxorder)
633  {
634  params_first = copy(Ak.begin() + 1, Ak.begin() + kp1 + 1,
635  params_first);
636  *sigma2e_first++ = sigma2e;
637  *gain_first++ = gain;
638  }
639 
640  // Update f and b for the next iteration if another remains
641  if (kp1 < maxorder)
642  {
643  for (size_t n = 0; n < N - kp1; ++n)
644  {
645  Value t1 = f[n + kp1] + mu*b[n];
646  Value t2 = b[n] + mu*f[n + kp1];
647  f[n + kp1] = t1;
648  b[n] = t2;
649  }
650  }
651  }
652 
653  // Output the lag [0,maxorder] autocorrelation coefficients in single pass
654  *autocor_first++ = 1;
655  copy(ac.begin(), ac.end(), autocor_first);
656 
657  // Return the number of values processed in [data_first, data_last)
658  return N;
659 }
660 
746 template <class InputIterator,
747  class Value,
748  class OutputIterator1,
749  class OutputIterator2,
750  class OutputIterator3,
751  class OutputIterator4>
752 std::size_t burg_method(InputIterator data_first,
753  InputIterator data_last,
754  Value& mean,
755  std::size_t& maxorder,
756  OutputIterator1 params_first,
757  OutputIterator2 sigma2e_first,
758  OutputIterator3 gain_first,
759  OutputIterator4 autocor_first,
760  const bool subtract_mean = false,
761  const bool hierarchy = false)
762 {
763  using std::vector;
764  vector<Value> f, b, Ak, ac; // Working storage
765 
766  return burg_method(data_first, data_last, mean, maxorder,
767  params_first, sigma2e_first, gain_first,
768  autocor_first, subtract_mean, hierarchy,
769  f, b, Ak, ac);
770 }
771 
772 // Type erasure for NoiseGenerator parameters within predictor.
773 // Either std::tr1::function or boost::function would better provide the
774 // desired capability but both add additional, undesired dependencies.
775 namespace
776 {
777 
779 template <typename Value>
780 struct nullary
781 {
782  virtual ~nullary() {}
783  virtual Value operator()() = 0;
784  virtual nullary* clone() = 0;
785 };
786 
788 template<typename Value>
789 struct nullary_impl0 : public nullary<Value>
790 {
791  Value operator()()
792  {
793  return 0;
794  }
795  nullary_impl0* clone()
796  {
797  return new nullary_impl0();
798  }
799 };
800 
802 template<typename Value, class T>
803 struct nullary_impl1 : public nullary<Value>
804 {
805  nullary_impl1(T t) : t(t) {}
806  Value operator()()
807  {
808  return t();
809  }
810  nullary_impl1* clone()
811  {
812  return new nullary_impl1(t);
813  }
814  T t;
815 };
816 
817 }
818 
822 template <typename Value, typename Index = std::size_t>
824 {
825 public:
826  typedef std::input_iterator_tag iterator_category;
827  typedef Value value_type;
828  typedef std::ptrdiff_t difference_type;
829  typedef const Value* pointer;
830  typedef const Value& reference;
831 
833  explicit predictor(Index n = 0) : n(n), d(), g(0), xn()
834  {
835 #ifndef NDEBUG
836  using std::numeric_limits;
837  if (numeric_limits<Value>::has_quiet_NaN)
838  xn = numeric_limits<Value>::quiet_NaN();
839 #endif
840  }
841 
853  template <class RandomAccessIterator>
854  predictor(RandomAccessIterator params_first,
855  RandomAccessIterator params_last)
856  : n(0),
857  d(2*std::distance(params_first, params_last), 0),
858  g(new nullary_impl0<Value>()),
859  xn((*g)())
860  {
861  // Finish preparing d = [ a_p, ..., a_1, 0, ..., 0 ]
862  using std::vector;
863  typename vector<Value>::size_type i = d.size() / 2;
864  while (i --> 0) d[i] = *params_first++;
865 
866  // Now x_n = 0 because x_{n-p} = ... = x_{n-1} = 0 by construction.
867  }
868 
883  template <class RandomAccessIterator,
884  class NoiseGenerator>
885  predictor(RandomAccessIterator params_first,
886  RandomAccessIterator params_last,
887  NoiseGenerator generator)
888  : n(0),
889  d(2*std::distance(params_first, params_last), 0),
890  g(new nullary_impl1<Value,NoiseGenerator>(generator)),
891  xn((*g)())
892  {
893  // Finish preparing d = [ a_p, ..., a_1, 0, ..., 0 ]
894  using std::vector;
895  typename vector<Value>::size_type i = d.size() / 2;
896  while (i --> 0) d[i] = *params_first++;
897 
898  // Here x_0 = \epsilon_0 because x_{0-p} = ... = x_{0-1} = 0.
899  }
900 
902  predictor(const predictor& other)
903  : n(other.n),
904  d(other.d),
905  g(other.g ? other.g->clone() : 0),
906  xn(other.xn)
907  {}
908 
911  {
912  if (this != &other)
913  {
914  nullary<Value> *tmp = 0;
915  try
916  {
917  tmp = other.g ? other.g->clone() : 0;
918  }
919  catch (...)
920  {
921  delete tmp;
922  throw;
923  }
924  n = other.n;
925  d = other.d;
926  delete g;
927  g = tmp;
928  xn = other.xn;
929  }
930  return *this;
931  }
932 
935  {
936  delete g;
937  }
938 
950  template <class InputIterator>
951  predictor& initial_conditions(InputIterator initial_first,
952  const Value x0adjust = 0)
953  {
954  // Zero the simulation time.
955  n = 0;
956 
957  // Set d = [ a_p, ..., a_1, x_{n-p}, ..., x_{n-1} ]
958  using std::vector;
959  typename vector<Value>::size_type i = d.size();
960  typename vector<Value>::size_type p = i / 2;
961  while (i --> p) d[i] = *initial_first++;
962 
963  // Make x_n := - a_p*x_{n-p} - ... - a_1*x_{n-1} + x_n + x0adjust.
964  // By design, x_n was whatever it happened to be.
965  using std::inner_product;
966  xn += x0adjust;
967  xn = -inner_product(d.begin(), d.begin() + p, d.begin() + p, -xn);
968 
969  return *this;
970  }
971 
972  // Concept: InputIterator
973 
976  {
977  using std::distance;
978  using std::inner_product;
979  using std::vector;
980 
981  if (g)
982  {
983  typename vector<Value>::size_type p = d.size() / 2;
984  if (p)
985  {
986  // Make x_n = - a_p*x_{n-p} - ... - a_1*x_{n-1} + \epsilon_n
987  // by (conceptually) storing previously computed x_n into
988  // circular buffer, updating ++n, and computing x_{n+1}.
989  typename vector<Value>::iterator ab = d.begin();
990  typename vector<Value>::iterator xb = ab + p;
991  typename vector<Value>::iterator c = xb + n % p;
992  typename vector<Value>::iterator xe = d.end();
993  *c++ = xn;
994  xn = inner_product(c, xe, ab, -(*g)());
995  xn = -inner_product(xb, c, ab + distance(c, xe), xn );
996  }
997  else
998  {
999  xn = (*g)();
1000  }
1001  }
1002  else
1003  {
1004 #ifndef NDEBUG
1005  using std::numeric_limits;
1006  if (numeric_limits<Value>::has_quiet_NaN)
1007  xn = numeric_limits<Value>::quiet_NaN();
1008 #endif
1009  }
1010 
1011  ++n;
1012 
1013  return *this;
1014  }
1015 
1017  predictor operator++(int) // Postfix increment
1018  {
1019  predictor t(*this);
1020  ++*this;
1021  return t;
1022  }
1023 
1025  reference operator* () const
1026  {
1027  return xn;
1028  }
1029 
1030  // Concept: EqualityComparable
1031 
1033  bool operator== (const predictor& other) const
1034  {
1035  return n == other.n;
1036  }
1037 
1039  bool operator!= (const predictor& other) const
1040  {
1041  return !(*this == other);
1042  }
1043 
1044 private:
1045 
1047  Index n;
1048 
1056  typename std::vector<Value> d;
1057 
1062  nullary<Value> *g;
1063 
1068  Value xn;
1069 };
1070 
1083 template <class RandomAccessIterator,
1084  class InputIterator,
1085  class Value>
1086 predictor<typename std::iterator_traits<RandomAccessIterator>::value_type>
1087 autocorrelation(RandomAccessIterator params_first,
1088  RandomAccessIterator params_last,
1089  Value gain,
1090  InputIterator autocor_first)
1091 {
1092  predictor<typename std::iterator_traits<
1093  RandomAccessIterator
1094  >::value_type> p(params_first, params_last);
1095  p.initial_conditions(++autocor_first, 1 / gain);
1096  return p;
1097 }
1098 
1124 template <class Value>
1125 Value decorrelation_time(const std::size_t N,
1126  predictor<Value> rho,
1127  const bool abs_rho = false)
1128 {
1129  using std::abs;
1130  using std::size_t;
1131 
1132  Value T0 = *rho++;
1133 
1134  const Value twoinvN = Value(2) / N;
1135  if (abs_rho) {
1136  for (size_t i = 1; i <= N; ++i, ++rho)
1137  T0 += (2 - i*twoinvN) * abs(*rho);
1138  } else {
1139  for (size_t i = 1; i <= N; ++i, ++rho)
1140  T0 += (2 - i*twoinvN) * (*rho);
1141  }
1142 
1143  return T0;
1144 }
1145 
1175 template <class Value>
1176 Value decorrelation_time(const std::size_t N,
1177  predictor<Value> rho1,
1178  predictor<Value> rho2,
1179  const bool abs_rho = false)
1180 {
1181  using std::abs;
1182  using std::size_t;
1183 
1184  Value T0 = 1;
1185  ++rho1;
1186  ++rho2;
1187 
1188  const Value twoinvN = Value(2) / N;
1189  if (abs_rho) {
1190  for (size_t i = 1; i <= N; ++i, ++rho1, ++rho2)
1191  T0 += (2 - i*twoinvN) * abs((*rho1) * (*rho2));
1192  } else {
1193  for (size_t i = 1; i <= N; ++i, ++rho1, ++rho2)
1194  T0 += (2 - i*twoinvN) * ((*rho1) * (*rho2));
1195  }
1196 
1197  return T0;
1198 }
1199 
1238 template<class RandomAccessIterator,
1239  class InputIterator,
1240  class OutputIterator>
1241 void zohar_linear_solve(RandomAccessIterator a_first,
1242  RandomAccessIterator a_last,
1243  RandomAccessIterator r_first,
1244  InputIterator d_first,
1245  OutputIterator s_first)
1246 {
1247  using std::copy;
1248  using std::distance;
1249  using std::inner_product;
1250  using std::invalid_argument;
1251  using std::iterator_traits;
1252  using std::reverse_iterator;
1253  using std::vector;
1254 
1255  // Tildes indicate transposes while hats indicate reversed vectors.
1256 
1257  // InputIterator::value_type determines the working precision
1258  typedef typename iterator_traits<InputIterator>::value_type value_type;
1259  typedef vector<value_type> vector_type;
1260  typedef typename vector_type::size_type size_type;
1261 
1262  // Determine problem size using [a_first,a_last) and ensure nontrivial
1263  typename iterator_traits<RandomAccessIterator>::difference_type dist
1264  = distance(a_first, a_last);
1265  if (dist < 1) throw invalid_argument("distance(a_first, a_last) < 1");
1266  const size_type n = static_cast<size_type>(dist);
1267 
1268  // Allocate working storage and set initial values for recursion:
1269  vector_type s; s .reserve(n+1); s .push_back( *d_first);
1270  vector_type ehat; ehat.reserve(n ); ehat.push_back(-a_first[0]);
1271  vector_type g; g .reserve(n ); g .push_back(-r_first[0]);
1272  value_type lambda = 1 - a_first[0]*r_first[0];
1273 
1274  // Though recursive updates to s and g can be done in-place, updates to
1275  // ehat seemingly require one additional vector for storage:
1276  //
1277  // "This sequence of computations is economical of storage. It is only
1278  // necessary to retain quantities computed at level m - 1 until the
1279  // computations at level m are complete." [Trench1967, page 1504]
1280  vector_type next_ehat; next_ehat.reserve(n);
1281 
1282  // Recursion for i = {1, 2, ..., n - 1}:
1283  for (size_type i = 1; i < n; ++i)
1284  {
1285 
1286  reverse_iterator<RandomAccessIterator> rhat_first(r_first + i);
1287 
1288  // \theta_i = \delta_{i+1} - \tilde{s}_i \hat{r}_i
1289  const value_type neg_theta = inner_product(
1290  s.begin(), s.end(), rhat_first, value_type(-(*++d_first)));
1291 
1292  // \eta_i = -\rho_{-(i+1)} - \tilde{a}_i \hat{e}_i
1293  const value_type neg_eta = inner_product(
1294  ehat.begin(), ehat.end(), a_first, value_type(a_first[i]));
1295 
1296  // \gamma_i = -\rho_{i+1} - \tilde{g}_i \hat{r}_i
1297  const value_type neg_gamma = inner_product(
1298  g.begin(), g.end(), rhat_first, value_type(r_first[i]));
1299 
1300  /*
1301  * s_{i+1} = \bigl(\begin{smallmatrix}
1302  * s_i + (\theta_i/\lambda_i) \hat{e}_i \\
1303  * \theta_i/\lambda_i
1304  * \end{smallmatrix}\bigr)
1305  *
1306  * \hat{e}_{i+1} = \bigl(\begin{smallmatrix}
1307  * \eta_i/\lambda_i \\
1308  * \hat{e}_i + (\eta_i/\lambda_i) g_i
1309  * \end{smallmatrix}\bigr)
1310  *
1311  * g_{i+1} = \bigl(\begin{smallmatrix}
1312  * g_i + (\gamma_i/\lambda_i) \hat{e}_i \\
1313  * \gamma_i/\lambda_i
1314  * \end{smallmatrix}\bigr)
1315  */
1316  const value_type theta_by_lambda = -neg_theta/lambda;
1317  const value_type eta_by_lambda = -neg_eta /lambda;
1318  const value_type gamma_by_lambda = -neg_gamma/lambda;
1319  next_ehat.clear();
1320  next_ehat.push_back(eta_by_lambda);
1321  for (size_type j = 0; j < i; ++j)
1322  {
1323  s[j] += theta_by_lambda*ehat[j];
1324  next_ehat.push_back(ehat[j] + eta_by_lambda*g[j]);
1325  g[j] += gamma_by_lambda*ehat[j];
1326  }
1327  s.push_back(theta_by_lambda);
1328  g.push_back(gamma_by_lambda);
1329  ehat.swap(next_ehat);
1330 
1331  // \lambda_{i+1} = \lambda_i - \eta_i \gamma_i / \lambda_i
1332  lambda -= neg_eta*neg_gamma/lambda;
1333  }
1334 
1335  // Recursion for i = n differs slightly per Zohar's "Last Computed Values"
1336  // Computing g_n above was unnecessary but the incremental expense is small
1337  {
1338  reverse_iterator<RandomAccessIterator> rhat_first(r_first + n);
1339 
1340  // \theta_n = \delta_{n+1} - \tilde{s}_n \hat{r}_n
1341  const value_type neg_theta = inner_product(
1342  s.begin(), s.end(), rhat_first, value_type(-(*++d_first)));
1343 
1344  /*
1345  * s_{n+1} = \bigl(\begin{smallmatrix}
1346  * s_n + (\theta_n/\lambda_n) \hat{e}_n \\
1347  * \theta_n/\lambda_n
1348  * \end{smallmatrix}\bigr)
1349  */
1350  const value_type theta_by_lambda = -neg_theta/lambda;
1351  for (size_type j = 0; j < n; ++j)
1352  {
1353  s[j] += theta_by_lambda*ehat[j];
1354  }
1355  s.push_back(theta_by_lambda);
1356  }
1357 
1358  // Output solution
1359  copy(s.begin(), s.end(), s_first);
1360 }
1361 
1387 template<class RandomAccessIterator,
1388  class ForwardIterator>
1389 void zohar_linear_solve(RandomAccessIterator a_first,
1390  RandomAccessIterator a_last,
1391  RandomAccessIterator r_first,
1392  ForwardIterator d_first)
1393 {
1394  return zohar_linear_solve(a_first, a_last, r_first, d_first, d_first);
1395 }
1396 
1397 
1420 template<class RandomAccessIterator,
1421  class ForwardIterator>
1422 void zohar_linear_solve(RandomAccessIterator a_first,
1423  RandomAccessIterator a_last,
1424  ForwardIterator d_first)
1425 {
1426  return zohar_linear_solve(a_first, a_last, a_first, d_first);
1427 }
1428 
1433 
1461 {
1463  template <typename Result, typename Integer>
1464  static Result empirical_variance_zero(Integer N)
1465  {
1466  assert(N >= 1);
1467 
1468  Result den = N;
1469  return 1 / den;
1470  }
1471 };
1472 
1475 {
1477  template <typename Result, typename Integer>
1478  static Result empirical_variance_zero(Integer)
1479  {
1480  return 0;
1481  }
1482 };
1483 
1484 namespace { // anonymous
1485 
1486 // Oh the simultaneous love/hate because -Werror => -Werror=type-limits...
1487 
1488 template <typename T, bool> struct is_nonnegative_helper;
1489 
1490 template <typename T> struct is_nonnegative_helper<T, /*signed?*/ true>
1491 {
1492  static bool check(const T& t) { return t >= 0; }
1493 };
1494 
1495 template <typename T> struct is_nonnegative_helper<T, /*signed?*/ false>
1496 {
1497  static bool check(const T&) { return true; }
1498 };
1499 
1500 template <typename T> bool is_nonnegative(const T& t)
1501 {
1502  using std::numeric_limits;
1503  return is_nonnegative_helper<T,numeric_limits<T>::is_signed>::check(t);
1504 }
1505 
1506 }
1507 
1508 
1519 
1521 template <class MeanHandling>
1523 {
1524 public:
1525 
1531  template <typename Result, typename Integer1, typename Integer2>
1532  static Result empirical_variance(Integer1 N, Integer2 i)
1533  {
1534  assert(N >= 1);
1535  assert(is_nonnegative(i));
1536  assert(static_cast<Integer1>(i) <= N);
1537 
1538  if (i == 0)
1539  return MeanHandling::template empirical_variance_zero<Result>(N);
1540 
1541  Result num = N - i, den = N*(N + 2);
1542  return num / den;
1543  }
1544 };
1545 
1547 template <class MeanHandling>
1548 class Burg : public estimation_method
1549 {
1550 public:
1551 
1557  template <typename Result, typename Integer1, typename Integer2>
1558  static Result empirical_variance(Integer1 N, Integer2 i)
1559  {
1560  assert(N >= 1);
1561  assert(is_nonnegative(i));
1562  assert(static_cast<Integer1>(i) <= N);
1563 
1564  if (i == 0)
1565  return MeanHandling::template empirical_variance_zero<Result>(N);
1566 
1567  Result den = N + 1 - i;
1568  return 1 / den;
1569  }
1570 };
1571 
1573 template <class MeanHandling>
1574 class LSFB : public estimation_method
1575 {
1576 public:
1577 
1583  template <typename Result, typename Integer1, typename Integer2>
1584  static Result empirical_variance(Integer1 N, Integer2 i)
1585  {
1586  assert(N >= 1);
1587  assert(is_nonnegative(i));
1588  assert(static_cast<Integer1>(i) <= N);
1589 
1590  if (i == 0)
1591  return MeanHandling::template empirical_variance_zero<Result>(N);
1592 
1593  // Factorizing expression will cause problems in unsigned arithmetic
1594  Result den = N + Result(3)/2 - Result(3)/2 * i;
1595  return 1 / den;
1596  }
1597 };
1598 
1600 template <class MeanHandling>
1601 class LSF : public estimation_method
1602 {
1603 public:
1604 
1610  template <typename Result, typename Integer1, typename Integer2>
1611  static Result empirical_variance(Integer1 N, Integer2 i)
1612  {
1613  assert(N >= 1);
1614  assert(is_nonnegative(i));
1615  assert(static_cast<Integer1>(i) <= N);
1616 
1617  if (i == 0)
1618  return MeanHandling::template empirical_variance_zero<Result>(N);
1619 
1620  // Factorizing expression will cause problems in unsigned arithmetic
1621  Result den = N + 2 - 2*i;
1622  return 1 / den;
1623  }
1624 };
1625 
1627 template <class EstimationMethod,
1628  typename Result,
1629  typename Integer1 = std::size_t,
1630  typename Integer2 = Integer1>
1632 {
1633  typedef Integer1 first_argument_type;
1634  typedef Integer2 second_argument_type;
1635  typedef Result result_type;
1636 
1637  Result operator() (Integer1 N, Integer2 i) const
1638  {
1639  return EstimationMethod::template empirical_variance<Result>(N, i);
1640  }
1641 };
1642 
1650 template <class EstimationMethod,
1651  typename Result,
1652  typename Integer1 = std::size_t,
1653  typename Integer2 = Integer1>
1655 {
1656 private:
1657 
1658  Integer1 N;
1659  Integer2 i;
1660 
1661 public:
1662 
1663  typedef Result result_type;
1664 
1665  empirical_variance_generator(Integer1 N) : N(N), i(0) {}
1666 
1667  Result operator() ()
1668  {
1669  return EstimationMethod::template empirical_variance<Result>(N, i++);
1670  }
1671 };
1672 
1684 template <class EstimationMethod,
1685  typename Result,
1686  typename Integer1 = std::size_t,
1687  typename Integer2 = Integer1>
1689 {
1690 private:
1691  Integer1 N;
1692  Integer2 i;
1693 
1694 public:
1695  typedef std::random_access_iterator_tag iterator_category;
1696  typedef Result value_type;
1697  typedef std::ptrdiff_t difference_type;
1698  typedef const Result* pointer;
1699  typedef const Result& reference;
1700 
1702  empirical_variance_iterator() : N(0), i(1) {} // Null
1703 
1705  empirical_variance_iterator(Integer1 N) : N(N), i(0)
1706  { assert(N >= 1); }
1707 
1709  empirical_variance_iterator(Integer1 N, Integer2 i) : N(N), i(i) {}
1710 
1711  // Forward traversal
1712 
1713  empirical_variance_iterator& operator++()
1714  { assert(N >= 1); ++i; return *this; }
1715 
1716  empirical_variance_iterator operator++(int)
1717  { assert(N >= 1); return empirical_variance_iterator(N, i++); }
1718 
1719  empirical_variance_iterator operator+(const difference_type& k)
1720  { assert(N >= 1); return empirical_variance_iterator(N, i + k); }
1721 
1722  empirical_variance_iterator& operator+=(const difference_type& k)
1723  { assert(N >= 1); i += k; return *this; }
1724 
1725  // Backward traversal
1726 
1727  empirical_variance_iterator& operator--()
1728  { assert(N >= 1); --i; return *this; }
1729 
1730  empirical_variance_iterator operator--(int)
1731  { assert(N >= 1); return empirical_variance_iterator(N, i--); }
1732 
1733  empirical_variance_iterator operator-(const difference_type& k)
1734  { assert(N >= 1); return empirical_variance_iterator(N, i - k); }
1735 
1736  empirical_variance_iterator& operator-=(const difference_type& k)
1737  { assert(N >= 1); i -= k; return *this; }
1738 
1739  // Distance support
1740 
1741  difference_type operator-(const empirical_variance_iterator& other) const
1742  {
1743  if (!this->N) {
1744  return 1 + other.N - other.i;
1745  } else if (!other.N) {
1746  return -static_cast<difference_type>(1 + this->N - this->i);
1747  } else {
1748  assert(this->N == other.N);
1749  return this->i - other.i;
1750  }
1751  }
1752 
1753  // EqualityComparable
1754 
1755  bool operator==(const empirical_variance_iterator& other) const
1756  {
1757  if (!this->N) {
1758  return other.i >= static_cast<Integer2>(other.N + 1);
1759  } else if (!other.N) {
1760  return this->i >= static_cast<Integer2>(this->N + 1);
1761  } else {
1762  return this->N == other.N && this->i == other.i;
1763  }
1764  }
1765 
1766  bool operator!=(const empirical_variance_iterator& other) const
1767  { return !(*this == other); }
1768 
1769  // LessThanComparable will trigger assertion on nonsense N cases
1770 
1771  bool operator<(const empirical_variance_iterator& other) const
1772  { return (*this - other) < 0; }
1773 
1774  bool operator<=(const empirical_variance_iterator& other) const
1775  { return (*this - other) <= 0; }
1776 
1777  bool operator>(const empirical_variance_iterator& other) const
1778  { return (*this - other) > 0; }
1779 
1780  bool operator>=(const empirical_variance_iterator& other) const
1781  { return (*this - other) >= 0; }
1782 
1783  // Dereference operations
1784 
1785  const value_type operator*() const
1786  {
1787  assert(is_nonnegative(i));
1788  assert(i <= static_cast<Integer2>(N));
1789 
1790  return EstimationMethod::template empirical_variance<Result>(N, i);
1791  }
1792 
1793  const value_type operator[](const difference_type &k) const
1794  {
1795  assert(is_nonnegative(i + k));
1796  assert(i + k <= static_cast<Integer2>(N));
1797 
1798  return EstimationMethod::template empirical_variance<Result>(N, i + k);
1799  }
1800 };
1801 
1806 
1831 {
1833  template <typename Result, typename Input>
1834  static Result underfit_penalty(Input sigma2e)
1835  {
1836  using std::log;
1837  return log(Result(sigma2e));
1838  }
1839 };
1840 
1850 template <class Criterion,
1851  typename Result,
1852  typename Integer1,
1853  typename Integer2>
1854 Result evaluate(Result sigma2e, Integer1 N, Integer2 p)
1855 {
1856  Result underfit = Criterion::template underfit_penalty<Result>(sigma2e);
1857  Result overfit = Criterion::template overfit_penalty<Result>(N, p);
1858  return underfit + overfit;
1859 }
1860 
1865 template <int AlphaNumerator = 3, int AlphaDenominator = 1>
1866 struct GIC : public criterion
1867 {
1869  template <typename Result, typename Integer1, typename Integer2>
1870  static Result overfit_penalty(Integer1 N, Integer2 p)
1871  {
1872  return Result(AlphaNumerator) * p / (N * AlphaDenominator);
1873  }
1874 };
1875 
1877 struct AIC : public GIC<2> {};
1878 
1880 struct BIC : public criterion
1881 {
1883  template <typename Result, typename Integer1, typename Integer2>
1884  static Result overfit_penalty(Integer1 N, Integer2 p)
1885  {
1886  using std::log;
1887  return log(Result(N)) * p / N;
1888  }
1889 };
1890 
1892 struct MCC : public criterion
1893 {
1895  template <typename Result, typename Integer1, typename Integer2>
1896  static Result overfit_penalty(Integer1 N, Integer2 p)
1897  {
1898  using std::log;
1899  return 2*log(log(Result(N))) * p / N;
1900  }
1901 };
1902 
1906 struct AICC : public criterion
1907 {
1909  template <typename Result, typename Integer1, typename Integer2>
1910  static Result overfit_penalty(Integer1 N, Integer2 p)
1911  {
1912  return 2 * Result(p) / (N - p - 1);
1913  }
1914 };
1915 
1921 template <class EstimationMethod,
1922  int AlphaNumerator = 3,
1923  int AlphaDenominator = 1 >
1924 struct FIC : public criterion
1925 {
1927  template <typename Result, typename Integer1, typename Integer2>
1928  static Result overfit_penalty(Integer1 N, Integer2 p)
1929  {
1930  // This accumulate invocation is inefficient but always correct
1931  using std::accumulate;
1933  EstimationMethod, Result, Integer1, Integer2
1934  > evi_type;
1935  Result sum = accumulate(evi_type(N), evi_type(N) + p, Result(0));
1936 
1937  return AlphaNumerator * sum / AlphaDenominator;
1938  }
1939 };
1940 
1946 template <class MeanHandling,
1947  int AlphaNumerator,
1948  int AlphaDenominator>
1949 struct FIC<YuleWalker<MeanHandling>, AlphaNumerator, AlphaDenominator>
1950  : public criterion
1951 {
1953  template <typename Result, typename Integer1, typename Integer2>
1954  static Result overfit_penalty(Integer1 N, Integer2 p)
1955  {
1956  Result v0 = YuleWalker<MeanHandling>
1957  ::template empirical_variance<Result>(N, Integer2(0));
1958 
1959  Result num = (2*N - p - 1)*p; // Avoids non-positive values
1960  Result den = 2*N*(N + 2);
1961 
1962  return AlphaNumerator * (v0 + num/den) / AlphaDenominator;
1963  }
1964 };
1965 
1966 // Specializations of the FIC for efficiency when digamma is available.
1967 #ifdef AR_DIGAMMA
1968 
1974 template <class MeanHandling,
1975  int AlphaNumerator,
1976  int AlphaDenominator>
1977 struct FIC<Burg<MeanHandling>, AlphaNumerator, AlphaDenominator>
1978  : public criterion
1979 {
1981  template <typename Result, typename Integer1, typename Integer2>
1982  static Result overfit_penalty(Integer1 N, Integer2 p)
1983  {
1984  Result t = Burg<MeanHandling>
1985  ::template empirical_variance<Result>(N, Integer2(0));
1986  t -= AR_DIGAMMA(N + 1);
1987  t += AR_DIGAMMA(N + 1 - p);
1988  return AlphaNumerator * t / AlphaDenominator;
1989  }
1990 };
1991 
1997 template <class MeanHandling,
1998  int AlphaNumerator,
1999  int AlphaDenominator>
2000 struct FIC<LSFB<MeanHandling>, AlphaNumerator, AlphaDenominator>
2001  : public criterion
2002 {
2004  template <typename Result, typename Integer1, typename Integer2>
2005  static Result overfit_penalty(Integer1 N, Integer2 p)
2006  {
2007  Result t = LSFB<MeanHandling>
2008  ::template empirical_variance<Result>(N, Integer2(0));
2009  Result a = AR_DIGAMMA((3 + 2*N) / Result(3) );
2010  Result b = AR_DIGAMMA((3 + 2*N) / Result(3) - p);
2011  return AlphaNumerator * (t - 2*(a - b)/3) / AlphaDenominator;
2012  }
2013 };
2014 
2020 template <class MeanHandling,
2021  int AlphaNumerator,
2022  int AlphaDenominator>
2023 struct FIC<LSF<MeanHandling>, AlphaNumerator, AlphaDenominator>
2024  : public criterion
2025 {
2027  template <typename Result, typename Integer1, typename Integer2>
2028  static Result overfit_penalty(Integer1 N, Integer2 p)
2029  {
2030  Result t = LSF<MeanHandling>
2031  ::template empirical_variance<Result>(N, Integer2(0));
2032  Result a = AR_DIGAMMA((2 + N) / Result(2) );
2033  Result b = AR_DIGAMMA((2 + N) / Result(2) - p);
2034  return AlphaNumerator * (t - (a - b)/2) / AlphaDenominator;
2035  }
2036 };
2037 
2038 #endif /* AR_DIGAMMA */
2039 
2044 template <class EstimationMethod>
2045 struct FSIC : public criterion
2046 {
2047 
2048 private:
2049 
2051  template <typename Result, typename Integer1, typename Integer2>
2052  class product_iterator
2053  : public empirical_variance_iterator<
2054  EstimationMethod, Result, Integer1, Integer2
2055  >
2056  {
2057  private:
2059  EstimationMethod, Result, Integer1, Integer2
2060  > base;
2061 
2062  public:
2063  typedef typename base::difference_type difference_type;
2064  typedef typename base::iterator_category iterator_category;
2065  typedef typename base::pointer pointer;
2066  typedef typename base::reference reference;
2067  typedef typename base::value_type value_type;
2068 
2069  product_iterator(Integer1 N) : base(N) {}
2070 
2071  value_type operator*() const
2072  {
2073  const value_type v = this->base::operator*();
2074  return (1 + v) / (1 - v);
2075  }
2076 
2077  value_type operator[](const difference_type &k) const
2078  {
2079  const value_type v = this->base::operator[](k);
2080  return (1 + v) / (1 - v);
2081  }
2082 
2083  };
2084 
2085 public:
2086 
2088  template <typename Result, typename Integer1, typename Integer2>
2089  static Result overfit_penalty(Integer1 N, Integer2 p)
2090  {
2091  // This accumulate invocation is inefficient but always correct
2092  using std::multiplies;
2093  using std::accumulate;
2094  product_iterator<Result, Integer1, Integer2> first(N), last(N);
2095  last += p; // Avoids overloading requirements for (last + p)
2096 
2097  return accumulate(first, last, Result(1), multiplies<Result>()) - 1;
2098  }
2099 };
2100 
2101 // Specializations of the FIC for efficiency when Pochhammer is available.
2102 #ifdef AR_POCHHAMMER
2103 
2108 template <class MeanHandling>
2109 struct FSIC<YuleWalker<MeanHandling> > : public criterion
2110 {
2112  template <typename Result, typename Integer1, typename Integer2>
2113  static Result overfit_penalty(Integer1 N, Integer2 p)
2114  {
2115  Result v0 = YuleWalker<MeanHandling>
2116  ::template empirical_variance<Result>(N, Integer2(0));
2117  Result a = AR_POCHHAMMER(N*(N+3) - p, p);
2118  Result b = AR_POCHHAMMER(Result(1 + N) - N*N, p);
2119 
2120  return (1 + v0) / (1 - v0) * (a / b) - 1;
2121  }
2122 };
2123 
2128 template <class MeanHandling>
2129 struct FSIC<Burg<MeanHandling> > : public criterion
2130 {
2132  template <typename Result, typename Integer1, typename Integer2>
2133  static Result overfit_penalty(Integer1 N, Integer2 p)
2134  {
2135  Result v0 = Burg<MeanHandling>
2136  ::template empirical_variance<Result>(N, Integer2(0));
2137  Result a = AR_POCHHAMMER(-Result(1) - N, p);
2138  Result b = AR_POCHHAMMER( Result(1) - N, p);
2139 
2140  return (1 + v0) / (1 - v0) * (a / b) - 1;
2141  }
2142 };
2143 
2148 template <class MeanHandling>
2149 struct FSIC<LSFB<MeanHandling> > : public criterion
2150 {
2152  template <typename Result, typename Integer1, typename Integer2>
2153  static Result overfit_penalty(Integer1 N, Integer2 p)
2154  {
2155  Result v0 = LSFB<MeanHandling>
2156  ::template empirical_variance<Result>(N, Integer2(0));
2157  Result a = AR_POCHHAMMER((-Result(2)-2*N)/3, p);
2158  Result b = AR_POCHHAMMER(( Result(2)-2*N)/3, p);
2159 
2160  return (1 + v0) / (1 - v0) * (a / b) - 1;
2161  }
2162 };
2163 
2168 template <class MeanHandling>
2169 struct FSIC<LSF<MeanHandling> > : public criterion
2170 {
2172  template <typename Result, typename Integer1, typename Integer2>
2173  static Result overfit_penalty(Integer1 N, Integer2 p)
2174  {
2175  Result v0 = LSF<MeanHandling>
2176  ::template empirical_variance<Result>(N, Integer2(0));
2177  Result a = AR_POCHHAMMER((-Result(1)-N)/2, p);
2178  Result b = AR_POCHHAMMER(( Result(1)-N)/2, p);
2179 
2180  return (1 + v0) / (1 - v0) * (a / b) - 1;
2181  }
2182 };
2183 
2184 #endif /* AR_POCHHAMMER */
2185 
2186 
2191 template <class EstimationMethod>
2192 struct CIC : public criterion
2193 {
2195  template <typename Result, typename Integer1, typename Integer2>
2196  static Result overfit_penalty(Integer1 N, Integer2 p)
2197  {
2198  using std::max;
2199  return max(
2200  FSIC<EstimationMethod>::template overfit_penalty<Result>(N, p),
2201  FIC <EstimationMethod>::template overfit_penalty<Result>(N, p)
2202  );
2203  }
2204 };
2205 
2210 
2237 template <class Criterion,
2238  typename Integer1,
2239  typename Integer2,
2240  class InputIterator,
2241  class OutputIterator>
2242 typename std::iterator_traits<InputIterator>::difference_type
2243 evaluate_models(Integer1 N,
2244  Integer2 ordfirst,
2245  InputIterator first,
2246  InputIterator last,
2247  OutputIterator crit)
2248 {
2249  using std::iterator_traits;
2250  using std::numeric_limits;
2251 
2252  typedef InputIterator iterator;
2253  typedef typename iterator_traits<iterator>::difference_type difference_type;
2254  typedef typename iterator_traits<iterator>::value_type value_type;
2255 
2256  // Short circuit on trivial input
2257  if (first == last)
2258  return numeric_limits<difference_type>::min();
2259 
2260  // Handle first iteration without comparison as AICC blows up on N == 1
2261  value_type best_val = evaluate<Criterion>(*first++, N, ordfirst);
2262  difference_type best_pos = 0, dist = 0;
2263 
2264  // Scan through rest of candidates (up to order N-1) updating best as we go
2265  while (first != last && static_cast<Integer1>(++dist) < N)
2266  {
2267  value_type candidate = evaluate<Criterion>(*first++, N, dist+ordfirst);
2268  *crit++ = candidate;
2269 
2270  if (candidate < best_val) {
2271  best_val = candidate;
2272  best_pos = dist;
2273  }
2274  }
2275 
2276  return best_pos;
2277 }
2278 
2301 template <class Criterion,
2302  typename Integer1,
2303  typename Integer2,
2304  class Sequence1,
2305  class Sequence2,
2306  class Sequence3,
2307  class Sequence4,
2308  class OutputIterator>
2309 typename Sequence1::difference_type
2310 best_model(Integer1 N,
2311  Integer2 minorder,
2312  Sequence1& params,
2313  Sequence2& sigma2e,
2314  Sequence3& gain,
2315  Sequence4& autocor,
2316  OutputIterator crit)
2317 {
2318  using std::advance;
2319  using std::copy_backward;
2320  using std::invalid_argument;
2321  using std::size_t;
2322 
2323  // Ensure all inputs have conformant sizes
2324  // Sanity checks written to provide order messages readable by end users
2325  AR_ENSURE_ARG(sigma2e.size() > 0);
2326  const size_t maxorder = sigma2e.size() - 1;
2327  AR_ENSURE_ARG(is_nonnegative(minorder));
2328  AR_ENSURE_ARG(static_cast<size_t>(minorder) <= maxorder);
2329  AR_ENSURE_ARG(params .size() == (sigma2e.size()-1)*sigma2e.size()/2);
2330  AR_ENSURE_ARG(gain .size() == sigma2e.size());
2331  AR_ENSURE_ARG(autocor.size() == sigma2e.size());
2332 
2333  // Find the best model index according to the given minorder and criterion
2334  typename Sequence1::difference_type best = minorder;
2335  {
2336  typename Sequence2::iterator iter = sigma2e.begin();
2337  advance(iter, minorder);
2338  best += evaluate_models<Criterion>(N, minorder, iter,
2339  sigma2e.end(), crit);
2340  }
2341 
2342  // Now trim away everything and leaving only the best model in Sequences...
2343 
2344  // ...first in params...
2345  {
2346  // Best parameters might overlap beginning of params so copy_backwards.
2347  // AR(0) is trivial and AR(1) starts at params.begin(), hence off by 1.
2348  typename Sequence1::iterator first = params.begin();
2349  typename Sequence1::iterator last = params.begin();
2350  typename Sequence1::iterator result = params.begin();
2351  advance(first, ((best-1)*best)/2 );
2352  advance(last, ((best-1)*best)/2 + best);
2353  advance(result, best);
2354  copy_backward(first, last, result);
2355  params.resize(best);
2356  }
2357 
2358  // ...next in sigma2e...
2359  {
2360  typename Sequence2::iterator cursor = sigma2e.begin();
2361  advance(cursor, best);
2362  *sigma2e.begin() = *cursor;
2363  sigma2e.resize(1);
2364  }
2365 
2366  // ...next in gain...
2367  {
2368  typename Sequence2::iterator cursor = gain.begin();
2369  advance(cursor, best);
2370  *gain.begin() = *cursor;
2371  gain.resize(1);
2372  }
2373 
2374  // ...and last in autocor...
2375  autocor.resize(best + 1);
2376 
2377  // ...but notice that resizing does not free capacity for std::vectors.
2378 
2379  return best;
2380 }
2381 
2382 namespace { // anonymous
2383 
2384 // Used to discard output per http://stackoverflow.com/questions/335930/
2385 struct null_output
2386 {
2387  typedef std::output_iterator_tag iterator_category;
2388  typedef void value_type;
2389  typedef void difference_type;
2390  typedef void pointer;
2391  typedef void reference;
2392 
2393  template <typename T> void operator=(const T&) {}
2394 
2395  null_output& operator++()
2396  { return *this; }
2397 
2398  null_output operator++(int)
2399  { null_output it(*this); ++*this; return it; }
2400 
2401  null_output& operator*()
2402  { return *this; }
2403 };
2404 
2405 }
2406 
2422 template <class Criterion,
2423  typename Integer1,
2424  typename Integer2,
2425  class InputIterator>
2426 typename std::iterator_traits<InputIterator>::difference_type
2427 evaluate_models(Integer1 N,
2428  Integer2 ordfirst,
2429  InputIterator first,
2430  InputIterator last)
2431 {
2432  return evaluate_models<Criterion>(N, ordfirst, first, last, null_output());
2433 }
2434 
2458 template <class Criterion,
2459  typename Integer1,
2460  typename Integer2,
2461  class Sequence1,
2462  class Sequence2,
2463  class Sequence3,
2464  class Sequence4>
2465 typename Sequence1::difference_type
2466 best_model(Integer1 N,
2467  Integer2 minorder,
2468  Sequence1& params,
2469  Sequence2& sigma2e,
2470  Sequence3& gain,
2471  Sequence4& autocor)
2472 {
2473  return best_model<Criterion>(N, minorder, params, sigma2e, gain,
2474  autocor, null_output());
2475 }
2476 
2508 template <template <class> class EstimationMethod,
2509  typename Integer1,
2510  typename Integer2,
2511  class Sequence1,
2512  class Sequence2 = Sequence1,
2513  class Sequence3 = Sequence2,
2514  class Sequence4 = Sequence3>
2516 {
2518  typedef typename Sequence1::difference_type (*type)(Integer1 N,
2519  Integer2 minorder,
2520  Sequence1& params,
2521  Sequence2& sigma2e,
2522  Sequence3& gain,
2523  Sequence4& autocor);
2524 
2542  template <class CharT, class Traits, class Allocator>
2543  static type lookup(std::basic_string<CharT,Traits,Allocator> abbreviation,
2544  const bool subtract_mean);
2545 
2559  static type lookup(const char *abbreviation, const bool subtract_mean)
2560  {
2561  std::string s(abbreviation);
2562  return lookup(s, subtract_mean);
2563  }
2564 };
2565 
2566 template <template <class> class EstimationMethod,
2567  typename Integer1,
2568  typename Integer2,
2569  class Sequence1,
2570  class Sequence2,
2571  class Sequence3,
2572  class Sequence4>
2573 template <class CharT, class Traits, class Allocator>
2574 typename best_model_function<
2575  EstimationMethod,Integer1,Integer2,Sequence1,Sequence2,Sequence3,Sequence4
2576 >::type
2577 best_model_function<
2578  EstimationMethod,Integer1,Integer2,Sequence1,Sequence2,Sequence3,Sequence4
2579 >::lookup(std::basic_string<CharT,Traits,Allocator> abbrev,
2580  const bool subtract_mean)
2581 {
2582  using std::basic_string;
2583  using std::toupper;
2584 
2585  // Canonicalize the abbreviation by making it uppercase and trimming it
2586  // For nothing but this reason the method accepts 'abbrev' by value
2587  typedef basic_string<CharT,Traits,Allocator> string_type;
2588  for (typename string_type::iterator p = abbrev.begin();
2589  abbrev.end() != p; ++p)
2590  {
2591  *p = toupper(*p);
2592  }
2593  abbrev.erase(0, abbrev.find_first_not_of(" \n\r\t"));
2594  abbrev.erase(1 + abbrev.find_last_not_of(" \n\r\t"));
2595 
2596  // Obtain best_model(...) per abbrev, subtract_mean, EstimationMethod
2597  // and assign to retval to provide unambiguous overload resolution.
2598  type retval;
2599 
2600  if (abbrev.empty() || 0 == abbrev.compare("CIC" )) // Default
2601  {
2602  if (subtract_mean)
2603  retval = best_model<CIC<EstimationMethod<mean_subtracted> > >;
2604  else
2605  retval = best_model<CIC<EstimationMethod<mean_retained > > >;
2606  }
2607  else if (0 == abbrev.compare("AIC" ))
2608  {
2609  retval = best_model<AIC>;
2610  }
2611  else if (0 == abbrev.compare("AICC"))
2612  {
2613  retval = best_model<AICC>;
2614  }
2615  else if (0 == abbrev.compare("BIC" ))
2616  {
2617  retval = best_model<BIC>;
2618  }
2619  else if (0 == abbrev.compare("FIC" ))
2620  {
2621  if (subtract_mean)
2622  retval = best_model<FIC<EstimationMethod<mean_subtracted> > >;
2623  else
2624  retval = best_model<FIC<EstimationMethod<mean_retained > > >;
2625  }
2626  else if (0 == abbrev.compare("FSIC"))
2627  {
2628  if (subtract_mean)
2629  retval = best_model<FSIC<EstimationMethod<mean_subtracted> > >;
2630  else
2631  retval = best_model<FSIC<EstimationMethod<mean_retained > > >;
2632  }
2633  else if (0 == abbrev.compare("GIC" ))
2634  {
2635  retval = best_model<GIC<> >;
2636  }
2637  else if (0 == abbrev.compare("MCC" ))
2638  {
2639  retval = best_model<MCC>;
2640  } else
2641  {
2642  retval = NULL;
2643  }
2644 
2645  return retval;
2646 }
2647 
2654 template<class Iterator>
2656 {
2657 public:
2658  typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category;
2659  typedef typename std::iterator_traits<Iterator>::value_type value_type;
2660  typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
2661  typedef typename std::iterator_traits<Iterator>::pointer pointer;
2662  typedef typename std::iterator_traits<Iterator>::reference reference;
2663 
2664  strided_adaptor() : i(NULL), step(0) {};
2665 
2666  strided_adaptor(const strided_adaptor& o) : i(o.i), step(o.step) {}
2667 
2668  strided_adaptor(Iterator x, difference_type n) : i(x), step(n) {}
2669 
2670  strided_adaptor& operator++()
2671  {
2672  using std::advance;
2673  advance(i, step);
2674  return *this;
2675  }
2676 
2677  strided_adaptor operator++(int)
2678  {
2679  strided_adaptor tmp(*this);
2680  using std::advance;
2681  advance(i, step);
2682  return tmp;
2683  }
2684 
2685  strided_adaptor& operator+=(difference_type x)
2686  {
2687  using std::advance;
2688  advance(i, x*step);
2689  return *this;
2690  }
2691 
2692  strided_adaptor& operator--( )
2693  {
2694  using std::advance;
2695  advance(i, -step);
2696  return *this;
2697  }
2698 
2699  strided_adaptor operator--(int)
2700  {
2701  strided_adaptor tmp(*this);
2702  using std::advance;
2703  advance(i, -step);
2704  return tmp;
2705  }
2706 
2707  strided_adaptor& operator-=(difference_type x)
2708  {
2709  using std::advance;
2710  advance(i, -x*step);
2711  return *this;
2712  }
2713 
2714  reference operator[](difference_type n)
2715  {
2716  return i[n * step];
2717  }
2718 
2719  reference operator*()
2720  {
2721  return *i;
2722  }
2723 
2724  bool operator==(const strided_adaptor& o) const
2725  {
2726  return i == o.i;
2727  }
2728 
2729  bool operator!=(const strided_adaptor& o) const
2730  {
2731  return i != o.i;
2732  }
2733 
2734  bool operator<(const strided_adaptor& o) const
2735  {
2736  return i < o.i;
2737  }
2738 
2739  difference_type operator-(const strided_adaptor& o) const
2740  {
2741  return (i - o.i) / step;
2742  }
2743 
2744  strided_adaptor operator+(difference_type x) const
2745  {
2746  strided_adaptor tmp(*this);
2747  tmp += x;
2748  return tmp;
2749  }
2750 
2751 private:
2752  Iterator i;
2753  difference_type step;
2754 };
2755 
2760 
2764 } // end namespace ar
2765 
2766 #endif /* AR_HPP */
ar::welford_covariance_sample
std::size_t welford_covariance_sample(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputType1 &mean1, OutputType2 &mean2, OutputType3 &covar)
Compute means and the sample covariance using Welford's algorithm.
Definition: ar.hpp:356
ar::Burg
Represents estimation using Burg's recursive method.
Definition: ar.hpp:1548
ar::MCC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1896
ar::welford_variance_population
std::size_t welford_variance_population(InputIterator first, InputIterator last, OutputType1 &mean, OutputType2 &var)
Compute the mean and population variance using Welford's algorithm.
Definition: ar.hpp:217
ar::decorrelation_time
Value decorrelation_time(const std::size_t N, predictor< Value > rho, const bool abs_rho=false)
Compute the decorrelation time for variance of the mean given autocorrelation details.
Definition: ar.hpp:1125
ar::empirical_variance_iterator::empirical_variance_iterator
empirical_variance_iterator()
Construct a past-end iterator.
Definition: ar.hpp:1702
ar::mean_retained::empirical_variance_zero
static Result empirical_variance_zero(Integer)
Computes the empirical variance estimate for order zero.
Definition: ar.hpp:1478
ar::negative_half_reflection_coefficient
ValueType negative_half_reflection_coefficient(InputIterator1 a_first, InputIterator1 a_last, InputIterator2 b_first)
Algorithms for autoregressive parameter estimation and manipulation.
Definition: ar.hpp:470
ar::predictor::operator++
predictor & operator++()
Prefix increment.
Definition: ar.hpp:975
ar::mean_subtracted::empirical_variance_zero
static Result empirical_variance_zero(Integer N)
Computes the empirical variance estimate for order zero.
Definition: ar.hpp:1464
ar::best_model_function
A template typedef and helper method returning a best_model implementation matching a model selection...
Definition: ar.hpp:2515
ar::MCC
Represents the minimally consistent criterion (MCC).
Definition: ar.hpp:1892
ar::predictor::predictor
predictor(RandomAccessIterator params_first, RandomAccessIterator params_last, NoiseGenerator generator)
Iterate on the process given zero initial conditions.
Definition: ar.hpp:885
ar::burg_method
std::size_t burg_method(InputIterator data_first, InputIterator data_last, Value &mean, std::size_t &maxorder, OutputIterator1 params_first, OutputIterator2 sigma2e_first, OutputIterator3 gain_first, OutputIterator4 autocor_first, const bool subtract_mean, const bool hierarchy, Vector &f, Vector &b, Vector &Ak, Vector &ac)
Fit an autoregressive model to stationary time series data using Burg's method.
Definition: ar.hpp:542
ar::mean_retained
Denotes the sample mean was retained in a signal during estimation.
Definition: ar.hpp:1474
ar::FSIC
Represents the finite sample information criterion (FSIC) as applied to a particular estimation_metho...
Definition: ar.hpp:2045
ar::BIC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1884
ar::welford_covariance_population
std::size_t welford_covariance_population(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputType1 &mean1, OutputType2 &mean2, OutputType3 &covar)
Compute means and the population covariance using Welford's algorithm.
Definition: ar.hpp:326
ar::evaluate_models
std::iterator_traits< InputIterator >::difference_type evaluate_models(Integer1 N, Integer2 ordfirst, InputIterator first, InputIterator last, OutputIterator crit)
Algorithmic helpers for autoregressive model order selection.
Definition: ar.hpp:2243
ar::criterion::underfit_penalty
static Result underfit_penalty(Input sigma2e)
Compute the underfit penalty given .
Definition: ar.hpp:1834
ar::zohar_linear_solve
void zohar_linear_solve(RandomAccessIterator a_first, RandomAccessIterator a_last, RandomAccessIterator r_first, InputIterator d_first, OutputIterator s_first)
Solve a Toeplitz set of linear equations.
Definition: ar.hpp:1241
ar::mean_subtracted
Method-specific estimation variance routines following Broersen.
Definition: ar.hpp:1460
ar::criterion
Criteria for autoregressive model order selection following Broersen.
Definition: ar.hpp:1830
AR_ENSURE_ARG
#define AR_ENSURE_ARG(expr)
Ensure that the argument-related expr evaluates to boolean true at runtime.
Definition: ar.hpp:134
ar::estimation_method
A parent type for autoregressive process parameter estimation techniques.
Definition: ar.hpp:1518
ar::empirical_variance_iterator
An immutable RandomAccessIterator over a method's empirical variance sequence.
Definition: ar.hpp:1688
ar::predictor::operator!=
bool operator!=(const predictor &other) const
Check if two iterators represent different simulation times.
Definition: ar.hpp:1039
ar::LSF::empirical_variance
static Result empirical_variance(Integer1 N, Integer2 i)
Approximates the empirical variance estimate.
Definition: ar.hpp:1611
ar::Burg::empirical_variance
static Result empirical_variance(Integer1 N, Integer2 i)
Approximates the empirical variance estimate.
Definition: ar.hpp:1558
ar::empirical_variance_iterator::empirical_variance_iterator
empirical_variance_iterator(Integer1 N, Integer2 i)
Construct an iterator over sequence order i, i+1, ..., N (inclusive).
Definition: ar.hpp:1709
ar::LSFB
Represents forward and backward prediction least squares minimization.
Definition: ar.hpp:1574
ar::best_model_function::lookup
static type lookup(const char *abbreviation, const bool subtract_mean)
Lookup a best_model function pointer matching EstimationMethod, the specified criterion c abbreviatio...
Definition: ar.hpp:2559
ar::GIC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1870
ar::strided_adaptor
An adapter to add striding over another (usually random access) iterator.
Definition: ar.hpp:2655
ar::LSFB::empirical_variance
static Result empirical_variance(Integer1 N, Integer2 i)
Approximates the empirical variance estimate.
Definition: ar.hpp:1584
ar::empirical_variance_generator
An STL AdaptableGenerator for a given method's empirical variance.
Definition: ar.hpp:1654
ar::best_model_function::lookup
static type lookup(std::basic_string< CharT, Traits, Allocator > abbreviation, const bool subtract_mean)
Lookup a best_model function pointer matching EstimationMethod, the specified criterion c abbreviatio...
Definition: ar.hpp:2579
ar::FSIC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:2089
ar::FIC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1928
ar::predictor::~predictor
~predictor()
Destructor.
Definition: ar.hpp:934
ar::YuleWalker::empirical_variance
static Result empirical_variance(Integer1 N, Integer2 i)
Approximates the empirical variance estimate.
Definition: ar.hpp:1532
ar::YuleWalker
Represents estimation by solving the Yule–Walker equations.
Definition: ar.hpp:1522
ar::predictor::predictor
predictor(RandomAccessIterator params_first, RandomAccessIterator params_last)
Iterate on the process .
Definition: ar.hpp:854
ar::predictor::predictor
predictor(const predictor &other)
Copy constructor.
Definition: ar.hpp:902
ar::predictor::operator==
bool operator==(const predictor &other) const
Check if two iterators represent the same simulation time.
Definition: ar.hpp:1033
ar::predictor::operator*
reference operator*() const
Obtain the process prediction .
Definition: ar.hpp:1025
ar::predictor::predictor
predictor(Index n=0)
Singular instance marking prediction index n.
Definition: ar.hpp:833
ar::welford_variance_sample
std::size_t welford_variance_sample(InputIterator first, InputIterator last, OutputType1 &mean, OutputType2 &var)
Compute the mean and sample variance using Welford's algorithm.
Definition: ar.hpp:241
ar::best_model_function::type
Sequence1::difference_type(* type)(Integer1 N, Integer2 minorder, Sequence1 &params, Sequence2 &sigma2e, Sequence3 &gain, Sequence4 &autocor)
The type returned by the lookup function.
Definition: ar.hpp:2518
ar::predictor
Simulate an autoregressive model process with an InputIterator interface.
Definition: ar.hpp:823
ar::empirical_variance_iterator::empirical_variance_iterator
empirical_variance_iterator(Integer1 N)
Construct an iterator over sequence order 0, 1, ..., N (inclusive).
Definition: ar.hpp:1705
ar::AICC
Represents the asymptotically-corrected Akaike information criterion (AICC).
Definition: ar.hpp:1906
ar::evaluate
Result evaluate(Result sigma2e, Integer1 N, Integer2 p)
Evaluate a given criterion for N samples and model order p.
Definition: ar.hpp:1854
ar::empirical_variance_function
An STL-ready binary_function for a given method's empirical variance.
Definition: ar.hpp:1631
ar::autocorrelation
predictor< typename std::iterator_traits< RandomAccessIterator >::value_type > autocorrelation(RandomAccessIterator params_first, RandomAccessIterator params_last, Value gain, InputIterator autocor_first)
Construct an iterator over the autocorrelation function given process parameters and initial conditi...
Definition: ar.hpp:1087
ar::LSF
Represents forward prediction least squares minimization.
Definition: ar.hpp:1601
ar::AICC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1910
ar::predictor::operator=
predictor & operator=(const predictor &other)
Assignment operator.
Definition: ar.hpp:910
ar::predictor::initial_conditions
predictor & initial_conditions(InputIterator initial_first, const Value x0adjust=0)
Specify process initial conditions where is the process order fixed by the constructor.
Definition: ar.hpp:951
ar::CIC::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:2196
ar::welford_nvariance
std::size_t welford_nvariance(InputIterator first, InputIterator last, OutputType1 &mean, OutputType2 &nvar)
Stable, one-pass algorithms for computing variances and covariances.
Definition: ar.hpp:178
ar::predictor::operator++
predictor operator++(int)
Postfix increment.
Definition: ar.hpp:1017
ar
Autoregressive process modeling tools in header-only C++.
Definition: ar.hpp:71
ar::best_model
Sequence1::difference_type best_model(Integer1 N, Integer2 minorder, Sequence1 &params, Sequence2 &sigma2e, Sequence3 &gain, Sequence4 &autocor, OutputIterator crit)
Obtain the best model according to criterion applied to given a hierarchy of candidates.
Definition: ar.hpp:2310
ar::welford_ncovariance
std::size_t welford_ncovariance(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputType1 &mean1, OutputType2 &mean2, OutputType3 &ncovar)
Compute means and the number of samples, N, times the population covariance using Welford's algorithm...
Definition: ar.hpp:271
ar::FIC< YuleWalker< MeanHandling >, AlphaNumerator, AlphaDenominator >::overfit_penalty
static Result overfit_penalty(Integer1 N, Integer2 p)
Compute overfit penalty given N observations at model order p.
Definition: ar.hpp:1954
ar::AIC
Represents the Akaike information criterion (AIC).
Definition: ar.hpp:1877
ar::CIC
Represents the combined information criterion (CIC) as applied to a particular estimation_method.
Definition: ar.hpp:2192
ar::BIC
Represents the consistent criterion BIC.
Definition: ar.hpp:1880
ar::GIC
Represents the generalized information criterion (GIC).
Definition: ar.hpp:1866
ar::FIC
Represents the finite information criterion (FIC) as applied to a particular estimation_method.
Definition: ar.hpp:1924
ar::welford_inner_product
ValueType welford_inner_product(InputIterator first, InputIterator last, ValueType init)
Compute the inner product of [first, last) with itself using welford_nvariance.
Definition: ar.hpp:383