Graph 用公共Lisp表示有向无环图

Graph 用公共Lisp表示有向无环图,graph,lisp,common-lisp,graph-theory,directed-acyclic-graphs,Graph,Lisp,Common Lisp,Graph Theory,Directed Acyclic Graphs,通常,为了在Lisp中表示一个基本的无向图,我可以创建一个父节点及其相应子节点的列表,如中所述(为方便起见,请参见下图) 此图生成一个边列表: (1 (2 6 7 8) 3 (4 (9 12)) 5 (10 11)) 这适用于树或任何其他无向图的情况。然而,当我们想要表示一个每个节点都可以有多个父节点的有向无环图时,这种类型的表示就失效了: 现在,节点8有多个父节点(2,3),但当我们试图表示这一点时,我们无法判断节点8是否连接到两个父节点,或者是否有两个节点8: (1 (2 6 7 8

通常,为了在Lisp中表示一个基本的无向图,我可以创建一个父节点及其相应子节点的列表,如中所述(为方便起见,请参见下图)

此图生成一个边列表:

(1 (2 6 7 8) 3 (4 (9 12)) 5 (10 11)) 
这适用于树或任何其他无向图的情况。然而,当我们想要表示一个每个节点都可以有多个父节点的有向无环图时,这种类型的表示就失效了:

现在,节点8有多个父节点(2,3),但当我们试图表示这一点时,我们无法判断节点8是否连接到两个父节点,或者是否有两个节点8:

(1 (2 6 7 8) (3 8) (4 (9 12)) (5 10 11))

对于具有唯一节点的图,我们当然可以做出这种假设,但据我所知,DAG可以具有重复节点。。。那么我们该如何应对呢?此外,如何在Lisp中将其表示为列表?

表示DAG的正确方法是一组节点(顶点):

由于结构只有两个插槽,当然可以使用, 而不是细胞

所给树的列表表示形式 将有效负载与无子节点合并 把最右边的树枝弄乱了。 正确的表示是

(1 (2 (6) (7) (8)) (3) (4 (9 (12))) (5 (10) (11)))
现在,在子节点之间共享无子节点的DAG
(8)
节点的
(2…
(3…
应仅共享单元:

(1 (2 (6) (7) #1=(8)) (3 #1#) (4 (9 (12))) (5 (10) (11)))
看到和 为读者提供符号。 当然,不应该使用它们来创建DAG

下面是创建DAG的方法:

(defun make-node (&key payload children)
  (cons payload children))
(defparameter *my-dag*
  (let ((shared-mode (make-node :payload 8)))
    (make-node
     :payload 1
     :children
     (list (make-node :payload 2
                      :children (list (make-node :payload 6)
                                      (make-node :payload 7)
                                      shared-mode))
           (make-node :payload 3
                      :children (list shared-mode))
           (make-node :payload 4
                      :children (list (make-node :payload 9
                                                 :children (list (make-node :payload 12)))))
           (make-node :payload 5
                      :children (list (make-node :payload 10)
                                      (make-node :payload 11)))))))
(setq *print-circle* t)
*my-dag*
==> (1 (2 (6) (7) #1=(8)) (3 #1#) (4 (9 (12))) (5 (10) (11)))

仅列出具有两个节点ID的顶点:

((1 2) (1 3) (1 4) (1 5) (2 6) (2 7) (2 8) ... )
或者使用向量:

#((1 2) (1 3) (1 4) (1 5) (2 6) (2 7) (2 8) ... )
或者使用节点及其后续节点的列表:

((1 2 3 4 5) (2 6 7 8) (3 8) (4 9) ...)

使用这种表示法,如果图形包含重复项,我如何确保(2 6 7 8)和(3 8)实际上指向同一个8节点?@ChristianAbbott:两种方法:a)使用节点本身,b)使用节点ID谢谢!这看起来正是我要找的。这是否有效地将引用分配给同一个8节点?我对#n=使用什么整数值重要吗?或者这仅仅是一个参考值?您不应该自己使用
#n=
符号,您应该通过创建节点并用子节点和有效载荷填充它们来构建图形。完美。非常感谢。
((1 2 3 4 5) (2 6 7 8) (3 8) (4 9) ...)