MathSolver / solver.py
Taizun's picture
Update solver.py
67adba9 verified
raw
history blame
8.06 kB
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, simplify, expand, log, exp, sin, cos, tan, asin, acos, atan, Symbol, factorial, laplace_transform
import re
def format_expression(expr):
"""Format expression to make it more readable."""
# Convert string representation to a more readable format
str_expr = str(expr)
replacements = {
'**': '^',
'*x': 'x',
'exp': 'e^',
'sqrt': '√',
'factorial': '!'
}
for old, new in replacements.items():
str_expr = str_expr.replace(old, new)
return str_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() # Evaluate factorial properly
return f"{format_expression(expr)} = {format_expression(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)}")