真值表 && 逻辑表达式

本文的真值表转逻辑表达式没有化到最简,最简详见:
更新链接:https://blog.csdn.net/wxkhturfun/article/details/131776977?spm=1001.2014.3001.5501

前言

遇到一个问题:想把真值表转换成逻辑表达式,真值表太长,不想手算,于是写了个脚本。但是为了检验结果的正确性,顺带写了个逻辑表达式转真值表的脚本。

一. 逻辑表达式转真值表

下面的例子是expression = abc+ (a非)b(c非),为了方便表示,用大写字母表示取非,小写字母表示原值,则expression = abc+AbC,在python代码中,该expression即被记为[(1,1,1),(0,1,0)],这里的(1,1,1)是按字母顺序的abc,这里的(0,1,0)是按字母顺序的AbC
此时已经可以表示了,但是如果还有字母d呢?即化简后d消失了,那么可以认为d是可有可无的x,为了统一处理,这里用数字2来表示x, 则此时expression=[(1,1,1,2),(0,1,0,2)] ,以此类推!


生成的真值表存储在test.csv文件中

import csv

def Write_csv(csv_file,data,encode='utf-8'):
    with open(csv_file, 'w', encoding=encode,newline='') as file_obj:
        writer = csv.writer(file_obj)
        for i in data:
            writer.writerow(i)

def gen_data(exp,N):
    data_out = []
    for i in range(2**N):
        line = bin(i)
        line = str(line)
        line = line[2:]
        line = '0'*(N-len(line)) + line
        tmp_0 = 0
        for data_in in exp:
            tmp_1 = 1 
            for i in range(N):
                if( data_in[i] == 2 ):
                    continue
                elif(data_in[i] == int(line[i])):
                    continue
                else:
                    tmp_1 = 0
                    break
            tmp_0 = tmp_0 + tmp_1
        if(tmp_0 != 0):
            line = line + '1'
        else:
            line = line + '0'
        data_out.append(tuple(line))
    return data_out

if __name__ == "__main__":
    #T = 1
    #F = 0
    #X = 2
    #大写字母代表取非
    #小写字母代表正常字母
    #expression = abc + AbC
    #exp = ['abc','AbC'] for N = 3
    #exp = ['abcX','AbCX'] for N=4(thus include D)
    #exp = [[1,2,1,2],[0,1,0,2]]
    exp = [[2,2,2,2],[1,2,1,0]]
    data = gen_data(exp,4)
    Write_csv('test.csv',data)

二. 真值表转逻辑表达式

这里输出的表达式的含义见上一小节。
需要注意的是两个极端例子:

  1. 如果真值表恒为1,则输出结果为[2,2,2,2](即真值表对应的输出结果永真时,其输入可为任意值)
  2. 如果真值表恒为0,则输出结果为[]
import csv

#input:csv file
#out1:元素个数
#out2:把结果为1的值读进data
def Read_csv_True(csv_file,encode='utf-8'):
    data = []
    column = 0
    with open(csv_file, 'r', encoding=encode) as file_obj:
        reader = csv.reader(file_obj)
        for row in reader:
            element = row[-1]
            if(0 == int(element)):
                continue
            tmp = row[:-1]
            for i in range(len(tmp)):
                tmp[i] = int(tmp[i])
            data.append(tmp)
    column = len(row)-1
    return column,data
def get_Exp(data,N):
    if(len(data) == 0):
        return []
    for n in range(N):
        for i in range(len(data)-1):
            for j in range(i,len(data)):
                if (j == len(data)):
                    #因为有del(data[j]),所以要判断溢出
                    break
                tmp = []
                cnt = 0
                for k in range(N):
                    if(data[i][k] == data[j][k]):
                        tmp.append(data[i][k])
                    else:
                        cnt += 1
                        tmp.append(2)
                if(cnt == 1):
                    data[i] = tmp
                    del(data[j])
if __name__ == "__main__":
	#N指字母个数
    N,data = Read_csv_True('test.csv','utf-8')
    print(N)
    get_Exp(data,N)
    print(data)

三.后记

本人试了几个结果,发现没有问题,如果有问题,可以@我。
另外,真值表转逻辑表达那个脚本本意就是想化简的,所以具有一定的化简功能,我感觉是化到最简了尚未进行严格的数学证明!)。(后发现不是最简)

补充,关于代码逻辑:
起先我是画了一个韦恩图,试图找到可以合并的两项的表达式有什么联系,然后发现:
可以合并的两项必然有一条边重合,也就是说在韦恩图中,如果两个最小区域(即不包含其他区域的区域)可以合并,那么至少有一条边是共有的。没有共有边或只有共有的顶点的两个最小区域不能合并。
(注:不知道有没有严格的数学证明,有的话可以在评论给我提示一下)
按这个思路来,有4项的项合并后,变为3项,那么就可以先把所有可以合并的4项给合并成3项,再合并成2项,直至不能合并!
按照这个思路,如果不能合并,那么必不存在共有边,即得到的逻辑表达式是最简的(想法没错,但是代码并没有化到最简)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Greate AUK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值