KingOfThoughtFleuren/aetherius-cognitive-systems
0
1# ===== FILE: math_kernel.py =====2# Author: Jonathan Wayne Fleuren (Aetherius Cognitive Systems) & Antigravity (Autonomous Pair AI Engine)3# Date: July 20264 5"""6Aetherius Math Kernel — SymPy Formal Algebra Computation Engine7Provides exact symbolic mathematics, calculus derivatives, integrals, and system equation solving8for arbitrary numbers of equations (M) and variables (N).9Supports implicit multiplication (e.g. 2x -> 2*x) and caret exponentiation (e.g. x^2 -> x**2).10"""11 12import sympy as sp13from sympy.parsing.sympy_parser import (14 parse_expr, 15 standard_transformations, 16 implicit_multiplication_application, 17 convert_xor18)19from typing import Dict, Any, Union, List, Tuple20 21TRANSFORMATIONS = standard_transformations + (implicit_multiplication_application, convert_xor)22 23 24def _parse_single_expr(expr_str: str) -> sp.Expr:25 """Safely parses a mathematical string expression or equality into a SymPy object with implicit multiplication & caret power support."""26 expr_str = str(expr_str).strip()27 if not expr_str:28 raise ValueError("Empty mathematical expression provided.")29 30 if "=" in expr_str and not expr_str.startswith("sp.Eq"):31 parts = expr_str.split("=")32 if len(parts) == 2:33 lhs = parse_expr(parts[0].strip(), transformations=TRANSFORMATIONS)34 rhs = parse_expr(parts[1].strip(), transformations=TRANSFORMATIONS)35 return sp.Eq(lhs, rhs)36 else:37 raise ValueError(f"Invalid equality syntax with multiple '=' signs in '{expr_str}'")38 39 return parse_expr(expr_str, transformations=TRANSFORMATIONS)40 41 42def _prepare_inputs(43 expr: Union[str, List[str], Tuple[str, ...]], 44 vars_input: Union[str, List[str], Tuple[str, ...], None] = None45) -> Tuple[List[sp.Expr], List[sp.Symbol]]:46 """Normalizes expressions and extracts or builds the set of SymPy variable symbols."""47 if isinstance(expr, str):48 clean_e = expr.strip()49 if clean_e.startswith("[") and clean_e.endswith("]"):50 clean_e = clean_e[1:-1]51 elif clean_e.startswith("(") and clean_e.endswith(")"):52 clean_e = clean_e[1:-1]53 54 raw_list = [e.strip() for e in clean_e.replace("\n", ";").split(",") if e.strip()]55 elif isinstance(expr, (list, tuple)):56 raw_list = [str(e).strip() for e in expr if str(e).strip()]57 else:58 raw_list = [str(expr).strip()]59 60 parsed_exprs = []61 for e in raw_list:62 parsed_e = _parse_single_expr(e)63 if isinstance(parsed_e, (list, tuple)):64 parsed_exprs.extend(parsed_e)65 else:66 parsed_exprs.append(parsed_e)67 68 symbols = []69 if vars_input is not None:70 if isinstance(vars_input, str):71 clean_v = vars_input.strip()72 if clean_v.startswith("[") and clean_v.endswith("]"):73 clean_v = clean_v[1:-1]74 elif clean_v.startswith("(") and clean_v.endswith(")"):75 clean_v = clean_v[1:-1]76 var_names = [v.strip() for v in clean_v.split(",") if v.strip()]77 elif isinstance(vars_input, (list, tuple)):78 var_names = [str(v).strip().strip("[]()") for v in vars_input if str(v).strip()]79 else:80 var_names = [str(vars_input).strip()]81 82 symbols = [sp.Symbol(v) for v in var_names if v]83 84 if not symbols:85 all_symbols = set()86 for pe in parsed_exprs:87 if hasattr(pe, "free_symbols"):88 all_symbols.update(pe.free_symbols)89 symbols = sorted(list(all_symbols), key=lambda s: s.name)90 91 if not symbols:92 symbols = [sp.Symbol("x")]93 94 return parsed_exprs, symbols95 96 97prepare_inputs = _prepare_inputs98 99 100def compute(101 task: str, 102 expr: Union[str, List[str], Tuple[str, ...]], 103 var: Union[str, List[str], Tuple[str, ...], None] = None, 104 lower: Union[float, str, None] = None, 105 upper: Union[float, str, None] = None106) -> Dict[str, Any]:107 """Core symbolic algebra calculation function."""108 task_clean = str(task).lower().strip()109 parsed_exprs, symbols = _prepare_inputs(expr, var)110 111 if task_clean == "solve":112 system = parsed_exprs[0] if len(parsed_exprs) == 1 else parsed_exprs113 target_vars = symbols[0] if (len(symbols) == 1 and len(parsed_exprs) == 1) else symbols114 115 res = sp.solve(system, target_vars, dict=True)116 117 if not res and len(parsed_exprs) > 1:118 try:119 res = sp.linsolve(parsed_exprs, symbols)120 except Exception:121 try:122 res = sp.nonlinsolve(parsed_exprs, symbols)123 except Exception:124 res = []125 126 return {127 "task": task_clean,128 "num_equations": len(parsed_exprs),129 "num_variables": len(symbols),130 "input_expr": [str(e) for e in parsed_exprs],131 "variables": [s.name for s in symbols],132 "result": str(res),133 "latex": sp.latex(res)134 }135 136 elif task_clean == "derivative":137 if len(parsed_exprs) == 1 and len(symbols) == 1:138 target = parsed_exprs[0]139 raw_expr = target.lhs - target.rhs if isinstance(target, sp.Eq) else target140 res = sp.diff(raw_expr, symbols[0])141 elif len(parsed_exprs) == 1 and len(symbols) > 1:142 target = parsed_exprs[0]143 raw_expr = target.lhs - target.rhs if isinstance(target, sp.Eq) else target144 res = [sp.diff(raw_expr, v) for v in symbols]145 else:146 raw_exprs = [e.lhs - e.rhs if isinstance(e, sp.Eq) else e for e in parsed_exprs]147 matrix_expr = sp.Matrix(raw_exprs)148 res = matrix_expr.jacobian(symbols)149 150 return {151 "task": task_clean,152 "num_equations": len(parsed_exprs),153 "num_variables": len(symbols),154 "input_expr": [str(e) for e in parsed_exprs],155 "variables": [s.name for s in symbols],156 "result": str(res),157 "latex": sp.latex(res)158 }159 160 elif task_clean == "integral":161 target = parsed_exprs[0]162 raw_expr = target.lhs - target.rhs if isinstance(target, sp.Eq) else target163 164 if lower is not None and upper is not None:165 l_val, u_val = sp.sympify(str(lower)), sp.sympify(str(upper))166 res = sp.integrate(raw_expr, (symbols[0], l_val, u_val))167 else:168 res = raw_expr169 for sym in symbols:170 res = sp.integrate(res, sym)171 172 return {173 "task": task_clean,174 "num_equations": len(parsed_exprs),175 "num_variables": len(symbols),176 "input_expr": str(raw_expr),177 "variables": [s.name for s in symbols],178 "result": str(res),179 "latex": sp.latex(res)180 }181 182 else:183 simplified = []184 for e in parsed_exprs:185 raw_e = e.lhs - e.rhs if isinstance(e, sp.Eq) else e186 simplified.append(sp.simplify(raw_e))187 res = simplified[0] if len(simplified) == 1 else simplified188 189 return {190 "task": task_clean,191 "num_equations": len(parsed_exprs),192 "num_variables": len(symbols),193 "input_expr": [str(e) for e in parsed_exprs],194 "variables": [s.name for s in symbols],195 "result": str(res),196 "latex": sp.latex(res)197 }