1

Say I have a Boolean formula that uses a known set of tokens, e.g.:

  • Boolean operators: and, or, not
  • Grouping operators: (, )

Given a Boolean formula using those tokens, e.g.:

F: (A or B) and not(A and C)

How can I convert this definition to a Python expression of set operators?

Fp = (x in A or x in B) and not(x in A and x in C)

For background on this question, see this thread and accepted answer.

Community
  • 1
  • 1
Amelio Vazquez-Reina
  • 91,494
  • 132
  • 359
  • 564
  • Not sure why you accepted the linked answer which apparently didn't really solve the general problem. Anyway, you need to parse the boolean expression. You might find the [pyparsing](http://pyparsing.wikispaces.com/) module helpful. It comes with a number of examples to help you get going. – martineau Mar 11 '14 at 17:50

4 Answers4

1

See the docs for set operations. You can do something like:

Fp = (A | B) - C
Matt Woelk
  • 1,940
  • 1
  • 20
  • 24
1

Assuming your variables are one character in length:

s = "(A or B) and not(A and C)"
print re.sub("(?<![a-zA-Z])([A-Za-z])(?![A-Za-z])", "x in \\1", s)
Sabuj Hassan
  • 38,281
  • 14
  • 75
  • 85
1

It looks like basically you are going to prepend x in to anything that is not one of your tokens. That looks like this, maybe:

tokens = ['and', 'or', 'not']
grouping = ['(', ')']

def resub(match):
    matchval = match.group(0)
    if matchval in tokens:
        return matchval
    return 'x in %s'%matchval

s = "(A or B) and not(A and C)"

re.sub('\w+', resub, s)
'(x in A or x in B) and not(x in A and x in C)'

It should work for symbols that are recognized as words; if you need something more specific (i.e. your variables have other characters in them), you'd need to define it yourself instead of using \w...

Corley Brigman
  • 11,633
  • 5
  • 33
  • 40
1

This function will match against any Python identifier, will substitute for any desired target variable, and it's all wrapped up to be easy to use:

import re

def subst_in(s, varname, keywords={'and', 'or', 'not'}):
    repl = "{} in {{}}".format(varname)
    def fn(match):
        s = match.group(0)
        return s if s in keywords else repl.format(s)
    return re.sub("[a-z_][a-z0-9_]*", fn, s, flags=re.I)

f = "(A or B) and not(A and C)"
fp = subst_in(f, "x")

gives

'(x in A or x in B) and not(x in A and x in C)'

Edit: although frankly it should be

'x in B or (x in A and x not in C)'
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99