mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-15 15:26:04 -05:00
refactor(preprocess): introduce Find_foreign, runs after preprocess
This commit is contained in:
parent
3d95fc16c4
commit
721ed2eac0
11 changed files with 173 additions and 60 deletions
|
|
@ -15,6 +15,7 @@ module Solver = Solver
|
||||||
module Theory = Theory
|
module Theory = Theory
|
||||||
module Theory_id = Theory_id
|
module Theory_id = Theory_id
|
||||||
module Preprocess = Preprocess
|
module Preprocess = Preprocess
|
||||||
|
module Find_foreign = Find_foreign
|
||||||
|
|
||||||
type theory = Theory.t
|
type theory = Theory.t
|
||||||
type solver = Solver.t
|
type solver = Solver.t
|
||||||
|
|
|
||||||
37
src/smt/find_foreign.ml
Normal file
37
src/smt/find_foreign.ml
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
open Sidekick_core
|
||||||
|
|
||||||
|
module type ACTIONS = sig
|
||||||
|
val declare_need_th_combination : Term.t -> unit
|
||||||
|
(** Declare that this term is a foreign variable in some other subterm. *)
|
||||||
|
|
||||||
|
val add_lit_for_bool_term : ?default_pol:bool -> Term.t -> unit
|
||||||
|
(** Add the (boolean) term to the SAT solver *)
|
||||||
|
end
|
||||||
|
|
||||||
|
type actions = (module ACTIONS)
|
||||||
|
type hook = actions -> is_sub:bool -> Term.t -> unit
|
||||||
|
type t = { seen: unit Term.Tbl.t; mutable hooks: hook list }
|
||||||
|
|
||||||
|
let create () : t = { hooks = []; seen = Term.Tbl.create 8 }
|
||||||
|
let add_hook self h = self.hooks <- h :: self.hooks
|
||||||
|
|
||||||
|
let traverse_term (self : t) ((module A) as acts : actions) (t : Term.t) : unit
|
||||||
|
=
|
||||||
|
let rec loop ~is_sub t =
|
||||||
|
if (not (Term.is_a_type t)) && not (Term.Tbl.mem self.seen t) then (
|
||||||
|
Term.Tbl.add self.seen t ();
|
||||||
|
Log.debugf 10 (fun k -> k "(@[find-foreign-in@ %a@])" Term.pp t);
|
||||||
|
|
||||||
|
(* boolean subterm: need a literal *)
|
||||||
|
if Term.is_bool (Term.ty t) then A.add_lit_for_bool_term t;
|
||||||
|
|
||||||
|
(* call hooks *)
|
||||||
|
List.iter (fun (h : hook) -> h acts ~is_sub t) self.hooks;
|
||||||
|
|
||||||
|
match Term.open_eq t with
|
||||||
|
| Some (_, _) when not is_sub ->
|
||||||
|
Term.iter_shallow t ~f:(fun _ u -> loop ~is_sub:false u)
|
||||||
|
| _ -> Term.iter_shallow t ~f:(fun _ u -> loop ~is_sub:true u)
|
||||||
|
)
|
||||||
|
in
|
||||||
|
loop ~is_sub:false t
|
||||||
28
src/smt/find_foreign.mli
Normal file
28
src/smt/find_foreign.mli
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
(** Find foreign variables.
|
||||||
|
|
||||||
|
This module is a modular discoverer of foreign variables (and boolean terms).
|
||||||
|
It should run after preprocessing of terms.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open Sidekick_core
|
||||||
|
|
||||||
|
module type ACTIONS = sig
|
||||||
|
val declare_need_th_combination : Term.t -> unit
|
||||||
|
(** Declare that this term is a foreign variable in some other subterm. *)
|
||||||
|
|
||||||
|
val add_lit_for_bool_term : ?default_pol:bool -> Term.t -> unit
|
||||||
|
(** Add the (boolean) term to the SAT solver *)
|
||||||
|
end
|
||||||
|
|
||||||
|
type actions = (module ACTIONS)
|
||||||
|
type t
|
||||||
|
type hook = actions -> is_sub:bool -> Term.t -> unit
|
||||||
|
|
||||||
|
val create : unit -> t
|
||||||
|
|
||||||
|
val add_hook : t -> hook -> unit
|
||||||
|
(** Register a hook to detect foreign subterms *)
|
||||||
|
|
||||||
|
val traverse_term : t -> actions -> Term.t -> unit
|
||||||
|
(** Traverse subterms of this term to detect foreign variables
|
||||||
|
and boolean subterms. *)
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
open Sidekick_core
|
|
||||||
open Sigs
|
open Sigs
|
||||||
module T = Term
|
module T = Term
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ module type PREPROCESS_ACTS = sig
|
||||||
val mk_lit : ?sign:bool -> term -> lit
|
val mk_lit : ?sign:bool -> term -> lit
|
||||||
val add_clause : lit list -> step_id -> unit
|
val add_clause : lit list -> step_id -> unit
|
||||||
val add_lit : ?default_pol:bool -> lit -> unit
|
val add_lit : ?default_pol:bool -> lit -> unit
|
||||||
val declare_need_th_combination : term -> unit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
type preprocess_actions = (module PREPROCESS_ACTS)
|
type preprocess_actions = (module PREPROCESS_ACTS)
|
||||||
|
|
@ -49,7 +48,7 @@ let preprocess_term_ (self : t) ((module A : PREPROCESS_ACTS) as acts)
|
||||||
match Term.Tbl.find_opt self.preprocessed t0 with
|
match Term.Tbl.find_opt self.preprocessed t0 with
|
||||||
| Some u -> u
|
| Some u -> u
|
||||||
| None ->
|
| None ->
|
||||||
Log.debugf 50 (fun k -> k "(@[smt.preprocess@ %a@])" Term.pp_debug t0);
|
Log.debugf 50 (fun k -> k "(@[smt.preprocess@ %a@])" Term.pp t0);
|
||||||
|
|
||||||
(* try hooks first *)
|
(* try hooks first *)
|
||||||
let t =
|
let t =
|
||||||
|
|
@ -82,21 +81,6 @@ let preprocess_term_ (self : t) ((module A : PREPROCESS_ACTS) as acts)
|
||||||
in
|
in
|
||||||
|
|
||||||
Term.Tbl.add self.preprocessed t0 t;
|
Term.Tbl.add self.preprocessed t0 t;
|
||||||
|
|
||||||
(* signal boolean subterms, so as to decide them
|
|
||||||
in the SAT solver *)
|
|
||||||
if Term.is_bool (Term.ty t) then (
|
|
||||||
Log.debugf 5 (fun k ->
|
|
||||||
k "(@[solver.map-bool-subterm-to-lit@ :subterm %a@])" Term.pp t);
|
|
||||||
|
|
||||||
(* ensure that SAT solver has a boolean atom for [t] *)
|
|
||||||
let lit = Lit.atom self.tst t in
|
|
||||||
A.add_lit lit;
|
|
||||||
|
|
||||||
(* also map [sub] to this atom in the congruence closure, for propagation *)
|
|
||||||
(* FIXME: use a delayed action "DA_declare_cc_lit (t, lit)" instead *)
|
|
||||||
CC.set_as_lit self.cc (CC.add_term self.cc t) lit
|
|
||||||
);
|
|
||||||
t
|
t
|
||||||
in
|
in
|
||||||
preproc_rec_ ~is_sub:false t
|
preproc_rec_ ~is_sub:false t
|
||||||
|
|
@ -114,8 +98,7 @@ let simplify_and_preproc_lit (self : t) acts (lit : Lit.t) :
|
||||||
| None -> t, None
|
| None -> t, None
|
||||||
| Some (u, pr_t_u) ->
|
| Some (u, pr_t_u) ->
|
||||||
Log.debugf 30 (fun k ->
|
Log.debugf 30 (fun k ->
|
||||||
k "(@[smt-solver.simplify@ :t %a@ :into %a@])" Term.pp_debug t
|
k "(@[smt-solver.simplify@ :t %a@ :into %a@])" Term.pp t Term.pp u);
|
||||||
Term.pp_debug u);
|
|
||||||
u, Some pr_t_u
|
u, Some pr_t_u
|
||||||
in
|
in
|
||||||
let v = preprocess_term_ self acts u in
|
let v = preprocess_term_ self acts u in
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,6 @@ module type PREPROCESS_ACTS = sig
|
||||||
|
|
||||||
val add_lit : ?default_pol:bool -> lit -> unit
|
val add_lit : ?default_pol:bool -> lit -> unit
|
||||||
(** Ensure the literal will be decided/handled by the SAT solver. *)
|
(** Ensure the literal will be decided/handled by the SAT solver. *)
|
||||||
|
|
||||||
val declare_need_th_combination : term -> unit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
type preprocess_actions = (module PREPROCESS_ACTS)
|
type preprocess_actions = (module PREPROCESS_ACTS)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
open Sigs
|
open Sigs
|
||||||
module Ty = Term
|
|
||||||
|
|
||||||
type th_states =
|
type th_states =
|
||||||
| Ths_nil
|
| Ths_nil
|
||||||
|
|
@ -27,6 +26,7 @@ module Registry = Registry
|
||||||
type delayed_action =
|
type delayed_action =
|
||||||
| DA_add_clause of { c: lit list; pr: step_id; keep: bool }
|
| DA_add_clause of { c: lit list; pr: step_id; keep: bool }
|
||||||
| DA_add_lit of { default_pol: bool option; lit: lit }
|
| DA_add_lit of { default_pol: bool option; lit: lit }
|
||||||
|
| DA_add_preprocessed_lit of { default_pol: bool option; lit: lit }
|
||||||
|
|
||||||
type preprocess_hook =
|
type preprocess_hook =
|
||||||
Preprocess.t ->
|
Preprocess.t ->
|
||||||
|
|
@ -48,6 +48,7 @@ type t = {
|
||||||
mutable on_partial_check: (t -> theory_actions -> lit Iter.t -> unit) list;
|
mutable on_partial_check: (t -> theory_actions -> lit Iter.t -> unit) list;
|
||||||
mutable on_final_check: (t -> theory_actions -> lit Iter.t -> unit) list;
|
mutable on_final_check: (t -> theory_actions -> lit Iter.t -> unit) list;
|
||||||
preprocess: Preprocess.t;
|
preprocess: Preprocess.t;
|
||||||
|
find_foreign: Find_foreign.t;
|
||||||
mutable model_ask: model_ask_hook list;
|
mutable model_ask: model_ask_hook list;
|
||||||
mutable model_complete: model_completion_hook list;
|
mutable model_complete: model_completion_hook list;
|
||||||
simp: Simplify.t;
|
simp: Simplify.t;
|
||||||
|
|
@ -83,6 +84,7 @@ let[@inline] has_delayed_actions self =
|
||||||
not (Queue.is_empty self.delayed_actions)
|
not (Queue.is_empty self.delayed_actions)
|
||||||
|
|
||||||
let on_preprocess self f = Preprocess.on_preprocess self.preprocess f
|
let on_preprocess self f = Preprocess.on_preprocess self.preprocess f
|
||||||
|
let on_find_foreign self f = Find_foreign.add_hook self.find_foreign f
|
||||||
|
|
||||||
let on_model ?ask ?complete self =
|
let on_model ?ask ?complete self =
|
||||||
Option.iter (fun f -> self.model_ask <- f :: self.model_ask) ask;
|
Option.iter (fun f -> self.model_ask <- f :: self.model_ask) ask;
|
||||||
|
|
@ -118,6 +120,9 @@ let add_sat_lit_ _self ?default_pol (acts : theory_actions) (lit : Lit.t) : unit
|
||||||
let delayed_add_lit (self : t) ?default_pol (lit : Lit.t) : unit =
|
let delayed_add_lit (self : t) ?default_pol (lit : Lit.t) : unit =
|
||||||
Queue.push (DA_add_lit { default_pol; lit }) self.delayed_actions
|
Queue.push (DA_add_lit { default_pol; lit }) self.delayed_actions
|
||||||
|
|
||||||
|
let delayed_add_preprocessed_lit (self : t) ?default_pol (lit : Lit.t) : unit =
|
||||||
|
Queue.push (DA_add_preprocessed_lit { default_pol; lit }) self.delayed_actions
|
||||||
|
|
||||||
let delayed_add_clause (self : t) ~keep (c : Lit.t list) (pr : step_id) : unit =
|
let delayed_add_clause (self : t) ~keep (c : Lit.t list) (pr : step_id) : unit =
|
||||||
Queue.push (DA_add_clause { c; pr; keep }) self.delayed_actions
|
Queue.push (DA_add_clause { c; pr; keep }) self.delayed_actions
|
||||||
|
|
||||||
|
|
@ -127,11 +132,34 @@ let preprocess_acts (self : t) : Preprocess.preprocess_actions =
|
||||||
let mk_lit ?sign t : Lit.t = Lit.atom ?sign self.tst t
|
let mk_lit ?sign t : Lit.t = Lit.atom ?sign self.tst t
|
||||||
let add_clause c pr = delayed_add_clause self ~keep:true c pr
|
let add_clause c pr = delayed_add_clause self ~keep:true c pr
|
||||||
let add_lit ?default_pol lit = delayed_add_lit self ?default_pol lit
|
let add_lit ?default_pol lit = delayed_add_lit self ?default_pol lit
|
||||||
|
end)
|
||||||
|
|
||||||
|
let find_foreign_acts (self : t) : Find_foreign.actions =
|
||||||
|
(module struct
|
||||||
|
let add_lit_for_bool_term ?default_pol t =
|
||||||
|
let lit = Lit.atom self.tst t in
|
||||||
|
(* [lit] has already been preprocessed, do not preprocess it
|
||||||
|
again lest we meet an infinite recursion *)
|
||||||
|
delayed_add_preprocessed_lit self ?default_pol lit
|
||||||
|
|
||||||
let declare_need_th_combination t =
|
let declare_need_th_combination t =
|
||||||
Th_combination.add_term_needing_combination self.th_comb t
|
Th_combination.add_term_needing_combination self.th_comb t
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
(* find boolean subterms/foreign variables in [t] *)
|
||||||
|
let find_foreign_vars_in (self : t) (t : Term.t) : unit =
|
||||||
|
let acts = find_foreign_acts self in
|
||||||
|
Find_foreign.traverse_term self.find_foreign acts t
|
||||||
|
|
||||||
|
let find_foreign_vars_in_lit (self : t) (lit : Lit.t) =
|
||||||
|
find_foreign_vars_in self (Lit.term lit)
|
||||||
|
|
||||||
|
let find_foreign_vars_in_lits (self : t) (c : Lit.t list) =
|
||||||
|
List.iter (find_foreign_vars_in_lit self) c
|
||||||
|
|
||||||
|
let find_foreign_vars_in_lit_arr (self : t) (c : Lit.t array) =
|
||||||
|
Array.iter (find_foreign_vars_in_lit self) c
|
||||||
|
|
||||||
let push_decision (self : t) (acts : theory_actions) (lit : lit) : unit =
|
let push_decision (self : t) (acts : theory_actions) (lit : lit) : unit =
|
||||||
let (module A) = acts in
|
let (module A) = acts in
|
||||||
(* make sure the literal is preprocessed *)
|
(* make sure the literal is preprocessed *)
|
||||||
|
|
@ -139,6 +167,7 @@ let push_decision (self : t) (acts : theory_actions) (lit : lit) : unit =
|
||||||
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self)
|
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self)
|
||||||
lit
|
lit
|
||||||
in
|
in
|
||||||
|
find_foreign_vars_in_lit self lit;
|
||||||
let sign = Lit.sign lit in
|
let sign = Lit.sign lit in
|
||||||
A.add_decision_lit (Lit.abs lit) sign
|
A.add_decision_lit (Lit.abs lit) sign
|
||||||
|
|
||||||
|
|
@ -160,12 +189,22 @@ module Perform_delayed (A : PERFORM_ACTS) = struct
|
||||||
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c
|
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c
|
||||||
pr_c
|
pr_c
|
||||||
in
|
in
|
||||||
|
find_foreign_vars_in_lits self c';
|
||||||
A.add_clause self acts ~keep c' pr_c'
|
A.add_clause self acts ~keep c' pr_c'
|
||||||
| DA_add_lit { default_pol; lit } ->
|
| DA_add_lit { default_pol; lit } ->
|
||||||
let lit, _ =
|
let lit, _ =
|
||||||
Preprocess.simplify_and_preproc_lit self.preprocess
|
Preprocess.simplify_and_preproc_lit self.preprocess
|
||||||
(preprocess_acts self) lit
|
(preprocess_acts self) lit
|
||||||
in
|
in
|
||||||
|
let t = Lit.term lit in
|
||||||
|
find_foreign_vars_in_lit self lit;
|
||||||
|
CC.set_as_lit self.cc (CC.add_term self.cc t) lit;
|
||||||
|
A.add_lit self acts ?default_pol lit
|
||||||
|
| DA_add_preprocessed_lit { default_pol; lit } ->
|
||||||
|
let t = Lit.term lit in
|
||||||
|
Log.debugf 5 (fun k ->
|
||||||
|
k "(@[solver.map-bool-subterm-to-lit@ :subterm %a@])" Term.pp t);
|
||||||
|
CC.set_as_lit self.cc (CC.add_term self.cc t) lit;
|
||||||
A.add_lit self acts ?default_pol lit
|
A.add_lit self acts ?default_pol lit
|
||||||
done
|
done
|
||||||
end
|
end
|
||||||
|
|
@ -182,26 +221,43 @@ module Perform_delayed_th = Perform_delayed (struct
|
||||||
end)
|
end)
|
||||||
|
|
||||||
let[@inline] preprocess self = self.preprocess
|
let[@inline] preprocess self = self.preprocess
|
||||||
|
let[@inline] find_foreign self = self.find_foreign
|
||||||
|
|
||||||
let preprocess_clause self c pr =
|
let preprocess_clause self c pr =
|
||||||
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c pr
|
let c, pr =
|
||||||
|
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c pr
|
||||||
|
in
|
||||||
|
find_foreign_vars_in_lits self c;
|
||||||
|
c, pr
|
||||||
|
|
||||||
let preprocess_clause_array self c pr =
|
let preprocess_clause_array self c pr =
|
||||||
Preprocess.preprocess_clause_array self.preprocess (preprocess_acts self) c pr
|
let c, pr =
|
||||||
|
Preprocess.preprocess_clause_array self.preprocess (preprocess_acts self) c
|
||||||
|
pr
|
||||||
|
in
|
||||||
|
find_foreign_vars_in_lit_arr self c;
|
||||||
|
c, pr
|
||||||
|
|
||||||
let simplify_and_preproc_lit self lit =
|
let simplify_and_preproc_lit self lit =
|
||||||
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self) lit
|
let lit, pr =
|
||||||
|
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self)
|
||||||
|
lit
|
||||||
|
in
|
||||||
|
find_foreign_vars_in_lit self lit;
|
||||||
|
lit, pr
|
||||||
|
|
||||||
let[@inline] add_clause_temp self _acts c (proof : step_id) : unit =
|
let add_clause_temp self _acts c (proof : step_id) : unit =
|
||||||
let c, proof =
|
let c, proof =
|
||||||
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c proof
|
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c proof
|
||||||
in
|
in
|
||||||
|
find_foreign_vars_in_lits self c;
|
||||||
delayed_add_clause self ~keep:false c proof
|
delayed_add_clause self ~keep:false c proof
|
||||||
|
|
||||||
let[@inline] add_clause_permanent self _acts c (proof : step_id) : unit =
|
let add_clause_permanent self _acts c (proof : step_id) : unit =
|
||||||
let c, proof =
|
let c, proof =
|
||||||
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c proof
|
Preprocess.preprocess_clause self.preprocess (preprocess_acts self) c proof
|
||||||
in
|
in
|
||||||
|
find_foreign_vars_in_lits self c;
|
||||||
delayed_add_clause self ~keep:true c proof
|
delayed_add_clause self ~keep:true c proof
|
||||||
|
|
||||||
let[@inline] mk_lit self ?sign t : lit = Lit.atom ?sign self.tst t
|
let[@inline] mk_lit self ?sign t : lit = Lit.atom ?sign self.tst t
|
||||||
|
|
@ -221,6 +277,7 @@ let add_lit_t self _acts ?sign t =
|
||||||
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self)
|
Preprocess.simplify_and_preproc_lit self.preprocess (preprocess_acts self)
|
||||||
lit
|
lit
|
||||||
in
|
in
|
||||||
|
find_foreign_vars_in_lit self lit;
|
||||||
delayed_add_lit self lit
|
delayed_add_lit self lit
|
||||||
|
|
||||||
let on_final_check self f = self.on_final_check <- f :: self.on_final_check
|
let on_final_check self f = self.on_final_check <- f :: self.on_final_check
|
||||||
|
|
@ -388,10 +445,8 @@ let assert_lits_ ~final (self : t) (acts : theory_actions) (lits : Lit.t Iter.t)
|
||||||
if new_intf_eqns <> [] then (
|
if new_intf_eqns <> [] then (
|
||||||
let (module A) = acts in
|
let (module A) = acts in
|
||||||
List.iter (fun lit -> A.add_lit ~default_pol:false lit) new_intf_eqns
|
List.iter (fun lit -> A.add_lit ~default_pol:false lit) new_intf_eqns
|
||||||
);
|
) else if not (has_delayed_actions self) then (
|
||||||
|
(* if theory combination didn't add new clauses, compute a model *)
|
||||||
(* if theory combination didn't add new clauses, compute a model *)
|
|
||||||
if not (has_delayed_actions self) then (
|
|
||||||
let m = mk_model_ self lits in
|
let m = mk_model_ self lits in
|
||||||
self.last_model <- Some m
|
self.last_model <- Some m
|
||||||
)
|
)
|
||||||
|
|
@ -469,6 +524,7 @@ let create (module A : ARG) ~stat ~proof (tst : Term.store) () : t =
|
||||||
let simp = Simplify.create tst ~proof in
|
let simp = Simplify.create tst ~proof in
|
||||||
let cc = CC.create (module A : CC.ARG) ~size:`Big 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
|
let preprocess = Preprocess.create ~stat ~proof ~cc ~simplify:simp tst in
|
||||||
|
let find_foreign = Find_foreign.create () in
|
||||||
let self =
|
let self =
|
||||||
{
|
{
|
||||||
tst;
|
tst;
|
||||||
|
|
@ -478,6 +534,7 @@ let create (module A : ARG) ~stat ~proof (tst : Term.store) () : t =
|
||||||
stat;
|
stat;
|
||||||
simp;
|
simp;
|
||||||
preprocess;
|
preprocess;
|
||||||
|
find_foreign;
|
||||||
last_model = None;
|
last_model = None;
|
||||||
seen_types = Term.Weak_set.create 8;
|
seen_types = Term.Weak_set.create 8;
|
||||||
th_comb = Th_combination.create ~stat tst;
|
th_comb = Th_combination.create ~stat tst;
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,13 @@ val preprocess_clause_array : t -> lit array -> step_id -> lit array * step_id
|
||||||
val simplify_and_preproc_lit : t -> lit -> lit * step_id option
|
val simplify_and_preproc_lit : t -> lit -> lit * step_id option
|
||||||
(** Simplify literal then preprocess it *)
|
(** Simplify literal then preprocess it *)
|
||||||
|
|
||||||
|
(** {3 Finding foreign variables} *)
|
||||||
|
|
||||||
|
val find_foreign : t -> Find_foreign.t
|
||||||
|
|
||||||
|
val on_find_foreign : t -> Find_foreign.hook -> unit
|
||||||
|
(** Add a hook for finding foreign variables *)
|
||||||
|
|
||||||
(** {3 hooks for the theory} *)
|
(** {3 hooks for the theory} *)
|
||||||
|
|
||||||
val raise_conflict : t -> theory_actions -> lit list -> step_id -> 'a
|
val raise_conflict : t -> theory_actions -> lit list -> step_id -> 'a
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ let processed_ (self : t) t : bool =
|
||||||
| Some set -> T.Set.mem t set
|
| Some set -> T.Set.mem t set
|
||||||
|
|
||||||
let add_term_needing_combination (self : t) (t : T.t) : unit =
|
let add_term_needing_combination (self : t) (t : T.t) : unit =
|
||||||
if not (processed_ self t) then (
|
if not (processed_ self t) && not (T.is_bool @@ T.ty t) then (
|
||||||
Log.debugf 50 (fun k -> k "(@[th.comb.add-term-needing-comb@ %a@])" T.pp t);
|
Log.debugf 50 (fun k -> k "(@[th.comb.add-term-needing-comb@ %a@])" T.pp t);
|
||||||
Vec.push self.unprocessed t
|
Vec.push self.unprocessed t
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -148,8 +148,7 @@ end = struct
|
||||||
let fresh_term self ~for_t ~pre ty =
|
let fresh_term self ~for_t ~pre ty =
|
||||||
let u = Gensym.fresh_term self.gensym ~pre ty in
|
let u = Gensym.fresh_term self.gensym ~pre ty in
|
||||||
Log.debugf 20 (fun k ->
|
Log.debugf 20 (fun k ->
|
||||||
k "(@[sidekick.bool.proxy@ :t %a@ :for %a@])" T.pp_debug u T.pp_debug
|
k "(@[sidekick.bool.proxy@ :t %a@ :for %a@])" T.pp u T.pp for_t);
|
||||||
for_t);
|
|
||||||
assert (Term.equal ty (T.ty u));
|
assert (Term.equal ty (T.ty u));
|
||||||
u
|
u
|
||||||
|
|
||||||
|
|
@ -160,7 +159,7 @@ end = struct
|
||||||
(* TODO: polarity? *)
|
(* TODO: polarity? *)
|
||||||
let cnf (self : state) (_preproc : SMT.Preprocess.t) ~is_sub:_ ~recurse
|
let cnf (self : state) (_preproc : SMT.Preprocess.t) ~is_sub:_ ~recurse
|
||||||
(module PA : SI.PREPROCESS_ACTS) (t : T.t) : T.t option =
|
(module PA : SI.PREPROCESS_ACTS) (t : T.t) : T.t option =
|
||||||
Log.debugf 50 (fun k -> k "(@[th-bool.cnf@ %a@])" T.pp_debug t);
|
Log.debugf 50 (fun k -> k "(@[th-bool.cnf@ %a@])" T.pp t);
|
||||||
let[@inline] mk_step_ r = Proof_trace.add_step PA.proof r in
|
let[@inline] mk_step_ r = Proof_trace.add_step PA.proof r in
|
||||||
|
|
||||||
(* handle boolean equality *)
|
(* handle boolean equality *)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ module SimpVar : Linear_expr.VAR with type t = Term.t and type lit = Tag.t =
|
||||||
struct
|
struct
|
||||||
type t = Term.t
|
type t = Term.t
|
||||||
|
|
||||||
let pp = Term.pp_debug
|
let pp = Term.pp
|
||||||
let compare = Term.compare
|
let compare = Term.compare
|
||||||
|
|
||||||
type lit = Tag.t
|
type lit = Tag.t
|
||||||
|
|
@ -62,7 +62,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
match A.view_as_lra t with
|
match A.view_as_lra t with
|
||||||
| LRA_other _ -> LE.monomial1 t
|
| LRA_other _ -> LE.monomial1 t
|
||||||
| LRA_pred _ ->
|
| LRA_pred _ ->
|
||||||
Error.errorf "type error: in linexp, LRA predicate %a" Term.pp_debug t
|
Error.errorf "type error: in linexp, LRA predicate %a" Term.pp t
|
||||||
| LRA_op (op, t1, t2) ->
|
| LRA_op (op, t1, t2) ->
|
||||||
let t1 = as_linexp t1 in
|
let t1 = as_linexp t1 in
|
||||||
let t2 = as_linexp t2 in
|
let t2 = as_linexp t2 in
|
||||||
|
|
@ -247,7 +247,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
k "(@[lra.encode-linexp@ `@[%a@]`@ :into-var %a@])" LE_.Comb.pp
|
k "(@[lra.encode-linexp@ `@[%a@]`@ :into-var %a@])" LE_.Comb.pp
|
||||||
le_comb Term.pp_debug proxy);
|
le_comb Term.pp proxy);
|
||||||
|
|
||||||
LE_.Comb.iter (fun v _ -> SimpSolver.add_var self.simplex v) le_comb;
|
LE_.Comb.iter (fun v _ -> SimpSolver.add_var self.simplex v) le_comb;
|
||||||
SimpSolver.define self.simplex proxy (LE_.Comb.to_list le_comb);
|
SimpSolver.define self.simplex proxy (LE_.Comb.to_list le_comb);
|
||||||
|
|
@ -293,20 +293,19 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
|
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
k "(@[lra.encode-linexp.to-term@ `@[%a@]`@ :new-t %a@])" LE_.Comb.pp
|
k "(@[lra.encode-linexp.to-term@ `@[%a@]`@ :new-t %a@])" LE_.Comb.pp
|
||||||
le_comb Term.pp_debug proxy);
|
le_comb Term.pp proxy);
|
||||||
|
|
||||||
proxy, A.Q.one)
|
proxy, A.Q.one)
|
||||||
|
|
||||||
(* preprocess linear expressions away *)
|
(* preprocess linear expressions away *)
|
||||||
let preproc_lra (self : state) _preproc ~is_sub ~recurse
|
let preproc_lra (self : state) _preproc ~is_sub:_ ~recurse
|
||||||
(module PA : SI.PREPROCESS_ACTS) (t : Term.t) : Term.t option =
|
(module PA : SI.PREPROCESS_ACTS) (t : Term.t) : Term.t option =
|
||||||
Log.debugf 50 (fun k -> k "(@[lra.preprocess@ %a@])" Term.pp_debug t);
|
Log.debugf 50 (fun k -> k "(@[lra.preprocess@ %a@])" Term.pp t);
|
||||||
let tst = self.tst in
|
let tst = self.tst in
|
||||||
|
|
||||||
(* tell the CC this term exists *)
|
(* tell the CC this term exists *)
|
||||||
let declare_term_to_cc ~sub:_ t =
|
let declare_term_to_cc ~sub:_ t =
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k -> k "(@[lra.declare-term-to-cc@ %a@])" Term.pp t);
|
||||||
k "(@[lra.declare-term-to-cc@ %a@])" Term.pp_debug t);
|
|
||||||
ignore (CC.add_term (SMT.Preprocess.cc _preproc) t : E_node.t)
|
ignore (CC.add_term (SMT.Preprocess.cc _preproc) t : E_node.t)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -331,7 +330,8 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(* TODO: box [t], recurse on [t1 <= t2] and [t1 >= t2],
|
(* TODO: box [t], recurse on [t1 <= t2] and [t1 >= t2],
|
||||||
add 3 atomic clauses, return [box t] *)
|
add 3 atomic clauses, return [box t] *)
|
||||||
let _, t = Term.abs self.tst t in
|
let _, t = Term.abs self.tst t in
|
||||||
if not (Term.Tbl.mem self.encoded_eqs t) then (
|
let box_t = Box.box self.tst t in
|
||||||
|
if not (Term.Tbl.mem self.encoded_eqs box_t) then (
|
||||||
(* preprocess t1, t2 recursively *)
|
(* preprocess t1, t2 recursively *)
|
||||||
let t1 = recurse t1 in
|
let t1 = recurse t1 in
|
||||||
let t2 = recurse t2 in
|
let t2 = recurse t2 in
|
||||||
|
|
@ -339,10 +339,10 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
let u1 = A.mk_lra tst (LRA_pred (Leq, t1, t2)) in
|
let u1 = A.mk_lra tst (LRA_pred (Leq, t1, t2)) in
|
||||||
let u2 = A.mk_lra tst (LRA_pred (Geq, t1, t2)) in
|
let u2 = A.mk_lra tst (LRA_pred (Geq, t1, t2)) in
|
||||||
|
|
||||||
Term.Tbl.add self.encoded_eqs t ();
|
Term.Tbl.add self.encoded_eqs box_t ();
|
||||||
|
|
||||||
(* encode [t <=> (u1 /\ u2)] *)
|
(* encode [t <=> (u1 /\ u2)] *)
|
||||||
let lit_t = PA.mk_lit t in
|
let lit_t = PA.mk_lit box_t in
|
||||||
let lit_u1 = PA.mk_lit u1 in
|
let lit_u1 = PA.mk_lit u1 in
|
||||||
let lit_u2 = PA.mk_lit u2 in
|
let lit_u2 = PA.mk_lit u2 in
|
||||||
add_clause_lra_ (module PA) [ Lit.neg lit_t; lit_u1 ];
|
add_clause_lra_ (module PA) [ Lit.neg lit_t; lit_u1 ];
|
||||||
|
|
@ -383,14 +383,14 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
op
|
op
|
||||||
in
|
in
|
||||||
|
|
||||||
let lit = fresh_lit self ~mk_lit:PA.mk_lit ~pre:"$lra" in
|
let lit = PA.mk_lit ~sign:true box_t in
|
||||||
let constr = SimpSolver.Constraint.mk v op q in
|
let constr = SimpSolver.Constraint.mk v op q in
|
||||||
SimpSolver.declare_bound self.simplex constr (Tag.Lit lit);
|
SimpSolver.declare_bound self.simplex constr (Tag.Lit lit);
|
||||||
Term.Tbl.add self.simp_preds (Lit.term lit) (v, op, q);
|
Term.Tbl.add self.simp_preds box_t (v, op, q);
|
||||||
Term.Tbl.add self.encoded_lits (Lit.term lit) box_t;
|
Term.Tbl.add self.encoded_lits box_t box_t;
|
||||||
|
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
k "(@[lra.preproc@ :t %a@ :to-constr %a@])" Term.pp_debug t
|
k "(@[lra.preproc@ :t %a@ :to-constr %a@])" Term.pp t
|
||||||
SimpSolver.Constraint.pp constr);
|
SimpSolver.Constraint.pp constr);
|
||||||
|
|
||||||
Some box_t
|
Some box_t
|
||||||
|
|
@ -404,11 +404,15 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
Term.Tbl.add self.simp_defined t (box_t, le);
|
Term.Tbl.add self.simp_defined t (box_t, le);
|
||||||
Some box_t)
|
Some box_t)
|
||||||
| LRA_const _n -> None
|
| LRA_const _n -> None
|
||||||
| LRA_other t when A.has_ty_real t && is_sub ->
|
|
||||||
PA.declare_need_th_combination t;
|
|
||||||
None
|
|
||||||
| LRA_other _ -> None
|
| LRA_other _ -> None
|
||||||
|
|
||||||
|
let find_foreign (acts : SMT.Find_foreign.actions) ~is_sub (t : Term.t) : unit
|
||||||
|
=
|
||||||
|
if A.has_ty_real t && is_sub then (
|
||||||
|
let (module FA : SMT.Find_foreign.ACTIONS) = acts in
|
||||||
|
FA.declare_need_th_combination t
|
||||||
|
)
|
||||||
|
|
||||||
let simplify (self : state) (_recurse : _) (t : Term.t) :
|
let simplify (self : state) (_recurse : _) (t : Term.t) :
|
||||||
(Term.t * Proof_step.id Iter.t) option =
|
(Term.t * Proof_step.id Iter.t) option =
|
||||||
let proof_eq t u =
|
let proof_eq t u =
|
||||||
|
|
@ -526,7 +530,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
|
|
||||||
let add_local_eq_t (self : state) si acts t1 t2 ~tag : unit =
|
let add_local_eq_t (self : state) si acts t1 t2 ~tag : unit =
|
||||||
Log.debugf 20 (fun k ->
|
Log.debugf 20 (fun k ->
|
||||||
k "(@[lra.add-local-eq@ %a@ %a@])" Term.pp_debug t1 Term.pp_debug t2);
|
k "(@[lra.add-local-eq@ %a@ %a@])" Term.pp t1 Term.pp t2);
|
||||||
reset_res_ self;
|
reset_res_ self;
|
||||||
let t1, t2 =
|
let t1, t2 =
|
||||||
if Term.compare t1 t2 > 0 then
|
if Term.compare t1 t2 > 0 then
|
||||||
|
|
@ -618,8 +622,8 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
match Term.Tbl.get self.simp_preds lit_t, A.view_as_lra lit_t with
|
match Term.Tbl.get self.simp_preds lit_t, A.view_as_lra lit_t with
|
||||||
| Some (v, op, q), _ ->
|
| Some (v, op, q), _ ->
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
k "(@[lra.partial-check.add@ :lit %a@ :lit-t %a@])" Lit.pp lit
|
k "(@[lra.partial-check.add@ :lit %a@ :lit-t %a@])" Lit.pp lit Term.pp
|
||||||
Term.pp_debug lit_t);
|
lit_t);
|
||||||
|
|
||||||
(* need to account for the literal's sign *)
|
(* need to account for the literal's sign *)
|
||||||
let op =
|
let op =
|
||||||
|
|
@ -686,7 +690,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
let res =
|
let res =
|
||||||
match self.last_res with
|
match self.last_res with
|
||||||
| Some (SimpSolver.Sat m) ->
|
| Some (SimpSolver.Sat m) ->
|
||||||
Log.debugf 50 (fun k -> k "(@[lra.model-ask@ %a@])" Term.pp_debug t);
|
Log.debugf 50 (fun k -> k "(@[lra.model-ask@ %a@])" Term.pp t);
|
||||||
(match A.view_as_lra t with
|
(match A.view_as_lra t with
|
||||||
| LRA_const n -> Some n (* always eval constants to themselves *)
|
| LRA_const n -> Some n (* always eval constants to themselves *)
|
||||||
| _ -> SimpSolver.V_map.get t m)
|
| _ -> SimpSolver.V_map.get t m)
|
||||||
|
|
@ -709,8 +713,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
match self.last_res with
|
match self.last_res with
|
||||||
| Some (SimpSolver.Sat m) when Term.Tbl.length self.in_model > 0 ->
|
| Some (SimpSolver.Sat m) when Term.Tbl.length self.in_model > 0 ->
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
k "(@[lra.in_model@ %a@])"
|
k "(@[lra.in_model@ %a@])" (Util.pp_iter Term.pp)
|
||||||
(Util.pp_iter Term.pp_debug)
|
|
||||||
(Term.Tbl.keys self.in_model));
|
(Term.Tbl.keys self.in_model));
|
||||||
|
|
||||||
let add_t t () =
|
let add_t t () =
|
||||||
|
|
@ -729,6 +732,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
SMT.Registry.set (SI.registry si) k_state st;
|
SMT.Registry.set (SI.registry si) k_state st;
|
||||||
SI.add_simplifier si (simplify st);
|
SI.add_simplifier si (simplify st);
|
||||||
SI.on_preprocess si (preproc_lra st);
|
SI.on_preprocess si (preproc_lra st);
|
||||||
|
SI.on_find_foreign si find_foreign;
|
||||||
SI.on_final_check si (final_check_ st);
|
SI.on_final_check si (final_check_ st);
|
||||||
(* SI.on_partial_check si (partial_check_ st); *)
|
(* SI.on_partial_check si (partial_check_ st); *)
|
||||||
SI.on_model si ~ask:(model_ask_ st) ~complete:(model_complete_ st);
|
SI.on_model si ~ask:(model_ask_ st) ~complete:(model_complete_ st);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue