简体   繁体   English

prolog - 检查结果后写出结果

[英]prolog - write out result after checking result

i have been writing code so that im able to search if there is a path in a graph and if there is one i would want to print out the path, if there is one i would like to print out all of them.我一直在编写代码,以便我能够搜索图形中是否有路径,如果有路径,我想打印出路径,如果有,我想打印出所有路径。 i have a condition that writes the path if the predicate is true but it never prints, how should i go about this?我有一个条件,如果谓词为真,则写入路径但它从不打印,我应该怎么做?

%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).

Have you considered adding a list as third argument to collect the nodes along the path?您是否考虑过添加一个列表作为第三个参数来收集路径上的节点? Instead of using write/1 to output every node, you'd have a list with all nodes from start to destination for every solution.不是使用 write/1 来输出每个节点,您将拥有一个包含每个解决方案从开始到目的地的所有节点的列表。 Consider the following change to your code:考虑对您的代码进行以下更改:

allways(X,Y,[X,Y]) :-
   edge(X,Y).
allways(X,Y,[X|Nodes]) :-
   edge(X,B),
   allways(B,Y,Nodes).

If there is an edge between X and Y it's the end of the path and both nodes are in the list.如果XY之间有一条边,则它是路径的末端,并且两个节点都在列表中。 Otherwise there has to be an intermediary node B and only X is in the list.否则必须有一个中间节点B并且只有X在列表中。 This predicate yields the desired result:此谓词产生所需的结果:

?- 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.

Now you get a list of nodes for every path from start to destination.现在,您将获得从起点到终点的每条路径的节点列表。 However, this query only terminates because the graph you provided is acyclic.但是,此查询只会终止,因为您提供的图形是非循环的。 Consider adding an edge such that the graph contains a cycle:考虑添加一条边,使图包含一个循环:

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

Now the above query loops because of the newly added cycle:现在由于新添加的循环,上面的查询循环:

?- 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] ;
.
.
.

If you do not want this behaviour, you can add a list of visited nodes as an additional argument.如果您不想要这种行为,您可以添加一个已访问节点列表作为附加参数。 I would also suggest a more descriptive name, say start_dest_path/3 for the calling predicate and start_dest_path_visited/4 for the actual relation:我还建议一个更具描述性的名称,比如调用谓词的 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]).

The predicate start_dest_path/3 is calling start_dest_path_visited/4 with an empty accumulator.谓词 start_dest_path/3 正在调用带有空累加器的 start_dest_path_visited/4。 The goal maplist(dif(S),Vs) in start_dest_path_visited/4 makes sure the node S has not already been visited. start_dest_path_visited/4 中的目标maplist(dif(S),Vs)确保节点S尚未被访问。 Now the query terminates with the cycle as well:现在查询也以循环结束:

?- 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.

Although the path cannot contain cycles this definition allows the path to be one big cycle.尽管路径不能包含循环,但此定义允许路径是一个大循环。 Consider the following query:考虑以下查询:

?- start_dest_path(a,a,P).
P = [a, b, c, a] ;
P = [a, c, a] ;
false.

If you want to exclude such solutions, add a goal maplist(dif(D),Vs) to the non-recursive rule of start_dest_path_visited/4.如果要排除此类解决方案,请在 start_dest_path_visited/4 的非递归规则中添加目标maplist(dif(D),Vs)

Note how the predicate start_dest_path_visited/4 still resembles the structure of allways/2 from your original post with two additional arguments (path and list of visited nodes) and an additional goal (maplist/2).请注意谓词 start_dest_path_visited/4 如何仍然类似于原始帖子中的 allways/2 结构,带有两个附加参数(路径和访问节点列表)和一个附加目标(maplist/2)。 You can see a slightly different definition for weighted paths in this and in this answer.您可以在答案中看到加权路径的定义略有不同。 You might also be interested in a more generic definition as suggested in this question and the corresponding answers.您可能还对这个问题和相应答案中建议的更通用的定义感兴趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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