mathai 2.2.0__tar.gz → 2.2.2__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 (57) hide show
  1. {mathai-2.2.0 → mathai-2.2.2}/PKG-INFO +29 -32
  2. {mathai-2.2.0 → mathai-2.2.2}/README.md +28 -31
  3. {mathai-2.2.0 → mathai-2.2.2}/mathai/__init__.py +2 -0
  4. {mathai-2.2.0 → mathai-2.2.2}/mathai/electronic.py +191 -197
  5. mathai-2.2.2/mathai/graphics.py +42 -0
  6. {mathai-2.2.0 → mathai-2.2.2}/mathai.egg-info/PKG-INFO +29 -32
  7. {mathai-2.2.0 → mathai-2.2.2}/mathai.egg-info/SOURCES.txt +1 -0
  8. {mathai-2.2.0 → mathai-2.2.2}/setup.py +1 -1
  9. {mathai-2.2.0 → mathai-2.2.2}/mathai/apart.py +0 -0
  10. {mathai-2.2.0 → mathai-2.2.2}/mathai/base.py +0 -0
  11. {mathai-2.2.0 → mathai-2.2.2}/mathai/decision.py +0 -0
  12. {mathai-2.2.0 → mathai-2.2.2}/mathai/diff.py +0 -0
  13. {mathai-2.2.0 → mathai-2.2.2}/mathai/expand.py +0 -0
  14. {mathai-2.2.0 → mathai-2.2.2}/mathai/factor.py +0 -0
  15. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/differentiation.marshal +0 -0
  16. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/integration.marshal +0 -0
  17. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/integration_trig.marshal +0 -0
  18. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/is_integrate_subs.marshal +0 -0
  19. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/lambda_compress.marshal +0 -0
  20. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/lambda_expand.marshal +0 -0
  21. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/lambda_reduce.marshal +0 -0
  22. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/limit_infinity.marshal +0 -0
  23. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/matrix_vectorization_calculus.marshal +0 -0
  24. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/power_rule.marshal +0 -0
  25. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/quadratic.marshal +0 -0
  26. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/statistics_1.marshal +0 -0
  27. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/statistics_2.marshal +0 -0
  28. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/test.marshal +0 -0
  29. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula/trigonometry_misc.marshal +0 -0
  30. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula_compiler.py +0 -0
  31. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula_data.py +0 -0
  32. {mathai-2.2.0 → mathai-2.2.2}/mathai/formula_interpretor.py +0 -0
  33. {mathai-2.2.0 → mathai-2.2.2}/mathai/fraction.py +0 -0
  34. {mathai-2.2.0 → mathai-2.2.2}/mathai/integrate.py +0 -0
  35. {mathai-2.2.0 → mathai-2.2.2}/mathai/inverse.py +0 -0
  36. {mathai-2.2.0 → mathai-2.2.2}/mathai/lambda_calculus.py +0 -0
  37. {mathai-2.2.0 → mathai-2.2.2}/mathai/limit.py +0 -0
  38. {mathai-2.2.0 → mathai-2.2.2}/mathai/linear.py +0 -0
  39. {mathai-2.2.0 → mathai-2.2.2}/mathai/logic.py +0 -0
  40. {mathai-2.2.0 → mathai-2.2.2}/mathai/matrix.py +0 -0
  41. {mathai-2.2.0 → mathai-2.2.2}/mathai/ml.py +0 -0
  42. {mathai-2.2.0 → mathai-2.2.2}/mathai/mlscalar.py +0 -0
  43. {mathai-2.2.0 → mathai-2.2.2}/mathai/ode.py +0 -0
  44. {mathai-2.2.0 → mathai-2.2.2}/mathai/parser.py +0 -0
  45. {mathai-2.2.0 → mathai-2.2.2}/mathai/pde.py +0 -0
  46. {mathai-2.2.0 → mathai-2.2.2}/mathai/printeq.py +0 -0
  47. {mathai-2.2.0 → mathai-2.2.2}/mathai/qm.py +0 -0
  48. {mathai-2.2.0 → mathai-2.2.2}/mathai/simplify.py +0 -0
  49. {mathai-2.2.0 → mathai-2.2.2}/mathai/statistics.py +0 -0
  50. {mathai-2.2.0 → mathai-2.2.2}/mathai/test.py +0 -0
  51. {mathai-2.2.0 → mathai-2.2.2}/mathai/tool.py +0 -0
  52. {mathai-2.2.0 → mathai-2.2.2}/mathai/trig.py +0 -0
  53. {mathai-2.2.0 → mathai-2.2.2}/mathai/univariate_inequality.py +0 -0
  54. {mathai-2.2.0 → mathai-2.2.2}/mathai.egg-info/dependency_links.txt +0 -0
  55. {mathai-2.2.0 → mathai-2.2.2}/mathai.egg-info/requires.txt +0 -0
  56. {mathai-2.2.0 → mathai-2.2.2}/mathai.egg-info/top_level.txt +0 -0
  57. {mathai-2.2.0 → mathai-2.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Mathematics solving Ai tailored to NCERT
5
5
  Home-page: https://github.com/infinity390/mathai
6
6
  Requires-Python: >=3.7
@@ -423,37 +423,22 @@ answer
423
423
  ```python
424
424
  from mathai import *
425
425
  load_formula_from_file()
426
- wire_1 = Edge((0,1))
427
- ohm_10 = Edge((1,2), "resistor", TreeNode("d_10"))
428
- ohm_5 = Edge((2,3), "resistor", TreeNode("d_5"))
429
- ohm_6 = Edge((2,4), "resistor", TreeNode("d_6"))
430
- ohm_7 = Edge((4,5), "resistor", TreeNode("d_7"))
431
- ohm_8 = Edge((4,6), "resistor", TreeNode("d_8"))
432
- ohm_20 = Edge((6,7), "resistor", TreeNode("d_20"))
433
- wire_2 = Edge((7,5))
434
- wire_3 = Edge((3,5))
435
- wire_4 = Edge((3,8))
436
- edge_list = [wire_1, wire_2, wire_3, wire_4, ohm_5, ohm_6, ohm_7, ohm_8, ohm_10, ohm_20]
437
- graph = CircuitGraph(9,edge_list,{})
438
- print(compute(find_resistance(graph, 0,8)))
439
- draw_circuit(graph)
440
-
441
- wire_1 = Edge((0,1))
442
- ohm_5 = Edge((1,2), "resistor", TreeNode("d_5"))
443
- ohm_10 = Edge((2,3), "resistor", TreeNode("d_10"))
444
- ohm_11 = Edge((3,4), "resistor", TreeNode("d_11"))
445
- ohm_8 = Edge((2,5), "resistor", TreeNode("d_8"))
446
- ohm_7 = Edge((5,4), "resistor", TreeNode("d_7"))
447
- ohm_6 = Edge((1,6), "resistor", TreeNode("d_6"))
448
- ohm_8_2 = Edge((1,7), "resistor", TreeNode("d_8"))
449
- wire_2 = Edge((6,8))
450
- wire_3 = Edge((7,8))
451
- ohm_20 = Edge((8,4), "resistor", TreeNode("d_20"))
452
- wire_4 = Edge((4,9))
453
- 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]
454
- graph = CircuitGraph(10,edge_list,{})
426
+ wire_1 = Edge((0, 1))
427
+ ohm_5 = Edge((1, 2), "resistor", TreeNode("d_5"))
428
+ ohm_10 = Edge((2, 3), "resistor", TreeNode("d_10"))
429
+ ohm_11 = Edge((3, 4), "resistor", TreeNode("d_11"))
430
+ ohm_8 = Edge((2, 5), "resistor", TreeNode("d_8"))
431
+ ohm_7 = Edge((5, 4), "resistor", TreeNode("d_7"))
432
+ ohm_6 = Edge((1, 6), "resistor", TreeNode("d_6"))
433
+ ohm_8_2 = Edge((1, 7), "resistor", TreeNode("d_8"))
434
+ wire_2 = Edge((6, 8))
435
+ wire_3 = Edge((7, 8))
436
+ ohm_20 = Edge((8, 4), "resistor", TreeNode("d_20"))
437
+ wire_4 = Edge((4, 9))
438
+ 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
+ graph = CircuitGraph(10, edge_list, {})
455
440
  print(compute(find_resistance(graph, 0, 9)))
456
- draw_circuit(graph)
441
+ draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
457
442
  ```
458
443
 
459
444
  #### Output
@@ -462,10 +447,22 @@ draw_circuit(graph)
462
447
  loading formulas from file...
463
448
  done
464
449
 
465
- 13.493975903614459
466
450
  8.66474543707973
467
451
  ```
468
452
 
453
+ #### Example Demonstration 11 (engineering graphics)
454
+ ```python
455
+ from mathai import *
456
+ s = "0 -25 0 None None None None None None 0 None 55 75"
457
+ s = [None if item == "None" else parse(item) for item in s.split(" ")]
458
+ print(solve_graphics(*s))
459
+ ```
460
+
461
+ #### Output
462
+ ```
463
+ {'v_0': 0, 'v_1': -25, 'v_2': 0, 'v_9': 0, 'v_11': 55, 'v_12': 75, 'v_7': sqrt(2600), 'v_10': arcsin((sqrt(2600)/75)), 'v_8': 75*sqrt((1-((sqrt(2600)/75)^2))), 'v_6': 0, 'v_3': 0, 'v_4': -25+sqrt(2600), 'v_5': 75*sqrt((1-((sqrt(2600)/75)^2)))}
464
+ ```
465
+
469
466
  ### Questions solved using god() function
470
467
 
471
468
  #### Code
@@ -407,37 +407,22 @@ answer
407
407
  ```python
408
408
  from mathai import *
409
409
  load_formula_from_file()
410
- wire_1 = Edge((0,1))
411
- ohm_10 = Edge((1,2), "resistor", TreeNode("d_10"))
412
- ohm_5 = Edge((2,3), "resistor", TreeNode("d_5"))
413
- ohm_6 = Edge((2,4), "resistor", TreeNode("d_6"))
414
- ohm_7 = Edge((4,5), "resistor", TreeNode("d_7"))
415
- ohm_8 = Edge((4,6), "resistor", TreeNode("d_8"))
416
- ohm_20 = Edge((6,7), "resistor", TreeNode("d_20"))
417
- wire_2 = Edge((7,5))
418
- wire_3 = Edge((3,5))
419
- wire_4 = Edge((3,8))
420
- edge_list = [wire_1, wire_2, wire_3, wire_4, ohm_5, ohm_6, ohm_7, ohm_8, ohm_10, ohm_20]
421
- graph = CircuitGraph(9,edge_list,{})
422
- print(compute(find_resistance(graph, 0,8)))
423
- draw_circuit(graph)
424
-
425
- wire_1 = Edge((0,1))
426
- ohm_5 = Edge((1,2), "resistor", TreeNode("d_5"))
427
- ohm_10 = Edge((2,3), "resistor", TreeNode("d_10"))
428
- ohm_11 = Edge((3,4), "resistor", TreeNode("d_11"))
429
- ohm_8 = Edge((2,5), "resistor", TreeNode("d_8"))
430
- ohm_7 = Edge((5,4), "resistor", TreeNode("d_7"))
431
- ohm_6 = Edge((1,6), "resistor", TreeNode("d_6"))
432
- ohm_8_2 = Edge((1,7), "resistor", TreeNode("d_8"))
433
- wire_2 = Edge((6,8))
434
- wire_3 = Edge((7,8))
435
- ohm_20 = Edge((8,4), "resistor", TreeNode("d_20"))
436
- wire_4 = Edge((4,9))
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]
438
- graph = CircuitGraph(10,edge_list,{})
410
+ wire_1 = Edge((0, 1))
411
+ ohm_5 = Edge((1, 2), "resistor", TreeNode("d_5"))
412
+ ohm_10 = Edge((2, 3), "resistor", TreeNode("d_10"))
413
+ ohm_11 = Edge((3, 4), "resistor", TreeNode("d_11"))
414
+ ohm_8 = Edge((2, 5), "resistor", TreeNode("d_8"))
415
+ ohm_7 = Edge((5, 4), "resistor", TreeNode("d_7"))
416
+ ohm_6 = Edge((1, 6), "resistor", TreeNode("d_6"))
417
+ ohm_8_2 = Edge((1, 7), "resistor", TreeNode("d_8"))
418
+ wire_2 = Edge((6, 8))
419
+ wire_3 = Edge((7, 8))
420
+ ohm_20 = Edge((8, 4), "resistor", TreeNode("d_20"))
421
+ wire_4 = Edge((4, 9))
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
+ graph = CircuitGraph(10, edge_list, {})
439
424
  print(compute(find_resistance(graph, 0, 9)))
440
- draw_circuit(graph)
425
+ draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
441
426
  ```
442
427
 
443
428
  #### Output
@@ -446,10 +431,22 @@ draw_circuit(graph)
446
431
  loading formulas from file...
447
432
  done
448
433
 
449
- 13.493975903614459
450
434
  8.66474543707973
451
435
  ```
452
436
 
437
+ #### Example Demonstration 11 (engineering graphics)
438
+ ```python
439
+ from mathai import *
440
+ s = "0 -25 0 None None None None None None 0 None 55 75"
441
+ s = [None if item == "None" else parse(item) for item in s.split(" ")]
442
+ print(solve_graphics(*s))
443
+ ```
444
+
445
+ #### Output
446
+ ```
447
+ {'v_0': 0, 'v_1': -25, 'v_2': 0, 'v_9': 0, 'v_11': 55, 'v_12': 75, 'v_7': sqrt(2600), 'v_10': arcsin((sqrt(2600)/75)), 'v_8': 75*sqrt((1-((sqrt(2600)/75)^2))), 'v_6': 0, 'v_3': 0, 'v_4': -25+sqrt(2600), 'v_5': 75*sqrt((1-((sqrt(2600)/75)^2)))}
448
+ ```
449
+
453
450
  ### Questions solved using god() function
454
451
 
455
452
  #### Code
@@ -15,6 +15,8 @@ from .test import test
15
15
 
16
16
  from .decision import god, trig7
17
17
 
18
+ from .graphics import solve_graphics
19
+
18
20
  from .expand import expand
19
21
 
20
22
  from .ml import NeuralNetwork, diff_matrix_matrix
@@ -1,5 +1,4 @@
1
- import schemdraw
2
- import schemdraw.elements as elm
1
+ import random
3
2
  import copy
4
3
  from .base import *
5
4
  from .simplify import simplify
@@ -214,202 +213,197 @@ def find_resistance(circuit, start, end):
214
213
  for variable, value in solutions.items():
215
214
  if variable in vlist(current):
216
215
  current = replace(current, tree_form(variable), value)
217
- current = simplify(current)
218
- if vlist(current):
219
- return None
220
- if current == TreeNode("d_0"):
221
- return None
222
- return simplify(TreeNode("d_1") / current)
223
- def draw_circuit(graph):
224
- size = 80
225
- margin = 35
226
- spacing = 6
227
- positions = []
228
- n = graph.node_count
229
- side_counts = [n // 4] * 4
230
- for i in range(n % 4):
231
- side_counts[i] += 1
232
- top, right, bottom, left = side_counts
233
- for i in range(top):
234
- positions.append((margin, margin + i * spacing))
235
- for i in range(right):
236
- positions.append(
237
- (margin + i * spacing, size - margin - 1)
238
- )
239
- for i in range(bottom):
240
- positions.append(
241
- (size - margin - 1, size - margin - 1 - i * spacing)
242
- )
243
- for i in range(left):
244
- positions.append(
245
- (size - margin - 1 - i * spacing, margin)
246
- )
247
- if len(positions) != n:
248
- print("No circuit layout found.")
249
- return
250
- edges = []
251
- for edge in graph.edge_list:
252
- if not edge.edge:
253
- continue
254
- u, v = edge.edge
255
- if u == v:
256
- continue
257
- edges.append((u, v))
258
- def orientation(a, b, c):
259
- value = (
260
- (b[1] - a[1]) * (c[0] - b[0])
261
- - (b[0] - a[0]) * (c[1] - b[1])
262
- )
263
- if value == 0:
264
- return 0
265
- return 1 if value > 0 else 2
266
- def on_segment(a, b, c):
267
- return (
268
- min(a[0], c[0]) <= b[0] <= max(a[0], c[0])
269
- and
270
- min(a[1], c[1]) <= b[1] <= max(a[1], c[1])
271
- )
272
- def intersects(a, b, c, d):
273
- o1 = orientation(a, b, c)
274
- o2 = orientation(a, b, d)
275
- o3 = orientation(c, d, a)
276
- o4 = orientation(c, d, b)
277
- if o1 != o2 and o3 != o4:
278
- return True
279
- if o1 == 0 and on_segment(a, c, b):
280
- return True
281
- if o2 == 0 and on_segment(a, d, b):
282
- return True
283
- if o3 == 0 and on_segment(c, a, d):
284
- return True
285
- if o4 == 0 and on_segment(c, b, d):
286
- return True
216
+ current = simplify(TreeNode("d_1")/current)
217
+ 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:
287
228
  return False
288
- def edge_intersects_node(a, b, node):
289
- if node == a or node == b:
290
- return False
291
- x1, y1 = a
292
- x2, y2 = b
293
- x, y = node
294
- cross = (
295
- (x - x1) * (y2 - y1)
296
- - (y - y1) * (x2 - x1)
297
- )
298
- if cross != 0:
299
- return False
300
- return (
301
- min(x1, x2) <= x <= max(x1, x2)
302
- and
303
- min(y1, y2) <= y <= max(y1, y2)
304
- )
305
- def valid_edge(a, b, drawn_edges, node_positions):
306
- for node in node_positions.values():
307
- if edge_intersects_node(a, b, node):
308
- return False
309
- for c, d in drawn_edges:
310
- if (
311
- a == c or
312
- a == d or
313
- b == c or
314
- b == d
315
- ):
316
- continue
317
- if intersects(a, b, c, d):
318
- 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]):
319
232
  return True
320
- node_order = list(range(n))
321
- def try_permutation(order):
322
- node_positions = {
323
- node: positions[i]
324
- for i, node in enumerate(order)
325
- }
326
- drawn_edges = []
327
- ordered_edges = sorted(
328
- edges,
329
- key=lambda edge: (
330
- abs(
331
- node_positions[edge[0]][0]
332
- - node_positions[edge[1]][0]
333
- )
334
- +
335
- abs(
336
- node_positions[edge[0]][1]
337
- - node_positions[edge[1]][1]
338
- )
339
- ),
340
- reverse=True
341
- )
342
- for u, v in ordered_edges:
343
- a = node_positions[u]
344
- b = node_positions[v]
345
- if not valid_edge(
346
- a,
347
- b,
348
- drawn_edges,
349
- node_positions
350
- ):
351
- return None
352
- drawn_edges.append((a, b))
353
- return node_positions, drawn_edges
354
- def permutations(items):
355
- if len(items) <= 1:
356
- yield items
357
- return
358
- for i in range(len(items)):
359
- first = items[i]
360
- rest = items[:i] + items[i + 1:]
361
- for result in permutations(rest):
362
- yield [first] + result
363
- result = None
364
- for order in permutations(node_order):
365
- result = try_permutation(order)
366
- if result is not None:
367
- break
368
- if result is None:
369
- print("No circuit layout found.")
370
- return
371
- node_positions, drawn_edges = result
372
- d = schemdraw.Drawing()
373
- for edge in graph.edge_list:
374
- if not edge.edge:
375
- continue
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]
376
317
  u, v = edge.edge
