Advertisement
Guest User

Untitled

a guest
May 20th, 2019
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.82 KB | None | 0 0
  1. #ifndef AUTOREG_HH
  2. #define AUTOREG_HH
  3.  
  4. #include <algorithm>             // for min, any_of, copy_n, for_each, generate
  5. #include <cassert>               // for assert
  6. #include <chrono>                // for duration, steady_clock, steady_clock...
  7. #include <cmath>                 // for isnan
  8. #include <cstdlib>               // for abs
  9. #include <functional>            // for bind
  10. #include <iostream>              // for operator<<, cerr, endl
  11. #include <fstream>               // for ofstream
  12. #include <random>                // for mt19937, normal_distribution
  13. #include <stdexcept>             // for runtime_error
  14.  
  15. #include <blitz/array.h>         // for Array, Range, shape, any
  16.  
  17. #include "sysv.hh"               // for sysv
  18. #include "types.hh"              // for size3, ACF, AR_coefs, Zeta, Array2D
  19. #include "voodoo.hh"             // for generate_AC_matrix
  20.  
  21. /// @file
  22. /// File with subroutines for AR model, Yule-Walker equations
  23. /// and some others.
  24.  
  25. namespace autoreg {
  26.  
  27.     template<class T>
  28.     ACF<T>
  29.     approx_acf(T alpha, T beta, T gamm, const Vec3<T>& delta, const size3& acf_size) {
  30.         ACF<T> acf(acf_size);
  31.         blitz::firstIndex t;
  32.         blitz::secondIndex x;
  33.         blitz::thirdIndex y;
  34.         acf = gamm
  35.             * blitz::exp(-alpha * (t*delta[0] + x*delta[1] + y*delta[2]))
  36. //          * blitz::cos(beta * (t*delta[0] + x*delta[1] + y*delta[2]));
  37.             * blitz::cos(beta * t * delta[0])
  38.             * blitz::cos(beta * x * delta[1])
  39.             * blitz::cos(beta * y * delta[2]);
  40.         return acf;
  41.     }
  42.  
  43.     template<class T>
  44.     T white_noise_variance(const AR_coefs<T>& ar_coefs, const ACF<T>& acf) {
  45.         return acf(0,0,0) - blitz::sum(ar_coefs * acf);
  46.     }
  47.  
  48.     template<class T>
  49.     T ACF_variance(const ACF<T>& acf) {
  50.         return acf(0,0,0);
  51.     }
  52.  
  53.     /// Удаление участков разгона из реализации.
  54.     template<class T>
  55.     Zeta<T>
  56.     trim_zeta(const Zeta<T>& zeta2, const size3& zsize) {
  57.         using blitz::Range;
  58.         using blitz::toEnd;
  59.         size3 zsize2 = zeta2.shape();
  60.         return zeta2(
  61.             Range(zsize2(0) - zsize(0), toEnd),
  62.             Range(zsize2(1) - zsize(1), toEnd),
  63.             Range(zsize2(2) - zsize(2), toEnd)
  64.         );
  65.     }
  66.  
  67.     template<class T>
  68.     bool is_stationary(AR_coefs<T>& phi) {
  69.         return !blitz::any(blitz::abs(phi) > T(1));
  70.     }
  71.  
  72.     template<class T>
  73.     AR_coefs<T>
  74.     compute_AR_coefs(const ACF<T>& acf) {
  75.         using blitz::Range;
  76.         using blitz::toEnd;
  77.         const int m = acf.numElements()-1;
  78.         Array2D<T> acm = generate_AC_matrix(acf);
  79.         //{ std::ofstream out("acm"); out << acm; }
  80.  
  81.         /**
  82.         eliminate the first equation and move the first column of the remaining
  83.         matrix to the right-hand side of the system
  84.         */
  85.         Array1D<T> rhs(m);
  86.         rhs = acm(Range(1, toEnd), 0);
  87.         //{ std::ofstream out("rhs"); out << rhs; }
  88.  
  89.         // lhs is the autocovariance matrix without first
  90.         // column and row
  91.         Array2D<T> lhs(blitz::shape(m,m));
  92.         lhs = acm(Range(1, toEnd), Range(1, toEnd));
  93.         //{ std::ofstream out("lhs"); out << lhs; }
  94.  
  95.         assert(lhs.extent(0) == m);
  96.         assert(lhs.extent(1) == m);
  97.         assert(rhs.extent(0) == m);
  98.         sysv<T>('U', m, 1, lhs.data(), m, rhs.data(), m);
  99.         AR_coefs<T> phi(acf.shape());
  100.         assert(phi.numElements() == rhs.numElements() + 1);
  101.         phi(0,0,0) = 0;
  102.         std::copy_n(rhs.data(), rhs.numElements(), phi.data()+1);
  103.         //{ std::ofstream out("ar_coefs"); out << phi; }
  104.         if (!is_stationary(phi)) {
  105.             std::cerr << "phi.shape() = " << phi.shape() << std::endl;
  106.             std::for_each(
  107.                 phi.begin(),
  108.                 phi.end(),
  109.                 [] (T val) {
  110.                     if (std::abs(val) > T(1)) {
  111.                         std::cerr << val << std::endl;
  112.                     }
  113.                 }
  114.             );
  115.             throw std::runtime_error("AR process is not stationary, i.e. |phi| > 1");
  116.         }
  117.         return phi;
  118.     }
  119.  
  120.     template<class T>
  121.     bool
  122.     isnan(T rhs) noexcept {
  123.         return std::isnan(rhs);
  124.     }
  125.  
  126.     /// Генерация белого шума по алгоритму Вихря Мерсенна и
  127.     /// преобразование его к нормальному распределению по алгоритму Бокса-Мюллера.
  128.     template<class T>
  129.     Zeta<T>
  130.     generate_white_noise(const size3& size, const T variance) {
  131.         if (variance < T(0)) {
  132.             throw std::runtime_error("variance is less than zero");
  133.         }
  134.  
  135.         // инициализация генератора
  136.         std::mt19937 generator;
  137.         #if !defined(DISABLE_RANDOM_SEED)
  138.         generator.seed(std::chrono::steady_clock::now().time_since_epoch().count());
  139.         #endif
  140.         std::normal_distribution<T> normal(T(0), std::sqrt(variance));
  141.  
  142.         // генерация и проверка
  143.         Zeta<T> eps(size);
  144.         std::generate(std::begin(eps), std::end(eps), std::bind(normal, generator));
  145.         if (std::any_of(std::begin(eps), std::end(eps), &::autoreg::isnan<T>)) {
  146.             throw std::runtime_error("white noise generator produced some NaNs");
  147.         }
  148.         return eps;
  149.     }
  150.  
  151.     /// Генерация отдельных частей реализации волновой поверхности.
  152.     template<class T>
  153.     void generate_zeta(const AR_coefs<T>& phi, Zeta<T>& zeta) {
  154.         const size3 fsize = phi.shape();
  155.         const size3 zsize = zeta.shape();
  156.         const int t1 = zsize[0];
  157.         const int x1 = zsize[1];
  158.         const int y1 = zsize[2];
  159.         for (int t=0; t<t1; t++) {
  160.             for (int x=0; x<x1; x++) {
  161.                 for (int y=0; y<y1; y++) {
  162.                     const int m1 = std::min(t+1, fsize[0]);
  163.                     const int m2 = std::min(x+1, fsize[1]);
  164.                     const int m3 = std::min(y+1, fsize[2]);
  165.                     T sum = 0;
  166.                     for (int k=0; k<m1; k++)
  167.                         for (int i=0; i<m2; i++)
  168.                             for (int j=0; j<m3; j++)
  169.                                 sum += phi(k, i, j)*zeta(t-k, x-i, y-j);
  170.                     zeta(t, x, y) += sum;
  171.                 }
  172.             }
  173.         }
  174.     }
  175.  
  176.     template<class T, int N>
  177.     T mean(const blitz::Array<T,N>& rhs) {
  178.         return blitz::sum(rhs) / rhs.numElements();
  179.     }
  180.  
  181.     template<class T, int N>
  182.     T variance(const blitz::Array<T,N>& rhs) {
  183.         assert(rhs.numElements() > 0);
  184.         const T m = mean(rhs);
  185.         return blitz::sum(blitz::pow(rhs-m, 2)) / (rhs.numElements() - 1);
  186.     }
  187.  
  188. }
  189.  
  190. #endif // AUTOREG_HH
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement