穿过类似DAG的结构,在Clojure中产生另一种类似DAG的结构

时间:2015-04-13 06:33:27

标签: clojure directed-acyclic-graphs

我有一个类似DAG的结构,基本上是一个深层嵌套的map。此结构中的映射可以具有公共值,因此整体结构不是,而是直接非循环图。为简洁起见,我将此结构称为 DAG

此图中的节点具有不同但有限数量的类别。每个类别都可以有自己的结构/关键字/子女数量。有一个唯一节点是此DAG的源,这意味着从此节点我们可以到达DAG中的所有节点。

任务是从源节点遍历DAG,并将每个节点转换为新构造图中的另一个或多个节点。我举一个例子来说明。

Illustration of Graph Transformation

上半部分的图形是输入的图形。下半部分是转化后的一半。为简单起见,转换仅在节点A上完成,其中它被分成节点1和A1。节点A的子节点也被重新分配。

我尝试过(或记住):

  1. 编写一个函数,将一个对象转换为不同的类型。在这个函数内部,递归调用自身来转换它的每个子节点。该方法存在数据不可变的问题。变换后的图形中的节点不能随机更改以添加子节点。为了解决这个问题,我需要将每个节点都包装在ref / atom / agent中。
  2. 在原始图表上进行拓扑排序。然后以相反的顺序转换节点,即自下而上。此方法需要额外遍历图形,但至少数据不需要是可变的。关于拓扑排序算法,我考虑了wiki页面中所述的基于DFS的方法,该方法不需要知道完整图形也不需要节点的父节点。
  3. 我的问题是:

    1. 您可能会考虑其他任何方法,可能更优雅/更有效/惯用吗?
    2. 我更赞成第二种方法,是否有任何缺陷或潜在问题?
    3. 谢谢!

      编辑:再想一想,拓扑排序不是必需的。转换可以在后序遍历中完成。

1 个答案:

答案 0 :(得分:1)

这看起来像是Zippers的完美应用。它们具有您根据需要描述的所有功能,可以生成经过编辑的新功能。 DAG。还有许多库使用谓词线程来简化搜索和替换功能。

在使用嵌套矢量或地图树中定义的OWL本体时,我使用过拉链。

另一个选择是看看Walkers,虽然我发现这些使用起来有点繁琐。