~james/reorder

fix(solver): validate fence constraint indices

commit
2efa23040a7a92f0fc1ff8413586104ed1c3814d browse tree
parent
40efec59037c8cfdff06a3d121284b6212866a65
author
james <j@cpl0.zip>
signature
Verified ~james signed with a key registered by ~james
date
2026-11-02 16:53 UTC

2 files changed, +17 −0

check.ml modified

@@ -148,6 +148,19 @@ let graph () =
148148 Printf.printf "unfenced graph closed: %d states, %d edges, %d violating states\n%!"
149149 (Array.length graph.states) graph.edges (List.length graph.violations)
150150
151+let constraints () =
152+ List.iter (fun (count, clauses) ->
153+ rejects (fun () -> ignore (Solver.candidate ~count ~budget:1 clauses))
154+ "invalid fence constraint")
155+ [-1, []; 1, [[-1]]; 1, [[1]]; 0, [[0]]];
156+ let solve count budget clauses = Solver.solve (Solver.candidate ~count ~budget clauses) in
157+ require (solve 0 0 [] = Solver.Sat []) "empty candidate set satisfies zero budget";
158+ require (solve 0 (-1) [] = Solver.Unsat) "negative lower budget remains unsatisfiable";
159+ require (solve 2 0 [[0; 1]] = Solver.Unsat) "zero budget cannot hit a nonempty clause";
160+ require (solve 2 1 [[0]; [1]] = Solver.Unsat) "independent singleton clauses require two fences";
161+ require (solve 2 2 [[0]; [1]] = Solver.Sat [Solver.Truth true; Solver.Truth true])
162+ "candidate values follow clause indices"
163+
151164 let validation () =
152165 let case = read "buffering" in
153166 let open Sexp in
@@ -207,6 +220,7 @@ let () =
207220 buffers ();
208221 outcomes ();
209222 graph ();
223+ constraints ();
210224 validation ();
211225 repair folder;
212226 Printf.printf "%d checks passed; %d bounded reference states; %.1fs\n%!"

solver.ml modified

@@ -204,6 +204,9 @@ let compile ?(timeout=300000) ?fixed ?(require_goal=true) ?(blocks=[]) case mode
204204 {source = Buffer.contents buffer; probes}
205205
206206 let candidate ~count ~budget clauses =
207+ if count < 0 then invalid_arg "negative fence candidate count";
208+ List.iter (List.iter (fun index ->
209+ if index < 0 || index >= count then invalid_arg "fence constraint index outside candidates")) clauses;
207210 let lines = ref [Store.read (Filename.concat (Store.root ()) "smt/fences.smt2")] in
208211 let add line = lines := line :: !lines in
209212 for i = 0 to count - 1 do add (Printf.sprintf "(declare-const f%d Bool)" i) done;