mathai 2.2.5__tar.gz → 2.2.6__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.
- {mathai-2.2.5 → mathai-2.2.6}/PKG-INFO +24 -4
- {mathai-2.2.5 → mathai-2.2.6}/README.md +23 -2
- {mathai-2.2.5 → mathai-2.2.6}/mathai/__init__.py +1 -1
- {mathai-2.2.5 → mathai-2.2.6}/mathai/electronic.py +27 -206
- {mathai-2.2.5 → mathai-2.2.6}/mathai/linear.py +27 -11
- {mathai-2.2.5 → mathai-2.2.6}/mathai.egg-info/PKG-INFO +24 -4
- {mathai-2.2.5 → mathai-2.2.6}/mathai.egg-info/requires.txt +0 -1
- {mathai-2.2.5 → mathai-2.2.6}/setup.py +2 -3
- {mathai-2.2.5 → mathai-2.2.6}/mathai/apart.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/base.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/decision.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/diff.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/expand.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/factor.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/differentiation.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/integration.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/integration_trig.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/is_integrate_subs.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/lambda_compress.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/lambda_expand.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/lambda_reduce.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/limit_infinity.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/matrix_vectorization_calculus.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/power_rule.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/quadratic.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/statistics_1.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/statistics_2.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/test.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula/trigonometry_misc.marshal +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula_compiler.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula_data.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/formula_interpretor.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/fraction.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/graphics.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/integrate.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/inverse.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/lambda_calculus.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/limit.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/logic.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/matrix.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/ml.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/mlscalar.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/ode.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/parser.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/pde.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/printeq.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/qm.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/simplify.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/statistics.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/test.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/tool.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/trig.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai/univariate_inequality.py +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai.egg-info/SOURCES.txt +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai.egg-info/dependency_links.txt +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/mathai.egg-info/top_level.txt +0 -0
- {mathai-2.2.5 → mathai-2.2.6}/setup.cfg +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathai
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.6
|
|
4
4
|
Summary: Mathematics solving Ai tailored to NCERT
|
|
5
5
|
Home-page: https://github.com/infinity390/mathai
|
|
6
6
|
Requires-Python: >=3.7
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: more_itertools
|
|
9
|
-
Requires-Dist: schemdraw
|
|
10
9
|
Dynamic: description
|
|
11
10
|
Dynamic: description-content-type
|
|
12
11
|
Dynamic: home-page
|
|
@@ -438,7 +437,6 @@ wire_4 = Edge((4, 9))
|
|
|
438
437
|
edge_list = [wire_1, wire_2, wire_3, wire_4,ohm_5, ohm_6, ohm_7, ohm_8, ohm_8_2, ohm_10, ohm_11, ohm_20]
|
|
439
438
|
graph = CircuitGraph(10, edge_list, {})
|
|
440
439
|
print(compute(find_resistance(graph, 0, 9)))
|
|
441
|
-
draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
|
|
442
440
|
```
|
|
443
441
|
|
|
444
442
|
#### Output
|
|
@@ -450,7 +448,29 @@ done
|
|
|
450
448
|
8.66474543707973
|
|
451
449
|
```
|
|
452
450
|
|
|
453
|
-
#### Example Demonstration 11 (
|
|
451
|
+
#### Example Demonstration 11 (resistors in parallel)
|
|
452
|
+
```python
|
|
453
|
+
from mathai import *
|
|
454
|
+
load_formula_from_file()
|
|
455
|
+
wire_1 = Edge((1, 3))
|
|
456
|
+
wire_2 = Edge((2, 3))
|
|
457
|
+
ohm_r1 = Edge((0, 1), "resistor", parse("x"))
|
|
458
|
+
ohm_r2 = Edge((0, 2), "resistor", parse("y"))
|
|
459
|
+
edge_list = [wire_1, ohm_r1, ohm_r2, wire_2]
|
|
460
|
+
graph = CircuitGraph(4, edge_list, {})
|
|
461
|
+
print(fraction(find_resistance(graph, 0, 3)))
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
#### Output
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
loading formulas from file...
|
|
468
|
+
done
|
|
469
|
+
|
|
470
|
+
(x*y)/(x+y)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### Example Demonstration 12 (engineering graphics)
|
|
454
474
|
```python
|
|
455
475
|
from mathai import *
|
|
456
476
|
# (z,y) is dash, a'b' is front view
|
|
@@ -422,7 +422,6 @@ wire_4 = Edge((4, 9))
|
|
|
422
422
|
edge_list = [wire_1, wire_2, wire_3, wire_4,ohm_5, ohm_6, ohm_7, ohm_8, ohm_8_2, ohm_10, ohm_11, ohm_20]
|
|
423
423
|
graph = CircuitGraph(10, edge_list, {})
|
|
424
424
|
print(compute(find_resistance(graph, 0, 9)))
|
|
425
|
-
draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
|
|
426
425
|
```
|
|
427
426
|
|
|
428
427
|
#### Output
|
|
@@ -434,7 +433,29 @@ done
|
|
|
434
433
|
8.66474543707973
|
|
435
434
|
```
|
|
436
435
|
|
|
437
|
-
#### Example Demonstration 11 (
|
|
436
|
+
#### Example Demonstration 11 (resistors in parallel)
|
|
437
|
+
```python
|
|
438
|
+
from mathai import *
|
|
439
|
+
load_formula_from_file()
|
|
440
|
+
wire_1 = Edge((1, 3))
|
|
441
|
+
wire_2 = Edge((2, 3))
|
|
442
|
+
ohm_r1 = Edge((0, 1), "resistor", parse("x"))
|
|
443
|
+
ohm_r2 = Edge((0, 2), "resistor", parse("y"))
|
|
444
|
+
edge_list = [wire_1, ohm_r1, ohm_r2, wire_2]
|
|
445
|
+
graph = CircuitGraph(4, edge_list, {})
|
|
446
|
+
print(fraction(find_resistance(graph, 0, 3)))
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### Output
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
loading formulas from file...
|
|
453
|
+
done
|
|
454
|
+
|
|
455
|
+
(x*y)/(x+y)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
#### Example Demonstration 12 (engineering graphics)
|
|
438
459
|
```python
|
|
439
460
|
from mathai import *
|
|
440
461
|
# (z,y) is dash, a'b' is front view
|
|
@@ -7,7 +7,7 @@ from .qm import hydrogen_gse, helium_gse, power_rule
|
|
|
7
7
|
|
|
8
8
|
from .lambda_calculus import lambda_expand, lambda_compress, lambda_reduce
|
|
9
9
|
|
|
10
|
-
from .electronic import Edge, CircuitGraph, find_resistance
|
|
10
|
+
from .electronic import Edge, CircuitGraph, find_resistance
|
|
11
11
|
|
|
12
12
|
from .linear import linear_solve
|
|
13
13
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import random
|
|
2
1
|
import copy
|
|
3
2
|
from .base import *
|
|
4
3
|
from .simplify import simplify
|
|
@@ -12,6 +11,7 @@ class Edge:
|
|
|
12
11
|
self.value = value
|
|
13
12
|
self.edge = tuple(edge) if edge else None
|
|
14
13
|
self.current = None
|
|
14
|
+
self.voltage = None
|
|
15
15
|
class CircuitGraph:
|
|
16
16
|
def __init__(self, node_count=0, edge_list=None, connection=None):
|
|
17
17
|
self.node_count = node_count
|
|
@@ -26,7 +26,7 @@ class CircuitGraph:
|
|
|
26
26
|
if edge.edge:
|
|
27
27
|
self.node_count = max(self.node_count, max(edge.edge) + 1)
|
|
28
28
|
self.connection = copy.deepcopy(connection) if connection else {}
|
|
29
|
-
self.variable_list = [TreeNode(f"v_{i}") for i in range(26)]
|
|
29
|
+
self.variable_list = [TreeNode(f"v_{i}") for i in range(6,26)]
|
|
30
30
|
self.complete_connection()
|
|
31
31
|
def complete_connection(self):
|
|
32
32
|
for i in range(self.node_count):
|
|
@@ -174,19 +174,21 @@ class CircuitGraph:
|
|
|
174
174
|
missing = [i for i, edge in enumerate(self.edge_list) if edge.current is None]
|
|
175
175
|
if missing:
|
|
176
176
|
raise ValueError(f"Could not determine currents: {missing}")
|
|
177
|
-
def find_resistance(circuit, start, end):
|
|
177
|
+
def find_resistance(circuit, start=None, end=None, compute_current_only=False):
|
|
178
178
|
circuit = copy.deepcopy(circuit)
|
|
179
|
-
if start == end:
|
|
179
|
+
if start == end and start is not None and end is not None:
|
|
180
180
|
return TreeNode("d_0")
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
181
|
+
cell_idx = None
|
|
182
|
+
if not compute_current_only:
|
|
183
|
+
new_node = circuit.node_count
|
|
184
|
+
circuit.node_count += 1
|
|
185
|
+
cell = Edge((end, new_node), "cell", TreeNode("d_1"))
|
|
186
|
+
wire = Edge((new_node, start), "wire")
|
|
187
|
+
circuit.edge_list.append(cell)
|
|
188
|
+
cell_idx = len(circuit.edge_list) - 1
|
|
189
|
+
circuit.edge_list.append(wire)
|
|
188
190
|
circuit.complete_connection()
|
|
189
|
-
circuit.assign_currents(
|
|
191
|
+
circuit.assign_currents()
|
|
190
192
|
cycles = circuit.all_simple_cycle()
|
|
191
193
|
equations = []
|
|
192
194
|
for cycle in cycles:
|
|
@@ -200,210 +202,29 @@ def find_resistance(circuit, start, end):
|
|
|
200
202
|
[TreeNode("f_eq", [equation, TreeNode("d_0")]) for equation in equations]
|
|
201
203
|
)
|
|
202
204
|
equations = simplify(fraction(simplify(equations)))
|
|
203
|
-
|
|
205
|
+
const_list = []
|
|
206
|
+
for item in circuit.edge_list:
|
|
207
|
+
if item.edge_type == "resistor":
|
|
208
|
+
const_list += [TreeNode(item) for item in vlist(item.value)]
|
|
209
|
+
equations = linear_solve(equations, const_list)
|
|
204
210
|
solutions = {}
|
|
205
211
|
equation_list = equations.children if equations.name == "f_and" else [equations]
|
|
206
212
|
for equation in equation_list:
|
|
207
|
-
variables = vlist(equation)
|
|
213
|
+
variables = list(set(vlist(equation))-set([item.name for item in const_list]))
|
|
208
214
|
if len(variables) != 1:
|
|
209
215
|
continue
|
|
210
216
|
variable = variables[0]
|
|
211
217
|
solutions[variable] = inverse(equation.children[0], variable)
|
|
218
|
+
for index, item in enumerate(circuit.edge_list):
|
|
219
|
+
for v in vlist(circuit.edge_list[index].current):
|
|
220
|
+
if TreeNode(v) in const_list:
|
|
221
|
+
continue
|
|
222
|
+
circuit.edge_list[index].current = simplify(replace(circuit.edge_list[index].current, TreeNode(v), solutions[v]))
|
|
223
|
+
if compute_current_only:
|
|
224
|
+
return circuit
|
|
212
225
|
current = circuit.edge_list[cell_idx].current
|
|
213
226
|
for variable, value in solutions.items():
|
|
214
227
|
if variable in vlist(current):
|
|
215
228
|
current = replace(current, tree_form(variable), value)
|
|
216
229
|
current = simplify(TreeNode("d_1")/current)
|
|
217
230
|
return current
|
|
218
|
-
import random
|
|
219
|
-
import schemdraw
|
|
220
|
-
import schemdraw.elements as elm
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
def on_segment(p, a, b):
|
|
224
|
-
"""Returns True if point p lies exactly on the line segment a-b."""
|
|
225
|
-
# Collinearity check (cross product == 0)
|
|
226
|
-
cross = (p[0] - a[0]) * (b[1] - a[1]) - (p[1] - a[1]) * (b[0] - a[0])
|
|
227
|
-
if abs(cross) > 1e-6:
|
|
228
|
-
return False
|
|
229
|
-
# Bounding box check
|
|
230
|
-
if min(a[0], b[0]) <= p[0] <= max(a[0], b[0]) and \
|
|
231
|
-
min(a[1], b[1]) <= p[1] <= max(a[1], b[1]):
|
|
232
|
-
return True
|
|
233
|
-
return False
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
def segments_conflict_exact(a, b, c, d):
|
|
237
|
-
"""
|
|
238
|
-
Checks if segment ab conflicts with cd (intersects or overlaps),
|
|
239
|
-
ignoring shared endpoints unless they perfectly overlap.
|
|
240
|
-
"""
|
|
241
|
-
def ccw(p, q, r):
|
|
242
|
-
return (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0])
|
|
243
|
-
|
|
244
|
-
c1, c2 = ccw(a, b, c), ccw(a, b, d)
|
|
245
|
-
c3, c4 = ccw(c, d, a), ccw(c, d, b)
|
|
246
|
-
|
|
247
|
-
# 1. True geometric intersection (lines cross)
|
|
248
|
-
if ((c1 > 0 and c2 < 0) or (c1 < 0 and c2 > 0)) and \
|
|
249
|
-
((c3 > 0 and c4 < 0) or (c3 < 0 and c4 > 0)):
|
|
250
|
-
return True
|
|
251
|
-
|
|
252
|
-
# 2. Collinear overlap (one point lies strictly inside the other segment)
|
|
253
|
-
if on_segment(c, a, b) and c != a and c != b: return True
|
|
254
|
-
if on_segment(d, a, b) and d != a and d != b: return True
|
|
255
|
-
if on_segment(a, c, d) and a != c and a != d: return True
|
|
256
|
-
if on_segment(b, c, d) and b != c and b != d: return True
|
|
257
|
-
|
|
258
|
-
# 3. Identical overlapping segments
|
|
259
|
-
if (a == c and b == d) or (a == d and b == c):
|
|
260
|
-
return True
|
|
261
|
-
|
|
262
|
-
return False
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def get_all_candidate_routes(p1, p2):
|
|
266
|
-
"""Generates all valid orthogonal straight line and 1-bend L-routes."""
|
|
267
|
-
x1, y1 = p1
|
|
268
|
-
x2, y2 = p2
|
|
269
|
-
|
|
270
|
-
# Collinear (Straight line along single axis)
|
|
271
|
-
if x1 == x2 or y1 == y2:
|
|
272
|
-
return [[p1, p2]]
|
|
273
|
-
|
|
274
|
-
# Standard L-shapes (Horizontal-first or Vertical-first)
|
|
275
|
-
return [
|
|
276
|
-
[p1, (x1, y2), p2],
|
|
277
|
-
[p1, (x2, y1), p2]
|
|
278
|
-
]
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
def route_to_segments(route):
|
|
282
|
-
return [(route[i], route[i + 1]) for i in range(len(route) - 1)]
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
def check_route_conflict(route, placed_routes, node_positions, u, v):
|
|
286
|
-
"""Validates that a new route does not cross placed routes or run over unrelated nodes."""
|
|
287
|
-
segs = route_to_segments(route)
|
|
288
|
-
|
|
289
|
-
# 1. Check against already placed routes
|
|
290
|
-
for placed_route in placed_routes:
|
|
291
|
-
placed_segs = route_to_segments(placed_route)
|
|
292
|
-
for a, b in segs:
|
|
293
|
-
for c, d in placed_segs:
|
|
294
|
-
if segments_conflict_exact(a, b, c, d):
|
|
295
|
-
return True
|
|
296
|
-
|
|
297
|
-
# 2. Check against nodes (prevent line from running through an unrelated node)
|
|
298
|
-
for node, pos in node_positions.items():
|
|
299
|
-
if node == u or node == v:
|
|
300
|
-
continue # Permitted to touch its own endpoints
|
|
301
|
-
for a, b in segs:
|
|
302
|
-
if on_segment(pos, a, b):
|
|
303
|
-
return True
|
|
304
|
-
|
|
305
|
-
return False
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
def solve_routing(edges, node_positions):
|
|
309
|
-
"""DFS Backtracking to find a 100% collision-free route mapping for a given node layout."""
|
|
310
|
-
placed_routes = []
|
|
311
|
-
|
|
312
|
-
def backtrack(edge_idx):
|
|
313
|
-
if edge_idx == len(edges):
|
|
314
|
-
return True
|
|
315
|
-
|
|
316
|
-
edge = edges[edge_idx]
|
|
317
|
-
u, v = edge.edge
|
|
318
|
-
p1, p2 = node_positions[u], node_positions[v]
|
|
319
|
-
|
|
320
|
-
candidate_routes = get_all_candidate_routes(p1, p2)
|
|
321
|
-
random.shuffle(candidate_routes)
|
|
322
|
-
|
|
323
|
-
for route in candidate_routes:
|
|
324
|
-
if not check_route_conflict(route, placed_routes, node_positions, u, v):
|
|
325
|
-
placed_routes.append(route)
|
|
326
|
-
if backtrack(edge_idx + 1):
|
|
327
|
-
return True
|
|
328
|
-
placed_routes.pop()
|
|
329
|
-
return False
|
|
330
|
-
|
|
331
|
-
if backtrack(0):
|
|
332
|
-
return placed_routes
|
|
333
|
-
return None
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def draw_circuit(graph, start=None, end=None, scale=3.0, grid_size=12, max_attempts=10000):
|
|
337
|
-
"""
|
|
338
|
-
Renders a circuit using randomized grid placement and exact geometric backtracking.
|
|
339
|
-
Guarantees strict L/straight paths without line intersections or bugs.
|
|
340
|
-
"""
|
|
341
|
-
edges = graph.edge_list
|
|
342
|
-
all_nodes = set()
|
|
343
|
-
for edge in edges:
|
|
344
|
-
all_nodes.add(edge.edge[0])
|
|
345
|
-
all_nodes.add(edge.edge[1])
|
|
346
|
-
|
|
347
|
-
nodes_list = sorted(list(all_nodes))
|
|
348
|
-
|
|
349
|
-
best_positions = None
|
|
350
|
-
best_routes = None
|
|
351
|
-
|
|
352
|
-
# Search for a node configuration that allows a perfect non-intersecting layout
|
|
353
|
-
for _ in range(max_attempts):
|
|
354
|
-
# Generate random available grid locations
|
|
355
|
-
available_cells = [
|
|
356
|
-
(col * scale, -row * scale)
|
|
357
|
-
for row in range(grid_size)
|
|
358
|
-
for col in range(grid_size)
|
|
359
|
-
]
|
|
360
|
-
random.shuffle(available_cells)
|
|
361
|
-
|
|
362
|
-
current_positions = {node: available_cells[i] for i, node in enumerate(nodes_list)}
|
|
363
|
-
|
|
364
|
-
# Attempt to perfectly route all edges
|
|
365
|
-
routes = solve_routing(edges, current_positions)
|
|
366
|
-
|
|
367
|
-
if routes is not None:
|
|
368
|
-
best_positions = current_positions
|
|
369
|
-
best_routes = routes
|
|
370
|
-
break # Perfect layout found!
|
|
371
|
-
|
|
372
|
-
if best_routes is None:
|
|
373
|
-
raise RuntimeError("Failed to find a non-intersecting layout. Try increasing grid_size or max_attempts.")
|
|
374
|
-
|
|
375
|
-
# Render Circuit Diagram with Schemdraw
|
|
376
|
-
d = schemdraw.Drawing()
|
|
377
|
-
|
|
378
|
-
for idx, edge in enumerate(edges):
|
|
379
|
-
route = best_routes[idx]
|
|
380
|
-
segs = route_to_segments(route)
|
|
381
|
-
resistor = getattr(edge, "edge_type", "") == "resistor"
|
|
382
|
-
value = getattr(edge, "value", "")
|
|
383
|
-
|
|
384
|
-
for i, (p1, p2) in enumerate(segs):
|
|
385
|
-
# Place resistor component on the last segment of the route
|
|
386
|
-
if resistor and i == len(segs) - 1:
|
|
387
|
-
lbl = f"{value} Ω" if value else ""
|
|
388
|
-
d.add(
|
|
389
|
-
elm.Resistor()
|
|
390
|
-
.at(p1)
|
|
391
|
-
.to(p2)
|
|
392
|
-
.label(lbl)
|
|
393
|
-
)
|
|
394
|
-
else:
|
|
395
|
-
d.add(elm.Line().at(p1).to(p2))
|
|
396
|
-
|
|
397
|
-
# Draw Nodes
|
|
398
|
-
for node, pos in best_positions.items():
|
|
399
|
-
d.add(elm.Dot().at(pos))
|
|
400
|
-
|
|
401
|
-
# Add Terminal Labels
|
|
402
|
-
if start is not None and start in best_positions:
|
|
403
|
-
d.add(elm.Label().at(best_positions[start]).label("Start", loc="left"))
|
|
404
|
-
|
|
405
|
-
if end is not None and end in best_positions:
|
|
406
|
-
d.add(elm.Label().at(best_positions[end]).label("End", loc="right"))
|
|
407
|
-
|
|
408
|
-
d.draw()
|
|
409
|
-
return d
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .inverse import inverse
|
|
2
2
|
import itertools
|
|
3
|
+
import copy
|
|
3
4
|
from .diff import diff
|
|
4
5
|
from .simplify import simplify
|
|
5
6
|
from .fraction import fraction
|
|
@@ -7,8 +8,10 @@ from .expand import expand
|
|
|
7
8
|
from .base import *
|
|
8
9
|
from .factor import factorconst
|
|
9
10
|
from .tool import poly
|
|
11
|
+
|
|
10
12
|
def ss(eq):
|
|
11
13
|
return dowhile(eq, lambda x: fraction(simplify(x)))
|
|
14
|
+
|
|
12
15
|
def rref(matrix, fxconst):
|
|
13
16
|
rows, cols = len(matrix), len(matrix[0])
|
|
14
17
|
lead = 0
|
|
@@ -32,25 +35,28 @@ def rref(matrix, fxconst):
|
|
|
32
35
|
matrix[i] = [ss(m - lv * n) for m, n in zip(matrix[i], matrix[r])]
|
|
33
36
|
lead += 1
|
|
34
37
|
return matrix
|
|
38
|
+
|
|
35
39
|
def linear(eqlist, fxconst):
|
|
36
40
|
orig = [item.copy_tree() for item in eqlist]
|
|
37
|
-
v2 = []
|
|
38
41
|
vl = []
|
|
42
|
+
|
|
39
43
|
def varlist(eq, fxconst):
|
|
40
44
|
nonlocal vl
|
|
41
|
-
nonlocal v2
|
|
42
|
-
if eq.name[:2] == "v_" and fxconst(eq):
|
|
43
|
-
vl.append(eq.name)
|
|
44
45
|
if eq.name[:2] == "v_" and not fxconst(eq):
|
|
45
|
-
|
|
46
|
+
vl.append(eq.name)
|
|
46
47
|
for child in eq.children:
|
|
47
48
|
varlist(child, fxconst)
|
|
49
|
+
|
|
48
50
|
for eq in eqlist:
|
|
49
51
|
varlist(eq, fxconst)
|
|
50
|
-
|
|
51
|
-
vl = list(set(vl))
|
|
52
|
+
|
|
53
|
+
vl = sorted(list(set(vl)))
|
|
54
|
+
|
|
52
55
|
if len(vl) > len(eqlist):
|
|
56
|
+
if len(eqlist) == 1:
|
|
57
|
+
return TreeNode("f_eq", [eqlist[0], tree_form("d_0")])
|
|
53
58
|
return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in eqlist])
|
|
59
|
+
|
|
54
60
|
m = []
|
|
55
61
|
for eq in eqlist:
|
|
56
62
|
s = copy.deepcopy(eq)
|
|
@@ -60,36 +66,46 @@ def linear(eqlist, fxconst):
|
|
|
60
66
|
s = replace(s, tree_form(v), tree_form("d_0"))
|
|
61
67
|
row.append(s)
|
|
62
68
|
m.append(row)
|
|
69
|
+
|
|
63
70
|
for i in range(len(m)):
|
|
64
71
|
for j in range(len(m[i])):
|
|
65
72
|
m[i][j] = simplify(expand(m[i][j]))
|
|
73
|
+
|
|
66
74
|
m = rref(m, fxconst)
|
|
75
|
+
|
|
67
76
|
for i in range(len(m)):
|
|
68
77
|
for j in range(len(m[i])):
|
|
69
78
|
m[i][j] = fraction(m[i][j])
|
|
79
|
+
|
|
70
80
|
output = []
|
|
71
81
|
for index, row in enumerate(m):
|
|
72
|
-
if not all(item ==
|
|
73
|
-
output.append(summation([tree_form(vl[index2])*coeff for index2, coeff in enumerate(row[:-1])])+row[-1])
|
|
74
|
-
elif row[-1] !=
|
|
82
|
+
if not all(item == tree_form("d_0") for item in row[:-1]):
|
|
83
|
+
output.append(summation([tree_form(vl[index2])*coeff for index2, coeff in enumerate(row[:-1])]) + row[-1])
|
|
84
|
+
elif row[-1] != tree_form("d_0"):
|
|
75
85
|
return tree_form("s_false")
|
|
86
|
+
|
|
76
87
|
if len(output) == 1:
|
|
77
88
|
return TreeNode("f_eq", [output[0], tree_form("d_0")])
|
|
78
89
|
if len(output) == 0:
|
|
79
90
|
return tree_form("s_false")
|
|
80
91
|
return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in output])
|
|
92
|
+
|
|
81
93
|
def linear_solve(eq, lst=None):
|
|
82
94
|
eq = simplify(eq)
|
|
83
95
|
eqlist = []
|
|
84
|
-
if eq.name =="f_and" and all(child.name == "f_eq" and child.children[1] == tree_form("d_0") for child in eq.children):
|
|
96
|
+
if eq.name == "f_and" and all(child.name == "f_eq" and child.children[1] == tree_form("d_0") for child in eq.children):
|
|
85
97
|
eqlist = [child.children[0] for child in eq.children]
|
|
98
|
+
elif eq.name == "f_eq" and eq.children[1] == tree_form("d_0"):
|
|
99
|
+
eqlist = [eq.children[0]]
|
|
86
100
|
else:
|
|
87
101
|
return eq
|
|
102
|
+
|
|
88
103
|
out = None
|
|
89
104
|
if lst is None:
|
|
90
105
|
out = linear(copy.deepcopy(eqlist), lambda x: False)
|
|
91
106
|
else:
|
|
92
107
|
out = linear(copy.deepcopy(eqlist), lambda x: any(contain(x, item) for item in lst))
|
|
108
|
+
|
|
93
109
|
if out is None:
|
|
94
110
|
return None
|
|
95
111
|
return simplify(out)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathai
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.6
|
|
4
4
|
Summary: Mathematics solving Ai tailored to NCERT
|
|
5
5
|
Home-page: https://github.com/infinity390/mathai
|
|
6
6
|
Requires-Python: >=3.7
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: more_itertools
|
|
9
|
-
Requires-Dist: schemdraw
|
|
10
9
|
Dynamic: description
|
|
11
10
|
Dynamic: description-content-type
|
|
12
11
|
Dynamic: home-page
|
|
@@ -438,7 +437,6 @@ wire_4 = Edge((4, 9))
|
|
|
438
437
|
edge_list = [wire_1, wire_2, wire_3, wire_4,ohm_5, ohm_6, ohm_7, ohm_8, ohm_8_2, ohm_10, ohm_11, ohm_20]
|
|
439
438
|
graph = CircuitGraph(10, edge_list, {})
|
|
440
439
|
print(compute(find_resistance(graph, 0, 9)))
|
|
441
|
-
draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
|
|
442
440
|
```
|
|
443
441
|
|
|
444
442
|
#### Output
|
|
@@ -450,7 +448,29 @@ done
|
|
|
450
448
|
8.66474543707973
|
|
451
449
|
```
|
|
452
450
|
|
|
453
|
-
#### Example Demonstration 11 (
|
|
451
|
+
#### Example Demonstration 11 (resistors in parallel)
|
|
452
|
+
```python
|
|
453
|
+
from mathai import *
|
|
454
|
+
load_formula_from_file()
|
|
455
|
+
wire_1 = Edge((1, 3))
|
|
456
|
+
wire_2 = Edge((2, 3))
|
|
457
|
+
ohm_r1 = Edge((0, 1), "resistor", parse("x"))
|
|
458
|
+
ohm_r2 = Edge((0, 2), "resistor", parse("y"))
|
|
459
|
+
edge_list = [wire_1, ohm_r1, ohm_r2, wire_2]
|
|
460
|
+
graph = CircuitGraph(4, edge_list, {})
|
|
461
|
+
print(fraction(find_resistance(graph, 0, 3)))
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
#### Output
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
loading formulas from file...
|
|
468
|
+
done
|
|
469
|
+
|
|
470
|
+
(x*y)/(x+y)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### Example Demonstration 12 (engineering graphics)
|
|
454
474
|
```python
|
|
455
475
|
from mathai import *
|
|
456
476
|
# (z,y) is dash, a'b' is front view
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
setup(
|
|
4
4
|
name="mathai",
|
|
5
|
-
version="2.2.
|
|
5
|
+
version="2.2.6",
|
|
6
6
|
description="Mathematics solving Ai tailored to NCERT",
|
|
7
7
|
long_description=Path("README.md").read_text(encoding="utf-8"),
|
|
8
8
|
long_description_content_type="text/markdown",
|
|
@@ -13,7 +13,6 @@ setup(
|
|
|
13
13
|
},
|
|
14
14
|
python_requires=">=3.7",
|
|
15
15
|
install_requires=[
|
|
16
|
-
"more_itertools"
|
|
17
|
-
"schemdraw"
|
|
16
|
+
"more_itertools"
|
|
18
17
|
],
|
|
19
18
|
)
|
|
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
|
|
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
|
|
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
|