Skip to content

Commit 5486fd1

Browse files
committed
Implemented parser to convert string into propositional logic.
Does not support brackets.
1 parent 32ce7d9 commit 5486fd1

3 files changed

Lines changed: 242 additions & 3 deletions

File tree

evaluation_function/evaluation.py

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,105 @@
11
from typing import Any
22
from lf_toolkit.evaluation import Result, Params
33

4+
from evaluation_function.propositional_logic.formula import *
5+
6+
7+
def parse_response(response: str) -> tuple[bool, Formula | str]:
8+
9+
response = response.strip()
10+
11+
# binaryOperators = ["↔","→","∨","∧"]
12+
# TODO: keep this mapping somewhere else for maintainability
13+
binaryOperators = {
14+
"↔" : Biconditional,
15+
"→" : Implication,
16+
"∨" : Disjunction,
17+
"∧" : Conjunction
18+
}
19+
20+
for binaryOperator in binaryOperators.keys():
21+
22+
if binaryOperator in response:
23+
split_index = response.rindex(binaryOperator)
24+
25+
left = response[:split_index]
26+
right = response[split_index+1:]
27+
28+
# check left and right not empty strings
29+
if not left:
30+
return (False, f"missing text on left of {binaryOperator}")
31+
elif not right:
32+
return (False, f"missing text on right of {binaryOperator}")
33+
34+
parse_left = parse_response(left)
35+
parse_right = parse_response(right)
36+
37+
error = False
38+
err_msgs = []
39+
40+
if not parse_left[0]:
41+
error = True
42+
err_msgs.append(parse_left[1])
43+
44+
if not parse_right[0]:
45+
error = True
46+
err_msgs.append(parse_right[1])
47+
48+
if error:
49+
return (False, err_msgs.join("\n"))
50+
51+
# both sides are find and valid
52+
result = binaryOperators[binaryOperator](parse_left[1], parse_right[1])
53+
return (True, result)
54+
55+
56+
# TODO: keep this mapping somewhere else for maintainability
57+
unaryOperators = {
58+
"¬" : Negation
59+
}
60+
61+
for unaryOperator in unaryOperators.keys():
62+
63+
#unary operator must syntactically be at the start of the string
64+
if response[0] == unaryOperator:
65+
66+
right = response[1:]
67+
#check not empty
68+
if not right:
69+
return (False, f"missing text on right of {unaryOperator}")
70+
71+
parse_right = parse_response(right)
72+
if not parse_right[0]:
73+
return parse_right
74+
75+
result = unaryOperators[unaryOperator](parse_right[1])
76+
return (True, result)
77+
78+
# check if the formual is just True or Falsity
79+
80+
singletons = { # not sure what the official term for these symbols is
81+
"⊤" : Truth,
82+
"⊥" : Falsity
83+
}
84+
85+
for singleton in singletons:
86+
87+
if len(response) > 1 and singleton in response:
88+
return (False, f"not allowed to use {singleton} in the atom identifier")
89+
90+
elif response == singleton:
91+
result = singletons[singleton]()
92+
return (True, result)
93+
94+
# response is likely an atom identifier
95+
96+
return (True, Atom(response))
97+
98+
99+
100+
101+
102+
4103
def evaluation_function(
5104
response: Any,
6105
answer: Any,
@@ -29,6 +128,27 @@ def evaluation_function(
29128
to output the evaluation response.
30129
"""
31130

32-
return Result(
33-
is_correct=response == answer
34-
)
131+
132+
if not isinstance(answer, str):
133+
raise Exception("Answer must be a string/text.")
134+
135+
136+
if not isinstance(response, str):
137+
return Result(
138+
is_correct=False,
139+
feedback="Please enter a string/text."
140+
)
141+
142+
143+
# this can be "equivilance", "tautology", "satisfiability"
144+
#potnetially can be switched with classes
145+
action = params.get("action", None)
146+
147+
feedback = None
148+
is_correct = False
149+
150+
pl_formula = parse_response(response)
151+
152+
#swtich on action
153+
154+
return Result(is_correct=False)

examples/basic_formula_parsing.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from evaluation_function.evaluation import parse_response
2+
3+
from evaluation_function.propositional_logic import (
4+
Atom,
5+
Truth,
6+
Falsity,
7+
Negation,
8+
Conjunction,
9+
Disjunction,
10+
Implication,
11+
Biconditional,
12+
Assignment,
13+
FormulaEvaluator,
14+
)
15+
16+
def main():
17+
p = Atom("p")
18+
q = Atom("q")
19+
20+
print("=== Basic Formula Parsing ===")
21+
print()
22+
23+
formulas = [
24+
("p", p),
25+
("q", q),
26+
("⊤", Truth()),
27+
("⊥", Falsity()),
28+
("¬p", Negation(p)),
29+
("p ∧ q", Conjunction(p, q)),
30+
("p ∨ q", Disjunction(p, q)),
31+
("p → q", Implication(p, q)),
32+
("p ↔ q", Biconditional(p, q)),
33+
]
34+
35+
passed = 0
36+
37+
for name, formula in formulas:
38+
result = None
39+
40+
try:
41+
result = parse_response(name)[1]
42+
except Exception as e:
43+
reslt = e
44+
45+
if formula != result:
46+
print()
47+
print("failed!!!!!!!!!!!!!!!!!!!!!!")
48+
print(f"formula: {name}")
49+
print(f"expected: {formula}")
50+
print(f"actual: {result}")
51+
else:
52+
print("passed")
53+
passed += 1
54+
55+
print()
56+
print("=== Result ===")
57+
print(f"{passed}/{len(formulas)}")
58+
59+
60+
if __name__ == "__main__":
61+
main()
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from evaluation_function.evaluation import parse_response
2+
3+
from evaluation_function.propositional_logic import (
4+
Atom,
5+
Truth,
6+
Falsity,
7+
Negation,
8+
Conjunction,
9+
Disjunction,
10+
Implication,
11+
Biconditional,
12+
Assignment,
13+
FormulaEvaluator,
14+
)
15+
16+
def main():
17+
p = Atom("p")
18+
q = Atom("q")
19+
20+
print("=== Complex Formula Parsing ===")
21+
print()
22+
23+
formulas = [
24+
("p ∧ q ∨ q", Disjunction(Conjunction(p, q), q)),
25+
# ("p ∨ q", Disjunction(p, q)),
26+
("p → p ∨ q", Implication(p, Disjunction(p, q))),
27+
("p ↔ p → p", Biconditional(p, Implication(p, p))),
28+
("p ↔ p ↔ p ↔ p", Biconditional(Biconditional(Biconditional(p, p), p), p)),
29+
("p ∧ q → ¬p ∨ q", Implication((Conjunction(p, q)), Disjunction(Negation(p), q)))
30+
]
31+
32+
passed = 0
33+
34+
for name, formula in formulas:
35+
result = None
36+
37+
try:
38+
result = parse_response(name)[1]
39+
except Exception as e:
40+
reslt = e
41+
42+
if formula != result:
43+
print()
44+
print("failed!!!!!!!!!!!!!!!!!!!!!!")
45+
print(f"formula: {name}")
46+
print(f"expected: {formula}")
47+
print(f"actual: {result}")
48+
else:
49+
print("passed")
50+
passed += 1
51+
52+
print()
53+
print("=== Result ===")
54+
print(f"{passed}/{len(formulas)}")
55+
56+
57+
if __name__ == "__main__":
58+
main()

0 commit comments

Comments
 (0)