DM02 - Obligatorisk opgave E.05 Rejseplanlægning. Jacob Aae Mikkelsen

Relaterede dokumenter
DM507 Eksamen Obligatorisk Opgave Rejseplanlægning

Sekvensafstand DM34 - Eksamensopgave. Jacob Aae Mikkelsen

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

Danmarks Tekniske Universitet

Algoritmer og datastrukturer Course No Cheat Sheet May 15, 2012

Sortering. Eksempel: De n tal i sorteret orden

DM507 Algoritmer og datastrukturer

Sortering. Eksempel: De n tal i sorteret orden

Sortering af information er en fundamental og central opgave.

Sortering. De n tal i sorteret orden. Eksempel: Kommentarer:

DM507 Algoritmer og datastrukturer

Sortering af information er en fundamental og central opgave.

DM507 Algoritmer og datastrukturer

Forelæsning 17, tirsdag 2. november 1999 Søgning efter en given værdi i en tabel. Programmering 1999

Skriftlig Eksamen Algoritmer og Datastrukturer (DM507)

DM507 Algoritmer og datastrukturer

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

Danmarks Tekniske Universitet

Skriftlig eksamen i Datalogi

Danmarks Tekniske Universitet

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

Grådige algoritmer. Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer.

Prioritetskøer og hobe. Philip Bille

Korteste veje. Introduktion Egenskaber for korteste veje Dijkstras algoritme Korteste veje på DAGs. Philip Bille

Datastrukturer (recap)

DM507 Algoritmer og datastrukturer

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 3

Danmarks Tekniske Universitet

Korteste veje. Introduktion Egenskaber for korteste veje Dijkstras algoritme Korteste veje på DAGs. Philip Bille

Martin Olsen. DM507 Projekt Del I. 19. marts 2012 FOTO: Colourbox

DM507 Algoritmer og datastrukturer

Korteste veje i vægtede grafer. Længde af sti = sum af vægte af kanter på sti.

Korteste veje i vægtede grafer. Længde af sti = sum af vægte af kanter på sti.

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

Danmarks Tekniske Universitet

Grådige algoritmer. Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer.

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

Grådige algoritmer. Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer.

Danmarks Tekniske Universitet

Rolf Fagerberg. Forår 2013

Algoritmeskabeloner: Sweep- og søgealgoritmer C#-version

Korteste veje i vægtede grafer. Længde af sti = sum af vægte af kanter på sti.

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 13/ Side 1 af 7

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

Skriftlig eksamen i Datalogi

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 4

Danmarks Tekniske Universitet

BRP Kursusintroduktion og Java-oversigt

BRP Sortering og søgning. Hægtede lister

Netværksalgoritmer 1

DANMARKS TEKNISKE UNIVERSITET

22 Hobe. Noter. PS1 -- Hobe. Binære hobe. Minimum-hob og maximum-hob. Den abstrakte datatype minimum-hob. Opbygning af hobe. Operationen siv-ned.

Algoritmeanalyse. Øvre grænse for algoritme. Øvre grænse for problem. Nedre grænse for problem. Identificer essentiel(le) operation(er)

Datastrukturer (recap)

Forelæsning Uge 5 Mandag

Skriftlig Eksamen Algoritmer og Datastrukturer (DM507)

Danmarks Tekniske Universitet

Mindste udspændende træ. Mindste udspændende træ. Introduktion. Introduktion

Introduktion til DM507

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet

Grafer og graf-gennemløb

Danmarks Tekniske Universitet

DM507 Algoritmer og datastrukturer

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet

Datastrukturer (recap) Datastruktur = data + operationer herpå

Rolf Fagerberg. Forår 2012

Løsning af møntproblemet

Rolf Fagerberg. Forår 2015

DM34-1. Obligatorisk opgave Dilemma spillet. Jacob Aae Mikkelsen kok04

Grådige algoritmer. Et algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer.

Grafer og grafalgoritmer

Stakke, køer og lidt om hægtede lister - kapitel 16 og 17

Stakke, køer og lidt om hægtede lister

Intervalsøgning. Algoritmisk geometri. Motivation for intervaltræer. Intervalsøgning. Lad der være givet en database over ansatte i en virksomhed

Algoritmisk geometri

Rolf Fagerberg. Forår 2015

Rekursion og dynamisk programmering

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

DM13-1. Obligatorisk opgave E.05. Jacob Aae Mikkelsen

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt.

Grafer og graf-gennemløb

Grafer og graf-gennemløb

Danmarks Tekniske Universitet

Find største element, sæt det på sidste plads. Grundidé i hobsortering. er er

Rolf Fagerberg. Forår 2014

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 2

Skriftlig eksamen i Datalogi

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 18/ Side 1 af 11

Abstrakte datatyper C#-version

DM02 Kogt ned. Kokken. Januar 2006

Datastrukturer. Datastruktur = data + operationer herpå

Danmarks Tekniske Universitet

b) Udvid din implementation af forme til at understøtte.equals. To objekter af samme form er ens hvis de har samme værdier i felterne.

BRP Tal. Om computer-repræsentation og -manipulation. Logaritmer

Transkript:

DM02 - Obligatorisk opgave E.05 Rejseplanlægning Jacob Aae Mikkelsen 191076 3. November 2005

Resumé Denne rapport dokumenterer opbygningen af et program der skal beregne den korteste rejsetid mellem en start og en slutstation i en køreplan. Rapporten forklarer teorien bag opbygning af grafen der søges i, opbygningen af en hob som minimums prioritetskø, samt Dijkstar s algoritme. Slutteligt er implementationen og afprøvningen af programmet beskrevet.

Indhold 1 Indledning 2 2 Kravspecifikation 3 3 Design 5 3.1 Udviklingsstrategi............................... 5 3.2 Teori om grafer................................. 5 3.3 Hob teori.................................... 6 3.4 Dijkstra s algoritme............................... 6 4 Implementation 7 4.1 Grafens opbygning............................... 7 4.2 Dijkstra s algoritme............................... 8 4.3 Implementation af hoben............................ 9 5 Køretids analyse 12 5.1 Opbygning af grafen.............................. 12 5.2 Søgningen.................................... 13 5.3 Pladsforbrug.................................. 14 6 Afprøvning 15 7 Konklusion 17 A Testkørsels udskrifter 19 A.1 Testkøreplanen................................. 19 B Kilde kode 20 B.1 Rute.java.................................... 20 B.2 TextReader.java................................. 23 B.3 Vertex.java................................... 24 B.4 Edge.java.................................... 27 B.5 Dijkstra.java.................................. 28 B.6 Heap.java.................................... 29 1

Kapitel 1 Indledning Denne rapport dokumenterer udviklingsforløbet og afprøvningen af et program der skal kunne beregne rejsetider i en togplan. Hoveddelene i opgaven er at konstruere en vægtet, orienteret graf, programmere en binær hob som prioritetskø, samt at implementere Dijkstras algoritme. Rapporten fungerer sammen med programmet, som obligatorisk opgave, og dermed som adgangskrav til eksamen i DM02 - efterår 2005 på Syddansk Universitet, Odense. Kravene til både programmet og rapporten er specificeret i punktform i afsnittet kravspecifikation. I design afsnittet er teorien bag Dijkstras algoritme, grafens opbygning og hoben beskrevet, samt hvorledes opgaven i praksis er grebet an. Afsnittet om implementation beskriver hvorledes koden er bygget op, og hvor kildekoden skiller sig væsentligt ud fra teorien i design afsnittet. Køretiden er analyseret i afsnittet herom, for opbygningen af grafen, såvel som for søgningen efter den korteste tur. Der er benyttet forskellige former for test til at afprøve programmet med, og disse er forklaret og dokumenteret i test afsnittet. Slutteligt er der konkluderet på de resultatet af opgaven. Programmet virker efter hensigten, og teorien bag er forklaret i denne rapport. 2

Kapitel 2 Kravspecifikation Opgaven går ud på at lave et program, som ud fra en togplan finder den bedste rute mellem to byer. Turen skal tage så kort tid som muligt, men med så få togskift som muligt. Turen må forlænges med 15 minutter for at undgå et togskift. Og hvis ruten ud fra disse kriterier er ens, er de lige gode. Der er i opgaven stillet følgende direkte krav til programmet Programmet skal kodes i programeringssproget JAVA (den nyeste version) Der skal konstrueres en graf, som representerer køreplanen, der skal overholde følgende krav: for hver toglinie tilføjes knuder for hver station, og kanter mellem to på hinanden følgende stationer (Eksterne kanter) Når alle toglinierne er tilføjet tilføjes for hver station kanter (Interne kanter), mellem de afgange der er mindst 5 minutter senere end den forige. Vægten af en ekstern kant er forskellen i minuttter mellem slut og start. Vægten af en intern kant er forskellen i minutter mellem slut og start, plus 15 minutter. Grafen skal kunne bygges i tid O(max{ n a log n a, n s k 2 }), hvor n a er det samlede antal afgang fra alle stationerne tilsammen, n s er antallet af stationer, og k er det største antal afgange, der er fra nogen station. Der skal kodes en binær hob, der kan fungere som prioritetskø Dijkstra s algoritme skal implementeres for at finde korteste vej korteste vej og antal skift for den ønskede rute skal kunne findes i tid O((n a + n s k 2 ) log(n a )) Programmet skal køre med tre inputs 1. fil med køreplan 3

KAPITEL 2. KRAVSPECIFIKATION 2. startstationen 3. slutstationen Output fra programmet skal være to tal adskilt af et mellemrum, det første skal være antal minutter om turen, og det andet antal togskift. Programmet skal testes og afprøves for korrekthed Kildekoden skal være kommenteret i passende omfang Der er til rapporten stillet følgende krav Beskrielse og begrundelser af væsentlige valg. Argument for at køretiderne overholdes. Forklaring af test og afprøvning Eventuelle fejl og mangler beskrives. Den skal indeholde en udskrift af kildekoden 4

Kapitel 3 Design 3.1 Udviklingsstrategi Opgaven er beskrevet ganske detaljeret, algoritmerne, såvel som strukturerne, er gennemgået i undervisningen. Med dette i mente er vandfaldsmodellen benyttet til projektet. Der er under testningen ikke fundet nævneværdige problemer, hvorfor dette synes et fornuftigt valg. 3.2 Teori om grafer Hvis en graf skal overføres fra et stykke papir til en computer er det fornuftigt at benytte enten et array eller en arrayliste, til at opbevare knuderne. Indeni knuderne gemmes en adjacens liste med de udgående kanter. I dette tilfælde, hvor kanterne har information om vægt, togskifte og den station den peger på, samt at vi ikke ved hvor mange knuder der skal være i grafen, når vi går igang med at bygge den, er det oplagt at benytte en ArrayListe. I ArrayListen gemmes så knuder, der oprettes som objekter af klassen Vertex. Knuder (Vertex) skal indeholde oplysninger om stationsnavn, tiden den er på stationen, afstanden fra start til knuden og antal togskift på den korteste rute fra startknuden, samt udgående kanter. De udgående kanter gemmes i en adjacensliste som objekter af typen Edge. Denne liste implementeres som en LinkedList i JAVA. De øvrige oplysninger kan gemmes som ret simple typer. For at opfylde kravet til køretid oprettes en variabel med knudens index i arraylisten, således at der ikke skal søges igennem listen for at finde knuden. Kanter (Edge) skal indeholde oplysninger om til hvilken station den går, hvor stor vægt den har, og om den representerer et togskifte (intern kant). Disse oplysninger kan også representeres ved simple typer. Opbygningen af grafen i opgaven sker ved at tilføje eksterne kanter på grafen først, altså de kanter hvor passagereren reelt kører med tog. Dette kan gøres efterhånden som linierne i inputfilen læses. Herefter skal knuderne sorteres efter navn og tid, med arraylistens indbyggede sorteringsfunktion. Herefter skal der for hver knude tilføjes kanter, til 5

3.3. HOB TEORI KAPITEL 3. DESIGN den samme station, blot der er 5 minutter mellem afgangene. 3.3 Hob teori I Cormen et. al[2] gennemgåes teorien for en max-hob. Teoretisk er det helt parallelt med en min-hob, således skal der implementeres metoderne: buildminheap, minheapify, decreasekey og extractmin. Elementerne i hoben bliver knuderne fra grafen, og nøglen de skal sorteres efter, er afstanden fra startknuden til knuden selv. Metoden minheapify(i) forudsætter at undertræerne fra i opfylder min-hob kravene. Ellers sammenligner denne metode nøglen for i med begge eventuelle børn, og evt. bytter denne med den mindste af dem, og kalder så sig selv på den nye plasering af i. I buildminheap(a) opbygges hoben ved kald til minheapify(i) for alle elementerne i den øverste halvdel af hoben, idet den nederste halvdel er blade i hoben, og disse opfylder i sig selv min-hob betingelserne. Metoden decreasekey(i, key) ændrer nøglen for den knude med index i til en lavere værdi, og bobler så denne op i hoben ved at sammenligne nøglen med forældrerens nøgle, og bytte hvis den er mindre. Når det kommer til extractmin(), der returnerer det mindste element i hoben, indføres en kontrol metode heaphasmoreelements(), således at metoden ikke bør kaldes inden der er kontrolleret om der faktisk er flere elementer i hoben. I extractmin() hentes det nederste element og indsættes som det øverste, der midlertidig er gemt, inden det returneres. Det nye øverste element bobles så ved hjælp af minheapify ned til den korrekte plads. Herved bevares hob strukturen efter det mindste element er fjernet, og den kan derfor bruges som prioritetskø. 3.4 Dijkstra s algoritme Dijkstra s algoritme er en søgealgoritme, der bruges til at bestemme korteste afstande mellem en startknude og alle andre knuder i en vægtet orienteret graf uden negative kanter. Algoritmen starter med at initializere alle knuderne til afstanden uendelig, undtagen startknuden. Her er startknuden lig med en startstation, og der kan derfor godt være flere knuder der starter med afstanden 0. Alle knuderne indsættes i prioriteskøen (hoben), og elementerne betragtes ét efter ét, med den mndste nøgle først. For hver knude, gennemgåes de knuder der peges på i dens adjacens liste. Disse knuders distance opdateres, hvis afstanden fra den knude kanten kommer fra plus vægten af kanten er mindre end knudens egen distance, og hoben opdateres for hvert skift. I denne implementation er vi bare ude efter afstanden og togskift mellem en startknude og en slutknude, og vi gemmer således ikke resultatet fra de andre knuder. Da knuderne, når de er udtaget af køen ikke ændrer deres værdi, er den første gang vi møder en knude der representerer slutstationen den der har den korteste distance, og algoritmen kan afbrydes der. 6

