Spaces:
Sleeping
Sleeping
Download src/math_env/grader.py from emrekuruu/math-openenv: direct link, hf CLI and curl.
- Browser
- Download file 2.38 kB
-
https://huggingface.co/spaces/emrekuruu/math-openenv/resolve/main/src/math_env/grader.py
- Command line
-
hf download hf://spaces/emrekuruu/math-openenv/src/math_env/grader.py
-
curl -L -o grader.py https://huggingface.co/spaces/emrekuruu/math-openenv/resolve/main/src/math_env/grader.py
2.38 kB
| """MATH final-answer normalization and equality grading.""" | |
| from __future__ import annotations | |
| import re | |
| class InfraError(RuntimeError): | |
| """The server could not grade a submission because its own data is invalid.""" | |
| _STRIP_RE = re.compile(r"[\\,;\s]") | |
| def normalize_answer(value: object) -> str: | |
| """Canonicalize a MATH final-answer string for comparison. | |
| Lowercases, converts LaTeX fractions/sqrt to plain forms, collapses whitespace/commas/ | |
| backslashes, and trims stray braces/dollars so equivalent LaTeX and plain forms of the | |
| same value agree. This is deliberately tolerant; it is not a full LaTeX semantic | |
| normalizer. | |
| """ | |
| text = str(value).strip() | |
| # Strip only dollar signs (and any outer paired braces like ${...}$); internal braces matter. | |
| text = text.strip("$") | |
| while text.startswith("{") and text.endswith("}") and "\\" not in text[:1]: | |
| text = text[1:-1].strip() | |
| # Convert \frac{a}{b}, \dfrac, \tfrac -> a/b (recursively, innermost first). | |
| for _ in range(8): | |
| new = re.sub( | |
| r"\\dfrac|\\tfrac|\\frac", | |
| r"\\frac", | |
| text, | |
| ) | |
| new = re.sub( | |
| r"\\frac\s*\{([^{}]*)\}\s*\{([^{}]*)\}", | |
| lambda m: f"{m.group(1).strip()}/{m.group(2).strip()}", | |
| new, | |
| ) | |
| # \sqrt{x} -> sqrt(x) | |
| new = re.sub( | |
| r"\\sqrt(?:\[[^\]]*\])?\s*\{([^{}]*)\}", | |
| r"sqrt(\1)", | |
| new, | |
| ) | |
| # \left / \right -> empty | |
| new = re.sub(r"\\left|\\right", "", new) | |
| if new == text: | |
| break | |
| text = new | |
| text = _STRIP_RE.sub("", text) | |
| text = text.strip("$") | |
| text = re.sub(r"\s+", "", text) | |
| return text.lower() | |
| def compare_answers(predicted: object, expected: str) -> bool: | |
| return normalize_answer(predicted) == normalize_answer(expected) | |
| def verification_report(predicted: object, expected: str) -> str: | |
| """Render a short, non-revealing grader report without leaking the reference value.""" | |
| if compare_answers(predicted, expected): | |
| return "## Answer Verification\nNormalized match: PASS\n" | |
| return ( | |
| "## Answer Verification\nNormalized match: FAIL\n" | |
| "Predicted was accepted as a valid attempt; the normalized form did not equal the " | |
| "reference answer. No reference value is exposed.\n" | |
| ) |