You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Current »

Denne oppgaven handler om en FeatureList-klasse, som representerer en såkalt feature vector. Dette er enkelt sagt er et sett med ord/navn med hvert sitt tilhørende (desimal)tall, omtrent som en matematisk vektor i N dimensjoner.

Bakgrunn

En feature vector (norsk: egenskapsvektor?) knytter et sett med navngitte "dimensjoner" til hvert sitt (desimal)tall, slik at en kombinasjon av egenskaper kan representeres som et punkt i et N-dimensjonalt rom. En slik vektor brukes i mange anvendelser, f.eks. til å representere evner. En figur i et spill kan f.eks. ha tallverdier for kløkt, smidighet, utholdenhet osv., tilsvarende evnevektoren (kløkt: 10, smidighet: 15, utholdenhet: 5). Hvis figuren utfører visse (trenings)oppgaver, så vil evnene endre/utvikle seg. Trikset da er å knytter en tilsvarende evnevektor til oppgaven, så en kan beregne figurens nye evneprofil ved å legge samme de to vektorene: ny evnevektor = gammel evnevektor + oppgavevektor.

Slike vektorer brukes i mange fagområder for klassifisering og beregninger, og i denne oppgaven skal du lage en FeatureList-klasse som representerer og opererer på slike vektorer.

FeatureList-klassen

FeatureList-klassen har en del grunnleggende metoder for å hente ut informasjon om hvilke dimensjoner eller egenskapsnavn og verdier vektoren har. I tillegg har den en del metoder for å endre på innholdet, både legge til dimensjoner og verdier og endre eksisterende verdier.

Metoder som leser tilstanden

FeatureList() - konstruktøren initialiserer objektet slik at det fra starten er helt tomt, dvs. uten egenskaper (navn og verdier).

FeatureList fl1 = new FeatureList() => fl1 er ()

Merk at du kan godt lage andre konstruktører i tillegg, hvis du synes det er praktisk. F.eks. kan du lage en med et varargs-parameter av typen Object[], altså FeatureList(Object... namesValues), slik at en kan skrive new FeatureList("a", 2.0, "b", 3.0)

boolean hasFeature(String featureName) - returnerer true dersom egenskapen (dimensjonen) med det gitt navnet finnes i denne FeatureList-instansen, og false ellers.

// Anta fl1 er (a: 2.0, b: 3.0)
fl1.hasFeature("a") => true
fl1.hasFeature("c") => false 

Collection<String> getFeatureNames() - returnere alle egenskapsnavnene (dimensjonene) i denne FeatureList-instansen på én gang. Rekkefølgen er uten betydning.

// Anta fl1 er (a: 2.0, b: 3.0)
fl1.getFeatureNames() => Collection<String> med elementene "a" og "b" 

double getFeatureVaue(String featureName) - returnerer verdien for den angitte egenskapen (dimensjonen) i denne FeatureList-instansen. Hvis den angitte egenskapen ikke finnes, så skal metoden returnere 0.0, som er den (implisitte) verdien for manglende egenskaper.

// Anta fl1 er (a: 2.0, b: 3.0)
fl1.getFeatureValue("a") => 2.0
fl1.getFeatureValue("c") => 0.0

FeatureList toFeatureList() - lager en kopi (altså en ny FeatureList-instans) med samme innhold som denne FeatureList-instansen. Hvis denne instansen eller kopien siden endres (med en av metodene nedenfor) så skal ikke den andre endres.

// Anta fl1 er (a: 2.0, b: 3.0)
FeatureList fl2 = fl1.toFeatureList() => fl2 er nå (a: 2.0, b: 3.0)
// hvis en nå endrer fl1 eller fl2 så vil ikke den andre blir endret

I tillegg kan det være lurt å lage en toString()-metode, som returnerer en String på formen som er brukt i eksemplene.

 

Metoder som endrer tilstanden

void addFeature(String featureName, double value) - legger til egenskapen med det angitte navnet, dersom denne ikke finnes fra før. Hvis den finnes fra før, skal egenskapen ikke endres.

FeatureList fl1 = new FeatureList();
fl1.addFeature("a", 2.0) => fl1 er (a: 2.0)
fl1.addFeature("b", 3.0) => fl1 er (a: 2.0, b: 3.0)
fl1.addFeature("a", 4.0) => fl1 er (a: 2.0, b: 3.0)

