====== Øvelse: Implementér Dijkstra's Algoritme ====== === Øvelsesbeskrivelse === I denne øvelse skal I implementere Dijkstra's algoritme i Processing til at finde korteste afstande i en graf, som er repræsenteret med en **adjacency matrix**. (nabo matrice) **Opgaver:** - Tegn først grafen på papir ud fra en adjacency matrix, som I selv skal definere i koden. - I skal opdele programmet i funktioner, der hver især har et klart ansvar: - Initialisering af søgealgoritmens arrays (afstande og besøgte noder) - Selve Dijkstra-algoritmen - Funktion til at finde den **næste node** med kortest kendt afstand - Udskrivning af resultaterne i et overskueligt format - Hjælpefunktion til at konvertere nodeindeks til navne (fx 0 → 'A') (optionel men rar at have:-)) - Jeg har lavet en skabelon, hvor funktionerne er tomme. Jeres opgave er at implementere funktionerne. - Test jeres løsning med forskellige grafer og startnoder. ---- === Hvad er en adjacency matrix? === En **adjacency matrix** er en måde at repræsentere en graf (netværk af noder og kanter) på ved hjælp af et to-dimensionel array (et gitter af tal). * Hver række og kolonne svarer til en node i grafen. * Værdien i ''matrix[c][r]'' viser vægten (afstand, pris eller omkostning) af kanten mellem node **c** og node **r**. * Hvis der ikke er registreret nogen forbindelse mellem to noder angives dette typisk med et stort tal (fx "∞" eller Integer.MAX_VALUE). * Diagonal-elementerne (sammen med sig selv) er normalt 0, fordi afstanden fra en node til sig selv er nul. ==== Eksempel på adjacency matrix for 5 noder (A til E) ==== A B C D E A [0, 4, ∞, 2, ∞] B [4, 0, 3, ∞, ∞] C [∞, 3, 0, 1, 6] D [2, ∞, 1, 0, 3] E [∞, ∞, 6, 3, 0] I matrix’en ovenfor betyder fx tallet 4 i position (A,B), at kanten fra node A til node B har vægten 4, mens "∞" betyder, at forbindelsen ikke er registreret endnu eller ukendt. ---- ===== Skabelon med funktioner ===== final int INF = Integer.MAX_VALUE; int[][] matrix; // Nabo matrice int nodeCount; // antallet af nodes int[] distances; // afstande fra startNode. boolean[] visited; // liste over besøgte nodes. (true, hvis besøgt) int[] parent; // liste int startNode; void setup() { // Initialiser variabler her, fx matrix, nodeCount og startNode initSearch(); runDijkstra(startNode); printResults(); } // Initialiserer distances- og besøgte nodes void initSearch() { // - Sæt startnode afstand til 0, og alle andre afstande til ∞. // - Marker alle nodes som __ikke besøgte__. } // Kører Dijkstra's algoritme void runDijkstra(int startNode) { // TODO: Implementér algoritmen } // Finder næste node med kortest kendt afstand som _ikke_ er besøgt int minDistanceNode() { // returneres der -1, betyder det, at enten er alle noder besøgt, eller at de resterende noder ikke er forbundne med startnoden return -1; // Midlertidig return } // Printer resultatet med afstande fra startnode void printResults() { // TODO: Implementér udskrivning. // Udskrivning af korteste vej. } // Hjælpefunktion der giver et bogstavnavn til node ud fra index (fx 0 -> A) String nodeName(int index) { // TODO: Implementér konvertering fra index til navn return ""; } ---- ===== Hints og eksempler på implementering ===== ++++ InitSearch | Initialiser distances til INF for alle noder Sæt distances[start] til 0 Initialiser visited til false for alle noder Initialiser parent til -1 for alle noder (ingen parent endnu) ++++ ++++ FindMinDistance | Sæt min til INF Sæt minIndex til -1 For hver node v: Hvis visited[v] == false og distances[v] <= min: min = distances[v] minIndex = v Returner minIndex ++++ ++++ RunDijkstra | Kald InitSearch(start) Gentag for nodeCount gange: u = FindMinDistance() Hvis u == -1: Stop løkken visited[u] = true For hver node v: Hvis visited[v] == false og der findes kant mellem u og v: Hvis distances[u] + graph[u,v] < distances[v]: distances[v] = distances[u] + graph[u,v] parent[v] = u // Opdater parent for v ++++ ++++ PrintResults | Skriv "Korteste afstande fra node " + NodeName(start) + ":" For hver node v: Hvis distances[v] == INF: distStr = "∞" Ellers: distStr = distances[v].ToString() Skriv NodeName(start) + " → " + NodeName(v) + ": " + distStr ++++ ++++ PrintPath | Funktion PrintPath(parent, start, end): Hvis end == start: Udskriv NodeName(start) Stop Hvis parent[end] == -1: Udskriv "Ingen sti fra " + NodeName(start) + " til " + NodeName(end) Stop PrintPath(parent, start, parent[end]) Udskriv " → " + NodeName(end) ++++ ---- ==== Test af Algoritme ==== Når du er færdig, kan du teste koden ved at initialisere din matrix, nodeCount og startNode i setup(), og køre programmet. (test din algoritme på nedestående matrice) matrix = new int[][] { // A B C D E { 0, 6, INF, 1, INF}, // A { 6, 0, 5, 2, 2 }, // B {INF, 5, 0, INF, 5 }, // C { 1, 2, INF, 0, 1 }, // D {INF, 2, 5, 1, 0 } // E }; Korteste sti fra A til C er: A -> D -> E -> C Afstand: 7