import argparse import json from pathlib import Path BENCHMARKS = { "formal_math500": ("FormalMath500", "formal_math500.jsonl"), "minif2f_solving": ("MiniF2FSolving", "minif2f_solving.jsonl"), "putnam_solving": ("PutnamBenchSolving", "putnam_solving.jsonl"), } LEAN_CODE_TEMPLATE = r'''import FormalProblemSolving.Basic {header_block} /- ## Problem {informal_problem} ## Answer {informal_answer} -/ -- # Formal Answer noncomputable abbrev Q{p_index}.gt := fun{formal_answer_args} (answer : {formal_answer_type}) => {formal_answer} -- # Formal Problem (FPS) namespace {benchmark_name}_FPS open scoped FPS problem Q{p_index} {V} find (answer : {formal_answer_type}) s.t.{Phi} : {Psi} := solve -- Placeholder all_goals sorry end {benchmark_name}_FPS -- # Formal Problem (D-FPS) namespace {benchmark_name}_DFPS open scoped DFPS problem Q{p_index} {V} find_all (answer : {formal_answer_type}) iff{Phi} : {Psi} := solve case Answer := sorry all_goals sorry end {benchmark_name}_DFPS ''' def load_jsonl(path: Path) -> list[dict]: with path.open("r", encoding="utf-8") as handle: return [json.loads(line) for line in handle if line.strip()] def render_problem(record: dict, benchmark_name: str, index: int) -> str: variables = [f" ({var['name'] or '_'} : {var['t']})" for var in record["independent_variables"]] hypotheses = [f" ({var['name'] or '_'} : {var['t']})" for var in record["hypotheses"]] header = (record.get("header") or "").strip() formal_answer_args = (" " if variables else "") + " ".join(var.strip() for var in variables) lean_code = LEAN_CODE_TEMPLATE.replace(r"{p_index}", str(index)).format( header_block=header + "\n" if header else "", informal_problem=(record.get("informal_problem") or "").strip(), informal_answer=str(record.get("informal_answer") or "").strip(), formal_answer_args=formal_answer_args, formal_answer=record["formal_answer"], formal_answer_type=record["formal_answer_type"], V=("\n" if variables else "") + "\n".join(variables), Phi=("\n" if hypotheses else "") + "\n".join(hypotheses), Psi=" ∧ ".join(record["conclusions"]).strip(), benchmark_name=benchmark_name, ) return "\n".join(line.rstrip() for line in lean_code.splitlines()) + "\n" def export_benchmark(data_root: Path, output_root: Path, benchmark: str) -> None: benchmark_name, filename = BENCHMARKS[benchmark] records = load_jsonl(data_root / filename) destination = output_root / "FormalProblemSolving" / benchmark_name destination.mkdir(parents=True, exist_ok=True) for index, record in enumerate(records, 1): (destination / f"{index}.lean").write_text(render_problem(record, benchmark_name, index), encoding="utf-8") def main() -> None: parser = argparse.ArgumentParser(description="Export FPS JSONL benchmarks to the Lean Formal Problem-Solving project.") parser.add_argument("--data_root", type=Path, default=Path("data")) parser.add_argument("--output_root", type=Path, required=True, help="Path to the Lean benchmark project root.") parser.add_argument("--benchmark", choices=["all", *BENCHMARKS.keys()], default="all") args = parser.parse_args() benchmarks = BENCHMARKS.keys() if args.benchmark == "all" else [args.benchmark] for benchmark in benchmarks: export_benchmark(args.data_root, args.output_root, benchmark) if __name__ == "__main__": main()