Constrain posteriors within parameter

Hi all,

I have the following model

data {
    int<lower=1> n_matches;                                           // number of matchres
    int<lower=1> n_players;                                           // number of players
    int<lower=1, upper=n_players> player_id[n_matches];               // player id
    int<lower=1, upper=n_players> opponent_id[n_matches];             // opponent id
    int<lower=0, upper=1> won[n_matches];                             // win or loss

}

parameters {
    real<lower=0, upper=1> p[n_players];
}


model {
    // likelihood
    for (match in 1:n_matches) {
        won[match] ~ bernoulli(custom_function(p[player_id[match]]));
    }
}

How can I insert the constraint that the sum of p[player_id[match]] and p[opponent_id[match]] should be equal to 1?

I tried the below:

model {
    real custom_function_p;

    for (match in 1:n_matches) {
        custom_fuction_p = custom_function(p[player_id[match]]);
        p[opponent_id[match]] = 1.0 - p[player_id[match]];
        won[match] ~ bernoulli(custom_function_p);
    }

But this yields the following error:

Cannot assign to global variable ā€˜p’ declared in previous blocks.

I also tried this without result:

model {
    for (match in 1:n_matches) {
        p[player_id[match]] + p[opponent_id[match]] ~ normal(1, 0);
        won[match] ~ bernoulli(custom_function_p);
    }

Resulting in

Exception: normal_lpdf: Scale parameter is 0, but must be positive!

Any advice?

The easiest way to do this would be to change your parameter p to be an array of simplexes:

parameters {
    array[n_matches] simplex[2] p;
}

Thank you for your suggestion.
If I have the below match-level data:

match player opponent
1 1 2
2 1 4
3 1 6
4 2 4
5 3 4
6 3 2
7 3 6
8 3 1
9 5 1
10 5 4

Based on the table the simplex-method will generate a matrix of 10 by 2. But are p[1,1], p[2,1], p[3,1], p[8,2], p[9,2] the same? How can I make sure this is the case?

Are you sure you want the probability for a given player to be the same regardless of match? If it is, then the probability for the opponent can only take one value.

In other words, if p[1,1] = p[2,1] = p[3,1], then by definition that implies p[1,2] = p[2,2] = p[3,2]

I see what you mean and, yes that is what I want for now

In that case, you only need a simplex for each player:

parameters {
array[n_players] simplex[2] p;
}

Since there is only possible value for the player, and then only one possible value for the opponent, you would just use the same p[player] for all matches with that player

1 Like