📌  相关文章
📜  门| Sudo GATE 2020 Mock II(2019 年 1 月 10 日)|问题2(1)

📅  最后修改于: 2023-12-03 15:28:47.047000             🧑  作者: Mango

这是一个涉及布尔逻辑的问题。给定 n 个布尔变量,每个变量可以是真或假,共有 $2^n$ 种可能的组合。在本问题中,我们要编写一个程序,该程序将输入表示一个布尔函数的真值表,输出该布尔函数的最小门集合,其中每个门可以是 NOT、AND、OR、XOR。

问题描述

考虑一个布尔函数 f(x_1, x_2, ..., x_n),其中每个变量 x_i 可以是T或F。输入表示 f(x_1, x_2, ..., x_n) 的所有可能组合的真值表。例如,如果 n = 2,则真值表如下所示:

| x1 | x2 | f(x1,x2) |
|----|----|----------|
| T  | T  | T        |
| T  | F  | F        |
| F  | T  | F        |
| F  | F  | F        |

这个布尔函数是以下表达式的简写:

((x1 AND x2) OR (NOT x1 AND NOT x2))

问题是找到此布尔函数的一个最小门级组合,其中每个门都可以是 NOT、AND、OR 或 XOR 操作。 每个元素都可以出现多次,其中:

  • NOT 操作仅应用于单个变量
  • AND 和 OR 操作仅应用两个变量
  • XOR 操作应用两个变量

在上面的例子中,最小门集合是:

NOT(x1) XOR x2
解法

这个问题是一个经典的问题,可以使用基于卡诺图和奎因-麦克拉斯基方法的变量消除算法来解决。这些解决方案旨在找到最小化逻辑门的布尔函数表示.

这里提供一种基于布尔公式缩减的解决方案,利用 Quine-McCluskey 算法与 Petrick’s 方法。具体步骤如下:

  1. 构建一个真值表并转换成布尔函数的标准表示。

  2. 将此表达式化简为Sum of Products(SOP)或 Product of Sum(POS)表达式。

  3. 将缩减后的表达式转换回最终布尔函数表示。

步骤一:构建真值表

输入给定 $2^n$ 行,每行 n+1 个字符,其中最后一个字符表示相应的布尔函数的输出值。对于第 i 行,输入表示为:

x_i,1 x_i,2 ... x_i,n y_i

其中,y_i 表示布尔函数输出值,可以是 0 或 1,x_i,j 是布尔变量 i 的第 j 个值。例如,如果 n = 2,则以下是真值表的一部分。

T T T
T F F
F T F
F F F
步骤二:化为标准表达式

我们首先将真值表化成布尔函数的标准表达式。具体而言,可以先化为 SOP 表达式,然后再简化为最小的 SOP。决策得 S算法可以帮助我们找到最小 SOP 表达式。

步骤三:最小化布尔函数

最后,通过 Petrick’s 方法将最小的 SOP 表达式转换为最小的门级逻辑表示,以便可轻松地实现。最小化布尔函数时,可以利用 Quine-McCluskey 算法和Petrick's 方法。有许多库和软件工具可以执行这个最小化过程。

代码实现

这里展示生成最小门级逻辑的示例 Python 代码:

from qm import QuineMcCluskey
from itertools import chain, combinations

def bool_minimizer(truth_table):
    vars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[:len(truth_table[0])-1]
    def implicants(minterms, vars):
        qmc = QuineMcCluskey(use_xor=False)
        qmc.set_coverage(vars)
        imp = qmc.simplify(minterms)
        return [ set(filter(lambda x: x.isupper(), i)) for i in imp ]
    def full_impl(minterms):
        impl = implicants(minterms, vars)
        nn = len(impl)
        s = [ set() ] + [ set(impl[i]) for i in range(nn) ]
        res = set()
        for r in chain.from_iterable(combinations(range(1,nn+1), i) for i in range(nn+1)):
            if len(s[r[0]].intersection(*(s[k] for k in r[1:]))) == 0:
                res.add(frozenset().union(*(s[k] for k in r)))
        return list(sorted(res, key=(lambda k: len(k))))[:10]
    def to_sum(f):
        return ' OR '.join([ ' AND '.join(v if c=='1' else 'NOT '+v for (v,c) in zip(vars,w)) for w in f ])
    n_values = len(truth_table)
    minterms = set(i for i in range(n_values) if truth_table[i][-1])
    mins = full_impl(minterms)
    results = []
    for m in mins:
        terms = []
        for v in vars:
            pos = frozenset( q | {v} for q in m if v not in q )
            neg = frozenset( q | {'!'+v} for q in m if '!'+v not in q )
            terms.append( f'({to_sum(pos)}) AND ({to_sum(neg)})' )
        results.append(' OR '.join(terms))
    return results

# 示例输入
truth_table = [
    ['T', 'T', 'T', 'T'],
    ['T', 'F', 'F', 'F'],
    ['F', 'T', 'F', 'F'],
    ['F', 'F', 'F', 'F']
]
# 输出最小化布尔函数的门级逻辑
print(bool_minimizer(truth_table))

代码说明

这个 Python 代码定义了一个函数 bool_minimizer(truth_table)truth_table 是一个由行列表示的真值表。函数返回一个最小化布尔函数的门级逻辑的列表(字符串)。

此功能的实现需要 qmc 模块,因此需要安装它包括 pip install qmc

此函数的工作原理是将真值表递交给 Quine-McCluskey 算法进行化简,以获得最小的 SOP 表达式。然后,我们在运用 Petrick 方法生成与原始真值表具有相同输出值的最短逻辑表达式。结果是表示最短逻辑表达式的一组门级逻辑。