我有以下工作程序:(可在此网站上测试:http://swish.swi-prolog.org,我已删除指向已保存程序的直接链接,因为我注意到任何人都可以编辑它。)
它在无向图中搜索两点之间的路径。重要的是,结果在“主”谓词的范围内返回。 (在Track变量中)
edge(a, b).
edge(b, c).
edge(d, b).
edge(d, e).
edge(v, w).
connected(Y, X) :-
(
edge(X, Y);
edge(Y, X)
).
path(X, X, _, []) :-
connected(X, _).
path(X, Y, _, [X, Y]) :-
connected(Y, X).
path(X, Z, Visited, [X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], Track).
main(X, Y) :-
path(X, Y, [], Track),
print(Track),
!.
结果:
?- main(a, e).
[a, b, d, e]
true
?- main(c, c).
[]
true
?- main(b, w).
false
我的问题:
访问节点列表以两种不同的方式传递给谓词。在绑定的Visited变量和未绑定的Track变量中。这两种不同形式的参数传递有哪些名称?
通常我只想使用未绑定的参数传递(Track变量),以使结果在主谓词的范围内。但是我也必须添加Visited变量,因为成员检查在Track变量上不起作用(我不知道为什么)。是否有可能只使用未绑定的方式传递Track? (没有Visited变量)
非常感谢!
答案 0 :(得分:1)
简短的回答:不,你不能避免额外的争论而不会使一切变得更加混乱。这是因为这种寻找路径的特定算法需要保持状态;基本上,你的额外论点是你的状态。
可能还有其他方法来保持状态,例如使用全局变量变量或动态更改Prolog数据库,但两者都更难以正确处理,并且涉及更多代码。
这个额外的参数通常被称为累加器,因为它会随着proof tree向下累积。最简单的例子是遍历一个列表:
foo([]).
foo([X|Xs]) :-
foo(Xs).
这很好,除非你在到达之前需要知道你已经看过的元素:
bar(List) :-
bar_(List, []).
bar_([], _).
bar_([X|Xs], Acc) :-
/* Acc is a list of all elements so far */
bar_(Xs, [X|Acc]).
这与您在代码中执行的操作大致相同。如果你特别注意这一点:
path(X, Z, Visited, /* here */[X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], /* and here */Track).
path/4
的最后一个参数在证明树中深度少一个时一个元素!当然,第三个参数是一个更长的时间(随着你走向证明树,它会增长)。
例如,您可以通过向上面的愚蠢bar
谓词添加另一个参数来反转列表:
list_reverse(L, R) :-
list_reverse_(L, [], R).
list_reverse_([], R, R).
list_reverse_([X|Xs], R0, R) :-
list_reverse_(Xs, [X|R0], R).
我不知道最后一个参数的任何特殊名称,一个在开头是免费的并且在最后保存解决方案。在某些情况下,它可能是输出参数,因为它意味着在以某种方式转换输入后捕获输出。在许多情况下,最好避免将参数视为严格的输入或输出参数。例如,length/2
:
?- length([a,b], N).
N = 2.
?- length(L, 3).
L = [_2092, _2098, _2104].
?- length(L, N).
L = [],
N = 0 ;
L = [_2122],
N = 1 ;
L = [_2122, _2128],
N = 2 . % and so on
注意:您的代码存在一些不重要的小问题,并且在Stackoverflow上提供这么多建议并不是一个好主意。如果您愿意,可以在Code Review上将其作为问题提交。
修改:您一定要学习this question。
我还提供了一个更简单的解决方案here。请注意使用term_expansion/2
在编译时从无向边创建有向边。更重要的是:你不需要main,只需从顶层调用你想要的谓词即可。当您删除剪切时,当From和To参数中的一个或两个都是自由变量时,您将获得所有可能的解决方案。