Binding Prolog中变量的几个绑定选项

Binding Prolog中变量的几个绑定选项,binding,prolog,constraint-programming,clpfd,Binding,Prolog,Constraint Programming,Clpfd,我想把一个变量绑定到几个原子上,这样以后它就可以和其中一个原子统一。 直觉上它应该是这样工作的(假设;是可能值的析取): 正如你所看到的,这个想法接近于类型层次结构的概念。 因此,我想知道是否有一些内置(元)谓词可以使这类事情变得容易,或者是否有一些常用的方法使用某种数据结构对此进行建模,或者我必须从头开始构建这类谓词?您可以使用: 或者使用可能值列表对此进行建模,以缩小可能性: 35 ?- _X1=[apple, pear], intersection(_X1, [apple], X2). X

我想把一个变量绑定到几个原子上,这样以后它就可以和其中一个原子统一。 直觉上它应该是这样工作的(假设;是可能值的析取):

正如你所看到的,这个想法接近于类型层次结构的概念。 因此,我想知道是否有一些内置(元)谓词可以使这类事情变得容易,或者是否有一些常用的方法使用某种数据结构对此进行建模,或者我必须从头开始构建这类谓词?

您可以使用:

或者使用可能值列表对此进行建模,以缩小可能性:

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 = [].

可能您使用了错误的语法:

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

但我同意Will Ness的建议。

虽然我的回答中不清楚该问题与类型层次结构的关系,但它是由类型层次结构引发的,本文给出了一个有效的解决方案: 类型化特征结构的优化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匹配: “苹果或梨”包含“苹果”和“梨”,
把“苹果或橘子”和“苹果或梨”统一起来就得到了“苹果”

正如您从其他答案中看到的,有一种直接的方法可以用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). 果_整数(苹果,0)。 水果(梨,1)。 果_整数(橙色,2)。 可变水果(变量、水果):- 地图列表(水果、整数、水果、整数), foldl(域,整数,1..0,D), D中的Var。 域(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. -可变水果(X,[苹果,梨]),水果整数(苹果,X)。 X=0。 -可变水果(X、[苹果、梨]), 水果_整数(苹果,X), 水果(梨,X)。 错。 ?可变水果(X、[苹果、梨、橙子], 各种水果(X、[苹果、橘子])。 0\/2中的X。 -可变水果(X、[苹果、橙子], 各种水果(X、[梨、橙])。 X=2。 -可变水果(X、[苹果、橙子], 水果(梨,X)。 错。 显然,您也可以在另一个方向上使用
fruit\u integer/2
,并将这些整数和域转换回原子列表。我把这当作一个简单的练习

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

还有几点需要注意:

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

你说的“类型层次结构概念”是什么意思?我看不出有什么相似之处。没错,很难找到这只猫。这与类型层次结构的概念很接近,因为orange、apple、pear可以是层次结构中的类型,类型为appl_pear、appl_oran、pear_oran(大致用(apple;pear)等表示),然后你想让prolog匹配作为类型层次结构中的一个统一。从技术上来说,你的回答为我的请求提供了两种解决方案,但我在发布问题时希望有更有效的方法。一) 第一种解决方案有效,但效率极低,因为存在许多选择点,如果在两个谓词之间有一些过程,例如member(X,[apple,pear])和member(X,[apple]),则会导致大量回溯。二) 第二个解决方案比第一个好得多,这就是我接受答案的原因。
它让你推迟目标,直到知道更多。
这是我最初的目标。你能给我一个mwe吗?我不熟悉属性变量。我添加了一个示例和一些附加注释。我希望有帮助。 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). ?- 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.