Skip to content

Commit 618d6b9

Browse files
hyperpolymathclaude
andcommitted
feat(extract): vendor ACL2 Community Books + MiniZinc benchmarks
ACL2 (277 → 170 455, 615×): - Sparse clone acl2/acl2 at external_corpora/acl2_full/ with `books/` checked out (~ 13 478 .lisp files, 1.5 GB). - Walk recursively alongside legacy curated cache. - Accept .lisp and .acl2 files. - Fix UTF-8 byte-index slice crash (switch to first(s, n)). - ACL2 vaults to #2 corpus after Lean — Community Books are dense with named defthm declarations across hundreds of books. MiniZinc (29 → 327, 11×): - Clone MiniZinc/minizinc-benchmarks at external_corpora/minizinc_full/ (~ 300 .mzn models + many .dzn data files). - Walk recursively. - Wrap three eachmatch calls in try/catch — large amalgamated data files caused PCRE catastrophic backtracking. Count growth limited by the extractor's gate (requires at least one variable or constraint); further uplift needs per-file lowering or data-file handling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 28cb74f commit 618d6b9

2 files changed

Lines changed: 75 additions & 21 deletions

File tree

scripts/extract_acl2.jl

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function parse_acl2_file(filepath::String)::Vector{Dict{String,Any}}
7474
body = strip(m.captures[2])
7575
# Clean up body
7676
body_clean = replace(body, r"\s+" => " ")
77-
body_clean = body_clean[1:min(300, length(body_clean))]
77+
body_clean = first(body_clean, 300)
7878

7979
# Extract hints
8080
hints_match = match(r":hints\s*\((.*?)\)"s, body)
@@ -251,16 +251,37 @@ function run()::Tuple{Int,Int}
251251
downloaded = download_acl2_files()
252252
println(" Downloaded/cached $downloaded files")
253253

254+
# Widening (2026-04-18): walk a sparse acl2/acl2 clone at
255+
# external_corpora/acl2_full/ (only `books/` checked out). The
256+
# ACL2 Community Books are the canonical proof corpus and hold
257+
# tens of thousands of named theorems across hundreds of books.
258+
# Accept .lisp and .acl2 files.
259+
src_files = String[]
254260
for fname in readdir(EXTERNAL_DIR)
255-
if endswith(fname, ".lisp")
256-
fpath = joinpath(EXTERNAL_DIR, fname)
257-
parsed = parse_acl2_file(fpath)
258-
append!(all_entries, parsed)
259-
if !isempty(parsed)
260-
println(" Parsed $(length(parsed)) theorems from $fname")
261+
(endswith(fname, ".lisp") || endswith(fname, ".acl2")) &&
262+
push!(src_files, joinpath(EXTERNAL_DIR, fname))
263+
end
264+
full_root = joinpath(dirname(EXTERNAL_DIR), "acl2_full")
265+
if isdir(full_root)
266+
println("[ACL2] Walking full clone at $(full_root) ...")
267+
for (root, _dirs, files) in walkdir(full_root)
268+
for fname in files
269+
(endswith(fname, ".lisp") || endswith(fname, ".acl2")) &&
270+
push!(src_files, joinpath(root, fname))
261271
end
262272
end
263273
end
274+
println(" $(length(src_files)) ACL2 source files to parse")
275+
276+
processed = 0
277+
for fpath in src_files
278+
parsed = parse_acl2_file(fpath)
279+
append!(all_entries, parsed)
280+
processed += 1
281+
if processed % 500 == 0
282+
println(" processed $(processed)/$(length(src_files)) files — running count: $(length(all_entries))")
283+
end
284+
end
264285
extracted_count = length(all_entries)
265286

266287
println("[ACL2] Phase 2: Generating synthetic proofs ...")

scripts/extract_minizinc.jl

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,30 @@ function parse_mzn_file(filepath::String)::Vector{Dict{String,Any}}
6666

