Download - Dijkstra Floyd

Transcript

ANALISIS ALGORITMA SHORTEST PATH DIJKSTRA & FLOYD

KELOMPOK 3 :1. PRASTOWO HADI 2. PARAMITHA A 3. NOVITA R 4. M.FARIS RUSYDI 5. ALFINA SHOFA PA / 9927 PA / 9980 04 / 181863 / PA / 10339 PA / 9759 PA / 10674

SHORTEST PATH (LINTASAN TERPENDEK) Persoalan lintasan terpendek yaitu menemukan lintasan terpendek antara dua atau beberapa simpul lebih yang berhubungan. Biasanya direpresentasikan dalam bentuk graf berbobot (weighted graph), yaitu graf yang setiap sisinya diberikan suatu nilai atau bobot. Bobot pada sisi graf dapat menyatakan jarak antar kota, waktu pengiriman pesan, ongkos pembangunan, dan sebagainya. Contoh-contoh terapan pencarian lintasan terpendek: 1. Misalkan simpul pada graf menyatakan kota, sedangkan sisi menyatakan jalan yang menghubungkan dua buah kota. Bobot sisi graf dapat menyatakan jarak antara dua buah kota atau rata-rata waktu tempuh antara dua buah kota. Apabila terdapat lebih dari satu lintasan dari kota A ke kota B, maka persoalan lintasan terpendek di sini adalah menentukan jarak terpendek atau waktu tersingkat dari kota A ke kota B. 2. Misalkan simpul pada graf menyatakan terminal komputer atau simpul komunikasi dalam suatu jaringan, sedangkan sisi menyatakan saluran komunikasi yang menghubungkan dua buah terminal. Bobot pada graf dapat menyatakan biaya pemakaian saluran komunikasi antara dua buah terminal, jarak antara dua buah terminal, atau waktu pengiriman pesan (message) antara dua buah terminal. Persoalan lintasan terpendek di sini adalah menentukan jalur komunikasi terpenek antara dua buah terminal komputer. Lintasan terpendek akan menghemat waktu pengiriman pesan dan biaya komunikasi. Beberapa macam persoalan lintasan terpendek antara lain: a. Lintasan terpendek antara dua buah simpul tertentu (a pair shortest path). b. Lintasan terpendek antara semua pasangan simpul (all pairs shortest path). c. Lintasan terpendek dari simpul tertentu ke semua simpul yang lain (single-source shortest path). d. Lintasan terpendek antara dua buah simpul yang melalui beberapa simpul tertentu

(intermediate shortest path). ALGORITMA SHORTEST PATH Dijkstra Bellman-Ford A-star Floyd-Warshall A. ALGORITMA DIJKSTRA Ditemukan oleh Edsger Wybe Dijkstra (profesor, programmer, dan

matematikawan) dari Belanda. Input graf berarah dan berbobot (V,E), dimana : V = daftar titik (node/vertex) E = daftar sisi (edge). Jumlah bobot sisi-sisi pada sebuah jalur adalah bobot jalur tersebut. Sisi pada E haruslah berbobot positif Merupakan salah satu varian dari Algoritma Greedy Sifat : sederhana dan lempang (straightforward). Greedy tamak / rakus, hanya memikirkan solusi terbaik yang akan diambil pada setiap langkah tanpa memikirkan konsekuensi ke depan. Prinsip : Ambillah apa yang bisa Anda dapatkan saat ini (take what you can get now!), dan keputusan yang telah diambil pada setiap langkah tidak akan bisa diubah kembali Berupaya membuat pilihan nilai optimum lokal pada setiap langkah dan berharap agar nilai optimum lokal ini mengarah kepada nilai optimum global.

