Skip to content

Commit b3b76af

Browse files
committed
implemented evaluators equivalence, satisfiability and tautology
1 parent 5486fd1 commit b3b76af

3 files changed

Lines changed: 141 additions & 54 deletions

File tree

evaluation_function/propositional_logic/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
Implication,
1010
Biconditional,
1111
)
12-
from .evaluator import Assignment, FormulaEvaluator
12+
from .evaluator import (
13+
Assignment,
14+
FormulaEvaluator,
15+
EquivalenceEvaluator,
16+
SatisfiabilityEvaluator,
17+
TautologyEvaluator,
18+
)
1319

1420
__all__ = [
1521
"Formula",
@@ -23,4 +29,7 @@
2329
"Biconditional",
2430
"Assignment",
2531
"FormulaEvaluator",
32+
"EquivalenceEvaluator",
33+
"SatisfiabilityEvaluator",
34+
"TautologyEvaluator",
2635
]

evaluation_function/propositional_logic/evaluator.py

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from itertools import product
2+
from typing import Mapping, Set
3+
from .formula import (
4+
Formula,
5+
Atom,
6+
Truth,
7+
Falsity,
8+
Negation,
9+
Conjunction,
10+
Disjunction,
11+
Implication,
12+
Biconditional,
13+
)
14+
15+
16+
class Assignment:
17+
def __init__(self, assignment: Mapping[Atom, bool]):
18+
self._assignment = dict(assignment)
19+
20+
def get(self, atom: Atom) -> bool:
21+
if atom not in self._assignment:
22+
raise ValueError(f"Atom {atom.name} not found in assignment")
23+
return self._assignment[atom]
24+
25+
def __contains__(self, atom: Atom) -> bool:
26+
return atom in self._assignment
27+
28+
29+
class FormulaEvaluator:
30+
def __init__(self, formula: Formula, assignment: Assignment):
31+
self._formula = formula
32+
self._assignment = assignment
33+
34+
def evaluate(self) -> bool:
35+
return self._evaluate_formula(self._formula)
36+
37+
def _evaluate_formula(self, formula: Formula) -> bool:
38+
if isinstance(formula, Atom):
39+
return self._assignment.get(formula)
40+
if isinstance(formula, Truth):
41+
return True
42+
if isinstance(formula, Falsity):
43+
return False
44+
if isinstance(formula, Negation):
45+
return not self._evaluate_formula(formula.operand)
46+
if isinstance(formula, Conjunction):
47+
return self._evaluate_formula(formula.left) and self._evaluate_formula(formula.right)
48+
if isinstance(formula, Disjunction):
49+
return self._evaluate_formula(formula.left) or self._evaluate_formula(formula.right)
50+
if isinstance(formula, Implication):
51+
return not self._evaluate_formula(formula.left) or self._evaluate_formula(formula.right)
52+
if isinstance(formula, Biconditional):
53+
return self._evaluate_formula(formula.left) == self._evaluate_formula(formula.right)
54+
raise TypeError(f"Unknown formula type: {type(formula)}")
55+
56+
57+
def _extract_atoms(formula: Formula) -> Set[Atom]:
58+
atoms = set()
59+
60+
if isinstance(formula, Atom):
61+
atoms.add(formula)
62+
elif isinstance(formula, (Truth, Falsity)):
63+
pass
64+
elif isinstance(formula, Negation):
65+
atoms.update(_extract_atoms(formula.operand))
66+
elif isinstance(formula, (Conjunction, Disjunction, Implication, Biconditional)):
67+
atoms.update(_extract_atoms(formula.left))
68+
atoms.update(_extract_atoms(formula.right))
69+
70+
return atoms
71+
72+
73+
class EquivalenceEvaluator:
74+
def __init__(self, formula1: Formula, formula2: Formula):
75+
self._formula1 = formula1
76+
self._formula2 = formula2
77+
78+
def evaluate(self) -> bool:
79+
atoms1 = _extract_atoms(self._formula1)
80+
atoms2 = _extract_atoms(self._formula2)
81+
all_atoms = list(atoms1 | atoms2)
82+
83+
for assignment_values in product([False, True], repeat=len(all_atoms)):
84+
assignment_dict = {atom: val for atom, val in zip(all_atoms, assignment_values)}
85+
assignment = Assignment(assignment_dict)
86+
87+
evaluator1 = FormulaEvaluator(self._formula1, assignment)
88+
evaluator2 = FormulaEvaluator(self._formula2, assignment)
89+
90+
if evaluator1.evaluate() != evaluator2.evaluate():
91+
return False
92+
93+
return True
94+
95+
96+
class SatisfiabilityEvaluator:
97+
def __init__(self, formula: Formula):
98+
self._formula = formula
99+
100+
def evaluate(self) -> bool:
101+
atoms = _extract_atoms(self._formula)
102+
all_atoms = list(atoms)
103+
104+
for assignment_values in product([False, True], repeat=len(all_atoms)):
105+
assignment_dict = {atom: val for atom, val in zip(all_atoms, assignment_values)}
106+
assignment = Assignment(assignment_dict)
107+
108+
evaluator = FormulaEvaluator(self._formula, assignment)
109+
if evaluator.evaluate():
110+
return True
111+
112+
return False
113+
114+
115+
class TautologyEvaluator:
116+
def __init__(self, formula: Formula):
117+
self._formula = formula
118+
119+
def evaluate(self) -> bool:
120+
atoms = _extract_atoms(self._formula)
121+
all_atoms = list(atoms)
122+
123+
for assignment_values in product([False, True], repeat=len(all_atoms)):
124+
assignment_dict = {atom: val for atom, val in zip(all_atoms, assignment_values)}
125+
assignment = Assignment(assignment_dict)
126+
127+
evaluator = FormulaEvaluator(self._formula, assignment)
128+
if not evaluator.evaluate():
129+
return False
130+
131+
return True

0 commit comments

Comments
 (0)