Flip
Signature
flip([p]) -> bool
p: real number in[0, 1](default:p = 0.5)return value:
true/false(boolean)
flip is a convenience function: it samples from a Bernoulli distribution.
Relationship to Bernoulli
Conceptual and practical equivalence:
flip(p)~sample(Bernoulli({p: p}))
When to use which?
Use
flipwhen you just need a quick weighted coin flip and a boolean result is fine.Use
Bernoulli({p: ...})when you want an explicit distribution object (e.g. to pass around, callscoreon it, orobserveagainst it).
Relationship to Categorical
Categorical({ps: ..., vs: ...}) is the general discrete distribution that returns one of the values in vs,
with probabilities proportional to ps (ps may be unnormalized).
You can express flip(p) as a categorical distribution over explicit outcomes:
sample(Categorical({ps: [p, 1-p], vs: [true, false]}))
When is Categorical better?
When you want non-boolean outcomes (e.g.
'H'/'T'or1/0).When you have more than two outcomes.
Working examples
1) One flip (default p=0.5 and explicit p)
1display(flip()); // default p = 0.5
2display(flip(0.8)); // explicit p = 0.8
true
true
undefined
2) Many flips: repeat + count trues + empirical rate
1var p = 0.3;
2var n = 20;
3
4var xs = repeat(n, function() { return flip(p); });
5
6// bool -> 0/1
7var ones = map(function(b) { return b ? 1 : 0; }, xs);
8
9display(xs);
10display(sum(ones)); // number of trues
11display(listMean(ones)); // empirical rate (~p)
[
true, true, false, false,
false, true, false, false,
false, true, false, true,
false, false, false, false,
false, false, true, true
]
7
0.35
undefined
3) Same distribution: flip vs Bernoulli vs Categorical (enumerate)
1var p = 0.7;
2
3var modelFlip = function() {
4 return flip(p);
5};
6
7var modelBern = function() {
8 return sample(Bernoulli({p: p}));
9};
10
11var modelCat = function() {
12 return sample(Categorical({ps: [p, 1 - p], vs: [true, false]}));
13};
14
15var d1 = Infer({method: 'enumerate', model: modelFlip});
16var d2 = Infer({method: 'enumerate', model: modelBern});
17var d3 = Infer({method: 'enumerate', model: modelCat});
18
19var summary = function(d) {
20 return {
21 support: d.support(),
22 pTrue: Math.exp(d.score(true)),
23 pFalse: Math.exp(d.score(false))
24 };
25};
26
27display([summary(d1), summary(d2), summary(d3)]);
[
{ support: [ false, true ], pTrue: 0.7, pFalse: 0.30000000000000004 },
{ support: [ false, true ], pTrue: 0.7, pFalse: 0.30000000000000004 },
{ support: [ false, true ], pTrue: 0.7, pFalse: 0.30000000000000004 }
]
undefined
Common pitfall: function vs result (repeat)
flip(without parentheses) is a function you can pass:repeat(10, flip)flip()is the result of one flip (a boolean), and cannot be passed as the callback
If you want repeated parameterized flips, wrap it:
correct:
repeat(10, function() { return flip(0.3); })