Kapitel 4 Implementation 4.1 Grafens opbygning 4.1.1 Tekstindlæsning Det første der sker i programmet er at der initialiseres et TextReader object med den køreplanfil programmet er startet med. Det er her valgt at anbringe indlæsningsenheden i en klasse for sig selv, da dette er en veldefineret opgave, og derfor berettiger til det. Textreaderen minder meget om en standart indlæsningsklasse, men er udvidet med to metoder, hasmorelines og getnextline. Dette letter at få køreplanen læst én linie af gangen. 4.1.2 Knuder og kanter Knuderne, representeret i Vertex klassen, er primært en samling af data, og indeholder mest metoder der gemmer data eller returnerer data. Det eneste der er værd at bemærke er at distancen initialiseres til 100.000.000. Dette er vurderet til at være stort nok til at rejsetiden i en togplan sagtens vil holde sig under dette tal. Metoden compareto laver blot strenge med stationsnavnet efterfulgt af tiden og sammenligner disse alfabetisk. 4.1.3 Eksterne kanter For hver linie der er i køreplanen, læses denne linie, og hvis den indeholder en station tilføjes en knude med oplysninger om stationsnavn og tid. Da vi kender startstationen, testes allerede her om stationen er startstationen, og hvis den er ændres knudens distance til 0. På denne måde gennemføres initializeringen til Dijkstra s algoritme allerede her. Hvis ikke stationen er den sidste på en banestrækning, tilføjes en kant fra den seneste knude til nuværende. På denne måde tilføjes alle knuder, samt alle eksterne kanter. 7

