Advertisement
Guest User

task4.cpp

a guest
Nov 13th, 2019
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.60 KB | None | 0 0
  1. #pragma GCC optimize("Ofast")
  2. #pragma GCC target("avx")
  3. #include <bits/stdc++.h>
  4. #define watch(x) std::cout << std::setw(12) << #x << " = " << std::setw(12) << x
  5. #define watchln(x) watch(x) << std::endl
  6. typedef double real;
  7. typedef std::vector<real> Vec;
  8. typedef std::vector<Vec> Mat;
  9. const real EPS = real(1e-14);
  10.  
  11. Mat transpose(const Mat& m);
  12. real dot(const Vec& a, const Vec& b);
  13. Vec operator*(const Vec& a, const Vec& b);
  14. Vec operator-(const Vec& a, const Vec& b);
  15. Vec gauss(Mat A, Vec v);
  16. Vec operator*(const Vec& a, real coeff);
  17. Vec operator*(real coeff, const Vec& a) { return a * coeff; }
  18.  
  19. class Timer {
  20.     std::chrono::time_point<std::chrono::steady_clock> timePoint;
  21.     size_t value;
  22. public:
  23.     void start() { timePoint = std::chrono::steady_clock::now(); }
  24.     void finish() {
  25.         auto curr = std::chrono::steady_clock::now();    
  26.         auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(curr - timePoint);
  27.         value = elapsed.count();
  28.     }
  29.     size_t get() const { return value; }
  30. };
  31.  
  32. Timer timer;
  33.  
  34. struct Solver {
  35.     std::string title;
  36.     real dx, ds, delta;
  37.     Vec x, s, u, ud, v, z;
  38.     Mat K, a;
  39.     Solver(std::string title_, real coeff_, real xa, real xb, int nx, real sa, real sb, int ns)
  40.         : title(title_), dx((xb - xa) / (nx - 1)), ds((sb - sa) / (ns - 1))
  41.     {
  42.         x = make_grid(xa, xb, nx);
  43.         s = make_grid(sa, sb, ns);
  44.         K.assign(ns, Vec(nx));
  45.         for (int is = 0; is < ns; is++) {
  46.             for (int ix = 0; ix < nx; ix++) {
  47.                 K[is][ix] = func_K(x[ix], s[is]);
  48.             }
  49.         }
  50.         std::mt19937 gen(123);
  51.         std::uniform_real_distribution<real> dist(-coeff_, coeff_);
  52.         u.resize(nx);
  53.         ud.resize(nx);
  54.         for (int ix = 0; ix < nx; ix++) {
  55.             u[ix] = func_u(x[ix]);
  56.             ud[ix] = u[ix] + dist(gen);
  57.         }
  58.         v.resize(ns);
  59.         auto integrate = make_integral_coeff(nx);
  60.         delta = std::sqrt(dot((u-ud)*(u-ud), integrate) * dx);
  61.         a.assign(ns, Vec(ns, 0));
  62.         for (int is = 0; is < ns; is++) {
  63.             v[is] = dot(K[is] * u, integrate) * dx;
  64.             for (int it = 0; it < ns; it++) {
  65.                 a[is][it] = dot(K[is] * K[it], integrate) * dx * ds;
  66.                 //std::cout << a[is][it] << " ";
  67.             }
  68.             //std::cout << std::endl;
  69.         }
  70.        
  71.         auto denum = std::sqrt(dot(ud*ud, integrate) * dx);
  72.         std::cout << "Solver created, delta is " << delta << ", delta / || ud || = " << delta / denum << std::endl;
  73.         auto norm_u = std::sqrt(dot(u*u, integrate) * dx);
  74.         std::cout << "||ud||=" << denum << std::endl;
  75.         std::cout << "||u||=" << norm_u << std::endl;
  76.         std::cout << "delta/||u||=" << delta / norm_u << std::endl;
  77.     }
  78.    
  79.     void solve(real alpha) {
  80.         for (int i = 0; i < (int)a.size(); i++) { a[i][i] += alpha; }
  81.         const auto ids2 = 1 / (ds * ds);
  82.         for (int i = 1; i+1 < (int)a.size(); i++) { a[i][i] += 2 * alpha * ids2; };
  83.         a[0][0] += alpha * ids2;
  84.         a.back().back() += alpha * ids2;
  85.         for (int i = 1; i < (int)a.size(); i++) {
  86.             a[i-1][i] -= alpha * ids2;
  87.             a[i][i-1] -= alpha * ids2;
  88.         }
  89.         z = gauss(a, v);
  90.         for (int i = 1; i < (int)a.size(); i++) {
  91.             a[i-1][i] += alpha * ids2;
  92.             a[i][i-1] += alpha * ids2;
  93.         }
  94.         a[0][0] -= alpha * ids2;
  95.         a.back().back() -= alpha * ids2;
  96.         for (int i = 1; i+1 < (int)a.size(); i++) { a[i][i] -= 2 * alpha * ids2; };
  97.         for (int i = 0; i < (int)a.size(); i++) { a[i][i] -= alpha; }
  98.     }
  99.    
  100.     real diff() {
  101.         const int nx = (int)x.size(), ns = (int)s.size();
  102.         auto int_x = make_integral_coeff(nx);
  103.         auto int_s = make_integral_coeff(ns);
  104.         Vec tmp(nx);
  105.         K = transpose(K);
  106.         for (int ix = 0; ix < nx; ix++) {
  107.             tmp[ix] = dot(K[ix] * z, int_s) * ds - ud[ix];
  108.         }
  109.         K = transpose(K);
  110.         return std::sqrt(dot(tmp * tmp, int_x) * dx) - delta;
  111.     }
  112.    
  113.     void dump_u() {
  114.         auto file = fopen((title + "_u.txt").c_str(), "wt");
  115.         for (int i = 0; i < (int)x.size(); i++) {
  116.             fprintf(file, "%f %f\n", (double)x[i], (double)u[i]);
  117.         }
  118.         fclose(file);
  119.         std::cout << "File " << (title + "_u.txt") << " is created" << std::endl;
  120.     }
  121.    
  122.     void dump_ud() {
  123.         auto file = fopen((title + "_ud.txt").c_str(), "wt");
  124.         for (int i = 0; i < (int)x.size(); i++) {
  125.             fprintf(file, "%f %f\n", (double)x[i], (double)ud[i]);
  126.         }
  127.         fclose(file);
  128.         std::cout << "File " << (title + "_ud.txt") << " is created" << std::endl;
  129.     }
  130.    
  131.     void dump_z() {
  132.         auto file = fopen((title + "_z.txt").c_str(), "wt");
  133.         for (int i = 0; i < (int)s.size(); i++) {
  134.             fprintf(file, "%f %f\n", (double)s[i], (double)z[i]);
  135.         }
  136.         fclose(file);
  137.         std::cout << "File " << (title + "_z.txt") << " is created" << std::endl;
  138.     }
  139.    
  140.     void dump_ro() {
  141.         auto file = fopen((title + "_ro.txt").c_str(), "wt");
  142.         for (real alpha = 1e-10; alpha < 1; alpha*=10) {
  143.             solve(alpha);
  144.             fprintf(file, "%f %f\n", alpha, diff());
  145.         }
  146.         fclose(file);
  147.         std::cout << "File " << (title + "_ro.txt") << " is created" << std::endl;
  148.     }
  149.    
  150.     Vec make_grid(real a, real b, int n) {
  151.         Vec res(n);
  152.         real step = (b - a) / (n - 1);
  153.         res[0] = a;
  154.         for (int i = 1; i < n; i++) res[i] = res[i-1] + step;
  155.         assert(std::abs(b-res.back()) < EPS * std::max(real(1), std::abs(b)));
  156.         return res;
  157.     }
  158.    
  159.     Vec make_integral_coeff(int n) {
  160.         Vec res(n, 1);
  161.         res.front() /= 2;
  162.         res.back()  /= 2;
  163.         return res;
  164.     }
  165.    
  166.     real func_K(real x, real s) {
  167.         return 1/(1+100*(x-s)*(x-s));
  168.     }
  169.  
  170.     real func_u(real x) {
  171.         return 0.01 * (10 * (1-x) * (std::atan(10*(1-x)) + std::atan(10*x)) - 0.5 * std::log((1+100*(1-x)*(1-x))/(1+100*x*x)));
  172.     }
  173. };
  174.  
  175. int main() {
  176.     timer.start();
  177.     Solver solver("task4", 0.02, -1, 1, 501, 0, 1, 501);
  178.     real L = 1e-6, R = 1;
  179.     for (int iter = 0; iter < 100; iter++) {
  180.         real m = (L + R) / 2;
  181.         solver.solve(m);
  182.         if (solver.diff() >= 0) R = m;
  183.         else L = m;
  184.         if (std::abs(solver.diff()) < 0.001 * solver.delta) break;
  185.     }
  186.     real alpha = (L+R) / 2;
  187.     std::cout << "Opt alpha = " << alpha << std::endl;
  188.     solver.solve(alpha);
  189.     std::cout << "Diff is " << solver.diff() << std::endl;
  190.     solver.dump_u();
  191.     solver.dump_ud();
  192.     solver.dump_z();
  193.     solver.dump_ro();
  194.     timer.finish();
  195.     std::cerr << "Done. Runtime is " << timer.get() << " ms" << std::endl;
  196.     return 0;
  197. }
  198.  
  199. real dot(const Vec& a, const Vec& b) {
  200.     assert(a.size() == b.size());
  201.     return std::inner_product(a.begin(), a.end(), b.begin(), real(0));
  202. }
  203.  
  204. Vec operator*(const Vec& a, real coeff) {
  205.     Vec res = a;
  206.     for (auto &it : res) it *= coeff;
  207.     return res;
  208. }
  209.  
  210. Vec operator*(const Vec& a, const Vec& b) {
  211.     assert(a.size() == b.size());
  212.     Vec res(a.size());
  213.     for (int i = 0; i < (int)a.size(); i++) {
  214.         res[i] = a[i] * b[i];
  215.     }
  216.     return res;
  217. }
  218.  
  219. Vec operator-(const Vec& a, const Vec& b) {
  220.     assert(a.size() == b.size());
  221.     Vec res(a.size());
  222.     for (int i = 0; i < (int)a.size(); i++) {
  223.         res[i] = a[i] - b[i];
  224.     }
  225.     return res;
  226. }
  227.  
  228. Mat transpose(const Mat& m) {
  229.     Mat res(m[0].size(), Vec(m.size()));
  230.     for (int i = 0; i < (int)res.size(); i++) {
  231.         for (int j = 0; j < (int)res[i].size(); j++) {
  232.             res[i][j] = m[j][i];
  233.         }
  234.     }
  235.     return res;
  236. }
  237.  
  238. Vec gauss(Mat A, Vec v) {
  239.     int nRows = (int)A.size(), nCols = (int)A[0].size();
  240.     assert(nRows == nCols);
  241.     for (int col = 0, row = 0; col < nCols; col++,row++) {
  242.         int best = row;
  243.         for (int r = row; r < nRows; r++) {
  244.             if (std::abs(A[r][col]) > std::abs(A[best][col])) {
  245.                 best = r;
  246.             }
  247.         }
  248.         std::swap(A[row], A[best]);
  249.         std::swap(v[row], v[best]);
  250.         //assert(std::abs(A[row][col]) > 1e-9);
  251.         for (int r = 0; r < nRows; r++) {
  252.             if (r == row) continue;
  253.             const real coeff = -A[r][col] / A[row][col];
  254.             for (int c = col; c < nCols; c++) {
  255.                 A[r][c] += A[row][c] * coeff;
  256.             }
  257.             v[r] += v[row] * coeff;
  258.         }
  259.     }
  260.     Vec answ(nCols);
  261.     for (int i = 0; i < nCols; i++) {
  262.         answ[i] = v[i] / A[i][i];
  263.     }
  264.     return answ;
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement