我正在尝试为以下情况制定数据结构。
图结构
我计划制作一个带有未加权有向边的节点图:Graph = [Node]
每个节点有:
- 一些待定内部(持久)状态
- 传入消息队列
- 它可以发送的一种消息,由接受当前节点状态的函数确定(有失败的可能性)
- 边列表
Node { nodeState :: NodeState, inbox :: Queue NodeMessage, nodeMessage :: (NodeState -> Maybe NodeMessage), connections::[NodeEdge] }
每条边都是一个中间步骤,用于捕获目标节点的未决消息
NodeEdge { pendingMessage:: Maybe NodeMessage, targetNode :: Node }
消息传递
消息传递是分阶段进行的,并且是不同步的(尽管队列可以并行处理以减少计算时间)。
- 第 1 阶段:检查每个节点的收件箱,处理任何消息并更新
NodeState
相关信息。 - 第 2 阶段:让每个节点运行
nodeMessage
,如果这导致Just NodeMessage
,将 NodeMessage 发送到每个连接([NodeEdge]
) - 阶段 3:检查每个节点边缘,如果有消息,则将其添加到目标节点的消息队列中。
莫纳特/ST
我最初的计划是为每个节点分配一个 ID(可能是一个简单的 Int)并将每个节点存储在 Map Int 节点中。我之前没有尝试过 ST Monad,但我想我可以使用类似ST s (M.Map Int Node)
. 对于任何给定阶段,每个节点的消息发送活动都可以在 O(k log N) 中处理。
另一方面,如果节点/边能够更新其边/节点的可变状态,那么任何单个队列都可以在 O(k) 中处理。
虽然 ST/Map 方法看起来相当直观,但让整个图可变却超出了我的范围。
有什么建议/提示/推荐阅读吗?