4.2. DIJKSTRA S ALGORITME KAPITEL 4. IMPLEMENTATION 4.1.4 Interne kanter For at tilføje interne kanter sorteres arraylisten med knuderne efter alfabetisk rækkefølge. For hver knude indsættes indexnummeret i knuden, og der tilføjes interne kanter til alle de stationer der har samme navn, og som tidsmæssigt kommer senere i arraylisten end den knude der tilføjes kanter til. Da stationerne er alfabetiserede, kan løkken stoppes så snart den første station der ikke er den samme som knuden selv mødes. Der skal være mindst 5 minutter mellem afgangene, således at et togskifte fysisk vil kunne lade sig gøre. if(calculatelength(nexttime,starttime) >= 5) { currentvertex.addedge(new Edge( nextvertex, calculatelength(nexttime,starttime)+15, 1)); De kanter der tilføjes her som interne, tilføjes 15 minutter i forhold til tidsforskellen mellem dem, og togskift sættes til 1. De 15 minutter fratrækkes i den sidste ende, for hvert togskift der har været. Grafen er nu bygget op, og Dijkstra s algoritme sættes igang med at søge efter den korteste distance til slut stationen. 4.2 Dijkstra s algoritme Dijkstra s algoritme starter teoretisk med initialize-single-source. Dette skridt er allerede laver i grafens opbygning. Alle knuderne placeres i en binær hob, som prioritetskø. Hobens opbygning beskrives i næste afsnit. public Dijkstra(ArrayList<Vertex> input, String to) { priorityqueue = new Heap(input); Alle elementerne hentes ud af køen, i rækkefølge efter den mindste afstand fra startknuden, ved hjælp af en while-løkke. while(priorityqueue.heaphasmoreelements()) { Vertex u = priorityqueue.heapextractmin(); For hver knude testes om den er slutstationen, og i hvis det er, så må det jo være den der er kortest afstand til, derfor kan algoritmen stoppes, med en break. if(u.getname().equals(to)) { fastestroute = u; //The first hit, we re done break; } Hvis ikke stationen er slutstationen, itereres over alle kanterne i knudens adjacenslist, og kalder funktionen relax for hver knude, som kanten peger på. 8

4.3. IMPLEMENTATION AF HOBEN KAPITEL 4. IMPLEMENTATION } } Iterator it = u.getadjacent().iterator(); while(it.hasnext()) { Edge w = (Edge)it.next(); relax(u, w.getto(), w.getlength(), w.gettrainshift()); } 4.2.1 Relax metoden Metoden relax kaldes med fire parametra. fra-knuden, til-knuden, kanten mellem dem s vægt, og kantens mulige togskift. Den sammenligner så til-knudens distance med fraknudens sammenlagt med kantens vægt, og opdaterer til-knuden hvis afstanden er mindre. Slutteligt kalder metoden decreasekey på køen, så denne opdateres. private void relax(vertex u, Vertex v, int weight, int shifts) { if(v.getdistance() > u.getdistance() + weight) { v.setdistance(u.getdistance() + weight); v.settrainshift(u.getshifts() + shifts); priorityqueue.decreasekey(v); } } 4.3 Implementation af hoben Det mest problematiske ved implementationen af hoben, var at arraylisten er indekseret fra nul, og hoben fra ét. Det er derfor markeret i koden, hvor der bruges array indeksering, og hvor der bruges hob indeksering. 4.3.1 minheapify Metoden minheapify kaldes med et hob-index, og antager at de to mulige undertræer af dette index opfylder min-hob egenskaben. Den sammenligner så knuden med dens to børn, og bytter det mindste til det kaldte indeks, hvis det ikke allerede er der (hertil benyttes metoden swap). Hvis der sker en ombytning, kaldes nimheapify med hob-indekset for den placering der blev byttet opad i hoben. Således vil metoden blive kaldt rekursivt, indtil knuden er på plads i hoben. private void minheapify(int index) //Heap numbered { int i = index - 1; //Array numbered int l = 2*index - 1; //Array numbered int r = 2*index; //Array numbered int smallest; //Array numbered 9

4.3. IMPLEMENTATION AF HOBEN KAPITEL 4. IMPLEMENTATION } if(l < numberofelements && heap.get(l).getdistance()<heap.get(i).getdistance()){ smallest = l; } else { smallest = i; } if(r < numberofelements && heap.get(r).getdistance()<heap.get(smallest).getdistance()){ smallest = r; } if(smallest!= i) { swap(smallest, i); minheapify(smallest+1); } 4.3.2 buildminheap Når hoben skal bygges fra en ikke sorteret arrayliste, benyttes den egenskab, at halvdelen af knuderne (rundet op) er blade. Blade opfylder hob egenskaberne, så metoden kalder bare minheapify fra den midterste knude ned til nummer ét. public void buildminheap() { for(int i = (int) Math.floor(numberOfElements/2) ; i > 0 ; i-- ) { minheapify(i); //Heap numbered } } 4.3.3 heapextractmin Her i heapextractmin hentes det første elemnent i arraylisten, gemmer det midlertidigt, mens det sidste element flyttes op på dens plads, og tildeles index 0. minheapify kaldes på listens nye første element, hvorved det bobles ned til dets rigtige plads. Pladsen hvor det sidste element overskrives med et null objekt, så listen bliver mindre for hver gang metoden kaldes. Slutteligt returneres det mindste element. public Vertex heapextractmin() { Vertex min = heap.get(0); heap.set(0, heap.get(numberofelements-1)); heap.get(0).setindex(0); heap.set(numberofelements-1, null); 10

4.3. IMPLEMENTATION AF HOBEN KAPITEL 4. IMPLEMENTATION } numberofelements--; minheapify(1); //Heap numbered return min; 4.3.4 decreasekey Metoden her er ikke helt som i bogen[2], idet knuden allerede har skiftet værdi (dette sker i Dijkstra s relax-metode). Relevant er til gengæld at knuden selv kender sit index, som også kunne være valgt som parameter i stedet for. At knuden selv kender sit index forøger hastigheden, frem for at skulle kalde metoden indexof, der skal søge listen igennem. Dette ville forøge køretiden med en faktor n a (Antal knuder). public void decreasekey(vertex v) { int index = v.getindex(); //Array numbered int parentindex = (int) Math.floor((index+1)/2)-1; //Array numbered while (index > 0 && (heap.get(parentindex).getdistance() > heap.get(index).getdistance())) { swap( index, parentindex); index = parentindex; parentindex = (int) Math.floor((index+1)/2)-1; } } 4.3.5 heaphasmoreelements & swap Disse to metoder er ganske simple, swap ombytter to elementer, der er på de to arraylist indekserede pladser, den kaldes med, og opdaterer også deres nye index. heaphasmoreelements returnerer true, hvis hoben indeholder flere elementer, og false ellers. Denne metode bruges, således at underflow fejl kan undgåes. 11

Kapitel 5 Køretids analyse De to klasser Vertex og Edge indeholder ikke metoder der kommer over konstant tid, da det er set og get metoder de fleste af dem. Dette er trivielt, og disse analyseres ikke nærmere når de enkelte metoder kaldes. 5.1 Opbygning af grafen 5.1.1 Indlæsning fra køreplanen og eksterne kanter Kravet til køretiden er at den skal kunne bygges i O(max{ n a log n a, n s k 2 }), hvor n a er det samlede antal afgang fra alle stationerne tilsammen, n s er antallet af stationer, og k er det største antal afgange, der er fra nogen station. Sammenhængen mellem antal afgange fra stationerne og linier tekst i inputfilen, afhænger af hvor mange tog-linier der er i inputfilen. For alle stationer på en tog-linie tilføjes kanter, med undtagelse af den sidste. Da vi skal alle linierne i køreplanen igennem, hvor nogen af dem er blanke for at markere linieskift, skal vi først argumentere for at der kun er en konstant faktor i forskel mellem antal blanke linier og slutstationer, og afgange ialt. Den mindste toglinie der kan forekomme er på to stationer, og herefter kommer en blank linie, det vil sige at n a mindst vil være en tredjedel af liniene i køreplanen. Vi ved at følgende sammenhæng er gyldig: O(3 n a ) O(n a log n a ) Da der ikke er løkker i TextLoader klassen, kan der kun opstå problemer i whileløkken i linie 41 i Rute. Da der ikke er noget inden i løkken der gøres mere end én gang for hver linie i filen, er der ikke problemer med at overholde kravet i denne del. 5.1.2 Interne kanter ArrayListens indbyggede sorterings algoritme er i API en[1] under Collecions.sort opgivet til: The sorting algorithm is a modified mergesort (in which the merge is 12

5.2. SØGNINGEN KAPITEL 5. KØRETIDS ANALYSE omitted if the highest element in the low sublist is less than the lowest element in the high sublist). This algorithm offers guaranteed n log(n) performance. Da ArrayListen indeholder præcis n a elementer, nemlig de externe kanter, giver dette præcis O(n a log n a ). I linie 68 i Rute itereres over alle knuderne, og indeni denne løkke i linie 74 startes en ny løkke. I denne løkke betragtes alle de knuder der har større index i arraylisten. Dette giver ved første øjekast en køretid på O(n 2 a). Dette er ikke tilfældet, da while-løkken stoppes med break, hvis det ikke længere er den samme by. Dette kan jo gøres første gang vi møder en anden by, da listen er i alfabetisk rækkefølge. Vi kommer dermed kun igennem løkken k gange. Dette giver så en køretid på O(n a k). Dette skal vi så prøve at se på. Hvis nu vi multiplicerer hver station (n s ) med det maksimale antal afgange fra hver station (k), så er det højst det antal afgange der samlet er fra alle stationerne (n a ). Det er ret intuitivt, da der bare skal være én station med mindre afgange end det maksimale. Derfor kan vi omskrive i udtrykket, således at: O(n a k) = O(n s k k) = O(n s k 2 ) Da indlæsningen af køreplanen og de externe kanter kan laves i O(n a log n a ), og de interne kanter kan tilføjes i O(n s k 2 ), kan hele grafen derfor bygges op i tiden O(max{ n a log n a, n s k 2 }). 5.2 Søgningen 5.2.1 Hob en Min-hoben er implementeret parallelt med den max-hob der er udførligt beskrevet i Cormen et al. [2]. Det vil sige at køretiderne for de enkelte metoder er som i skemaet, hvor n betegner antal knuder i hoben: Metode Køretid minheapify O(log n) buildminheap O(n) heaphasmoreelements O(1) heapextractmin O(log n) decreasekey O(log n) swap O(1) Køretiden for buildminheap fremkommer, fordi man ser på halvdelen af elementerne, og disse skiftes højst én plads, for hver knude der betragtes. De logaritmiske køretider fremkommer ved at hoben maksimalt har højden log n, og de enkelte knuder dermed højst flyttes log n pladser. Værd at bemærke er derimod, at der i knuderne er der oprettet en variabel, der ved hvilket indeks knuden er placeret på. Derfor benyttes arraylistens metode indexof ikke, der benytter O(n) tid, men derimod blot et kald til knuden, der benytter O(1) tid. Køretiderne for heaphasmoreelements og swap er trivielle, da der ikke er nogen løkker eller rekursive kald, der kan forlænge køretiden, men kun kald til set og get metoder. 13

5.3. PLADSFORBRUG KAPITEL 5. KØRETIDS ANALYSE 5.2.2 Dijkstra Selve søgningen skal kunne gennemføres i tiden O((n a + n s k 2 ) log(n a )). Vi har vist at n a er antallet af externe afgange, og med god tilnærmelse antallet af knuder (i hvert fald kun adskilt af en konstant faktor). Der er også argumenteret for at n s k 2, er det maksimale antal af interne kanter. Derfor må n a + n s k 2 være det samlede antal af kanter i grafen. Dijkstra starter med at oprette en hob med alle knuder. Da hoben kan laves i køretid O(n a log n a ), er dette ikke et problem ( n a < n a + n s k 2 ). For hver knude gennemløbes while-løkken, indtil vi møder en knude der repræsenterer slut stationen, hvor den afbrydes. Worst case er jo at møde slut knuden som den sidste, så i store O beregningerne betyder dette intet, men i praksis vil det nok ofte spare en del beregninger. For hver knude kaldes heapextractmin, således er køretiden på O(n a log(n a )) efter dette skridt. For hver knude stadigvæk hentes adjacenslisten, og metoden relax kaldes på de knuder der står i den. Da alle adjacens listerne løbes igennem, er det dermed alle kanterne der kalder relax. Metoden relax laver et par simple operationer, inden den kalder decreasekey, så dennes køretid er O(log(n a )). Den samlede køretid for denne operation er O(AntalKanter log(n a )) = O((n a +n s k 2 ) log(n a )). Dette er større end den tidligere fundne køretid, så det er denne tid, som gælder indtil nu. Rute klassen overtager igen styringen, og beder Dijkstra om at aflevere resultatet. Dette sker i konstant tid, så den samlede køretid for søgningen bliver altså: O((n a + n s k 2 ) log(n a )) 5.3 Pladsforbrug Det er gennem hele programmet den samme arraylist der benyttes, og de samme adjacenslister i knuderne. Dette gør at efter grafens opbygning benyttes minimalt plads, da der bare byttes rundt i arraylisten i hobens operationer, frem for at kopiere dataene. Faktisk slettes knuderne efterhånden som de er færdigbehandlede i søgningen, og dette må siges at være ganske tilfredsstillende. 14

Kapitel 6 Afprøvning For at afprøve korrektheden er følgende testtilfælde oplagte. Hvis køreplanen fra opgaven benyttes til en søgning fra Lunderskov til Middelfart, finder programmet også korrekt svaret 42 1 Den i opgaven anbefalede DM02check test består programmet også uden problemer. 1. Ingen mulighed mellem de to byer 2. Vej gennem grafen uden skift 3. Vej med skift der er lige så lang som vej uden skift 4. Vej medskift der er 15 min. kortere end vej uden skift 5. Vej med flere skift 6. Start og slut station den samme 7. Station der ikke eksisterer 8. Vej hvor skift mindre end 5 min havde været hurtigere Resultatet af de nummererede tests er anført i skemaet nedenfor, alle sammen udført på testkøreplanen i bilag A. Test Input Forventet Reelt +/- 1 c til a Ingen vej Ingen vej Godkendt 2 b til d 60 0 60 0 Godkendt 3 a til c 120 0 120 0 Godkendt 4 a til d 165 0 eller 150 1 165 0 Godkendt 5 a til e 240 2 240 2 Godkendt 6 a til a 0 0 0 0 Godkendt 7 a til q Ingen vej Ingen vej Godkendt 8 a til c 120 0 120 0 Godkendt 15

KAPITEL 6. AFPRØVNING 6.0.1 Evaluering af kodens kvalitet Programmeringen overholder de retningslinier for god kilde, som beskrevet af Michael Kölling i Objects First... [3]. Koden er kommenteret, og effektiviseret de steder det synes oplagt. 16

Kapitel 7 Konklusion Alle kravene i kravspecifikationen er opfyldt, både til programmet og til rapporten. Det vurderes derfor at opgaven er løst tilfredsstillende i henhold til opgaveformuleringen. Teorien er beskrevet, om Dijkstras algoritme, binær hob og opbygning af grafer på en computer. Selve implementationen er forklaret, med henblik på at forklare de valg der er gjort, i forbindelse med køretid og korrekthed. Programmet er afprøvet for især korrekthed, og har bestået de opstillede tests, også den med opgaven anbefalede DM02check. Der er ikke i den forstand testet robusthed, da det forventes at input er i det beskrevne format. Det er lykkedes at få programmet til at overholde kravet til worst case køretid, som der er, mens det reelt endda vil lave færre beregninger i de fleste tilfælde. 17

Litteratur [1] http://java.sun.com/j2se/1.5.0/docs/api/index.html?java/security/codesource.html. [2] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms (2. Edition). MIT Press, 2001. [3] Michael Kölling and David J. Barnes. Objects First with JAVA - A practical introduction using BlueJ (2nd Edition). Pearson Educational Limited 2004, 2005. 18

Bilag A Testkørsels udskrifter A.1 Testkøreplanen a, 01:00 b, 02:00 b, 02:30 c, 03:00 d, 03:30 b, 02:04 c, 02:10 a, 01:30 c, 03:30 a, 02:00 d, 04:45 d, 04:00 e, 05:00 19

Bilag B Kilde kode B.1 Rute.java 1 import java. u t i l. ArrayList ; 2 import java. u t i l. C o l l e c t i o n s ; 3 / 4 This i s t h e main c l a s s f o r t h e mandatory assignment in DM02 SDU F a l l 2005 5 6 I t c o n t r o l s t h e f l o w o f information in t h e program, used to c a l c u l a t e t h e 7 s h o r t e s t time to t r a v e l from a to b in a t r a i n d e p a r t u r e plan 8 9 In t h i s c l a s s, t h e graph i s b u i l d 10 11 @author Kokken 12 / 13 public class Rute { 14 / 15 The s t a r t i n g p o i n t o f t h e a p p l i c a t i o n 16 @param args [ 0 ] t h e f i l e with t h e t r a i n d e p a r t u r e plan 17 @param args [ 1 ] t h e s t a t i o n t r a v e l i n g from 18 @param args [ 2 ] t h e s t a t i o n t r a v e l l i n g to 19 / 20 public s t a t ic void main ( S t r i n g [ ] a r g s ) { 21 ArrayList<Vertex> v e r t e x L i s t = new ArrayList<Vertex >() ; 22 23 S t r i n g t r a i n I t e n n e r a r y = "" ; 24 S t r i n g from = "" ; 25 S t r i n g to = "" ; 26 try { 27 t r a i n I t e n n e r a r y = a r g s [ 0 ] ; 28 from = a r g s [ 1 ] ; 29 to = a r g s [ 2 ] ; 30 } 31 catch ( ArrayIndexOutOfBoundsException e ) { 32 System. out. p r i n t l n ( " Problems e x i s t s on the input arguments " ) ; 33 } 34 20

B.1. RUTE.JAVA BILAG B. KILDE KODE 35 // B u i l d i n g Vertex s and E x t e r n a l edges 36 TextReader r e a d e r = new TextReader ( t r a i n I t e n n e r a r y ) ; 37 S t r i n g s t a r t = "" ; 38 S t r i n g starttime = "" ; 39 Vertex l a s t V e r t e x = null ; 40 41 while ( r e a d e r. hasmorelines ( ) ) { 42 S t r i n g t h i s L i n e = r e a d e r. getnextline ( ) ; 43 i f ( t h i s L i n e. l e n g t h ( ) > 5) { // Line must be l o n g e r than 5 to be an entry, e l s e i t s a new r o u t e 44 S t r i n g [ ] p a r t s O f S t r i n g = t h i s L i n e. s p l i t ( ", " ) ; // S p l i t s around t h e,, i s o l a t i n g t h e name 45 S t r i n g [ ] time = p a r t s O f S t r i n g [ 1 ]. s p l i t ( " : " ) ; // S p l i t s around t h e :, i s o l a t i n g minnuttes and hours 46 S t r i n g localtime = time [ 0 ]. s u b s t r i n g ( time [ 0 ]. l e n g t h ( ) 2) + " : " + time [ 1 ]. subsequence ( 0, 2 ) ; 47 S t r i n g v = p a r t s O f S t r i n g [ 0 ] + ", " + localtime ; 48 Vertex newvertex = new Vertex ( p a r t s O f S t r i n g [ 0 ], localtime ) ; 49 50 i f (! s t a r t. e q u a l s ( "" ) ) { // Adding e x t e r n a l edge, i f t h e s t a t i o n i s n t t h e l a s t on t h e r o u t e 51 l a s t V e r t e x. addedge (new Edge ( newvertex, c a l c u l a t e L e n g t h ( localtime, starttime ), 0 ) ) ; 52 } 53 i f ( p a r t s O f S t r i n g [ 0 ]. e q u a l s ( from ) ) { // I n i t i a l i z e s t h e d i s t a n c e, i f t h e s t a t i o n i s t h e s t a r t i n g one 54 newvertex. s e t D i s t a n c e ( 0 ) ; 55 } 56 v e r t e x L i s t. add ( newvertex ) ; 57 s t a r t = v ; 58 starttime = localtime ; 59 l a s t V e r t e x = newvertex ; 60 } 61 else { 62 s t a r t = "" ; 63 } 64 } 65 66 // Adding i n t e r n a l edges 67 C o l l e c t i o n s. s o r t ( ( ArrayList<Vertex >) v e r t e x L i s t ) ; // S o r t s t h e v e r t e x s according to name and d e p a r t u r e t i m e 68 for ( int i = 0 ; i < v e r t e x L i s t. s i z e ( ) 1; i ++) { // I t e r a t e s over a l l t h e v e r t e x s 69 Vertex currentvertex = ( Vertex ) v e r t e x L i s t. get ( i ) ; 70 currentvertex. s e t I n d e x ( i ) ; // S e t s t h e indexnumber 71 S t r i n g F i r s t C i t y = currentvertex. getname ( ) ; 72 starttime = currentvertex. getdeparturetime ( ) ; 73 int j = i +1; 74 while ( j<v e r t e x L i s t. s i z e ( ) ) { // Keeps us i n s i d e t h e 21

B.1. RUTE.JAVA BILAG B. KILDE KODE a r r a y L i s t 75 i f (! ( ( Vertex ) v e r t e x L i s t. get ( j ) ). getname ( ). e q u a l s ( F i r s t C i t y ) ) { 76 break ; // Stops t h e w h i l e lop, i f t h e s t a t i o n i s no l o n g e r t h e same 77 } 78 else { 79 Vertex nextvertex = ( Vertex ) v e r t e x L i s t. get ( j ) ; 80 S t r i n g nexttime = nextvertex. getdeparturetime ( ) ; 81 i f ( c a l c u l a t e L e n g t h ( nexttime, starttime ) >= 5) { // Only adds i n t e r n a l edge, i f t h e time between a r r i v a l and d e p a r t u r e i s more than 5 minnuttes 82 currentvertex. addedge (new Edge ( nextvertex, c a l c u l a t e L e n g t h ( nexttime, starttime )+15, 1) ) ; 83 } 84 } 85 j ++; 86 } 87 } 88 v e r t e x L i s t. get ( v e r t e x L i s t. s i z e ( ) 1). s e t I n d e x ( v e r t e x L i s t. s i z e ( ) 1) ; 89 90 //The d i j k s t r a a l g o r i t h m i s s t a r t e d here 91 D i j k s t r a d i j k s t r a = new D i j k s t r a ( v e r t e x L i s t, to ) ; 92 System. out. p r i n t l n ( d i j k s t r a. g e t R e s u l t ( ) ) ; 93 } 94 95 / 96 C a l c u l a t e s t h e t h e l e n g t h o f t h e time i n t e r v a l between t h e two parameters 97 98 @param a r r i v a l The a r r i v a l time, as a s t r i n g in t h e format "hh :mm" 99 @param d e p a r t u r e The d e p a r t u r e time, as a s t r i n g in t h e format "hh :mm" 100 / 101 private static int c a l c u l a t e L e n g t h ( S t r i n g a r r i v a l, S t r i n g departure ) 102 { 103 i f ( c a l c u l a t e R e l a t i v e T i m e ( a r r i v a l ) c a l c u l a t e R e l a t i v e T i m e ( departure ) < 0) { 104 return ( c a l c u l a t e R e l a t i v e T i m e ( a r r i v a l ) c a l c u l a t e R e l a t i v e T i m e ( departure ) ) +1440; 105 } 106 return c a l c u l a t e R e l a t i v e T i m e ( a r r i v a l ) c a l c u l a t e R e l a t i v e T i m e ( departure ) ; 107 } 108 109 / 110 C a l c u l a t e s t h e number o f minutes from 00:00 to t h e time i n p u t t e t 111 112 @param time t h e time, as a s t r i n g in t h e format "hh :mm" 113 / 114 private static int c a l c u l a t e R e l a t i v e T i m e ( S t r i n g time ) 22

B.2. TEXTREADER.JAVA BILAG B. KILDE KODE 115 { 116 int hours = I n t e g e r. p a r s e I n t ( time. s u b s t r i n g ( time. l e n g t h ( ) 5, time. l e n g t h ( ) 3) ) ; 117 int minutes = I n t e g e r. p a r s e I n t ( time. s u b s t r i n g ( time. l e n g t h ( ) 2, time. l e n g t h ( ) ) ) ; 118 return hours 60 + minutes ; 119 } 120 } B.2 TextReader.java 1 import java. i o. BufferedReader ; 2 import java. i o. FileNotFoundException ; 3 import java. i o. FileReader ; 4 import java. i o. IOException ; 5 / 6 Basic c l a s s f o r t e x t input, 7 O b j e c t s o f t h i s c l a s s i s ment to read a f i l e once only, 8 but one l i n e at a time. 9 10 @author Kokken 11 / 12 public class TextReader { 13 14 private S t r i n g nextline = null ; 15 private BufferedReader r e a d e r ; 16 / 17 Constructor f o r t h e TextReader c l a s s, 18 I n i t i a l i z e s t h e reading o f t h e f i l e which i s s p e c i f i e d 19 20 @param f i l e n a m e The f i l e to read 21 / 22 public TextReader ( S t r i n g f i l e n a m e ) 23 { 24 try { 25 r e a d e r = new BufferedReader (new FileReader ( f i l e n a m e ) ) ; 26 nextline = r e a d e r. readline ( ) ; 27 } 28 catch ( FileNotFoundException e ) { 29 System. out. p r i n t l n ( " F i l e wasn t found! " ) ; 30 } 31 catch ( IOException e ) { 32 System. out. p r i n t l n ( " Something went wrong i n reading the f i l e! " ) ; 33 } 34 } 35 36 / 37 Method to determine, whether t h e f i l e has any more l i n e s in i t 38 I f not, t h e f i l e i s c l o s e d p r o p e r l y 39 / 40 public boolean hasmorelines ( ) 41 { 23

B.3. VERTEX.JAVA BILAG B. KILDE KODE 42 i f ( nextline!= null ) { 43 return true ; 44 } 45 else { 46 try{ 47 r e a d e r. c l o s e ( ) ; 48 } 49 catch ( IOException e ) { 50 System. out. p r i n t l n ( " Something went wrong i n reading the f i l e! " ) ; 51 } 52 catch ( NullPointerException e ) { 53 System. out. p r i n t l n ( " Closing e r r o r, f i l e didn t e x i s t! " ) ; 54 } 55 return f a l s e ; 56 } 57 } 58 59 / 60 Method to g e t t h e next l i n e from t h e f i l e 61 Should only be c a l l e d, i f a l r e a d y checked 62 i f t h e f i l e has more l i n e s in i t. 63 / 64 public S t r i n g getnextline ( ) 65 { 66 try { 67 S t r i n g l a s t L i n e = nextline ; 68 nextline = r e a d e r. readline ( ) ; 69 return l a s t L i n e ; 70 } 71 catch ( IOException e ) { 72 System. out. p r i n t l n ( " Something went wrong i n reading the f i l e! " ) ; 73 } 74 return null ; 75 } 76 } B.3 Vertex.java 1 import java. u t i l. LinkedList ; 2 / 3 This c l a s s i s used in t h e DM02 p r o j e c t o f f a l l 2005. 4 I t i s a c l a s s, used to s t o r e information o f v e r t i c e s o f 5 a d i r e c t e d graph. 6 7 @author Kokken // Jacob Aae Mikkelsen 8 / 9 public c l a s s Vertex implements Comparable { 10 11 private S t r i n g name ; 12 private S t r i n g departuretime ; 24

B.3. VERTEX.JAVA BILAG B. KILDE KODE 13 private int d i s t a n c e ; 14 private int t r a i n S h i f t s ; 15 private int arrayindex ; 16 private LinkedList <Edge> a d j a c e n t ; 17 / 18 Constructor o f c l a s s Vertex. 19 / 20 public Vertex ( S t r i n g name, S t r i n g departure ) 21 { 22 this. name = name ; 23 this. departuretime = departure ; 24 this. d i s t a n c e = 100000000; 25 this. t r a i n S h i f t s = 0 ; 26 this. arrayindex = 0 ; 27 a d j a c e n t = new LinkedList <Edge >() ; 28 } 29 30 / 31 Method to add an edge to t h e adjacency l i s t o f t h e v e r t e x 32 / 33 public void addedge ( Edge newedge ) 34 { 35 a d j a c e n t. add ( newedge ) ; 36 } 37 38 / 39 Returns t h e name o f t h e s t a t i o n in t h e Vertex 40 / 41 public S t r i n g getname ( ) 42 { 43 return name ; 44 } 45 46 / 47 Returns t h e d e p a r t u r e time o f t h e Vertex 48 / 49 public S t r i n g getdeparturetime ( ) 50 { 51 return departuretime ; 52 } 53 54 / 55 Returns t h e d i s t a n c e from t h e s t a r t i n g s t a t i o n to t h i s v e r t e x 56 / 57 public int g e t D i s t a n c e ( ) 58 { 59 return d i s t a n c e ; 60 } 61 62 / 63 Returns t h e number o f t r a i n s h i f t s on t h e way to t h i s v e r t e x 64 / 65 public int g e t S h i f t s ( ) 66 { 25

B.3. VERTEX.JAVA BILAG B. KILDE KODE 67 return t r a i n S h i f t s ; 68 } 69 70 / 71 Returns t h e index o f t h e Vertex in t h e a r r a y L i s t 72 / 73 public int getindex ( ) 74 { 75 return arrayindex ; 76 } 77 78 79 / 80 S e t s t h e index o f v e r t e x in t h e a r r a y L i s t 81 / 82 public void s e t I n d e x ( int newindex ) 83 { 84 arrayindex = newindex ; 85 } 86 87 / 88 Returns t h e l i s t o f edges, p o i n t i n g to t h e a d j a c e n t v e r t e x s 89 / 90 public LinkedList getadjacent ( ) 91 { 92 return a d j a c e n t ; 93 } 94 95 / 96 S e t s t h e d i s t a n c e from t h e s t a r t i n g s t a t i o n to t h e v e r t e x 97 / 98 public void s e t D i s t a n c e ( int amount ) 99 { 100 d i s t a n c e = amount ; 101 } 102 103 / 104 S e t s t h e number o f t r a i n s h i f t s from t h e s t a r t i n g s t a t i o n to t h i s v e r t e x 105 / 106 public void s e t T r a i n S h i f t ( int s h i f t s ) 107 { 108 t r a i n S h i f t s = s h i f t s ; 109 } 110 111 / 112 Overwrites t h e t o S t r i n g method from t h e Object c l a s s 113 r e t u r n s t h e name and d e p a r t u r e time, only s e p a r a t e d with a, 114 / 115 public S t r i n g t o S t r i n g ( ) 116 { 117 118 return name + ", " + departuretime ; 119 } 120 26

B.4. EDGE.JAVA BILAG B. KILDE KODE 121 / 122 Compares two v e r t i c e s, only by t h e i r S t r i n g r e p r e s e n t a t i o n 123 / 124 public int compareto ( Object arg0 ) { 125 S t r i n g t h i s V e r t e x = this. t o S t r i n g ( ) ; 126 S t r i n g othervertex = arg0. t o S t r i n g ( ) ; 127 return t h i s V e r t e x. compareto ( othervertex ) ; 128 } 129 } B.4 Edge.java 1 / 2 This c l a s s i s used in t h e DM02 p r o j e c t o f f a l l 2005. 3 I t i s an implementation o f t h e information s t o r e d in 4 edges o f a d i r e c t e d graph 5 6 @author Kokken // Jacob Aae Mikkelsen 7 / 8 public class Edge { 9 private Vertex to ; 10 private int l e n g t h ; 11 private int t r a i n S h i f t ; 12 13 / 14 c o n s t r u c t o r o f c l a s s Edge 15 / 16 public Edge ( Vertex to, int l e n g t h, int t r a i n S h i f t ) 17 { 18 this. to = to ; 19 this. l e n g t h = l e n g t h ; 20 this. t r a i n S h i f t = t r a i n S h i f t ; 21 } 22 23 / 24 r e t u r n s t h e v e r t e x, t h e edge i s p o i n t i n g towards 25 / 26 public Vertex getto ( ) 27 { 28 return to ; 29 } 30 31 / 32 r e t u r n s t h e l e n g t h o f t h e edge 33 / 34 public int getlength ( ) 35 { 36 return l e n g t h ; 37 } 38 39 / 40 r e t u r n s number o f t r a i n s h i f t s 41 / 27

B.5. DIJKSTRA.JAVA BILAG B. KILDE KODE 42 public int g e t T r a i n S h i f t ( ) 43 { 44 return t r a i n S h i f t ; 45 } 46 47 / 48 Overwrites t h e t o S t r i n g method o f Object 49 / 50 public S t r i n g t o S t r i n g ( ) 51 { 52 return to + ", " + l e n g t h ; 53 } 54 } B.5 Dijkstra.java 1 import java. u t i l. ArrayList ; 2 import java. u t i l. I t e r a t o r ; 3 / 4 This c l a s s i s used in t h e DM02 p r o j e c t o f f a l l 2005. 5 I t i s an implementation o f most o f t h e D i j k s t r a a l g o r i t h m 6 @author Kokken // Jacob Aae Mikkelsen 7 / 8 public class D i j k s t r a 9 { 10 private Vertex f a s t e s t R o u t e = null ; 11 private Heap priorityqueue ; 12 / 13 Constructor o f t h e D i j k s t r a c l a s s 14 15 Uses t h e D i j k s t r a a l g o r i t h m to f i n d t h e s h o r t e s t path t h r o u g t t h e graph, 16 r e p r e s e n t e d in t h e ArrayList o f V e r t i c e s. The l i s t s h o u l d a l r e a d y be i n i t i a l i z e d 17 to s t a r t from a s t a t i o n, and t h i s implementation only s t o r e s information about 18 t h e d e s t i n a t i o n to save memory space 19 / 20 public D i j k s t r a ( ArrayList<Vertex> input, S t r i n g to ) 21 { 22 p riorityqueue = new Heap ( input ) ; 23 while ( priorityqueue. heaphasmoreelements ( ) ) { 24 Vertex u = p r i orityqueue. heapextractmin ( ) ; 25 i f ( u. getname ( ). e q u a l s ( to ) ) { 26 f a s t e s t R o u t e = u ; //The f i r s t h i t, which i s t h e f a s t e s t, we re done 27 break ; 28 } 29 I t e r a t o r i t = u. getadjacent ( ). i t e r a t o r ( ) ; 30 while ( i t. hasnext ( ) ) { 31 Edge w = ( Edge ) i t. next ( ) ; 32 r e l a x ( u, w. getto ( ), w. getlength ( ), w. g e t T r a i n S h i f t ( ) ) ; 28

B.6. HEAP.JAVA BILAG B. KILDE KODE 33 } 34 } 35 } 36 37 / 38 Returns t h e s h o r t e s t d i s t a n c e found 39 / 40 public S t r i n g g e t R e s u l t ( ) 41 { 42 i f ( f a s t e s t R o u t e!= null ) { 43 return "" + ( f a s t e s t R o u t e. g e t D i s t a n c e ( ) (15 f a s t e s t R o u t e. g e t S h i f t s ( ) ) ) + " " + f a s t e s t R o u t e. g e t S h i f t s ( ) ; 44 } 45 else { 46 return "Der er ingen måde at komme frem på! " ; 47 } 48 } 49 50 / 51 P r i v a t e method used by t h e d i j k s t r a a l g o r i t h m to update t h e d i s t a n c e s 52 o f t h e v e r t i c e s, and i t updates t h e queue, so t h e next element i s t h e 53 c o r r e c t one. 54 / 55 private void r e l a x ( Vertex u, Vertex v, int weight, int s h i f t s ) 56 { 57 i f ( v. g e t D i s t a n c e ( ) > u. g e t D i s t a n c e ( ) + weight ) { 58 v. s e t D i s t a n c e ( u. g e t D i s t a n c e ( ) + weight ) ; 59 v. s e t T r a i n S h i f t ( u. g e t S h i f t s ( ) + s h i f t s ) ; 60 p riorityqueue. decreasekey ( v ) ; 61 } 62 } 63 } B.6 Heap.java 1 import java. u t i l. ArrayList ; 2 / 3 This c l a s s i s used in t h e DM02 p r o j e c t o f f a l l 2005. 4 I t i s an implementation o f a heap, used as a p r i o r i t y queue 5 6 @author Kokken // Jacob Aae Mikkelsen 7 / 8 public class Heap { 9 10 private ArrayList <Vertex> heap ; 11 private int numberofelements ; 12 / 13 I n i t i a l i z e s t h e heap. 14 / 15 public Heap ( ArrayList <Vertex> A) 16 { 17 heap = A; 18 numberofelements = A. s i z e ( ) ; 29

