【问题标题】:Parsing and computing boolean set definitions解析和计算布尔集定义
【发布时间】:2014-04-14 11:09:54
【问题描述】:

假设我有一组 S 定义为字符串,例如如下:

S = '(A or B) and not(A and C)'

其中 A、B 和 C 是有限集,例如:

A = {0, 1}
B = {0, 2}
C = {1, 3}

如果我们一步一步分析S,我们有:

(A or B)   = {0, 1, 2}
(A & C)    = {1}
not(A & C) = {0, 2, 3}

这给了我们最终的结果:

S = {0,2}

鉴于S 的定义为一般布尔公式,我如何计算其元素?

我不太清楚如何着手解决这个问题。一方面,我想知道是否需要使用完整的词法解析器。另外,经过一番阅读,我还发现了两个似乎高度相关的概念,但不知道它们将如何应用:

【问题讨论】:

  • 旁白:andor 可能不会像您认为的那样行事。如果您尝试A = {0, 1}; B = {0, 2}; Z = A or B; print(Z),您将看不到{0, 1, 2}。 OTOH,A | B 应该满足您的期望。

标签: python math set boolean scipy


【解决方案1】:

我要做的是使用shunting yard algorithm 将其转换为反向波兰表示法,然后使用此simple algorithm 来评估espression。

那么就不需要合适的解析器了,你只需要识别组成定义的每个单词、parens和特殊字符,而不需要“理解句子的结构”。

【讨论】:

    【解决方案2】:

    如果您愿意将 S 转换为适合与eval() 一起使用的字符串,则无需编写自己的解析器。将 S'(A or B) and not(A and C)' 更改为使用 Python 的 in 运算符 '(x in A or x in B) and not(x in A and x in C)' 的等效 T

    通过遍历整个元素并测试它们是否与上述表达式匹配来计算结果。 这是交互式提示中的一个已解决的示例:

    >>> T = '(x in A or x in B) and not(x in A and x in C)'
    >>> sets = {'A': {0, 1}, 'B': {0, 2}, 'C': {1, 3}}
    >>> universe = {x for s in sets.values() for x in s}
    >>> {x for x in universe if eval(T, sets, {'x': x})}
    set([0, 2])
    

    要自动进行转换,请为集合变量创建一个命名空间,其中变量查找会执行集合成员资格测试。将它们放在一起为您提供了一个简单而干净的集合表达式评估器:

    class SetVariables(dict):
        'Transform a variable lookup into a membership test'
        def __getitem__(self, var):
            s = dict.__getitem__(self, var)
            return self.x in s
    
    def set_eval(expr, **sets):
        'Evaluation a set expression for the given sets'
        universe = {x for s in sets.values() for x in s}
        expr = compile(expr, '', 'eval')
        variables = SetVariables(sets)
        results = set()
        for x in universe:
            variables.x = x
            if eval(expr, {}, variables):
                results.add(x)
        return results
    
    if __name__ == '__main__':
        print set_eval(expr = '(A or B) and not(A and C)',
                       A = {0, 1},
                       B = {0, 2},
                       C = {1, 3}
                      )
    

    希望这能解决您的问题并让您不必编写自己的解析器:-)

    【讨论】:

      猜你喜欢
      • 2015-05-10
      • 1970-01-01
      • 2016-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 2014-11-30
      • 2023-03-15
      相关资源
      最近更新 更多