Files
partridge-cpp/tests/reference_test.py
T
Codex instance 0a7ce1e49e bench: add optional CP-SAT reference
Provide a separately installed OR-Tools model to compare a generic constraint solver with the native first-solution path without adding a production or default-test dependency.

Use no-overlap, exact-fill, edge and equal-copy symmetry constraints, validate placements independently, and record model size, memory, worker count and timings for orders 8 and 9. Keep the tool only as a reference and defer DLX absent new evidence.

Tests: Release CTest (9 passed)

Tests: Python reference tests and compilation checks

Tests: independently validated CP-SAT orders 8 and 9

Refs: #5
2026-07-30 17:40:17 +01:00

84 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Dependency-free tests for the CP-SAT reference support code."""
from __future__ import annotations
import importlib.util
import json
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "tools"))
from partridge_validator import validate # noqa: E402
KNOWN_ORDER_8 = {
"order": 8,
"board_side": 36,
"placements": [
{"x": x, "y": y, "side": side}
for x, y, side in [
(0, 0, 8), (8, 0, 8), (16, 0, 8), (24, 0, 8),
(32, 0, 4), (32, 4, 4), (0, 8, 8), (8, 8, 8),
(16, 8, 8), (24, 8, 6), (30, 8, 6), (24, 14, 5),
(29, 14, 7), (0, 16, 6), (6, 16, 3), (9, 16, 8),
(17, 16, 7), (6, 19, 3), (24, 19, 5), (29, 21, 7),
(0, 22, 7), (7, 22, 2), (17, 23, 1), (18, 23, 6),
(7, 24, 6), (13, 24, 5), (24, 24, 5), (29, 28, 3),
(32, 28, 4), (0, 29, 7), (13, 29, 7), (20, 29, 7),
(27, 29, 2), (7, 30, 6), (27, 31, 5), (32, 32, 4),
]
],
}
def main() -> int:
assert validate(KNOWN_ORDER_8) == []
invalid = json.loads(json.dumps(KNOWN_ORDER_8))
invalid["placements"].pop()
diagnostics = validate(invalid)
assert any("side 4 has multiplicity 3; expected 4" in d for d in diagnostics)
assert any("not completely covered" in d for d in diagnostics)
invalid = json.loads(json.dumps(KNOWN_ORDER_8))
invalid["placements"][0]["x"] = 36
diagnostics = validate(invalid)
assert any("outside the board" in diagnostic for diagnostic in diagnostics)
assert any("not completely covered" in diagnostic for diagnostic in diagnostics)
invalid = json.loads(json.dumps(KNOWN_ORDER_8))
invalid["placements"][1]["x"] = invalid["placements"][0]["x"]
invalid["placements"][1]["y"] = invalid["placements"][0]["y"]
diagnostics = validate(invalid)
assert any("overlaps placement 0" in diagnostic for diagnostic in diagnostics)
invalid = json.loads(json.dumps(KNOWN_ORDER_8))
invalid["placements"][0]["side"] = 9
diagnostics = validate(invalid)
assert any("invalid side length" in diagnostic for diagnostic in diagnostics)
if importlib.util.find_spec("ortools") is not None:
process = subprocess.run(
[
sys.executable,
str(ROOT / "tools" / "cp_sat_reference.py"),
"1",
"--workers",
"1",
],
text=True,
capture_output=True,
check=True,
)
report = json.loads(process.stdout)
assert report["result"]["valid"]
assert validate(report["solution"]) == []
return 0
if __name__ == "__main__":
raise SystemExit(main())