Skip to content

Commit 3b1496d

Browse files
committed
Add ICCMA timeout row runner
1 parent 1d1a16d commit 3b1496d

2 files changed

Lines changed: 146 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from __future__ import annotations
2+
3+
from tools.iccma_run_timeout_rows import selected_timeout_rows, summarize_results
4+
5+
6+
def test_selected_timeout_rows_filters_year_and_subtrack() -> None:
7+
rows = [
8+
{"year": 2017, "subtrack": "DS-PR", "instance": "a.apx"},
9+
{"year": 2019, "subtrack": "DS-PR", "instance": "b.apx"},
10+
{"year": 2023, "subtrack": "DS-PR", "instance": "c.apx"},
11+
{"year": 2017, "subtrack": "SE-PR", "instance": "d.apx"},
12+
]
13+
14+
assert selected_timeout_rows(rows, years={2017, 2019}, subtrack="DS-PR") == rows[:2]
15+
16+
17+
def test_summarize_results_groups_statuses_and_timeouts() -> None:
18+
results = [
19+
{"source": {"instance": "a.apx"}, "result": {"status": "solved"}},
20+
{"source": {"instance": "b.apx"}, "result": {"status": "timeout"}},
21+
{"source": {"instance": "c.apx"}, "result": {"status": "solved"}},
22+
]
23+
24+
assert summarize_results(results) == {
25+
"total": 3,
26+
"by_status": {"solved": 2, "timeout": 1},
27+
"timeouts": ["b.apx"],
28+
}

tools/iccma_run_timeout_rows.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
import json
5+
from pathlib import Path
6+
import sys
7+
from typing import Any
8+
9+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
10+
11+
from tools.iccma_run_selected import run_selected
12+
13+
14+
def selected_timeout_rows(
15+
rows: list[dict[str, Any]],
16+
*,
17+
years: set[int],
18+
subtrack: str,
19+
) -> list[dict[str, Any]]:
20+
return [
21+
row
22+
for row in rows
23+
if row.get("year") in years and row.get("subtrack") == subtrack
24+
]
25+
26+
27+
def run_timeout_rows(
28+
rows: list[dict[str, Any]],
29+
*,
30+
timeout_seconds: float,
31+
backend: str,
32+
data_root: Path,
33+
) -> list[dict[str, Any]]:
34+
results: list[dict[str, Any]] = []
35+
total = len(rows)
36+
for index, row in enumerate(rows, start=1):
37+
year = int(row["year"])
38+
result = run_selected(
39+
root=data_root / str(year),
40+
relative_path=str(row["instance"]).replace("/", "\\"),
41+
kind=str(row["instance_kind"]),
42+
subtrack=str(row["subtrack"]),
43+
backend=backend,
44+
timeout_seconds=timeout_seconds,
45+
arguments_or_atoms=row.get("arguments_or_atoms"),
46+
track=str(row["track"]),
47+
instance_kind=str(row["instance_kind"]),
48+
)
49+
materialized = {"source": row, "result": result}
50+
results.append(materialized)
51+
print(
52+
json.dumps(
53+
{
54+
"event": "timeout_row",
55+
"index": index,
56+
"total": total,
57+
"year": year,
58+
"subtrack": row["subtrack"],
59+
"instance": row["instance"],
60+
"status": result.get("status"),
61+
"answer": result.get("answer"),
62+
"reason": result.get("reason"),
63+
},
64+
sort_keys=True,
65+
),
66+
file=sys.stderr,
67+
flush=True,
68+
)
69+
return results
70+
71+
72+
def summarize_results(results: list[dict[str, Any]]) -> dict[str, Any]:
73+
by_status: dict[str, int] = {}
74+
for item in results:
75+
status = str(item["result"].get("status"))
76+
by_status[status] = by_status.get(status, 0) + 1
77+
return {
78+
"total": len(results),
79+
"by_status": dict(sorted(by_status.items())),
80+
"timeouts": [
81+
item["source"]["instance"]
82+
for item in results
83+
if item["result"].get("status") == "timeout"
84+
],
85+
}
86+
87+
88+
def main(argv: list[str] | None = None) -> int:
89+
parser = argparse.ArgumentParser(description="Run selected rows from an ICCMA timeout fixture.")
90+
parser.add_argument("--timeouts", type=Path, required=True)
91+
parser.add_argument("--year", type=int, action="append", required=True)
92+
parser.add_argument("--subtrack", required=True)
93+
parser.add_argument("--timeout-seconds", type=float, default=20.0)
94+
parser.add_argument("--backend", default="auto")
95+
parser.add_argument("--data-root", type=Path, default=Path("data") / "iccma")
96+
parser.add_argument("--output", type=Path, required=True)
97+
args = parser.parse_args(argv)
98+
99+
rows = json.loads(args.timeouts.read_text(encoding="utf-8"))
100+
selected = selected_timeout_rows(rows, years=set(args.year), subtrack=args.subtrack)
101+
results = run_timeout_rows(
102+
selected,
103+
timeout_seconds=args.timeout_seconds,
104+
backend=args.backend,
105+
data_root=args.data_root,
106+
)
107+
payload = {
108+
"summary": summarize_results(results),
109+
"results": results,
110+
}
111+
args.output.parent.mkdir(parents=True, exist_ok=True)
112+
args.output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
113+
print(json.dumps(payload["summary"], indent=2, sort_keys=True))
114+
return 0
115+
116+
117+
if __name__ == "__main__":
118+
raise SystemExit(main())

0 commit comments

Comments
 (0)