从字符串中读取方程并解析它



>我有这样用字符串形式编写的布尔数学表达式

"A and B or C and not D"
"A and (B or C) and not D"

我想使用 python 解决它,将为"and"、"or"和"and not"和"or not"运算符调用不同的函数。我想不出任何可以解决这个问题的想法。

我可以用分裂来打破等式,但下一步是什么?

更新: A 和 B 以及其他可以包含一些将返回列表的单词,并在该列表上执行"和"、"或"和其他操作。

我已经创建了该列表,我可以解决 2 个变量问题,但是当它具有多个组合时如何解决它。

符号包 Sympy 似乎是一个不错的选择。

在其基本形式中,sympy希望andornot写成&|~,可以在调用解析器之前替换。请注意,如果存在包含"and"之类的名称,则简单的字符串替换将不起作用。

之后,您可以使用sympy进行任何类型的简化,操作和替换,就像任何其他数学表达式一样。

举个例子:

from sympy.parsing.sympy_parser import parse_expr
str = "Alice and (Bob or Carla) and not David"
str = str.replace('and', '&').replace('or', '|').replace('not', '~')
expr = parse_expr(str)
print(expr)
print(expr.subs({'Alice': True, 'Bob': False}))

输出:

Alice & ~David & (Bob | Carla)
Carla & ~David

在注释中,您要求在集合上操作,而不是在布尔值上操作。小数的集合在 Sympy 中表示为FiniteSet。通常,它们需要使用函数表示法编写:Union(arg1, arg2, arg3, ...)。但是我们可以利用布尔运算符AndOrNot,它们确实允许中缀符号构造表达式,然后像集合操作一样进行计算。

from sympy.parsing.sympy_parser import parse_expr
from sympy import Atom, FiniteSet, And, Or, Not, Union, Intersection, Complement

def evaluate_expr(expr, replacements, complete_set):
if isinstance(expr, Atom):
return expr.subs(replacements)
elif expr.func == Or:
return Union(*[evaluate_expr(a, replacements, complete_set) for a in expr.args])
elif expr.func == And:
return Intersection(*[evaluate_expr(a, replacements, complete_set) for a in expr.args])
elif expr.func == Not:
return Complement(complete_set, evaluate_expr(expr.args[0], replacements, complete_set))
replacements = {'Alice': {1, 2}, 'Bob': {1, 2, 3}, 'Carla': {5}, 'David': {1, 4, 6}}
for r in replacements:
# convert the replacements to their Sympy representation
replacements[r] = FiniteSet(*replacements[r])
print("Replacements:", replacements)
complete_set = Union(*replacements.values()) # the set of all possible values is used to implement "not"
tests = ["Alice", "Alice or Bob", "Alice and Bob and Carla", "Alice and (Bob or Carla) and not David"]
for test in tests:
expr = parse_expr(test.replace('and', '&').replace('or', '|').replace('not', '~'))
print(expr)
print(" --->", evaluate_expr(expr, replacements, complete_set))

输出:

Replacements: {'Alice': FiniteSet(1, 2), 'Bob': FiniteSet(1, 2, 3), 'Carla': FiniteSet(5), 'David': FiniteSet(1, 4, 6)}
Alice
---> FiniteSet(1, 2)
Alice | Bob
---> FiniteSet(1, 2, 3)
Alice & Bob & Carla
---> EmptySet
Alice & ~David & (Bob | Carla)
---> FiniteSet(2)

最新更新