377
- if u == v:
378
- continue
379
- start = node_positions[u]
380
- end = node_positions[v]
381
- if edge.edge_type == "resistor":
382
- element = (
383
- elm.Resistor()
384
- .at(start)
385
- .to(end)
386
- )
387
- if edge.value is not None:
388
- element.label(str(edge.value))
389
- elif edge.edge_type == "cell":
390
- element = (
391
- elm.Cell()
392
- .at(start)
393
- .to(end)
394
- )
395
- else:
396
- element = (
397
- elm.Line()
398
- .at(start)
399
- .to(end)
400
- )
401
- d.add(element)
402
- for node, position in node_positions.items():
403
- d.add(
404
- elm.Dot()
405
- .at(position)
406
- .label(chr(ord("A") + node))
407
- )
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
408
  d.draw()
409
- d.save("circuit.png")
410
- try:
411
- from IPython.display import Image, display
412
- display(Image("circuit.png"))
413
- except:
414
- pass
415
- return node_positions
409
+ return d
@@ -0,0 +1,42 @@
1
+ from .base import *
2
+ from .fraction import fraction
3
+ from .simplify import simplify
4
+ from .trig import trig0
5
+ import itertools
6
+ from .inverse import inverse
7
+ def solve_graphics(Ax, Ay, Az, Bx, By, Bz, BAx, BAy, BAz, phi, theta, fvl, length):
8
+ eq1 = TreeNode("f_eq", [TreeNode("v_6"), TreeNode("v_3")-TreeNode("v_0")])
9
+ eq2 = TreeNode("f_eq", [TreeNode("v_7"), TreeNode("v_4")-TreeNode("v_1")])
10
+ eq3 = TreeNode("f_eq", [TreeNode("v_8"), TreeNode("v_5")-TreeNode("v_2")])
11
+ eq4 = TreeNode("f_eq", [TreeNode("v_6"), TreeNode("v_9").fx("sin")*TreeNode("v_12")])
12
+ eq5 = TreeNode("f_eq", [TreeNode("v_7"), TreeNode("v_10").fx("sin")*TreeNode("v_12")])
13
+ eq6 = TreeNode("f_eq", [TreeNode("v_8"), (TreeNode("d_1") - TreeNode("v_9").fx("sin")**2 - TreeNode("v_10").fx("sin")**2).fx("sqrt")*TreeNode("v_12")])
14
+ eq7 = TreeNode("f_eq", [TreeNode("v_7"), (TreeNode("v_12")**2 - TreeNode("v_11")**2).fx("sqrt")])
15
+ q = operation("f_and", [eq1, eq2, eq3, eq4, eq5, eq6, eq7])
16
+ lst = [Ax, Ay, Az, Bx, By, Bz, BAx, BAy, BAz, phi, theta, fvl, length]
17
+ lst_map = {}
18
+ for index, item in enumerate(lst):
19
+ lst_map[index] = item
20
+ solution = {}
21
+ for i in range(len(lst_map.keys())):
22
+ if lst_map[i] is not None:
23
+ solution[f"v_{i}"] = lst_map[i]
24
+ done = True
25
+ q = simplify(q)
26
+ while done:
27
+ done = False
28
+ for i in range(len(q.children)):
29
+ item = q.children[i]
30
+ for key, item2 in solution.items():
31
+ item = replace(item, TreeNode(key), item2)
32
+ item = fraction(trig0(simplify(item)))
33
+ q.children[i] = item
34
+ if len(vlist(item)) == 1:
35
+ solution[vlist(item)[0]] = inverse(
36
+ item.children[0], vlist(item)[0]
37
+ )
38
+ done = True
39
+ break
40
+ if done:
41
+ continue
42
+ return solution
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Mathematics solving Ai tailored to NCERT
5
5
  Home-page: https://github.com/infinity390/mathai
