mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 11:15:43 -05:00
feat(sudoku): add stats
This commit is contained in:
parent
63802fe3d6
commit
6ccabc70aa
1 changed files with 37 additions and 19 deletions
|
|
@ -141,7 +141,7 @@ module B_ref = Sidekick_util.Backtrackable_ref
|
||||||
module Solver : sig
|
module Solver : sig
|
||||||
type t
|
type t
|
||||||
|
|
||||||
val create : Grid.t -> t
|
val create : stat:Stat.t -> Grid.t -> t
|
||||||
val solve : t -> Grid.t option
|
val solve : t -> Grid.t option
|
||||||
end = struct
|
end = struct
|
||||||
open Sidekick_core
|
open Sidekick_core
|
||||||
|
|
@ -180,15 +180,18 @@ end = struct
|
||||||
type t
|
type t
|
||||||
|
|
||||||
val grid : t -> Grid.t
|
val grid : t -> Grid.t
|
||||||
val create : Term.store -> Grid.t -> t
|
val create : stat:Stat.t -> Term.store -> Grid.t -> t
|
||||||
val to_plugin : t -> Sat.plugin
|
val to_plugin : t -> Sat.plugin
|
||||||
end = struct
|
end = struct
|
||||||
type t = { tst: Term.store; grid: Grid.t B_ref.t }
|
type t = {
|
||||||
|
tst: Term.store;
|
||||||
|
grid: Grid.t B_ref.t;
|
||||||
|
stat_check_full: int Stat.counter;
|
||||||
|
stat_conflict: int Stat.counter;
|
||||||
|
}
|
||||||
|
|
||||||
let[@inline] grid self : Grid.t = B_ref.get self.grid
|
let[@inline] grid self : Grid.t = B_ref.get self.grid
|
||||||
let[@inline] set_grid self g : unit = B_ref.set self.grid g
|
let[@inline] set_grid self g : unit = B_ref.set self.grid g
|
||||||
let push_level self = B_ref.push_level self.grid
|
|
||||||
let pop_levels self n = B_ref.pop_levels self.grid n
|
|
||||||
let pp_c_ = Fmt.(list ~sep:(return "@ ∨ ")) Lit.pp
|
let pp_c_ = Fmt.(list ~sep:(return "@ ∨ ")) Lit.pp
|
||||||
|
|
||||||
let[@inline] logs_conflict kind c : unit =
|
let[@inline] logs_conflict kind c : unit =
|
||||||
|
|
@ -200,6 +203,7 @@ end = struct
|
||||||
let (module A) = acts in
|
let (module A) = acts in
|
||||||
Grid.all_cells (grid self) (fun (x, y, c) ->
|
Grid.all_cells (grid self) (fun (x, y, c) ->
|
||||||
if Cell.is_empty c then (
|
if Cell.is_empty c then (
|
||||||
|
Stat.incr self.stat_check_full;
|
||||||
let c =
|
let c =
|
||||||
CCList.init 9 (fun c ->
|
CCList.init 9 (fun c ->
|
||||||
mk_cell_lit self.tst x y (Cell.make (c + 1)))
|
mk_cell_lit self.tst x y (Cell.make (c + 1)))
|
||||||
|
|
@ -214,7 +218,7 @@ end = struct
|
||||||
Log.debugf 4 (fun k ->
|
Log.debugf 4 (fun k ->
|
||||||
k "(@[sudoku.check@ @[:g %a@]@])" Grid.pp (B_ref.get self.grid));
|
k "(@[sudoku.check@ @[:g %a@]@])" Grid.pp (B_ref.get self.grid));
|
||||||
let (module A) = acts in
|
let (module A) = acts in
|
||||||
let[@inline] all_diff kind f =
|
let[@inline] all_diff c_kind f =
|
||||||
let pairs =
|
let pairs =
|
||||||
f (grid self)
|
f (grid self)
|
||||||
|> Iter.flat_map (fun set ->
|
|> Iter.flat_map (fun set ->
|
||||||
|
|
@ -231,7 +235,8 @@ end = struct
|
||||||
mk_cell_lit self.tst ~sign:false x2 y2 c2;
|
mk_cell_lit self.tst ~sign:false x2 y2 c2;
|
||||||
]
|
]
|
||||||
in
|
in
|
||||||
logs_conflict ("all-diff." ^ kind) c;
|
Stat.incr self.stat_conflict;
|
||||||
|
logs_conflict c_kind c;
|
||||||
A.raise_conflict c Proof_trace.dummy_step_id
|
A.raise_conflict c Proof_trace.dummy_step_id
|
||||||
))
|
))
|
||||||
in
|
in
|
||||||
|
|
@ -282,12 +287,18 @@ end = struct
|
||||||
check_full_ self acts;
|
check_full_ self acts;
|
||||||
check_ self acts
|
check_ self acts
|
||||||
|
|
||||||
let create tst g : t = { tst; grid = B_ref.create g }
|
let create ~stat tst g : t =
|
||||||
|
{
|
||||||
|
tst;
|
||||||
|
grid = B_ref.create g;
|
||||||
|
stat_check_full = Stat.mk_int stat "sudoku.check-cell-full";
|
||||||
|
stat_conflict = Stat.mk_int stat "sudoku.conflict";
|
||||||
|
}
|
||||||
|
|
||||||
let to_plugin (self : t) : Sat.plugin =
|
let to_plugin (self : t) : Sat.plugin =
|
||||||
Sat.mk_plugin_cdcl_t
|
Sat.mk_plugin_cdcl_t
|
||||||
~push_level:(fun () -> push_level self)
|
~push_level:(fun () -> B_ref.push_level self.grid)
|
||||||
~pop_levels:(fun n -> pop_levels self n)
|
~pop_levels:(fun n -> B_ref.pop_levels self.grid n)
|
||||||
~partial_check:(partial_check self) ~final_check:(final_check self) ()
|
~partial_check:(partial_check self) ~final_check:(final_check self) ()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -312,20 +323,20 @@ end = struct
|
||||||
(* TODO: print some stats *)
|
(* TODO: print some stats *)
|
||||||
r
|
r
|
||||||
|
|
||||||
let create g : t =
|
let create ~stat g : t =
|
||||||
let tst = Term.Store.create () in
|
let tst = Term.Store.create () in
|
||||||
let theory = Theory.create tst g in
|
let theory = Theory.create ~stat tst g in
|
||||||
let plugin : Sat.plugin = Theory.to_plugin theory in
|
let plugin : Sat.plugin = Theory.to_plugin theory in
|
||||||
{
|
{
|
||||||
tst;
|
tst;
|
||||||
solver = Sat.create ~proof:Proof_trace.dummy plugin;
|
solver = Sat.create ~stat ~proof:Proof_trace.dummy plugin;
|
||||||
theory;
|
theory;
|
||||||
grid0 = g;
|
grid0 = g;
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
let solve_grid (g : Grid.t) : Grid.t option =
|
let solve_grid ~stat (g : Grid.t) : Grid.t option =
|
||||||
let s = Solver.create g in
|
let s = Solver.create ~stat g in
|
||||||
Solver.solve s
|
Solver.solve s
|
||||||
|
|
||||||
module type CHRONO = sig
|
module type CHRONO = sig
|
||||||
|
|
@ -341,7 +352,7 @@ let chrono ~pp_time : (module CHRONO) =
|
||||||
end in
|
end in
|
||||||
(module M)
|
(module M)
|
||||||
|
|
||||||
let solve_file ~pp_time file =
|
let solve_file ~use_stats ~pp_time file =
|
||||||
let@ () = Profile.with_ "solve-file" in
|
let@ () = Profile.with_ "solve-file" in
|
||||||
let open (val chrono ~pp_time) in
|
let open (val chrono ~pp_time) in
|
||||||
Format.printf "solve grids in file %S@." file;
|
Format.printf "solve grids in file %S@." file;
|
||||||
|
|
@ -365,7 +376,8 @@ let solve_file ~pp_time file =
|
||||||
Format.printf
|
Format.printf
|
||||||
"@[<v>@,#########################@,@[<2>solve grid:@ %a@]@]@." Grid.pp g;
|
"@[<v>@,#########################@,@[<2>solve grid:@ %a@]@]@." Grid.pp g;
|
||||||
let open (val chrono ~pp_time) in
|
let open (val chrono ~pp_time) in
|
||||||
match solve_grid g with
|
let stat = Stat.create () in
|
||||||
|
(match solve_grid ~stat g with
|
||||||
| None -> Format.printf "no solution%t@." pp_elapsed
|
| None -> Format.printf "no solution%t@." pp_elapsed
|
||||||
| Some g' when not @@ Grid.is_full g' ->
|
| Some g' when not @@ Grid.is_full g' ->
|
||||||
errorf "grid %a@ is not full" Grid.pp g'
|
errorf "grid %a@ is not full" Grid.pp g'
|
||||||
|
|
@ -376,7 +388,8 @@ let solve_file ~pp_time file =
|
||||||
g
|
g
|
||||||
| Some g' ->
|
| Some g' ->
|
||||||
Format.printf "@[<v>@[<2>solution%t:@ %a@]@,###################@]@."
|
Format.printf "@[<v>@[<2>solution%t:@ %a@]@,###################@]@."
|
||||||
pp_elapsed Grid.pp g')
|
pp_elapsed Grid.pp g');
|
||||||
|
if use_stats then Fmt.printf "stats: %a@." Stat.pp stat)
|
||||||
grids;
|
grids;
|
||||||
Format.printf "@.solved %d grids%t@." (List.length grids) pp_elapsed;
|
Format.printf "@.solved %d grids%t@." (List.length grids) pp_elapsed;
|
||||||
()
|
()
|
||||||
|
|
@ -387,17 +400,22 @@ let () =
|
||||||
let files = ref [] in
|
let files = ref [] in
|
||||||
let debug = ref 0 in
|
let debug = ref 0 in
|
||||||
let pp_time = ref true in
|
let pp_time = ref true in
|
||||||
|
let use_stats = ref false in
|
||||||
let opts =
|
let opts =
|
||||||
[
|
[
|
||||||
"--debug", Arg.Set_int debug, " debug";
|
"--debug", Arg.Set_int debug, " debug";
|
||||||
"-d", Arg.Set_int debug, " debug";
|
"-d", Arg.Set_int debug, " debug";
|
||||||
"--no-time", Arg.Clear pp_time, " do not print solve time";
|
"--no-time", Arg.Clear pp_time, " do not print solve time";
|
||||||
|
"--stat", Arg.Set use_stats, " print statistics";
|
||||||
]
|
]
|
||||||
|> Arg.align
|
|> Arg.align
|
||||||
in
|
in
|
||||||
Arg.parse opts (fun f -> files := f :: !files) "sudoku_solve [options] <file>";
|
Arg.parse opts (fun f -> files := f :: !files) "sudoku_solve [options] <file>";
|
||||||
Log.set_debug !debug;
|
Log.set_debug !debug;
|
||||||
try List.iter (fun f -> solve_file ~pp_time:!pp_time f) !files
|
try
|
||||||
|
List.iter
|
||||||
|
(fun f -> solve_file ~pp_time:!pp_time ~use_stats:!use_stats f)
|
||||||
|
!files
|
||||||
with Failure msg | Invalid_argument msg ->
|
with Failure msg | Invalid_argument msg ->
|
||||||
Format.printf "@{<Red>Error@}:@.%s@." msg;
|
Format.printf "@{<Red>Error@}:@.%s@." msg;
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue