Tämä kurssi on jo päättynyt.

Kurssin viimeisimmän version löydät täältä: O1: 2024

Luku 7.5: Kaupunkisimulaattori

Tästä sivusta:

Pääkysymyksiä: Lisäharjoitusta, kiitos? Miten reaalimaailman ilmiötä voi simuloida ohjelmassa?

Mitä käsitellään? Pääaiheina edelleen periytyminen ja kokoelmametodit. Algoritmista harjoittelua. Vapaaehtoisessa tehtävässä esimerkki refaktoroinnista periytymisen avulla.

Mitä tehdään? Tutustutaan annettuun koodiin ja ohjelmoidaan.

Suuntaa antava työläysarvio:? Kolme, neljä tuntia?

Pistearvo: C60.

Oheisprojektit: CitySim (uusi). Lisätehtävässä AuctionHouse2 (uusi).

../_images/person04.png

Kaupunkilaisia simulaattorissa

../_images/schelling1.png

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.

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 projektin CitySim, jossa mallinnamme kaupunkilaisten muuttoliikehdintää kaupungin kartalla ja erityisesti 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 9.2 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 luonnollisesti 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-projekti

CitySim-projektissa on kaksi pakkausta. Varsinaisen kaupunkimallimme muodostaa pakkaus o1.city, jonka keskeiset luokat ovat:

  • 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 periytyy Grid-luokasta kuten GameBoard luvun 7.4 Viinaharava-tehtävässä. 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ä 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:

../_images/project_citysim.png

Tehtävänanto

Lisää piirreluokka Demographic ja 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 ja Vacant ei tarvitse lisätä kuin extends-määrittely.
  • Sulje piirreluokka sealed-sanalla (luku 7.2). Nyt minkä tahansa Demographic-olion on väistämättä oltava joko Occupied tai Vacant.
  • 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ä.

findDemographic-metodi:

  • 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.

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.
  • Pyri jaottelemaan metodin koko tehtävä osatehtäviin. Yksi osatehtävä on esimerkiksi se, että on tutkittava, onko tietyn osoitteen naapurusto epätyydyttävä.
  • Voit laatia apufunktioita joko yksityisiksi metodeiksi tai paikallisiksi funktioiksi dissatisfiedResidents-metodin sisään.
  • Hyödynnä taas CityMap-olion toimintoja. Muista, että CityMap on eräänlainen Grid, joten sillä on ruudukkojen yleismetodit.
  • Jos käytät jakolaskua, niin muista, että kokonaislukujen jakolasku heittää desimaalit pois.

moveResidents-metodi:

  • Käytä kahta muuta toteuttamaasi metodia apuna.
  • Viinaharava-tehtävän (luku 7.4) esittelemästä Random.shuffle-metodista on taas apua, ja ehkä Random-luokasta (luku 3.6) muutenkin.

Lisäapua metodin toteutukseen

Näytä vinkkiPiilota vinkki

Ranka yhdelle ratkaisutavalle:

  1. Muodosta puskuri, jossa on kaikki vapaiden asuntojen sijainnit.
  2. Muodosta kokoelma, jossa on kaikki tyytymättömien asukkaiden sijainnit sattumanvaraisessa järjestyksessä.
  3. 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.

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 kollektiivisesti ryhmäytymisen. 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?

Palauttaminen

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.

Jos kiinnostuit

Ilmaisena versionakin tarjolla oleva 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.

Huutokaupat uusiksi yliluokilla

Loput tästä luvusta muodostaa ohjelmointitehtävä, joka on jatkoa aiemmille kauppapaikka-aiheisille tehtäville. Itse tehtävä on vapaaehtoinen, mutta suosittelemme että vähintäänkin tutustut siihen, mihin tehtävässä pyritään.

Luvussa 5.1 kehitit luokan FixedPriceSale, ehkä myös luokat DutchAuction ja EnglishAuction. Nämä luokat kuvaavat eri tavoin myyntiin laitettuja esineitä. Luvun 5.5 esimerkissä puolestaan laadimme luokan AuctionHouse, joka edusti sellaisia kauppapaikkoja, joissa kaikki esineet ovat huudettavissa perinteiseen EnglishAuction-tyyliin.

Jos teit mainitut aiemmat tehtävät, voit käyttää omia ratkaisujasi pohjana seuraavalle tehtävälle. Jos et, voit käyttää esimerkkiratkaisuja (FixedPriceSale, DutchAuction, EnglishAuction).

Uudistus luokkarakenteeseen

Aiemmissa tehtävissä esiintyneet luokat suhtautuvat toisiinsa suurin piirtein näin:

