Spaces:
Sleeping
Sleeping
File size: 3,519 Bytes
7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 a8211b4 7813169 | 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 | import sympy as sp
import random
from typing import Dict, Any, Tuple
class TaskGenerationEngine:
def __init__(self):
self.x = sp.Symbol('x')
# Components for generating random functions F(x)
self.basic_functions = [
lambda x, c: x**c,
lambda x, c: sp.sin(c*x),
lambda x, c: sp.cos(c*x),
lambda x, c: sp.exp(c*x),
lambda x, c: sp.ln(sp.Abs(c*x))
]
def _score_difficulty(self, components: int, nesting: int) -> float:
"""D = num_components + degree_of_nesting * 2"""
return float(components + nesting * 2.0)
def generate_random_function(self, complexity: int) -> Tuple[Any, float]:
"""Generates a random F(x)."""
num_components = max(1, int(complexity / 2))
nesting = max(0, int(complexity / 4))
f_expr = 0
for _ in range(num_components):
comp_func = random.choice(self.basic_functions)
coeff = random.randint(1, 5)
term = comp_func(self.x, coeff)
# Apply nesting
for _ in range(nesting):
outer = random.choice(self.basic_functions)
term = outer(term, 1)
f_expr += random.randint(1, 10) * term
return f_expr, self._score_difficulty(num_components, nesting)
def generate_task(self, target_difficulty_band: float) -> Dict[str, Any]:
"""Provides an indefinite integral task."""
complexity = max(1, int(target_difficulty_band))
# 1. Generate F(x)
F_expr, diff = self.generate_random_function(complexity)
# 2. Differentiate to get the problem f(x)
f_expr = sp.diff(F_expr, self.x)
# 3. Format strings
problem_text = f"Find the indefinite integral: \int ({sp.pretty(f_expr)}) dx"
solution_text = f"{sp.simplify(F_expr)} + C"
return {
"problem": problem_text,
"difficulty": diff,
"solution": solution_text,
"type": "integration",
"sympy_F": F_expr,
"sympy_f": f_expr
}
def generate_variants(self, task: Dict[str, Any], count: int = 2) -> list[Dict[str, Any]]:
"""
LADDER Component: Recursive Decomposition for Integration.
Breaks down sums or simplifies coefficients.
"""
variants = []
F_expr = task.get("sympy_F")
if F_expr is None:
# Fallback if task was not generated by us
return [self.generate_task(max(1, task.get("difficulty", 2) - 2))]
# Recursive Rule 1: Linearity (split sums)
if isinstance(F_expr, sp.Add):
args = F_expr.args
for arg in args[:count]:
sub_F = arg
sub_f = sp.diff(sub_F, self.x)
variants.append({
"problem": f"Integrate step-variant: \int ({sp.pretty(sub_f)}) dx",
"solution": f"{sub_F} + C",
"difficulty": task["difficulty"] - 1.0,
"type": "integration",
"sympy_F": sub_F,
"sympy_f": sub_f
})
# Recursive Rule 2: Constant simplification
if not variants:
# Just return a simpler integral by reducing difficulty
variants.append(self.generate_task(max(1.0, task["difficulty"] - 2.0)))
return variants[:count]
|