转载自:https://mp.weixin.qq.com/s/kSCgQlrJw4h_tGW_MpFJBQ
1、逻辑表达式的真值表(1)
定义谓词and/2, or/2, nand/2, nor/2, xor/2, impl/2 and equ/2 (用于逻辑等价),这些谓词根据各自的运算结果而成功或失败;例如,且仅当A和B都成功时,and(A,B)才会成功。请注意,A和B可以成为Prolog目标(不仅是常数true和fail)。
然后,可以使用前缀表示法编写两个变量中的逻辑表达式,如以下示例所示:and(or(A,B),nand(A,B)).
and(A,B) :- %与关系
A, B. %A,B只要有其中一个为fail则为fail
or(A,_) :- %或关系
A. %A,B有一个为true则为true
or(_,B) :-
B.
equ(A,B) :- %A,B相同则为true
or(and(A,B), and(not(A),not(B))).
xor(A,B) :- %异或关系
not(equ(A,B)). %A,B不同则为true
nor(A,B) :- %或非关系
not(or(A,B)). %A,B都为fail则为true
nand(A,B) :- %A,B都为true则为fail
not(and(A,B)). %A,B只要其中一个为fail则为true
impl(A,B) :- %A,B只有当A为trueB为fail时为fail
or(not(A),B).
% bind(X) :- 依次实例化X为真和假
bind(true).
bind(fail).
table(A,B,Expr) :-
bind(A),
bind(B),
do(A,B,Expr),
fail. %强制失败
do(A,B,_) :-
write(A),
write(' '),
write(B),
write(' '),
fail. %强制失败,去匹配do的下一个子句
do(_,_,Expr) :-
Expr,
!, %截断,组织回溯
write(true),
nl.
do(_,_,_) :-
write(fail),
nl.
现在,现在调用谓词table/3,它在两个变量中打印给定逻辑表达式的真值表。
示例:
?- consult(‘p3_01').
true.
?- table(A,B,and(A,or(A,B))).
true true true
true fail true
fail true fail
fail fail fail
每行3个有4行为了后面解释方便我们在此给它们编号
1.1 true 1.2 true 1.3 true
2.1 true 2.2 fail 2.3 true
3.1 fail 3.2 true 3.3 fail
4.1 fail 4.2 fail 4.3 fail
我们来对此查询做个trace操作来观察它是如何运行的,用所编的号码来标识到具体执行的步骤:
?- consult('p3_01').
true.
?- trace,table(A,B,and(A,or(A,B))).
Call: (11) table(_47750, _47752, and(_47750, or(_47750, _47752))) ? creep
Call: (12) bind(_47750) ? creep
Exit: (12) bind(true) ? creep
Call: (12) bind(_47752) ? creep
Exit: (12) bind(true) ? creep
Call: (12) do(true, true, and(true, or(true, true))) ? creep
Call: (13) write(true) ? creep
true 1.1
Exit: (13) write(true) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) write(true) ? creep
true 1.2
Exit: (13) write(true) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) fail ? creep
Fail: (13) fail ? creep
Redo: (12) do(true, true, and(true, or(true, true))) ? creep
Call: (13) and(true, or(true, true)) ? creep
Call: (14) true ? creep
Exit: (14) true ? creep
Call: (14) or(true, true) ? creep
Call: (15) true ? creep
Exit: (15) true ? creep
Exit: (14) or(true, true) ? creep
Exit: (13) and(true, or(true, true)) ? creep
Call: (13) write(true) ? creep
true 1.3
Exit: (13) write(true) ? creep
Call: (13) nl ? creep
Exit: (13) nl ? creep
Exit: (12) do(true, true, and(true, or(true, true))) ? creep
Call: (12) fail ? creep
Fail: (12) fail ? creep
Redo: (12) bind(_47752) ? creep
Exit: (12) bind(fail) ? creep
Call: (12) do(true, fail, and(true, or(true, fail))) ? creep
Call: (13) write(true) ? creep
true 2.1
Exit: (13) write(true) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) write(fail) ? creep
fail 2.2
Exit: (13) write(fail) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) fail ? creep
Fail: (13) fail ? creep
Redo: (12) do(true, fail, and(true, or(true, fail))) ? creep
Call: (13) and(true, or(true, fail)) ? creep
Call: (14) true ? creep
Exit: (14) true ? creep
Call: (14) or(true, fail) ? creep
Call: (15) true ? creep
Exit: (15) true ? creep
Exit: (14) or(true, fail) ? creep
Exit: (13) and(true, or(true, fail)) ? creep
Call: (13) write(true) ? creep
true 2.3
Exit: (13) write(true) ? creep
Call: (13) nl ? creep
Exit: (13) nl ? creep
Exit: (12) do(true, fail, and(true, or(true, fail))) ? creep
Call: (12) fail ? creep
Fail: (12) fail ? creep
Redo: (12) bind(_47750) ? creep
Exit: (12) bind(fail) ? creep
Call: (12) bind(_47752) ? creep
Exit: (12) bind(true) ? creep
Call: (12) do(fail, true, and(fail, or(fail, true))) ? creep
Call: (13) write(fail) ? creep
fail 3.1
Exit: (13) write(fail) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) write(true) ? creep
true 3.2
Exit: (13) write(true) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) fail ? creep
Fail: (13) fail ? creep
Redo: (12) do(fail, true, and(fail, or(fail, true))) ? creep
Call: (13) and(fail, or(fail, true)) ? creep
Call: (14) fail ? creep
Fail: (14) fail ? creep
Fail: (13) and(fail, or(fail, true)) ? creep
Redo: (12) do(fail, true, and(fail, or(fail, true))) ? creep
Call: (13) write(fail) ? creep
fail 3.3
Exit: (13) write(fail) ? creep
Call: (13) nl ? creep
Exit: (13) nl ? creep
Exit: (12) do(fail, true, and(fail, or(fail, true))) ? creep
Call: (12) fail ? creep
Fail: (12) fail ? creep
Redo: (12) bind(_47752) ? creep
Exit: (12) bind(fail) ? creep
Call: (12) do(fail, fail, and(fail, or(fail, fail))) ? creep
Call: (13) write(fail) ? creep
fail 4.1
Exit: (13) write(fail) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) write(fail) ? creep
fail 4.2
Exit: (13) write(fail) ? creep
Call: (13) write(' ') ? creep
Exit: (13) write(' ') ? creep
Call: (13) fail ? creep
Fail: (13) fail ? creep
Redo: (12) do(fail, fail, and(fail, or(fail, fail))) ? creep
Call: (13) and(fail, or(fail, fail)) ? creep
Call: (14) fail ? creep
Fail: (14) fail ? creep
Fail: (13) and(fail, or(fail, fail)) ? creep
Redo: (12) do(fail, fail, and(fail, or(fail, fail))) ? creep
Call: (13) write(fail) ? creep
fail 4.3
Exit: (13) write(fail) ? creep
Call: (13) nl ? creep
Exit: (13) nl ? creep
Exit: (12) do(fail, fail, and(fail, or(fail, fail))) ? creep
Call: (12) fail ? creep
Fail: (12) fail ? creep
Fail: (11) table(_47750, _47752, and(_47750, or(_47750, _47752))) ? creep
false.
2、逻辑表达式的真值表(2)
通过将and/2或or/2等定义为运算符来继续问题1。这样可以以更自然的方式编写逻辑表达式,如示例中所示:A和(A或非B)。照常定义运算符优先级;即与Java中一样。(请参考教材《现在学习Prolog 下》理解项一文中内的第4节)
:- ensure_loaded(p3_01). %确保装入p3_01.pl
:- op(900, fy,not). %前缀运算符
:- op(910, yfx, and). %中缀运算符
:- op(910, yfx, nand). %中缀运算符
:- op(920, yfx, or). %中缀运算符
:- op(920, yfx, nor). %中缀运算符
:- op(930, yfx, impl). %中缀运算符
:- op(930, yfx, equ). %中缀运算符
:- op(930, yfx, xor). %中缀运算符
?- consult(‘p3_02.pl').
true.
?- table(A,B, A and (A or not B)).
true true true
true fail true
fail true fail
fail fail fail
3、逻辑表达式的真值表(3)
以使逻辑表达式可以包含任意数量的逻辑变量的方式概括问题2。定义table/2,使table(List,Expr)打印表达式Expr的真值表,该表包含List中枚举的逻辑变量。
如:?- table([A,B,C], A and (B or C) equ A and B or A and C).
A B C Result
true true true true
true true fail true
true fail true true
true fail fail true
fail true true true
fail true fail true
fail fail true true
fail fail fail true
1 :- ensure_loaded(p3_02).
2
3 table(VarList,Expr) :-
4 bindList(VarList),
5 do(VarList,Expr),
6 fail.
7
注释行:
1. 确保装入p3_02
2. 空行
3.
4. 实例化
5. 求值并打印
6. 强制失败
7.
8 bindList([]).
9 bindList([V|Vs]) :-
10 bind(V),
11 bindList(Vs).
12
注释行:
8. 终止条件
9.
10. 实例化V
11. %继续实例化列表剩余元素
12. 空行
13 do(VarList,Expr) :-
14 writeVarList(VarList),
15 writeExpr(Expr),
16 nl.
17
注释行:
13.
14. 打印实例化列表的元素
15. 打印表达式的求值结果
16.
17.
18 writeVarList([]).
19 writeVarList([V|Vs]) :-
20 write(V),
21 write(' '),
22 writeVarList(Vs).
23
注释行:
18. 终止条件
19.
20. 打印元素
21.
22. 继续递归打印后续元素
23.
24 writeExpr(Expr) :-
25 Expr,
26 !,
27 write(true).
28 writeExpr(_) :-
29 write(fail).
注释行:
24.
25. true
26. 截断
27.
28. 上一子句失败
29.
结果如下:
?- table([A,B,C], A and (B or C) equ A and B or A and C).
true true true true
true true fail true
true fail true true
true fail fail true
fail true true true
fail true fail true
fail fail true true
fail fail fail true
false.

这篇博客介绍了如何在Prolog中实现逻辑表达式的真值表,包括and、or、nand、nor、xor、impl和equ等逻辑运算,并提供了具体的代码示例和查询演示,展示了如何通过table/3谓词打印给定逻辑表达式的真值表。

被折叠的 条评论
为什么被折叠?



