前言
之前写的”真值表 && 逻辑表达式“表达有误,代码没有问题,但是化简没有达到最简,另外,代码的输入有点反人类,这里也更新一下
一. 逻辑表达式转真值表(代码更新)
改为采用符号表达,其中以exp = Ad + AcD + acd + abC + abcD为例,s[0]表示a/A,s[1]表示b/B,以此类推。
取反不再使用字母的大小写表达,而是采用取反符号。
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 get_data(exp, s):
num = len(s)
data_out = []
for i in range(2**num):
line = bin(i)
line = str(line)
line = line[2:]
line = '0'*(num-len(line)) + line
for j in range(num):
s[j] = eval(line[j])
#**************************************
if(eval(exp) != 0):
line = line + '1'
else:
line = line + '0'
#**************************************
data_out.append(tuple(line))
return data_out
if __name__ == "__main__":
s = [0, 0, 0, 0]#初始化列表
EXP = "(~s[0])&s[2] | (~s[0])&s[3] | s[2]&s[3] | s[0]&s[1]"
data = get_data(EXP, s)
Write_csv('test.csv',data)
二. 真值表转逻辑表达式
2.1 赘述
经过之前()的尝试,发现基于韦恩图的化简,难以处理,并且不利于计算(本人又不想用原始的卡诺图),于是在将韦恩图盯着看一上午后,将曲线变为直线,为了便于分析,本人利用坐标系抽象出一个立方体:如下
其中左图是平面直角坐标系,右图是对应的8421编码的值
2.2 数学原理
声明:以下数学原理毫无根据,纯属个人猜想,有错指出,无错请证明
将所有真值表为1的值,用数字表示,例如:
以3维体系为例:
expression = abc + ABc ,表示坐标中的(1,1,1)和(0,0,1)这两个点,则对应的数值为7和1,
- 如果两个点可以合并,表示存在一条立方体的边,该边的端点为这两个点
- 如果两条边可以合并,表示存在立方体的一个面,该正方形可以这两条边形成,例如(4,5)和(6,7)可以合并成面:(4,5,7,6),但是(0,1)和(6,7)不可以合并成面(0,1,6,7),因为该面穿越了立方体,不在立方体的表面
- 推论1:在N维情况下,如果两个点可以合并,意味着其8421编码对应的各个位的二进制之和中,恰好有(N-1)个0或。例如:
当N=3时,(4)和(6)可以合并,因为4=100(2),6=110(2)
第0位相加 =1+1 =2 (等于,这里是2的1次幂,因为两个点合并,两个点是1维)
第1位相加 = 0+1=1 (等于1,即不是0,也不是)
第2位相加 = 0+0=2 (等于,这里是2的1次幂,因为两个点合并,两个点是1维)
所以结果是0的个数和的个数共有2个,恰好为(N-1)=3-1=2,因此两个点可以合并同理,我们检验下(0)和(6)
0 = 000(2),6=110(2)
0+1=1
0+1=1
0+0=0
0和的个数共有1个,不是(N-1)= 2,因此两个点不可以合并
- 推论2:在N维情况下,如果两条线可以合并,意味着其8421编码对应的二进制之和恰好有(N-2)个0或。
- 推论3:在N维情况下,如果两个m维(为点是m=1,为线是m=2,…)可以合并,意味着其8421编码对应的0和1之和恰好有(N-1)个0或。
重复一遍:以上理论都是猜的,有误请指出,无误给证明
2.3 Python处理过程
- 因为在化简的过程中,无法确定顺序A->B->C->…的顺序,因为对某些表达式来讲存在一种可能,仅在该顺序下可以化到最简(本人bug出来的)
- 最初我想把A->B的线段当作一个矢量,对矢量进行处理,但是2、3、4维不好处理(计算上不好处理)
- 想到常用的
chmod 755
这个例子,决定按二进制进行处理 - 在采用二进制后,虽说带有权重了,但是不能直接化简,因为有吸收律:a+ab->a,但是何时将b吸收进a,还是吸收进可能的c,需要考虑,因此不能直接吸收
- 在使用8421编码后,不能直接相减,例如(5,4,3,2)这四个虽然共面,但是不存在于立方体的表面,因此该组数据不能统一化简
2.4 源码
我的思路是:点线面体 4维 …
即
- 首先将所有真值表中值为1的点进行互连,得到线段,将穿越面、穿越体、穿越时间等的线段进行剔除,得到“合理”的线段
- 在线段的基础上,得到“合理”的面
- 在面的基础上,得到合理的“体”
- …直到最高维度
- 将所有的线、面、体、…的集合(python这里我用的是一个列表)进行化简,因为之前得到的线、面、体、…肯定有重复的,可以剔除的
- 剔除方法为:从低维向高进行剔除,因为有的线已经构成面了,因此将所有的面中的元素进行合并,判断该线段是否在合并的列表中,在则剔除。
- 同理剔除多余的面、体、…
- 最后进行同维度的剔除,比如线段ab、bc、cd,其实只需要ab、cd就够了,不需要bc了,因为b点和c点已经包含在ab、cd中了,这是同维度的剔除。
- 同理进行其余维度的同维度剔除
最后代码如下:
本人水平有限,如有错误,感谢指正
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
result = []
for i in data:
num = 0
for j in range(len(i)):
num += i[j] * (2**(column-1-j))
result.append([num])
return column,result
# 判断是否共线、共面、共体、...
def Cmp(A, B, N):
result = A + B
result.sort(reverse=False)
if(len(result) != len(set(result))):
return None
cmp = []
flag = A[0] >= B[0]
for i in range(len(A)):
if(flag):
cmp.append(A[i] - B[i])
else:
cmp.append(B[i] - A[i])
cmp = list(set(cmp))
cmp.sort(reverse=False)
#print("++++++++++++++++++++++++++++++++++")
#print(cmp)
#print(len(A))
#print("----------------------------------")
#if(len(cmp) == 1):
if(len(cmp) == 1):
for i in range(N):
if(cmp[0] == 2**i):
#if(result == [11,12,13,14]):
cnt = [0] * N
for i in result:
num = bin(i)[2:]
num = '0'*(N-len(num)) + num
for j in range(N):
cnt[j] += eval(num[j])
cnt_2 = 0
for i in cnt:
if(i == 0 or i == 2*len(A)):
cnt_2 += 1
if(cnt_2 == N-len(A)):
return result
else:
return None
return None
# dot是所有值为1的点的集合,
# N是超几何空间的维度
def Expansion(dot, N):
data_update = dot
data_update.sort(reverse=False)
data = []
data.append(data_update)
for i in range(N):
tmp = []
for j in range(len(data_update)):
if (len(data_update) == 1):
tmp = []
break
for k in range(j+1, len(data_update)):
cmp_data = Cmp(data_update[j], data_update[k], N)
if (cmp_data != None):
tmp.append(cmp_data)
#if(tmp == [[0,2,5,7]]):
# print("+++++++++++++++++++++++++++++++++++")
# print(data_update)
# print("-----------------------------------")
####################################################################
# 去重
#print(tmp)
tmp.sort(reverse=False)
unique_list = []
[unique_list.append(i) for i in tmp if not i in unique_list]
####################################################################
data = data + [unique_list]
# data.append(unique_list)
data_update = unique_list
return data
def Include(high, low):
return set(low).issubset(set(high))
def Simplify(data):
result = data
scatter = []
################################
for i in result:
tmp = []
for j in i:
for k in j:
tmp.append(k)
scatter.append(tmp)
################################
for i in range(len(data) - 1):
for j in range(len(data[i])-1, -1, -1):
if (Include(scatter[i+1], data[i][j])):
del (result[i][j])
# 同级去重
final_result = []
for i in result:
final_result.append(Level_simply(i))
return final_result
def Level_simply(data):
result = []
NUM = sum_List(data)
i = 0
while(i <len(data)):
tmp = data.copy()
del(tmp[i])
if(NUM != sum_List(tmp)):
result.append(data[i])
else:
del(data[i])
i -= 1
del(tmp)
if(i == len(data)-1):
break
i += 1
return result
def sum_List(data):
scatter = []
for i in data:
for j in i:
scatter.append(j)
scatter = list(set(scatter))
return len(scatter)
def Get_Exp(data, N):
result = []
for i in range(len(data)):
for j in data[i]:
if (j != []):
result.append(Num_2_Symbol(j, i, N))
return result
def Print_Exp(data):
line = ""
for i in data:
#line += i + " + "
line += str(i) + " | "
line = line[:-3]
return line
def Num_2_Symbol(data, l, N):
level = 2**l
#print("+++++++++++++++++++++++++++++++++++++++")
#print(data)
#print(level)
#print("---------------------------------------")
flag = [0]*N
line = ""
if (len(data) > 1):
for i in range(len(data)):
num = bin(data[i])[2:]
num = '0'*(N-len(num)) + num
for j in range(N):
flag[j] = flag[j] + eval(num[j])
#######################################
for i in range(N):
if (flag[i] == 0):
line += "(~s[" + str(i) + "])&"
elif (flag[i] == level):
line += "s[" + str(i) + "]&"
line = line[:-1]
else:
# 进入else说明只有1个元素
num = bin(data[0])[2:]
num = '0'*(N-len(num)) + num
for i in range(len(num)):
if (eval(num[i]) == 0):
line += "(~s[" + str(i) + "])&"
else:
line += "s[" + str(i) + "]&"
line = line[:-1]
#print("++++++++++++++++++++++++++++++")
#print(data)
#print(level)
#print(flag)
#print(line)
#print("--------------------------------")
return line
if __name__ == "__main__":
#a = [[3], [7], [5], [4], [1]]
#a = [[0], [7], [5],[2]]
#r = Expansion(a, 3)
#f = Simplify(r)
#s = Get_Exp(f, 3)
#t = Print_Exp(r)
#print(r)
#N指字母个数
N,a = Read_csv_True('test.csv','utf-8')
r = Expansion(a, N)
f = Simplify(r)
s = Get_Exp(f, N)
t = Print_Exp(s)
print(t)
2.5 2024-4-17更新
晚上在看《Digital System Test and Testable Design》的时候,看到一张让我眼前一亮的图():
原书内容:We use circuit of Fig. 6.8 as a primitive that will be described in cubical form. The Karnaugh
map and the cubical representation of this function are also shown and will be used for describing
cubes for this function.