Advertisement
Guest User

Untitled

a guest
May 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.74 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. #include <vector>
  15.  
  16. #include <blitz/array.h>         // for Array, Range, shape, any
  17.  
  18. #include "sysv.hh"               // for sysv
  19. #include "types.hh"              // for size3, ACF, AR_coefs, Zeta, Array2D
  20. #include "voodoo.hh"             // for generate_AC_matrix
  21.  
  22. #include <condition_variable>
  23. #include <mutex>  
  24. #include <queue>
  25. #include <atomic>
  26. #include <thread>
  27. #include "parallel_mt.hh"
  28. #include <string>
  29. #include <omp.h>
  30.  
  31. /// @file
  32. /// File with subroutines for AR model, Yule-Walker equations
  33. /// and some others.
  34.  
  35. namespace autoreg {
  36.  
  37.     template<class T>
  38.     ACF<T>
  39.     approx_acf(T alpha, T beta, T gamm, const Vec3<T>& delta, const size3& acf_size) {
  40.         ACF<T> acf(acf_size);
  41.         blitz::firstIndex t;
  42.         blitz::secondIndex x;
  43.         blitz::thirdIndex y;
  44.         acf = gamm
  45.             * blitz::exp(-alpha * (t*delta[0] + x*delta[1] + y*delta[2]))
  46. //          * blitz::cos(beta * (t*delta[0] + x*delta[1] + y*delta[2]));
  47.             * blitz::cos(beta * t * delta[0])
  48.             * blitz::cos(beta * x * delta[1])
  49.             * blitz::cos(beta * y * delta[2]);
  50.         return acf;
  51.     }
  52.  
  53.     template<class T>
  54.     T white_noise_variance(const AR_coefs<T>& ar_coefs, const ACF<T>& acf) {
  55.         return acf(0,0,0) - blitz::sum(ar_coefs * acf);
  56.     }
  57.  
  58.     template<class T>
  59.     T ACF_variance(const ACF<T>& acf) {
  60.         return acf(0,0,0);
  61.     }
  62.  
  63.     /// Удаление участков разгона из реализации.
  64.     template<class T>
  65.     Zeta<T>
  66.     trim_zeta(const Zeta<T>& zeta2, const size3& zsize) {
  67.         using blitz::Range;
  68.         using blitz::toEnd;
  69.         size3 zsize2 = zeta2.shape();
  70.         return zeta2(
  71.             Range(zsize2(0) - zsize(0), toEnd),
  72.             Range(zsize2(1) - zsize(1), toEnd),
  73.             Range(zsize2(2) - zsize(2), toEnd)
  74.         );
  75.     }
  76.  
  77.     template<class T>
  78.     bool is_stationary(AR_coefs<T>& phi) {
  79.         return !blitz::any(blitz::abs(phi) > T(1));
  80.     }
  81.  
  82.     template<class T>
  83.     AR_coefs<T>
  84.     compute_AR_coefs(const ACF<T>& acf) {
  85.         using blitz::Range;
  86.         using blitz::toEnd;
  87.         const int m = acf.numElements()-1;
  88.         Array2D<T> acm = generate_AC_matrix(acf);
  89.         //{ std::ofstream out("acm"); out << acm; }
  90.  
  91.         /**
  92.         eliminate the first equation and move the first column of the remaining
  93.         matrix to the right-hand side of the system
  94.         */
  95.         Array1D<T> rhs(m);
  96.         rhs = acm(Range(1, toEnd), 0);
  97.         //{ std::ofstream out("rhs"); out << rhs; }
  98.  
  99.         // lhs is the autocovariance matrix without first
  100.         // column and row
  101.         Array2D<T> lhs(blitz::shape(m,m));
  102.         lhs = acm(Range(1, toEnd), Range(1, toEnd));
  103.         //{ std::ofstream out("lhs"); out << lhs; }
  104.  
  105.         assert(lhs.extent(0) == m);
  106.         assert(lhs.extent(1) == m);
  107.         assert(rhs.extent(0) == m);
  108.         sysv<T>('U', m, 1, lhs.data(), m, rhs.data(), m);
  109.         AR_coefs<T> phi(acf.shape());
  110.         assert(phi.numElements() == rhs.numElements() + 1);
  111.         phi(0,0,0) = 0;
  112.         std::copy_n(rhs.data(), rhs.numElements(), phi.data()+1);
  113.         //{ std::ofstream out("ar_coefs"); out << phi; }
  114.         if (!is_stationary(phi)) {
  115.             std::cerr << "phi.shape() = " << phi.shape() << std::endl;
  116.             std::for_each(
  117.                 phi.begin(),
  118.                 phi.end(),
  119.                 [] (T val) {
  120.                     if (std::abs(val) > T(1)) {
  121.                         std::cerr << val << std::endl;
  122.                     }
  123.                 }
  124.             );
  125.             throw std::runtime_error("AR process is not stationary, i.e. |phi| > 1");
  126.         }
  127.         return phi;
  128.     }
  129.  
  130.     template<class T>
  131.     bool
  132.     isnan(T rhs) noexcept {
  133.         return std::isnan(rhs);
  134.     }
  135.  
  136.     /// Генерация белого шума по алгоритму Вихря Мерсенна и
  137.     /// преобразование его к нормальному распределению по алгоритму Бокса-Мюллера.
  138.     template<class T>
  139.     Zeta<T>
  140.     generate_white_noise(const size3& size, const T variance) {
  141.         if (variance < T(0)) {
  142.             throw std::runtime_error("variance is less than zero");
  143.         }
  144.  
  145.         Zeta<T> eps(size);
  146.        
  147.         #pragma omp parallel
  148.         {
  149.             //создание генераторов
  150.             int tid = omp_get_thread_num();
  151.             std::string filename;
  152.             filename = "3_task/mt_";
  153.             filename += std::to_string(tid);
  154.             std::ifstream fin(filename);
  155.             mt_config conf;
  156.             fin >> conf;
  157.             parallel_mt generator(conf);
  158.             std::normal_distribution<T> normal(T(0), std::sqrt(variance));
  159.             //генерация волн
  160.             #pragma omp for
  161.             for (int i = 0; i < size[0]; i++) {
  162.                 for (int j = 0; j < size[1]; j++) {
  163.                     for (int k = 0; k < size[2]; k++) {
  164.                         eps(i,j,k) = normal(generator);
  165.                     }
  166.                 }
  167.             }
  168.         }
  169.        
  170.         //проверка
  171.         if (std::any_of(std::begin(eps), std::end(eps), &::autoreg::isnan<T>)) {
  172.             throw std::runtime_error("white noise generator produced some NaNs");
  173.         }
  174.         return eps;
  175.     }
  176.  
  177.     /// Генерация отдельных частей реализации волновой поверхности.
  178.     template<class T>
  179.     void generate_zeta(const AR_coefs<T>& phi, Zeta<T>& zeta) {
  180.         const size3 fsize = phi.shape();
  181.         const size3 zsize = zeta.shape();
  182.         std::cout << fsize << std::endl;
  183.         std::cout << zsize << std::endl;
  184.         const int t1 = zsize[0];
  185.         const int x1 = zsize[1];
  186.         const int y1 = zsize[2];
  187.         struct Task
  188.         {
  189.             int t;
  190.             int x;
  191.             int y;
  192.         };
  193.  
  194.         std::queue<Task> tasks;
  195.         std::mutex mtx;
  196.         std::condition_variable cv;
  197.         int t_step = 40;
  198.         int x_step = 8;
  199.         int y_step = 8;
  200.         int t_count = ((t1 + t_step - 1)/t_step);
  201.         int x_count = ((x1 + x_step - 1)/x_step);
  202.         int y_count = ((y1 + y_step - 1)/y_step);
  203.  
  204.         size3 matrixSize(t_count, x_count, y_count);
  205.         Array3D<int> matrix(matrixSize);
  206.  
  207.         for (int i = 0; i < matrixSize[0]; i++) {
  208.             for (int j = 0; j < matrixSize[1]; j++) {
  209.                 for (int k = 0; k < matrixSize[2]; k++) {
  210.                     int c = 3;
  211.                     if (i == 0)
  212.                         c -= 1;
  213.                     if (j == 0)
  214.                         c -= 1;
  215.                     if (k == 0)
  216.                         c -= 1;
  217.                     //change matrix params
  218.                     if (c == 3)
  219.                         c = 7;
  220.                     else if (c == 2)
  221.                         c = 3;
  222.                     matrix(i,j,k) = c;
  223.  
  224.                 }
  225.             }
  226.         }
  227.  
  228.         //create initial task
  229.         Task task;
  230.         task.t = 0;
  231.         task.x = 0;
  232.         task.y = 0;
  233.         tasks.push(task);
  234.        
  235.         std::atomic<bool> stopped{false};
  236.         #pragma omp parallel
  237.         {
  238.             std::unique_lock<std::mutex> lock{mtx};
  239.             cv.wait(lock, [&] () {
  240.                 while (!tasks.empty()) {
  241.                     Task task = tasks.front();
  242.                     tasks.pop();
  243.                     int t = task.t;
  244.                     int x = task.x;
  245.                     int y = task.y;
  246.                     lock.unlock();
  247.                    
  248.                     int t_start = t*t_step;
  249.                     int t_end = std::min((t+1)*t_step, t1);
  250.                     int x_start = x*x_step;
  251.                     int x_end = std::min((x+1)*x_step, x1);
  252.                     int y_start = y*y_step;
  253.                     int y_end = std::min((y+1)*y_step, y1);
  254.                    
  255.                     for (int t = t_start; t < t_end; t++)
  256.                         for (int x = x_start; x < x_end; x++)
  257.                             for (int y = y_start; y < y_end; y++) {
  258.                                 const int m1 = std::min(t+1, fsize[0]);
  259.                                 const int m2 = std::min(x+1, fsize[1]);
  260.                                 const int m3 = std::min(y+1, fsize[2]);
  261.                                 T sum = 0;
  262.                                 for (int k=0; k<m1; k++)
  263.                                     for (int i=0; i<m2; i++)
  264.                                         for (int j=0; j<m3; j++)
  265.                                             sum += phi(k, i, j)*zeta(t-k, x-i, y-j);
  266.                                 zeta(t, x, y) += sum;
  267.                             }
  268.                    
  269.                     std::vector<Task> newTasks;
  270.                     newTasks.push_back(Task{t+1, x, y});
  271.                     newTasks.push_back(Task{t, x+1, y});
  272.                     newTasks.push_back(Task{t, x, y+1});
  273.                     newTasks.push_back(Task{t+1, x+1, y});
  274.                     newTasks.push_back(Task{t+1, x, y+1});
  275.                     newTasks.push_back(Task{t, x+1, y+1});
  276.                     newTasks.push_back(Task{t+1, x+1, y+1});
  277.  
  278.                     if ((t==t_count-1)&&(x==x_count-1)&&(y==y_count-1)) {
  279.                         stopped = true;
  280.                         cv.notify_all();
  281.                     }
  282.  
  283.                     lock.lock();
  284.                     for (size_t tn = 0; tn < newTasks.size(); tn++) {
  285.                         if ((newTasks[tn].t<t_count)&&
  286.                                 (newTasks[tn].x<x_count)&&
  287.                                 (newTasks[tn].y<y_count)) {
  288.                             matrix(newTasks[tn].t, newTasks[tn].x, newTasks[tn].y) -= 1;
  289.                             if (matrix(newTasks[tn].t, newTasks[tn].x, newTasks[tn].y) == 0) {
  290.                                 tasks.push(newTasks[tn]);
  291.                                 cv.notify_one();
  292.                             }
  293.                         }
  294.                     }
  295.                 }
  296.                 return stopped.load();
  297.             });
  298.         }
  299.     }
  300.  
  301.     template<class T, int N>
  302.     T mean(const blitz::Array<T,N>& rhs) {
  303.         return blitz::sum(rhs) / rhs.numElements();
  304.     }
  305.  
  306.     template<class T, int N>
  307.     T variance(const blitz::Array<T,N>& rhs) {
  308.         assert(rhs.numElements() > 0);
  309.         const T m = mean(rhs);
  310.         return blitz::sum(blitz::pow(rhs-m, 2)) / (rhs.numElements() - 1);
  311.     }
  312.  
  313. }
  314.  
  315. #endif // AUTOREG_HH
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement