繁体   English   中英

prolog - 检查结果后写出结果

[英]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).

如果XY之间有一条边,则它是路径的末端,并且两个节点都在列表中。 否则必须有一个中间节点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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM