Prolog中否定变量的目标满意度

时间:2015-03-05 15:18:16

标签: prolog negation

我已经开始学习PROLOG了,我有一个非常基本的例子。我正在使用SWI PROLOG,代码如下:

is_true(a).
is_true(c).
is_true(d).
is_false(b).
is_false(e).

and(A,B) :- is_true(A),is_true(B).
nand(A,B) :- \+(and(A,B)).

然后:

[imanol@I56106 prolog]$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.4)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- consult(test).
% test compiled 0.00 sec, 8 clauses
true.

?- and(a,X).
X = a ;
X = c ;
X = d.

一切都很棒ATM,我让PROLOG回溯了所有符合目标的可能值和(A,B)A = a。但如果我尝试使用目标nand(A,B):

?- nand(a,X).
false.

要么它认为目标是不可能的,要么它没有回溯,我没有丝毫的线索为什么。 :/

有人知道我做错了吗?

提前致谢。

PS:我也尝试过:

nand(A,B) :- not(and(A,B)).

它会产生相同的结果。

编辑:看到我的问题对某些人来说很神秘:

我希望PROLOG给我一个变量A和B的值列表,这些变量使得和(A,B)不可满足

EDIT2:我希望PROLOG告诉我:

?- nand(a,X).
    X = e ;
    X = b.

2 个答案:

答案 0 :(得分:1)

来自the SWI-Prolog documentation

" ...如果'目标'无法证明..."

换句话说:\+(and(A, B))只有在and(A, B)失败时才会成功。换句话说,如果存在and(A, B)的解决方案,则\+(and(A, B))将失败。

从我看到的情况来看,and(a, X)and(A, B)都有解决方案。

对未明确声明为is_true/1的参数进行任何查询。

尝试google for"否定为失败"和"封闭的世界假设"。两者都有值得阅读的维基百科文章。

混合布尔逻辑和Prolog时要小心。他们没有做出同样的假设。

针对您的问题:您有一堆逻辑变量。其中一些是真的,其中一些是假的。您希望能够计算真值表。当输出列为true时,说and(A, B)应该成功,否则失败。此时,您已经混淆了两个不同的概念:

  1. 逻辑正确且错误
  2. Prolog的成功与失败
  3. 这实际上是错误的,我建议反对它。代替:

    and(f, f, f).
    and(f, t, f).
    and(t, f, f).
    and(t, t, t).
    
    not(t, f).
    not(f, t).
    
    nand(A, B, R) :- and(A, B, R0), not(R0, R).
    
    val(a, t). val(c, t). val(d, t).
    val(b, f). val(e, f).
    
    solve(and(A, B), R) :- val(A, VA), val(B, VB), and(VA, VB, R).
    % solve(nand...) as exercise
    

    等等。

    然后,您可以获得更多信息丰富的查询:

    ?- solve(and(a, c), R).
    R = t.
    
    ?- solve(and(a, X), R).
    X = a,
    R = t ;
    X = c,
    R = t ;
    X = d,
    R = t ;
    X = b,
    R = f ;
    X = e,
    R = f ;
    false.
    
    ?- solve(nand(a, X), R).
    X = a,
    R = f ;
    X = c,
    R = f ;
    X = d,
    R = f ;
    X = b,
    R = t ;
    X = e,
    R = t ;
    false.
    

答案 1 :(得分:1)

一种简单的方法是引入一个成功获得有效变量的谓词。因此,对于现有谓词,请添加:

is_valid(X) :- is_true(X) ; is_false(X).

然后nand/2谓词可以在该域内工作,限制可能值的Universe 。否则,\+ and(A, B)不知道可以选择哪些值来确定and(A, B)的失败:

nand(A, B) :- is_valid(A), is_valid(B), \+ and(A, B).

| ?- nand(a, X).

X = b ? ;

X = e ? ;

no

换句话说,is_valid/1nand/2提供了一种方法,可以生成可以测试\+ and(A, B)的可能选项。

您可以合理地将此“将宇宙限制”应用于其他谓词,例如and/2and(A, B) :- is_valid(A), is_valid(B), is_true(A), is_true(B).,但您可以看到这将是多余的。