SWI Prolog中无向图的最大空子图

问题描述

给出了无向图。查找图形的内部稳定性数。这意味着找到最大的空子图的幂。 (空子图是一个没有顶点通过边直接连接的子图。)

设置边和顶点。而且,我正在显示未由边连接的顶点列表。

接下来我该怎么办?

reb(a,1,2).   % (* 1 ---a--- 2 ---b--- 3 ---d--- 4 ---e--- 6  *)
reb(b,2,3).   % (*  \_________c_______/                   /   *)
reb(c,3).   % (*                      7 ---g--- 5 ---f-*    *)
reb(d,3,4).                             
reb(e,4,6).
reb(f,5,6).
reb(g,7).

ver(1).   % (* empty subgraphs here are                   *)
ver(2).   % (*  145,146,147,245,246,247,35,36,... *)
ver(3).   % (* the length of the largest of them is 3     *)
ver(4).   
ver(5).
ver(6).
ver(7).

edge(A,B) :- reb(_,A,B) ; reb(_,B,A).

nonadjacency(A,B) :-
    ver(A),ver(B),\+(edge(A,B)).

do(L) :-
    findall( (A,B),nonadjacency (A,L),write(L),nl.

dfs(From,To,_,[edge(From,To)]) :-
    edge(From,To).

dfs(From,Visitednodes,[(From,X) | TailPath]) :- 
    edge(From,X),not(member(X,Visitednode)),dfs(X,[From | Visitednodes],TailPath).

解决方法

让我们让 Prolog 为我们努力工作,而不是自己努力构造未连接的子图(您称为“空”)子图,构造一个最大的子集,而不是 not “非空”,即已连接:

empty_subgraph(       E,M ) :-
    findall( X,ver(X),Vertices),subset( Vertices,E ),\+ is_connected(  E ),length(           E,M ).

is_connected(  E ) :-
    select( A,E,N ),select( B,N,_),\+ \+ ( reb(_,A,B) ; reb(_,B,A) ).   % an edge exists

使用select/3

剩下的就是枚举Vertices的子集,从最大到最小。

简单的代码不会削减它:

subset( S,S).
subset( S,X) :- select(_,S,N),subset( N,X).

你知道为什么吗?

。 。

。 。

答案是Prolog的深度优先搜索策略。为了在较短的子集之前获得较大的子集,我们需要广度优先搜索。将不得不自己编写代码:

subset( S,X) :- XS = [S|T],bfs_subsets(XS,T),member(X,XS).

bfs_subsets( [[] | _],[]  ) :- !.
bfs_subsets( [[_]| _],[[]]) :- !.
bfs_subsets( [S  | T],Q ) :-
    findall( N,select(_,NS ),append( NS,Z,Q ),bfs_subsets(   T,Z ).

有很多多余的答案,但是生成它们的顺序是我们想要的。正确至上,效率至上!产生的第一个答案将是最长的空白子图中的一个,我们不在乎哪个。

70 ?- empty_subgraph( E,M ).
E = [3,6,7],M = 3 ;
E = [3,M = 3 ;
E = [2,4,M = 3 ;
.......

欢迎您找到一种方法来消除重复项,或者更好的方法是首先不产生任何重复项。