逻辑与代码 1

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

转载自: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) :-      %与关系

AB.        %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(900fy,not).   %前缀运算符

:- op(910yfxand).  %中缀运算符

:- op(910yfxnand). %中缀运算符

:- op(920yfxor). %中缀运算符

:- op(920yfxnor). %中缀运算符

:- op(930yfximpl). %中缀运算符

:- op(930yfxequ). %中缀运算符

:- op(930yfxxor). %中缀运算符

 

?- 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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值