mathai 0.4.8__tar.gz → 0.5.0__tar.gz

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.
Files changed (32) hide show
  1. {mathai-0.4.8 → mathai-0.5.0}/PKG-INFO +1 -1
  2. {mathai-0.4.8 → mathai-0.5.0}/mathai/__init__.py +2 -3
  3. mathai-0.5.0/mathai/bivariate_inequality.py +296 -0
  4. mathai-0.5.0/mathai/linear.py +157 -0
  5. {mathai-0.4.8 → mathai-0.5.0}/mathai.egg-info/PKG-INFO +1 -1
  6. {mathai-0.4.8 → mathai-0.5.0}/mathai.egg-info/SOURCES.txt +1 -0
  7. {mathai-0.4.8 → mathai-0.5.0}/setup.py +1 -1
  8. mathai-0.4.8/mathai/linear.py +0 -156
  9. {mathai-0.4.8 → mathai-0.5.0}/README.md +0 -0
  10. {mathai-0.4.8 → mathai-0.5.0}/mathai/apart.py +0 -0
  11. {mathai-0.4.8 → mathai-0.5.0}/mathai/base.py +0 -0
  12. {mathai-0.4.8 → mathai-0.5.0}/mathai/console.py +0 -0
  13. {mathai-0.4.8 → mathai-0.5.0}/mathai/diff.py +0 -0
  14. {mathai-0.4.8 → mathai-0.5.0}/mathai/expand.py +0 -0
  15. {mathai-0.4.8 → mathai-0.5.0}/mathai/factor.py +0 -0
  16. {mathai-0.4.8 → mathai-0.5.0}/mathai/fraction.py +0 -0
  17. {mathai-0.4.8 → mathai-0.5.0}/mathai/integrate.py +0 -0
  18. {mathai-0.4.8 → mathai-0.5.0}/mathai/inverse.py +0 -0
  19. {mathai-0.4.8 → mathai-0.5.0}/mathai/limit.py +0 -0
  20. {mathai-0.4.8 → mathai-0.5.0}/mathai/logic.py +0 -0
  21. {mathai-0.4.8 → mathai-0.5.0}/mathai/ode.py +0 -0
  22. {mathai-0.4.8 → mathai-0.5.0}/mathai/parser.py +0 -0
  23. {mathai-0.4.8 → mathai-0.5.0}/mathai/printeq.py +0 -0
  24. {mathai-0.4.8 → mathai-0.5.0}/mathai/simplify.py +0 -0
  25. {mathai-0.4.8 → mathai-0.5.0}/mathai/structure.py +0 -0
  26. {mathai-0.4.8 → mathai-0.5.0}/mathai/tool.py +0 -0
  27. {mathai-0.4.8 → mathai-0.5.0}/mathai/trig.py +0 -0
  28. {mathai-0.4.8 → mathai-0.5.0}/mathai/univariate_inequality.py +0 -0
  29. {mathai-0.4.8 → mathai-0.5.0}/mathai.egg-info/dependency_links.txt +0 -0
  30. {mathai-0.4.8 → mathai-0.5.0}/mathai.egg-info/requires.txt +0 -0
  31. {mathai-0.4.8 → mathai-0.5.0}/mathai.egg-info/top_level.txt +0 -0
  32. {mathai-0.4.8 → mathai-0.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.4.8
3
+ Version: 0.5.0
4
4
  Summary: Mathematics solving Ai tailored to NCERT
5
5
  Home-page: https://github.com/infinity390/mathai4
6
6
  Author: educated indians are having a low iq and are good for nothing
@@ -1,7 +1,7 @@
1
1
  from .ode import diffsolve as ode_solve
2
2
  from .ode import diffsolve_sep as ode_shift_term
3
3
 
4
- from .linear import linear_solve
4
+ from .linear import linear_solve, linear_or
5
5
 
6
6
  from .expand import expand
7
7
 
@@ -39,11 +39,10 @@ from .logic import logic0, logic1, logic2, logic3
39
39
 
40
40
  from .apart import apart, apart2
41
41
 
42
- from .console import console
43
-
44
42
  from .limit import limit
45
43
 
46
44
  from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt
45
+ from .bivariate_inequality import inequality_solve
47
46
 
48
47
  from .base import *
49
48
 
@@ -0,0 +1,296 @@
1
+ import math
2
+ from .linear import linear_or
3
+ from functools import reduce
4
+ import operator
5
+ from .base import *
6
+ from .simplify import simplify
7
+ def shoelace_area(vertices):
8
+ n = len(vertices)
9
+ area = 0.0
10
+ for i in range(n):
11
+ j = (i + 1) % n
12
+ area += vertices[i][0] * vertices[j][1]
13
+ area -= vertices[j][0] * vertices[i][1]
14
+ return abs(area) / 2.0
15
+
16
+ def triangle_area(p1, p2, p3):
17
+ area = 0.0
18
+ area += p1[0] * (p2[1] - p3[1])
19
+ area += p2[0] * (p3[1] - p1[1])
20
+ area += p3[0] * (p1[1] - p2[1])
21
+ return abs(area) / 2.0
22
+
23
+ def is_point_inside_polygon(point, vertices):
24
+ if len(vertices) < 3:
25
+ return False
26
+
27
+ polygon_area = shoelace_area(vertices)
28
+
29
+ total_triangle_area = 0.0
30
+ n = len(vertices)
31
+ for i in range(n):
32
+ j = (i + 1) % n
33
+ total_triangle_area += triangle_area(point, vertices[i], vertices[j])
34
+
35
+ tolerance = 1e-5
36
+ return abs(total_triangle_area - polygon_area) < tolerance
37
+
38
+ def distance_point_to_segment(px, py, x1, y1, x2, y2):
39
+ dx, dy = x2 - x1, y2 - y1
40
+ if dx == dy == 0:
41
+ return ((px - x1)**2 + (py - y1)**2)**0.5
42
+ t = max(0, min(1, ((px - x1) * dx + (py - y1) * dy) / (dx*dx + dy*dy)))
43
+ proj_x = x1 + t * dx
44
+ proj_y = y1 + t * dy
45
+ return ((px - proj_x)**2 + (py - proj_y)**2)**0.5
46
+
47
+ def deterministic_middle_point(vertices, grid_resolution=100):
48
+ xs = [v[0] for v in vertices]
49
+ ys = [v[1] for v in vertices]
50
+ xmin, xmax = min(xs), max(xs)
51
+ ymin, ymax = min(ys), max(ys)
52
+
53
+ best_point = None
54
+ max_dist = -1
55
+
56
+ for i in range(grid_resolution + 1):
57
+ for j in range(grid_resolution + 1):
58
+ px = xmin + (xmax - xmin) * i / grid_resolution
59
+ py = ymin + (ymax - ymin) * j / grid_resolution
60
+ if not is_point_inside_polygon((px, py), vertices):
61
+ continue
62
+ min_edge_dist = float('inf')
63
+ n = len(vertices)
64
+ for k in range(n):
65
+ x1, y1 = vertices[k]
66
+ x2, y2 = vertices[(k + 1) % n]
67
+ d = distance_point_to_segment(px, py, x1, y1, x2, y2)
68
+ min_edge_dist = min(min_edge_dist, d)
69
+ if min_edge_dist > max_dist:
70
+ max_dist = min_edge_dist
71
+ best_point = (px, py)
72
+
73
+ return best_point
74
+
75
+ def build(eq):
76
+ if len(eq) <= 1:
77
+ return None
78
+ eq = TreeNode("f_or", eq)
79
+ eq = flatten_tree(eq)
80
+ orig = eq.copy_tree()
81
+ def fxhelper3(eq):
82
+ if eq.name[2:] in "le ge lt gt".split(" "):
83
+ return TreeNode("f_eq", [child.copy_tree() for child in eq.children])
84
+ return TreeNode(eq.name, [fxhelper3(child) for child in eq.children])
85
+ eq = fxhelper3(eq)
86
+
87
+ result = linear_or(eq)
88
+ maxnum = tree_form("d_2")
89
+ if len(result[1]) != 0:
90
+ maxnum = max([max([simplify(item2.fx("abs")) for item2 in item], key=lambda x: compute(x)) for item in result[1]], key=lambda x: compute(x))
91
+ maxnum += 1
92
+ maxnum = simplify(maxnum)
93
+ eq = flatten_tree(eq | simplify(TreeNode("f_or", [TreeNode("f_eq", [tree_form(item)+maxnum, tree_form("d_0")])|\
94
+ TreeNode("f_eq", [tree_form(item)-maxnum, tree_form("d_0")]) for item in vlist(eq)])))
95
+ result2 = linear_or(eq)
96
+
97
+ point_lst = result2[2]
98
+
99
+ def gen(point):
100
+ nonlocal point_lst
101
+ out = []
102
+ for item in point_lst:
103
+ p = None
104
+ if point in item:
105
+ p = item.index(point)
106
+ else:
107
+ continue
108
+ if p < len(item)-1:
109
+ out.append(item[p+1])
110
+ if p > 0:
111
+ out.append(item[p-1])
112
+ return list(set(out))
113
+ start = list(range(len(result2[1])))
114
+ graph= {}
115
+ for item in start:
116
+ graph[item] = gen(item)
117
+
118
+ points = {}
119
+ for index, item in enumerate(result2[1]):
120
+ points[index] = [compute(item2) for item2 in item]
121
+
122
+ res = []
123
+ for index, item in enumerate(result2[1]):
124
+ if any(simplify(item2.fx("abs")-maxnum)!=0 and abs(compute(item2))>compute(maxnum) for item2 in item):
125
+ res.append(index)
126
+
127
+ graph = {k: sorted(v) for k, v in graph.items()}
128
+
129
+ def dfs(current, parent, path, visited, cycles):
130
+ path.append(current)
131
+ visited.add(current)
132
+ for neighbor in graph[current]:
133
+ if neighbor == parent:
134
+ continue
135
+ if neighbor in visited:
136
+ idx = path.index(neighbor)
137
+ cycle = path[idx:]
138
+ cycles.append(cycle)
139
+ else:
140
+ dfs(neighbor, current, path, visited, cycles)
141
+ path.pop()
142
+ visited.remove(current)
143
+
144
+ cycles = []
145
+ for start in sorted(graph.keys()):
146
+ path = []
147
+ visited = set()
148
+ dfs(start, -1, path, visited, cycles)
149
+
150
+ def normalize(cycle):
151
+ k = len(cycle)
152
+ if k < 3:
153
+ return None
154
+ candidates = []
155
+ for direction in [cycle, list(reversed(cycle))]:
156
+ doubled = direction + direction[:-1]
157
+ for i in range(k):
158
+ rot = tuple(doubled[i:i + k])
159
+ candidates.append(rot)
160
+ return min(candidates)
161
+
162
+ unique = set()
163
+ for c in cycles:
164
+ norm = normalize(c)
165
+ if norm:
166
+ unique.add(norm)
167
+
168
+ cycles = sorted(list(unique), key=lambda x: (len(x), x))
169
+
170
+ start = list(range(len(result2[1])))
171
+ for i in range(len(cycles)-1,-1,-1):
172
+ if any(item in cycles[i] for item in res) or\
173
+ any(is_point_inside_polygon([compute(item2) for item2 in list(result2[1][p])], [[compute(item2) for item2 in result2[1][item]] for item in cycles[i]]) for p in list(set(start) - set(cycles[i]))) or\
174
+ any(len(set(graph[item]) & set(cycles[i]))>2 for item in cycles[i]):
175
+ cycles.pop(i)
176
+
177
+ point_lst = [index for index, item in enumerate(result2[1]) if item in result[1]]
178
+ border = []
179
+ for item in start:
180
+ for item2 in graph[item]:
181
+ a = result2[1][item]
182
+ b = result2[1][item2]
183
+
184
+ if a[0] == b[0] and simplify(a[0].fx("abs") - maxnum) == 0:
185
+ continue
186
+ if a[1] == b[1] and simplify(a[1].fx("abs") - maxnum) == 0:
187
+ continue
188
+ border.append(tuple(sorted([item, item2])))
189
+ line = []
190
+ for key in graph.keys():
191
+ for item in list(set(point_lst)&set(graph[key])):
192
+ line.append(tuple(sorted([item, key])))
193
+ line = list(set(line+border))
194
+ point_in = [deterministic_middle_point([[compute(item3) for item3 in result2[1][item2]] for item2 in item]) for item in cycles]
195
+ def work(eq, point):
196
+ if "f_eq" in str_form(eq):
197
+ return False
198
+ nonlocal result2
199
+ if eq.name[:2] == "d_":
200
+ return float(eq.name[2:])
201
+ if eq.name in result2[0]:
202
+ return point[result2[0].index(eq.name)]
203
+ if eq.name == "f_add":
204
+ return sum(work(item, point) for item in eq.children)
205
+ if eq.name == "f_mul":
206
+ return math.prod(work(item, point) for item in eq.children)
207
+ return {"gt":lambda a,b: a>b, "lt":lambda a,b: a<b}[eq.name[2:]](work(eq.children[0], point), work(eq.children[1], point))
208
+
209
+ data = []
210
+ for index, item in enumerate(result2[2][:-4]):
211
+ a = tuple(set(item) & set(point_lst))
212
+ b = tuple(set([tuple(sorted([item[i], item[i+1]])) for i in range(len(item)-1)]) & set(line))
213
+ c = tuple([tuple(item) for index2, item in enumerate(cycles) if work(orig.children[index], point_in[index2])])
214
+ data.append((a,b,c))
215
+
216
+ total = tuple([tuple(point_lst), tuple(line), tuple(cycles)])
217
+ final = {}
218
+ for index, item in enumerate(orig.children):
219
+ final[item] = tuple(data[index])
220
+ return final, total, result2[1]
221
+
222
+ def inequality_solve(eq):
223
+ element = []
224
+ def helper(eq):
225
+ nonlocal element
226
+ if eq.name[2:] in "le ge lt gt eq".split(" ") and "v_" in str_form(eq):
227
+ element.append(eq)
228
+ return TreeNode(eq.name, [helper(child) for child in eq.children])
229
+ helper(eq)
230
+
231
+ out = build(list(set(element)))
232
+
233
+ if out is None:
234
+ return eq
235
+
236
+ def helper2(eq):
237
+ nonlocal out
238
+ if eq == tree_form("s_true"):
239
+ return [set(item) for item in out[1]]
240
+ if eq == tree_form("s_false"):
241
+ return [set(), set(), set()]
242
+ if eq in out[0].keys():
243
+ return [set(item) for item in out[0][eq]]
244
+ if eq.name == "f_or":
245
+ result = [helper2(child) for child in eq.children]
246
+ a = []
247
+ b = []
248
+ c = []
249
+ for item in result:
250
+ a += [item[0]]
251
+ b += [item[1]]
252
+ c += [item[2]]
253
+ x = a[0]
254
+ for item in a[1:]:
255
+ x |= item
256
+ y = b[0]
257
+ for item in b[1:]:
258
+ y |= item
259
+ z = c[0]
260
+ for item in c[1:]:
261
+ z |= item
262
+ return [x, y, z]
263
+ if eq.name == "f_and":
264
+ result = [helper2(child) for child in eq.children]
265
+ a = []
266
+ b = []
267
+ c = []
268
+ for item in result:
269
+ a += [item[0]]
270
+ b += [item[1]]
271
+ c += [item[2]]
272
+ x = a[0]
273
+ for item in a[1:]:
274
+ x &= item
275
+ y = b[0]
276
+ for item in b[1:]:
277
+ y &= item
278
+ z = c[0]
279
+ for item in c[1:]:
280
+ z &= item
281
+ return [x, y, z]
282
+ if eq.name == "f_not":
283
+ eq2 = helper2(eq.children[0])
284
+ a,b,c= eq2
285
+ d,e,f= [set(item) for item in out[1]]
286
+ return [d-a,e-b,f-c]
287
+ out2 = helper2(eq)
288
+
289
+ out = list(out)
290
+ out[1] = [set(item) for item in out[1]]
291
+
292
+ if tuple(out[1]) == tuple(out2):
293
+ return tree_form("s_true")
294
+ if tuple(out2) == (set(), set(), set()):
295
+ return tree_form("s_false")
296
+ return eq
@@ -0,0 +1,157 @@
1
+ from .inverse import inverse
2
+ import itertools
3
+ from .diff import diff
4
+ from .simplify import simplify, solve
5
+ from .fraction import fraction
6
+ from .expand import expand
7
+ from .base import *
8
+ from .factor import factorconst
9
+ def ss(eq):
10
+ return dowhile(eq, lambda x: fraction(expand(simplify(x))))
11
+ def rref(matrix):
12
+ rows, cols = len(matrix), len(matrix[0])
13
+ lead = 0
14
+ for r in range(rows):
15
+ if lead >= cols:
16
+ return matrix
17
+ i = r
18
+ while ss(matrix[i][lead]) == tree_form("d_0"):
19
+ i += 1
20
+ if i == rows:
21
+ i = r
22
+ lead += 1
23
+ if lead == cols:
24
+ return matrix
25
+ matrix[i], matrix[r] = matrix[r], matrix[i]
26
+ lv = matrix[r][lead]
27
+ matrix[r] = [ss(m / lv) for m in matrix[r]]
28
+ for i in range(rows):
29
+ if i != r:
30
+ lv = matrix[i][lead]
31
+ matrix[i] = [ss(m - lv * n) for m, n in zip(matrix[i], matrix[r])]
32
+ lead += 1
33
+ return matrix
34
+ def islinear(eq, fxconst):
35
+ eq =simplify(eq)
36
+ if eq.name == "f_pow" and fxconst(eq):#"v_" in str_form(eq):
37
+ return False
38
+ for child in eq.children:
39
+ out = islinear(child, fxconst)
40
+ if not out:
41
+ return out
42
+ return True
43
+ def linear(eqlist, fxconst):
44
+ eqlist = [eq for eq in eqlist if fxconst(eq)]
45
+ if not all(islinear(eq, fxconst) for eq in eqlist):
46
+ return TreeNode("f_and", copy.deepcopy(eqlist))
47
+ vl = []
48
+ def varlist(eq, fxconst):
49
+ nonlocal vl
50
+ if eq.name[:2] == "v_" and fxconst(eq):
51
+ vl.append(eq.name)
52
+ for child in eq.children:
53
+ varlist(child, fxconst)
54
+ for eq in eqlist:
55
+ varlist(eq, fxconst)
56
+ vl = list(set(vl))
57
+
58
+ if len(vl) > len(eqlist):
59
+ return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in eqlist])
60
+ m = []
61
+ for eq in eqlist:
62
+ s = copy.deepcopy(eq)
63
+ row = []
64
+ for v in vl:
65
+ row.append(diff(eq, v))
66
+ s = replace(s, tree_form(v), tree_form("d_0"))
67
+ row.append(s)
68
+ m.append(row)
69
+ for i in range(len(m)):
70
+ for j in range(len(m[i])):
71
+ m[i][j] = simplify(expand(m[i][j]))
72
+
73
+ m = rref(m)
74
+
75
+ for i in range(len(m)):
76
+ for j in range(len(m[i])):
77
+ m[i][j] = fraction(m[i][j])
78
+
79
+ output = []
80
+ for index, row in enumerate(m):
81
+ if not all(item == 0 for item in row[:-1]):
82
+ output.append(summation([tree_form(vl[index2])*coeff for index2, coeff in enumerate(row[:-1])])+row[-1])
83
+ elif row[-1] != 0:
84
+ return tree_form("s_false")
85
+ if len(output) == 1:
86
+ return TreeNode("f_eq", [output[0], tree_form("d_0")])
87
+ if len(output) == 0:
88
+ return tree_form("s_false")
89
+ return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in output])
90
+ def order_collinear_indices(points, idx):
91
+ """
92
+ Arrange a subset of collinear points (given by indices) along their line.
93
+
94
+ points: list of (x, y) tuples
95
+ idx: list of indices referring to points
96
+ Returns: list of indices sorted along the line
97
+ """
98
+ if len(idx) <= 1:
99
+ return idx[:]
100
+
101
+ # Take first two points from the subset to define the line
102
+ p0, p1 = points[idx[0]], points[idx[1]]
103
+ dx, dy = p1[0] - p0[0], p1[1] - p0[1]
104
+
105
+ # Projection factor for sorting
106
+ def projection_factor(i):
107
+ vx, vy = points[i][0] - p0[0], points[i][1] - p0[1]
108
+ return compute((vx * dx + vy * dy) / (dx**2 + dy**2))
109
+
110
+ # Sort indices by projection
111
+ sorted_idx = sorted(idx, key=projection_factor)
112
+ return list(sorted_idx)
113
+ def linear_or(eq):
114
+ eq = simplify(eq)
115
+ eqlst =[]
116
+ if eq.name != "f_or":
117
+ eqlst = [eq]
118
+ else:
119
+ eqlst = eq.children
120
+ v = vlist(eq)
121
+ p = []
122
+ line = {}
123
+ for i in range(len(eqlst)):
124
+ line[i] = []
125
+ for item in itertools.combinations(enumerate(eqlst), 2):
126
+ x, y = item[0][0], item[1][0]
127
+ item = [item[0][1], item[1][1]]
128
+ out = linear_solve(TreeNode("f_and", list(item)))
129
+ if out.name == "f_and" and all(len(vlist(child)) == 1 for child in out.children) and set(vlist(out)) == set(v):
130
+ t = {}
131
+ for child in out.children:
132
+ t[v.index(vlist(child)[0])] = simplify(inverse(child.children[0], vlist(child)[0]))
133
+ t2 = []
134
+ for key in sorted(t.keys()):
135
+ t2.append(t[key])
136
+ t2 = tuple(t2)
137
+ if t2 not in p:
138
+ p.append(t2)
139
+ line[x] += [p.index(t2)]
140
+ line[y] += [p.index(t2)]
141
+ line2 = []
142
+ for key in sorted(line.keys()):
143
+ line2.append(order_collinear_indices(p, list(set(line[key]))))
144
+ return v, p, line2, eqlst
145
+ def linear_solve(eq, lst=None):
146
+ eq = simplify(eq)
147
+ eqlist = []
148
+ if eq.name =="f_and" and all(child.name == "f_eq" and child.children[1] == 0 for child in eq.children):
149
+ eqlist = [child.children[0] for child in eq.children]
150
+ else:
151
+ return eq
152
+ out = None
153
+ if lst is None:
154
+ out = linear(copy.deepcopy(eqlist), lambda x: "v_" in str_form(x))
155
+ else:
156
+ out = linear(copy.deepcopy(eqlist), lambda x: any(contain(x, item) for item in lst))
157
+ return simplify(out)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.4.8
3
+ Version: 0.5.0
4
4
  Summary: Mathematics solving Ai tailored to NCERT
