我正在寻找一种方法来扩展形式的逻辑表达式(在字符串中):
'(A或B)和((C和D)或E)'
在Python中生成所有正集的列表,即
['A and C and D',
'A and E',
'B and C and D',
'B and E']
但我一直无法找到如何做到这一点。我已经调查了pyparser,但我无法确定哪个例子在这种情况下是相关的。使用某种逻辑操作可能非常容易,但我不知道任何形式逻辑。任何帮助或对可能有用的资源的引用都将非常感激。
答案 0 :(得分:2)
这是pyparsing位,取自示例SimpleBool.py。首先,使用infixNotation
(以前称为operatorPrecedence
)来定义支持括号分组的表达式语法,并识别操作的优先级:
from pyparsing import *
term = Word(alphas)
AND = Keyword("and")
OR = Keyword("or")
expr = infixNotation(term,
[
(AND, 2, opAssoc.LEFT),
(OR, 2, opAssoc.LEFT),
])
sample = '(A or B) and ((C and D) or E)'
result = expr.parseString(sample)
from pprint import pprint
pprint(result.asList())
打印:
[[['A', 'or', 'B'], 'and', [['C', 'and', 'D'], 'or', 'E']]]
从这里,我们可以看到表达式至少被正确解析。
接下来,我们将解析操作添加到操作层次结构的每个级别。对于这里的解析操作,我们实际上传递了类,因此解析器不是执行函数并返回一些值,而是调用类构造函数和初始化器并返回特定子表达式的类实例:
class Operation(object):
def __init__(self, tokens):
self._tokens = tokens[0]
self.assign()
def assign(self):
"""
function to copy tokens to object attributes
"""
def __repr__(self):
return self.__class__.__name__ + ":" + repr(self.__dict__)
__str__ = __repr__
class BinOp(Operation):
def assign(self):
self.op = self._tokens[1]
self.terms = self._tokens[0::2]
del self._tokens
class AndOp(BinOp):
pass
class OrOp(BinOp):
pass
expr = infixNotation(term,
[
(AND, 2, opAssoc.LEFT, AndOp),
(OR, 2, opAssoc.LEFT, OrOp),
])
sample = '(A or B) and ((C and D) or E)'
result = expr.parseString(sample)
pprint(result.asList())
返回:
[AndOp:{'terms': [OrOp:{'terms': ['A', 'B'], 'op': 'or'},
OrOp:{'terms': [AndOp:{'terms': ['C', 'D'],
'op': 'and'}, 'E'], 'op': 'or'}],
'op': 'and'}]
既然表达式已经转换为子表达式的数据结构,我就把它留给你来完成向AndOp和OrOp添加方法的工作,以生成将整体评估为True的各种术语组合。 (查看invregex.py示例中的逻辑,该逻辑反转正则表达式,以获取有关如何将生成器函数添加到已解析类以生成所需术语的不同组合的想法。)
答案 1 :(得分:1)
听起来好像要将这些表达式转换为Disjunctive Normal Form。用于执行此操作的规范算法是Quine-McCluskey算法;您可以在相关Wikipedia article和this SO question的答案中找到有关其Python实现的一些信息。