Advertisement
JoelSjogren

collatz24/main.cpp

May 15th, 2018
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.08 KB | None | 0 0
  1. #include <utility>
  2. #include <map>
  3. #include <ostream>
  4. #include <iostream>
  5. #include <iomanip>
  6. #include <vector>
  7. //#include <gmp.h>
  8. #include <boost/multiprecision/cpp_dec_float.hpp>
  9.  
  10. typedef long long num;
  11.  
  12. //typedef double approx;
  13. //typedef long double approx;
  14. typedef boost::multiprecision::cpp_dec_float_50 approx;
  15.  
  16. num gcd(num a, num b) {
  17.   while (a) {
  18.     // a, b = b%a, a
  19.     num tmp = b%a; b = a; a = tmp;
  20.   }
  21.   return b;
  22. }
  23.  
  24. template<typename T>
  25. class ord {
  26.   friend bool operator==(T const &a, T const &b) { return cmp(a, b) == 0; }
  27.   friend bool operator!=(T const &a, T const &b) { return cmp(a, b) != 0; }
  28.   friend bool operator<(T const &a, T const &b) { return  cmp(a, b) < 0; }
  29.   friend bool operator<=(T const &a, T const &b) { return cmp(a, b) <= 0; }
  30.   friend bool operator>(T const &a, T const &b) { return  cmp(a, b) > 0; }
  31.   friend bool operator>=(T const &a, T const &b) { return cmp(a, b) >= 0; }
  32. };
  33.  
  34. struct roll : ord<roll> {
  35.   num r, s;
  36.  
  37.   constexpr roll(num r_, num s_) : r(r_), s(s_) {}
  38.  
  39.   static const roll zero;
  40.   static const roll one;
  41.   static const roll inf;  // don't use in algebra
  42.  
  43.   friend roll operator*(const roll& i, const roll& j) {
  44.     return { i.r + i.s*j.r , i.s*j.s };
  45.   }
  46.  
  47.   friend roll operator/(const roll& i, const roll& j) {
  48.     return { (i.r-j.r) / j.s , i.s / j.s };
  49.   }
  50.  
  51.   static roll lcm(roll i, roll j) {
  52.     if (i == inf or j == inf) return inf;
  53.     num g = gcd(i.s, j.s);
  54.     // if (g == 0) return i == j ? i : inf;  // new case
  55.     if ((i.r-j.r) % g) return inf;
  56.     num l = i.s*j.s/g;
  57.     while (i.r != j.r) {
  58.       if (i.r < j.r) i.r += i.s * ((j.r-i.r+i.s-1)/i.s);
  59.       if (i.r > j.r) j.r += j.s * ((i.r-j.r+j.s-1)/j.s);
  60.     }
  61.     return { i.r , l };
  62.   }
  63.  
  64.   friend std::ostream& operator<<(std::ostream& os, const roll& i) {
  65.     return os << i.r << "(" << i.s << ")";
  66.   }
  67.  
  68.   friend int cmp(const roll& i, const roll& j) {
  69.     if (i.s < j.s or (i.s == j.s and i.r < j.r)) return -1;
  70.     if (i.s == j.s and i.r == j.r) return 0;
  71.     return 1;
  72.   }
  73.  
  74. };
  75.  
  76. constexpr const roll roll::zero = { 0 , 0 };
  77. constexpr const roll roll::one = { 0 , 1 };
  78. constexpr const roll roll::inf = { 0 , -1 };
  79.  
  80. struct pix : ord<pix> {
  81.   roll i, j;
  82.  
  83.   constexpr pix(roll i_, roll j_) : i(i_), j(j_) {}
  84.  
  85.   static const pix zero;
  86.   static const pix one;
  87.  
  88.   friend pix operator*(pix a, pix b) {
  89.     if (a == zero or b == zero) return zero;
  90.     roll l = roll::lcm(a.j, b.i);
  91.     if (l == roll::inf) return zero;
  92.     return { a.i * (l/a.j) , b.j * (l/b.i) };
  93.   }
  94.  
  95.   static pix vert(roll i) {
  96.     return { i , roll::zero };
  97.   }
  98.  
  99.   static pix horz(roll j) {
  100.     return { roll::zero , j };
  101.   }
  102.  
  103.   friend std::ostream& operator<<(std::ostream& os, const pix& a) {
  104.     return os << a.i << a.j;
  105.   }
  106.  
  107.   friend int cmp(const pix& a, const pix& b) {
  108.     if (a.i < b.i or (a.i == b.i and a.j < b.j)) return -1;
  109.     if (a.i == b.i and a.j == b.j) return 0;
  110.     return 1;
  111.   }
  112. };
  113.  
  114. constexpr const pix pix::zero = { roll::inf , roll::inf };
  115. constexpr const pix pix::one = { roll::one , roll::one };
  116.  
  117. struct mat {
  118.   std::multimap<pix, approx> m;
  119.  
  120.   mat() {}
  121.   mat(std::multimap<pix, approx> m_) : m(m_) {}
  122.   mat(approx x) : m{ {pix::one, x} } {}
  123.  
  124.   static mat zero() { return mat(); }
  125.   static mat one() { return mat({ {pix::one, 1.0} }); }
  126.   static mat single(pix a) {
  127.     mat X;
  128.     X.m.emplace(a, 1.0);
  129.     X.compress();
  130.     return X;
  131.   }
  132.  
  133.   friend mat operator+(const mat& X, const mat& Y) {
  134.     mat Z;
  135.     Z.m.insert(X.m.begin(), X.m.end());
  136.     Z.m.insert(Y.m.begin(), Y.m.end());
  137.     Z.compress();
  138.     return Z;
  139.   }
  140.  
  141.   friend mat operator*(const mat& X, const mat& Y) {
  142.     //std::cout << "input: " << X.m.size() << "x" << Y.m.size() << std::endl;
  143.     mat Z;
  144.     for (auto i = X.m.begin(); i != X.m.end(); i++)
  145.       for (auto j = Y.m.begin(); j != Y.m.end(); j++)
  146.         Z.m.emplace(i->first * j->first, i->second * j->second);
  147.     //std::cout << "before: {" << Z.m.size() << "} " << Z << std::endl;
  148.     Z.compress();
  149.     //std::cout << "after: {" << Z.m.size() << "} " << Z << std::endl;
  150.     return Z;
  151.   }
  152.  
  153.   static mat pow(mat X, num n) {
  154.     mat Y = one();
  155.     for ( ; n; n /= 2) {
  156.       if (n % 2) Y = X*Y;
  157.       if (n != 1) X = X*X;
  158.     }
  159.     return Y;
  160.   }
  161.  
  162.   approx technical() {
  163.     approx s = 0.0;
  164.     for (auto i = m.begin(); i != m.end(); i++)
  165.       s += i->second;
  166.     return s;
  167.   }
  168.  
  169.   approx quadranc1() {
  170.     approx s = 0.0;
  171.     for (auto i = m.begin(); i != m.end(); i++) {
  172.       s += i->second / i->first.j.s;
  173.     }
  174.     return s;
  175.   }
  176.  
  177.   approx inner(roll u, roll v) {
  178.     mat uX = (single(pix::horz(u)) * (*this));
  179.     approx uXv = 0.0;
  180.     for (auto i = uX.m.begin(); i != uX.m.end(); i++) {
  181.       num lcm = roll::lcm(i->first.j, v).s;
  182.       if (lcm != -1)
  183.         uXv += i->second / lcm;
  184.     }
  185.     return uXv;
  186.   }
  187.  
  188.   friend std::ostream& operator<<(std::ostream& os, const mat& X) {
  189.     if (X.m.empty()) return os << "0";
  190.     for (auto i = X.m.begin(); i != X.m.end(); i++)
  191.       os << i->second << "[" << i->first << "]";
  192.     return os;
  193.   }
  194.  
  195. private:
  196.   void compress() {
  197.     std::multimap<pix, approx> w;
  198.     for (auto i = m.begin(); i != m.end(); ) {
  199.       std::pair<pix, approx> p = {pix::zero, 0};
  200.       for (p.first = i->first; p.first == i->first; i++)
  201.         p.second += i->second;
  202.       if (p.first != pix::zero and p.second != 0)
  203.         w.insert(p);
  204.     }
  205.     m = w;
  206.   }
  207. };
  208.  
  209. mat A = mat::single({{2 , 2} , {1 , 1}});
  210. mat B = mat::single({{1 , 2} , {4 , 6}});
  211.  
  212. mat C_plain = A + B;
  213.  
  214. mat C(approx p, approx q) { return p*A + q*B; }
  215.  
  216. void quadranc1_experiment(const approx p, const approx q) {
  217.   mat X = mat::one();
  218.   approx t = 0;
  219.   std::cout << std::setprecision(30);
  220.   for (int i = 0; i < 40; i++) {
  221.     std::cout << std::setw(3) << i << ", "
  222.               << std::setw(30) << X.technical() << ", "
  223.               << (X.quadranc1() / t) << std::endl;
  224.     t = X.quadranc1();
  225.     X = X*C(p,q);
  226.   }
  227. }
  228.  
  229. void inner_experiment(const roll u, const roll v) {
  230.   mat X = mat::one();
  231.   std::cout << u << v << std::endl;
  232.   for (int i = 0; i < 25; i++) {
  233.     if (i >= 20)
  234.       std::cout << std::setw(3) << i << ", "
  235.                 << std::setprecision(3) << std::scientific
  236.                 << X.technical() << ", "
  237.                 << std::setprecision(30) << std::fixed
  238.                 << X.inner(u, v) << std::endl;
  239.     X = X*C(.75,1);  // max eig = 1.0
  240.   }
  241. }
  242.  
  243. struct rat {
  244.   num a, b;
  245.   rat (num a_, num b_) : a(a_), b(b_) {}
  246.   rat (num a_) : a(a_), b(1) {}
  247.   friend rat operator+(rat x, rat y) { return { x.a*y.b+x.b*y.a , x.b*y.b }; }
  248.   friend rat operator*(rat x, rat y) { return { x.a*y.a , x.b*y.b }; }
  249.   friend rat operator/(rat x, rat y) { return { x.a*y.b , x.b*y.a }; }
  250.   void compress() { num g = gcd(a, b); a /= g; b /= g; }
  251.   friend std::ostream& operator<<(std::ostream& os, const rat& x) {
  252.     return os << x.a << "/" << x.b;
  253.   }
  254. };
  255.  
  256. rat sb(approx x, approx tol) {
  257.   if (x > 1) return sb(1/x, tol);
  258.   if (x < tol) return rat(0, 1);
  259.   return 1 / (rat(num(1/x), 1) + sb(1/x-num(1/x), tol));
  260. }
  261.  
  262. void inner_matrix(num u_max, num v_max) {
  263.   for (num u_num = 1; u_num <= u_max; u_num++) {
  264.     for (num v_num = 1; v_num <= v_max; v_num++) {
  265.       roll u = { 0 , u_num };
  266.       roll v = { 0 , v_num };
  267.       mat X = mat::one();
  268.       int i = 0;
  269.       approx t = -1;
  270.       do {
  271.         t = X.inner(u, v);
  272.         X = X*C(.75,1);
  273.         i++;
  274.       } while (i < 20 or (i < 30 and t > 1e-3 and
  275.                           abs(X.inner(u, v)-t) > 1e-8));
  276.       std::cout << std::setfill(' ')
  277.                 << "u:(0," << std::setw(2) << u_num
  278.                 << "),v:(0," << std::setw(2) << v_num << ") "
  279.                 << std::setprecision(3) << std::scientific
  280.                 << abs(X.inner(u, v)-t);
  281.       rat r = sb(X.inner(u, v), 1e-4);
  282.       r.compress();
  283.       if (r.b > 100000)
  284.         r = 0;
  285.       std::cout << " " << r << std::endl;
  286.     }
  287.   }
  288. }
  289.  
  290. void inner_left_triangle(num u_max) {
  291.   for (num u_num = 1; u_num <= u_max; u_num++) {
  292.     for (num u_shift = 1; u_shift <= u_num; u_shift++) {
  293.       roll u = { u_shift , u_num };
  294.       roll v = roll::one;
  295.       mat X = mat::one();
  296.       int i = 0;
  297.       approx t = -1;
  298.       do {
  299.         t = X.inner(u, v);
  300.         X = X*C(.75,1);
  301.         i++;
  302.       } while (i < 20 or (i < 30 and t > 1e-3 and
  303.                           abs(X.inner(u, v)-t) > 1e-8));
  304.       std::cout << std::setfill(' ')
  305.                 << u << " "
  306.                 << std::setprecision(3) << std::scientific
  307.                 << abs(X.inner(u, v)-t);
  308.       rat r = sb(X.inner(u, v), 1e-4);
  309.       r.compress();
  310.       if (r.b > 100000)
  311.         r = 0;
  312.       std::cout << " " << r << std::endl;
  313.     }
  314.   }
  315. }
  316.  
  317. void inner_top_triangle(num v_max) {
  318.   for (num v_num = 1; v_num <= v_max; v_num++) {
  319.     for (num v_shift = 1; v_shift <= v_num; v_shift++) {
  320.       roll u = roll::one;
  321.       roll v = { v_shift , v_num };
  322.       mat X = mat::one();
  323.       int i = 0;
  324.       approx t = -1;
  325.       do {
  326.         t = X.inner(u, v);
  327.         X = X*C(.75,1);
  328.         i++;
  329.       } while (i < 20 or (i < 30 and t > 1e-3 and
  330.                           abs(X.inner(u, v)-t) > 1e-8));
  331.       std::cout << std::setfill(' ')
  332.                 << v << " "
  333.                 << std::setprecision(3) << std::scientific
  334.                 << abs(X.inner(u, v)-t);
  335.       rat r = sb(X.inner(u, v), 1e-4);
  336.       r.compress();
  337.       if (r.b > 100000)
  338.         r = 0;
  339.       std::cout << " " << r << std::endl;
  340.     }
  341.   }
  342. }
  343.  
  344. void inner_left_zero(num u_max) {
  345.   for (num u_num = 1; u_num <= u_max; u_num++) {
  346.     {
  347.       num u_shift = 0;
  348.       roll u = { u_shift , u_num };
  349.       roll v = roll::one;
  350.       mat X = mat::one();
  351.       int i = 0;
  352.       approx t = -1;
  353.       do {
  354.         t = X.inner(u, v);
  355.         X = X*C(.75,1);
  356.         i++;
  357.       } while (i < 20 or (i < 30 and t > 1e-3 and
  358.                           abs(X.inner(u, v)-t) > 1e-8));
  359.       std::cout << std::setfill(' ')
  360.                 << u << " "
  361.                 << std::setprecision(3) << std::scientific
  362.                 << abs(X.inner(u, v)-t);
  363.       rat r = sb(X.inner(u, v), 1e-4);
  364.       r.compress();
  365.       if (r.b > 100000)
  366.         r = 0;
  367.       std::cout << " " << r << std::endl;
  368.     }
  369.   }
  370. }
  371.  
  372. void inner_top_zero(num v_max) {
  373.   {
  374.     for (num v_num = 1; v_num <= v_max; v_num++) {
  375.       roll u = roll::one;
  376.       num v_shift = 0;
  377.       roll v = { v_shift , v_num };
  378.       mat X = mat::one();
  379.       int i = 0;
  380.       approx t = -1;
  381.       do {
  382.         t = X.inner(u, v);
  383.         X = X*C(.75,1);
  384.         i++;
  385.       } while (i < 20 or (i < 30 and t > 1e-3 and
  386.                           abs(X.inner(u, v)-t) > 1e-8));
  387.       std::cout << std::setfill(' ')
  388.                 << v << " "
  389.                 << std::setprecision(3) << std::scientific
  390.                 << abs(X.inner(u, v)-t);
  391.       rat r = sb(X.inner(u, v), 1e-4);
  392.       r.compress();
  393.       if (r.b > 100000)
  394.         r = 0;
  395.       std::cout << " " << r << std::endl;
  396.     }
  397.   }
  398. }
  399.  
  400. void quadranc1_2nd_eig() {
  401.   const approx p = approx(3)/4;
  402.   const approx q = 1;
  403.   mat X = mat::one();
  404.   approx t = 0;
  405.   std::cout << std::setprecision(30);
  406.   for (int i = 0; i < 20; i++) {
  407.     approx t2 = X.quadranc1() - approx(14)/15;
  408.     std::cout << std::setw(3) << i << ", "
  409.               << std::setprecision(3) << std::scientific
  410.               << X.technical() << ", "
  411.               << std::setprecision(30) << std::fixed
  412.               << (t2 / t) << std::endl;
  413.     t = t2;
  414.     X = X*C(p,q);
  415.   }
  416. }
  417.  
  418. void fine_experiment() {
  419.   const approx p = approx(3)/4;
  420.   const approx q = 1;
  421.   mat X = mat::single(pix::horz(roll::one));
  422.   std::cout << std::setprecision(30);
  423.   for (int i = 0; i < 40; i++) {
  424.  
  425.     approx t = 0;
  426.     for (auto j = X.m.begin(); j != X.m.end(); j++)
  427.       if (j->first.j.r == 1)
  428.         t += j->second;
  429.    
  430.     std::cout << std::setw(3) << i << ", "
  431.               << std::setprecision(3) << std::scientific
  432.               << X.technical() << ", "
  433.               << std::setprecision(30) << std::fixed
  434.               << t << std::endl;
  435.     X = X*C(p,q);
  436.   }
  437. }
  438.  
  439. void fine_experiment_special() {
  440.   std::vector<std::pair<num, approx>> oui = { { 1 , 1.0 } };
  441.  
  442.   for (num i = 0; i < 60; i++) {
  443.     std::vector<std::pair<num, approx>> non;
  444.     for (auto j = oui.begin(); j != oui.end(); j++) {
  445.       if (j->first % 6 == 4)
  446.         non.push_back({ (j->first-1)/3 , j->second });
  447.       non.push_back({ j->first*2 , j->second*3/4 });
  448.     }
  449.     oui = non;
  450.     approx t = 0;
  451.     for (auto j = oui.begin(); j != oui.end(); j++)
  452.       t += j->second;
  453.     std::cout << i << " " << std::setprecision(10) << t << std::endl;
  454.   }
  455. }
  456.  
  457.  
  458. int main() {
  459.  
  460.   // quadranc1_experiment(.75,1);  // <-- you will want to vary this
  461.  
  462.   /*
  463.   for (int m = 1; m < 8; m++) {
  464.     for (int n = 1; n < 8; n++) {
  465.       inner_experiment({ 0 , m }, { 0 , n });
  466.     }
  467.     }*/
  468.  
  469.   // inner_left_matrix(30);
  470.   // inner_left_triangle(50);
  471.   // inner_left_zero(100);
  472.  
  473.   // inner_top_triangle(30);
  474.   // inner_top_zero(100);
  475.  
  476.   // quadranc1_2nd_eig();  // -1/4 pure
  477.   // fine_experiment();
  478.   fine_experiment_special();  // 27/22?
  479.  
  480. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement