CFTPについてのまとめとサンプルコード

# CFTPとは
coupling from the past　の略。
無限の攪拌時間を要することなく
目的の分布に厳密に従うサンプリングを行うことができる。

詳しいことは以下のリンクを見るべし。


#リンク
[CFTPの説明（日本語）](https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwjIxKmP3uXXAhULbrwKHUT0C24QFggrMAA&url=http%3A%2F%2Fwww.simplex.t.u-tokyo.ac.jp%2F~imahori%2Fsuperrobust%2Fworkshop%2Fmatsui.pdf&usg=AOvVaw0dgSh5fC8ELj-AfC8Cr6oU)
[CFTPに関する書籍(日本語)「やさしいmcmc入門」](www.amazon.co.jp/やさしいMCMC入門-有限マルコフ連鎖とアルゴリズム-Olle-H¨aggstr¨om/dp/4320113144/ref=sr_1_1)
[David Bruce Wilson氏の論文全て](http://dbwilson.com)
[CFTPに関する論文](http://www.uoregon.edu/~dlevin/MARKOV/markovmixing.pdf)
[RCFTPに関する論文](http://arxiv.org/pdf/math.PR/9910050.pdf)
[David Bruce Wilson氏のRCFTPを用いたコード](http://dbwilson.com/strauss/)

#サンプルコード
状態空間S
![image.png](https://qiita-image-store.s3.amazonaws.com/0/188178/1e95d6e9-31c4-8ebc-254f-a4656750b547.png)

推移関数P
![image.png](https://qiita-image-store.s3.amazonaws.com/0/188178/32d3e0aa-6751-2ee6-e003-c7fa9970c323.png)

をもつマルコフ連鎖は明らかに次の定常分布を持つ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/188178/84452ffc-2210-8d02-c5b0-635a17e6690c.png)


```c:simple_cftp1.c



#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
using namespace std;


const int STATE_NUM = 3 ;
//更新
int move(int state, int  &r){
    switch(state){
        case 0:
            if(r) return 0;
            else return 1;
            break;
            
        case STATE_NUM - 1:
            if(r) return state - 1;
            else return state;
            break;
            
        default:
            if(r) return state - 1;
            else return state + 1;
    }
}

int q(){
    //更新関数に食わせる確率変数は使い回す必要があるので保存しておく
    vector<int> r_list;
    
    int state1 = 0;
    int state2 = 1;
    int state3 = 2;

    int n = 0;
    while(state1 != state2 || state1 != state3){
        state1 = 0;
        state2 = 1;
        state3 = 2;
        int size = r_list.size();
        for(int i = 0; i < pow(2,n) - size ; i++){
            r_list.push_back(rand() % 2);
        }
        n++;
        
        
        for(int i = r_list.size() - 1; i >= 0; i--){
            
            state1 = move(state1, r_list[i]);
            state2 = move(state2, r_list[i]);
            state3 = move(state3, r_list[i]);

            
        }
    }
    return state1;
    

}

void sample(int n){
    int samples[STATE_NUM] = {0};
    
    for(int i = 0; i < n; i++){
        samples[q()]++;
    }
    for(int i = 0; i < STATE_NUM; i++){
        cout << (double)samples[i] / n << "\n";
    }
    
}

int main(){
    srand((unsigned)time(NULL));
    sample(200);
    
}



```
結果

>
0.325
0.37
0.305

既知の定常分布と結果を比較すると
正しくサンプリングされていることが分かる

#単調CFTP、挟み撃ち法のサンプルコード
状態空間と推移行列は上記のサンプルと同じ。

このマルコフ連鎖は単調なので挟み撃ち法が使える。
つまり、一番上のs1を初期状態とするstate1と一番下のs3を初期状態とするstate2を用意し
state1とstate2が一致しことを終了条件にすれば良い。

```c:sandwich_cftp.c


#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
using namespace std;


const int STATE_NUM = 3 ;
//更新
int move(int state, int  &r){
    switch(state){
        case 0:
            if(r) return 0;
            else return 1;
            break;
            
        case STATE_NUM - 1:
            if(r) return state - 1;
            else return state;
            break;
            
        default:
            if(r) return state - 1;
            else return state + 1;
    }
}

int q(){
    //更新関数に食わせる確率変数は使い回す必要があるので保存しておく
    vector<int> r_list;
    
    int state1 = -1;
    int state2 = -2;

    int n = 0;
    while(state1 != state2){
        state1 = 0;
        state2 = STATE_NUM - 1;
        int size = r_list.size();
        for(int i = 0; i < pow(2,n) - size ; i++){
            r_list.push_back(rand() % 2);
        }
        n++;
        
        
        for(int i = r_list.size() - 1; i >= 0; i--){
            
            state1 = move(state1, r_list[i]);
            state2 = move(state2, r_list[i]);

            
        }
    }
    return state1;
    

}

void sample(int n){
    int samples[STATE_NUM] = {0};
    
    for(int i = 0; i < n; i++){
        samples[q()]++;
    }
    for(int i = 0; i < STATE_NUM; i++){
        cout << (double)samples[i] / n << "\n";
    }
    
}

int main(){
    srand((unsigned)time(NULL));
    sample(200);
    
}




```

結果

>
0.344734
0.326233
0.329033

既知の定常分布と結果を比較すると
正しくサンプリングされていることが分かる