Monty Hall Pythonilla – osa 3 

Viime vuoden puolella julkaisin kaksi artikkelia liittyen Monty Hall -probleemaan. Lupasin tehdä simulaation yleisestä tapauksesta, jossa vuohia on vähintään kaksi kappaletta ja autoja vähintään yksi. Lasketaan sellaisen tapauksen todennäköisyyksiä, että kilpailija aina vaihtaa valintansa, kun yksi vuohi on paljastettu.

Mikäli et ole lukenut aikaisempia tarinoita, niin katso täältä.

https://mikkorahikka.blog/2021/10/08/monty-hall-pythonilla/

https://mikkorahikka.blog/2021/10/29/monty-hall-pythonilla-osa-2/

Laitetaan tähän vielä muistin virkistykseksi Wikipediasta Monty Hall -pelin määritelmä: ”Monty Hallin ongelmassa kilpailijalla on edessään kolme ovea. Yhden oven takana on palkintona auto, kahden muun takana vuohi. Kilpailija, joka ei tiedä minkä oven takana mikin palkinto on, saa valita ovista yhden. Valittuaan oven hän ei vielä avaa sitä. Jäljelle jääneistä kahdesta ovesta avataan toinen, ja sen takana on aina vuohi. Tämän jälkeen kilpailija saa valita, vaihtaako ensin valitsemansa oven toiseen jäljellä olevaan suljettuun oveen, vai pitääkö ensin valitsemansa oven.”

python

Kolmen vuohen ja kahden auton tapauksessa vaikutti siltä, että todennäköisyys oli noin 8/15. 

Tehdään ohjelma, jossa vuohien ja autojen määrää voi muuttaa. Vuohia pitää olla vähintään kaksi, jotta peliä voi pelata ja autoja vähintään yksi. Kuvan koodi on Spyder-ohjelmointiympäristöstä.

Selitän rivillä 50 olevan yleisen kaavan johtamisen tarina loppupuolella.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Alla tulos Spyderin konsolista.

Nyt kun koodi näyttää toimivan, niin pakkohan sitä on kokeilla ylioppilaskoejärjestelmässä. Kopioin koodista rivit 10-52 ja sijoitin ne osoitteessa https://cheat.abitti.fi/build/index.html?fi&programming olevaan YTL:n Pythoniin. Ohjelma toimi, niin kuin sen pitikin.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

kuvaaja

3D-kuvaajan piirtäminen onnistuu helpoimmin, kun käyttää numpy-kirjastoa. Sillä saa kerralla laskettua funktion arvot matriisiin (2D taulukkoon), ohjelmakoodissa muuttuja Z rivillä 19. En kommentoi sen tarkemmin mitä kukin rivi tekee, jos haluat oppia, niin kokeile. Joskus opiskelen matplotlib ja numpy-kirjastot siten, että osaisin selittää miten ne oikeasti toimivat. Nyt olen vielä aloittelija niiden kanssa touhutessa. Useimmiten saan kuvaajat haluamikseni yrityksellä ja erehdyksellä.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Alla tuotos.

Tätä koodia ei voi suorittaa YTL:n Pythonissa, sillä se ei tuota kuvia. Alla vihreilmoitus osoitteessa https://cheat.abitti.fi/build/index.html?fi&programming

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

kuvaaja GeoGebralla

Edellisestä kuvasta on mielestäni hankala hahmottaa millaisilla arvoilla pelaaja voittaa. Niinpä päädyin käyttämään GeoGebraa.

Alla 3D-kuva

Loin sen kirjoittamalla GeoGebra 5:n syöttökenttään

p(x, y) = (x y + y (y – 1)) / ((x + y) (x + y – 2))

pp(x, y) = Jos(1 ≤ x < 11 ∧ 2 <= y < =11, p(x, y))

z=1/2

Piilotin p:n kuvaajasta. Ei tuonkaan kuvan pyörittely hahmota minulle, millainen alue on kyseessä.

