使用extendedRecursionEngine定义reachableFrom图

时间:2010-11-09 20:23:43

标签: haskell

我正在尝试使用extendedRecursionEngine定义reachableFrom。随身携带已沿路径展开的节点列表很有用。在递归期间传递的值是一对(node_to_be_expanded,nodes_already_expanded)。

这是我到目前为止可以绘制的内容。我不知道如何实现它,所以我可以毫无错误地运行它。

reachableFrom graph startNode = 
   extendedRecursionEngine
      (\ (node, expanded) ->         -- Stop if we have already expanded this node.
      (\ (node, _) -> Node node [])  -- If we are done, construct a Tree Node with no descendents.
      Node                           -- Build a Tree Node from a graph node and the returned subtrees.
      (\ (node, _) -> node)          -- Save the graph node for the reduceFn.
      (\ (node, expanded) ->         -- Construct a list of nodes that can be reached in one step.
                                     -- Also add the current node to expanded.
      (startNode, [])                -- Start at the start node. expanded is initially empty.

当我们可以从中运行时,应该输出

之类的输出
> reachableFrom exampleGraph 2
Node 2 [ Node 3 [ Node 5 [ Node 2 []                     -- Don't expand 2 again.
                         , Node 6 []
                         ]
       , Node 4 [ Node 1 [ Node 2 []]]                   -- Don't expand 2 again.
       ]

> reachableFrom exampleGraph 4 
Node 4 [ Node 1 [ Node 2 [ Node 3 [ Node 5 [ Node 2 []   -- Don't expand 2 again.
                                           , Node 6 []
                                           ]
                         , Node 4 []                     -- Don't expand 4 again.
                         ]
                ]
       ]

> reachableFrom exampleGraph 5 
Node 5 [ Node 2 [ Node 3 [ Node 5 []]                    -- Don't expand 5 again.
                , Node 4 [ Node 1 [ Node 2 []]]          -- Don't expand 2 again.
                ]
       , Node 6 []
       ]       

其中exampleGraph和tree定义为

-- Nodes are not declared explicitly. A value of type a is a node.
-- The nodes are linked by Links: (node_a, node_b)
data Tree a = Leaf | Node a [Tree a]
type Link a = (a, a)
data (Eq a, Show a) => 
     Graph a = Graph {nodes :: [a], links :: [Link a]} 
     deriving (Show, Eq)
-- A Graph is a collection of values (of type a) with Links joining them.

exampleGraph = 
  let node1 =  1      
      node2 =  2       
      node3 =  3       
      node4 =  4       
      node5 =  5       
      node6 =  6       
  in Graph [node1, node2, node3, node4, node5, node6] 
           [ (node1, node2)
           , (node2, node3)
           , (node2, node4)
           , (node3, node5)
           , (node5, node2)
           , (node4, node1)
           , (node5, node6)
           ]

这是我运行这个程序时会发生的事情。

> exampleGraph 
Graph {nodes = [1,2,3,4,5,6], links = [(1,2),(2,3),(2,4),(3,5),(5,2),(4,1),(5,6)]}

当我尝试定义reachableFrom时,我遇到了这个实用程序函数,它返回给定节点直接链接到的节点。

linksFrom :: (Eq a, Show a) => Graph a -> a -> [a]
linksFrom graph node = [n2 | (n1, n2) <- links graph, n1 == node]

我不确定我是否可以用任何方式来定义我的reachableFrom。如何使用此recursionEngine实现reachableFrom?

1 个答案:

答案 0 :(得分:1)

好了玩了一会儿后,我得到了答案。 这里我们如何定义reachableFrom函数。

reachableFrom graph startNode = 
   extendedRecursionEngine
      (\ (node, expanded) -> node `elem` expanded )       -- Stop if we have already expanded node.
      (\ (node, _) -> Node node [])  -- If we are done, construct a Tree Node with no descendents.
      Node                           -- Build a Tree Node from a graph node and the returned subtrees.
      (\ (node, _) -> node)          -- Save the graph node for the reduceFn.
      (\(node, expanded) -> [ (myNode, node:expanded) | myNode <- linksFrom graph node ])       -- Construct a list of nodes that can be reached in one step. myNode
                                     -- Also add the current node to expanded.
      (startNode, [])               -- Start at the start node. expanded is initially empty.