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,sqrt, 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 'sqrt' in processed_expr.lower(): try: transformations = standard_transformations + (implicit_multiplication_application,) # Remove "sqrt" and parse the expression inside expr = sp.parse_expr(processed_expr.replace("sqrt", ""), transformations=transformations) sqrt_result = sp.sqrt(expr) # If it's sqrt(x^2), simplify it to |x| simplified_result = sp.simplify(sqrt_result) steps = [] steps.append(f"**Step 1:** Original expression: \n{to_latex(expr)}") # Case 1: Perfect Squares → Show exact value (e.g., sqrt(9) = ±3) if sqrt_result.is_Integer: steps.append(f"**Step 2:** √{to_latex(expr)} is a perfect square") steps.append(f"**Step 3:** Solution: \n±{to_latex(sqrt_result)}") solution = "\n".join(steps) # Case 2: Non-Perfect Squares → Show decimal value (e.g., sqrt(2) ≈ 1.41) elif sqrt_result.is_real and not sqrt_result.is_rational: decimal_value = float(sqrt_result.evalf()) steps.append(f"**Step 2:** √{to_latex(expr)} is not a perfect square") steps.append(f"**Step 3:** Approximate value: \n{decimal_value}") solution = "\n".join(steps) # Case 3: Expressions like √x² → |x| elif simplified_result != sqrt_result: steps.append(f"**Step 2:** Simplification using identity: \n{to_latex(simplified_result)}") solution = "\n".join(steps) # Case 4: General Expression → Return as-is else: steps.append(f"**Step 2:** Taking square root: \n{to_latex(sqrt_result)}") steps.append(f"**Step 3:** Considering both positive and negative roots: \n±{to_latex(sqrt_result)}") solution = "\n".join(steps) except Exception as e: solution = f"Error: {str(e)}" 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 solve_equation(equation_str): """Solve the given equation and return the solution.""" try: if '=' not in equation_str: return process_expression(equation_str) # Preprocess equation equation_str = preprocess_equation(equation_str) # Split equation into left and right parts left_side, right_side = [side.strip() for side in equation_str.split('=')] # Parse both sides with implicit multiplication transformations = standard_transformations + (implicit_multiplication_application,) left_expr = parse_expr(left_side, transformations=transformations) right_expr = parse_expr(right_side, transformations=transformations) equation = left_expr - right_expr # Solve the equation x = Symbol('x') solution = solve(equation, x) # Format solution if len(solution) == 0: return "No solution exists" elif len(solution) == 1: return f"x = {format_expression(solution[0])}" else: return "x = " + ", ".join([format_expression(sol) for sol in solution]) except Exception as e: raise Exception(f"Invalid equation format: {str(e)}") def generate_steps(equation_str): """Generate step-by-step solution for the equation or expression.""" steps = [] try: if '=' not in equation_str: steps.append(f"1. Original expression: {equation_str}") result = process_expression(equation_str) steps.append(f"2. Result: {result}") return steps # Preprocess equation processed_eq = preprocess_equation(equation_str) # Split equation into left and right parts left_side, right_side = [side.strip() for side in processed_eq.split('=')] # Parse expressions with implicit multiplication transformations = standard_transformations + (implicit_multiplication_application,) left_expr = parse_expr(left_side, transformations=transformations) right_expr = parse_expr(right_side, transformations=transformations) # Step 1: Show original equation steps.append(f"1. Original equation: {format_expression(left_expr)} = {format_expression(right_expr)}") # Step 2: Move all terms to left side equation = left_expr - right_expr steps.append(f"2. Move all terms to left side: {format_expression(equation)} = 0") # Step 3: Factor if possible factored = sp.factor(equation) if factored != equation: steps.append(f"3. Factor the equation: {format_expression(factored)} = 0") # Step 4: Solve x = Symbol('x') solution = solve(equation, x) steps.append(f"4. Solve for x: x = {', '.join([format_expression(sol) for sol in solution])}") # Step 5: Verify solutions steps.append("5. Verify solutions:") for sol in solution: result = equation.subs(x, sol) steps.append(f" When x = {format_expression(sol)}, equation equals {format_expression(result)}") return steps except Exception as e: raise Exception(f"Error generating steps: {str(e)}")