带有先决条件的 Prolog 路径查找
Posted
技术标签:
【中文标题】带有先决条件的 Prolog 路径查找【英文标题】:Prolog Path Finding with Prerequisites 【发布时间】:2018-10-10 17:54:33 【问题描述】:所以我尝试自己制作这个程序,但我真的坚持下去了。问题如下:
给定网络中的任务 T,到 T 的路径是任务列表 从没有先决条件的任务 X 开始,以 T 结束,以及 这样列表中的每个元素,除了 X,都有它的前身作为 先决条件。
如果任务 T 没有先决条件,那么给定的只有一条路径 按列表 [T]。
否则到 T 的路径可以通过计算所有 T 的先决条件的路径并使用元素扩展这些路径 T.
一个列表Ts中所有任务路径的列表可以通过启动计算 使用空列表并附加通向每个列表的路径 连续元素。
定义谓词路径和所有路径以分别计算路径 到单个任务和列表中给出的任务,例如
?- paths(f,Paths). Paths = [[b, c, f]] ?- paths(g,Paths). Paths = [[e, g], [b, c, f, g], [k,h,g]].
先决条件是这样的:
prereqs(e,[]). prereqs(f,[c]). prereqs(g,[e,f,h]).
我尝试定义路径谓词,但我得到的不是一个列表,而是嵌套列表。
add(X, List, [X|List]).
path(T, [H|Hs]) :-
prereqs(T, []),
add(T, [], [H|Hs]).
path(T, [H|Hs]) :-
prereqs(T, [N|_]),
add(T,[] , Hs),
path(N, H).
我在询问时得到以下答案:
?- path(f, Path).
Path = [[[b], c], f] .
?- path(e, Path).
Path = [e] .
在这一点上,我不明白如何使它正确。
【问题讨论】:
【参考方案1】:你很接近,但列表语法似乎让你有点困惑。而且,不幸的是,您的 add
谓词没有帮助。
让我们尝试了解add
在您使用它的两种情况下的含义。在path
的第一个子句中,您的目标是add(T, [], [H|Hs])
。我们可以问 Prolog 这是什么意思:
?- add(T, [], [H|Hs]).
T = H,
Hs = [].
所以path
的第一个子句只有在Hs
是空列表时才适用(因此[H|Hs]
与[H]
相同)并且T
与H
相同。因此,我们可以像这样重写该子句:
path(T, [T]) :-
prereqs(T, []).
这看起来有道理,实际上是规范相关部分直接翻译成Prolog:
如果任务 T 没有先决条件,则列表 [T] 给出了一个到达它的单一路径。
现在让我们尝试在path
的第二个子句中使用add
。它采用以下形式:
?- add(T, [], Hs).
Hs = [T].
如上简化path
的第二个子句,使用这个等式,得到:
path(T, [H, T]) :-
prereqs(T, [N|_]),
path(N, H).
注意头部的第二个参数是[H, T]
,因为[H|Hs]
= [H|[T]]
= [H, T]
。因此,这只能对二元素列表成功,这就是您所看到的。 (每个列表的第一个元素可以是另一个嵌套的二元素列表。)
您正在寻找的是更多类似这些方面的东西:
path(T, Path) :-
prereqs(T, [N|_]),
path(N, PathToPrerequisite),
append(PathToPrerequisite, [T], Path).
这仍然有一个错误,它不会找到所有路径,但它至少可以生成它找到的正确格式的路径:
?- path(f, Path).
Path = [b, c, f] ;
false.
【讨论】:
感谢您的帮助。我现在会尝试这样做,以便显示所有路径。以上是关于带有先决条件的 Prolog 路径查找的主要内容,如果未能解决你的问题,请参考以下文章