pgg2Punishments.java

/* ********** ゲームの定義 **************** */
public class pgg2Punishments {

    class parameters {
    double r, gamma, beta, m, gamma_m, K;
    }
    public static parameters param;

    public int [][] s;
    static int size;

    /* コンストラクタ */
    pgg2Punishments(int givenSize) {
    param = new parameters();
    size = givenSize;
    s = new int [size][size];
    }

    /* 係数の設定 */
    public void setParameters(double gamma,double beta,double r, double K, double m) {
    param.gamma =gamma;
    param.beta = beta;
    param.r = r;
    param.K = K;
    param.m = m;
    param.gamma_m = gamma*m;
    }

    /* ランダムパターンに初期化 */
    public void initializePlayers() {
        int i, j;
        // initialize array of players:
    for (i = 0; i < size; i++) {
            for (j = 0; j < size; j++) {
        this.s[i][j] = (int) (Math.random()*4.0);
            }
        }
    }

    /* ****************************************************
     * 1ステップ
     * *****************************************************
     */
    public boolean update_strategy(int i, int j) {
    double diffPayoff;
    int neighbor_i, neighbor_j;

    if(Math.random() < 0.5) {
        neighbor_j = j;
        if(Math.random()<0.5)
        neighbor_i = plus_neighbor(i);
        else
        neighbor_i = minus_neighbor(i);
    } else {
        neighbor_i=i;
        if(Math.random() <0.5)
        neighbor_j = minus_neighbor(j);
        else
        neighbor_j = plus_neighbor(j);
    }
    diffPayoff = calcPayoff(i,j) - calcPayoff(neighbor_i,neighbor_j);

    if(Math.random() < 1.0 / (1.0 + Math.exp(diffPayoff / param.K))) {
        this.s[i][j] = this.s[neighbor_i][neighbor_j];
        return true;
    }
    else return false;
    }

    /* ****************************
     *  隣の格子番号を返す(境界条件)
     * ****************************
     */
    public static int plus_neighbor(int i) {
    if(i==size-1) return 0;
    else return i+1;
    }
    public static int minus_neighbor(int i) {
    if(i==0) return size-1;
    else return i-1;
    }

    /* ****************************
     * payoffの計算
     * *****************************
     */
    /* (i,j)とその周辺を中心とする5つのゲームのpayoffの総和 */
    public double calcPayoff(int i, int j) {

    return calcPayoffInSingleGame(i,j,this.s[i][j]) +
        calcPayoffInSingleGame(plus_neighbor(i),j,this.s[i][j]) +
        calcPayoffInSingleGame(minus_neighbor(i),j,this.s[i][j]) +
        calcPayoffInSingleGame(i,plus_neighbor(j),this.s[i][j]) +
        calcPayoffInSingleGame(i,minus_neighbor(j),this.s[i][j]);

    }

    /* (i,j)を中心とする1つのゲームでの、my_strategyに関するpayoffを計算 */
    public double calcPayoffInSingleGame(int i, int j, int my_strategy) {

        double invest, n_d, n_e, f_o;
        /* invest: C,O,Eの総数, n_d, n_e: D, Eの数, f_o: Oの数の階段関数 */
        int right, left, top, bottom;

        // 左右上下の格子番号取得
        left = minus_neighbor(i);
        right = plus_neighbor(i);
        bottom = minus_neighbor(j);
        top = plus_neighbor(j);

        /* payoff の計算 */
        invest = 0.0;
        n_e = 0.0;
        f_o = 0.0;

        if (this.s[i][j] != 0) { // Dでなかったら
            invest += 1.0;
            if (this.s[i][j] == 2)
                f_o = 1.0; // pool punisherの場合
            else if (this.s[i][j] == 1)
                n_e += 1.0; // peer punisherの場合
        }
        if (this.s[right][j] != 0) {
            invest += 1.0;
            if (this.s[right][j] == 2)
                f_o = 1.0;
            else if (this.s[right][j] == 1)
                n_e += 1.0;
        }
        if (this.s[left][j] != 0) {
            invest += 1.0;
            if (this.s[left][j] == 2)
                f_o = 1.0;
            else if (this.s[left][j] == 1)
                n_e += 1.0;
        }
        if (this.s[i][top] != 0) {
            invest += 1.0;
            if (this.s[i][top] == 2)
                f_o = 1.0;
            else if (this.s[i][top] == 1)
                n_e += 1.0;
        }
        if (this.s[i][bottom] != 0) {
            invest += 1.0;
            if (this.s[i][bottom] == 2)
                f_o = 1.0;
            else if (this.s[i][bottom] == 1)
                n_e += 1.0;
        }

        n_d = 5.0 - invest;

        if (my_strategy == 3) { // cooperator
            return param.r * invest / 5.0 - 1.0;
        } else if (my_strategy == 2) { // pool punisher
            return param.r * invest / 5.0 - 1.0 - param.gamma;
        } else if (my_strategy == 1) { // peer punisher
            return param.r * invest / 5.0 - 1.0 - param.gamma_m * n_d;
        } else if (my_strategy == 0) { // defector
            return param.r * invest / 5.0 - param.beta * (param.m * n_e + f_o);
        } else { // エラー
            // System.out.println(i+j);
            return 100.0;
        }
    }
}