B.6. HEAP.JAVA BILAG B. KILDE KODE 19 buildminheap ( ) ; 20 } 21 22 / 23 s o r t s t h e element i n t o i t s p l a c e in t h e heap, 24 assuming t h e lower t r e e s i s in c o r r e c t order 25 / 26 private void minheapify ( int index ) // Heap numbered 27 { 28 int i = index 1 ; // Array numbered 29 int l = 2 index 1 ; // Array numbered 30 int r = 2 index ; // Array numbered 31 int s m a l l e s t ; // Array numbered 32 33 i f ( l < numberofelements && heap. get ( l ). g e t D i s t a n c e ( ) < heap. get ( i ). g e t D i s t a n c e ( ) ) { 34 s m a l l e s t = l ; 35 } 36 else { 37 s m a l l e s t = i ; 38 } 39 i f ( r < numberofelements && heap. get ( r ). g e t D i s t a n c e ( ) < heap. get ( s m a l l e s t ). g e t D i s t a n c e ( ) ) { 40 s m a l l e s t = r ; 41 } 42 i f ( s m a l l e s t!= i ) { 43 swap ( s m a l l e s t, i ) ; // Array numbered 44 minheapify ( s m a l l e s t +1) ; 45 } 46 } 47 48 / 49 Converts an unsorted l i s t to a l i s t with heap p r o p e r t i e s 50 / 51 public void buildminheap ( ) 52 { 53 for ( int i = ( int ) Math. f l o o r ( numberofelements /2) ; i > 0 ; i ) { 54 minheapify ( i ) ; //Heap numbered 55 } 56 } 57 58 / 59 Returns true, i f t h e r e i s more elements in t h e heap 60 / 61 public boolean heaphasmoreelements ( ) 62 { 63 i f ( numberofelements > 0) { 64 return true ; 65 } 66 else { 67 return f a l s e ; 30