Piirtoalueen xy-tasolle saa alueen, jossa p ≥ ½, näkyville seuraavasti. Jouduin hieman auttamaan GeoGebraa, jotta se osasi värittää epäyhtälön alueen.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Matikkanörtit voivat tutkia, millaiseta käyrästä on kyse.

ratkaisu kirjainlaskennolla

Koodeissa näkyvä yleisen ratkaisun lauseke voidaan johtaa oheisen puukaavion avulla.

Merkitään vuohien lukumäärää v:llä ja autojen a:lla.

Pelaaja voitttaa, jos toinen valinta on a. 

Jos hän valitsee vuohen ensin, niin sen todennäköisyys on v/(a + v). Tässä tapauksessa hän saa auton todennäköisyydellä a/(a + v – 2). Mahdollisuudet vähenevät kahdella, sillä hän ei voi valita samaa kuin ennen ja yksi vuohi on vähemmän.

Jos hän valitsee auton ensin, niin sen todennäköisyys on a/(a + v). Auton todennäköisyys tämän jälkeen on (a -1)(a + v + 2).

koodi

Tarinassa esitetty koodi löytyy Colabista

https://colab.research.google.com/drive/1Y2ODH9KNV4NX5OJ_8AbzWEzYW4Mz5Uoc?usp=sharing

lähteitä

Monty Hall englanniksi Wikipediass

https://en.wikipedia.org/wiki/Monty_Hall_problem

ja suomeksi https://fi.wikipedia.org/wiki/Monty_Hallin_ongelma

Lisää pohdittavaa tässä artikkelissa

https://www.researchgate.net/publication/233565559_The_Monty_Hall_Problem_Reconsidered

Monty Hall Pythonilla – osa 2

Pari viikkoa sitten käsittelin Monty Hall -probleemaa Python ohjelmoinnin avulla. Jatkan tässä tarinaa aiheesta. Yleistetään ongelmaa hieman ja saadaan uusia ongelmia ratkaistavaksi. Aiempi artikkeli löytyy täältä.

Ongelma sanallisesti

Wikipediassa perinteinen Monty Hall -ongelma esitetään seuraavasti: ”Monty Hallin ongelmassa kilpailijalla on edessään kolme ovea. Yhden oven takana on palkintona auto, kahden muun takana vuohi. Kilpailija, joka ei tiedä minkä oven takana mikin palkinto on, saa valita ovista yhden. Valittuaan oven hän ei vielä avaa sitä. Jäljelle jääneistä kahdesta ovesta avataan toinen, ja sen takana on aina vuohi. Tämän jälkeen kilpailija saa valita, vaihtaako ensin valitsemansa oven toiseen jäljellä olevaan suljettuun oveen, vai pitääkö ensin valitsemansa oven.”

Yleistetään ongelmaa siten, että vuohien ja autojen määrää voi vaihtaa. Ongelma olisi nyt tämän kaltainen. ”Olkoon v vuohien määrä (v > 1) ja a autojen määrä ( a ≥ 1). Ovien määrä on v + a.  Vuohet ja autot laitetaan satunnaisesti, yksi kunkin suljetun oven taakse. Kilpailija valitsee jonkin oven. Sen jälkeen lopuista ovista poistetaan yksi sellainen ovi, jonka takana on vuohi. Tämän jälkeen kilpailija saa valita, vaihtaako ensin valitsemansa oven johonkin jäljellä olevaan suljettuun oveen, vai pitääkö ensin valitsemansa oven.”

Ratkaisu Pythonilla

