bsat.logic.laws
Defines the laws of propositional logic.
View Source
def distribute_ands(expr: Expression) -> Expression: """Applies distributive law where an OR occurs over an AND. Recursively applies the following distributive law until it is no longer applicable: a OR (b AND c) <=> (a OR b) AND (a OR c). Args: expr: The Boolean expression to apply the distributive law on. Returns: An equivalent Boolean expression with all ORs distributed over ANDs. """ if isinstance(expr, BinaryOperation): pq = distribute_ands(expr.operand_1) qr = distribute_ands(expr.operand_2) op = expr.operator if op == Operators.OR and qr.operator == Operators.AND: p = pq.parse_tree q = qr.operand_1.parse_tree r = qr.operand_2.parse_tree expr_n = ExpressionBuilder.from_parse_tree([Operators.AND, [Operators.OR, p, q], [Operators.OR, p, r]]) tree_n = [Operators.AND, distribute_ands(expr_n.operand_1).parse_tree, distribute_ands(expr_n.operand_2).parse_tree] elif op == Operators.OR and pq.operator == Operators.AND: p = pq.operand_1.parse_tree q = pq.operand_2.parse_tree r = qr.parse_tree expr_n = ExpressionBuilder.from_parse_tree([Operators.AND, [Operators.OR, p, r], [Operators.OR, q, r]]) tree_n = [Operators.AND, distribute_ands(expr_n.operand_1).parse_tree, distribute_ands(expr_n.operand_2).parse_tree] else: tree_n = [op, pq.parse_tree, qr.parse_tree] elif isinstance(expr, UnaryOperation): tree_n = [expr.operator, distribute_ands(expr.operand_1).parse_tree] else: tree_n = expr.parse_tree return ExpressionBuilder.from_parse_tree(tree_n)
Applies distributive law where an OR occurs over an AND.
Recursively applies the following distributive law until it is no longer applicable: a OR (b AND c) <=> (a OR b) AND (a OR c).
Args: expr: The Boolean expression to apply the distributive law on.
Returns: An equivalent Boolean expression with all ORs distributed over ANDs.
View Source
def de_morgans_law(expr: Expression) -> Expression: """Moves negations inwards by repeatedly applying De Morgan's Law and removing double negations. De Morgan's Law States moves the negation inwards by inverting the truth value of both operands and switching AND with OR and vice versa. i.e. 1) NOT(a OR b) <=> NOT(a) AND NOT(b) 2) NOT(A AND B) <=> NOT(A) OR NOT(B) This is a recursive implementation, which also removes double negations which may arise from application of De Morgan's law, or otherwise. Args: expr: The Boolean expression to apply De Morgan's law on. Returns: An equivalent Boolean expression with negations only over literals. """ # De Morgan's is only applicable if current formula has the negation operator and the # operand itself is a binary formula with a conjunction or disjunction operator. if expr.operator == Operators.NOT and expr.operand_1.operator in [Operators.AND, Operators.OR]: if expr.operand_1.operator == Operators.AND: op = Operators.OR else: op = Operators.AND op1_neg = ExpressionBuilder.from_parse_tree([Operators.NOT, expr.operand_1.operand_1.parse_tree]) t1 = de_morgans_law(op1_neg).parse_tree op2_neg = ExpressionBuilder.from_parse_tree([Operators.NOT, expr.operand_1.operand_2.parse_tree]) t2 = de_morgans_law(op2_neg).parse_tree tree_n = [op, t1, t2] # In case current formula is a negation, and the child is also a negation, we simply # eliminate the double negation. elif expr.operator == Operators.NOT and expr.operand_1.operator == Operators.NOT: tree_n = expr.operand_1.parse_tree[-1] # In case current formula is itself binary, we check both operands for De Morgan's applicability. elif isinstance(expr, BinaryOperation): tree_n = [expr.operator, de_morgans_law(expr.operand_1).parse_tree, de_morgans_law(expr.operand_2).parse_tree] # Otherwise return the current formula as-is. else: tree_n = expr.parse_tree return ExpressionBuilder.from_parse_tree(tree_n)
Moves negations inwards by repeatedly applying De Morgan's Law and removing double negations.
De Morgan's Law States moves the negation inwards by inverting the truth value of both operands and switching AND with OR and vice versa. i.e. 1) NOT(a OR b) <=> NOT(a) AND NOT(b) 2) NOT(A AND B) <=> NOT(A) OR NOT(B)
This is a recursive implementation, which also removes double negations which may arise from application of De Morgan's law, or otherwise.
Args: expr: The Boolean expression to apply De Morgan's law on.
Returns: An equivalent Boolean expression with negations only over literals.