En Kısa Yol Problemleri (Shortest Path Problems) Bir yol haritası üzerinde 2 nokta arasındaki en kısa yolu nasıl bulabiliriz? Problemi bir çizge problemi olarak modelleyebiliriz: Yol haritası ağırlıklı bir çizgedir: Köşeler = şehirlerdir Kirişler = şehirler arasındaki yollardır Kiriş ağırlığı = 2 şehir arasındaki yolun uzunluğudur Amaç: 2 köşe (şehir) arasında en kısa yolu bulmaktır
En Kısa Yol Problemi Giriş: Yolun ağırlığı p = v0, v1, . . . , vk Yönlü çizge G = (V, E) Ağırlık fonksiyonu w : E → R Yolun ağırlığı p = v0, v1, . . . , vk u dan v ye en kısa yolun ağırlığı: δ(u, v) = min w(p) : u v u dan v ye yol varsa ∞ aksi durumda Not: u dan v ye birden çok kısa yol olabilir. 3 9 5 11 6 7 s t x y z 2 1 4 p
En kısa yol problemi çeşitleri Tek kaynaklı en kısa yollar(Single-source shortest paths (SSSP) G = (V, E) ve başlangıç s köşesi veriliyors den her v V köşesine giden en kısa yolları bulmak gerekir Tek hedefli en kısa yollar (Single-destination shortest paths (SDSP) Verilen t hedef köşesine her v köşesinden gelen en kısa yolları bulmak gerekir. Tüm kirişlerin yönlerini değiştirirsek bu soru tek kaynaklı en kısa yol problemine dönüşür.
En kısa yol problemi çeşitleri) Tek ikili arasında en kısa yol problemi (Single-pair shortest path) Verilen u ve v köşeleri için bu köşeler arasındaki en kısa yolu bulma problemi Tüm ikililer arasında en kısa yol problemi (All-pairs shortest-paths) Her u ve v köşeleri için bu köşeler arasındaki en kısa yolu bulma problemi
Negatif Ağırlıklı Kirişler Negatif ağırlıklı kirişler negatif ağırlıklı döngülere neden olabilirler. Eğer bu tür bir döngüye başlangıç köşeden ulaşılabiliyorsa δ(s, v) düzgün tanımlanmamıştır! Bu tür bir döngü üzerinde sonsuz dönüldüğünde döngü üzerindeki her v köşesi için w(s, v) = - olur. 3 -4 2 8 -6 s a b e f -3 y 5 6 4 7 c d g
Negatif Ağırlıklı kirişler s a: sadece bir yol var δ(s, a) = w(s, a) = 3 s b: sadece bir yol var δ(s, b) = w(s, a) + w(a, b) = -1 s c: sonsuz sayıda yol s, c, s, c, d, c, s, c, d, c, d, c döngü değeri pozitiftir (6 - 3 = 3) s, c en kısa yoldur δ(s, c) = w(s, c) = 5 3 -1 - -4 2 8 -6 s a b e f 5 11 -3 y 6 4 7 c d g
Negatif Ağırlıklı Çizgeler s e: sonsuz sayıda yol var: s, e, s, e, f, e, s, e, f, e, f, e e, f, e döngüsünün ağırlığı negatiftir: 3 + (- 6) = -3 s den e ye istenilen kadar küçük negatif ağırlıklı yol bulunur δ(s, e) = - s den s ye kısa yol yoktur Benzer olarak: δ(s, f) = - , δ(s, g) = - 3 -1 - -4 2 8 -6 s a b e f 5 11 -3 y 6 4 7 c d g j h i 2 3 -8 h, i, j köşeleri s den ulaşılabilir değil δ(s, h) = δ(s, i) = δ(s, j) =
Döngüler En kısa yol üzerinde döngü olabilir mi? Negatif ağırlıklı döngü? En kısa yol iyi tanımlanmamış olur Positif ağırlıklı döngü?: Döngüyü yoldan kaldırırsak daha kısa yol elde ederiz Sıfır ağırlıklı döngü? Kullanmak anlamsızdır Döngüyü yoldan kaldırırsak en kısa yol değeri değişmez Hayır! Hayır!
Optimal Altyapı teoremi Verilen: Ağırlıklı yönlü çizge G = (V, E) Ağırlık fonksiyonu w: E R, v1 den vk ya en kısa p = v1, v2, . . . , vk yolu P nin bir altyolu: pij = vi, vi+1, . . . , vj, burada 1 i j k Bu durumda: pij yolu vi den vj ye en kısa yoldur İspat: p = v1 vi vj vk w(p) = w(p1i) + w(pij) + w(pjk) vi den vj ye w(pij’) < w(pij) olacak biçimde bir pij’ yolu var olsun w(p’) = w(p1i) + w(pij’) + w(pjk) < w(p) çelişki! vj pjk v1 pij p1i pij’ vk vi p1i pij pjk
Üçgen eşitsizliği Her (u, v) E kirişi için δ (s, v) ≤ δ (s, u) + δ (u, v) - Eğer u köşesi en kısa yolun üzerinde ise eşitlik vardır s u v s u v
Algoritmalar Bellman-Ford algorithm Dijkstra’s algorithm Negatif ağırlıklara izin veriliyor Negatif döngünün varlığını buluyor Dijkstra’s algorithm Negatif ağırlıklara izin verilmiyor Her iki algoritmanın ortak işlemleri: Başlangıç değerleri atama işlemi(Initialization) Hafifletme işlemi (Relaxation)
En kısa yol işaretlemeleri Her v V köşesi için: δ(s, v): s den v ye en kısa yolun ağırlığı d[v]: bakılan adıma kadar s den v ye bulunan en kısa yolun ağırlığı Başlangıçta, d[v]=∞ d[v]δ(s,v) algoritma bitiminde [v] = bakılan adımda s den v ye bulunan en kısa yolda v den bir önceki köşe Bu köşe yoksa, [v] = NIL yardımıyla bir ağaç oluşur en kısa yol ağacı 3 9 5 11 6 7 s t x y z 2 1 4
Başlangıç değerleri atama(Initialization) Alg.: INITIALIZE-SINGLE-SOURCE(V, s) for each v V do d[v] ← [v] ← NIL d[s] ← 0 Tüm en kıs ayol algoritmaları INITIALIZE-SINGLE-SOURCE fonksiyonu ile başlar
Hafifletme (Relaxation) adımı (u, v) kirişinde hafifletme = v ye u dan gelmek daha avantajlı mıdır? If d[v] > d[u] + w(u, v) bu durumda v ye gelen yolu kısaltabiliriz ( u dan geçerek) d[v]=d[u]+w(u,v) [v] ← u Hafifletme sonrası: d[v] d[u] + w(u, v) s s 5 9 2 u v 5 6 2 u v RELAX(u, v, w) RELAX(u, v, w) 5 7 2 u v 5 6 2 u v Değişiklik yok
Bellman-Ford Algoritması Tek kaynaklı en kısa yol problemini çözüyor δ(s, v) ve [v] yi her v V için buluyor Negatif ağırlıklara izin veriyor ve negatif ağırlıklı döngü varsa varlığını buluyor. Eğer negatif ağırlıklı döngü yoksa TRUE döndürüyor ( s den ulaşılabilir döngü) Aksi durumda FALSE döndürüyor
Bellman-Ford Algoritması Ana fikir: |V–1| defa tüm kirişlere tek tek bakılıyor ve hafifletme işlemi yapılıyor. Aşağıdaki örnekte verilen kiriş sırası ile Bellman-Ford algoritması uygulayalım (t, x), (t, y), (t, z), (x, t), (y, x), (y, z), (z, x), (z, s), (s, t), (s, y) t x 5 6 -2 -3 8 7 s -4 7 2 9 y z
BELLMAN-FORD(V, E, w, s) s t x y z Pass 1 s t x y z 6 7 6 5 7 9 s t x y z 8 -3 2 -4 -2 Pass 1 6 5 7 9 s t x y z 8 -3 2 -4 -2 6 7 E: (t, x), (t, y), (t, z), (x, t), (y, x), (y, z), (z, x), (z, s), (s, t), (s, y)
Örnek (t, x), (t, y), (t, z), (x, t), (y, x), (y, z), (z, x), (z, s), (s, t), (s, y) 6 7 5 9 s t x y z 8 -3 2 -4 -2 6 7 5 9 s t x y z 8 -3 2 -4 -2 1. geçiş 2. geçiş 11 4 2 3. geçiş 6 7 5 9 s t x y z 8 -3 2 -4 -2 11 4 6 7 5 9 s t x y z 8 -3 2 -4 -2 11 4 4. geçiş 2 -2
do if d[v] > d[u] + w(u, v) then return FALSE return TRUE Negatif döngüyü bulma (tüm kirişler üzerinden ek olarak bir defa daha geçiliyor) for each edge (u, v) E do if d[v] > d[u] + w(u, v) then return FALSE return TRUE c s b 2 3 -8 1st geçiş 2nd geçiş c s b 2 3 -8 -3 2 5 c s b 3 -8 (s, b) ye bakalım: d[b] = -1 d[s] + w(s, b) = -4 d[b] > d[s] + w(s, b) -3 2 -6 -1 5 2 (s,b) (b,c) (c,s)
BELLMAN-FORD(V, E, w, s) INITIALIZE-SINGLE-SOURCE(V, s) for i ← 1 to |V| - 1 do for each edge (u, v) E do RELAX(u, v, w) for each edge (u, v) E do if d[v] > d[u] + w(u, v) then return FALSE return TRUE Running time: O(V+VE+E)=O(VE) (V) O(V) O(VE) O(E) O(E)
Dijkstra’ Algoritması Tek kaynaklı en kısa yol problemi: Negatif ağırlıklı kiriş yok: w(u, v) > 0, (u, v) E Bu algoritmada her kiriş bir defa hafifletilir! Her adımda 2 çeşit köşeler kümesi olur: d[v]=δ (s, v) d[v]>δ (s, v)
Dijkstra Algoritması V – S kümesinde min-öncelikli kuyruk vardır Q de kısa yolların değerleri d[u] ile değerlendirilir Her adımda d[u] değeri en küçük olan u V – S, köşesi seçilir ve u dan çıkan tüm kirişlere Relax uygulanır
Dijkstra (G, w, s) Q=<y,t,x,z> S=<> Q=<s,t,x,z,y> S=<s> Q=<y,t,x,z> 10 1 5 2 s t x y z 3 9 7 4 6 10 1 5 2 s t x y z 3 9 7 4 6 10 5
Örnek S=<s,y> Q=<z,t,x> S=<s,y,z> Q=<t,x> 10 10 5 1 2 s t x y z 3 9 7 4 6 8 14 5 7 10 1 2 s t x y z 3 9 4 6 8 14 13 7 S=<s,y> Q=<z,t,x> S=<s,y,z> Q=<t,x>
Örnek S=<s,y,z,t,x> Q=<> S=<s,y,z,t> Q=<x> 8 9 8 9 5 7 10 1 2 s t x y z 3 4 6 8 13 5 7 10 1 2 s t x y z 3 9 4 6 9
Dijkstra (G, w, s) INITIALIZE-SINGLE-SOURCE(V, s) (V) S ← Q ← V[G] while Q do u ← EXTRACT-MIN(Q) S ← S {u} for each vertex v Adj[u] do RELAX(u, v, w) Update Q (DECREASE_KEY) Running time: O(VlgV + ElgV) = O(ElgV) (V) O(V) build min-heap Executed O(V) times O(VlgV) O(lgV) O(E) times (total) O(ElgV) O(lgV)
Dijskstra Algoritmasının doğruluğu İddia: Her u V köşesi için bu köşe S e eklendiğinde d[u] = δ(s, u) olur. İspat: u bu koşulu sağlamayan ilk köşe olsun, yani u köşesi S e eklendiğinde d[u] δ(s, u) olsun. p yolu s den u ya en kısa yol olsun:
Dijskstra Algoritmasının doğruluğu d[u] için aşağıdaki doğrudur? d[u]≤d[v]+w(v,u)= δ(s,v)+w(v,u) d[u’] için aşağıdaki doğrudur? d[u’]≤d[v’]+w(v’,u’)= δ(s,v’)+w(v’,u’) u’ köşesi u ya giden en kısa yol üzerinde: d[u’]<δ(s,u) d[u’]<d[u] diğer taraftan: d[u]>δ(s,u) Çelişki! Öncelikli kuyruk Q: <u, …, u’, ….> (yani, d[u]<…<d[u’]<… )
Problem 1 Negatif ağırlıklı çizgeler için Dijkstra algoritmasının doğru çalışmadığını gösteren bir örnek yazınız. s u 1 1 w -1 1 1. iterasyon v d[s]=0 d[u]=1 d[v]=1 S={s} Q={u,v,w} 2. iterasyon 3. iterasyon 4. iterasyon d[w]=2 S={s,u} Q={v,w} d[u]=0 S={s,u,v} Q={w} S={s,u,v,w} Q={} d[w] doğru değil! u köşesi S e girdikten sonra d[u]=δ[s,u] olmalıdır!
Problem 2 G=(V,E) yönlü bir çizgesi ve bu çizgenin her (u,v) kirişine karşılık gelen r(u,v) sayısı veriliyor., Burada 0≤r(u,v) ≤1 dir ve r(u,v) sayısı u dan v ye olan iletişim kanalının güvenilirliğini göstermektedir. r(u,v) sayısını u dan v ye olan kanalın doğru çalışma olasılığı olarak da düşünebiliriz ve tüm kanalların olasılıklarının bağımsız olduğunu düşünüyoruz. 2 köşe arasındaki en güvenilir yolu bulunuz.
Problem 2 Çözüm1: Dijkstra algoritmasını modifiye ederiz Relax işlemini değiştiririz: if d[v] < d[u] w(u,v) then d[v] = d[u] w(u,v) “EXTRACT_MIN” yerine “EXTRACT_MAX” kullanırız
Problem 2 Çözüm 2: Dijkstra algoritmasını değişiklik yapmadan uygularız! r(u,v)=(u,v) kanalının çalışma olasılığı olsun Olasılıklar bağımsız olsun, p=<v1,v2,…,vk> yolunun çalışma olasılığı: r(v1,v2)r(v2,v3) … r(vk-1,vk) Biz olasılığı en yüksek olan yolu arıyoruz,
Problem 2 (cont.) Dijkstra algoritması ise min hesaplar Logaritma alalım
Problem 2 Minimum arama problemine dönüştürelim: Şimdi Dijkstra algoritmasını alarak uygulayalım.