Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of get-info SMT2 command #837

Merged
merged 4 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions src/bin/common/solving_loop.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ let empty_solver_ctx = {
global = [];
}

let unsupported_opt () =
Printer.print_std "unsupported"

let main () =
let () = Dolmen_loop.Code.init [] in

Expand Down Expand Up @@ -399,8 +402,52 @@ let main () =
| ":produce-unsat-assumptions"
| ":print-success"
| ":random-seed"), _
-> Printer.print_wrn "unsupported option %s" name
| _ -> Printer.print_wrn "unsupported option %s" name
->
unsupported_opt ();
Printer.print_wrn "unsupported option '%s'" name
| _ ->
unsupported_opt ();
Printer.print_err "unknown option '%s'" name
in

let handle_get_info (st : State.t) (name: string) =
let print_std =
fun (type a) (pp :a Fmt.t) (a : a) ->
Printer.print_std "(%s %a)" name pp a
in
let pp_reason_unknown st =
let err () =
let msg = "Invalid (get-info :reason-unknown)" in
Printer.print_smtlib_err "%s" msg
in
match State.get partial_model_key st with
| None -> err ()
| Some sat ->
match SAT.get_unknown_reason sat with
| None -> err ()
| Some s ->
print_std
Format.pp_print_string
(Frontend.unknown_reason_to_string s)
in
match name with
| ":authors" ->
print_std (fun fmt -> Fmt.pf fmt "%S") "Alt-Ergo developers"
| ":error-behavior" ->
print_std Fmt.string "immediate-exit"
| ":name" ->
print_std (fun fmt -> Fmt.pf fmt "%S") "Alt-Ergo"
| ":reason-unknown" ->
pp_reason_unknown st
| ":version" ->
print_std Fmt.string Version._version
| ":all-statistics"
| ":assertion-stack-levels" ->
unsupported_opt ();
Printer.print_wrn "unsupported option '%s'" name
| _ ->
unsupported_opt ();
Printer.print_err "unknown option '%s'" name
in

let handle_stmt :
Expand Down Expand Up @@ -504,6 +551,10 @@ let main () =
st
end

