首先,对于一个布尔表达式,肯定可以用布尔代数里的那一系列定理和定律进行化简。但是,我想除非布尔表达式的项非常少且可化简项显而易见,否则应该没人会去用那一套方法。而且,就算你能化简,你也不一定能保证化简结果是最简的。
化简布尔表达式,首先想到的应该是卡诺图。卡诺图的操作方法非常简单,概括起来就是两字:画圈。而且,不只是画圈,还是画各种圈。对于3~4个变量组成的布尔表达式,运用卡诺图可以很快地化简。但是,当输入变量一多,光是构造一张卡诺图就很麻烦(对于10个变量,卡诺图就有
2
10
=
1024
2^{10}=1024
210=1024个项)。而且,卡诺图画圈的方法非常佛系,不利于算法实现。国外有个朋友写了一个卡诺图化简程序,使用的是C++语言。我下载下了试了一下,还是挺不错的。我用它来化简布尔表达式
F
(
A
,
B
,
C
,
D
,
E
)
=
∑
(
2
,
3
,
7
,
9
,
10
,
11
,
12
,
13
,
18
,
19
,
22
,
23
,
26
,
27
,
30
,
31
)
F(A,B,C,D,E)=\sum(2,3,7,9,10,11,12,13,18,19,22,23,26,27,30,31)
F(A,B,C,D,E)=∑(2,3,7,9,10,11,12,13,18,19,22,23,26,27,30,31)
结果如下:
注意一下这里的结果,我将用它来验证接下来要介绍的Q-M法化简的结果。
上面既然说了卡诺图的弊端——不利于算法实现。那么,接下来介绍一种利于算法实现的布尔表达式化简方法——Quine-McCluskey法,或者简称Q-M法。
其实,Q-M法的原理其实和卡诺图是一致的。只不过卡诺图用画圈的形式让化简更加直观通俗,而Q-M法的分组形式更利于程序化执行。下面给出Q-M法的化简步骤。
Q-M法分四步:
1、将布尔表达式的项按只含0个“1”,只含1个“1”,只含2个“1”,…,只含n个“1”(n为变量个数)划分为不同的Group,并按“1”的数量排列(升序或降序均可)成表;
2、准备一张新表。从含有最少数量的“1”的Group开始依次向下,将当前Group中的每一项与下一个Group的每一项比较。若两者只有一个变量不同,则将两项提取出来,并将不同的变量处用“-”标记,生成一个新的项。如果新的项在新表中已存在,则不执行动作;若不存在,则将这个新的项放到新表中的相应Group中。最后,在原表的两个Group中将提取的两项对应的“Subcube Covered”打上标记。
3、在新生成的表中,重复2,直到新表中不存在只有一个变量不同的项为止。
4、化简结果即为所有表中“Subcube Covered”未被标记的项的和。
说的好像很抽象,下面我们给出一个具体的例子来演示一下怎么操作。
还是以扔给卡诺图化简程序的布尔表达式为例:
F
(
A
,
B
,
C
,
D
,
E
)
=
∑
(
2
,
3
,
7
,
9
,
10
,
11
,
12
,
13
,
18
,
19
,
22
,
23
,
26
,
27
,
30
,
31
)
F(A,B,C,D,E)=\sum(2,3,7,9,10,11,12,13,18,19,22,23,26,27,30,31)
F(A,B,C,D,E)=∑(2,3,7,9,10,11,12,13,18,19,22,23,26,27,30,31)
先执行1:划分Group,结果如下:
下面进行2:提取只有一个变量不同的项,结果如下:
这步结束之后,我们可以在1的表中标记“Subcube Covered”列,结果如下:
接着,我们在2得到的新表中重复执行2,结果如下:
其中,红色标记的部分为Group中已经存在过的项。这里只是为了演示才将其列出,实际上它们将不被加入表中。
同样的,这一步结束后,可以更新上一步表中的“Subcube Covered”列,结果如下:
其中,黄色标记为未被标记的项。
接着,我们继续在新表中执行2,结果如下:
同样的,更新上一步表中的“Subcube Covered”列,结果如下:
这一步结束后,可以看出新表中已经没有只有一个变量相同的项了,于是算法结束,记得将最后得到的表中的所有项的“Subcube Covered”标上黄色,表示他们未被标记:
最后,Q-M法化简的结果即为所有表中所有未被标记的项的和:
r
e
s
u
l
t
=
C
‘
D
+
A
D
+
B
‘
D
E
+
A
‘
B
C
‘
E
+
A
‘
B
D
‘
E
+
A
‘
B
C
D
‘
result=C^`D+AD+B^`DE+A^`BC^`E+A^`BD^`E+A^`BCD^`
result=C‘D+AD+B‘DE+A‘BC‘E+A‘BD‘E+A‘BCD‘
比较这个结果和之前卡诺图程序化简的结果,可以发现Q-M法化简结果并不是最简。导致这种结果的原因显而易见。如果有多种化简结果,直接用Q-M法化简的到的未标记项包含所有化简结果的乘积项,直接相加的话必然会存在冗余。要解决这个冗余问题,就需要用到下面的素项表。
将所有“Subcube Covered”未被标记的项列在一张表中,并将包含的最小项做上标记:
其中,被标记为红色的项表示该列中只有一项。这就表示最后的化简结果中必须包含这个最小项,也就是必须包含这个最小项所在的项。
下面给出对素项表的操作:
1、对所有只包含一项的列(图中的红色标记)的项所在的行画横线,并对横线所经过的项画竖线。结果如下:
可以看出,进过这一步之后只有两项未被划线(图中框处的两项)。
2、找出为包含最大数量未被划线的项的行,若有多行,则必有多种化简结果,需要对每一行单独列出一种情况进行操作。
由于例子中只有两项未被标记,且分别位于两行。因此,这一步找到的行有两行,分别对应两种不同的化简结果。
3、对于2中的行,对其划横线,并对横线所经过的项画竖线。
两种结果分别如下:
4、若经过划线后还存在未划线项,继续2-3直到无未划线项为止。
5、最后的化简结果即为所有划横线的行对应的项的和。
本例中,有两种化简结果:
r
e
s
u
l
t
1
=
C
‘
D
+
A
D
+
B
‘
D
E
+
A
‘
B
C
‘
E
+
A
‘
B
C
D
‘
result1=C^`D+AD+B^`DE+A^`BC^`E+A^`BCD^`
result1=C‘D+AD+B‘DE+A‘BC‘E+A‘BCD‘
r
e
s
u
l
t
2
=
C
‘
D
+
A
D
+
B
‘
D
E
+
A
‘
B
D
‘
E
+
A
‘
B
C
D
‘
result2=C^`D+AD+B^`DE+A^`BD^`E+A^`BCD^`
result2=C‘D+AD+B‘DE+A‘BD‘E+A‘BCD‘
将这两种化简结果与卡诺图程序化简的结果相比较,可以发现两者是一样的。
最后,谈一谈对于无关项的处理。
在用Q-M法化简时,首选需要将所有无关项当“1”处理。但是到素项表时,在列中不将无关项列出。同时,也不将“Subcube Covered”未被标记的纯无关项(“MinTerms”中全部是无关项)列在行中。素项表的操作与前述一致。