statement-to-tikz / tests /test_solver.py
will702's picture
Upload folder using huggingface_hub
eab734a verified
Raw
History Blame Contribute Delete
2.33 kB
"""Solver unit tests."""
from __future__ import annotations
import math
import pytest
from helpers import load_fixture
from statement_to_tikz.ir import SolveMode
from statement_to_tikz.pipeline import solve_with_fallback
from statement_to_tikz.solve import evaluate_residuals, solve_geometry
@pytest.mark.parametrize(
"fixture",
[
"equilateral.json",
"isosceles_median.json",
"right_altitude.json",
"parallelogram.json",
"circumcenter.json",
"angle_bisector.json",
],
)
def test_exact_fixtures(fixture: str) -> None:
ir, expected = load_fixture(fixture)
assert expected == "exact"
scene = solve_geometry(ir)
assert scene.mode == SolveMode.exact, scene.message
assert scene.max_residual <= 1e-4
def test_equilateral_side_lengths() -> None:
ir, _ = load_fixture("equilateral.json")
scene = solve_geometry(ir)
a = scene.coordinates["A"]
b = scene.coordinates["B"]
c = scene.coordinates["C"]
def dist(p, q):
return math.hypot(p[0] - q[0], p[1] - q[1])
assert abs(dist(a, b) - 1.0) < 1e-3
assert abs(dist(b, c) - 1.0) < 1e-3
assert abs(dist(c, a) - 1.0) < 1e-3
def test_midpoint_property() -> None:
ir, _ = load_fixture("isosceles_median.json")
scene = solve_geometry(ir)
b, c, d = (scene.coordinates[k] for k in ("B", "C", "D"))
assert abs(d[0] - 0.5 * (b[0] + c[0])) < 1e-3
assert abs(d[1] - 0.5 * (b[1] + c[1])) < 1e-3
a = scene.coordinates["A"]
# non-degenerate: A not on BC
area = abs((b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]))
assert area > 0.5
def test_underconstrained_becomes_schematic() -> None:
ir, expected = load_fixture("underconstrained_triangle.json")
assert expected == "schematic"
scene = solve_with_fallback(ir)
assert scene.mode == SolveMode.schematic
assert set(scene.coordinates) >= {"A", "B", "C"}
def test_conflicting_falls_back_schematic() -> None:
ir, expected = load_fixture("conflicting_lengths.json")
exact = solve_geometry(ir)
assert exact.mode != SolveMode.exact
scene = solve_with_fallback(ir)
assert scene.mode == SolveMode.schematic
# residuals remain large for conflicting lengths
res = evaluate_residuals(ir, scene.coordinates)
assert max(res) > 0.1