def logically_reduce(self, token_list): """Return token_list in conjunctive normal form as a string. CNF has the property that there will only ever be one level of parenthetical nesting, and all distributable operators (such as the not in -(p | q) will be fully distributed (as -p + -q). """ maxdepth, dummy_balanced, d0_p = self.nesting_depth_and_balance( token_list) s = ' '.join(token_list) s = self._invenio_to_python_logical(s) last_maxdepth = 0 while maxdepth != last_maxdepth: # XXX: sometimes NaryExpr doesn't try: # fully flatten Expr; but it usually s = str(to_cnf(s)) # does in 2 passes FIXME: diagnose except SyntaxError: raise SyntaxError( str(s) + " couldn't be converted to a logic expression.") last_maxdepth = maxdepth maxdepth, dummy_balanced, d0_p = self.nesting_depth_and_balance( self.tokenize(s)) if d0_p == 1 and s[0] == '(' and s[ -1] == ')': # s can come back with extra parens s = s[1:-1] s = self._python_logical_to_invenio(s) return s
def logically_reduce(self, token_list): """Return token_list in conjunctive normal form as a string. CNF has the property that there will only ever be one level of parenthetical nesting, and all distributable operators (such as the not in -(p | q) will be fully distributed (as -p + -q). """ maxdepth, dummy_balanced, d0_p = self.nesting_depth_and_balance(token_list) s = " ".join(token_list) s = self._invenio_to_python_logical(s) last_maxdepth = 0 while maxdepth != last_maxdepth: # XXX: sometimes NaryExpr doesn't try: # fully flatten Expr; but it usually s = str(to_cnf(s)) # does in 2 passes FIXME: diagnose except SyntaxError: raise SyntaxError(str(s) + " couldn't be converted to a logic expression.") last_maxdepth = maxdepth maxdepth, dummy_balanced, d0_p = self.nesting_depth_and_balance(self.tokenize(s)) if d0_p == 1 and s[0] == "(" and s[-1] == ")": # s can come back with extra parens s = s[1:-1] s = self._python_logical_to_invenio(s) return s
def test_ANDed_pair(self): """logicutils - ANDed pair should be in CNF""" self.assertEqual(to_cnf(expr('a & b')), Expr('&', 'a', 'b'))
def test_ORed_pair(self): """logicutils - ORed pair should be in CNF""" self.assertEqual(to_cnf(expr('a | b')), Expr('|', 'a', 'b'))
def test_complex_example_Norvig(self): """logicutils - (P&Q) | (~P & ~Q) in CNF""" self.assertEqual(str(to_cnf('(P&Q) | (~P & ~Q)')), str('((~P | P) & (~Q | P) & (~P | Q) & (~Q | Q))'))
def test_singleton(self): """logicutils - singletons are already in CNF""" self.assertEqual(to_cnf(expr('a')), Expr('a'))