Tehdään Pythonilla simulaatio, jossa pelaaja aina vaihtaa valintansa. Tutkitaan aluksi sellaista erikoistapausta, jossa on kolme ovea ja kaksi autoa. Yritän tässä jäljitellä minun tapaani tuottaa ohjelmia, ensin yritän saada ohjelman toimimaan yksinkertaisella versiolla, sitten siirryn monimutkaisempaan tapaukseen. Pyrin myös välttämään kovin pitkiä, vaikeasti luettavia koodirivejä. En myöskään pyri tässä mahdollisimman tehokkaaseen koodin. Tämä on tarkoitettu opiskelumateriaaliksi opettajille ja ohjelmoinnista kiinnostuneille koululaisille ja opiskelijoille.

Koodi

Alla olevat kuvankaappaukset ovat Spyder ohjelmointiympäristön editorin ja konsolin kuvia. Eli kuvassa näkyy ohjelma ja sen tuotos.

Jos olet lukenut edellisen tarinan ja ymmärtänyt sen, niin koodi taitaa olla aika itsestään selvä. Muutamia kommentteja silti. 

Rivit 1-7: Spyderin tuottamaa metatietoa, tämä on ”turhaa”. Toki rivi 2 takaa, että ääkkösten pitäisi toimia.

9-10: Random kirjaston funktiot, shuffle sekoittaa listan ja randint arpoo kokonaisluvun.

13: Luodaan ovet, nollat vuohia ja ykköset autoja eli voittoja.

16: Sekoitetaan ovet-lista.

20: Arvotaan luku väliltä 0, …, 4. Tässä pitää muistaa, että Pythonissa listan ensimmäisen jäsenen järjestysluku on 0. Funktio len(lista) tulostaa lista pituuden eli sen jäsenten lukumäärän. 

28: pop-metodi poistaa olion listasta ja antaa sen tulosteena.  Jos lista  = [13, 42, 666, 42], niin lista.pop(1) antaa tulokseksi luvun 42 ja samalla listasta katoaa jäsen 42, eli nyt lista on [13, 666, 42].

32: remove-metodi poistaa ensimmäisen esiintymän syötteestään. Jos lista  = [13, 42, 42, 666, 42], niin lista.remove(42) muuttaa sen listaksi [13, 42, 666, 42].

37: Sekoitetaan jäljelle jääneet ovet uudestaan.

42: Valitaan ensimmäinen ovi. En enää jaksa arpoa jotain ovea ja sen jälkeen avata sitä, avaan eina ekan oven. Rivin 37 sekoittaminen takaa, että ovi on satunnainen. Saman olisi tietysti voinut tehdä jo rivillä 20, mutta siellä yritin noudattaa alkuperäistä reseptiä.

46-49 Päätöksentekoa voitosta.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Alla pari suorituskertaa.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Iterointia

Toistetaan peliä muutaman kerran ja lasketaan kuinka suuri osa tuottaa voittoja.

Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti
Kuva, joka sisältää kohteen teksti

Kuvaus luotu automaattisesti

Ongelmia

Palannen yleiseen ongelmaan lähiaikoina. Nyt varmaankin valistunut lukija pystyy itsekin tuottamaan oman ratkaisunsa tämän kaltaisiin ongelmiin.

1 Jos vuohia on x kpl ja autoja y, niin määritä P(x, y).

2 Milloin P(x, y) > ½? Millainen tasoalue on kyseessä?

3 Kun sinulla on lauseke P:lle. Miten esittäisit sitä fiksuimmin kuvaajana?

4 Etsi pilkkuvirhe artikkelista.

koodi colabissa

täshätää

Jos edellä oleva linkki ei toimi, niin koita toisella selaimella.

Monty Hall Pythonilla

Luin Dimensiosta Hannu Korhosen kirja-arvion Tapio Lindin Vesimelonin kuivatus ja muita matemaattisia pähkinöitä -kirjasta. En ole vielä ehtinyt lukemaan kirjaa, mutta se pitänee lukea lähiaikoina. Kirjassa yhtenä ongelmana on kuuluisa Monty Hall-probleema. Aihe on kuikertanut mielessäni jo jonkin aikaa. Niinpä päätin tehdä siitä pienen Python ohjelman. Lähinnä itselleni ja samalla myös oppilaitani varten esimerkkinä siitä, miten sanallinen ongelma käännetään tietokoneohjelmaksi.

