I'm trying to solve the following problem. I have a set of logical operations and I would like to resolve them into all possible combinations. For example:
"((A | X) & B & C) | (C | E) & A & ~Y"
Should result in the following solutions:
"A & B & C" "X & B & C" "C & A & ~Y" "E & A & ~Y"
In the past i got help with a similar porblem here which came back with the solution:
from sympy.parsing.sympy_parser import parse_expr
from sympy.logic.boolalg import to_dnf
lst = ['(a | b) & (c & d)', '(e & f) | (g | h)', '(i | j) | k']
comb = set()
for exp in lst:
log_expr = str(to_dnf(parse_expr(exp)))
for e in log_expr.split('|'):
comb.add(str(parse_expr(e)))
print(comb)
This code works till the additional OR clause. How would a efficient approach to this look like? The expressions can get quite complex, with multiple levels of parentheses, "and", "or", and "not" operations.
Don't use string methods like .split('|')
for symbolic manipulation. I don't know who recommended that to you before but it is bad advice.
Put the result into DNF and then Or.make_args
can separate the clauses:
In [55]: from sympy import *
In [56]: expr1 = parse_expr("((a | x) & b & c) | (c | e) & a & ~y")
In [57]: for expr2 in Or.make_args(to_dnf(expr1)): print(expr2)
a & b & c
a & c & ~y
b & c & x
a & e & ~y
For your other case:
In [70]: lst = ['(a | b) & (c & d)', '(e & f) | (g | h)', '(i | j) | k']
In [71]: expr1 = And(*map(parse_expr, lst))
In [72]: expr1
Out[72]: c ∧ d ∧ (a ∨ b) ∧ (g ∨ h ∨ (e ∧ f)) ∧ (i ∨ j ∨ k)
In [73]: for expr2 in Or.make_args(to_dnf(expr1)): print(expr2)
a & c & d & h & i
a & c & d & e & f & j
a & c & d & e & f & i
a & c & d & g & k
b & c & d & g & k
a & c & d & h & j
b & c & d & h & j
b & c & d & g & i
a & c & d & g & i
b & c & d & e & f & k
b & c & d & e & f & i
a & c & d & e & f & k
b & c & d & g & j
a & c & d & g & j
b & c & d & h & k
a & c & d & h & k
b & c & d & e & f & j
b & c & d & h & i