确定两个集团是否不同

问题描述

假设我有一个图,并且想在图的后面找到2个不同的集团。集团是图顶点的子集,所有图顶点都连接在一起。具有2个集团(a,b,c)和(b,c,d)的集团大小为3的示例图:

edge(a,b). edge(a,c). edge(b,c). edge(d,b).
vertex(X;Y) :- edge(X,Y).

enter image description here

获得2个团体非常简单:

#const cs=3. % cliquesize
cs{clique1(X) : vertex(X)}cs.
:- clique1(X),clique1(Y),X!=Y,not edge(X,Y),not edge(Y,X).
cs{clique2(X) : vertex(X)}cs.
:- clique2(X),clique2(Y),X).

#show clique1/1.
#show clique2/1.

给予:

Answer: 1
clique2(d) clique1(a) clique2(b) clique2(c) clique1(b) clique1(c)
Answer: 2
clique2(d) clique1(d) clique2(b) clique2(c) clique1(b) clique1(c)
Answer: 3
clique2(a) clique1(a) clique2(b) clique2(c) clique1(b) clique1(c)
Answer: 4
clique2(a) clique1(d) clique2(b) clique2(c) clique1(b) clique1(c)
SATISFIABLE

可以解释为:

Answer 1: (a,b,c),(b,c,d)
Answer 2: (b,d),d)
Answer 3: (a,(a,c)
Answer 4: (b,c)

但是如何检验两个派别是否不同?我尝试过

differ() :- clique1(X),X!=Y.
:- not differ().

但这对输出没有影响。如何测试两个集团是否不同?


现在我找到了此解决方案:

differ() :- clique1(X),vertex(X),not clique2(X).
:- not differ().

它可以工作,但我不喜欢它需要2行。如何将其置于一个约束中?

解决方法

如何将其置于一个约束中?

这有点棘手,因为您基本上想要一个存在的量化:“各派之间必须至少有一个顶点差异”,因此简单地插入派生differ/0的规则主体是行不通的。 (因为这将是所有顶点的通用量化)

我认为以下内容将满足您对单行约束的要求:

:- #count{X : clique1(X),not clique2(X)} < 1.

但是,取决于输入图的大小,我可以想象这可能会导致性能问题。

我不确定您的确切要求,但也许您可以采用稍微不同的方法:

  • 仅查找一个集团(基本上将clique2部分注释掉)
  • 通过从clingo请求的答案集的数量来配置您实际想要的小集团的数量。

在您的情况下,那将是..$clingo -n 2 clique.asp,另外的好处是,每个答案集只能得到一个团体,而您想要的却是(不同的)团体。