PSEUDOCODE Algoritma ini mencari panjang lintasan terpendek dari verteks a ke z dalam sebuah graf berbobot tersambung. Bobot dari rusuk (i,j) adalah w(i,j)>0 dan label verteks x adalah L(x). Hasilnya, L(z) merupakan panjang lintasan terpendek dari a ke z. Masukan : Sebuah graf berbobot tersambung dengan bobot positif. Verteks a sampai z. Keluaran : L(z), panjang lintasan terpendek dari a ke z,jalur lintasan terpendek.procedure dijkstra (w,a,z,L) L(a) := 0 for semua verteks x a do L(x) := T := himpunan semua verteks // T adalah himpunan verteks yang panjang terpendeknya dari a belum ditemukan while zT do begin pilih vT dengan minimum L(v) T:=T-{v} for setiap xT di samping v do L(x):=min{L(x), L(v)+w(v,x)} end end dijkstra

Algoritma di atas digunakan untuk mencari single source shortest path. Untuk intermediate shortest path, hanya perlu mengganti pada bagian :while zT

dengan while T0

KOMPLEKSITAS WAKTU Kompleksitas waktu untuk Single Source Shortest Path adalah O(V), sedangkan kompleksitas waktu untuk Intermediate Shortest Path adalah O(V2)

Best Case Jika suatu verteks (a) hanya memerlukan satu langkah untuk mencapai tujuan (z) dan hasilnya optimum pada Single Source Shortest Path Worst case Jika suatu verteks (a) harus melewati semua verteks untuk mencapai tujuan (z) pada Intermediate Shortest Path Jadi kompleksitas waktu untuk Algoritma Dijkstra ini adalah O(V) g(n) O(V2) KOMPLEKSITAS MEMORY Kompleksitas memory dari Algoritma Dijkstra ini adalah O(V2+2V) karena kita membutuhkan sebuah matriks untuk graphnya dan 2 kali banyaknya verteks untuk menyimpan T(himpunan verteks) dan v. KEMUDAHAN Algoritma yang lebih efisien Implementasinya lebih sukar Array, list agak sulit karena harus menggunakan list Intermediate Source Path lebih mudah karena tinggal mengecek T 0 daripada Single Source Shortest Path yang harus mengecek apakah z berada dalam himpunan T. Karena jika diimplementasikan dengan bahasa pemrograman yang belum bisa langsung mengecek zT, akan terasa sangat sulit. Tetapi karena kami menggunakan bahasa pemrograman C# yang sudah bisa langsung mengenali kondisi itu, maka kemudahannya adalah sama. B. ALGORITMA FLOYD

Input graf berarah dan berbobot (V,E), dimana : V = daftar titik (node/vertex) E = daftar sisi (edge). Jumlah bobot sisi-sisi pada sebuah jalur adalah bobot jalur tersebut. Sisi pada E diperbolehkan memiliki bobot negatif, akan tetapi tidak diperbolehkan bagi graf ini untuk memiliki siklus dengan bobot negatif. Algoritma ini menghitung bobot terkecil dari semua jalur yang menghubungkan sebuah pasangan titik, dan melakukannya sekaligus untuk semua pasangan titik. Salah satu varian dari pemrograman dinamis Memandang solusi yang akan diperoleh sebagai suatu keputusan yang saling terkait. Solusi-solusi dibentuk dari solusi yang berasal dari tahap sebelumnya dan ada kemungkinan solusi lebih dari satu. Prinsip prinsip optimalitas, yaitu jika solusi total optimal, maka bagian solusi sampai suatu tahap (misalnya tahap ke-i) juga optimal. Greedy Vs Dynamic Programming Greedy keputusan yang diambil pada tiap tahap hanya berdasarkan pada informasi yang terbatas sehingga nilai optimum yang diperoleh pada saat itu, tidak memikirkan konsekuensi yang terjadi seandainya memilih suatu keputusan pada suatu tahap. Dalam beberapa kasus, algoritma greedy gagal memberikan solusi terbaik. Dynamic Programming mencoba untuk memberikan solusi yang memiliki pemikiran terhadap konsekuensi yang ditimbulkan dari pengambilan keputusan pada suatu tahap. Pemrograman dinamis mampu mengurangi pengenumerasian keputusan yang tidak mengarah ke solusi. PSEUDOCODE