B.6. HEAP.JAVA BILAG B. KILDE KODE 68 } 69 } 70 71 / 72 Returns t h e s m a l l e s t element in t h e heap, 73 s o r t i n g t h e remaining elements so t h e heap p r o p e r t i e s 74 i s maintained 75 / 76 public Vertex heapextractmin ( ) 77 { 78 Vertex min = heap. get ( 0 ) ; 79 heap. s e t ( 0, heap. get ( numberofelements 1) ) ; 80 heap. get ( 0 ). s e t I n d e x ( 0 ) ; 81 heap. s e t ( numberofelements 1, null ) ; // D e l e t e s t h e l a s t entry, j u s t copied to t h e f i r s t 82 numberofelements ; 83 minheapify ( 1 ) ; // Heap numbered 84 return min ; 85 } 86 87 / 88 S o r t s t h e element i n t o i t s c o r r e c t p l a c e in t h e heap s t r u c t u r e, 89 a f t e r change has been made to t h e w e i g h t o f t h e eement 90 / 91 public void decreasekey ( Vertex v ) 92 { 93 int index = v. getindex ( ) ; // Array numbered 94 int parentindex = ( int ) Math. f l o o r ( ( index +1) /2) 1; // Array numbered 95 while ( index > 0 && ( heap. get ( parentindex ). g e t D i s t a n c e ( ) > heap. get ( index ). g e t D i s t a n c e ( ) ) ) { 96 swap ( index, parentindex ) ; 97 index = parentindex ; 98 parentindex = ( int ) Math. f l o o r ( ( index +1) /2) 1; 99 } 100 } 101 102 / 103 Changes t h e l o c a t i o n o f t h e two elements in t h e array 104 / 105 private void swap ( int index1, int index2 ) 106 { 107 Vertex temp1 = heap. g e t ( index1 ) ; // Array numbered 108 Vertex temp2 = heap. g e t ( index2 ) ; // Array numbered 109 temp1. s e t I n d e x ( index2 ) ; 110 temp2. s e t I n d e x ( index1 ) ; 111 heap. s e t ( index2, temp1 ) ; 112 heap. s e t ( index1, temp2 ) ; 113 } 114 } 31