我编写了以下代码来使用 FGL 包增加图形给定边的标签,如果边不存在,则在增加之前创建它:
import Data.Graph.Inductive
incrementEdge :: Edge -> Gr a Int -> Gr a Int
incrementEdge edge g = gmap (increment edge) g
increment :: Edge -> Context a Int -> Context a Int
increment (a,b) all@(p,n,x,v) = if a /= n then all else (p,n,x,v'')
where
v' = let (r,_) = elemNode b v in if r then v else ((0,b):v)
v'' = map (\(x,y) -> if y == b then (x+1,y) else (x,y)) v'
a :: Gr String Int
a = ([],1,"a",[]) & empty
b = ([],2,"b",[]) & a
在测试时我得到以下结果:
*Main> incrementEdge (1,1) b
1:"a"->[(1,1)]
2:"b"->[]
*Main> incrementEdge (1,2) b
1:"a"->[(1,2)]
2:"b"->[]
*Main> incrementEdge (2,2) b
1:"a"->[]
2:"b"->[(1,2)]
但是...
*Main> incrementEdge (2,1) b
*** Exception: Edge Exception, Node: 1
这里有什么问题吗?
版本
elemNode ys [] = (False,0)
elemNode ys ((m,xs):xss) = if ys == xs then (True,m) else elemNode ys xss
我想编写一个函数,它将从两个节点标签向图形添加一条边,该函数检查这两个节点是否存在,如果不存在,则创建它们: - 如果节点已经存在,则它们之间的边的标签是增量, - 如果这些节点之间没有边,则在递增之前创建它
感谢您的回复
最佳答案
我认为您不应该使用 gmap
添加边:它以任意顺序折叠图中的所有上下文,并通过 &< 构建新图
将新上下文组合在一起。如果新上下文具有指向或来自尚未进行 &
编辑的节点的链接,您将收到 Edge Exception
。
这是一个简单的例子:
*Main> ([], 1, "a", [(0, 2)]) & empty :: Gr String Int
*** Exception: Edge Exception, Node: 2
我只在几个小项目中使用过FGL
,而且我当然不是专家,但添加新边缘可能更有意义(带有标签1
)使用 insEdge
,然后在需要时进行所有计数:
import Data.Graph.Inductive
import qualified Data.IntMap as I
incrementEdge :: Edge -> Gr a Int -> Gr a Int
incrementEdge (a, b) = insEdge (a, b, 1)
count :: Gr a Int -> Gr a Int
count = gmap $ \(p, n, x, v) -> (countAdj p, n, x, countAdj v)
where
swap (a, b) = (b, a)
countAdj = map swap . I.toList . I.fromListWith (+) . map swap
这似乎按预期工作:
*Main> count $ incrementEdge (2, 1) b
1:"a"->[]
2:"b"->[(1,1)]
*Main> count $ incrementEdge (2, 1) $ incrementEdge (2, 1) b
1:"a"->[]
2:"b"->[(2,1)]
关于haskell - 修改Haskell包fgl中的边缘标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3907083/