Dasar algoritma: Asumsikan semua simpul graf berarah G adalah V = {1, 2, 3, 4, ..., n}, perhatikan subset {1, 2, 3, ..., k}. Untuk setiap pasangan simpul i, j pada V, perhatikan semua lintasan dari i ke j dimana semua simpul pertengahan diambil dari {1, 2, ..., k}, dan p adalah lintasan berbobot minimum diantara semuanya. Algoritma ini mengeksploitasi relasi antara lintasan p dan lintasan terpendek dari i ke j dengan semua simpul pertengahan berada pada himpunan {1, 2, ..., k-1}. Relasi tersebut bergantung pada apakah k adalah simpul pertengahan pada lintasan p. Implementasi algoritma dalam pseudocode: (Graf direpresentasikan sebagai matrix keterhubungan, yang isinya ialah bobot / jarak sisi yang menghubungkan tiap pasangan titik, dilambangkan dengan indeks baris dan kolom) (Ketiadaan sisi yang menghubungkan sebuah pasangan dilambangkan dengan Takhingga)function fw(int[1..n,1..n] graph) { // Inisialisasi var int[1..n,1..n] jarak := graph var int[1..n,1..n] sebelum for i from 1 to n for j from 1 to n if jarak[i,j] < Tak-hingga sebelum[i,j] := i // Perulangan utama pada algoritma for k from 1 to n for i from 1 to n for j from 1 to n if jarak[i,j] > jarak[i,k] + jarak[k,j] jarak[i,j] = jarak[i,k] + jarak[k,j] sebelum[i,j] = sebelum[k,j]

return jarak return path }

KOMPLEKSITAS WAKTU Algoritma ini berjalan dengan waktu O(V3) karena dalam algoritmanya kita lihat bahwa terdapat 3 iterasi / perulangan. Sebenarnya IF-nya terlalu banyak karena ada pasangan jarak yang seharusnya tidak perlu dihitung lagi. Misalnya jarak terpendek dari kota Jogja ke Jogja itu sendiri. Tidak mungkin jarak terpendeknya harus melewati kota Semarang terlebih dahulu. Pastilah jarak terpendeknya adalah 0. Tapi hal itu bisa diabaikan, karena jika itu dilakukan pun, kompleksitas waktunya tetap O(V3). KOMPLEKSITAS MEMORY Kompleksitas memory dari algoritma Floyd ini adalah O(2V2) karena kita membutuhkan 2 matriks untuk graph dan KEMUDAHAN Algoritmanya sederhana dan mudah diimplementasikan Hanya menggunakan array sehingga Floyd lebih mudah dibandingkan Dijkstra.

STUDI KASUS 0100090000037800000002001c00000000000400000003010800050000000b020000 0000050000000c020f066007040000002e0118001c000000fb021000070000000000bc02 000000000102022253797374656d0006600700007cc8110072edc630606a1b000c020000 60070000040000002d01000004000000020101001c000000fb02c4ff0000000000009001 000000000440001254696d6573204e657720526f6d616e00000000000000000000000000 00000000040000002d010100050000000902000000020d000000320a360000000100040 0000000005e070d0620001b00040000002d010000030000000000 Lintasan terpendek dari kota A ke kota G? Berapakah jaraknya? Waktu pemrosesan / pengerjaannya? Penentuan lintasan terpendek dengan Algoritma Dijkstra cara manual : L(a):= 0 L(x):= T = {a,b,c,d,e,f,g} z = {g} while z T pilih v T dengan minimum L(v) L(v) adalah jarak dari titik v ke a (titik awal) L(a) = 0; L(b) = 3 ; L(c) = 9; L(d) = ; L(e) = ; L(f) = ; L(g) = ; v = {a} // karena L(a) mempunyai nilai yang paling kecil / minimum. T := T {a} = {b,c,d,e,f,g} For setiap x T di samping v x = {b,c} // titik yang terdekat dengan titik a adalah b dan c L(b) = 3 ; L(c) = 9; v = {a,b} T:= T {b} = {c,d,e,f,g}