| {contents = `Get_info kind; _ } ->
handle_get_info st kind;
st

| _ ->
(* TODO:
- Separate statements that should be ignored from unsupported
Expand Down
42 changes: 26 additions & 16 deletions src/lib/frontend/frontend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ open Commands
open Format
open Options

let timeout_reason_to_string = function
| Sat_solver_sig.Assume -> "Assume"
| ProofSearch -> "ProofSearch"
| ModelGen -> "ModelGen"

let unknown_reason_to_string = function
| Sat_solver_sig.Incomplete -> "Incomplete"
| Memout -> "Memout"
| Timeout t -> Format.sprintf "Timeout:%s" (timeout_reason_to_string t)

let unknown_reason_opt_to_string =
function
| None -> "Decided"
| Some r -> unknown_reason_to_string r

module E = Expr
module Ex = Explanation
module type S = sig
Expand Down Expand Up @@ -154,27 +169,20 @@ module Make(SAT : Sat_solver_sig.S) : S with type sat_env = SAT.t = struct
if Options.get_unsat_core () then Ex.singleton (Ex.RootDep {name;f;loc})
else Ex.empty

let timeout_reason_to_string = function
| None -> "(?)"
| Some SAT.NoTimeout -> "NoTimeout"
| Some SAT.Assume -> "Assume"
| Some SAT.ProofSearch -> "ProofSearch"
| Some SAT.ModelGen -> "ModelGen"

let print_model env timeout =
let print_model env unknown_reason_opt =
if Options.(get_interpretation () && get_dump_models ()) then begin
let s = timeout_reason_to_string timeout in
let s = unknown_reason_opt_to_string unknown_reason_opt in
match SAT.get_model env with
| None ->
Printer.print_fmt (Options.Output.get_fmt_diagnostic ())
"@[<v 0>It seems that no model has been computed so \
far. You may need to change your model generation strategy \
or to increase your timeouts. Returned timeout reason = %s@]" s
or to increase your timeouts. Returned unknown reason = %s@]" s

| Some (lazy model) ->
Printer.print_fmt
(Options.Output.get_fmt_diagnostic ())
"@[<v 0>; Returned timeout reason = %s@]" s;
"@[<v 0>; Returned unknown reason = %s@]" s;
Models.output_concrete_model (Options.Output.get_fmt_models ()) model
end

Expand Down Expand Up @@ -270,7 +278,7 @@ module Make(SAT : Sat_solver_sig.S) : S with type sat_env = SAT.t = struct
(* This case should mainly occur when a query has a non-unsat result,
so we want to print the status in this case. *)
print_status (Sat (d,t)) (Steps.get_steps ());
print_model env (Some SAT.NoTimeout);
print_model env None;
env, `Sat t, dep
| SAT.Unsat dep' ->
(* This case should mainly occur when a new assumption results in an unsat
Expand All @@ -280,14 +288,16 @@ module Make(SAT : Sat_solver_sig.S) : S with type sat_env = SAT.t = struct
if get_debug_unsat_core () then check_produced_unsat_core dep;
(* print_status (Inconsistent d) (Steps.get_steps ()); *)
env , `Unsat, dep
| SAT.I_dont_know {env = t; timeout} ->
| SAT.I_dont_know t ->
(* TODO: always print Unknown for why3 ? *)
let ur = SAT.get_unknown_reason t in
let status =
if timeout != NoTimeout then (Timeout (Some d))
else (Unknown (d, t))
match ur with
| Some (Sat_solver_sig.Timeout _) -> Timeout (Some d)
| _ -> Unknown (d, t)
in
print_status status (Steps.get_steps ());
print_model t (Some timeout);
print_model t ur;
(* TODO: Is it an appropriate behaviour? *)
(* if timeout != NoTimeout then raise Util.Timeout; *)
env, `Unknown t, dep
Expand Down
2 changes: 2 additions & 0 deletions src/lib/frontend/frontend.mli
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,5 @@ module type S = sig
end

module Make (SAT: Sat_solver_sig.S) : S with type sat_env = SAT.t

val unknown_reason_to_string : Sat_solver_sig.unknown_reason -> string
39 changes: 15 additions & 24 deletions src/lib/reasoners/fun_sat.ml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
add_inst: E.t -> bool;
unit_facts_cache : (E.gformula * Ex.t) ME.t ref;
last_saved_model : Models.t Lazy.t option ref;
unknown_reason : Sat_solver_sig.unknown_reason option;
}

let reset_refs () =
Expand All @@ -192,25 +193,13 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
{ env with
unit_facts_cache = ref refs.unit_facts}, guard

(* Specify the pass in which Alt-Ergo runs out of time. This information
is used to decide if the last produced model is relevant. *)
type timeout_reason =
| NoTimeout
| Assume
(* Timeout while assuming a ground formula. *)

| ProofSearch
(* Timeout while doing instantiation or backtracking phases
during the proof search. *)

| ModelGen
(* Timeout while generating a new model. *)

exception Sat of t
exception Unsat of Explanation.t
exception I_dont_know of { env : t; timeout : timeout_reason }
exception I_dont_know of t
exception IUnsat of Ex.t * SE.t list

let i_dont_know env ur =
raise (I_dont_know {env with unknown_reason = Some ur})

(*BISECT-IGNORE-BEGIN*)
module Debug = struct
Expand Down Expand Up @@ -1144,14 +1133,14 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
raise (IUnsat (expl, classes))
end

let update_model_and_return_unknown env compute_model ~timeout =
let update_model_and_return_unknown env compute_model ~unknown_reason =
try
let env = may_update_last_saved_model env compute_model in
Options.Time.unset_timeout ();
raise (I_dont_know {env; timeout })
i_dont_know env unknown_reason
with Util.Timeout when !(env.model_gen_phase) ->
(* In this case, timeout reason becomes 'ModelGen' *)
raise (I_dont_know {env; timeout = ModelGen })
i_dont_know env (Timeout ModelGen)

let model_gen_on_timeout env =
let i = Options.get_interpretation () in
Expand All @@ -1160,7 +1149,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
!(env.model_gen_phase) || (* we timeouted in model-gen-phase *)
Stdlib.(=) ti 0. (* no time allocated for extra model search *)
then
raise (I_dont_know {env; timeout = ProofSearch})
i_dont_know env (Timeout ProofSearch)
else
begin
(* Beware: models generated on timeout of ProofSearch phase may
Expand All @@ -1170,7 +1159,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
Options.Time.unset_timeout ();
Options.Time.set_timeout ti;
update_model_and_return_unknown
env i ~timeout:ProofSearch (* may becomes ModelGen *)
env i ~unknown_reason:(Timeout ProofSearch) (* may becomes ModelGen *)
end

let reduce_hypotheses tcp_cache tmp_cache env acc (hyp, gf, dep) =
Expand Down Expand Up @@ -1286,7 +1275,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
this returns a wrong model. *)
update_model_and_return_unknown
env (Options.get_last_interpretation ())
~timeout:NoTimeout (* may becomes ModelGen *)
~unknown_reason:Incomplete (* may becomes ModelGen *)
| IAuto | IGreedy ->
let gre_inst =
ME.fold
Expand Down Expand Up @@ -1314,7 +1303,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
else
update_model_and_return_unknown
env (Options.get_last_interpretation ())
~timeout:NoTimeout (* may becomes ModelGen *)
~unknown_reason:Incomplete (* may becomes ModelGen *)

let normal_instantiation env try_greedy =
Debug.print_nb_related env;
Expand Down Expand Up @@ -1763,8 +1752,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
| Util.Timeout ->
(* don't attempt to compute a model if timeout before
calling unsat function *)
raise (I_dont_know {env; timeout = Assume})

i_dont_know env (Timeout Assume)

let pred_def env f name dep _loc =
Debug.pred_def f;
Expand Down Expand Up @@ -1842,6 +1830,7 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
guards = init_guards ();
add_inst = (fun _ -> true);
last_saved_model = ref None;
unknown_reason = None;
}
in
assume env gf_true Ex.empty
Expand All @@ -1856,6 +1845,8 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct
(** returns the latest model stored in the env if any *)
let get_model env = !(env.last_saved_model)