Ongelma sanallisesti

Wikipediassa Monty Hall -ongelma esitetään seuraavasti: ” Monty Hallin ongelmassa kilpailijalla on edessään kolme ovea. Yhden oven takana on palkintona auto, kahden muun takana vuohi. Kilpailija, joka ei tiedä minkä oven takana mikin palkinto on, saa valita ovista yhden. Valittuaan oven hän ei vielä avaa sitä. Jäljelle jääneistä kahdesta ovesta avataan toinen, ja sen takana on aina vuohi. Tämän jälkeen kilpailija saa valita, vaihtaako ensin valitsemansa oven toiseen jäljellä olevaan suljettuun oveen, vai pitääkö ensin valitsemansa oven.”

Varmaankin kaikki matikan opet tietävät (viimeistään lukemalla ratkaisun Wikipediasta), että kilpailijan kannattaa vaihtaa, sillä pitämällä ensimmäisen valinnan, niin todennäköisyys voittoon on 1/3 ja vaihtamalla 2/3.

Python koodi

Tehdään Pythonilla ohjelma, joka noudattaa edellä esitettyä tilannetta siten, että kilpailija vaihtaa aina valintansa. Koodia kirjoittaessa en käytä järkeä siinä mielessä, että oikaisisin suoraan ratkaisuun. Toteutan tilanteen ikään kuin ohjeen mukaan. Laitan koodiin rivinumerot ja kommentit, joiden avulla yritän kertoa lukijalle mitä koodissa tapahtuu.

Muutama kommentti koodista

Lukijan on hyvä muistaa, että Pythonissa listan ensimmäisen jäsenen järjestysluku on nolla, toisen järjestysluku on 1 jne. Siksi ovien numerot ovat 0, 1, ja 2.

Rivillä 9: shuffle(lista) funktio sekoittaa syötelistansa jäsenet satunnaisesti.

Rivillä 13: randint(a, b) tuottaa satunnaisen kokonaisluvun väliltä [a, b].

Rivillä 17: pop-metodi poistaa olion listasta ja antaa sen tulosteena.  Jos lista  = [13, 42, 666, 42], niin lista.pop(1) antaa tulokseksi luvun 42 ja samalla listasta katoaa jäsen 42, eli nyt lista on [13, 666, 42].

Rivillä 20: remove-metodi poistaa ensimmäisen esiintymän syötteestään. Jos lista  = [13, 42, 666, 42], niin lista.remove(42) muutaa listan listaksi [13, 666, 42].

Rivillä 23: Leikkauksien avulla saadaan valittua listasta jäseniä. Jos lista on lista  = [13, 42, 666, 42], niin lista[1] tulostaa luvun 42.

Alla ohjelman tuottama tulos muutamalla suorituskerralla.

Kun tuota ohjelmaa ja tulosteita katsoo, niin pikku hiljaa (ainakin minulle) selkenee, että tässä pelissä pelaaja voittaa, jos hän on alun perin valinnut vuohen. Vuohi valitaan todennäköisyydellä 2/3.

Tehdään vielä ohjelmaan sellainen muutos, että suoritetaan se vaikkapa 1000 kertaa ja lasketaan voittojen lukumäärä.

Alla ohjelman tulos:

Seuraavassa tarinassani muokkaan ongelmaa/ohjelmaa sellaiseksi, että vuohia onkin vaikkapa 5 ja voittoautoja 2. Ja samalla tietysti pohdin, mikä siinä tilanteessa on voiton todennäköisyys.

Lähteet

https://dimensiolehti.fi/kirjallisuutta-vesimelonin-kuivatus/

https://fi.wikipedia.org/wiki/Monty_Hallin_ongelma