我正在尝试针对以下情况制定数据结构。
图表结构
我计划得到一个带有未加权有向边的节点图:Graph = [Node]
每个节点都有:
Node { nodeState :: NodeState, inbox :: Queue NodeMessage, nodeMessage :: (NodeState -> Maybe NodeMessage), connections::[NodeEdge] }
每个边缘都是捕获目标节点的待处理消息的中间步骤
NodeEdge { pendingMessage:: Maybe NodeMessage, targetNode :: Node }
消息传递
消息传递分阶段进行并且不是连续的(尽管队列可以并行处理以减少计算时间)。
NodeState
(如果相关)。nodeMessage
,如果这导致Just NodeMessage
,则将NodeMessage发送到每个连接([NodeEdge]
)Monat / ST
我最初的计划是为每个节点分配一个ID(可能是一个简单的Int),并将每个节点存储在Map Int Node中。我之前没有尝试过ST Monad,但我想我可以使用像ST s (M.Map Int Node)
这样的东西。对于任何给定阶段,每个节点的消息发送活动可以在O(k log N)中处理。
另一方面,如果节点/边缘能够更新其边/节点的可变状态,则可以在O(k)中处理任何单个队列。
虽然ST / Map方法看起来相当直观,但整个图形的可变性超出了我的范围。
任何建议/提示/推荐阅读?
答案 0 :(得分:1)
我不打算将这个答案标记为正确,因为它并没有真正回答这个问题。然而,这是我的解决方案。
因为我图中的节点数永远不会改变,所以我意识到我可以使用数组。我实际上正在重新考虑使用可变数据类型 - 即使我得到一个更简单的工作流程更新数组我得到的懒惰的好处更少,我最终编写了大量的命令式样式代码。我实际上在考虑使用Array和State Monad,而不是ST。
这是我使用STArray编写的一些测试代码。 A"适当"回答这个问题的是一个专门针对Graphs的类似数据类型 - 也许有一个STGraph库?
无论如何 - 这是使用STArray的示例代码:
import Control.Monad.ST
import Data.Array.ST
import Data.Array
import qualified Data.Dequeue as DQ
type Id = Int
data Node = Node {
nodeId :: Id,
nodeState :: NodeState,
nodeInbox :: DQ.BankersDequeue NodeMessage,
nodeMessage :: (NodeState -> Maybe NodeMessage),
connections :: [NodeEdge] }
instance Show Node where
show x = "Node: " ++ (show . nodeId $ x) ++ " :: Inbox: " ++ (show . nodeInbox $ x) ++ " :: " ++ (show . connections $ x)
data NodeEdge = NodeEdge { pendingMessage:: Maybe NodeMessage, targetNode :: Id } deriving Show
data NodeState = NodeState { stateLevel :: Int } deriving Show
data NodeMessage = NodeMessage { value :: Int } deriving Show
es = [[NodeEdge Nothing 1,NodeEdge Nothing 2],[NodeEdge Nothing 0,NodeEdge Nothing 2],[NodeEdge Nothing 0,NodeEdge Nothing 1]]
ns = take 3 $ map (\x -> Node x (NodeState 0) (DQ.fromList []) (\_ -> Nothing) (es !! x)) $ [0,1..]
testArray :: Array Int Node
testArray = listArray (0,2) ns
testSTarr = do arr <- newListArray (0,2) ns :: ST s (STArray s Int Node)
a <- readArray arr 1
let i = targetNode . head $ connections a
b <- readArray arr i
let m = NodeMessage 2
ms = DQ.pushBack (nodeInbox b) m
b' = b { nodeInbox = ms }
writeArray arr (nodeId b) b'
return arr
testSTarr' x = do a <- readArray x 0
return a
bp = testSTarr >>= testSTarr'
main = do
print $ runST bp
return ()