2013-08-03 6 views
11

, grafik algoritmaları çoğu Node n ve Graph g verilen uyu fonksiyonu bağlıdır, cn arasında Context olan c & g', döndürür ve g' dinlenme grafiğin (n referansı içermiyor). Bunu yapmanın görebilirsinizHaskell'in FGL'sinde 'eşleşme' nasıl O (1) olacak? Haskell'ın Fonksiyonel Grafik Kütüphanesi (FGL) 'de

tek yolu g içinde bağlamlarda her inceleyerek ve n başvuran tüm kenarları kaldırılması ve bağlam c ekleyerek olmak olduğunu. Bu lineer zaman alırdı, inanıyorum. Kütüphaneyi yazan Martin Erwig, bu dönüşümün sabit ya da en azından alt-lineer sürede yapılabileceğini akla getirmektedir. Bu kitap, this belgesinde yazmaktadır. Bunun nasıl yapıldığını bana açıklayabilir mi?

+5

Çok yüksek düzeyde bir genel bakış - en yaygın grafik uygulaması için "eşleme" işlevinin çoğu, "IntMap" modülünden 'lookup' işlevini kullanır. Bu, "n" (n (W)) 'dir; burada n ', haritadaki elemanların sayısıdır ve" W ", bir int (normalde 32 veya 64) bitindeki boyuttur. Bu nedenle, n, n = 32 veya n = 64'e kadar n '' lineer '' lineerdir, bundan sonra sabittir - özellikle, asimptotik olarak O (1) 'dir. –

cevap

7

match, Graph typeclass içinde tanımlanmıştır, bu nedenle, bu işlevin uygulanması, typeclass'i uygulayan veri türüne bağlıdır.

Paket iki uygulama ile birlikte gelir; one using Patricia trees, one using regular trees. Kaynağı kendiniz de görebilirsiniz. Örneğin

Patricia ağaç uygulanması:

import   Data.Graph.Inductive.Graph 
import   Data.IntMap (IntMap) 
import qualified Data.IntMap as IM 
import   Data.List 
import   Data.Maybe 
import   Control.Arrow(second) 


newtype Gr a b = Gr (GraphRep a b) 

type GraphRep a b = IntMap (Context' a b) 
type Context' a b = (IntMap [b], a, IntMap [b]) 

type UGr = Gr()() 


instance Graph Gr where 
    -- ... 
    match   = matchGr 
    -- ... 

matchGr :: Node -> Gr a b -> Decomp Gr a b 
matchGr node (Gr g) 
    = case IM.lookup node g of 
     Nothing 
      -> (Nothing, Gr g) 

     Just (p, label, s) 
      -> let !g1 = IM.delete node g 
        !p' = IM.delete node p 
        !s' = IM.delete node s 
        !g2 = clearPred g1 node (IM.keys s') 
        !g3 = clearSucc g2 node (IM.keys p') 
       in 
       (Just (toAdj p', node, label, toAdj s), Gr g3) 

lookup and delete on IntMaps have O(min(n,W)) runtime, bir dizi tamsayı genişliği (W) verilen bir makinede etkili bir sabittir.

clearSucc :: GraphRep a b -> Node -> [Node] -> GraphRep a b 
clearSucc g _ []  = g 
clearSucc g v (p:rest) = clearSucc g' v rest 
    where 
     g' = IM.adjust f p g 
     f (ps, l, ss) = (ps, l, IM.delete v ss) 


clearPred :: GraphRep a b -> Node -> [Node] -> GraphRep a b 
clearPred g _ []  = g 
clearPred g v (s:rest) = clearPred g' v rest 
    where 
     g' = IM.adjust f s g 
     f (ps, l, ss) = (IM.delete v ps, l, ss) 

adjust da O(min(n,W)), bu nedenle bu konuda endişelenmenize gerek yoktur:

Yani bu sadece clearPred, clearSucc ve toAdj bırakır. clearSucc ve clearPred öğelerinin her ikisi de, bitişik listedeki her öğe boyunca tekrarlanır; bu nedenle, O (derece) birleştirilir.

toAdj :: IntMap [b] -> Adj b 
toAdj = concatMap expand . IM.toList 
    where 
    expand (n,ls) = map (flip (,) n) ls 

toAdj O yeni bir kenar liste oluşturur (maks (| V |, | E |)), ancak bu lazily inşa edilmiştir, bu yüzden bunun kullanıldığı sürece bu konuda endişe etmenize gerek yoktur.

İlgili konular