2

我想以这样的方式将变量绑定到几个原子,以便稍后它将与这些原子之一统一。直觉上它应该像这样工作(假设 ; 是可能值的析取):

    ?- X = (apple; pear), X = apple.
    X = apple.

    ?- X = (apple; pear), X = apple, X = pear.
    false.

    ?- X = (apple; pear; orange), X = (apple; orange).
    X = (apple; orange).

    ?- X = (apple; orange), X = (pear; orange).
    X = orange. 

    ?- X = (apple; orange), X = pear.
    false. 

如您所见,这个想法接近类型层次结构的概念。所以,我想知道是否有一些内置的(元)谓词可以很容易地做这样的事情,或者是否有一些常用的方法使用某种数据结构来建模,或者我必须构建这种谓词从头开始?

4

4 回答 4

2

正如您从其他答案中看到的那样,使用 Prolog 有一种直接的方式来表达这一点,使用析取(留下选择点),或者通过明确推理集合及其交集。

另一种方法是使用约束,它可以让您推迟目标直到知道更多:例如,您可以将原子映射到整数,然后使用CLP(FD)将变量的成员资格表示为具有特定整数域的集合约束。或者,您可以使用属性变量或约束处理规则 ( CHR ) 实现一个自定义约束求解器,该求解器对原子进行推理。这两种情况的主要优势是您获得了重新排序目标的更多自由,并且在发布更多约束时会隐式调用约束推理。

编辑:例如,考虑使用CLP(FD) 约束来解决您的任务。最多只需进行最少的修改,以下示例就可以在 SICStus、SWI、YAP 和其他系统中运行。根据您的 Prolog 系统,您可能需要导入合适的库来使用其中一些谓词:

水果整数(苹果,0)。
水果整数(梨,1)。
水果整数(橙色,2)。

variable_fruits(Var, Fruits) :-
        maplist(fruit_integer, Fruits, Integers),
        foldl(domain_, 整数, 1..0, D),
        D中的Var

domain_(E, D0, D0 \/ E)。

在这种情况下,关键思想是将fruits 映射到 integers,以便您可以使用 CLP(FD) 约束来表达所有包含的内容。

您的示例查询和答案::

?- variable_fruits(X, [apple,pear]),fruit_integer(apple, X)。
X = 0。

?- variable_fruits(X, [apple,pear]),
   水果整数(苹果,X),
   水果整数(梨,X)。
的。

?- variable_fruits(X, [apple,pear,orange]),
   可变水果(X,[苹果,橙子])。
X 在 0\/2中。

?- variable_fruits(X, [apple,orange]),
   可变水果(X,[梨,橙])。
X = 2。

?- variable_fruits(X, [apple,orange]),
   水果整数(梨,X)。
的。

显然,您也可以fruit_integer/2另一个方向使用,并将这些整数和域转换回atom列表。我把它作为一个简单的练习。

正是由于这个原因,CLP(FD) 约束被称为有限域上的约束:所有有限域都可以映射到整数的有限子集。因此,CLP(FD) 约束不仅可用于表示一般的整数算术,还可用于推理任意有限集。有关详细信息,请参阅

一些附加说明:

  • 所有最广泛使用的 Prolog 系统都附带 CLP(FD) 约束,如果您使用它们,您的解决方案将非常便携。
  • 一些 Prolog 系统附带了用于集合的专用约束求解 。如果您的系统支持这一点,这可能值得研究。
  • CHR 是一种用于定义自定义传播规则的有用语言,非常值得研究,尤其是对于更复杂的任务。
  • 直接使用属性变量接口会降低您的解决方案的可移植性,因此我建议您使用更高级别的方法之一。首先尝试 CLP(FD)(因为它最容易应用),然后查看 CHR,然后才考虑实现自定义求解器。
于 2013-05-25T23:34:17.063 回答
1

您可以使用member/2

24 ?- member(X, [apple, pear]), member(X, [apple]).
X = apple ;
false.

25 ?- member(X, [apple, pear]), member(X, [apple]), member(X, [pear]).
false.

26 ?- member(X, [apple, pear, orange]), member(X, [apple, orange]).
X = apple ;
X = orange.

27 ?- member(X, [apple, orange]), member(X, [pear, orange]).
X = orange.

28 ?- member(X, [apple, orange]), member(X, [pear]).
false.

或使用可能值列表对此进行建模,intersection/3用于缩小可能性:

35 ?- _X1=[apple, pear], intersection(_X1, [apple], X2).
X2 = [apple].

36 ?- _X1=[apple, pear], intersection(_X1, [apple], _X2), 
                         intersection(_X2, [pear], X3).
X3 = [].

37 ?- _X1=[apple, pear, orange], intersection(_X1, [apple, orange], X2).
X2 = [apple, orange].

38 ?- _X1=[apple, orange], intersection(_X1, [pear, orange], X2).
X2 = [orange].

39 ?- _X1=[apple, orange], intersection(_X1, [pear], X2).
X2 = [].
于 2013-05-25T12:43:26.367 回答
0

也许您使用了错误的语法:

?- X = apple ; X = pear.
X = apple ;
X = pear.

但我会接受 Will Ness 的建议。

于 2013-05-25T14:08:00.973 回答
0

虽然在我的回答中不清楚问题与类型层次结构有何关系,但它是由后者触发的,论文中给出了一个有效的解决方案: AN OPTIMIZED PROLOG ENCODING OF TYPED FEATURE STRUCTURES, GERALD PENN, 1999 。使用Colmerauer 的方法并简单地说:

'apple or pear' = f(0,_,1,1).
'pear or orange' = f(0,0,_,1).
'orange or apple' = f(0,X,X,1).
'apple' = f(0,1,1,1).
'orange' = f(0,0,0,1).
'pear' = f(0,0,1,1)

并且所有这些表示都服从序言匹配:“apple or pear”包含“apple”和“pear”,将“apple or orange”与“apple or pear”统一得到“apple”。

于 2013-05-25T21:48:59.570 回答