Get elements in AND in a logical string using Python

I want to analyze logical strings and get all combinations of elements that are in the "and" logic. For example, for the string '(A and (B or C))' I should get [[A, B], [A, C]] and for the string '(A and B and (C or D and F) or F and G) "I have to get [[A, B, C], [A, B, D, F], [F, G]].

I am trying to use pyparsing. After this post, here is a parsing of a complex logical expression in pyparsing in binary tree mode. I manage to get a nested list with letters grouped according to preference ("and" has preference over "or", and the brackets overlap this):

import pyparsing as pp complex_expr = pp.Forward() vars = pp.Word(pp.alphas, pp.alphanums + "_") | pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?").setName('proteins') clause = pp.Group(vars ^ (pp.Suppress("(") + complex_expr + pp.Suppress(")") )) expr = pp.operatorPrecedence(clause,[ ("and", 2, pp.opAssoc.LEFT, ), ("or", 2, pp.opAssoc.LEFT, ),]) #print expr complex_expr << expr parseresult=complex_expr.parseString('( A and B and ( C or D and F ) or F and G )') print parseresult 

What gives:

[[[['A'], 'and', ['B'], 'and', [[[[C]], 'or', [['D'], 'and', ['F'] ]]]], 'or', [['F'], 'and', ['G']]]]]

Now, how can I process this result to achieve the desired result? I would appreciate any help. I tried pyparsing, but I'm open to other modules that might be better.

Thanks in advance.

+5
source share
1 answer

Python libraries will help us a bit:

 import re import itertools 

Record the required function:

 def analyse(expression): # Find all used symbols symbols = set(re.findall(r"\b[AZ]\b", expression)) # Find all combinations of symbols and values mappings = (dict(zip(symbols, values)) for values in itertools.product([False, True], repeat=len(symbols))) # Select combinations that make the whole expression true solutions = [sorted(name for name in mapping if mapping[name]) for mapping in mappings if eval(expression, None, mapping)] # Filter out redundant solutions return sorted(s1 for s1 in solutions if not any(set(s1) > set(s2) for s2 in solutions)) 

And let him test it:

 assert analyse("( A and ( B or C ) )") == [["A", "B"], ["A", "C"]] assert analyse("( A and B and ( C or D and F ) or F and G )") == [["A", "B", "C"], ["A", "B", "D", "F"], ["F", "G"]] 

There are comments in the source code. In any case, the main steps:

  • Variable expressions are found as single-character uppercase names.
  • Each variable can be either True or False. We find all the combinations.
  • We select only those combinations that make the whole expression True.
  • We keep only minimal solutions, i.e. those that are not supernets of other solutions.

I would like to thank you for a good question. Python itertools never ceases to amaze me .; -)

+3
source

All Articles