calculus-animator / core /detector.py
Rsan0948
Prepare for open source release v1.0.0
de8ccff
Raw
History Blame Contribute Delete
2.43 kB
import re
from enum import Enum, auto
from typing import Optional
class CalculusType(Enum):
DERIVATIVE = auto()
INTEGRAL_INDEFINITE = auto()
INTEGRAL_DEFINITE = auto()
LIMIT = auto()
SERIES = auto()
TAYLOR_SERIES = auto()
DIFFERENTIAL_EQ = auto()
SIMPLIFY = auto()
UNKNOWN = auto()
_TAG_MAP = {
"derivative": CalculusType.DERIVATIVE,
"integral": CalculusType.INTEGRAL_INDEFINITE,
"definite_integral": CalculusType.INTEGRAL_DEFINITE,
"limit": CalculusType.LIMIT,
"series": CalculusType.SERIES,
"taylor": CalculusType.TAYLOR_SERIES,
"ode": CalculusType.DIFFERENTIAL_EQ,
}
# Order matters — check definite integral before indefinite
_PATTERNS = [
(CalculusType.DIFFERENTIAL_EQ, [
r"\\frac\{dy\}\{dx\}\s*=", r"y''\s*[+\-=]", r"y'\s*[+\-=]",
]),
(CalculusType.DERIVATIVE, [
r"\\frac\{d", r"\\frac\{\\partial", r"'",
r"\bd(?:\^\d+)?\s*/\s*d[a-z](?:\^\d+)?\b",
]),
(CalculusType.INTEGRAL_DEFINITE, [
r"\\int_", r"\bint_", r"∫_",
]),
(CalculusType.INTEGRAL_INDEFINITE, [
r"\\int", r"\bint\b", r"∫",
]),
(CalculusType.LIMIT, [
r"\\lim", r"\blim\b", r"\blim_", r"\blim\s*[\(\{]",
]),
(CalculusType.SERIES, [
r"\\sum", r"\\prod",
]),
(CalculusType.TAYLOR_SERIES, [
r"(?i)taylor", r"(?i)maclaurin",
]),
]
class TypeDetector:
def detect(self, latex: str, explicit_tag: Optional[str] = None) -> CalculusType:
"""Detect the calculus operation type from a LaTeX string.
Pattern matching is ordered so that more specific forms (e.g. definite
integral) are checked before generic ones (indefinite integral).
Falls back to ``SIMPLIFY`` when no pattern matches.
Args:
latex: The raw LaTeX expression to inspect.
explicit_tag: Optional string override (e.g. ``"derivative"``,
``"definite_integral"``). When provided, regex scanning is
skipped entirely.
Returns:
A ``CalculusType`` enum member representing the detected operation.
"""
if explicit_tag:
return _TAG_MAP.get(explicit_tag.lower(), CalculusType.UNKNOWN)
for calc_type, patterns in _PATTERNS:
for p in patterns:
if re.search(p, latex):
return calc_type
return CalculusType.SIMPLIFY