-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse_formula.py
127 lines (108 loc) · 4.4 KB
/
parse_formula.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import re
def parse_formula(formula):
formula = formula.replace(" ", "")
# Atomic propositions
proposition = r"^(\w)$"
match = re.match(proposition, formula)
if match is not None:
p = match.group(1)
return [p]
negation = r"^~\((.+)\)$|^~(\w)$"
match = re.match(negation, formula)
if match is not None:
sub = match.group(1) if match.group(1) is not None else match.group(2)
return ["~", parse_formula(sub)]
# Knowledge operator
knowledge = r"^K_(\w+)\((.+)\)$|^K_(\w+)([a-z])$"
match = re.match(knowledge, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["K", agent, parse_formula(sub)]
# Belief operator
belief = r"^B_(\w+)\((.+)\)$|^B_(\w+)([a-z])$"
match = re.match(belief, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["B", agent, parse_formula(sub)]
# Safe belief operator
safebelief = r"^S_(\w+)\((.+)\)$|^S_(\w+)([a-z])$"
match = re.match(safebelief, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["S", agent, parse_formula(sub)]
# Weakly safe belief operator
weaklysafebelief = r"^W_(\w+)\((.+)\)$|^W_(\w+)([a-z])$"
match = re.match(weaklysafebelief, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["T", agent, parse_formula(sub)]
# Strong belief operator
strongbelief = r"^T_(\w+)\((.+)\)$|^T_(\w+)([a-z])$"
match = re.match(strongbelief, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["T", agent, parse_formula(sub)]
# Ignorance operator
ignorance = r"^I_(\w+)\((.+)\)$|^I_(\w+)([a-z])$"
match = re.match(ignorance, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["I", agent, parse_formula(sub)]
# Doubt operator
doubt = r"^D_(\w+)\((.+)\)$|^D_(\w+)([a-z])$"
match = re.match(doubt, formula)
if match is not None:
agent = match.group(1) if match.group(1) is not None else match.group(3)
sub = match.group(2) if match.group(2) is not None else match.group(4)
return ["D", agent, parse_formula(sub)]
# Binary operators
subs, op = get_multi_subformulas(formula)
parsed = [parse_formula(sub) for sub in subs]
return [op] + parsed
def get_multi_subformulas(formula):
# Identify operators
n_parens = 0
operators = ["\\/", "/\\", "=>"]
op_pos = []
ops = []
for idx in range(len(formula)):
if formula[idx] == r"(":
n_parens += 1
continue
if formula[idx] == r")":
n_parens -= 1
continue
if formula[idx] == "!" and n_parens == 0:
op_pos.append(idx)
ops.append(formula[idx])
if formula[idx:idx+2] in operators and n_parens == 0:
op_pos.append(idx)
ops.append(formula[idx:idx+2])
# Check that there is just one operator type
if len(set(ops)) > 1:
raise "Cannot mix operators"
op = ops[0]
# Identify subformulas
n_subs = len(op_pos)
idxs = []
idxs.append((0, op_pos[0]))
idxs += [(op_pos[i]+len(op), op_pos[i+1]) for i in range(n_subs-1)]
idxs.append((op_pos[n_subs-1]+len(op), len(formula)))
phis = [formula[i:j] for (i,j) in idxs]
# Check that numbers of subformulas are valid
if (op == "=>" or op == "!") and len(phis) > 2:
raise "Cannot have more than 2 subformulas for operator"
# Remove outermost parentheses
for i,phi in enumerate(phis):
if phi[0] == "(":
phi = phi[1:]
if phi[-1] == ")":
phi = phi[:-1]
phis[i] = phi
return phis, op