mathai 0.2.8__py3-none-any.whl → 0.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mathai/logic.py CHANGED
@@ -1,224 +1,224 @@
1
- import itertools
2
- from .base import *
3
-
4
- def logic0(eq):
5
- if eq.children is None or len(eq.children)==0:
6
- return eq
7
- if eq.name in ["f_eq", "f_lt", "f_gt" "f_ge"] and eq.children[1].name[:2]=="d_" and eq.children[0].name[:2]=="d_":
8
- a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
9
- if eq.name == "f_eq":
10
- return tree_form("s_true") if a==b else tree_form("s_false")
11
- if eq.name == "f_ge":
12
- return tree_form("s_true") if a>=b else tree_form("s_false")
13
- if eq.name == "f_lt":
14
- return tree_form("s_true") if a < b else tree_form("s_false")
15
- if eq.name == "f_ge":
16
- return TreeNode("f_gt", eq.children) | TreeNode("f_eq", eq.children)
17
-
18
- if eq.name == "f_gt":
19
- return TreeNode("f_lt", eq.children).fx("not") & TreeNode("f_eq", eq.children).fx("not")
20
-
21
- if eq.name == "f_le":
22
- return TreeNode("f_lt", eq.children) | TreeNode("f_eq", eq.children)
23
- return TreeNode(eq.name, [logic0(child) for child in eq.children])
24
- def logic3(eq):
25
- if eq.name == "f_forall" and eq.children[1] in [tree_form("s_true"), tree_form("s_false")]:
26
- return eq.children[1]
27
- if eq.name == "f_not" and eq.children[0].name == "f_exist":
28
- return TreeNode("f_forall", [eq.children[0].children[0], eq.children[0].children[1].fx("not")])
29
- if eq.name == "f_exist" and eq.children[1].name == "f_or":
30
- return TreeNode("f_or", [TreeNode("f_exist", [eq.children[0], child]) for child in eq.children[1].children])
31
- if eq.name == "f_forall" and eq.children[1].name == "f_and":
32
- return TreeNode("f_and", [TreeNode("f_forall", [eq.children[0], child]) for child in eq.children[1].children])
33
- if eq.name == "f_exist":
34
- return TreeNode("f_forall", [eq.children[0], eq.children[1].fx("not")]).fx("not")
35
- return TreeNode(eq.name, [logic3(child) for child in eq.children])
36
- def logic2(eq):
37
- if eq.name in ["f_exist", "f_forall"]:
38
- return TreeNode(eq.name, [eq.children[0], logic2(eq.children[1])])
39
- if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
40
- return eq
41
- def convv(eq):
42
- if eq == tree_form("s_true"):
43
- return True
44
- if eq == tree_form("s_false"):
45
- return False
46
- return None
47
- def conv2(val):
48
- if val:
49
- return tree_form("s_true")
50
- return tree_form("s_false")
51
- if all(convv(child) is not None for child in eq.children):
52
- if eq.name == "f_not":
53
- return conv2(not convv(eq.children[0]))
54
- elif eq.name == "f_or":
55
- return conv2(convv(eq.children[0]) or convv(eq.children[1]))
56
- elif eq.name == "f_and":
57
- return conv2(convv(eq.children[0]) and convv(eq.children[1]))
58
- if eq == tree_form("s_false").fx("not"):
59
- return tree_form("s_true")
60
- if eq.name == "f_not":
61
- if eq.children[0].name == "f_not":
62
- return eq.children[0].children[0]
63
- elif eq.children[0].name in ["f_or", "f_and"]:
64
- out = TreeNode({"f_or":"f_and", "f_and":"f_or"}[eq.children[0].name], [])
65
- for child in eq.children[0].children:
66
- out.children.append(child.fx("not"))
67
- return out
68
- if eq.name in ["f_and", "f_or"]:
69
- for i in range(len(eq.children)):
70
- for j in range(len(eq.children)):
71
- if i ==j:
72
- continue
73
- if eq.children[i] == eq.children[j].fx("not"):
74
- eq2 = copy.deepcopy(eq)
75
- eq2.children.pop(max(i, j))
76
- eq2.children.pop(min(i, j))
77
- eq2.children.append({"f_or":tree_form("s_true"), "f_and":tree_form("s_false")}[eq.name])
78
- if len(eq2.children) == 1:
79
- return eq2.children[0]
80
- return eq2
81
- if eq.name in ["f_and", "f_or"]:
82
- for i in range(len(eq.children)):
83
- if eq.children[i] == tree_form("s_false"):
84
- eq2 = copy.deepcopy(eq)
85
- eq2.children.pop(i)
86
- if eq.name == "f_and":
87
- return tree_form("s_false")
88
- if len(eq2.children) == 1:
89
- return eq2.children[0]
90
- return eq2
91
- elif eq.children[i] == tree_form("s_true"):
92
- eq2 = copy.deepcopy(eq)
93
- eq2.children.pop(i)
94
- if eq.name == "f_or":
95
- return tree_form("s_true")
96
- if len(eq2.children) == 1:
97
- return eq2.children[0]
98
- return eq2
99
- if eq.name in ["f_and", "f_or"]:
100
- lst = remove_duplicates_custom(eq.children, lambda x,y: x==y)
101
- if len(lst) < len(eq.children):
102
- if len(lst) == 1:
103
- return lst[0]
104
- return TreeNode(eq.name, lst)
105
-
106
- if eq.name in ["f_and", "f_or"] and any(child.children is not None and len(child.children)!=0 for child in eq.children):
107
- for i in range(len(eq.children),1,-1):
108
- for item in itertools.combinations(enumerate(eq.children), i):
109
- op = "f_and"
110
- if eq.name == "f_and":
111
- op = "f_or"
112
- item3 = []
113
- for item4 in item:
114
- item3.append(item4[0])
115
- item5 = []
116
- for item4 in item:
117
- item5.append(item4[1])
118
- item = item5
119
- out = None
120
- for j in range(len(item)):
121
- out = set(item[j].children)
122
- for item2 in item:
123
- if item2.name == op:
124
- out = out & set(item2.children)
125
- else:
126
- out = out & set([item2])
127
- if out == set(item[j].children):
128
- break
129
- out = None
130
- if out is None:
131
- continue
132
- out = list(out)
133
- if out == []:
134
- continue
135
- if len(out) != 1:
136
- out = [TreeNode(op, out)]
137
- for item4 in list(set(range(len(eq.children))) - set(item3)):
138
- out.append(eq.children[item4])
139
- if len(out) == 1:
140
- return out[0]
141
- output = flatten_tree(TreeNode(eq.name, out))
142
- return output
143
- return TreeNode(eq.name, [flatten_tree(logic2(child)) for child in eq.children])
144
- def logic1(eq):
145
- def helper(eq):
146
- if eq.name in ["f_exist", "f_forall"]:
147
- return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
148
- if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
149
- return eq
150
- if eq.name == "f_equiv":
151
- A, B = eq.children
152
- A, B = logic1(A), logic1(B)
153
- A, B = dowhile(A, logic2), dowhile(B, logic2)
154
- return flatten_tree((A & B) | (A.fx("not") & B.fx("not")))
155
- if eq.name == "f_imply":
156
-
157
- A, B = eq.children
158
- A, B = logic1(A), logic1(B)
159
- A, B = dowhile(A, logic2), dowhile(B, logic2)
160
- return flatten_tree(A.fx("not") | B)
161
- return TreeNode(eq.name, [helper(child) for child in eq.children])
162
- if eq.name in ["f_exist", "f_forall"]:
163
- return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
164
- if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
165
- return eq
166
- eq = helper(eq)
167
- eq = flatten_tree(eq)
168
-
169
- if len(eq.children) > 2:
170
- lst = []
171
- l = len(eq.children)
172
-
173
- # Handle last odd child directly
174
- if l % 2 == 1:
175
- last_child = eq.children[-1]
176
- # expand/simplify only if needed
177
- if isinstance(last_child, TreeNode):
178
- last_child = dowhile(last_child, logic2)
179
- lst.append(last_child)
180
- l -= 1
181
-
182
- # Pairwise combine children
183
- for i in range(0, l, 2):
184
- left, right = eq.children[i], eq.children[i+1]
185
- pair = TreeNode(eq.name, [left, right])
186
- simplified = dowhile(logic1(pair), logic2)
187
- lst.append(simplified)
188
-
189
- # If only one element left, just return it instead of nesting
190
- if len(lst) == 1:
191
- return flatten_tree(lst[0])
192
-
193
- # Otherwise rewrap
194
- return flatten_tree(TreeNode(eq.name, lst))
195
-
196
- if eq.name == "f_and":
197
- lst= []
198
- for child in eq.children:
199
- if child.name == "f_or":
200
- lst.append(child.children)
201
- else:
202
- lst.append([child])
203
- out = TreeNode("f_or", [])
204
- for item in itertools.product(*lst):
205
- c = TreeNode("f_and", list(item))
206
- out.children.append(c)
207
- if len(out.children) == 1:
208
- out = out.children[0]
209
- return flatten_tree(out)
210
- elif eq.name == "f_or":
211
- lst= []
212
- for child in eq.children:
213
- if child.name == "f_and":
214
- lst.append(child.children)
215
- else:
216
- lst.append([child])
217
- out = TreeNode("f_and", [])
218
- for item in itertools.product(*lst):
219
- c = TreeNode("f_or", list(item))
220
- out.children.append(c)
221
- if len(out.children) == 1:
222
- out = out.children[0]
223
- return flatten_tree(out)
224
- return TreeNode(eq.name, [logic1(child) for child in eq.children])
1
+ import itertools
2
+ from .base import *
3
+
4
+ def logic0(eq):
5
+ if eq.children is None or len(eq.children)==0:
6
+ return eq
7
+ if eq.name in ["f_eq", "f_lt", "f_gt" "f_ge"] and eq.children[1].name[:2]=="d_" and eq.children[0].name[:2]=="d_":
8
+ a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
9
+ if eq.name == "f_eq":
10
+ return tree_form("s_true") if a==b else tree_form("s_false")
11
+ if eq.name == "f_ge":
12
+ return tree_form("s_true") if a>=b else tree_form("s_false")
13
+ if eq.name == "f_lt":
14
+ return tree_form("s_true") if a < b else tree_form("s_false")
15
+ if eq.name == "f_ge":
16
+ return TreeNode("f_gt", eq.children) | TreeNode("f_eq", eq.children)
17
+
18
+ if eq.name == "f_gt":
19
+ return TreeNode("f_lt", eq.children).fx("not") & TreeNode("f_eq", eq.children).fx("not")
20
+
21
+ if eq.name == "f_le":
22
+ return TreeNode("f_lt", eq.children) | TreeNode("f_eq", eq.children)
23
+ return TreeNode(eq.name, [logic0(child) for child in eq.children])
24
+ def logic3(eq):
25
+ if eq.name == "f_forall" and eq.children[1] in [tree_form("s_true"), tree_form("s_false")]:
26
+ return eq.children[1]
27
+ if eq.name == "f_not" and eq.children[0].name == "f_exist":
28
+ return TreeNode("f_forall", [eq.children[0].children[0], eq.children[0].children[1].fx("not")])
29
+ if eq.name == "f_exist" and eq.children[1].name == "f_or":
30
+ return TreeNode("f_or", [TreeNode("f_exist", [eq.children[0], child]) for child in eq.children[1].children])
31
+ if eq.name == "f_forall" and eq.children[1].name == "f_and":
32
+ return TreeNode("f_and", [TreeNode("f_forall", [eq.children[0], child]) for child in eq.children[1].children])
33
+ if eq.name == "f_exist":
34
+ return TreeNode("f_forall", [eq.children[0], eq.children[1].fx("not")]).fx("not")
35
+ return TreeNode(eq.name, [logic3(child) for child in eq.children])
36
+ def logic2(eq):
37
+ if eq.name in ["f_exist", "f_forall"]:
38
+ return TreeNode(eq.name, [eq.children[0], logic2(eq.children[1])])
39
+ if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
40
+ return eq
41
+ def convv(eq):
42
+ if eq == tree_form("s_true"):
43
+ return True
44
+ if eq == tree_form("s_false"):
45
+ return False
46
+ return None
47
+ def conv2(val):
48
+ if val:
49
+ return tree_form("s_true")
50
+ return tree_form("s_false")
51
+ if all(convv(child) is not None for child in eq.children):
52
+ if eq.name == "f_not":
53
+ return conv2(not convv(eq.children[0]))
54
+ elif eq.name == "f_or":
55
+ return conv2(convv(eq.children[0]) or convv(eq.children[1]))
56
+ elif eq.name == "f_and":
57
+ return conv2(convv(eq.children[0]) and convv(eq.children[1]))
58
+ if eq == tree_form("s_false").fx("not"):
59
+ return tree_form("s_true")
60
+ if eq.name == "f_not":
61
+ if eq.children[0].name == "f_not":
62
+ return eq.children[0].children[0]
63
+ elif eq.children[0].name in ["f_or", "f_and"]:
64
+ out = TreeNode({"f_or":"f_and", "f_and":"f_or"}[eq.children[0].name], [])
65
+ for child in eq.children[0].children:
66
+ out.children.append(child.fx("not"))
67
+ return out
68
+ if eq.name in ["f_and", "f_or"]:
69
+ for i in range(len(eq.children)):
70
+ for j in range(len(eq.children)):
71
+ if i ==j:
72
+ continue
73
+ if eq.children[i] == eq.children[j].fx("not"):
74
+ eq2 = copy.deepcopy(eq)
75
+ eq2.children.pop(max(i, j))
76
+ eq2.children.pop(min(i, j))
77
+ eq2.children.append({"f_or":tree_form("s_true"), "f_and":tree_form("s_false")}[eq.name])
78
+ if len(eq2.children) == 1:
79
+ return eq2.children[0]
80
+ return eq2
81
+ if eq.name in ["f_and", "f_or"]:
82
+ for i in range(len(eq.children)):
83
+ if eq.children[i] == tree_form("s_false"):
84
+ eq2 = copy.deepcopy(eq)
85
+ eq2.children.pop(i)
86
+ if eq.name == "f_and":
87
+ return tree_form("s_false")
88
+ if len(eq2.children) == 1:
89
+ return eq2.children[0]
90
+ return eq2
91
+ elif eq.children[i] == tree_form("s_true"):
92
+ eq2 = copy.deepcopy(eq)
93
+ eq2.children.pop(i)
94
+ if eq.name == "f_or":
95
+ return tree_form("s_true")
96
+ if len(eq2.children) == 1:
97
+ return eq2.children[0]
98
+ return eq2
99
+ if eq.name in ["f_and", "f_or"]:
100
+ lst = remove_duplicates_custom(eq.children, lambda x,y: x==y)
101
+ if len(lst) < len(eq.children):
102
+ if len(lst) == 1:
103
+ return lst[0]
104
+ return TreeNode(eq.name, lst)
105
+
106
+ if eq.name in ["f_and", "f_or"] and any(child.children is not None and len(child.children)!=0 for child in eq.children):
107
+ for i in range(len(eq.children),1,-1):
108
+ for item in itertools.combinations(enumerate(eq.children), i):
109
+ op = "f_and"
110
+ if eq.name == "f_and":
111
+ op = "f_or"
112
+ item3 = []
113
+ for item4 in item:
114
+ item3.append(item4[0])
115
+ item5 = []
116
+ for item4 in item:
117
+ item5.append(item4[1])
118
+ item = item5
119
+ out = None
120
+ for j in range(len(item)):
121
+ out = set(item[j].children)
122
+ for item2 in item:
123
+ if item2.name == op:
124
+ out = out & set(item2.children)
125
+ else:
126
+ out = out & set([item2])
127
+ if out == set(item[j].children):
128
+ break
129
+ out = None
130
+ if out is None:
131
+ continue
132
+ out = list(out)
133
+ if out == []:
134
+ continue
135
+ if len(out) != 1:
136
+ out = [TreeNode(op, out)]
137
+ for item4 in list(set(range(len(eq.children))) - set(item3)):
138
+ out.append(eq.children[item4])
139
+ if len(out) == 1:
140
+ return out[0]
141
+ output = flatten_tree(TreeNode(eq.name, out))
142
+ return output
143
+ return TreeNode(eq.name, [flatten_tree(logic2(child)) for child in eq.children])
144
+ def logic1(eq):
145
+ def helper(eq):
146
+ if eq.name in ["f_exist", "f_forall"]:
147
+ return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
148
+ if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
149
+ return eq
150
+ if eq.name == "f_equiv":
151
+ A, B = eq.children
152
+ A, B = logic1(A), logic1(B)
153
+ A, B = dowhile(A, logic2), dowhile(B, logic2)
154
+ return flatten_tree((A & B) | (A.fx("not") & B.fx("not")))
155
+ if eq.name == "f_imply":
156
+
157
+ A, B = eq.children
158
+ A, B = logic1(A), logic1(B)
159
+ A, B = dowhile(A, logic2), dowhile(B, logic2)
160
+ return flatten_tree(A.fx("not") | B)
161
+ return TreeNode(eq.name, [helper(child) for child in eq.children])
162
+ if eq.name in ["f_exist", "f_forall"]:
163
+ return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
164
+ if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
165
+ return eq
166
+ eq = helper(eq)
167
+ eq = flatten_tree(eq)
168
+
169
+ if len(eq.children) > 2:
170
+ lst = []
171
+ l = len(eq.children)
172
+
173
+ # Handle last odd child directly
174
+ if l % 2 == 1:
175
+ last_child = eq.children[-1]
176
+ # expand/simplify only if needed
177
+ if isinstance(last_child, TreeNode):
178
+ last_child = dowhile(last_child, logic2)
179
+ lst.append(last_child)
180
+ l -= 1
181
+
182
+ # Pairwise combine children
183
+ for i in range(0, l, 2):
184
+ left, right = eq.children[i], eq.children[i+1]
185
+ pair = TreeNode(eq.name, [left, right])
186
+ simplified = dowhile(logic1(pair), logic2)
187
+ lst.append(simplified)
188
+
189
+ # If only one element left, just return it instead of nesting
190
+ if len(lst) == 1:
191
+ return flatten_tree(lst[0])
192
+
193
+ # Otherwise rewrap
194
+ return flatten_tree(TreeNode(eq.name, lst))
195
+
196
+ if eq.name == "f_and":
197
+ lst= []
198
+ for child in eq.children:
199
+ if child.name == "f_or":
200
+ lst.append(child.children)
201
+ else:
202
+ lst.append([child])
203
+ out = TreeNode("f_or", [])
204
+ for item in itertools.product(*lst):
205
+ c = TreeNode("f_and", list(item))
206
+ out.children.append(c)
207
+ if len(out.children) == 1:
208
+ out = out.children[0]
209
+ return flatten_tree(out)
210
+ elif eq.name == "f_or":
211
+ lst= []
212
+ for child in eq.children:
213
+ if child.name == "f_and":
214
+ lst.append(child.children)
215
+ else:
216
+ lst.append([child])
217
+ out = TreeNode("f_and", [])
218
+ for item in itertools.product(*lst):
219
+ c = TreeNode("f_or", list(item))
220
+ out.children.append(c)
221
+ if len(out.children) == 1:
222
+ out = out.children[0]
223
+ return flatten_tree(out)
224
+ return TreeNode(eq.name, [logic1(child) for child in eq.children])