转载自:https://mp.weixin.qq.com/s/QHLodTI9LDrapgCtVs1Wng
上一练习中所需文件p6_04.dat的内容:
graph([a, b, c, d, e, f, g, h], [e(a, b), e(a, d), e(b, c), e(b, e), e(c, e), e(d, e), e(d, f), e(d, g), e(e, h), e(f, g), e(g, h)]).
5、构造标记图的最小生成树
ms_tree(G,T,S) :- T是图G的最小生成树。S是边值的总和。 Prim的算法。
程序p6_05.pl
1 :- ensure_loaded(p6_01). %图 练习 1的转换程序
2 :- ensure_loaded(p6_04). %transfer/3, incident/3, and accept/3
3
4 ms_tree(graph([N|Ns],GraphEdges),graph([N|Ns],TreeEdges),Sum) :-
5 predsort(compare_edge_values,GraphEdges,GraphEdgesSorted),
6 transfer(Ns,GraphEdgesSorted,TreeEdgesUnsorted),
7 sort(TreeEdgesUnsorted,TreeEdges),
8 edge_sum(TreeEdges,Sum).
9
行注释:
1. 载入图 练习1中程序
2. 载入图 练习3中标题序号为4的程序
3. 空行
4. GraphEdges是图列表[N|Ns]的最小生成树,Sum是边值的总和
5. 按谓词compare_edge_values规则对列表GraphEdges排序排好序的列表为GraphEdgesSorted
6. 参看图 练习3中’4’
7. 将TreeEdgesUnsorted排序结果放入TreeEdges
8. 计算TreeEdges的边的总和,放入Sum
9.
10 compare_edge_values(Order,e(X1,Y1,V1),e(X2,Y2,V2)) :-
11 compare(Order,V1+X1+Y1,V2+X2+Y2).
12
13 edge_sum([],0).
14 edge_sum([e(_,_,V)|Es],S) :-
15 edge_sum(Es,S1),
16 S is S1 + V.
17
行注释:
10.
11. 内置谓词:确定标准项中两个项之间的顺序(Order)。顺序(Order)是<,>或=之一,其含义很明显。
12.
13. 终止条件
14.
15. 继续递归
16. S是S1+V
17.
18 test :-
19 see('p6_05.dat'),
20 read(G),
21 seen,
22 human_gterm(H,G),
23 write(H), nl,
24 ms_tree(G,T,S),
25 human_gterm(TH,T),
26 write(S), nl,
27 write(TH).
行注释:
18.
19. 将输入流转到文件’p6_05.dat’
20. 读取的结果放入G
21. 将输入流转回原输入流
22. 参看图 练习1
23. 输出H
24. 将G转为T(最小生成树)S为边值的总和
25. 将T转为TH(与H比较下)
26. 输出S
27. 输出TH
内置谓词predsort/3: 排序类似于sort / 2,但通过调用Pred(-Delta,+ E1,+ E2)确定两个项的顺序。该调用必须将Delta与<,>或=中的一个统一。如果使用内置谓词compare / 3,则结果与sort / 2相同。另请参阅keysort / 2。
所需文件p6_05.dat的内容:
graph([a, b, c, d, e, f, g, h], [e(a, b, 5), e(a, d, 3), e(b, c, 2), e(b, e, 4), e(c, e, 6), e(d, e, 7), e(d, f, 4), e(d, g, 3), e(e, h, 5), e(f, g, 4), e(g, h, 1)]).
测试:
?- test.
[a-b/5,a-d/3,b-c/2,b-e/4,c-e/6,d-e/7,d-f/4,d-g/3,e-h/5,f-g/4,g-h/1]
22
[a-b/5,a-d/3,b-c/2,b-e/4,d-f/4,d-g/3,g-h/1]
true .
6、同构图
这仅是图的解决方案。为有向图写相应的谓词并不困难
程序p6_06.pl
1 :- ensure_loaded(p6_01). % conversions
2
% isomorphic(G1,G2) :- 图G1和G2是同构的
3 isomorphic(G1,G2) :-
4 isomorphic(G1,G2,_).
5
行注释:
1. 载入图 练习1中程序
2.
3.
4. 常用编程技巧
5.
% isomorphic(G1,G2,Iso) :- 图G1和G2是同构的。
% Iso是代表图的节点集之间的双射的列表。它是一个开放式列表,包含每对对应节点的i(X,Y)项
6 isomorphic(graph(Ns1,Es1),graph(Ns2,Es2),Iso) :-
7 append(Es1,Ns1,List1),
8 append(Es2,Ns2,List2),
9 isomo(List1,List2,Iso).
10
% isomo(List1,List2,Iso) :- List1和List2表示的图是同构的。
行注释:
6.
7. 内置谓词
8. 内置谓词
9. List1和List2表示的图是同构的
10.
11 isomo([],[],_) :- !.
12 isomo([X|Xrest],Ys,Iso) :-
13 select(Y,Ys,Yrest),
14 iso(X,Y,Iso),
15 isomo(Xrest,Yrest,Iso).
行注释:
11. 终止条件
12.
13. 内置谓词,Yrest是删除列表Ys中元素Y的列表。
14. X与Y的边对应或同为鼓励顶点
15.
% iso(E1,E2,Iso) :- 一个图中的边E1对应于另一图中的边E2。请注意,边是无向的。
% iso(N1,N2,Iso) :- 匹配孤立的顶点.
16 iso(E1,E2,Iso) :-
17 edge(E1,X1,Y1),
18 edge(E2,X2,Y2),
19 bind(X1,X2,Iso),
20 bind(Y1,Y2,Iso).
21 iso(E1,E2,Iso) :-
22 edge(E1,X1,Y1),
23 edge(E2,X2,Y2),
24 bind(X1,Y2,Iso),
25 bind(Y1,X2,Iso).
26 iso(N1,N2,Iso) :-
27 \+ edge(N1,_,_),
28 \+ edge(N2,_,_), % 孤立的顶点
29 bind(N1,N2,Iso).
30
行注释:
16.
17. E1是X1,Y1的边
18. E2是X2,Y2的边
19. 将X1绑定到X2作为双射Iso的一部分
20. 将Y1绑定到Y2作为双射Iso的一部分
21.
22. E1是X1,Y1的边
23. E2是X2,Y2的边
24. 将X1绑定到Y2作为双射Iso的一部分
25. 将Y1绑定到X2作为双射Iso的一部分
26.
27. N1不是边
28. N2不是边
29. 将N1绑定到N2作为双射Iso的一部分(孤立顶点)
30.
31 edge(e(X,Y),X,Y).
32 edge(e(X,Y,_),X,Y).
33
% bind(X,Y,Iso) :- 可以将X绑定到Y作为双射Iso的一部分;即项i(X,Y)已经在Iso列表中,或者可以在不违反规则的情况下将其添加到其中。请注意,如果将i(X,Y)添加到Iso,则bind(X,Y,Iso)可确保X和Y都是“新的”。
34 bind(X,Y,Iso) :-
35 memberchk(i(X,Y0),Iso),
36 nonvar(Y0),
37 !,
38 Y = Y0.
39 bind(X,Y,Iso) :-
40 memberchk(i(X0,Y),Iso),
41 X = X0.
42
行注释:
31. 无标识边
32. 有标识边
33. 空行
34.
35. 项i(X,Y0)在Iso中
36. Y0不是变量
37. 截断
38. 将Y0绑定到Y
39.
40. 项i(X0,Y)在Iso中
41. 将X0绑定到X
42.
43 test(1) :-
44 human_gterm([f-e,e-d,e-g,c-e,c-b,a-b,c-d,beta],G1),
45 human_gterm([6-3,6-4,3-4,alfa,4-5,7-4,6-2,1-2],G2),
46 isomorphic(G1,G2,Iso), write(Iso).
47 test(2) :-
48 human_gterm([f-e,e-d,e-g,c-e,c-b,a-b,c-d,beta],G1),
49 human_gterm([6-3,6-4,3-4,4-5,7-4,6-2,1],G2),
50 isomorphic(G1,G2,Iso), write(Iso).
51 test(3) :-
52 human_gterm([a-b,c-d,e,d-f],G1),
53 human_gterm([1-2,1-3,5,4-6],G2),
54 isomorphic(G1,G2,Iso), write(Iso).
行注释:
43. 测试1
44. 将参数1转为G1
45. 将参数1转为G2
46. 验证同构
47. 测试2
48. 将参数1转为G1
49. 将参数1转为G2
50. 验证同构
51. 测试3
52. 将参数1转为G1
53. 将参数1转为G2
54. 验证同构
?- test(1).
[i(a,1),i(b,2),i(c,6),i(d,3),i(e,4),i(f,5),i(g,7),i(beta,alfa)|_21202]
true .
?- test(2).
false.
?- test(3).
[i(a,4),i(b,6),i(c,2),i(d,1),i(f,3),i(e,5)|_1556]
true .