File size: 11,642 Bytes
761e949
 
 
e3ba37d
67adba9
761e949
4c66c38
 
96569b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761e949
4c66c38
 
 
 
96569b8
761e949
 
 
 
 
 
 
 
 
 
7461bb9
 
 
761e949
 
 
67adba9
 
761e949
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4c66c38
e3ba37d
2bad1d3
e3ba37d
 
2bad1d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e3ba37d
2bad1d3
 
 
 
 
 
e3ba37d
2bad1d3
 
 
 
e3ba37d
2bad1d3
 
 
 
 
e3ba37d
 
2bad1d3
7461bb9
761e949
a11b9a1
 
761e949
7461bb9
8a81f3a
 
 
 
 
 
761e949
 
 
 
 
 
 
 
 
8a81f3a
 
 
 
761e949
ca22451
761e949
 
 
 
ca22451
 
 
 
761e949
ca22451
 
761e949
ca22451
 
761e949
 
ca22451
761e949
ca22451
f4b04e0
ca22451
 
 
 
 
 
 
761e949
 
ca22451
761e949
ca22451
 
 
761e949
ca22451
 
 
 
 
761e949
ca22451
 
761e949
ca22451
 
761e949
ca22451
 
 
 
761e949
ca22451
 
f4b04e0
ca22451
 
 
761e949
ca22451
 
 
 
761e949
ca22451
 
 
 
761e949
ca22451
 
 
 
 
765211f
ca22451
765211f
 
ca22451
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
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)}")