如何是';匹配';在Haskell'中实施;s FGL是否为O(1)?

如何是';匹配';在Haskell'中实施;s FGL是否为O(1)?,haskell,functional-programming,graph-algorithm,Haskell,Functional Programming,Graph Algorithm,在Haskell的函数图库(FGL)中,大多数图算法依赖于“匹配”函数,给定节点n和图g,该函数返回c&g',其中c是n的上下文,而g'是图的其余部分(不包含对n的引用) 我能看到的唯一方法是检查g中的每个上下文,删除所有引用n的边,并将它们添加到上下文c。我相信这需要线性时间 编写该库的Martin Erwig在论文中建议,这种转换可以在常数时间或至少是次线性时间内完成。有人能向我解释一下这是如何完成的吗?match是在typeclass中定义的,因此该函数的实现取决于实现typeclass的

在Haskell的函数图库(FGL)中,大多数图算法依赖于“匹配”函数,给定
节点n
图g
,该函数返回
c&g'
,其中
c
n
上下文,而
g'
是图的其余部分(不包含对
n
的引用)

我能看到的唯一方法是检查
g
中的每个上下文,删除所有引用
n
的边,并将它们添加到上下文
c
。我相信这需要线性时间


编写该库的Martin Erwig在论文中建议,这种转换可以在常数时间或至少是次线性时间内完成。有人能向我解释一下这是如何完成的吗?

match
是在typeclass中定义的,因此该函数的实现取决于实现typeclass的数据类型

该包附带两个实现。您可以自己查看源代码

例如,Patricia树实现:

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)
,该值在给定机器上以设定的整数宽度(
W
)有效地保持不变

这样就只剩下
clearPred
clearcucc
,和
toAdj

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
也是
O(min(n,W))
,所以我们不必担心这一点。
ClearUCC
clearPred
都通过邻接列表中的每个元素递归,所以这是O(度)的组合

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

toAdj
创建一个新的边列表,即O(max(|V |,| E |)),但这是惰性构造的,因此我们不需要担心,除非使用它。

非常高级别的概述-最常见的图形实现的
match
函数中的大多数工作都使用
IntMap
模块中的
lookup
函数。这是
O(min(n,W))
其中
n
是映射中的元素数,
W
是整数的大小(通常为32或64位)。因此查找在n中是线性的,最大值为n=32或n=64,之后是常数,尤其是渐近O(1)。