Spaces:
Running
Running
File size: 6,147 Bytes
0772b5a | 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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | """
End-to-End and Regression Test Suite for MathSolver Pipeline.
Verifies:
1. DSL Parser + Geometry Engine + Geometry Validator integration.
2. Canonical 3D solids (Pyramid, Cube, Prism, Cone) coordinate solving & invariants.
3. GeometryStatus propagation (VALID, DEGRADED, FAILED).
4. Machine-readable structured error feedback for LLM repair loops.
5. Evaluation framework components and metrics calculation.
"""
from __future__ import annotations
import pytest
from eval.benchmark import BenchmarkDataset, BenchmarkSample
from eval.metrics import compute_cer, compute_wer, latex_match
from eval.runner import EvalRunner
from solver.dsl_parser import DSLParser
from solver.engine import GeometryEngine
from solver.validator import GeometryStatus, GeometryValidator, StructuredError, ValidationResult
def test_metric_calculations():
"""Verify CER, WER, and LaTeX matching functions."""
# CER
assert compute_cer("SA = 6", "SA = 6") == 0.0
assert compute_cer("SA = 6", "SA = 8") == pytest.approx(1 / 6)
assert compute_cer("", "") == 0.0
# WER
assert compute_wer("Cho hình vuông ABCD", "Cho hình vuông ABCD") == 0.0
assert compute_wer("Cho hình vuông ABCD", "Cho hình chữ nhật ABCD") == pytest.approx(2 / 4)
# LaTeX matching
assert latex_match("\\frac{1}{3} \\cdot S \\cdot h", "\\frac{1}{3} * S * h")
assert latex_match("S_{ABCD}", "S_{ABCD}")
def test_validator_structured_feedback():
"""Verify that ValidationResult properly generates structured error feedback."""
err = StructuredError(
error_type="constraint_violation",
constraint="Length constraint violated",
expected="AB = 4",
actual="AB = 5",
instruction="Correct the DSL length values.",
)
res = ValidationResult(
is_valid=False,
errors=["Length constraint violated: |AB| expected 4.00, got 5.00"],
status=GeometryStatus.FAILED,
structured_errors=[err],
)
fb = res.to_structured_feedback()
assert fb["status"] == "failed"
assert fb["error_count"] == 1
assert len(fb["details"]) == 1
assert fb["details"][0]["error_type"] == "constraint_violation"
assert fb["details"][0]["constraint"] == "Length constraint violated"
def test_regression_pyramid_solving_and_validation():
"""Tests S.ABCD square pyramid DSL parse -> engine solve -> validator pass."""
dsl = """
PYRAMID(S_ABCD)
SQUARE(ABCD)
LENGTH(AB, 4)
LENGTH(SA, 6)
PERPENDICULAR_PLANE(SA, ABCD)
"""
parser = DSLParser()
points, constraints, is_3d = parser.parse(dsl)
assert is_3d is True
assert len(points) >= 5
engine = GeometryEngine()
result = engine.solve(points, constraints, is_3d)
assert result is not None
coords = result.get("coordinates", {})
assert len(coords) >= 5
assert "S" in coords and "A" in coords
validator = GeometryValidator()
val_res = validator.validate(result, constraints, is_3d)
assert val_res.is_valid is True
assert val_res.status == GeometryStatus.VALID
def test_regression_cube_solving_and_validation():
"""Tests Cube ABCD.A1B1C1D1 DSL parse -> engine solve -> validator pass."""
dsl = """
CUBE(ABCD_A1B1C1D1)
LENGTH(AB, 5)
"""
parser = DSLParser()
points, constraints, is_3d = parser.parse(dsl)
assert is_3d is True
engine = GeometryEngine()
result = engine.solve(points, constraints, is_3d)
assert result is not None
coords = result.get("coordinates", {})
assert len(coords) >= 8
validator = GeometryValidator()
val_res = validator.validate(result, constraints, is_3d)
assert val_res.is_valid is True
assert val_res.status == GeometryStatus.VALID
def test_regression_triangular_prism_solving_and_validation():
"""Tests Right Triangular Prism ABC.A1B1C1 solving & validation."""
dsl = """
PRISM(ABC_A1B1C1)
POINT(A, 0, 0, 0)
POINT(B, 3, 0, 0)
POINT(C, 0, 4, 0)
POINT(A1, 0, 0, 6)
POINT(B1, 3, 0, 6)
POINT(C1, 0, 4, 6)
LENGTH(AA1, 6)
PERPENDICULAR_PLANE(AA1, ABC)
"""
parser = DSLParser()
points, constraints, is_3d = parser.parse(dsl)
assert is_3d is True
engine = GeometryEngine()
result = engine.solve(points, constraints, is_3d)
assert result is not None
coords = result.get("coordinates", {})
assert len(coords) >= 6
validator = GeometryValidator()
val_res = validator.validate(result, constraints, is_3d)
assert val_res.is_valid is True
assert val_res.status == GeometryStatus.VALID
def test_regression_cone_solving():
"""Tests Cone with apex S and base center O."""
dsl = "CONE(S_O, 3, 4)"
parser = DSLParser()
points, constraints, is_3d = parser.parse(dsl)
assert is_3d is True
engine = GeometryEngine()
result = engine.solve(points, constraints, is_3d)
assert result is not None
coords = result.get("coordinates", {})
assert "S" in coords and "O" in coords
def test_regression_2d_rectangle_solving_and_validation():
"""Tests 2D Rectangle ABCD solving & validation."""
dsl = """
RECTANGLE(ABCD)
LENGTH(AB, 6)
LENGTH(BC, 8)
"""
parser = DSLParser()
points, constraints, is_3d = parser.parse(dsl)
assert is_3d is False
engine = GeometryEngine()
result = engine.solve(points, constraints, is_3d)
assert result is not None
coords = result.get("coordinates", {})
assert len(coords) == 4
validator = GeometryValidator()
val_res = validator.validate(result, constraints, is_3d)
assert val_res.is_valid is True
assert val_res.status == GeometryStatus.VALID
def test_eval_runner_on_benchmark():
"""Tests EvalRunner deterministic pass over benchmark dataset."""
dataset = BenchmarkDataset.load_all_standard()
assert len(dataset) >= 5
runner = EvalRunner()
metrics = runner.evaluate_dsl_deterministic(dataset)
assert metrics.total_samples >= 5
assert metrics.dsl_valid_rate == 1.0
assert metrics.solvability_rate == 1.0
assert metrics.validation_pass_rate == 1.0
assert metrics.degradation_rate == 0.0
|