../_images/project_auctionhouse1.png

Toisin sanoen: AuctionHousessa on englantilaistyyppisiä huutokauppoja. Luokat FixedPriceSale ja DutchAuction ovat täysin irrallisia.

Tässä tehtävässä refaktoroit aiemmin laadittua koodia. Refaktoroinnin tavoite on parempi laatu: muokkaat FixedPriceSale-, EnglishAuction- ja DutchAuction-luokkia siten, että niitä kaikkia voi käyttää yhdessä. Samalla vähennät turhaa toistoa koodissa. Refaktoroinnin työkaluna käytämme tässä tapauksessa periytymistä (luku 7.3).

Tarkoitus olisi rakentaa tällainen versio:

../_images/project_auctionhouse2.png

Keskeisin uudistus on, että abstrakti luokka ItemForSale on yliluokkana eri tavoin myytäville esineille. Kun näin on, voimme käyttää yläkäsitettä ItemForSale, kun toteutamme luvun 5.5 versiota yleishyödyllisemmän AuctionHouse-luokan. Lisäksi InstantPurchase-luokka kokoaa yhteen vakiohintaisten esineiden ja hollantilaishuutokauppojen yhteisiä ominaisuuksia.

Toteuta uudistus

Toteuta luokat ItemForSale, EnglishAuction, InstantPurchase, FixedPriceSale, DutchAuction ja AuctionHouse sellaisiksi, että ne vastaavat projektiin AuctionHouse2 liitettyä Scaladoc-dokumentaatiota.

Ohjeita ja vinkkejä

  • Luokat kannattanee toteuttaa yllä luetellussa järjestyksessä.

  • Katso dokumentaatiosta tarkasti, mitkä luokat ja metodit ovat abstrakteja sekä mitkä metodit periytyvät kullekin luokalle sen yläkäsitteiltä.

  • Kuten luvun 7.3 tehtävissä, älä nytkään toista val-sanaa aliluokan konstruktoriparametreissa, jos kyseinen muuttuja on jo yliluokassa määritelty. Älä siis käytä esimerkiksi description-muuttujan kohdalla val-sanaa aliluokkien alussa vaan vain yliluokassa ItemForSale. Aliluokissakin voi kyllä olla tuon niminen konstruktoriparametri.

  • Tässäkin kauppapaikka-aiheisessa tehtävässä voit käyttää annettua käyttöliittymää kokeillaksesi tärkeimpien metodien toimivuutta. Käynnistysolion o1.auctionhouse.gui.TestApp ohjelmakoodista tosin tulee aluksi virheilmoituksia, mutta ne kaikkoavat, kunhan saat oman toteutuksesi käynnistyskuntoon.

    ../_images/auctionhouse2_gui.png
  • Ainoa AuctionHouse-luokaan tarvittava muutos on, että korvaat EnglishAuctionin yleisemmällä käsitteellä.

Palauttaminen

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.

Tehtävän tehtyäsi voit ihalla, miten periytyminen muutti vanhat irralliset ja toisteiset koodit kauniiksi käsitteelliseksi malliksi, jossa kustakin käsitteestä (luokasta) on määritelty vain juuri ne muutamat asiat, jotka erottavat sen sen sukulaiskäsitteistä.

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!

Kierrokset 1–13 ja niihin liittyvät tehtävät ja viikkokoosteet on laatinut Juha Sorva.

Kierrokset 14–20 on laatinut Otto Seppälä. Ne eivät ole julki syksyllä, mutta julkaistaan ennen kuin määräajat lähestyvät.

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, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä ja Aleksi Vartiainen.

Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.

Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista ovat suunnitelleet Juha Sorva ja Teemu Sirkiä. Niiden teknisen toteutuksen ovat tehneet Teemu Sirkiä ja Riku Autio käyttäen Teemun toteuttamia Jsvee- ja Kelmu-työkaluja.

Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset on laatinut Juha Sorva.

O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen ja Juha Sorva. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.

Opetustapa, jossa 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+ on luotu Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Pääkehittäjänä toimii tällä hetkellä Jaakko Kantojärvi, jonka lisäksi järjestelmää kehittävät useat tietotekniikan ja informaatioverkostojen opiskelijat.

Kurssin tämänhetkinen henkilökunta on kerrottu luvussa 1.1.

Lisäkiitokset tähän lukuun

Thomas Schellingin laatimaan käyttäytymismalliin perustuva tehtävä on mukaelma Frank McCownin suunnittelemasta ohjelmointiharjoituksesta.

a drop of ink
Palautusta lähetetään...