6
6
  Requires-Python: >=3.7
@@ -423,37 +423,22 @@ answer
423
423
  ```python
424
424
  from mathai import *
425
425
  load_formula_from_file()
426
- wire_1 = Edge((0,1))
427
- ohm_10 = Edge((1,2), "resistor", TreeNode("d_10"))
428
- ohm_5 = Edge((2,3), "resistor", TreeNode("d_5"))
429
- ohm_6 = Edge((2,4), "resistor", TreeNode("d_6"))
430
- ohm_7 = Edge((4,5), "resistor", TreeNode("d_7"))
431
- ohm_8 = Edge((4,6), "resistor", TreeNode("d_8"))
432
- ohm_20 = Edge((6,7), "resistor", TreeNode("d_20"))
433
- wire_2 = Edge((7,5))
434
- wire_3 = Edge((3,5))
435
- wire_4 = Edge((3,8))
436
- edge_list = [wire_1, wire_2, wire_3, wire_4, ohm_5, ohm_6, ohm_7, ohm_8, ohm_10, ohm_20]
437
- graph = CircuitGraph(9,edge_list,{})
438
- print(compute(find_resistance(graph, 0,8)))
439
- draw_circuit(graph)
440
-
441
- wire_1 = Edge((0,1))
442
- ohm_5 = Edge((1,2), "resistor", TreeNode("d_5"))
443
- ohm_10 = Edge((2,3), "resistor", TreeNode("d_10"))
444
- ohm_11 = Edge((3,4), "resistor", TreeNode("d_11"))
445
- ohm_8 = Edge((2,5), "resistor", TreeNode("d_8"))
446
- ohm_7 = Edge((5,4), "resistor", TreeNode("d_7"))
447
- ohm_6 = Edge((1,6), "resistor", TreeNode("d_6"))
448
- ohm_8_2 = Edge((1,7), "resistor", TreeNode("d_8"))
449
- wire_2 = Edge((6,8))
450
- wire_3 = Edge((7,8))
451
- ohm_20 = Edge((8,4), "resistor", TreeNode("d_20"))
452
- wire_4 = Edge((4,9))
453
- 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]
454
- graph = CircuitGraph(10,edge_list,{})
426
+ wire_1 = Edge((0, 1))
427
+ ohm_5 = Edge((1, 2), "resistor", TreeNode("d_5"))
428
+ ohm_10 = Edge((2, 3), "resistor", TreeNode("d_10"))
429
+ ohm_11 = Edge((3, 4), "resistor", TreeNode("d_11"))
430
+ ohm_8 = Edge((2, 5), "resistor", TreeNode("d_8"))
431
+ ohm_7 = Edge((5, 4), "resistor", TreeNode("d_7"))
432
+ ohm_6 = Edge((1, 6), "resistor", TreeNode("d_6"))
433
+ ohm_8_2 = Edge((1, 7), "resistor", TreeNode("d_8"))
434
+ wire_2 = Edge((6, 8))
435
+ wire_3 = Edge((7, 8))
436
+ ohm_20 = Edge((8, 4), "resistor", TreeNode("d_20"))
437
+ wire_4 = Edge((4, 9))
438
+ 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
+ graph = CircuitGraph(10, edge_list, {})
455
440
  print(compute(find_resistance(graph, 0, 9)))
456
- draw_circuit(graph)
441
+ draw_circuit(graph, start=0, end=9, scale=3.0, grid_size=30)
457
442
  ```
