generated from mmistakes/mm-github-pages-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
--- | ||
title: "Combinations and Probabilities." | ||
categories: | ||
- Basic Probability | ||
tags: | ||
- Probability | ||
--- | ||
# Permutations and Combinations | ||
|
||
An ordered set of elements in $[n]={1,2,...,n}$ is called a *permutation*. | ||
|
||
If we consider an ordered subset with r elements in a set of n elements we call this an *r permutation*. | ||
|
||
Example(lottery): An urn contains 25 balls. We draw 4 balls from the urn and record their order and number. | ||
We see that the state space is simple the set {4 permutations}. | ||
|
||
```python | ||
from itertools import permutations | ||
import random | ||
|
||
sample_space = set(permutations(range(1,26), 4)) | ||
random.sample(sorted(sample_space), 3) | ||
``` | ||
``` | ||
[(6, 23, 8, 10), (1, 9, 25, 12), (16, 1, 21, 20)] | ||
``` | ||
How many elements are in the above sample space? | ||
For the first element we have 25 possibilities, for the second 24, for the third 23 and for the last ball 22 possibilities. | ||
|
||
```python | ||
len(sample_space) == 25 * 24 * 23 * 22 | ||
``` | ||
``` | ||
True | ||
``` | ||
Let's consider the event that the first two balls are 1 and 2. | ||
|
||
```python | ||
event = {s for s in sample_space if s[0]==1 and s[1]==2} | ||
random.sample(sorted(event), 3) | ||
``` | ||
``` | ||
[(1, 2, 9, 13), (1, 2, 5, 13), (1, 2, 7, 3)] | ||
``` | ||
How many elements are in the above event? For the first and second element we have 1 possibility. For the remaining two elements we have 23 and 22 possibilities. | ||
|
||
```python | ||
len(event) == 1 * 1 * 23 * 22 | ||
``` | ||
``` | ||
True | ||
``` | ||
In general there are n! permutations of $n$. We will call this "n factorial". | ||
|
||
There are $(n)_r = n \times (n-1) \times ... \times (n-r+1) = n!/(n-r)!$ r permutations of n. We call this "n fall r". | ||
|
||
```python | ||
from math import factorial | ||
|
||
def get_number_permutations(n): return factorial(n) | ||
|
||
def get_number_fall_permutations(n, r): return factorial(n)/factorial(n-r) | ||
``` | ||
|
||
```python | ||
len(sample_space) == get_number_fall_permutations(25, 4) | ||
``` | ||
``` | ||
True | ||
``` | ||
Let us consider the above experiment but this time we will ignore the order. | ||
That means something like $(1,2,3,4,5)$ will be equivalent to $(2,1,3,4,5)$. | ||
|
||
```python | ||
from itertools import combinations | ||
|
||
sample_space_wo = set(combinations(range(1,26), 4)) | ||
random.sample(sorted(sample_space_wo), 3) | ||
``` | ||
``` | ||
[(6, 7, 8, 23), (1, 16, 21, 22), (5, 15, 16, 22)] | ||
``` | ||
How many elements will this sample space have? | ||
|
||
From above we know that the sample space which takes into account order has $(25)_4$ elements. | ||
|
||
To get "the order out" we need to simply divide this quantity by the number of 4-permutations. | ||
|
||
${25\choose4} = (25)_4/4!$ | ||
|
||
The generalized formula is | ||
${n\choose k} = (n)_k/k!$ | ||
```python | ||
def get_number_k_out_of_n(n,k): | ||
return get_number_fall_permutations(n,k)/get_number_permutations(k) | ||
``` | ||
|
||
```python | ||
len(sample_space_wo) == get_number_k_out_of_n(25,4) | ||
``` | ||
``` | ||
True | ||
``` | ||
We can apply these concepts to the game of poker. | ||
Let's consider the starting hand of Holdem Poker. | ||
|
||
We have 13 ranks and 4 suits (Club, Heart, Spades & Diamonds). The deck consists of the unique $(rank, suit)$ combinations. This gives the $13 \times 4 = 52$ cards mentioned above. | ||
|
||
```python | ||
from collections import namedtuple | ||
from itertools import product | ||
|
||
ranks = list(range(2,15)) | ||
suits = ["C", "H", "S", "D"] | ||
Card = namedtuple('Card', ['rank', 'suit']) | ||
|
||
cards = [Card(rank, suit) for rank, suit in product(ranks, suits)] | ||
hands = set(combinations(cards, 2)) | ||
``` | ||
|
||
```python | ||
len(hands) == get_number_k_out_of_n(52,2) | ||
``` | ||
``` | ||
True | ||
``` | ||
Let's consider the event that we get a pair as a starting hand. | ||
For that we need the rank of the two cards to be equal. | ||
|
||
```python | ||
event = {h for h in hands if h[0].rank == h[1].rank} | ||
``` | ||
|
||
How many elements to be have in the event? | ||
|
||
We choose one length and than can choose two suits so we have | ||
$\#E = {13 \choose 1}{4 \choose 2}$ | ||
|
||
```python | ||
len(event) == get_number_k_out_of_n(13,1)*get_number_k_out_of_n(4,2) | ||
``` | ||
``` | ||
True | ||
``` | ||
What's the probability of getting a pair? | ||
|
||
```python | ||
from fractions import Fraction | ||
|
||
Fraction(len(event), len(hands)), f"{len(event)/len(hands) * 100:.2f} %" | ||
``` | ||
``` | ||
(Fraction(1, 17), '5.88 %') | ||
``` | ||
Another possible hand is called "suited connector". | ||
|
||
That means that the ranks are only seperated by one, for example $((9, H), (10, H))$ is a suited connector. | ||
|
||
We want to consider the "best" suited connectors where the minimum rank is larger than 9. | ||
|
||
```python | ||
event = {h for h in hands if abs(h[0].rank-h[1].rank)==1 and min(h[0].rank,h[1].rank)>=9 and h[0].suit == h[1].suit} | ||
``` | ||
|
||
We have | ||
9, 10, 11, 12 and 13 as the possible lowest rank. | ||
We can choose one of the suits. | ||
So in total we have | ||
${5 \choose 1}{4 \choose 1}$ possibilties. | ||
|
||
```python | ||
len(event) == get_number_k_out_of_n(5,1)*get_number_k_out_of_n(4,1) | ||
``` | ||
``` | ||
True | ||
``` | ||
The corresponding probability is easily calculated as: | ||
|
||
```python | ||
Fraction(len(event), len(hands)), f"{len(event)/len(hands) * 100:.2f} %" | ||
``` | ||
``` | ||
(Fraction(10, 663), '1.51 %') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
--- | ||
title: "Introduction to basic probability." | ||
categories: | ||
- Basic Probability | ||
tags: | ||
- Probability | ||
--- | ||
# Introduction | ||
|
||
In this notebook I want to implement some of the ideas from [this lecture](https://www.youtube.com/watch?v=2Xwk6yNq9og) in Python. | ||
The approach of implementation is inspired by [the great notebook of Peter Norvig](https://github.com/norvig/pytudes/blob/main/ipynb/Probability.ipynb). | ||
|
||
Let us start with the notion of a *sample space*. A sample space describes the set of all possible outcomes when performing an experiment. | ||
|
||
Let us consider a simple coin throw. The sample space is simply $\{H, T\}$. We can get either Heads or Tails as a result. | ||
|
||
```python | ||
sample_space_coin = {"H", "T"} | ||
``` | ||
|
||
Let's consider the experiment that we throw a coin three times. | ||
The state space contains all possible combinations of Heads and Tails at each turn. | ||
|
||
```python | ||
from itertools import product | ||
|
||
sample_space_coins = set(product(sample_space_coin,repeat=3)) | ||
sample_space_coins | ||
``` | ||
``` | ||
{('H', 'H', 'H'), | ||
('H', 'H', 'T'), | ||
('H', 'T', 'H'), | ||
('H', 'T', 'T'), | ||
('T', 'H', 'H'), | ||
('T', 'H', 'T'), | ||
('T', 'T', 'H'), | ||
('T', 'T', 'T')} | ||
``` | ||
|
||
An *event* is a possible outcome of our experiment. | ||
Let's consider the event that Heads showed at least two times up. | ||
|
||
```python | ||
event = {s for s in sample_space_coins if s.count("H") >= 2} | ||
event | ||
``` | ||
``` | ||
{('H', 'H', 'H'), ('H', 'H', 'T'), ('H', 'T', 'H'), ('T', 'H', 'H')} | ||
``` | ||
The *frequentist* approach states the following: | ||
If all possible outcomes are equally likely an event E occurs with frequency $\#E/\#S$ where $\#E$ is the number of elements in the Event and #S is the number of elements in the State Space. | ||
For our particular example we can do it very simply in Python. | ||
|
||
```python | ||
from fractions import Fraction | ||
|
||
Fraction(len(event)/len(sample_space_coins)) | ||
``` | ||
|
||
Similar we can consider a repeated dice throw. | ||
We identify each side of the dice with a number from 1-6. | ||
That means our sample space for a single dice throw is $\{1,...,6\}$ | ||
|
||
```python | ||
sample_space_dice = {1,2,3,4,5,6} | ||
``` | ||
|
||
```python | ||
sample_space_dices = set(product(sample_space_dice, repeat=2)) | ||
sample_space_dices | ||
``` | ||
``` | ||
{(1, 1), | ||
(1, 2), | ||
(1, 3), | ||
(1, 4), | ||
(1, 5), | ||
(1, 6), | ||
(2, 1), | ||
(2, 2), | ||
(2, 3), | ||
(2, 4), | ||
(2, 5), | ||
(2, 6), | ||
(3, 1), | ||
(3, 2), | ||
(3, 3), | ||
(3, 4), | ||
(3, 5), | ||
(3, 6), | ||
(4, 1), | ||
(4, 2), | ||
(4, 3), | ||
(4, 4), | ||
(4, 5), | ||
(4, 6), | ||
(5, 1), | ||
... | ||
(6, 2), | ||
(6, 3), | ||
(6, 4), | ||
(6, 5), | ||
(6, 6)} | ||
``` | ||
Let's consider the event that the sum of two dice throws is four or less. | ||
|
||
```python | ||
event = {s for s in sample_space_dices if sum(s) <= 4} | ||
event | ||
``` | ||
``` | ||
{(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (3, 1)} | ||
``` | ||
|
||
```python | ||
Fraction(len(event), len(sample_space_dices)) | ||
``` | ||
``` | ||
Fraction(1, 6) | ||
``` |