17

考虑一个(元逻辑)谓词var_in_vars(Var, Vars),它接受一个变量Var和一个变量列表,Vars如果Var出现在Vars. 所以我们不需要确保它Var是一个变量,也不是一个变量Vars列表。

在 ISO Prolog 中表达这一点的最紧凑和最规范的方式是什么?以下是ISO/IEC 13211-1:1995 中内置函数的概述,包括 Cor.2:2012。

?- var_in_vars(V, [U,V,W]).
true.

?- var_in_vars(V, [X,Y,Z]).
false.
4

6 回答 6

8

一种可能:

var_in_vars(V, Vs) :- \+ unify_with_occurs_check(V, Vs).

更短:

var_in_vars(V, Vs) :- \+ subsumes_term(V, Vs).

编辑:未来的读者,请考虑问题的上下文,这是一个特定的紧凑性挑战,涉及给定情况下 ISO 谓词的表达性。

在其他情况下,您可能会从以下定义中受益更多:

var_in_vars(V, Vs) :-
        must_be(list, Vs),
        once((member(X, Vs), V == X)).
于 2014-12-10T00:24:51.170 回答
7

这个定义通过了测试,但是......我错过了一些微妙之处吗?

var_in_vars(V, [H|_]) :- V == H, !.
var_in_vars(V, [_|T]) :- var_in_vars(V, T).
于 2014-12-09T21:51:10.513 回答
5

这是另一个,虽然有点复杂:

var_in_vars(V, Vs) :-
   term_variables(Vs+V, Ws),
   Ws == Vs.

因此,这取决于访问变量的精确顺序。由于这在标准中得到了很好的定义,我们可以相信他们

...根据它们在从左到右遍历中的第一次出现出现...

这个定义的一个缺点是它具有与长度成正比的最小成本Vs。但是由于内部遍历通常非常有效地实现,所以这不是一个问题。

它有一个很大的优势:它只有在Vs是变量列表时才会成功。

于 2014-12-10T00:43:39.697 回答
2

另一种解决方案是:

var_in_vars(V, Vs) :-
    \+ (V = Vs, acyclic_term(Vs)).

但是@mat 的解决方案更好、更优雅,@CapelliC 的解决方案长期以来一直是最便携的解决方案(subsumes_term/2谓词只是最近才标准化,并非所有系统都提供unify_with_occurs_check/2谓词)。

于 2015-06-03T09:26:13.703 回答
2

解决方案@false 可以简化为:

var_in_vars(V, Vs) :-
    term_variables(Vs+V, Vs).

VVs列表的成员时,第二个参数返回Vs(由于术语的从左到右遍历Vs+V)。当V不是 的成员时Vs,第二个参数返回一个比它多一个元素的列表,Vs因此不能与它统一。尽管在第二个参数中有一个隐含的统一,但在这两种情况下都不存在创建循环项的危险。即统一是 STO 在这个简化的解决方案中不是问题。

但是对于性能而言,这种简化值得吗?使用相等,(==)/2有可能更早失败,从而使原始解决方案更快。

于 2015-06-03T10:16:01.023 回答
-1

溶液合成

解决方案:

var_in_vars(V, Vs) :- \+ subsumes_term(V, Vs).

备选方案 1:简单

var_in_vars(V, Vs) :- \+ unify_with_occurs_check(V, Vs).

备选方案 2:根据情况,这可能更合适

var_in_vars(V, Vs) :-
        must_be(list, Vs),
        once((member(X, Vs), V == X)).

备选方案 3:更复杂

var_in_vars(V, Vs) :-
   term_variables(Vs+V, Ws),
   Ws == Vs.

备选方案 4:其他可能性

var_in_vars(V, [H|_]) :- V == H, !.
var_in_vars(V, [_|T]) :- var_in_vars(V, T).

链接:

标准


注意:问题的上下文,这是一个特定的紧凑性挑战,涉及给定情况下 ISO 谓词的表达性。

于 2015-06-03T02:34:36.650 回答