Spaces:
Running
Running
Update app.py
Browse filesKey fixes:
1. Fixed integral parsing:
Used raw strings for regex patterns
Added support for both ∫ and \int symbols
Simplified the integrand extraction
2. Improved differentiation handling:
Better function extraction
Simplified query format
Added more specific error messages
3. Enhanced MVT verification:
Added special handling for sqrt expressions
Improved numerical comparison
Better extraction of the function and interval
Two-step process: first get derivative, then solve equation
app.py
CHANGED
@@ -67,71 +67,62 @@ def verify_solution(problem, answer):
|
|
67 |
clean_problem = problem.replace('$$', '').replace('$', '').strip()
|
68 |
|
69 |
# Case 1: Definite Integral
|
70 |
-
if '∫' in clean_problem or '
|
71 |
-
#
|
72 |
-
integrand_match = re.search(r'
|
73 |
if integrand_match:
|
74 |
lower, upper, integrand = integrand_match.groups()
|
75 |
-
#
|
|
|
76 |
query = f"integrate {integrand} from {lower} to {upper}"
|
|
|
77 |
else:
|
78 |
-
#
|
79 |
-
integrand_match = re.search(r'
|
80 |
if integrand_match:
|
81 |
-
|
82 |
-
query = f"integrate {integrand} from
|
83 |
-
|
84 |
-
return {
|
85 |
-
'verified': False,
|
86 |
-
'wolfram_solution': None,
|
87 |
-
'error': "Could not parse integral expression"
|
88 |
-
}
|
89 |
|
90 |
-
# Case 2:
|
91 |
-
elif '
|
92 |
-
#
|
93 |
-
|
94 |
-
if
|
95 |
-
|
96 |
-
query = f"
|
97 |
-
|
98 |
-
return {
|
99 |
-
'verified': False,
|
100 |
-
'wolfram_solution': None,
|
101 |
-
'error': "Could not parse differential equation"
|
102 |
-
}
|
103 |
|
104 |
# Case 3: Mean Value Theorem
|
105 |
elif 'Mean Value Theorem' in clean_problem:
|
106 |
-
# Extract function and interval
|
107 |
func_match = re.search(r'f\(x\)\s*=\s*(.*?)\s+on', clean_problem)
|
108 |
-
interval_match = re.search(r'\[(
|
109 |
if func_match and interval_match:
|
110 |
-
func = func_match.group(1)
|
111 |
a, b = interval_match.groups()
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
125 |
# Ensure query is not empty
|
126 |
if not query.strip():
|
127 |
return {
|
128 |
'verified': False,
|
129 |
'wolfram_solution': None,
|
130 |
-
'error': "Could not generate valid query"
|
131 |
}
|
132 |
|
133 |
-
print(f"
|
134 |
-
|
135 |
result = wolfram_client.query(query)
|
136 |
|
137 |
if not result.success:
|
@@ -143,10 +134,30 @@ def verify_solution(problem, answer):
|
|
143 |
|
144 |
# Process the result
|
145 |
for pod in result.pods:
|
146 |
-
if pod.title in ['Result', 'Solution', 'Numerical result', 'Decimal approximation', 'Definite integral']:
|
147 |
wolfram_answer = pod.text
|
148 |
print(f"Wolfram pod {pod.title}: {wolfram_answer}")
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
# Handle numerical answers
|
151 |
if str(answer).replace('.', '').isdigit():
|
152 |
wolfram_nums = re.findall(r'[-+]?(?:\d*\.)?\d+', wolfram_answer)
|
@@ -177,7 +188,6 @@ def verify_solution(problem, answer):
|
|
177 |
}
|
178 |
|
179 |
except Exception as e:
|
180 |
-
# Now query will always be defined when we get here
|
181 |
error_msg = f"Error during verification: {str(e)}"
|
182 |
if query:
|
183 |
error_msg += f"\nQuery attempted: {query}"
|
|
|
67 |
clean_problem = problem.replace('$$', '').replace('$', '').strip()
|
68 |
|
69 |
# Case 1: Definite Integral
|
70 |
+
if 'integral' in clean_problem.lower() or '∫' in clean_problem or '\int' in clean_problem:
|
71 |
+
# Use raw string for regex to avoid escape issues
|
72 |
+
integrand_match = re.search(r'(?:\int|∫)_(\d+)\^(\d+)\s*\(?([\dx+\s]+)\)?\s*dx', clean_problem, re.UNICODE)
|
73 |
if integrand_match:
|
74 |
lower, upper, integrand = integrand_match.groups()
|
75 |
+
# Clean up the integrand
|
76 |
+
integrand = integrand.replace(' ', '')
|
77 |
query = f"integrate {integrand} from {lower} to {upper}"
|
78 |
+
print(f"Integral query: {query}")
|
79 |
else:
|
80 |
+
# Fallback for simpler pattern
|
81 |
+
integrand_match = re.search(r'(?:\int|∫).*?\(([\dx+\s]+)\)\s*dx', clean_problem, re.UNICODE)
|
82 |
if integrand_match:
|
83 |
+
integrand = integrand_match.group(1).replace(' ', '')
|
84 |
+
query = f"integrate {integrand} from 0 to 1" # Common default bounds
|
85 |
+
print(f"Fallback integral query: {query}")
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
+
# Case 2: Simple Differentiation
|
88 |
+
elif 'derivative' in clean_problem.lower() or 'd/dx' in clean_problem:
|
89 |
+
# Look for function after equals sign or f(x) =
|
90 |
+
func_match = re.search(r'[f\(x\)\s*=\s*](.*?)$', clean_problem)
|
91 |
+
if func_match:
|
92 |
+
func = func_match.group(1).strip()
|
93 |
+
query = f"derivative of {func}"
|
94 |
+
print(f"Derivative query: {query}")
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
# Case 3: Mean Value Theorem
|
97 |
elif 'Mean Value Theorem' in clean_problem:
|
|
|
98 |
func_match = re.search(r'f\(x\)\s*=\s*(.*?)\s+on', clean_problem)
|
99 |
+
interval_match = re.search(r'\[(\d+),\s*(\d+)\]', clean_problem)
|
100 |
if func_match and interval_match:
|
101 |
+
func = func_match.group(1).strip()
|
102 |
a, b = interval_match.groups()
|
103 |
+
# Calculate f'(x) first
|
104 |
+
derivative_query = f"derivative of {func}"
|
105 |
+
print(f"MVT derivative query: {derivative_query}")
|
106 |
+
derivative_result = wolfram_client.query(derivative_query)
|
107 |
+
|
108 |
+
if derivative_result.success:
|
109 |
+
for pod in derivative_result.pods:
|
110 |
+
if pod.title in ['Derivative']:
|
111 |
+
derivative = pod.text
|
112 |
+
# Now calculate [f(b) - f(a)]/(b-a)
|
113 |
+
query = f"solve {derivative} = ({func.replace('x', b)} - {func.replace('x', a)})/({b} - {a})"
|
114 |
+
print(f"MVT final query: {query}")
|
115 |
+
break
|
116 |
+
|
117 |
# Ensure query is not empty
|
118 |
if not query.strip():
|
119 |
return {
|
120 |
'verified': False,
|
121 |
'wolfram_solution': None,
|
122 |
+
'error': "Could not generate valid query from problem"
|
123 |
}
|
124 |
|
125 |
+
print(f"Final query to Wolfram Alpha: {query}")
|
|
|
126 |
result = wolfram_client.query(query)
|
127 |
|
128 |
if not result.success:
|
|
|
134 |
|
135 |
# Process the result
|
136 |
for pod in result.pods:
|
137 |
+
if pod.title in ['Result', 'Solution', 'Numerical result', 'Decimal approximation', 'Definite integral', 'Solutions']:
|
138 |
wolfram_answer = pod.text
|
139 |
print(f"Wolfram pod {pod.title}: {wolfram_answer}")
|
140 |
|
141 |
+
# For MVT problems, handle sqrt expressions
|
142 |
+
if 'Mean Value Theorem' in clean_problem:
|
143 |
+
# Convert both answers to decimal for comparison
|
144 |
+
if 'sqrt' in str(answer).lower():
|
145 |
+
# Convert sqrt expression to decimal
|
146 |
+
sqrt_match = re.search(r'sqrt\((\d+)/(\d+)\)', str(answer))
|
147 |
+
if sqrt_match:
|
148 |
+
num, denom = map(float, sqrt_match.groups())
|
149 |
+
user_value = (num/denom)**0.5
|
150 |
+
# Look for decimal in Wolfram result
|
151 |
+
wolfram_nums = re.findall(r'[-+]?(?:\d*\.)?\d+', wolfram_answer)
|
152 |
+
if wolfram_nums:
|
153 |
+
wolfram_value = float(wolfram_nums[0])
|
154 |
+
is_verified = abs(wolfram_value - user_value) < 0.01
|
155 |
+
return {
|
156 |
+
'verified': is_verified,
|
157 |
+
'wolfram_solution': wolfram_answer,
|
158 |
+
'error': None
|
159 |
+
}
|
160 |
+
|
161 |
# Handle numerical answers
|
162 |
if str(answer).replace('.', '').isdigit():
|
163 |
wolfram_nums = re.findall(r'[-+]?(?:\d*\.)?\d+', wolfram_answer)
|
|
|
188 |
}
|
189 |
|
190 |
except Exception as e:
|
|
|
191 |
error_msg = f"Error during verification: {str(e)}"
|
192 |
if query:
|
193 |
error_msg += f"\nQuery attempted: {query}"
|