带有循环的拓扑排序

时间:2019-07-31 14:43:33

标签: algorithm loops sorting graph

我正在为组合电路和顺序电路编写一个简单的数字模拟器,并且选择了一种图形方法来对该问题进行建模。

如果电路没有回路,我可以将其表示为DAG。在这种情况下,我可以想到至少两种执行模拟的方法:递归地,从输出向后进行或对图进行拓扑排序。

问题出现了,当存在循环时,因为我无法再对节点进行排序,但是由于电路是有向图,其边沿仅在一个方向上从输入到输出,所以循环是“返回”的唯一边。 / p>

因此,在这些限制下,我正在寻找一种在给定邻接表后执行拓扑排序“忽略循环”的方法。

这是我的主意:如果我想对组件进行排序而不考虑循环,那么我可以简单地先评估循环驱动程序,然后像模拟不存在循环那样进行仿真。当我手动解决逻辑电路时,这种方法效果很好。

换句话说,我想对图进行某种排序,假装不存在后边缘(因此我有DAG)。 有没有办法做到这一点?

编辑:看下面的图片。 enter image description here  这是与该电路相对应的邻接表:

n -> XNOR
m -> AND
AND -> NOT
NOT -> NAND
NAND -> D-FLIPFLOP
XNOR -> NAND
D-FLIPFLOP-> x, AND, XNOR
x -> 

我想要获得的拓扑是(例如)这个:

m AND NOT n XNOR NAND D-FLIPFLOP x  

忽略两个循环

D-FLIPFLOP -> AND
D-FLIPFLOP -> XNOR

1 个答案:

答案 0 :(得分:1)

您似乎对寻找小型feedback arc set的问题感兴趣。寻找最小的此类集合的问题通常是NP-hard的,但是存在一种快速算法,该算法具有由this question的答案中链接的Eades,Lin和Smyth得到不错的近似结果。我在这里重复一遍。该算法的目标是找到边缘的排序,以使相对较少的边缘与该排序相反,这也是您感兴趣的。

  1. 您有自己的图形,一个左堆栈(最初是空的)和一个右堆栈(也最初是空的)。
  2. 虽然图具有源(没有传入边的顶点):
    • 选择一个源,将其与图形断开连接,并将其放置在左侧堆栈的顶部。
  3. 虽然图中有一个接收器(没有输出边缘的顶点):
    • 选择一个接收器,将其与图形断开连接,并将其放置在正确的堆栈顶部。
  4. 如果图形不为空:
    • 选择图形的顶点,以使输出边缘的数量减去输入边缘的数量尽可能大。
    • 从图形上断开该顶点,并将其放在左侧堆栈的顶部。
    • 转到1。
  5. 取左堆栈,将其翻转并将其放在右堆栈的顶部。从上到下正确的堆栈是所需的顺序。