[英]prolog - write out result after checking result
我一直在编写代码,以便我能够搜索图形中是否有路径,如果有路径,我想打印出路径,如果有,我想打印出所有路径。 我有一个条件,如果谓词为真,则写入路径但它从不打印,我应该怎么做?
%graph
edge(a,b).
edge(a,c).
edge(b,c).
edge(c,d).
edge(c,e).
edge(d,e).
edge(f,g).
edge(g,h).
% condition
allways(X,Y) :-
edge(X,Y).
% recursion
allways(X,Y) :-
edge(X,B),
allways(B,Y).
%print out path if there is one (its meant to print out all paths it can find)
allways(P,Y) == true -> writepath(X,Y).
writepath(X,Y):-
edge(X,Y).
writepath(X,Y) :-
edge(X,B),
write(B),
writepath(B,Y).
您是否考虑过添加一个列表作为第三个参数来收集路径上的节点? 不是使用 write/1 来输出每个节点,您将拥有一个包含每个解决方案从开始到目的地的所有节点的列表。 考虑对您的代码进行以下更改:
allways(X,Y,[X,Y]) :-
edge(X,Y).
allways(X,Y,[X|Nodes]) :-
edge(X,B),
allways(B,Y,Nodes).
如果X
和Y
之间有一条边,则它是路径的末端,并且两个节点都在列表中。 否则必须有一个中间节点B
并且只有X
在列表中。 此谓词产生所需的结果:
?- allways(a,e,P).
P = [a, b, c, e] ;
P = [a, b, c, d, e] ;
P = [a, c, e] ;
P = [a, c, d, e] ;
false.
现在,您将获得从起点到终点的每条路径的节点列表。 但是,此查询只会终止,因为您提供的图形是非循环的。 考虑添加一条边,使图包含一个循环:
edge(a,b).
edge(a,c).
edge(b,c).
edge(c,e).
edge(c,d).
edge(d,e).
edge(f,g).
edge(g,h).
edge(c,a). % <- new edge
现在由于新添加的循环,上面的查询循环:
?- allways(a,e,P).
P = [a, b, c, e] ;
P = [a, b, c, d, e] ;
P = [a, b, c, a, b, c, e] ;
P = [a, b, c, a, b, c, d, e] ;
P = [a, b, c, a, b, c, a, b, c, e] ;
P = [a, b, c, a, b, c, a, b, c, d, e] ;
P = [a, b, c, a, b, c, a, b, c, a, b, c, e] ;
.
.
.
如果您不想要这种行为,您可以添加一个已访问节点列表作为附加参数。 我还建议一个更具描述性的名称,比如调用谓词的 start_dest_path/3 和实际关系的 start_dest_path_visited/4 :
:- use_module(library(apply)).
start_dest_path(S,D,P) :-
start_dest_path_visited(S,D,P,[]).
start_dest_path_visited(S,D,[S,D],Vs) :-
maplist(dif(S),Vs),
edge(S,D).
start_dest_path_visited(S,D,[S|Nodes],Vs) :-
maplist(dif(S),Vs),
edge(S,X),
start_dest_path_visited(X,D,Nodes,[S|Vs]).
谓词 start_dest_path/3 正在调用带有空累加器的 start_dest_path_visited/4。 start_dest_path_visited/4 中的目标maplist(dif(S),Vs)
确保节点S
尚未被访问。 现在查询也以循环结束:
?- start_dest_path(a,e,P).
P = [a, b, c, e] ;
P = [a, b, c, d, e] ;
P = [a, c, e] ;
P = [a, c, d, e] ;
false.
尽管路径不能包含循环,但此定义允许路径是一个大循环。 考虑以下查询:
?- start_dest_path(a,a,P).
P = [a, b, c, a] ;
P = [a, c, a] ;
false.
如果要排除此类解决方案,请在 start_dest_path_visited/4 的非递归规则中添加目标maplist(dif(D),Vs)
。
请注意谓词 start_dest_path_visited/4 如何仍然类似于原始帖子中的 allways/2 结构,带有两个附加参数(路径和访问节点列表)和一个附加目标(maplist/2)。 您可以在此和此答案中看到加权路径的定义略有不同。 您可能还对这个问题和相应答案中建议的更通用的定义感兴趣。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.