首页 > 编程知识 正文

卡诺化简法依据的基本原理,卡诺化简例题20题

时间:2023-05-05 01:59:03 阅读:227917 作者:1473

一文彻底理解zydg化简算法 写在前面背景算法第一步第二步第三步
本文基于Abdelrahman Elzedy的文章《A C++ Karnaugh Map Minimizer (Infinite Variables)》,在一些比较难懂的地方我加了一些自己的解释,原文链接:https://www.codeproject.com/Articles/649849/A-Cplusplus-Karnaugh-Map-Minimizer-Infinte-Variabl
大家可以在网站上可以下载exe文件和源代码

写在前面

这篇文章主要介绍了一种可以化简包含任意多个变量的zydg的算法。但是原文链接所提供的代码只实现了26个变量的zydg化简(与英文字母的个数相同)。

背景

本文假设读者具有基本的布尔代数和zydg知识。(译者注:大家如果忘了zydg是啥可以参考百度百科)

程序运行的时候长这样:

程序的使用步骤如下:

输入zydg的类型(也就是变量的个数)输入zydg中1的位置(在最后以-1结尾表示结束输入)输入zydg中不关心的位置(在最后以-1结尾表示结束输入)选择结果的类型(POS (Product of Sum)或SOP(Sum of Product))得到zydg的化简结果 算法

算法主要有三步,在代码中,每一步都由一个类(class)实现。

按照用户的输入(值为1和不关心的位置)初始化zydg,并且将值为1和不关心的位置信息保存为二进制值
(译者注:将位置值保存为二进制主要是为了方便后面的化简,因为使用二进制判断位置是否相邻比较方便,大家往后看就明白了~)比较所有值为1和不关心的位置,得到所有可能的最小项检查上一步得到的结果,去掉所有多余的最小项,得到最终的结果 (译者注:如果结果不唯一时程序会输出所有可能的结果)

一脸懵逼ing?当时我读这篇文章时到这里也是不知所云,只感觉不明觉厉。不过别担心,继续往下读,我会用栗子和图的方式让大家搞懂的(译者注)

第一步

在这一步中,我们首先得到了用户输入的zydg的信息(变元个数,值为1与不关心的位置)。然后我们就将这些信息转化为二进制的形式。
举个栗子:
首先我们要知道zydg是怎么编号的,一个典型的四元zydg的编号方式如下:

从图中很容易看出zydg的编号方式:横纵坐标都是按照格雷码的方式编号(不知道格雷码的编号方式请点击这里);处于横坐标的变量(图中的A、B)的值作为高位,处于纵坐标的变量(图中的C、D)的值作为低位,构成二进制数,这个二进制数所对应的十进制数就是该位置的编号。
如果我们需要输入一个如下图所示的zydg(其中空的位置都是0,X表示不关心的值):

那我们首先应该输入4(zydg变量的个数),然后在下一行输入0 1 3 4 11 -1(其中-1表示这一行输入结束,0 1 3 4 11是值为1的位置编号),然后再另起一行,输入5 -1(5是X的位置编号,-1代表输入结束)。这样,用户的输入就完成了。
然后程序将用户输入的位置转化为二进制(因为有四个变量,所以转化为四位二进制)。值为1的位置二进制编号分别为0000,0001,0011,0100和1011;X的位置二进制编号为0101。
可能大家已经看出来了,zydg这样编号的好处就是将位置和二进制的编号联系在了一起。比如我们很容易推断,二进制编号为0000和0001的两个位置是相邻的。这样就为我们接下来zydg化简奠定了基础。

第二步

在这一步中,我们需要两两比较上一步保存的值为1和X的位置二进制编号。比较的步骤如下(设变元总个数为n):

如果有两个二进制数在n-1位上都相同,只有一位不同,则将不同的那一位设为 -1 ,相同位置数字不变,生成一个新的二进制数。
例如上面栗子中的0000和0001,只有第四位不同,则生成新数000(-1)将上面步骤中配过对的数字标记,在下一轮的比较中只加入新生成的数和未标记的数(即没有配对的数)。重复以上步骤n次。(考虑最坏的情况:如果我们处理的是一个全部位置都是1的zydg,那我们必须重复n次)如果有一个数重复多次,则只保留一个。

接着第一步的栗子。在第一步中,我们已经得到了值为1的位置和值为X的位置的二进制编号:0000,0001,0011,0100、1011、0101。我们按照上面叙述的步骤走一遍:

Step1: 将每两个编号都进行比较,生成新数

如下图所示,红笔表示新数生成的过程,红色的√标记此数已经与其他的数配过对。

Step2 将生成的新数加进序列,并剔除做过标记的数,得到第一次处理后的数列为:
000(-1), 0(-1)00, 00(-1)1, 0(-1)01, (-1)011 and 010(-1)

Step3: 重复以上步骤,得到的第二次处理后的数列为:
0(-1)0(-1), 0(-1)0(-1), 00(-1)1 and (-1)011
第三次处理后的数列为:
0(-1)0(-1), 0(-1)0(-1), 00(-1)1 and (-1)011
第四次处理后的数列为:
0(-1)0(-1), 0(-1)0(-1), 00(-1)1 and (-1)011
去掉重复的0(-1)0(-1)得到:
0(-1)0(-1), 00(-1)1 and (-1)011

其实这个过程模拟的就是我们化简zydg时画圈的过程。
处理完n次后,我们就可以将我们得到的二进制数列转化为字母表示,转化规则如下:

二进制中的第一位、第二位…第n位分别对应zydg中的第一个、第二个…第n个字母。0表示对应的字母取非,1表示对应的字母不取非。如果某位上的数字为(-1),则表示对应的字母应该忽略。

例如将上面的数列 0(-1)0(-1), 00(-1)1 and (-1)011 转化为字母形式应该为:
A’C’, A’B’D and B’CD(符号 ’ 表示取非,你懂的)
有两种特殊的情况需要考虑:

如果在某一步中数列出现每位都是 -1 的数,则说明对应zydg化简的结果为1;如果初始的数列为空,则表示这是一个所有元素都为0的zydg,化简的结果为0。 第三步

在这一步中,我们将上一步得到的所有最小项进行组合,如果组合能够覆盖zydg中所有值为1的位置,则保留这个组合,得到所有可能的结果。最后输出所有最小项最少的组合。
例如在文章开始在这个图中:

我们第二步结束后得到的结果应该是 B’D’, B’C, BD, AB’, AD and CD。当我们将这些项做排列组合时,B’D’+B’C+BD+AB’ 和B’D’+B’C+BD+AD+AB’都可以覆盖zydg中所有值为1的位置。但是因为前一个组合的最小项数为4,后一个为5,所以输出B’D’+B’C+BD+AB’ 而不输出B’D’+B’C+BD+AD+AB’。

以上就是zydg化简算法的全部内容。如果大家有什么不懂的地方,或者觉得算法有可以改进的地方,欢迎在评论区讨论~

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。