使用python,将一串AND和OR转换为disjunctive normal form(也称为"产品总和")的最佳方法是什么?
b AND (c OR (a AND d))
变为
(b AND c) OR (b AND a AND d)
我想按字典顺序对这些进行排序
(a AND b AND d) OR (b AND c)
答案 0 :(得分:2)
答案 1 :(得分:0)
以下是部分回答问题的示例(即不是解析/排序)
REPR_FORM_AS_TEXT = False
class Or(frozenset):
def __repr__(self):
if REPR_FORM_AS_TEXT:
return " OR ".join(repr(e) for e in self)
else:
return super().__repr__()
class And(frozenset):
def __repr__(self):
if REPR_FORM_AS_TEXT:
if len(self) > 1:
return "(" + " AND ".join(repr(e) for e in self) + ")"
else:
return "".join(repr(e) for e in self)
else:
return super().__repr__()
def dnf(expr, ):
"""Normalize a boolean expression to its DNF.
Expr can be an element, it this case it returns Or({And({element})}).
Expr can be an Or(...) / And(...) expressions, in which cases it returns also a disjunctive normalised form (removing identical elements)
assert dnf(And((Or((4, 5, 1)), Or((1, 2)), 7, 7))) == Or(
(
And((2, 5, 7)),
And((1, 5, 7)),
And((1, 2, 7)),
And((1, 7)),
And((2, 4, 7)),
And((1, 4, 7)),
)
)
"""
if not isinstance(expr, (Or, And)):
result = Or((And((expr,)),))
elif isinstance(expr, Or):
result = Or(se for e in expr for se in dnf(e))
elif isinstance(expr, And):
total = []
for c in itertools.product(*[dnf(e) for e in expr]):
total.append(And(se for e in c for se in e))
result = Or(total)
return result