import sympy as sp from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application from sympy.solvers import solve from sympy import integrate, diff, latex,simplify, expand, log, exp, sin, cos, tan, asin, acos, atan, Symbol, factorial, laplace_transform import re def format_expression(expr): latex_expr = latex(expr) replacements = { '**': '^', # Power notation '*x': 'x', # Remove unnecessary multiplication signs '*(': '(', # Remove multiplication before parentheses 'exp': 'e^', # Exponential notation 'sqrt': '√', # Square root 'factorial': '!', # Factorial symbol 'gamma': 'Γ', # Gamma function 'Gamma': 'Γ', # Sometimes SymPy capitalizes it 'fresnels': 'S', # Fresnel S integral 'fresnelc': 'C', # Fresnel C integral 'hyper': '₁F₂', # Generalized hypergeometric function 'log': 'ln', # Natural logarithm 'oo': '∞', # Infinity symbol 'pi': 'π', # Pi symbol 'E': 'ℯ', # Euler's constant 'I': '𝒊', # Imaginary unit 'Abs': '|', # Absolute value 'Integral': '∫', # Integral symbol 'Derivative': 'd/dx', # Differentiation 'Sum': 'Σ', # Summation symbol 'Product': '∏', # Product symbol 'sin': 'sin', 'cos': 'cos', 'tan': 'tan', # Trig functions (unchanged) 'asin': 'sin⁻¹', 'acos': 'cos⁻¹', 'atan': 'tan⁻¹', # Inverse trig 'sinh': 'sinh', 'cosh': 'cosh', 'tanh': 'tanh', # Hyperbolic trig 'asinh': 'sinh⁻¹', 'acosh': 'cosh⁻¹', 'atanh': 'tanh⁻¹', # Inverse hyperbolic trig 'diff': 'd/dx', # Derivative notation 'integrate': '∫', # Integral notation 'Limit': 'lim', # Limit notation 'floor': '⌊', # Floor function 'ceiling': '⌈', # Ceiling function 'mod': 'mod', # Modulus (unchanged) 'Re': 'ℜ', # Real part 'Im': 'ℑ' # Imaginary part } for old, new in replacements.items(): latex_expr = latex_expr.replace(old, new) return f"$$ {latex_expr} $$" def preprocess_equation(equation_str): """Convert user-friendly equation format to SymPy format.""" try: # Replace common mathematical notations replacements = { '^': '**', 'sin⁻¹': 'asin', 'cos⁻¹': 'acos', 'tan⁻¹': 'atan', 'e^': 'exp', 'ln': 'log', # Convert ln to log (SymPy default) '√': 'sqrt', # Convert square root symbol to sqrt() '!': '.factorial()', # Convert factorial to function call } for old, new in replacements.items(): equation_str = equation_str.replace(old, new) equation_str = re.sub(r'(\d+)!', r'factorial(\1)', equation_str) # Handle exponential expressions if 'exp' in equation_str: parts = equation_str.split('exp') for i in range(1, len(parts)): if parts[i] and parts[i][0] != '(': parts[i] = '(' + parts[i] if '=' in parts[i]: exp_part, rest = parts[i].split('=', 1) parts[i] = exp_part + ')=' + rest else: parts[i] = parts[i] + ')' equation_str = 'exp'.join(parts) # Add multiplication symbol where needed processed = '' i = 0 while i < len(equation_str): if i + 1 < len(equation_str): if equation_str[i].isdigit() and equation_str[i+1] == 'x': processed += equation_str[i] + '*' i += 1 continue processed += equation_str[i] i += 1 return processed except Exception as e: raise Exception(f"Error in equation format: {str(e)}") def process_expression(expr_str): """Process mathematical expressions without equations.""" try: processed_expr = preprocess_equation(expr_str) x = Symbol('x') if expr_str.startswith('∫'): # Integration expr_to_integrate = processed_expr[1:].strip() expr = parse_expr(expr_to_integrate, transformations=(standard_transformations + (implicit_multiplication_application,))) result = integrate(expr, x) return f"∫{format_expression(expr)} = {format_expression(result)}" elif expr_str.startswith('d/dx'): # Differentiation expr_to_diff = processed_expr[4:].strip() if expr_to_diff.startswith('(') and expr_to_diff.endswith(')'): expr_to_diff = expr_to_diff[1:-1] expr = parse_expr(expr_to_diff, transformations=(standard_transformations + (implicit_multiplication_application,))) result = diff(expr, x) return f"d/dx({format_expression(expr)}) = {format_expression(result)}" elif 'factorial' in processed_expr: # Factorial case expr = parse_expr(processed_expr, transformations=(standard_transformations + (implicit_multiplication_application,))) result = expr.doit() # Compute the factorial correctly return f"{format_expression(expr)} = {result}" elif '/' in expr_str: # Handle fractions and return decimal expr = parse_expr(processed_expr, transformations=(standard_transformations + (implicit_multiplication_application,))) simplified = simplify(expr) decimal_value = float(simplified) return f"Simplified: {format_expression(simplified)}\nDecimal: {decimal_value}" else: # Regular expression simplification expr = parse_expr(processed_expr, transformations=(standard_transformations + (implicit_multiplication_application,))) simplified = simplify(expr) expanded = expand(simplified) return f"Simplified: {format_expression(simplified)}\nExpanded: {format_expression(expanded)}" except Exception as e: raise Exception(f"Error processing expression: {str(e)}") except Exception as e: raise Exception(f"Error processing expression: {str(e)}") def to_latex(expr): """Converts a SymPy expression into LaTeX format.""" return f"$$ {sp.latex(expr)} $$" def solve_equation(equation_str): """Solves an equation and returns a detailed LaTeX-formatted step-by-step solution.""" try: if '=' not in equation_str: return process_expression(equation_str) left_side, right_side = [side.strip() for side in equation_str.split('=')] transformations = standard_transformations + (implicit_multiplication_application,) left_expr = sp.parse_expr(left_side, transformations=transformations) right_expr = sp.parse_expr(right_side, transformations=transformations) equation = left_expr - right_expr x = Symbol('x') solutions = solve(equation, x) steps = [] steps.append(f"**Step 1:** Original equation: \n{to_latex(left_expr)} = {to_latex(right_expr)}") steps.append(f"**Step 2:** Move all terms to one side: \n{to_latex(equation)} = 0") factored = sp.factor(equation) if factored != equation: steps.append(f"**Step 3:** Factorizing the equation: \n{to_latex(factored)} = 0") steps.append(f"**Step 4:** Solving for x:") for sol in solutions: steps.append(f" x = {to_latex(sol)}") steps.append("**Step 5:** Verification:") for sol in solutions: verification = equation.subs(x, sol) steps.append(f" When x = {to_latex(sol)}, the equation evaluates to {to_latex(verification)}") return "\n".join(steps) except Exception as e: return f"Error: {str(e)}" def integrate_expression(expression_str): """Computes the integral of a given expression and provides detailed LaTeX-formatted steps.""" try: x = Symbol('x') expr = sp.parse_expr(expression_str, transformations=standard_transformations + (implicit_multiplication_application,)) steps = [] steps.append(f"**Step 1:** Original integral: \n$$ \\int {sp.latex(expr)} \\,dx $$") if '^' in expression_str: steps.append("**Step 2:** Checking if substitution is needed.") result = integrate(expr, x) steps.append(f"**Step 3:** Applying integration formula(s):") steps.append(f"$$ \\int f(x) \\,dx = F(x) + C $$") steps.append(f"**Step 4:** Solution: \n$$ {sp.latex(result)} + C $$") return "\n".join(steps) except Exception as e: return f"Error: {str(e)}" def laplace_transform_expression(expression_str): """Computes the Laplace transform of a given expression with LaTeX-formatted steps.""" try: t, s = sp.symbols('t s') expr = sp.parse_expr(expression_str, transformations=standard_transformations + (implicit_multiplication_application,)) steps = [] steps.append(f"**Step 1:** Original function: \n$$ \\mathcal{L}\\{{ {sp.latex(expr)} \\}}(t) $$") L_transform = laplace_transform(expr, t, s, noconds=True) steps.append(f"**Step 2:** Applying Laplace Transform:") steps.append("$$ \\mathcal{L}\\{ f(t) \\} = \\int_{0}^{\\infty} e^{-st} f(t) \\,dt $$") steps.append(f"**Step 3:** Solution: \n$$ {sp.latex(L_transform)} $$") return "\n".join(steps) except Exception as e: return f"Error: {str(e)}" def process_input(equation): """Determine whether the input is an equation, an integral, or a Laplace transform.""" try: if "laplace" in equation.lower(): solution = laplace_transform_expression(equation) elif "integrate" in equation.lower(): solution = integrate_expression(equation) else: solution = solve_equation(equation) return solution except Exception as e: return f"Error processing input: {str(e)}"