6767
model_name = splitext(basename(filepath))[1]
6868

69-
# Extract variables
70-
variables = [(m.captures[2], m.captures[1]) for m in eachmatch(r"var\s+([\w.]+)\s*:\s*(\w+)"i, content)]
69+
# Each of these regexes can catastrophically backtrack on large
70+
# data files or amalgamated benchmarks. Wrap each collection in
71+
# a try/catch so a single pathological file just skips — the rest
72+
# of the corpus still extracts.
73+
variables = try
74+
[(m.captures[2], m.captures[1]) for m in eachmatch(r"var\s+([\w.]+)\s*:\s*(\w+)"i, content)]
75+
catch
76+
Tuple{Any,Any}[]
77+
end
7178

72-
# Extract constraints
73-
constraints = [first(replace(strip(m.captures[1]), r"\s+" => " "), 200)
74-
for m in eachmatch(r"constraint\s+(.*?)\s*;"s, content)]
79+
constraints = try
80+
[first(replace(strip(m.captures[1]), r"\s+" => " "), 200)
81+
for m in eachmatch(r"constraint\s+(.*?)\s*;"s, content)]
82+
catch
83+
String[]
84+
end
7585

76-
# Extract objective
7786
objective = "satisfy"
78-
for m in eachmatch(r"solve\s+(.*?)\s*;"s, content)
79-
objective = first(replace(strip(m.captures[1]), r"\s+" => " "), 200)
87+
try
88+
for m in eachmatch(r"solve\s+(.*?)\s*;"s, content)
89+
objective = first(replace(strip(m.captures[1]), r"\s+" => " "), 200)
90+
end
91+
catch
92+
# keep default
8093
end
8194

8295
if !isempty(variables) || !isempty(constraints)
@@ -320,16 +333,36 @@ function run()::Tuple{Int,Int}
320333
downloaded = download_mzn_files()
321334
println(" Downloaded/cached $(downloaded) files")
322335

336+
# Widening (2026-04-18): walk MiniZinc/minizinc-benchmarks at
337+
# external_corpora/minizinc_full/ — the official benchmark suite
338+
# with hundreds of real-world constraint models. Accepts .mzn
339+
# (model) and .dzn (data) files.
340+
src_files = String[]
323341
for fname in readdir(EXTERNAL_DIR)
324-
if endswith(fname, ".mzn")
325-
fpath = joinpath(EXTERNAL_DIR, fname)
326-
parsed = parse_mzn_file(fpath)
327-
append!(all_entries, parsed)
328-
if !isempty(parsed)
329-
println(" Parsed $(length(parsed)) models from $(fname)")
342+
(endswith(fname, ".mzn") || endswith(fname, ".dzn")) &&
343+
push!(src_files, joinpath(EXTERNAL_DIR, fname))
344+
end
345+
full_root = joinpath(dirname(EXTERNAL_DIR), "minizinc_full")
346+
if isdir(full_root)
347+
println("[MiniZinc] Walking full benchmark clone at $(full_root) ...")
348+
for (root, _dirs, files) in walkdir(full_root)
349+
for fname in files
350+
(endswith(fname, ".mzn") || endswith(fname, ".dzn")) &&
351+
push!(src_files, joinpath(root, fname))
330352
end
331353
end
332354
end
355+
println(" $(length(src_files)) MiniZinc source files to parse")
356+
357+
processed = 0
358+
for fpath in src_files
359+
parsed = parse_mzn_file(fpath)
360+
append!(all_entries, parsed)
361+
processed += 1
362+
if processed % 500 == 0
363+
println(" processed $(processed)/$(length(src_files)) files — running count: $(length(all_entries))")
364+
end
365+
end
333366
extracted_count = length(all_entries)
334367

335368
println("[MiniZinc/Constraint Solvers] Phase 2: Generating synthetic models ...")

0 commit comments

Comments
 (0)