458
443
 
459
444
  #### Output
@@ -462,10 +447,22 @@ draw_circuit(graph)
462
447
  loading formulas from file...
463
448
  done
464
449
 
465
- 13.493975903614459
466
450
  8.66474543707973
467
451
  ```
468
452
 
453
+ #### Example Demonstration 11 (engineering graphics)
454
+ ```python
455
+ from mathai import *
456
+ s = "0 -25 0 None None None None None None 0 None 55 75"
457
+ s = [None if item == "None" else parse(item) for item in s.split(" ")]
458
+ print(solve_graphics(*s))
459
+ ```
460
+
461
+ #### Output
462
+ ```
463
+ {'v_0': 0, 'v_1': -25, 'v_2': 0, 'v_9': 0, 'v_11': 55, 'v_12': 75, 'v_7': sqrt(2600), 'v_10': arcsin((sqrt(2600)/75)), 'v_8': 75*sqrt((1-((sqrt(2600)/75)^2))), 'v_6': 0, 'v_3': 0, 'v_4': -25+sqrt(2600), 'v_5': 75*sqrt((1-((sqrt(2600)/75)^2)))}
464
+ ```
465
+
469
466
  ### Questions solved using god() function
470
467
 
471
468
  #### Code
@@ -13,6 +13,7 @@ mathai/formula_compiler.py
13
13
  mathai/formula_data.py
14
14
  mathai/formula_interpretor.py
15
15
  mathai/fraction.py
16
+ mathai/graphics.py
16
17
  mathai/integrate.py
17
18
  mathai/inverse.py
18
19
  mathai/lambda_calculus.py
@@ -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.0",
5
+ version="2.2.2",
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",
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