【问题标题】:Diff for Directed Acyclic Graphs有向无环图的 Diff
【发布时间】:2013-05-09 08:00:57
【问题描述】:

我正在寻找一种可以diff 两个有向无环图(DAG)的算法。也就是说,我想要一种算法,它在第一个 DAG 上产生一系列删除和插入,以产生第二个 DAG。

我不是百分百肯定,但我认为最长的公共子序列可以应用于 DAG。我不太关心生成的编辑序列的长度(只要它足够短),而更关心算法的运行时间。

一个复杂的问题是,除了单个根节点之外,我的所有顶点都没有被标记。根节点也是唯一具有零入边的节点。图的边缘被标记,图中的“数据”由从根到叶的路径表示。这类似于trie,但使用有向图而不是树。实际上,我的图表与directed acyclic word graph 数据结构非常相似。

这是一个例子。

DAG1

DAG2

要获得 DAG 2,您只需将一个顶点从根添加到另一个带有标签“b”的顶点。从那个顶点开始,有一条边到 DAG 1 中的最终“ac”顶点,还有一条边到标签为“d”的新顶点。从最后一个顶点到 DAG 1 中的“ac”顶点还有另一条边。我会以 DAG 形式发布一个指向差异的链接,但我不能发布两个以上的链接。

谢谢,希望这足够清晰。

【问题讨论】:

  • 一个节点是否可以有两条标签相同的边从它引出?
  • @borrible:这是个好问题,我认为他们做不到。如果他们这样做,它会彻底改变吗?
  • 说你有一个有很多顶点的有向无环图,在有向无环图中间的某个地方你建立了一个新的边(当然没有创建一个循环)。 如果顶点没有标记,找到那个简单的差异是一项艰巨的任务——而且,你甚至如何描述它?
  • @WalterTross 我的错误,我在发放赏金时想到的用例是带有标签的顶点:每个顶点都有多个属性。

标签: algorithm diff directed-acyclic-graphs


【解决方案1】:

您的特定数据表示如何显示 DAG 2 示例中的边 cx 终止于同一顶点?

如果我们假设 Wikipedia 对 "directed graph""vertex""edge" 的一般定义,则不存在“未标记顶点”之类的东西,因为如果不标记它们,就无法描述边缘,根据那里的定义。

在我看来,您的问题无法回答。请提供 (1) 提供给算法的输入的简单示例——将每个图描述为顶点和边的集合的数据结构——以及以类似方式的预期输出,以及 (2) 一种一致的方式来区分是否存在第一个 DAG 中的边或顶点等价于第二个 DAG 中的一个,这意味着图的这方面没有区别。

也许您的问题实际上主要是关于如何确定输入中每个 DAG 中顶点的标签以及如何最好地关联它们。或者,也许标签只是为了方便描述每个图,而问题实际上是在寻找minimal set of changes to describe a transformation of the structure of one graph to another

也就是说,图的传统数学定义中的边和顶点是原子的。如果我们假设任何特定顶点或边的相同标签表示完全相同的顶点或边,则每个顶点或边在任何一个图中都存在或不存在,这使得差异的概念有些无意义,或者构建起来微不足道在这两个图中。

这种简单的算法基本上只是枚举两个 DAG 中的每个顶点和边,并将适当的操作添加到差异中,仅从以下操作中进行选择:

add vertex v
remove vertex v
add edge e
remove edge e
switch direction for edge e

【讨论】:

  • 你提出了一个很好的观点。我在发放赏金时想到的用例是带有标签的顶点:每个顶点都有多个属性。
  • @phant0m 你能解释一下并举个例子吗? “多重属性”是什么意思?可以有不同的方法来确定第一个 DAG 中的边或顶点是否等同于第二个 DAG 中的边或顶点。在没有说明 OP 如何为 他们的 用例(或你的)做这件事的情况下,我看不出我们该如何回答。
  • 假设其中一个节点有一个id 属性作为键。或者,作为概括,有一些 `0 1 表示图 A 中的顶点 a 等同于图 B 中的顶点 b。所以在在id 的情况下,如果ab 具有相同的id,则函数计算为1,否则计算为零。在我的例子中,每对节点之间只能有一条边,因此可以相对于它们的顶点来识别边。
  • @phant0m 谢谢。所以我们可以通过它们唯一的id来识别顶点。据我了解,DAG 中的“边缘”通常定义为(vertex_1, vertex_2, direction)。如果我们将顶点标识​​作为唯一 ID,您能否帮助我理解为什么创建差异并非易事? DAG 中要么存在顶点(以及延伸的边),要么不存在。只需枚举它们并标记操作 - 如果它在两者中,则什么都不做,否则:如果它在 1 而不是 2 中,标记remove;如果在 2 而不是 1,标记add,如果在 1 和 2 但改变方向,标记change direction。我错过了什么? :)
【解决方案2】:

这可能有点太晚了,但只是为了好玩: 您的两个 DAG 都可以表示为矩阵,行索引表示“从”顶点,列索引表示“到”顶点,对应的单元格标有边 id。您可以为顶点提供唯一且随机的 id。

下一部分有点棘手,因为只有您的边具有从 DAG1 映射到 DAG2 的有意义的标签。假设您有一组边 E*,它们是来自 DAG1 和 DAG2 的标记边的交集,您将需要执行一系列行移位(向上或向下移动)或列移位(向左或向右移动)所以所有位置DAG1 和 DAG2 中 E* 中的边相互映射。请注意,对于以 Matrix 表示的 DAG,整行或整列的移动位置仍然使表示等效。

剩下的操作是根据映射的矩阵重命名顶点,比较两个矩阵,并确定所需的新边和新顶点(以及可以删除的边和顶点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 2015-08-09
    • 1970-01-01
    • 2013-01-10
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多