@@ -18,6 +18,8 @@ using Dates
1818# ---------------------------------------------------------------------------
1919
2020const TRAINING_DIR = joinpath (dirname (dirname (abspath (@__FILE__ ))), " training_data" )
21+ const BALANCED_OUTPUT_FILE = joinpath (TRAINING_DIR, " proof_states_UNIFIED_BALANCED.jsonl" )
22+ const BALANCED_CAP_PER_PROVER = 12_000
2123
2224# Per-prover source files -- the authoritative extractions.
2325# We list them explicitly to avoid pulling in aggregate/merged files
@@ -41,6 +43,9 @@ const PER_PROVER_FILES = [
4143 " proof_states_twelf.jsonl" , # Twelf (synthetic)
4244 " proof_states_imandra.jsonl" , # Imandra (synthetic)
4345 " proof_states_minizinc.jsonl" , # MiniZinc / constraint solvers
46+ " proof_states_isabelle.jsonl" , # Isabelle (tropical + theory extraction)
47+ " proof_states_tptp.a2ml" , # Vampire / EProver / SPASS from TPTP
48+ " proof_states_typechecker_ecosystem.jsonl" , # Typechecker/prover expansion
4449 " proof_states_mathlib4.jsonl" , # Additional mathlib4 (smaller set)
4550 " proof_states_coqgym.jsonl" , # Additional CoqGym (smaller set)
4651 " proof_states_2026-03-20.jsonl" , # Dated snapshot
@@ -55,6 +60,11 @@ const ALL_PROVERS = Set([
5560 " TLAPS" , " Twelf" , " Nuprl" , " Minlog" , " Imandra" ,
5661 " Vampire" , " EProver" , " E Prover" , " SPASS" ,
5762 " GLPK" , " SCIP" , " MiniZinc" , " Chuffed" , " ORTools" , " OR-Tools" ,
63+ # Typechecker-native and research prover/tool families
64+ " TypeLL" , " KatagoriaVerifier" , " TropicalTypeChecker" ,
65+ " ChoreographicTypeChecker" , " EpistemicTypeChecker" , " EchoTypeChecker" ,
66+ " SessionTypeChecker" , " ModalTypeChecker" , " QTTTypeChecker" ,
67+ " EffectRowTypeChecker" , " DependentTypeChecker" , " RefinementTypeChecker" ,
5868])
5969
6070# Canonical prover name mapping (normalise variants).
@@ -69,8 +79,8 @@ const PROVER_CANONICAL = Dict(
6979 " OR-Tools" => " ORTools" ,
7080)
7181
72- # Total expected backend count for coverage calculation.
73- const TOTAL_BACKENDS = 30
82+ # Total expected backend/tool count for coverage calculation.
83+ const TOTAL_BACKENDS = 60
7484
7585"""
7686 canonical_prover(name::String) -> String
@@ -118,23 +128,164 @@ end
118128Load a JSONL file, skipping malformed lines.
119129"""
120130function load_jsonl (filepath:: String ):: Vector{Dict{String,Any}}
131+ if endswith (lowercase (filepath), " .a2ml" )
132+ return load_tptp_a2ml (filepath)
133+ end
134+
121135 entries = Dict{String,Any}[]
122136 if ! isfile (filepath)
123137 return entries
124138 end
139+ malformed = 0
125140 for (lineno, line) in enumerate (eachline (filepath))
126141 stripped = strip (line)
127142 isempty (stripped) && continue
128143 try
129- entry = Dict {String,Any} ( pairs (JSON3 . read (stripped)) )
144+ entry = JSON3 . read (stripped, Dict{String,Any})
130145 push! (entries, entry)
131146 catch
132- println (" WARN: Skipped malformed JSON at $(basename (filepath)) :$lineno " )
147+ malformed += 1
148+ if malformed <= 5
149+ println (" WARN: Skipped malformed JSON at $(basename (filepath)) :$lineno " )
150+ end
133151 end
134152 end
153+ if malformed > 5
154+ println (" WARN: Suppressed $(malformed - 5 ) additional malformed lines in $(basename (filepath)) " )
155+ end
135156 return entries
136157end
137158
159+ """
160+ parse_a2ml_value(raw::String) -> Any
161+
162+ Parse a basic A2ML scalar/list value used in proof-state blocks.
163+ """
164+ function parse_a2ml_value (raw:: String ):: Any
165+ value = strip (raw)
166+ if startswith (value, " \" " ) && endswith (value, " \" " ) && length (value) >= 2
167+ return replace (value[2 : end - 1 ], " \\\" " => " \" " )
168+ elseif value == " []"
169+ return Any[]
170+ elseif occursin (r" ^-?\d +$" , value)
171+ try
172+ return parse (Int, value)
173+ catch
174+ return value
175+ end
176+ else
177+ return value
178+ end
179+ end
180+
181+ """
182+ load_tptp_a2ml(filepath::String) -> Vector{Dict{String,Any}}
183+
184+ Load TPTP proof-state blocks from an A2ML file.
185+ """
186+ function load_tptp_a2ml (filepath:: String ):: Vector{Dict{String,Any}}
187+ entries = Dict{String,Any}[]
188+ if ! isfile (filepath)
189+ return entries
190+ end
191+
192+ current = Dict {String,Any} ()
193+ in_block = false
194+
195+ for line in eachline (filepath)
196+ stripped = strip (line)
197+ isempty (stripped) && continue
198+ startswith (stripped, " #" ) && continue
199+
200+ if stripped == " [[proof-state]]"
201+ if in_block && ! isempty (current)
202+ push! (entries, current)
203+ end
204+ current = Dict {String,Any} ()
205+ in_block = true
206+ continue
207+ end
208+
209+ ! in_block && continue
210+ m = match (r" ^([A-Za-z0-9_.-]+)\s *=\s *(.+)$" , stripped)
211+ m === nothing && continue
212+ key = String (m. captures[1 ])
213+ raw = String (m. captures[2 ])
214+ current[key] = parse_a2ml_value (raw)
215+ end
216+
217+ if in_block && ! isempty (current)
218+ push! (entries, current)
219+ end
220+
221+ return entries
222+ end
223+
224+ """
225+ evenly_sample(entries::Vector{Dict{String,Any}}, target::Int) -> Vector{Dict{String,Any}}
226+
227+ Sample approximately evenly across a sorted list, preserving breadth.
228+ """
229+ function evenly_sample (entries:: Vector{Dict{String,Any}} , target:: Int ):: Vector{Dict{String,Any}}
230+ n = length (entries)
231+ n <= target && return entries
232+ target <= 0 && return Dict{String,Any}[]
233+
234+ step = n / target
235+ sampled = Dict{String,Any}[]
236+ seen = Set {Int} ()
237+ for i in 1 : target
238+ idx = clamp (floor (Int, (i - 1 ) * step) + 1 , 1 , n)
239+ if idx ∉ seen
240+ push! (sampled, entries[idx])
241+ push! (seen, idx)
242+ end
243+ end
244+ return sampled
245+ end
246+
247+ """
248+ write_balanced_subset(deduped::Vector{Dict{String,Any}})
249+
250+ Write a capped per-prover balanced subset to reduce dominance by top provers.
251+ """
252+ function write_balanced_subset (deduped:: Vector{Dict{String,Any}} ):: Dict{String,Int}
253+ grouped = Dict {String,Vector{Dict{String,Any}}} ()
254+ for entry in deduped
255+ prover = string (get (entry, " prover" , " Unknown" ))
256+ if ! haskey (grouped, prover)
257+ grouped[prover] = Dict{String,Any}[]
258+ end
259+ push! (grouped[prover], entry)
260+ end
261+
262+ balanced = Dict{String,Any}[]
263+ balanced_counts = Dict {String,Int} ()
264+
265+ for prover in sort (collect (keys (grouped)))
266+ entries = grouped[prover]
267+ sort! (entries, by= e -> (string (get (e, " theorem" , " " )), string (get (e, " source" , " " ))))
268+ selected = evenly_sample (entries, BALANCED_CAP_PER_PROVER)
269+ append! (balanced, selected)
270+ balanced_counts[prover] = length (selected)
271+ end
272+
273+ # Fresh IDs for balanced file only.
274+ sort! (balanced, by= e -> (string (get (e, " prover" , " " )), string (get (e, " theorem" , " " ))))
275+ for (idx, entry) in enumerate (balanced)
276+ entry[" id" ] = idx
277+ end
278+
279+ open (BALANCED_OUTPUT_FILE, " w" ) do fh
280+ for entry in balanced
281+ println (fh, JSON3. write (entry))
282+ end
283+ end
284+
285+ println (" Wrote balanced corpus to $BALANCED_OUTPUT_FILE ($(length (balanced)) proofs)" )
286+ return balanced_counts
287+ end
288+
138289"""
139290 extract_words(text::String) -> Set{String}
140291
@@ -143,7 +294,7 @@ Split on non-alphanumeric, keep tokens >= 3 chars that are alphabetic.
143294"""
144295function extract_words (text:: String ):: Set{String}
145296 tokens = split (text, r" [^a-zA-Z]+" )
146- return Set (lowercase (t) for t in tokens if length (t) >= 3 && all (isalpha , t))
297+ return Set (lowercase (t) for t in tokens if length (t) >= 3 && all (isletter , t))
147298end
148299
149300function main ():: Int
@@ -209,6 +360,11 @@ function main()::Int
209360 end
210361 println (" \n Wrote $(length (deduped)) proofs to $unified_path " )
211362
363+ # ------------------------------------------------------------------
364+ # 4b. Write capped balanced subset (per-prover cap)
365+ # ------------------------------------------------------------------
366+ balanced_counts = write_balanced_subset (deduped)
367+
212368 # ------------------------------------------------------------------
213369 # 5. Compute statistics
214370 # ------------------------------------------------------------------
@@ -250,6 +406,12 @@ function main()::Int
250406 " total_backends" => TOTAL_BACKENDS,
251407 " coverage_percentage" => coverage_pct,
252408 " per_prover_counts" => per_prover,
409+ " balanced_output_file" => basename (BALANCED_OUTPUT_FILE),
410+ " balanced_cap_per_prover" => BALANCED_CAP_PER_PROVER,
411+ " balanced_total_proofs" => sum (values (balanced_counts)),
412+ " balanced_per_prover_counts" => Dict (
413+ k => v for (k, v) in sort (collect (balanced_counts); by= x -> - x[2 ])
414+ ),
253415 " per_source_counts_top50" => per_source_top50,
254416 " vocabulary_size" => length (vocab),
255417 " source_files_used" => file_counts,
@@ -283,6 +445,8 @@ function main()::Int
283445 println (" Vocabulary words: $(lpad (string (length (vocab)), 10 )) " )
284446 println (" Provers with data: $(lpad (string (provers_with_data), 10 )) / $TOTAL_BACKENDS " )
285447 println (" Coverage: $(lpad (string (coverage_pct), 9 )) %" )
448+ println (" Balanced proofs: $(lpad (string (sum (values (balanced_counts))), 10 )) " )
449+ println (" Cap per prover: $(lpad (string (BALANCED_CAP_PER_PROVER), 10 )) " )
286450 println ()
287451 println (" Per-prover breakdown:" )
288452 for (prover, count) in sorted_prover_counts
0 commit comments