0

我已经开始学习 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 的值列表,这使得 and(A,B) 无法满足

EDIT2:我希望 PROLOG 告诉我:

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

2 回答 2

1

来自SWI-Prolog 文档

“……如果‘目标’不能被证明,则为真……”

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

据我所知,对于and(a, X), 和 对于and(A, B).

尝试对未显式声明为的参数进行任何查询is_true/1

尝试用谷歌搜索“否定失败”和“封闭世界假设”。两者都有值得一读的维基百科文章。

混合布尔逻辑和 Prolog 时要小心。他们不会做出相同的假设。

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

  1. 逻辑真假
  2. Prolog的成功与失败

这实际上是错误的,我建议反对它。反而:

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.
于 2015-03-05T15:42:21.993 回答
1

一种简单的方法是引入一个成功用于有效变量的谓词。因此,在您现有的谓词中,添加:

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

然后nand/2谓词可以在该域内工作并限制可能值的范围。否则,\+ 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/1提供了一种nand/2生成\+ and(A, B)可以测试的可能选项的方法。

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

于 2015-03-05T19:23:23.193 回答