x = {e,d } L(e) = min { L(e), L(b) + w(b,e) } // w(b,e) = bobot dari titik b ke e = min { , 3 + 1 } = 4 L(d) = min ( L(d), L(b) + w(b,d) } = min { , 3 + 7 } = 10 v = {a,b,e} T := T {e} = { c,d,f,g} x = {c,d,f} L(c) = min { L(c), L(e) + w(e,c) } = min { 9, 4+4 } = 8 L(d) = min { L(d), L(e) + w(e,d) } = min { 10, 4+5 } = 9 L(f) = min { L(f), L(e) + w(e,f) } = min { , 4+9 } = 13 v = {a,b,e,c} T := T {c} = {d,f,g} x = {d} L(d) = min { L(d), L(c) + w(c,d) } = min { 9, 8+7 } = 9 v = {a,b,e,c,d} T := T {d} = { f.g} x = {f,g} L(f) = min { L(f), L(d) + w(d,f) } = min { 13, 9+2 } = 11 L(g) = min { L(g), L(d) + w(d,g) } = min { , 9+8 } = 17 v = {a,b,e,c,d,f} T := T {f} = { g} x = {g} L(g) = min { L(g), L(f) + w(f,g) } = min { 17, 11+4 } = 15

v = {a,b,e,c,d,f,g} T := T {g} = {} end // z T Perlu diketahui bahwa v bukanlah merupakan jalur lintasannya. Coba saja hitung jaraknya jika v merupakan jalur terpendeknya. Akan didapat hasil 21. Dibandingkan dengan jarak minimum sebenarnya yang didapat dari hasil penghitungan di atas akan jelas berbeda. Dari penghitungan, didapat jarak 15. Perhatikan saja nilai-nilai minimum yang terbentuk pada setiap tahap. Pada saat terbentuk jalur a b e c, jarak minimumnya adalah sama jika dihitung secara manual yaitu 3+1+4=8. Tetapi pada tahap berikutnya, saat melewati titik d, jarak minimumnya adalah berbeda. Jika jalurnya melewati c, a b e c d, jaraknya adalah 15, sedangkan seharusnya dari penghitungan didapat nilai 9. Berarti c tidak termasuk dalam jalur path terpendek. Jalurnya diupdate menjadi a b e d. Kita lanjutkan pada titik f. Jalur a b e d f bernilai sama, yaitu 11. Kemudian yang terahir, titik g. Jalur a b e d f g memberikan hasil jarak 15 yang merupakan jarak terpendeknya. Jadi lintasan terpendeknya adalah a b e d f g dengan jarak 15.

Penghitungan dengan Program -Single Source Shortest Path0100090000037800000002001c00000000000400000003010800050000000b020000 0000050000000c020f066007040000002e0118001c000000fb021000070000000000b c02000000000102022253797374656d0006600700007cc8110072edc630606a1b000c 02000060070000040000002d01000004000000020101001c000000fb02c4ff0000000 000009001000000000440001254696d6573204e657720526f6d616e00000000000000 00000000000000000000040000002d010100050000000902000000020d000000320a 3600000001000400000000005e070d0620001b00040000002d010000030000000000

Penghitungan dengan Program -Intermediate Shortest Path0100090000037800000002001c00000000000400000003010800050000000b0200000 000050000000c020f066007040000002e0118001c000000fb021000070000000000bc020 00000000102022253797374656d0006600700007cc8110072edc630606a1b000c0200006 0070000040000002d01000004000000020101001c000000fb02c4ff00000000000090010 00000000440001254696d6573204e657720526f6d616e000000000000000000000000000

Penentuan lintasan terpendek dengan Algoritma Floyd cara manual : Algoritma ini menggunakan konsep Dynamic Programming. Dimisalkan v1 = a, .... , v7 = g dan W = matriks graph. Matriks awal W01 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2

9 7 1 0 7 0 2 8 4 5 0 9 0 4 0

