improve tracing, add show_trace

This commit is contained in:
Simon Cruanes 2022-09-30 22:11:41 -04:00
parent 8f563c838f
commit 3aadc640c4
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
19 changed files with 173 additions and 46 deletions

View file

@ -5,5 +5,5 @@ let default_arg =
let view_as_cc = Term.view_as_cc
end : Sidekick_smt_solver.Sigs.ARG)
let create_default ?stat ?size ~proof ~theories tst : t =
create default_arg ?stat ?size ~proof ~theories tst ()
let create_default ?stat ?size ?tracer ~proof ~theories tst : t =
create default_arg ?stat ?size ?tracer ~proof ~theories tst ()

View file

@ -45,7 +45,7 @@ end
module Decode = struct
exception Fail
let of_string ?(idx = 0) s =
let of_string ?(idx = 0) s : (int * _) option =
let i = ref idx in
let[@inline] check_not_eof () =
@ -111,7 +111,11 @@ module Decode = struct
read_map (Util.Str_map.add k v acc)
in
try Some (top ()) with Fail -> None
try
let v = top () in
let len = !i - idx in
Some (len, v)
with Fail -> None
let of_string_exn ?idx s =
match of_string ?idx s with

View file

@ -6,11 +6,11 @@ module Encode : sig
end
module Decode : sig
val of_string : ?idx:int -> string -> t option
(** Decode string.
val of_string : ?idx:int -> string -> (int * t) option
(** Decode string, and also return how many bytes were consumed.
@param idx initial index (default 0) *)
val of_string_exn : ?idx:int -> string -> t
val of_string_exn : ?idx:int -> string -> int * t
(** Parse string.
@raise Error.Error if the string is not valid bencode. *)
end

View file

@ -55,13 +55,23 @@ let emit_term_ (self : state) (t : Term.t) =
in
loop t
class type t =
object
method emit_term : Term.t -> term_ref
end
class dummy : t =
object
method emit_term _ = Tr.Entry_id.dummy
end
(* tracer *)
class t ~sink =
class concrete ~sink : t =
object
val state = { sink; emitted = T.Weak_map.create 16 }
method emit_term (t : Term.t) : term_ref = emit_term_ state t
end
let create ~sink () : t = new t ~sink
let create ~sink () : t = new concrete ~sink
let emit (self : #t) (t : T.t) : term_ref = self#emit_term t
let emit' self t : unit = ignore (emit self t : term_ref)

View file

@ -22,12 +22,21 @@ type Tr.entry_view +=
(* FIXME: remove *)
[@@ocaml.warning "-38"]
class t :
sink:Tr.Sink.t
-> object
class type t =
object
method emit_term : Term.t -> term_ref
end
(** Dummy implementation, returns {!Tr.Entry_id.dummy} *)
class dummy :
object
inherit t
method emit_term : Term.t -> term_ref
end
class concrete : sink:Tr.Sink.t -> t
(** Concrete implementation of [t] *)
val create : sink:Tr.Sink.t -> unit -> t
(** [create ~sink ()] makes a tracer that will write terms
into the given sink. *)

View file

@ -4,8 +4,16 @@
(name main)
(public_name sidekick)
(package sidekick-bin)
(modules main pure_sat_solver)
(modes native)
(libraries containers iter result sidekick.sat sidekick.core sidekick-base
sidekick.smt-solver sidekick-bin.smtlib sidekick.tef sidekick.drup
sidekick.memtrace sidekick-bin.lib)
(flags :standard -safe-string -color always -open Sidekick_util))
(executable
(name show_trace)
(modules show_trace)
(modes native)
(libraries containers sidekick.util sidekick.core sidekick.trace)
(flags :standard -safe-string -color always -open Sidekick_util))

View file

@ -22,6 +22,7 @@ let file = ref ""
let p_cnf = ref false
let p_proof = ref false
let p_model = ref false
let file_trace = ref ""
let check = ref false
let time_limit = ref 300.
let mem_limit = ref 1_000_000_000.
@ -90,6 +91,7 @@ let argspec =
" store temporary proof in given file (no cleanup)" );
"-o", Arg.Set_string proof_file, " file into which to output a proof";
"--model", Arg.Set p_model, " print model";
"--trace", Arg.Set_string file_trace, " emit trace into <file>";
"--no-model", Arg.Clear p_model, " do not print model";
( "--bool",
Arg.Symbol
@ -133,6 +135,15 @@ let check_limits () =
else if s > !mem_limit then
raise Out_of_space
let mk_tracer () =
if !file_trace = "" then
Sidekick_smt_solver.Tracer.dummy
else (
let oc = open_out_bin !file_trace in
Sidekick_smt_solver.Tracer.concrete
~sink:(Sidekick_trace.Sink.of_out_channel_using_bencode oc)
)
let main_smt ~config () : _ result =
let tst = Term.Store.create ~size:4_096 () in
@ -169,6 +180,7 @@ let main_smt ~config () : _ result =
let proof = Proof.create ~config () in
*)
let proof = Proof.dummy in
let tracer = mk_tracer () in
let solver =
(* TODO: probes, to load only required theories *)
@ -179,7 +191,7 @@ let main_smt ~config () : _ result =
(Sidekick_smt_solver.Theory.name th_bool));
[ th_bool; Process.th_ty_unin; Process.th_data; Process.th_lra ]
in
Process.Solver.create_default ~proof ~theories tst
Process.Solver.create_default ~tracer ~proof ~theories tst
in
let finally () =
@ -238,6 +250,7 @@ let main_cnf () : _ result =
in
CCFun.protect ~finally @@ fun () ->
let tst = Term.Store.create () in
(* FIXME :tracer? *)
let solver = S.SAT.create_pure_sat ~size:`Big ~proof ~stat () in
S.Dimacs.parse_file solver tst !file >>= fun () ->

View file

@ -1,6 +1,7 @@
(* pure SAT solver *)
open Sidekick_core
module Tracer = Sidekick_smt_solver.Tracer
module E = CCResult
module SS = Sidekick_sat

21
src/main/show_trace.ml Normal file
View file

@ -0,0 +1,21 @@
open Sidekick_trace
let show_file file : unit =
Log.debugf 1 (fun k -> k "(@[show-file %S@])" file);
let src = Source.of_string_using_bencode @@ CCIO.File.read_exn file in
Source.iter_all src (fun i ~tag v ->
Format.printf "[%d]: %S %a@." i tag Sidekick_util.Ser_value.pp v)
let () =
let files = ref [] in
let opts =
[
( "--bt",
Arg.Unit (fun () -> Printexc.record_backtrace true),
" enable backtraces" );
]
|> Arg.align
in
Arg.parse opts (fun f -> files := f :: !files) "show_trace [file]+";
let files = List.rev !files in
List.iter show_file files

View file

@ -40,6 +40,7 @@ type t = {
mutable last_res: res option;
stat: Stat.t;
proof: P.t;
tracer: Tracer.t; [@ocaml.warn "-69"]
theory_id_gen: Theory_id.state;
n_clause_input: int Stat.counter;
n_clause_internal: int Stat.counter;
@ -71,13 +72,15 @@ let add_theory (self : t) (th : theory) : unit =
let add_theory_l self = List.iter (add_theory self)
(* create a new solver *)
let create arg ?(stat = Stat.global) ?size ~proof ~theories tst () : t =
let create arg ?(stat = Stat.global) ?size ?(tracer = Tracer.dummy) ~proof
~theories tst () : t =
Log.debug 5 "smt-solver.create";
let si = Solver_internal.create arg ~stat ~proof tst () in
let si = Solver_internal.create arg ~tracer ~stat ~proof tst () in
let self =
{
si;
proof;
tracer;
last_res = None;
solver = Sat_solver.create ~proof ?size ~stat (SI.to_sat_plugin si);
stat;
@ -101,8 +104,8 @@ let default_arg =
let view_as_cc = Default_cc_view.view_as_cc
end : ARG)
let create_default ?stat ?size ~proof ~theories tst () : t =
create default_arg ?stat ?size ~proof ~theories tst ()
let create_default ?stat ?size ?tracer ~proof ~theories tst () : t =
create default_arg ?stat ?size ?tracer ~proof ~theories tst ()
let[@inline] solver self = self.solver
let[@inline] stats self = self.stat
@ -155,6 +158,7 @@ end)
let add_clause (self : t) (c : lit array) (proof : step_id) : unit =
let c, proof = preprocess_clause_ self c proof in
Tracer.assert_clause_arr' self.tracer c;
add_clause_nopreproc_ ~internal:false self c proof;
Perform_delayed_.top self.si self;
(* finish preproc *)

View file

@ -49,6 +49,7 @@ val create :
?stat:Stat.t ->
?size:[ `Big | `Tiny | `Small ] ->
(* TODO? ?config:Config.t -> *)
?tracer:Tracer.t ->
proof:proof_trace ->
theories:Theory.t list ->
Term.store ->
@ -71,6 +72,7 @@ val create_default :
?stat:Stat.t ->
?size:[ `Big | `Tiny | `Small ] ->
(* TODO? ?config:Config.t -> *)
?tracer:Tracer.t ->
proof:proof_trace ->
theories:Theory.t list ->
Term.store ->
@ -104,8 +106,8 @@ val add_clause_l : t -> lit list -> step_id -> unit
(** Add a clause to the solver, given as a list. *)
val assert_terms : t -> term list -> unit
(** Helper that turns each term into an atom, before adding the result
to the solver as an assertion *)
(** Helper that turns each term into an atom, before adding disjunction of
the resulting atoms to the solver as a clause assertion *)
val assert_term : t -> term -> unit
(** Helper that turns the term into an atom, before adding the result

View file

@ -58,6 +58,7 @@ type t = {
mutable level: int;
mutable complete: bool;
stat: Stat.t;
tracer: Tracer.t; [@ocaml.warning "-69"]
count_axiom: int Stat.counter;
count_conflict: int Stat.counter;
count_propagate: int Stat.counter;
@ -520,7 +521,7 @@ let add_theory_state ~st ~push_level ~pop_levels (self : t) =
self.th_states <-
Ths_cons { st; push_level; pop_levels; next = self.th_states }
let create (module A : ARG) ~stat ~proof (tst : Term.store) () : t =
let create (module A : ARG) ~stat ~tracer ~proof (tst : Term.store) () : t =
let simp = Simplify.create tst ~proof in
let cc = CC.create (module A : CC.ARG) ~size:`Big tst proof in
let preprocess = Preprocess.create ~stat ~proof ~cc ~simplify:simp tst in
@ -530,6 +531,7 @@ let create (module A : ARG) ~stat ~proof (tst : Term.store) () : t =
tst;
cc;
proof;
tracer;
th_states = Ths_nil;
stat;
simp;

View file

@ -284,4 +284,10 @@ val add_theory_state :
unit
val create :
(module ARG) -> stat:Stat.t -> proof:Proof_trace.t -> Term.store -> unit -> t
(module ARG) ->
stat:Stat.t ->
tracer:Tracer.t ->
proof:Proof_trace.t ->
Term.store ->
unit ->
t

View file

@ -4,9 +4,16 @@ module V = Ser_value
type Tr.entry_view += Assert of Term.t | Assert_clause of Lit.t list
class t (sink : Tr.Sink.t) =
class type t =
object
inherit Term.Tracer.t ~sink as emit_t
inherit Term.Tracer.t
method emit_assert_term : Term.t -> Tr.Entry_id.t
method emit_assert_clause : Lit.t list -> Tr.Entry_id.t
end
class concrete (sink : Tr.Sink.t) : t =
object
inherit Term.Tracer.concrete ~sink as emit_t
method emit_assert_term t =
let id_t = emit_t#emit_term t in
@ -29,7 +36,17 @@ class t (sink : Tr.Sink.t) =
id
end
class dummy : t =
object
inherit Term.Tracer.dummy
method emit_assert_term _ = Tr.Entry_id.dummy
method emit_assert_clause _ = Tr.Entry_id.dummy
end
let assert_term (self : #t) t = self#emit_assert_term t
let assert_term' (self : #t) t = ignore (assert_term self t : Tr.Entry_id.t)
let assert_clause (self : #t) c = self#emit_assert_clause c
let assert_clause' (self : #t) c = ignore (assert_clause self c : Tr.Entry_id.t)
let assert_clause_arr' (self : #t) c = assert_clause' self (Array.to_list c)
let dummy : #t = new dummy
let concrete ~sink = new concrete sink

View file

@ -3,9 +3,8 @@ module Tr = Sidekick_trace
type Tr.entry_view += Assert of Term.t | Assert_clause of Lit.t list
class t :
Tr.Sink.t
-> object
class type t =
object
inherit Term.Tracer.t
method emit_assert_term : Term.t -> Tr.Entry_id.t
@ -15,7 +14,16 @@ class t :
(** Emit an assertion *)
end
class dummy : t
(** Dummy tracer *)
class concrete : Tr.Sink.t -> t
(** Tracer emitting to a sink *)
val dummy : t
val concrete : sink:Tr.Sink.t -> t
val assert_term : #t -> Term.t -> Tr.Entry_id.t
val assert_term' : #t -> Term.t -> unit
val assert_clause : #t -> Lit.t list -> Tr.Entry_id.t
val assert_clause' : #t -> Lit.t list -> unit
val assert_clause_arr' : #t -> Lit.t array -> unit

View file

@ -6,3 +6,6 @@
increasing with time. *)
include Int_id.Make ()
(** Dummy id *)
let dummy : t = of_int_unsafe (-1)

View file

@ -18,6 +18,11 @@ let[@inline] emit (module Sink : S) ~tag (v : Ser_value.t) : Entry_id.t =
let[@inline] emit' (self : t) ~tag v : unit =
ignore (emit self ~tag v : Entry_id.t)
let null : t =
(module struct
let emit ~tag:_ _ = Entry_id.dummy
end)
let of_out_channel_using_bencode (oc : out_channel) : t =
let id_ = ref 0 in
let buf = Buffer.create 128 in
@ -29,6 +34,7 @@ let of_out_channel_using_bencode (oc : out_channel) : t =
let v' = Ser_value.(list [ int id; string tag; v ]) in
incr id_;
Sidekick_bencode.Encode.to_buffer buf v';
Buffer.add_char buf '\n';
Buffer.output_buffer oc buf;
Buffer.clear buf;
id

View file

@ -16,6 +16,9 @@ type t = (module S)
val emit : t -> tag:tag -> Ser_value.t -> Entry_id.t
val emit' : t -> tag:tag -> Ser_value.t -> unit
val null : t
(** Sink that writes nowhere, just eats bytes. *)
val of_out_channel_using_bencode : out_channel -> t
(** A sink that emits entries using Bencode into the given channel *)

View file

@ -19,25 +19,35 @@ let decode_bencode_entry_ =
let+ id, tag, view = tup3 int string any in
id, tag, view)
let is_whitespace_ = function
| ' ' | '\t' | '\n' -> true
| _ -> false
let of_string_using_bencode (str : string) : t =
(module struct
let iter_all f =
let i = ref 0 in
while !i < String.length str do
while !i < String.length str && is_whitespace_ str.[!i] do
incr i
done;
if !i < String.length str then (
match Sidekick_bencode.Decode.of_string ~idx:!i str with
| None -> i := String.length str
| Some b ->
| Some (len, b) ->
i := !i + len;
(match Ser_decode.run decode_bencode_entry_ b with
| Error err ->
Error.errorf "cannot decode string entry: %a" Ser_decode.Error.pp
err
| Ok (id, tag, v) -> f id ~tag v)
)
done
let get_entry id : tag * Ser_value.t =
match Sidekick_bencode.Decode.of_string str ~idx:id with
| None -> Error.errorf "invalid offset %d" id
| Some b ->
| Some (_len, b) ->
(match Ser_decode.run decode_bencode_entry_ b with
| Error err ->
Error.errorf "cannot decode string entry: %a" Ser_decode.Error.pp err