5
5
  Home-page: https://github.com/infinity390/mathai4
6
6
  Author: educated indians are having a low iq and are good for nothing
@@ -3,6 +3,7 @@ setup.py
3
3
  mathai/__init__.py
4
4
  mathai/apart.py
5
5
  mathai/base.py
6
+ mathai/bivariate_inequality.py
6
7
  mathai/console.py
7
8
  mathai/diff.py
8
9
  mathai/expand.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="mathai",
5
- version="0.4.8",
5
+ version="0.5.0",
6
6
  description="Mathematics solving Ai tailored to NCERT",
7
7
  long_description=open("README.md").read(),
8
8
  long_description_content_type="text/markdown",
@@ -1,156 +0,0 @@
1
- from .diff import diff
2
- from .simplify import simplify, solve
3
- from .fraction import fraction
4
- from .expand import expand
5
- from .base import *
6
- from .factor import factorconst
7
- def ss(eq):
8
- return dowhile(eq, lambda x: fraction(expand(simplify(x))))
9
- def rref(matrix):
10
- rows, cols = len(matrix), len(matrix[0])
11
- lead = 0
12
- for r in range(rows):
13
- if lead >= cols:
14
- return matrix
15
- i = r
16
- while ss(matrix[i][lead]) == tree_form("d_0"):
17
- i += 1
18
- if i == rows:
19
- i = r
20
- lead += 1
21
- if lead == cols:
22
- return matrix
23
- matrix[i], matrix[r] = matrix[r], matrix[i]
24
- lv = matrix[r][lead]
25
- matrix[r] = [ss(m / lv) for m in matrix[r]]
26
- for i in range(rows):
27
- if i != r:
28
- lv = matrix[i][lead]
29
- matrix[i] = [ss(m - lv * n) for m, n in zip(matrix[i], matrix[r])]
30
- lead += 1
31
- return matrix
32
- def islinear(eq, fxconst):
33
- eq =simplify(eq)
34
- if eq.name == "f_pow" and fxconst(eq):#"v_" in str_form(eq):
35
- return False
36
- for child in eq.children:
37
- out = islinear(child, fxconst)
38
- if not out:
39
- return out
40
- return True
41
- def linear(eqlist, fxconst):
42
- final = []
43
- extra = []
44
- for i in range(len(eqlist)-1,-1,-1):
45
- if eqlist[i].name == "f_mul" and not islinear(expand2(eqlist[i]), fxconst):
46
- if "v_" in str_form(eqlist[i]):
47
- eqlist[i] = TreeNode("f_mul", [child for child in eqlist[i].children if fxconst(child)])
48
- if all(islinear(child, fxconst) for child in eqlist[i].children):
49
- for child in eqlist[i].children:
50
- extra.append(TreeNode("f_eq", [child, tree_form("d_0")]))
51
- eqlist.pop(i)
52
- else:
53
- final.append(TreeNode("f_eq", [eqlist[i], tree_form("d_0")]))
54
- eqlist.pop(i)
55
-
56
- if extra != []:
57
- final.append(TreeNode("f_or", extra))
58
- if eqlist == []:
59
- if len(final)==1:
60
-
61
- return final[0]
62
- return TreeNode("f_and", final)
63
- eqlist = [eq for eq in eqlist if fxconst(eq)]
64
- if not all(islinear(eq, fxconst) for eq in eqlist):
65
- return TreeNode("f_and", copy.deepcopy(final+eqlist))
66
- vl = []
67
- def varlist(eq, fxconst):
68
- nonlocal vl
69
- if eq.name[:2] == "v_" and fxconst(eq):
70
- vl.append(eq.name)
71
- for child in eq.children:
72
- varlist(child, fxconst)
73
- for eq in eqlist:
74
- varlist(eq, fxconst)
75
- vl = list(set(vl))
76
-
77
- if len(vl) > len(eqlist):
78
- return TreeNode("f_and", final+[TreeNode("f_eq", [x, tree_form("d_0")]) for x in eqlist])
79
- m = []
80
- for eq in eqlist:
81
- s = copy.deepcopy(eq)
82
- row = []
83
- for v in vl:
84
- row.append(diff(eq, v))
85
- s = replace(s, tree_form(v), tree_form("d_0"))
86
- row.append(s)
87
- m.append(row)
88
- for i in range(len(m)):
89
- for j in range(len(m[i])):
90
- m[i][j] = simplify(expand(m[i][j]))
91
-
92
- m = rref(m)
93
-
94
- for i in range(len(m)):
95
- for j in range(len(m[i])):
96
- m[i][j] = fraction(m[i][j])
97
-
98
- for item in m:
99
- if all(item2==tree_form("d_0") for item2 in item[:-1]) and item[-1] != tree_form("d_0"):
100
- return tree_form("s_false")
101
-
102
- output = []
103
- for index, row in enumerate(m):
104
- count = 0
105
- for item in row[:-1]:
106
- if item == tree_form("d_1"):
107
- count += 1
108
- if count == 2:
109
- break
110
- elif item == tree_form("d_0") and count == 1:
111
- break
112
- if count == 0:
113
- continue
114
- output.append(tree_form(vl[index])+row[-1])
115
- if len(output) == 1 and len(final)==0:
116
- return TreeNode("f_eq", [output[0], tree_form("d_0")])
117
- return TreeNode("f_and", final+[TreeNode("f_eq", [x, tree_form("d_0")]) for x in output])
118
-
119
- def rmeq(eq):
120
- if eq.name == "f_eq":
121
- return rmeq(eq.children[0])
122
- return TreeNode(eq.name, [rmeq(child) for child in eq.children])
123
-
124
- def mat0(eq, lst=None):
125
- def findeq(eq):
126
- out = []
127
- if "f_list" not in str_form(eq) and "f_eq" not in str_form(eq):
128
- return [str_form(eq)]
129
- else:
130
- for child in eq.children:
131
- out += findeq(child)
132
- return out
133
- eqlist = findeq(eq)
134
- eqlist = [tree_form(x) for x in eqlist]
135
- eqlist = [rmeq(x) for x in eqlist]
136
- eqlist = [TreeNode("f_mul", factor_generation(x)) for x in eqlist if x != tree_form("d_0")]
137
- eqlist = [x.children[0] if len(x.children) == 1 else x for x in eqlist]
138
- out = None
139
-
140
- if lst is None:
141
- out = linear(copy.deepcopy(eqlist), lambda x: "v_" in str_form(x))
142
- else:
143
- out = linear(copy.deepcopy(eqlist), lambda x: any(contain(x, item) for item in lst))
144
- def rms(eq):
145
- if eq.name in ["f_and", "f_or"] and len(eq.children) == 1:
146
- return eq.children[0]
147
- return TreeNode(eq.name, [rms(child) for child in eq.children])
148
- return rms(out)
149
- def linear_solve(eq, lst=None):
150
- if eq.name == "f_and":
151
- eq2 = copy.deepcopy(eq)
152
- eq2.name = "f_list"
153
- return mat0(eq2, lst)
154
- elif eq.name == "f_eq":
155
- return mat0(eq, lst)
156
- return TreeNode(eq.name, [linear_solve(child, lst) for child in eq.children])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes