优化逻辑的工具?

时间:2012-05-22 21:48:24

标签: logic boolean-logic

我正在用java编写处理器模拟器,控制信号非常繁琐。是否有任何生成逻辑的工具如下:

二进制逻辑:

input[0]: 00001
input[1]: 00000
input[2]: 00010
input[3]: 00011

输出:

if(input.subString(0,3) == "000") 
    //do something;

基本上输出找到输入的公共部分。在上面的例子中,无论是00000, 00001, 00010, 00011

,它都会说“任何以000开头的东西都会做某事”

优化类似于k-map,除了我有一百个输入,手动优化根本不实用。

以下是k-map的示例,与我上面的示例无关

example kmap

输出不必是java语法,任何简化的逻辑语句都可以

1 个答案:

答案 0 :(得分:1)

所以你有一大堆长度为N位的字符串(其中N大约为100),你想要一个匹配这些字符串的简单逻辑表达式而不是其他字符串吗?

您可以尝试制作一个为您构建Kernaugh地图的程序。这将是一个有趣的练习。我不太记得Kernaugh地图,但我认为行和列上的标签使用格雷码进行排列。

或者你可以试着让这个问题对于手工制作的Kernaugh地图更容易处理。对于每个字符串,找到所有字符串共有的位。然后打印人类剩余比特位置的列表,以构建地图。

一些Python代码:

str_len = 5
strs = [
     [0,0,0,0,1],
     [0,0,0,0,0],
     [0,0,0,1,0],
     [0,0,0,1,1],
]
for i in range(str_len):
    if all([x[i] for x in strs]):
        print 'Bit %d is 1' % i
    elif not any([x[i] for x in strs]):
        print 'Bit %d is 0' % i
    else:
        print 'Bit %d is contingent' % i

此时你可以尝试考虑编码B剩余的偶然位的方法。在这个例子中,碰巧所有案例都被覆盖(你可以将其作为一个特例来检测 - 例如N = 2^B)。

用于查找或有位的公式的强力算法将是:

  1. 选择下一个临时位i
  2. 将S分为S0(位i = 0的子集)和S1(位i = 1的子集)。
  3. 分别递归地找到S0和S1的公式f0和f1。
  4. S的公式为(~b[i] & f0) | (b[i] & f1)
  5. 有一些优化。容易的是S0或S1为空的地方 - 然后省略所得公式的那个分支。另一个是所有可能的组合在一个集合中(类似于上面的例子);在这种情况下,公式不需要引用位。最难的是找到一个好的顺序迭代比特。按顺序天真地做它可能会导致一个不太理想的公式。

    你实际上可以跳过上面的第一个建议并在所有位上运行它。总是1或0的位只会产生S0或S1为空的微不足道的情况。

    这个相当混乱的Python代码通过一些优化来执行算法。 N.B。它没有经过多少测试,也不一定能产生最佳输出!

    def get_formula(S, i=0):
        # Special case where it's an empty set -- return a tautology
        if len(S) == 0:
            return '1'
    
        remaining_bits = len(S[0]) - i
    
        # Special case where no bits are left
        if remaining_bits <= 0:
            return '1'
    
        # Partition the set
        S0 = filter(lambda x: x[i] == 0, S)
        S1 = filter(lambda x: x[i] == 1, S)
    
        f0 = get_formula(S0, i+1)
        f1 = get_formula(S1, i+1)
    
        # Special cases where one subset is empty
        # Also special case for subformula being tautology
        if len(S1) == 0:
            if f0 == '1':
                return '~b[%d]' % i
            return '~b[%d] & (%s)' % (i, f0)
        if len(S0) == 0:
            if f1 == '1':
                return 'b[%d]' % i
            return 'b[%d] & (%s)' % (i, f1)
    
        # Special cases where one or both subformulas was a tautology
        if f0 == '1' and f1 == '1':
            return '1'
        if f0 == '1':
            return '~b[%d] | b[%d] & (%s)' % (i, i, f1)
        if f1 == '1':
            return '~b[%d] & (%s) | b[%d]' % (i, f0, 1)
    
        # General case
        return '~b[%d] & (%s) | b[%d] & (%s)' % (i, f0, i, f1)
    
    
    strs = [
         [0,0,0,0,1],
         [0,0,0,0,0],
         [0,0,0,1,0],
         [0,0,0,1,1],
    ]
    
    print get_formula(strs)
    

    最后,我认为使这段代码找到更优化公式的一种方法是在S中向前扫描始终为0或始终为1的位,并提前处理它们。每个子集中剩余的相关位将被推入深度嵌套的子公式中,在这些子公式中,与过早处理它们相比,它们将形成更少的冗余公式。我认为这实际上模拟了Kernaugh-map样式结构:在每一步,始终为0或总是1位的集合在地图上定义了一个矩形。找到该集合,一次处理它们(例如,作为紧凑的公式~b[0] & ~b[1] & ~b[2])然后递归剩余的位。您需要跟踪已处理的位位置,而不是使用i按顺序执行。

    (实际上,现在我考虑一下,对于最佳公式,你还需要通过一次选择一堆相关位来巧妙地进行分区。一个有趣的问题......)