Galton Board - Central boundary theorem

19

The reason for this is study / learning. To know / apply programming techniques and concepts, transforming something "material" into "application".

I received a video on WhatsApp, where mixed colored balls were separated by colors passing through the pins. Either it was a lot of mechanical technology or fake video. In the end, it was a fake video, where a graphic design reproduced a Galton Board for a study paper.

Wanting to know more, I found it in the Wikipedia , and I would like to turn it into a "program".

Theboardbasicallysimulatesthe"Central Limit Theorem" ( link ): The theorem describes the distribution of the mean of a random sample of a population with finite variance.

Idea:

Startingwiththeboard,Idecidedtocreateanarray,whereIhavemalhasandpinos,formingaline:

-------Malha------->[P1][P2][P3][P4][P5]...

Pinvalues:

Astheoddsoftheballsgoingdownisalwaysgreaterfromthecentertothesides,Icreatedthepinswithvalues,andthebigger,morechancesof"continue " there. But also, since the pins are "interleaved" and not aligned vertically , I also considered that.

Creating the meshes:

// Definicoes
$qtdMalhas = 15;
$qtdPinos = 15;

// Auxiliares malhas/pinos
$am = $ap = 0;

// Criando as malhas e seus pinos
while ($am <= $qtdMalhas) {

    while ($ap < $qtdPinos) {

        if ($ap < ($qtdPinos/2)) {

            if ($am % 2 == 0) {
                $m[$am][$ap] = $ap;
            } else {
                $m[$am][$ap] = $ap+1;
            }
        } else {

            if ($am % 2 == 0) {
                $m[$am][$ap] = $qtdPinos-$ap-1;
            } else {
                $m[$am][$ap] = $qtdPinos-$ap;
            }
        }

        $ap++;      
    }

    $ap = 0;
    $am++;  
}

Mesh structure:

Considering the array basically in the following format:

$m[0][0]-$m[0][1]-$m[0][2]-$m[0][3]-$m[0][4]...
$m[1][0]-$m[1][1]-$m[1][2]-$m[1][3]-$m[1][4]...
$m[2][0]-$m[2][1]-$m[2][2]-$m[2][3]-$m[2][4]...
$m[3][0]-$m[3][1]-$m[3][2]-$m[3][3]-$m[3][4]...
$m[4][0]-$m[4][1]-$m[4][2]-$m[4][3]-$m[4][4]...
...

Printing the mesh:

// Zera auxiliares malhas/pinos
$am = $ap = 0; 

// Imprime a malha
while ($am < $qtdMalhas) {

    echo '<br>|';

    while ($ap < $qtdPinos) {

        echo $m[$am][$ap].'|';

        $ap++;
    }

    $ap = 0;
    $am++;
}

Result:

|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|
|1|2|3|4|5|6|7|8|7|6|5|4|3|2|1|
|0|1|2|3|4|5|6|7|6|5|4|3|2|1|0|

Could you knit in other ways?

Yes, using zero and one for the pins but I believe that it would have more work to draw according to the probability of each pin. Among other ways.

With the mesh ready, how can I "pass the balls"?

The idea would be to draw between the values of the pins below, considering that the chances of it staying closer to the highest value pin , ie a draw with different probabilities, and thus get the result as the "Galton Tray".

Feel free to post your own way.

    
asked by anonymous 13.04.2018 / 19:47

1 answer

11

I did this:

<?php
    function cai_bolinha($linhas) {
        $sorteio = mt_rand() % (1 << $linhas);
        return substr_count(decbin($sorteio), '1');
    }

    $linhas = 15;
    $bolinhas = 100000;

    $casas = [];
    for ($i = 0; $i <= $linhas; $i++) {
        $casas[$i] = 0;
    }

    for ($i = 0; $i < $bolinhas; $i++) {
        $casa_resultante = cai_bolinha($linhas);
        $casas[$casa_resultante]++;
    }

    for ($i = 0; $i <= $linhas; $i++) {
        echo $i . "->" . $casas[$i] . "\n";
    }
?>

Here's the output (it can vary, of course):

0->5
1->35
2->310
3->1459
4->4079
5->9071
6->15089
7->19622
8->19771
9->15366
10->9265
11->4136
12->1409
13->334
14->46
15->3

See here working on ideone.

The trick is that mt_rand() will generate any random number. This number in binary is represented by zeros and ones, where zero means falling to the left and one means falling to the right. The % (1 << $linhas) is used so that the result has the quantity of bits that interests us, represented by the variable $linhas , which corresponds to the number of lines of pins that the ball has to cross, which is the same amount of " right "with 50% probability for each side.

With this, the number $sorteio corresponds to a number where each bit describes to which side the ball was. If that number is zero (all bits are zero), then in all the sweeps it went to the left. If all the bits are 1, then in all the raffles he went to the right. Note that these two cases are quite rare and unlikely, and the greater probabilities are that the resulting number will consist of a mixture of zeros and ones.

After that, having this $sorteio , counting how many bits 1 are in it, one discovers in which house the ball fell, where house zero is the far left and the house $linhas a far right.

In the second loop for , I make 100,000 draws (the variable $bolinhas ) with balls falling to observe the distribution. Note that the resulting distribution is an approximation of the normal distribution (in fact it is a binomial distribution), and as expected, the central houses (7 and 8) accumulate the largest numbers of balls, while the extreme houses (0 and 15 ) the smallest numbers.

Feel free to try out other values for the variables $linhas and $bolinhas .

    
16.04.2018 / 19:48