Simulaattorimme mallintaa kaupungin karttaa ruudukkona. Kukin
sijainti on osoite, johon kaupunkilainen (tai perhe) voi muuttaa.
Sininen ja punainen väri edustavat eri kansanosia. Valkoiset ruudut
ovat parhaillaan ilman asukasta. Suuri osa asutuista sijainneista
on merkitty pyöreällä merkillä, joka tarkoittaa sitä, että nämä
asukkaat ovat tyytymättömiä tämänhetkiseen sijaintiinsa.
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 on Gridin alityyppi (kuten GameBoard ja RobotWorld
aiemmissa tehtävissä). Kukin ruudukon elementeistä on tyyppiä:
Demographic (puuttuu). Yksinkertainen suljettu
piirreluokka toimii yläkäsitteenä luokalle Occupied ja
yksittäisoliolle Vacant, 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ä CitySimApp tarjoaa käynnistysfunktion, joka
laittaa sovelluksen näkyviin: 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.
Vinkkejä tehtävän eri vaiheisiin löytyy alta.
Yleinen 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.scalan lopusta Simulator-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 CitySimAppin 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).
Vinkkejä: Demographic
Tämä piirreluokka on erittäin yksinkertainen: siihen ei tarvita metodeita lainkaan.
Myöskään alakäsitteisiin Occupied ja Vacant ei tarvitse lisätä kuin extends-määrittely.
Sulje piirreluokka sealed-sanalla (luku 7.4). Nyt minkä tahansa Demographic-olion
on väistämättä oltava joko Occupied tai Vacant.
Sivuhuomio
Lopputulos muistuttaa Option-luokkaa ja sen Some- ja
None-alakäsitteitä. Optioniakin olisi tässä voinut käyttää,
mutta Demographic alatyyppeineen mallintaa selvemmin juuri
tähän sovellukseen liittyviä käsitteitä.
Vinkkejä: findDemographic
Huomaa, että sinulla on Simulator-olion cityMap-ilmentymämuuttujassa viittaus
aktiiviseen kaupungin karttaan eli CityMap-olioon, joka sisältää Demographic-olioita ruudukossa.
Metodille on varsin yksinkertainen toteutus, kunhan vain poimit työkaluiksi sopivat
metodit Simulator ja/tai CityMap-luokkien dokumentaatiosta.
Vinkkejä: dissatisfiedResidents
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äänlainen
Grid, joten sillä on ruudukkojen yleismetodit. Tarjolla on esimerkiksi tapa
selvittää, millainen asukas tietyssä GridPos-sijainnissa parhaillaan on.
Selvittääksesi, onko sijainti tyhjä, voit verrata sijainnin sisältöä Vacant-yksittäisolioon. Vertailu hoituu ==- tai !=-operaattorilla.
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.
Vinkkejä: moveResidents
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 CityMapissä 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 (CityMapissä) sekä
apupuskuria, jossa pidät kirjaa vapaista asunnoista. Yhden näistä
päivittäminen ei automaattisesti päivitä toista.
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
mallikin esitellään eräässä kirjan luvuista.
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.
Tehtävien automaattisen arvioinnin ovat toteuttaneet Aallon opiskelijat (aakkosjärjestyksessä)
Riku Autio, Kai Bukharenko, Nikolas Drosdek, Kaisa Ek, Rasmus Fyhrqvist, Joonatan Honkamaa,
Antti Immonen, Jaakko Kantojärvi, Onni Komulainen, Niklas Kröger, Kalle Laitinen, Teemu Lehtinen,
Mikael Lenander, Ilona Ma, Jaakko Nakaza, Strasdosky Otewa, Kaappo Raivio, Timi Seppälä,
Teemu Sirkiä, Konsta Suuriniemi, Onni Tammi, Joel Toppinen, Anna Valldeoriola Cardó,
Aleksi Vartiainen ja Oiva Ylönen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat piirsi 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. Opetustekstit animaatioihin kirjoitti
Juha Sorva.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset laati Juha Sorva.
O1Library-ohjelmakirjaston ovat
kehittäneet Juha Sorva, Aleksi Lukkarinen 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.
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.
Palautusta lähetetään...
Identtinen palautus
Tämä palautus on identtinen aikaisemman palautuksen kanssa. Oletko varma, että haluat lähettää palautuksen?
Palautuksen lähettämisessä arvosteluun tapahtui virhe. Tarkistathan internet-yhteytesi. Jos palautuskerta käytettiin, palautus arvostellaan automaattisesti, kun palvelu on jälleen käytettävissä.