Iterasi untuk k = 1 Untuk setiap sel matriks W dicek apakah w[i,j] > w[i,1] + w[1,j]. Jika ya maka w[i,j] = w[i,1] + w[1,j] Contoh : w[1,2] = 3, sedangkan w[1,1] + w[1,2] = 0+3=3 w[1,2] = w[1,1] + w[1,2] , maka w[1,2] tetap nilainya. Di matriks W1 ini tidak ada nilai yang berubah. Iterasi untuk k = 2 w[1,4] = , sedangkan w[1,2] + w[2,4] = 3+7=10 w[1,4] > w[1,2] + w[2,4] , maka nilai w[1,4] diubah menjadi 10 Artinya ada path dari v1 ke v4 melalui v2 yang mempunyai bobot lebih kecil (yaitu path v1 v2 v4 dengan jumlah bobot 10) dibandingkan path dari v1 ke v4 secara langsung (bobot = karena tidak ada path dari v1 ke v4 secara langsung) Nilai yang digunakan untuk menentukan nilai w pada iterasi ini adalah harga w yang diperoleh pada iterasi sebelumnya, W1. Begitu seterusnya, sampai iterasi ke7. Di sinilah konsep dynamic programming berlaku pada algoritma floyd ini. Jadi solusi

setiap tahap akan digunakan untuk menyelesaikan tahap selanjutnya. Matriks hasilnya adalah matriks hasil iterasi k = 7, yaitu W*. Jika pada harga W* ada wij dengan harga berarti tidak ada path dari vi ke vj baik langsung maupun tidak langsung. Iterasi k = 1 W11 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2

9 7 1 0 7 0 2 8 4 5 0 9 0 4 0

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2 6

9 10 4 7 1 0 7 3 0 2 8 4 5 0 9 0 4 0

Iterasi k = 4 W41 2 3 4 5 6 7

Iterasi k = 2 W21 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2

9 10 4 7 1 0 7 3 0 2 8 4 5 0 9 0 4 0

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2 6

9 10 4 12 18 7 1 9 15 0 7 3 9 15 0 2 8 4 5 0 7 13 0 4 0

Iterasi k = 5 W51 2 3 4 5 6 7

Iterasi k = 3 W31 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2 6

8 9 4 11 18 5 6 1 8 12 0 7 3 9 15 0 2 8 4 5 0 7 13 0 4 0

Iterasi k = 6 W61 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2 6

8 9 4 11 15 5 6 1 8 12 0 7 3 9 15 0 2 6 4 5 0 7 13 0 4 0

Iterasi k = 7 W7 = W*1 2 3 4 5 6 7

v1 0 v 2 v 3 v 4 v 5 v 6 v 7

3 0 2 6

8 9 4 11 15 5 6 1 8 12 0 7 3 9 13 0 2 6 4 5 0 7 11 0 4 0

Penghitungan dengan Program Floyd0100090000037800000002001c00000000000400000003010800050000000b0 200000000050000000c020f066007040000002e0118001c000000fb02100007000000000 0bc02000000000102022253797374656d0006600700007cc8110072edc630606a1b000c0 2000060070000040000002d01000004000000020101001c000000fb02c4ff00000000000 09001000000000440001254696d6573204e657720526f6d616e000000000000000000000 0000000000000040000002d010100050000000902000000020d000000320a3600000001 000400000000005e070d0620001b00040000002d010000030000000000 0100090000037800000002001c00000000000400000003010800050000000b02000 00000050000000c020f066007040000002e0118001c000000fb021000070000000000bc0 2000000000102022253797374656d0006600700007cc8110072edc630606a1b000c02000 060070000040000002d01000004000000020101001c000000fb02c4ff000000000000900 1000000000440001254696d6573204e657720526f6d616e0000000000000000000000000 000000000040000002d010100050000000902000000020d000000320a36000000010004 00000000005e070d0620001b00040000002d010000030000000000

Hasil Dan Kesimpulan Studi Kasus Lintasan terpendek dari kota A ke G : A-B-E-D-F-G Jaraknya : 15 km Waktu : Dijkstra SINGLE SOURCE Shortest Path = 20 ms Dijkstra INTERMEDIATE Shortest Path = 70 ms

Floyd ALL PAIR shortest path = 100 ms Yang paling cepat waktu pemrosesannya adalah Dijkstra, sehingga dapat dikatakan lebih efisien bila dibandingkan dengan Floyd.

