2015-10-14 109 views
4

我在做一个Prolog程序,它可以找到一组列表的一个子集。这个子集必须符合一些特定的条件,其中一个方面是子集的列表不能相同。什么是困惑我的是,当我试图找到变量匹配,X,如果我把它们插入到查询到位X的例如生成返回错误结果:为什么Prolog会将变量与直接插入的结果匹配失败?

?- containsSet(2, [[3],[7],[7]], X). 
X = [[3], [7]] ; 
X = [[3], [7]] ; 
X = [[7], [7]] ; 
false. 

?- containsSet(2, [[3],[7],[7]], [[7],[7]]). 
false. 

怎么可能呢如果在直接插入时返回false,可能会将X与[[7],[7]]匹配。

containsSet的思想是找到在匹配位置中没有匹配元素的长度为N的子集(在本例中为2)(即,子集中没有两个列表具有相同的第一个元素,或者相同第二元素等)。在上面的例子中,[7]和[7]中的第一个(也是唯一)元素匹配,所以它返回false。

+4

非常好的观察!这显然违反了连接的交换性,因此违背了我们对纯逻辑关系的期望。很可能,您在代码中使用非单调和不纯的结构,如'(\ +)/ 1','!/ 0'或if-then-else。你应该使用'dif/2'这样的限制来消除这些杂质,以表示这两个术语是不同的。这会让你的程序变得纯粹,并且可以在更多方向上使用。参见[tag:prolog-dif]和[tag:logical-purity]。另外,'please_use_more_readable_names''insteadOfNamesNoOneCanReadProperly'。 – mat

+2

啊!我在set_is_compatible(SET)行中使用'(\ +)/ 1'几次: - \ +(select(X,SET,R),\ + list_compatible_with_set(X,R))''。我会试着弄清楚如何重写这个。谢谢! – vestlen

+4

是的,我强烈推荐使用'dif/2'这样的纯谓词来代替。 '(\ +)/ 1'版本将为您创建无尽的声明性问题。考虑如下:'?\ \ + select(X,[a,b,c],Rest),X = d.',产生'false',**但**,如果我们只交换这两个目标合意!)交合的交换性,我们得到:'X = d'。如果它的论证是基础的,那么“(\ +)/ 1”是合理的,但是总的来说,你不能依赖这种非单调谓词来获得真正的一般的和陈述性的解决方案。您最好留在Prolog的纯粹和单调子集中以保留这些好的属性。 – mat

回答

3

首先,祝贺我在初学者的问题中看到的最具说明性和合理性的观察结果之一!

一方面,它是联合是逻辑上可交换的最基本和最着名的属性之一。另一方面,许多Prolog初学者没有意识到使用诸如(\+)/1之类的非单调谓词几乎总是破坏这样的基本不变量。你注意到在这里发生了一些非常意外的事情,并且你期待Prolog有更正确的行为。幸运的是,针对这些问题的声明性解决方案现在比Prolog系统中更广泛地传播。

首先考虑,如果你在程序中使用(\+)/1很快出现了一些问题:

 
?- X = d, \+ member(X, [a,b,c]). 
X = d. 

的是,如果我们只是靠结合的交换性交流的目标,我们得到的不同答案:

 
?- \+ member(X, [a,b,c]), X = d. 
false. 

这表明(\+)/1单调的:它可能会导致更普遍失败查询虽然更具体查询产生的解决方案:

 
?- \+ member(X, [a,b,c]). 
false. 

?- \+ member(d, [a,b,c]). 
true. 

因此,非单调谓词导致各种杂质和违反声明语义。声明,知道有解决方案,我们当然期望成功更一般的查询,但失败

在这个具体的,可以指定一个术语是从列表中的所有其他条款不同,使用约束dif/2dif/2适用于所有方向,如果其参数是变量,也会产生正确的答案。例如:

not_member(X, Ls) :- maplist(dif(X), Ls). 

这个定义保留相结合的交换性,因为我们深深的渴望,事实上,从纯逻辑关系预期:

 
?- not_member(X, [a,b,c]), X = d. 
X = d. 

?- X = d, not_member(X, [a,b,c]). 
X = d. 

由于not_member/2只使用纯谓词,你已确保—已经建设—,它只给出声明正确的答案。

对于声明性的关于你的代码的推理,我赞成你的方法,我建议你留在Prolog的纯单调子集中。有关更多信息,请参阅

+1

感谢这些例子!这真的很有启发。我想我已经开始了解Prolog如何以这种方式更好地工作 – vestlen

相关问题