Want more features on Pastebin? Sign Up, it's FREE!
Guest

Programming Praxis 10 May 2013

By: a guest on May 10th, 2013  |  syntax: C++  |  size: 3.89 KB  |  views: 14  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. Programming Praxis 2013-05-10
  3. see
  4. http://programmingpraxis.com/2013/05/10/mindcipher/#comments
  5. */
  6.  
  7. #include <iostream>
  8. #include <vector>
  9. #include <stdexcept>
  10.  
  11. //some doodads I'll need.
  12. #include <boost/numeric/ublas/matrix.hpp>
  13.  
  14.  
  15. /*
  16.         I'll start with #1.
  17.            
  18.         1: Coin Flip: On Monday, you flip a coin all day. You start flipping it until you see the pattern Head, Tail, Head. You record the number of flips required to reach this pattern, and start flipping again (and counting up from 1 again) until you see that pattern again, you record the second number, and start again. At the end of the day you average all of the numbers you’ve recorded. On Tuesday you do the EXACT same thing except you flip until you see the pattern Head, Tail, Tail.
  19.  
  20.     Will Monday’s number be higher than Tuesday’s, equal to Tuesday’s, or lower than Tuesday’s?
  21.  
  22.         Obviously the answer is 'I can't possibly know in advance'. But this is probably supposed to be about long-term behaviour, so
  23.         I'll start by getting the means I want.
  24.  
  25.         The Markov state "the last three flips" can be represented by a 3-bit binary number, which is how I'll proceed.
  26. */
  27.  
  28. typedef boost::numeric::ublas::matrix<double,boost::numeric::ublas::row_major,std::vector<double>> matrix_t;
  29. typedef boost::numeric::ublas::vector<double,std::vector<double>> vector_t;
  30.  
  31. //define some row ops
  32. matrix_t& swap_rows(matrix_t::size_type i,matrix_t::size_type j, matrix_t& m){
  33.         if(i == j) return m;
  34.         for(matrix_t::size_type k = 0; k < m.size2() ; ++k){
  35.                 double temp = m(i,k);
  36.                 m(i,k) = m(j,k);
  37.                 m(j,k) = temp;
  38.         }
  39.         return m;
  40. }
  41.  
  42. matrix_t& scale_row(matrix_t::size_type i,double scale,matrix_t& m){
  43.         for(matrix_t::size_type k = 0; k < m.size2() ; ++k){
  44.                 m(i,k) *= scale;
  45.         }
  46.         return m;
  47. }
  48.  
  49. matrix_t& addmultiple_rows(matrix_t::size_type i,matrix_t::size_type j,double scale,matrix_t& m){
  50.         for(matrix_t::size_type k = 0 ; k < m.size2() ; ++k){
  51.                 m(i,k) += scale*m(j,k);
  52.         }
  53.         return m;
  54. }
  55.  
  56. //Perform row reduction.
  57. void row_reduce(double e,matrix_t& m,vector_t& v){
  58.         typedef matrix_t::size_type st;
  59.  
  60.         st row = 0;
  61.         st pivot = 0;
  62.         double temp;
  63.         while(pivot < m.size2()){
  64.                 //find the biggest element in the current column.
  65.                 st max = row;
  66.                 for(st i = row+1 ; i < m.size1() ; ++i)
  67.                         if(abs(m(i,pivot)) > abs(m(max,pivot))) max = i;
  68.                 swap_rows(row,max,m);
  69.                 //also swap in the vector
  70.                 temp = v(row);
  71.                 v(row) = v(max);
  72.                 v(max) = temp;
  73.                 //check it's worth operating on.
  74.                 if(abs(m(row,pivot)) > e){
  75.                         //scale things.
  76.                         v(row) *= 1.0/m(row,pivot);
  77.                         scale_row(row,1.0/m(row,pivot),m);
  78.                         //clean out
  79.                         for(st i = 0 ; i < m.size1() ; ++i){
  80.                                 if(i != row){
  81.                                         double scale = -m(i,pivot);
  82.                                         v(i) += scale * v(row);
  83.                                         addmultiple_rows(i,row,scale,m);
  84.                                 }
  85.                         }
  86.                         ++row;
  87.                 }
  88.                 ++pivot;
  89.         }      
  90. }
  91.  
  92. double mean_time(unsigned char target_state){
  93.         if(target_state>8) throw std::invalid_argument("mean_time parameter not in range.");
  94.  
  95.         //Build the bits I need for production of mean hitting times.
  96.         //Hitting {target_state}.
  97.         matrix_t mean_matrix(9,9,0.0);
  98.         for(int i = 0 ; i < 8 ; ++i){
  99.                 //set up the ith row...
  100.                 if(i == target_state) mean_matrix(i,i) = 1.0;
  101.                 else{
  102.                         int u = (i << 1) & 7;
  103.                         int v = u | 1;
  104.                         mean_matrix(i,u) += 0.5;
  105.                         mean_matrix(i,v) += 0.5;
  106.                         mean_matrix(i,i) += -1.0;
  107.                 }
  108.                 //set up the start row while I'm here.
  109.                 mean_matrix(8,i) = 0.125;
  110.         }
  111.         //finish the start row.
  112.         mean_matrix(8,8) = -1.0;
  113.        
  114.         vector_t rhs(9,-1.0);
  115.         rhs(target_state) = 0.0;
  116.         rhs(8) = -3.0;  //Essentially the first step is three.
  117.  
  118.         //triangularise mean_matrix.
  119.         row_reduce(1e-10,mean_matrix,rhs);
  120.  
  121.         //The matrices are all invertible here, so there's no need to perform the next step.
  122.         return rhs(8);
  123. }
  124.  
  125. int main(){
  126.         for(int i = 0; i < 8 ; ++i)
  127.                 std::cout << "Mean time to hit " << ((i&4)?"H":"T") << ((i&2)?"H":"T") << ((i&1)?"H":"T") << " = "<< mean_time(i) << std::endl;
  128.         std::cin.get();
  129.         return 0;
  130. }
clone this paste RAW Paste Data