Listing Programusing System.Collections.Generic; using System.Text; namespace ShortestPath { public class Dijkstra { public static Dictionary GetIntermediateShortestPath(Graph graph, Node start, out

TimeSpan span) { Dictionary path = new Dictionary(); Dictionary predecessor = new Dictionary(); Dictionary distance = new Dictionary(); List stack = new List(graph.Nodes); DateTime startTime = DateTime.Now; // Inisialisasi foreach (Node node in graph) { predecessor.Add(node, null); distance.Add(node, double.PositiveInfinity); } distance[start] = 0; // Dijkstra - Intermediate Shortest Path while (stack.Count > 0) { Node minNode = stack[0]; foreach (Node node in stack) if (distance[node] < distance[minNode]) minNode = node; stack.Remove(minNode); foreach (KeyValuePair val in minNode.Edges) { if (distance[minNode] + val.Value < distance[val.Key]) { predecessor[val.Key] = minNode;

distance[val.Key] = distance[minNode] + val.Value; } } } DateTime endTime = DateTime.Now; span = Time.Span(startTime, endTime); // Get path foreach (Node node in graph) { Node pre = predecessor[node]; List list = new List(); while (pre != start && pre != null) { list.Insert(0, pre); pre = predecessor[pre]; } list.Insert(0, start); list.Add(node); path.Add(list, distance[node]); } return path; } public static Dictionary GetSingleSourceShortestPath(Graph graph, Node start, Node end, out TimeSpan span) { Dictionary path = new Dictionary(); Dictionary predecessor = new Dictionary(); Dictionary distance = new Dictionary(); List stack = new List(graph.Nodes); DateTime startTime = DateTime.Now; // Inisialisasi foreach (Node node in graph) { predecessor.Add(node, null); distance.Add(node, double.PositiveInfinity); } distance[start] = 0; // Dijkstra Single Source Shortest Path while (stack.Contains(end)) { Node minNode = stack[0]; foreach (Node node in stack) if (distance[node] < distance[minNode]) minNode = node; stack.Remove(minNode); foreach (KeyValuePair val in minNode.Edges) { if (distance[minNode] + val.Value < distance[val.Key]) { predecessor[val.Key] = minNode; distance[val.Key] = distance[minNode] + val.Value; } } } DateTime endTime = DateTime.Now;

span = Time.Span(startTime, endTime); // Get path Node pre = predecessor[end]; List list = new List(); while (pre != start && pre!=null) { list.Insert(0, pre); pre = predecessor[pre]; } list.Insert(0, start); list.Add(end); path.Add(list, distance[end]); return path; } } }

using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace ShortestPath { public class Floyd { public static Dictionary GetAllPairShortestPath(Graph nodes, out TimeSpan span) { Dictionary path = new Dictionary(); Dictionary predecessor = new Dictionary();

Dictionary distance = new Dictionary(); DateTime startTime = DateTime.Now; // Inisialisasi foreach (Node n1 in nodes) { foreach (Node n2 in nodes) { KeyValuePair now = new KeyValuePair(n1,n2); distance.Add(now, nodes.GetDistance(n1, n2)); if (distance[now] < double.PositiveInfinity) predecessor.Add(now, n1); else predecessor.Add(now, null); } } // Floyd foreach (Node n1 in nodes) { foreach (Node n2 in nodes) { KeyValuePair now21 = new KeyValuePair(n2,n1); foreach (Node n3 in nodes) { KeyValuePair now23 = new KeyValuePair(n2, n3); KeyValuePair now13 = new KeyValuePair(n1, n3); if (distance[now23] > distance[now21] + distance[now13]) {

distance[now23] = distance[now21] + distance[now13]; predecessor[now23] = predecessor[now13]; } } } } DateTime endTime = DateTime.Now; span = Time.Span(startTime, endTime); // Get path foreach (Node n1 in nodes) { foreach (Node n2 in nodes) { KeyValuePair pre = new KeyValuePair(n1, predecessor[new KeyValuePair(n1, n2)]); List list = new List(); while (pre.Value != n1 && pre.Value != null) { list.Insert(0, pre.Value); pre = new KeyValuePair(n1, predecessor[new KeyValuePair (n1, pre.Value)]); } list.Insert(0, n1); list.Add(n2); path.Add(list, distance[new KeyValuePair(n1, n2)]); } } return path; }

} }


Top Related