转载自:https://mp.weixin.qq.com/s/ymcl69qtM2sYA6O9wxv_JA
3、从给定节点循环
cycle(G,A,P) :- P是从图形G中的节点A开始的封闭路径。G以图项形式给出。
1 :- ensure_loaded(p6_01). % conversions
2 :- ensure_loaded(p6_02). % adjacent/3 and path/4
3
4 cycle(G,A,P) :-
5 adjacent(B,A,G),
6 path(G,A,B,P1),
7 length(P1,L),
8 L > 2,
9 append(P1,[A],P).
行注释:
1. 载入’图 练习1’转换程序
2. 载入’图 练习2’ adjacent/3 and path/4程序
3. 空行
4.
5. B与A邻接
6. A到B有非循环路径
7. 获取路径P1的长度L
8. 确保路径长度大于2(确保不是圈)
9. 将节点A加入到路径P1后到P
测试:
?- consult(‘p6_01.pl').
?- consult(‘p6_02.pl').
?- human_gterm([b-c, f-c, g-h, d, f-b, k-f, h-g],G),cycle(G,A,P).
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = c,
P = [c, f, b, c] ;
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = f,
P = [f, c, b, f] ;
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = f,
P = [f, b, c, f] ;
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = b,
P = [b, f, c, b] ;
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = b,
P = [b, c, f, b] ;
G = graph([b, c, d, f, g, h, k], [e(b, c), e(b, f), e(c, f), e(f, k), e(g, h)]),
A = c,
P = [c, b, f, c] ;
false.
4、构造所有生成树
s_tree(G,T) :- T是图G的生成树
1 :- ensure_loaded(p6_01). % 图 练习 1的转换程序
2
3 s_tree(graph([N|Ns],GraphEdges), graph([N|Ns],TreeEdges)) :-
4 transfer(Ns,GraphEdges,TreeEdgesUnsorted),
5 sort(TreeEdgesUnsorted,TreeEdges).
6
行注释:
1. 载入图 练习1中程序
2. 空行
3. 将图边GraphEdges转为树边TreeEdges
4. 取节点列表的N(无表首N),将图边GraphEdges转为树边TreeEdgesUnsorted
5. 将列表TreeEdgesUnsorted排序,结果表为TreeEdges
6. 空行
transfer(Ns,GEs,TEs) :- 将边从GEs(graph edges)转到TEs(tree edges),直到尚未连接的树节点列表NS变为空。当且仅当一个端点已连接到树而另一个端点未连接时,才接受边。
7 transfer([],_,[]).
8 transfer(Ns,GEs,[GE|TEs]) :-
9 select(GE,GEs,GEs1),
10 incident(GE,X,Y),
11 acceptable(X,Y,Ns),
12 delete(Ns,X,Ns1),
13 delete(Ns1,Y,Ns2),
14 transfer(Ns2,GEs1,TEs).
15
行注释:
7. 终止条件
8.
9. 从列表GEs中取出元素GE后,结果列表为GEs1
10. 从GE中解析出X和Y
11. 确定Y,Y是否在Ns中可接受
12. 从Ns中删除X结果列表为Ns1
13. 从Ns1中删除X结果列表为Ns2
14. 继续递归
15. 空行
16 incident(e(X,Y),X,Y).
17 incident(e(X,Y,_),X,Y).
18
行注释:
16. 从无标记中解析
17. 从有标记中解析
18. 空行
19 acceptable(X,Y,Ns) :-
20 memberchk(X,Ns),
21 \+ memberchk(Y,Ns),
22 !.
23 acceptable(X,Y,Ns) :-
24 memberchk(Y,Ns),
25 \+ memberchk(X,Ns).
26
行注释:
19. 提示:要匹配X-Y和Y-X两个表示法
20. X在列表Ns中
21. Y不在Ns中
22. 截断
23.
24. Y在列表Ns中
25. X不在Ns中
26.
is_tree(G) :- 判断G是树
27 is_tree(G) :-
28 s_tree(G,G), !.
29
is_connected(G) :- 判断图G是否连接,是树则连接
30 is_connected(G) :-
31 s_tree(G,_), !.
32
p6_04.dat是文件
33 test :-
34 see('p6_04.dat'),
35 read(G), seen,
36 human_gterm(H,G),
37 write(H), nl,
38 setof(T,s_tree(G,T),Ts),
39 length(Ts,N),
40 write(N).
行注释:
33. 测试
34. 将输入流转为文件p6_04.dat
35. 将读到的信息放到G,seen是恢复到原输入流
36. 将G转为H
37. 输出H,后nl输出换行
38. 内置谓词
39. 生成所有无重复的树的列表Ts
40. 有N个数
测试:
?- test.
[a-b,a-d,b-c,b-e,c-e,d-e,d-f,d-g,e-h,f-g,g-h]
112
true ;
false.