【问题标题】:Editing/Updating Graphs in Haskell在 Haskell 中编辑/更新图表
【发布时间】:2012-01-24 12:02:22
【问题描述】:

我正在使用 Data.Graph Graph 在 Haskell 中对模拟进行建模。模拟仅限于我的图形模型的 2D 网格。下面网格上每个点的节点都将包含一个 Maybe Molecule 类型,因此可能存在一个分子或什么都没有。

1  - 2  - 3  
|    |    |  
4  - 5  - 6  
|    |    |  
7  - 8 -  9  

我已经设置了这个表示,但是当涉及到更新分子的位置时,我觉得我在这个问题上走了很长一段路。到目前为止,我所做的是将所有节点剥离成一个节点列表。我编写了一个函数来交换此节点列表中的两项。但是现在,当我将所有内容重新压缩在一起时,我遇到了问题,因为要生成一个新图形,我需要一个顶点列表,我可以从 vertices Graph 函数中轻松获得这些顶点列表。但我还需要用边缘接触的顶点列表来压缩它。不幸的是,Data.Graph 的 edges Graph 函数返回一个 Edge 类型的元组列表,据我所知,这对于生成图形并没有立即帮助,尽管我可以编写一个函数来派生具有顶点的边的列表顶点。这样做似乎对我来说已经足够了,我想知道我是否错过了这一点,是否有一个 Graph 函数,它只获取一个图并返回一个带有更新节点的图?

【问题讨论】:

    标签: haskell graph simulation


    【解决方案1】:

    您在这里使用图表是否有特殊原因?在我看来,边缘集几乎是固定的,并且您的网格仅在分子的位置上有所不同。

    您为什么不直接使用数组或其他一些数据结构来让您专注于分子及其位置?例如:

    import Data.Array
    
    data Molecule = H2O | CO2 | NH3
    
    type Grid = Array (Int, Int) (Maybe Molecule)
    
    -- creates an empty grid                                                        
    grid :: Int -> Int -> Grid
    grid m n = array ((0, 0), (m - 1, n - 1)) assocs
      where
        assocs = [((i, j), Nothing) | i <- [0 .. m - 1], j <- [0 .. n - 1]]
    
    -- swap the molecules at the specified indices                                  
    swap :: (Int, Int) -> (Int, Int) -> Grid -> Grid
    swap (i, j) (u, v) grid =
      grid // [((i, j), grid ! (u, v)), ((u, v), grid ! (i, j))]
    
    -- etc.
    

    (如果你有充分的理由使用图表,我当然在这里完全不合时宜,在这种情况下我道歉......)

    【讨论】:

    • 如果我使用图表,我可以查看相邻节点是否被其他分子占用以进行碰撞检测检查。
    • @mikeyP 但是你也可以用数组来做到这一点,不是吗?
    • 你说得对,Graph 下面是一个数组。但是通过图表,我将能够删除图表上的节点,即分子无法通过的区域。我看不出用数组来做这件事的好方法。
    【解决方案2】:

    FGL 拥有这种出色的“上下文”机制,可让您在图形查询中进行模式匹配。您可以将其想象为拉动选定的顶点,使其位于图形其余部分的一侧。这使您可以查看该顶点如何连接到图形的其余部分。

    {-# LANGUAGE TupleSections #-}
    import Control.Applicative
    import Control.Arrow
    import Data.Graph.Inductive
    
    -- Example graph from SO question.
    graph :: Gr (Maybe Int) ()
    graph = mkGraph (map (id&&&Just) [1,2,3,4,5,6,7,8,9])
                    (map (\(x,y) -> (x,y,())) $
                         concatMap gridNeighbors [1..9])
      where gridNeighbors n = map (n,) 
                            . filter ((&&) <$> valid <*> not . boundary n) 
                            $ [n-3,n-1,n+1,n+3]
            valid x = x > 0 && x < 10
            boundary n x = case n `rem` 3 of
                             0 -> x == n + 1
                             1 -> x == n - 1
                             _ -> False
    
    -- Swap the labels of nodes 4 and 7
    swapTest g = case match 4 g of
                   (Just c4, g') -> case match 7 g' of
                                      (Just c7, g'') -> setLabel c4 (lab' c7) & 
                                                        (setLabel c7 (lab' c4) &
                                                         g'')
                                      _ -> error "No node 7!"
                   _ -> error "No node 4!"
      where setLabel :: Context a b -> a -> Context a b
            setLabel (inEdges, n, _, outEdges) l = (inEdges, n, l, outEdges)
    

    您可以尝试运行 swapTest graph 来查看图中节点 4 和 7 的标签是否已交换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多