带有先决条件的 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] 相同)并且TH 相同。因此,我们可以像这样重写该子句:

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 路径查找的主要内容,如果未能解决你的问题,请参考以下文章

PROLOG通过条件获得名称

prolog中的路径查找

Prolog中定义图:边和路径,查找两个顶点之间是不是有路径

PROLOG - 条件函数

搜索所有有条件的父亲在Prolog

gerrit prolog提交规则条件检查