MATLAB Tutorial #9

W ostatniej części poradnika przedstawiłem dwa sposoby symulacji zachowania uparciuchów uczestniczących w turnieju "Idź na całość". Tym razem zajmiemy się symulacją zachowania graczy niestatecznych, którzy, jeśli nadarzy się okazja, zmieniają swoje pierwotne wskazania. Zadanie jest o wiele trudniejsze i tym razem ciężko jest obyć się bez pomocy pętli for.

Paradoks Monty'ego Halla - Trudniejszy przypadek

Zakładamy, że gdy prowadzący zaproponuje zmianę wyboru bramki, gracz zawsze przystanie na to rozwiązanie. Ponownie, zaczniemy prototypować rozwiązanie bezpośrednio w Command Window MATLAB’a, a później utworzymy skrypt.
Gra rozpoczyna się identycznie jak poprzednio. Najpierw przygotowujemy bramki, po czym losowo wybieramy jedną z nich, do której trafia nagroda główna.

bramki = [false false false];
bramka_z_nagroda = randi(3); % polecenie losuję liczbę naturalną w zakresie 1 - 3 
bramki(bramka_z_nagroda) = true

bramki=

0 0 1

Następnie symulujemy zachowanie gracza. Ten, nie mając żadnych przesłanek do wyboru konkretnej bramki wskazuję jedną w sposób losowy.

pierwszy_wybor = randi(3)

pierwszy_wybor =

3

Na tym etapie rolą prowadzącego turniej jest odsłonięcie pustej bramki i zaproponowanie graczowi zmiany pierwotnego wyboru. Ostatnio nie rozwodziliśmy się nad tym krokiem rozgrywki, gdyż dla gracza uparciucha nie miał on żadnego znaczenia. W rzeczywistości jest to moment kluczowy i właśnie w tym miejscu trzeba szukać wyjaśnienia paradoksu Monty'ego Halla. Prowadzący dla podgrzania atmosfery wskazuje jedną z pustych bramek ale zastanówmy się, skąd on wie, że może wskazać konkretną bramkę jako pustą??? Musi zajrzeć za kurtynę lub dostać cynk z reżyserki. Na pewno nie może wskazać dowolnej bramki, gdyż mógłby przez przypadek wskazać na bramkę z samochodem a wtedy propozycja zamiany straciłaby przecież sens. Zasymulujmy zachowanie prowadzącego.

Przede wszystkim, prowadzący nie może odsłonić bramki z nagrodą. W naszym algorytmie możemy posłużyć się funkcją setdiff, która pozwala na usunięcie elementu ze zbioru (macierzy).

numery_bramek = [1 2 3];
numery_pustych_bramek = setdiff(numery_bramek, bramka_z_nagroda)

numery_pustych_bramek =

1 2

Po drugie, prowadzący nie może ujawnić bramki, która została już wskazana przez uczestnika zabawy.

opcje_prowadzacego = setdiff(numery_pustych_bramek, pierwszy_wybor)

opcje_prowadzacego =

1 2

W tej konkretnej symulacji prowadzącemu pozostają dwie opcje. Okazuje się jednak, że w 2/3 przypadków prowadzący ma tylko jedną opcje wyboru przy ujawnianiu pustej bramki. Jeśli możliwości, które ma prowadzący są dwie, to znaczy, że uczestnik turnieju prawidłowo wskazał bramkę z nagrodą za pierwszym razem ale tak jest tylko w 1/3 przypadków!
Prowadzący musi jeszcze tylko ujawnić konkretną pustą bramkę.

wskazanie_prowadzacego = opcje_prowadzacego(1) 

W zasadzie wystarczy, że wskazana zostanie pierwsza z brzegu z dostępnych bramek. Jednak można oczywiście zasymulować losowe wskazanie prowadzącego w przypadku, gdy ma on dwie opcje.

wskazanie_prowadzacego = opcje_prowadzacego(randi(length(opcje_prowadzacego)), 1) %wersja dla purystów

wskazanie_prowadzacego =

1

To już prawie koniec symulacji pojedynczej rozgrywki. Gracz przyjmuje propozycje prowadzącego i zmienia swój pierwotny wybór. Spośród wszystkich bramek wskazuje tą, która nie została ujawniona przez prowadzącego jako pusta i która nie była jego pierwszym wyborem. Czy wygrał?

drugi_wybor = setdiff(numery_bramek, [wskazanie_prowadzacego, pierwszy_wybor]); 
wygrana = bramki(drugi_wybor)

wygrana =

0

Tym razem się nie udało. Pozostało nam sprawdzić na ile strategia niestatecznego jest skuteczna w przypadku większej ilości gier.

  • Utwórz skrypt monty_niestateczny.m i przeprowadź symulację 10000 gier wykorzystując strategię niestatecznego.
liczba_gier = 10000;
liczba_wygranych = 0;
for i = 1:liczba_gier
    bramki = [false false false];
    bramka_z_nagroda = randi(3); % polecenie losuję liczbę naturalną w zakresie 1 - 3
    bramki(bramka_z_nagroda) = true;
    pierwszy_wybor = randi(3);
    numery_bramek = [1 2 3];
    numery_pustych_bramek = setdiff(numery_bramek, pierwszy_wybor);
    opcje_prowadzacego = setdiff(numery_pustych_bramek, bramka_z_nagroda);
    wskazanie_prowadzacego = opcje_prowadzacego(1);
    drugi_wybor = setdiff(numery_bramek, [wskazanie_prowadzacego, pierwszy_wybor]);
    wygrana = bramki(drugi_wybor);
    liczba_wygranych = liczba_wygranych + wygrana;
end

Pozostało sprawdzić jaka jest skuteczność strategii.

liczba_wygranych / liczba_gier

ans =

0.6641

Symulacja dowodzi, że strategia zmiany dwukrotnie zwiększa szansę na wygranie samochodu! Problem został rozwiązany, jednak dla wykazania efektów stosowania dwóch różnych strategii gry musimy uruchomić dwa różne skrypty. Wkrótce to zmienimy, zapraszam do kolejnej części poradnika.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *