问题描述
设置边和顶点。而且,我正在显示未由边连接的顶点列表。
接下来我该怎么办?
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 ;
.......
欢迎您找到一种方法来消除重复项,或者更好的方法是首先不产生任何重复项。