Prolog中的Variable的几个绑定选项

时间:2013-05-25 11:38:51

标签: binding prolog constraint-programming

我希望将变量绑定到几个原子,以便稍后它将与其中一个原子统一。 直觉上它应该像这样工作(假设;是可能值的分离):

    ?- 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 个答案:

答案 0 :(得分:2)

正如你从其他答案中看到的那样,有一种直截了当的方式用Prolog表达这一点,使用析取(离开选择点),或明确推理集合及其交叉点。

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

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

fruit_integer(apple,  0).
fruit_integer(pear,   1).
fruit_integer(orange, 2).

variable_fruits(Var, Fruits) :-
        maplist(fruit_integer, Fruits, Integers),
        foldl(domain_, Integers, 1..0, D),
        Var in D.

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

在这种情况下,关键的想法是将水果映射到整数,这样您就可以使用CLP(FD)约束来表达所有内容。

您的示例查询和答案::

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

?- variable_fruits(X, [apple,pear]), 
   fruit_integer(apple, X),
   fruit_integer(pear, X).
false.

?- variable_fruits(X, [apple,pear,orange]),
   variable_fruits(X, [apple,orange]).
X in 0\/2.

?- variable_fruits(X, [apple,orange]),
   variable_fruits(X, [pear,orange]).
X = 2.

?- variable_fruits(X, [apple,orange]),
   fruit_integer(pear, X).
false.

显然,您也可以在其他方向使用fruit_integer/2,并将此类整数和域转换回 atoms 列表。我把这作为一个简单的练习。

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

一些补充说明:

  • 所有使用最广泛的Prolog系统都附带CLP(FD)限制,如果您使用它们,您的解决方案非常便携。
  • 某些Prolog系统附带了的专用约束求解器。如果您的系统支持此功能,这可能值得一试。
  • CHR是一种用于定义自定义传播规则的有用语言,特别适用于更复杂的任务。
  • 直接使用属性变量界面会降低您的解决方案的可移植性,因此我建议您使用其中一种更高级别的方法。首先尝试CLP(FD)(因为它最容易应用),然后查看CHR,然后考虑实现自定义求解器。

答案 1 :(得分: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 = [].

答案 2 :(得分:0)

也许你正在使用错误的语法:

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

但我会接受Will Ness的建议。

答案 3 :(得分:0)

虽然在我的回答中并不清楚问题是如何与类型层次结构相关的,但它是由后者触发的,本文给出了一个有效的解决方案: 优化的PROLOG编码类型的结构,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)

并且所有这些表示都遵循prolog匹配: 'apple or pear'包含'apple'和'pear', 用'苹果或梨'统一'苹果或橙子'给'苹果'。