let get_unknown_reason env = env.unknown_reason

let reinit_ctx () =
(* all_models_sat_env := None; *)
(* latest_saved_env := None;
Expand Down
21 changes: 14 additions & 7 deletions src/lib/reasoners/sat_solver_sig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@
(* We put an ml file for the module type, to avoid issues when
building the lib *)

type timeout_reason =
| Assume
| ProofSearch
| ModelGen

type unknown_reason =
| Incomplete
| Memout
| Timeout of timeout_reason

module type S = sig
type t

type timeout_reason =
| NoTimeout
| Assume
| ProofSearch
| ModelGen

exception Sat of t
exception Unsat of Explanation.t
exception I_dont_know of { env : t; timeout : timeout_reason }
exception I_dont_know of t

(* the empty sat-solver context *)
val empty : unit -> t
Expand Down Expand Up @@ -82,6 +86,9 @@ module type S = sig
(** [get_model t] produces the current model. *)
val get_model: t -> Models.t Lazy.t option

(** [get_unknown_reason t] returns the reason Alt-Ergo raised
[I_dont_know] if it did. If it did not, returns None. *)
val get_unknown_reason : t -> unknown_reason option
end


Expand Down
21 changes: 14 additions & 7 deletions src/lib/reasoners/sat_solver_sig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,22 @@
(* *)
(**************************************************************************)

type timeout_reason =
| Assume
| ProofSearch
| ModelGen

type unknown_reason =
| Incomplete
| Memout
| Timeout of timeout_reason

module type S = sig
type t

type timeout_reason =
| NoTimeout
| Assume
| ProofSearch
| ModelGen

exception Sat of t
exception Unsat of Explanation.t
exception I_dont_know of { env : t; timeout : timeout_reason }
exception I_dont_know of t

(** the empty sat-solver context *)
val empty : unit -> t
Expand Down Expand Up @@ -83,6 +87,9 @@ module type S = sig
(** [get_model t] produces the current model. *)
val get_model: t -> Models.t Lazy.t option

(** [get_unknown_reason t] returns the reason Alt-Ergo raised
[I_dont_know] if it did. If it did not, returns None. *)
val get_unknown_reason : t -> unknown_reason option
end


Expand Down
Loading
Loading