void setFeatureValue(String featureName, double value) - endrer verdien til den angitte, eksisterende egenskapen. Hvis egenskapen ikke finnes, så skal FeatureList-instansen ikke endres.

// fortsettelse, fl1 er altså (a: 2.0, b: 3.0)
fl1.setFeatureValue("a", 4.0) => fl1 er
(a: 4.0, b: 3.0)
fl1.setFeatureValue("c", 1.0) => fl1 er (a: 4.0, b: 3.0)

void increment(double value) - øker verdien til alle egenskapene i denne FeatureList-instansen med den angitte verdien.

// fortsettelse, fl1 er altså (a: 4.0, b: 3.0)
fl1.increment(3.0) => fl1 er (a: 7.0, b: 6.0)

void add(FeatureList featureList) - endrer denne FeatureList-instansen, slik at den etterpå har alle egenskapene som denne og den angitte instansen hadde. Verdien til hver egenskap er summen av verdiene i de to instansene. Hvis en instans mangler en egenskap, så er det som om verdien til den er 0.0.

// fl1 er fortsatt (a: 7.0, b: 6.0), mens fl2 er (b: 1.0, c: 6.0)
fl1.add(f2) => fl1 er (a: 7.0, b: 7.0, c: 6.0), fl2 er uendret

void mult(FeatureList featureList) - endrer denne FeatureList-instansen, slik at den etterpå har alle egenskapene som denne og den angitte instansen hadde. Verdien til hver egenskap er produktet av verdiene i de to instansene. Hvis en instans mangler en egenskap, så er det som om verdien til den er 0.0.

// fl1 er fortsatt (a: 7.0, b: 7.0, c: 6.0) og fl2 fortsatt (b: 1.0, c: 6.0)
fl2.addFeature("d", 3.0) => fl2 er (b: 1.0, c: 6.0, d: 3.0)
fl1.mult(f2) => (a: 0.0, b: 7.0, c: 36.0, d: 0.0)

Løsningshint:

  • Egenskapsnavn og -verdier kan representeres på tre måter: 1) Med to lister med navn og tilhørende verdi i samme posisjon, 2) én liste med instanser av en hjelpeklasse, f.eks. kalt NameValuePair, som holder på et navn og den tilhørende verdien og 3) en Map. Velg den varianten du synes virker enklest.
  • Velg representasjon først, altså hvilke felt du trenger, og skriv så metodene som leser tilstanden. Deretter skriver du én og én metode i den rekkefølgen de står over.
  • Hvis én metode har flere krav, f.eks. hvordan den håndterer spesialtilfeller, så skriv kode for den typiske oppførselen først.
  • Test hver nye metode du lager i din egen main-metode eller hovedprogram, f.eks. basert på eksemplene over, før du kjører våre tester.

JExercise-testkode for denne oppgaven finner du her: objectstructures/FeatureListTest.java. jextest-koden finner du her: objectstructures/FeatureList.jextest.

.ex for bruk med Exercise-panelet finner du her: FeatureList.ex.


JExercise lar deg sjekke din egen kode vha. forhåndslagde JUnit-tester og JExercise-panelet

Bruk av JExercise:

  1. Sørg for at jexercise-standalone.jar er lagt til i ditt prosjekts Build Path. Dette må gjøres hver gang du oppretter et nytt prosjekt, og det er derfor lurt å gjenbruke samme prosjekt til alle oppgaver.
  2. JExercise-tillegget må være installert. Installer tillegget fra følgende oppdateringsadresse: http://folk.ntnu.no/hal/dev/updatesite.
  3. Åpne JExercise-panelet via Window -> Show View -> Other, og navigere deg fram til JExercise i vinduet som kommer opp, velge det og klikke OK.
  4. Klikke og dra oppgavens testklasse, <oppgavenavn>Test.java fra pakkeoversikten og slippe den i JExercise panelet. 
  5. Testene kan så kjøres ved å dobbeltklikke på testen som ønskes kjørt.

Ved trøbbel, se først om du finner løsningen i Løsninger på trøbbel med JExercise.

Unknown macro: {html}

Twitre gjerne om oppgaven når du er ferdig: <a href="https://twitter.com/share" class="twitter-share-button" data-hashtags="jexercise">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

  • No labels