Luku 8.4: Kaupunkisimulaattori
Kaupunkilaisia simulaattorissa
Yksi ohjelmoinnin väkevimmistä voimista on maailmassa esiintyvien ilmiöiden ja prosessien mallintaminen. Tässä tehtävässä käytämme laskennallista mallia sosiaalisen ilmiön tutkimiseen. Otat haltuun moduulin CitySim, jossa mallinnamme kaupunkilaisten muuttoliikehdintää kaupungin kartalla ja varsinkin sitä, miten asukkaiden kuuluminen eri kansanosiin voi vaikuttaa kaupungin sosiaalisiin rakenteisiin.
Kansanosalla (demographic) tarkoitamme tässä mitä tahansa sellaista kaupunkilaisten osajoukkoa, jonka ihmiset saattavat kokea merkitykselliseksi arvioidessaan naapurustoaan. Kaupunkilaiset voidaan luokitella kansanosiin vaikkapa taloudellisen tilanteen, poliittisen kannan, etnisen taustan tai iän perusteella. Tämän luvun versiossa ohjelmasta on vain kaksi kansanosaa, jotka on kuvattu punaisella ja sinisellä värillä; luvussa 10.1 laajennamme ohjelman käsittelemään useampia ryhmiä.
Kunkin simulaation alussa kartalle sijoitetaan punaisen ja sinisen kansanosan edustajia sattumanvaraisiin paikkoihin. Simulaatio etenee askelittain: kullakin askelella kaupunkilaiset arvioivat tyytyväisyytensä nykyiseen naapurustoonsa ja saattavat muuttaa johonkin tyhjistä asunnoista. Tyytyväisyyttä arvioidaan sen perusteella, kuuluuko riittävän suuri osuus naapurustosta samaan kansanosaan.
Käyttämämme malli perustuu taloustieteen nobelisti Thomas Schellingin työhön. Se on tietysti yksinkertaistus todellisesta maailmasta; mallit ovat.
Let me remind you of the particular characteristics of all of these behavior systems. It is that people are impinging on other people and adapting to other people. What people do affects what other people do.
—Thomas Schelling
CitySim-moduuli
CitySim-moduulissa on kaksi pakkausta. Varsinaisen kaupunkimallimme muodostaa pakkaus
o1.city
, jonka keskeiset luokat ovat nämä:
Simulator
(annettu osittaisena). Simulaattorioliota voi pyytää käynnistämään uuden simulaation (startNew
) tai edistämään viimeksi käynnistettyä simulaatiota yhdellä askelella eteenpäin (moveResidents
). Apunaan simulaattori käyttää kaupungin karttaa kuvaavaa oliota, joka on tyyppiä:CityMap
(annettu valmiina). Kartta on eräänlainen ruudukko:CityMap
onGrid
in alityyppi (kutenGameBoard
jaRobotWorld
aiemmissa tehtävissä). Kukin ruudukon elementeistä on tyyppiä:Demographic
(puuttuu). Yksinkertainen suljettu piirreluokka toimii yläkäsitteenä luokalleOccupied
ja yksittäisoliolleVacant
, jotka kuvaavat varattuja ja vapaita osoitteita.
Pakkauksen o1.city.gui
luokat määrittelevät sovelluksen käyttöliittymän. Ne voit
jättää huomiotta, kunhan tiedät, että SimulatorApp
toimii käynnistysoliona: se luo
Simulator
-luokasta ilmentymän ja komentaa sitä käyttäjän nappuloilla ja liukusäätimillä
antamien ohjeiden mukaisesti.
Kaavio mainittujen luokkien suhteista:
Tehtävänanto
Lisää suljettu piirreluokka Demographic
. Määrittele Occupied
ja Vacant
sen
alakäsitteiksi.
Lisää Simulator
-luokkaan metodit findDemographic
, dissatisfiedResidents
ja
moveResidents
. (Luokasta puuttuu myös residents
-niminen metodi, mutta sen
toteuttaminen jääköön myöhemmäksi.)
Kokeile erilaisia asetuksia ohjelman käyttöliittymässä ja pohdi, miten ne vaikuttavat naapurustojen muodostumiseen.
Ohjeita ja vinkkejä
Demographic
-piirreluokka:
Tämä piirreluokka on erittäin yksinkertainen: siihen ei tarvita metodeita lainkaan.
Alakäsitteisiin
Occupied
jaVacant
ei tarvitse lisätä kuinextends
-määrittely.Sulje piirreluokka
sealed
-sanalla (luku 7.4). Nyt minkä tahansaDemographic
-olion on väistämättä oltava jokoOccupied
taiVacant
.Lopputulos muistuttaa
Option
-luokkaa ja senSome
- jaNone
-alakäsitteitä.Option
iakin olisi tässä voinut käyttää, muttaDemographic
alatyyppeineen mallintaa selvemmin juuri tähän sovellukseen liittyviä käsitteitä.
findDemographic
-metodi:
Huomaa, että sinulla on
Simulator
-olioncityMap
-ilmentymämuuttujassa viittaus aktiiviseen kaupungin karttaan eliCityMap
-olioon, joka sisältääDemographic
-olioita ruudukossa.Metodille on varsin yksinkertainen toteutus, kunhan vain poimit työkaluiksi sopivat metodit
Simulator
ja/taiCityMap
-luokkien dokumentaatiosta.
dissatisfiedResidents
-metodi:
Tyytyväisyys riippuu siitä, kuuluuko riittävän iso prosentti naapureista samaan kansanosaan. Tuo käyttäjän liukusäätimellä asettama tavoiteprosenttiosuus on sinulle tarjolla lukuna 0:n ja 100:n väliltä muuttujassa
similarityDesired
.Jokaisella asunnolla ei ole samaa määrää naapureita. Huomioi huolellisesti Scaladocin kuvaamat erilaiset tilanteet.
Hyödynnä taas
CityMap
-olion toimintoja. Muista, ettäCityMap
on eräänlainenGrid
, joten sillä on ruudukkojen yleismetodit. Tarjolla on esimerkiksi tapa selvittää, millainen asukas tietyssäGridPos
-sijainnissa parhaillaan on.Koeta jaotella metodin koko tehtävä osatehtäviin.
Yksi osatehtävä on esimerkiksi sen tutkiminen, onko tietyn osoitteen naapurusto epätyydyttävä.
Voit laatia apufunktioita joko yksityisiksi metodeiksi tai paikallisiksi funktioiksi
dissatisfiedResidents
-metodin sisään.
Jos metodisi laskee väärin, tsekkaa ainakin nämä:
Huomasitko, että
similarityDesired
on prosenttiluku väliltä 0–100 eikä 0.0–1.0?Mikäli käytit jakolaskua, muistitko, että kokonaislukujen jakolasku heittää desimaalit pois?
Jätitkö varmasti tyhjät osoitteet pois naapureista samanlaisuutta laskiessasi?
Jätitkö varmasti tyhjät osoitteet pois tuloksista? (Tyhjä osoite ei voi olla tyytymätön.)
moveResidents
-metodi:
Käytä kahta muuta toteuttamaasi metodia apuna.
Viinaharava-tehtävän (luku 8.1) esittelemästä
Random.shuffle
-metodista on taas apua, ja ehkäRandom
-luokasta (luku 3.6) muutenkin.
Lisäapua metodin toteutukseen
Ranka yhdelle ratkaisutavalle:
Muodosta puskuri, jossa on kaikki vapaiden asuntojen sijainnit.
Muodosta kokoelma, jossa on kaikki tyytymättömien asukkaiden sijainnit sattumanvaraisessa järjestyksessä.
Toista jokaiselle tyytymättömälle: Poimi uusi osoite sattumanvaraisesti vapaiden asuntojen joukosta. Siirrä asukas
CityMap
issä uuteen osoitteeseen. Korvaa vapaiden osoitteiden puskurista kohdeosoite lähtöosoitteella.
Huomaa, että kunkin tyytymättömän kohdalla on päivitettävä kahta
eri asiaa: asukkaiden sijainteja kartalla (CityMap
issä) sekä
apupuskuria, jossa pidät kirjaa vapaista asunnoista. Yhden näistä
päivittäminen ei automaattisesti päivitä toista.
Lisävinkki virheiden metsästykseen
Tässä tehtävässä satunnaisuus voi hankaloittaa virheiden etsimistä, kun ohjelman eri suorituskerroilla tapahtuu eri asioita. Onneksi kyseessä ovat vain näennäissatunnaiset luvut, joihin voi vaikuttaa siemenellä.
Voit testimielessä määrätä, että ohjelman jokaisella suorituskerralla tapahtuu täsmälleen samat asiat. Yksinkertaisin tapa on tämä:
Etsi
Simulator.scala
n lopustaSimulator
-yksittäisolio ja sieltäRandom.setSeed
-rivi, joka on kommentoitu pois.Poista kommenttimerkki rivin alusta. Voit jättää rivillä lukevan siemenluvun tai kokeilla jotakin toista.
Nyt kun käynnistät
SimulatorApp
in useita kertoja, arvotaan "satunnaiset" tapahtumat aina identtisesti. (Toki jos teet käyttöliittymässä eri käynnistyskerroilla eri asioita, tämä vaikuttaa myös satunnaislukuihin. Koodiin tekemäsi muutokset voivat myös vaikuttaa satunnaislukuihin; näin tapahtuu, jos koodimuutoksesi vaikuttavat satunnaislukujen käyttöön.)
Tarkennus: Tuo nimenomainen temppu toimii vain, jos käytät
satunnaisuuden tuottamiseen Random
-yksittäisoliota eli käskyjä
kuten Random.shuffle
ja Random.nextInt
. Se ei toimi, jos luot
uusia Random
-luokan ilmentymiä ja kutsut niiden metodeita (mihin
ei kuitenkaan ole tässä tehtävässä mitään tarvetta).
Tutki ilmiötä simulaattorilla
Kokeile simulaattoria oletusasetuksilla. Askella ensin Single Step -nappulalla. Kokeile myös Run-nappia. Asukkaiden tyytyväisyyskynnys on 70 %, eli he ovat varsin helposti tyytymättömiä nykyiseen osoitteeseensa.
Kokeile isommilla ja pienemmillä kynnysarvoilla.
Selvältä tuntuu, että jos asukkaat haluavat paljon itsensä kaltaisia naapureita, he päätyvät asumaan oman kansanosansa pariin. Vähemmän itsestäänselvää on, kuinka pieni oman ryhmän kaipuu yksilötasolla riittää aiheuttamaan ryhmäytymisen kollektiivisella tasolla. Tutki.
Voisiko samankaltaisella mallilla selittää myös sosiaalisen median "kuplia"?
Mitä kaikkea tämä malli ei huomioi?
Mitä tapahtuisi, jos esimerkiksi yksi kansanosa välittää naapurustosta kuten ohjelmassamme, mutta toinen on aina tyytyväinen tai vaikkapa satunnaisesti 99 % ajasta tyytyväinen? Tai mitä jos asukkaat eivät ainoastaan laittaisi alarajaa naapuruston samankaltaisuudelle vaan myös ylärajan?
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Jos kiinnostuit
Ilmaisenakin versiona löytyvä kirja Networks, Crowds, and Markets: Reasoning About a Highly Connected World kertoo lisää mm. sosiaalisten, taloudellisten ja lääketieteellisten ilmiöiden mallintamisesta. Tässä tehtävässä käsiteltyä Schellingin mallia esitellään kirjan neljännessä luvussa.
Palaute
Huomaathan, että tämä on henkilökohtainen osio! Vaikka olisit tehnyt lukuun liittyvät tehtävät parin kanssa, täytä palautelomake itse.
Tekijät
Tämän oppimateriaalin kehitystyössä on käytetty apuna tuhansilta opiskelijoilta kerättyä palautetta. Kiitos!
Materiaalin luvut tehtävineen ja viikkokoosteineen on laatinut Juha Sorva.
Liitesivut (sanasto, Scala-kooste, usein kysytyt kysymykset jne.) on kirjoittanut Juha Sorva sikäli kuin sivulla ei ole toisin mainittu.
Tehtävien automaattisen arvioinnin ovat toteuttaneet: (aakkosjärjestyksessä) Riku Autio, Nikolas Drosdek, Kaisa Ek, Joonatan Honkamaa, Antti Immonen, Jaakko Kantojärvi, Onni Komulainen, Niklas Kröger, Kalle Laitinen, Teemu Lehtinen, Mikael Lenander, Ilona Ma, Jaakko Nakaza, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä, Joel Toppinen, Anna Valldeoriola Cardó ja Aleksi Vartiainen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.
Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista suunnittelivat Juha Sorva ja Teemu Sirkiä. Teemu Sirkiä ja Riku Autio toteuttivat ne apunaan Teemun aiemmin rakentamat työkalut Jsvee ja Kelmu.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset laati Juha Sorva.
O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen, Juha Sorva ja Jaakko Nakaza. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.
Tapa, jolla käytämme O1Libraryn työkaluja (kuten Pic
) yksinkertaiseen graafiseen
ohjelmointiin, on saanut vaikutteita tekijöiden Flatt, Felleisen, Findler ja Krishnamurthi
oppikirjasta How to Design Programs sekä Stephen Blochin oppikirjasta Picturing Programs.
Oppimisalusta A+ luotiin alun perin Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Nykyään tätä avoimen lähdekoodin projektia kehittää Tietotekniikan laitoksen opetusteknologiatiimi ja tarjoaa palveluna laitoksen IT-tuki; sitä ovat kehittäneet kymmenet Aallon opiskelijat ja muut.
A+ Courses -lisäosa, joka tukee A+:aa ja O1-kurssia IntelliJ-ohjelmointiympäristössä, on toinen avoin projekti. Sen suunnitteluun ja toteutukseen on osallistunut useita opiskelijoita yhteistyössä O1-kurssin opettajien kanssa.
Kurssin tämänhetkinen henkilökunta löytyy luvusta 1.1.
Lisäkiitokset tähän lukuun
Thomas Schellingin laatimaan käyttäytymismalliin perustuva tehtävä on mukaelma Frank McCownin suunnittelemasta ohjelmointiharjoituksesta.