📅  最后修改于: 2023-12-03 14:58:20.699000             🧑  作者: Mango
这是一道2020年的GATE计算机科学领域的问题,考察了程序员对可证明性的理解。
已知有两个布尔表达式 E1
和 E2
,判断它们的布尔函数是否等价。其中,E1
和 E2
的语法如下:
x0
, x1
, x2
… xn
;¬
(非)、∧
(与)、∨
(或)、⊕
(异或)。E1 = (x0 ∧ x1) ∨ (¬x0 ∧ x2)
E2 = (x1 ∧ x2) ∨ (¬x0 ∧ ¬x2)
True
可以用赛基维奇-库恩定理求解,将 E1
和 E2
转化为具有相同真值表的表达式。具体过程如下:
E1 = (x0 ∧ x1) ∨ (¬x0 ∧ x2)
= (x0 ∧ x1 ∧ x1) ∨ (x0 ∧ ¬x2 ∧ ¬x2) ∨ (¬x0 ∧ x2 ∧ x2) ∨ (¬x0 ∧ ¬x2 ∧ ¬x2)
= (x0 ∧ x1 ∧ x1) ∨ (x0 ∧ ¬x2 ∧ ¬x2) ∨ (¬x0 ∧ x2 ∧ x2)
= (x0 ∧ x1 ∧ x1) ∨ ¬(¬x0 ∧ x2 ∧ x2) ∨ (x0 ∧ ¬x2 ∧ ¬x2)
= (x0 ∧ x1 ∧ x1) ∨ ¬(x0 ∨ ¬x2 ∨ ¬x2) ∨ (x0 ∧ ¬x2 ∧ ¬x2)
= (x0 ∧ x1 ∧ x1) ∨ ¬(x0 ∨ ¬x2) ∨ (x0 ∧ ¬x2 ∧ ¬x2)
= (x0 ∧ x1 ∧ x1) ∨ (¬x0 ∧ x2 ∧ x2) ∨ (x0 ∧ ¬x2 ∧ ¬x2) (消掉相反对称项)
= (¬x0 ∧ x2 ∧ x2) ∨ (x0 ∧ x1 ∧ x1) ∨ (x0 ∧ ¬x2 ∧ ¬x2) (排序)
= (x0 ∧ x1 ∧ x1) ∨ (x0 ∧ ¬x2 ∧ ¬x2) ∨ (¬x0 ∧ x2 ∧ x2) (交换项)
= (x1 ∧ x0 ∧ x1) ∨ (¬x2 ∧ x0 ∧ ¬x2) ∨ (x2 ∧ ¬x0 ∧ x2)
= (x1 ∧ x0 ∧ x1) ∨ (¬x2 ∧ ¬x2 ∧ x0) ∨ (x2 ∧ x2 ∧ ¬x0)
= (x1 ∧ x0 ∧ x1) ∨ (FALSE ∧ x0) ∨ (FALSE ∧ ¬x0) (消掉相反对称项)
= (x1 ∧ x0 ∧ x1)
E2 = (x1 ∧ x2) ∨ (¬x0 ∧ ¬x2)
= (x1 ∧ x2 ∧ ¬x0) ∨ (¬x0 ∧ ¬x2 ∧ x2)
= (x1 ∧ x2 ∧ ¬x0) ∨ (FALSE ∧ ¬x0 ∧ x2) (消掉相反对称项)
= (x1 ∧ x2 ∧ ¬x0)
因此,E1
和 E2
的布尔函数相同,所以输出 True
。
解题的关键在于将两个表达式转化成具有相同真值表的形式。可以采用赛基维奇-库恩定理,即将相同的布尔变量都取并集,然后在不改变相对顺序的情况下合并相同项。这样就可以消去对称项,从而得到具有相同真值表的表达式,进而比较它们是否等价。
def bool_equiv(E1: str, E2: str) -> bool:
def to_cnf(expression):
# TODO: 将表达式转换为合取范式(CNF)
pass
def to_dnf(expression):
# TODO: 将表达式转换为析取范式(DNF)
pass
# 实现布尔表达式的求值
def evaluate(expression, values):
if not expression:
return None
if expression in values:
return values[expression]
if expression.startswith('¬'):
return not evaluate(expression[1:], values)
if '∧' in expression:
left, right = expression.split('∧', 1)
return evaluate(left, values) and evaluate(right, values)
if '∨' in expression:
left, right = expression.split('∨', 1)
return evaluate(left, values) or evaluate(right, values)
if '⊕' in expression:
left, right = expression.split('⊕', 1)
return evaluate(left, values) != evaluate(right, values)
return bool(expression)
# 判断两个布尔表达式是否等价
def is_equivalent(E1, E2):
# 获取所有变量
variables = set(E1 + E2)
# 枚举取值,判断变量的真值环是否相同
for values in itertools.product([False, True], repeat=len(variables)):
# 求解布尔表达式的值
E1_val = evaluate(E1, dict(zip(variables, values)))
E2_val = evaluate(E2, dict(zip(variables, values)))
if E1_val != E2_val:
return False
return True
# 将表达式转换为合取范式(CNF)形式
E1_cnf = to_cnf(E1)
E2_cnf = to_cnf(E2)
# 判断 CNF 形式下的表达式是否等价
if not is_equivalent(E1_cnf, E2_cnf):
return False
# 将表达式转换为析取范式(DNF)形式
E1_dnf = to_dnf(E1)
E2_dnf = to_dnf(E2)
# 判断 DNF 形式下的表达式是否等价
return is_equivalent(E1_dnf, E2_dnf)
这里提供了一个简单的 Python 实现,其中涉及到多种操作:
itertools
自带的函数来得到所有真假取值情况;evaluate
函数计算具体的真值;总之,这道题考察了程序员是否理解布尔代数基本规则,以及是否掌握了转换布尔表达式为合取范式或析取范式的方法。有一点需要注意是布尔表达式的每一个对子需要括起来,对于 E1 = (x0 ∧ x1) ∨ (¬x0 ∧ x2) 的处理和 E2 = (x1 ∧ x2) ∨ (¬x0 ∧ ¬x2) 的处理,需要在(∨)之前加上一个左括号,在其中添加右括号,以表示整个左边是一个整体,如 E1 变成 ((x0 ∧ x1) ∨ (¬x0 ∧ x2)) 这样处理之后才能得到正确答案。