Something went wrong. Try again.
math snipping extension
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091r"""End-to-end oracle: does our converted integrand match an independent solver?
Symbolab's `getImageId` endpoint is unauthenticated and returns both the OCR'dLaTeX and a final antiderivative. Differentiating that antiderivative shouldgive back the integrand we produced. Nothing in that chain shares code with us,so a match exercises OCR, normalisation, parsing and printing at once.
This is a development tool, not part of the service. It sends images to a thirdparty; run it on your own screenshots only.
uv run python scripts/crosscheck.py shot.png [more.png ...]"""
from __future__ import annotations
import sysfrom pathlib import Path
import requestsfrom sympy import Symbol, diff
from integrand.convert import ConvertError, convertfrom integrand.equivalence import agreefrom integrand.normalize import normalize
ENDPOINT = "https://www.symbolab.com/api/getImageId"
def ocr(path: Path) -> dict: response = requests.post( ENDPOINT, params={"sessionid": "1", "language": "en"}, files={"data": (path.name, path.read_bytes(), "image/jpeg")}, timeout=30, ) response.raise_for_status() return response.json()
def antiderivative_matches(solution_latex: str, integrand, var) -> bool | None: """Strip the constant of integration, differentiate, compare.
Returns None when the solution itself is beyond our parser, which is a limitation of the check rather than a failure of the conversion. """ from sympy.parsing.latex import parse_latex
stripped = normalize(solution_latex).replace("+C", "").replace("+c", "").strip() try: parsed = parse_latex(stripped) except Exception: return None # abs() only has a sensible derivative over the reals, and parse_latex # hands back symbols with no assumptions at all. real = Symbol(var.name, real=True) return agree(diff(parsed.subs(var, real), real), integrand.subs(var, real), real)
def main(paths: list[str]) -> int: failures = 0 for raw in paths: path = Path(raw) seen = ocr(path) print(f"{path.name}\n latex {seen['latex']}")
try: result = convert(seen["latex"]) except ConvertError as exc: print(f" REJECTED {exc.code}: {exc.detail}\n") failures += 1 continue
print(f" infix {result.infix}") print(f" verified {result.verified}")
from sympy.parsing.latex import parse_latex
integrand = parse_latex(normalize(seen["latex"])).function agrees = antiderivative_matches(seen["solution"], integrand, Symbol(result.var)) label = {True: "agrees", False: "DISAGREES", None: "unparseable"}[agrees] print(f" oracle {label} ({seen['solution']})\n") if agrees is False or not result.verified: failures += 1
print(f"{len(paths) - failures}/{len(paths)} clean") return 1 if failures else 0
if __name__ == "__main__": sys.exit(main(sys.argv[1:] or ["-"]))