prolog - 写入未命名变量

标签 prolog

我正在 Prolog (gprolog) 中编写一个在图上查找路径的程序。我部分基于 this SO post .

让我举个例子。这是我绘制的示例图:example graph

这是代码最初的样子:

path([Goal],Goal,Goal).
path(P,Start,Goal) :- adjacent(Start,X),
                      \+ (memberchk(X,P)),
                      (
                        Goal=X
                      ;
                        path([Start|P],X,Goal)
                      ).

无论该基本情况是否多余,问题都在这里。我想要的输入样式为

| ?- path(P,a,f).

对于该输入,我会得到输出

P = [a,s,f]

true ?

但是,现有代码的问题在于 memberchk。对于 memberchk(a,P),它尝试统一,调用 memberchk(a,[a|_]),并返回 true。我不希望发生这种情况,因此我首先检查 P 是否使用 var/1 谓词实例化。因此,我的代码更改为

path([Goal],Goal,Goal).
path(P,Start,Goal) :- var(P), 
                      path([],Start,Goal).
path(P,Start,Goal) :- adjacent(Start,X),
                      \+ (memberchk(X,P)),
                      (
                        Goal=X
                      ;
                        path([Start|P],X,Goal)
                      ).

现在,如果 P 未实例化,我们将使用空列表调用 path/3我的问题是这样的:现在我无法在最后打印 P,因为我调用 path([],Start,Goal)P 不再与 [] 关联。

我尝试过使用 write/1 谓词,但它要么在每一步打印出 P ,要么打印出 P = _26 (意思是它打印的是未实例化的 P,而不是 P 的最终值)。

我希望这是一个简单的问题,我对 Prolog 还很陌生。

如果有人问过类似的问题,我们深表歉意;我很乐意被指出其他可能有帮助的问题。在发布此内容之前,我通过 SO 和 Google 进行了搜索。

最佳答案

您需要的概念是累加器

您实际上非常接近:您确实意识到将 P 初始化为 [],并用 [Start|P] 填充它作为你递归是一种工作策略。这称为累加器,要获得最终结果,您只需添加另一个参数

这是您查询的新 path/3 谓词:

path(P, Start, Goal) :-
    path([], P, Start, Goal).

如您所见,这里我们将 [] 添加为 path/4 的第一个参数,我们的实现如下:

path(L, P, Goal, Goal) :-
    reverse([Goal|L], P).
path(L, P, Start, Goal) :- 
    adjacent(Start, X),
    \+ (memberchk(X, L)),
    path([Start|L], P, X, Goal).

第一个子句用于终止递归。一旦 StartGoal 参数与您注意到的相同,递归就应该结束。当使用累加器时,这意味着我们将累加器与输出参数统一起来。但是,累加器包含相反的答案(并且缺少最终目标),因此我们有 reverse([Goal|L], P)

第二个子句与您编写的内容非常相似,但我们现在需要将 P 按原样传递给递归子句。请注意,我已经删除了该子句中的析取,在这种情况下不需要它。

完整代码:

path(P, Start, Goal) :-
    path([], P, Start, Goal).
path(L, P, Goal, Goal) :-
    reverse([Goal|L], P).
path(L, P, Start, Goal) :- 
    adjacent(Start, X),
    \+ (memberchk(X, L)),
    path([Start|L], P, X, Goal).

关于prolog - 写入未命名变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43035831/

相关文章:

Prolog:平铺程序

prolog - 用累积表示设置时间

http - 在 Prolog 中处理 PWP HTML 页面内的 http 查询字符串

Prolog 约束处理 : Packing Squares

list - 我应该如何删除列表中的非数字使用序言

arrays - 给定一个枢轴,如何在序言中分解列表?

prolog - 如何检查变量是否在 Prolog 中实例化?

prolog - Prolog 地下

Prolog DCG 使用 separotr 从文件中读取

algorithm - 理解 Prolog 中的冒泡排序解决方案