mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-05 19:00:33 -05:00
refactor(smt): remove functor, split into modules
This commit is contained in:
parent
6e1da96e7e
commit
05faac97e7
10 changed files with 125 additions and 199 deletions
|
|
@ -3,5 +3,5 @@
|
||||||
(public_name sidekick.smt-solver)
|
(public_name sidekick.smt-solver)
|
||||||
(synopsis "main SMT solver")
|
(synopsis "main SMT solver")
|
||||||
(libraries containers iter sidekick.core sidekick.util sidekick.cc
|
(libraries containers iter sidekick.core sidekick.util sidekick.cc
|
||||||
sidekick.sat)
|
sidekick.sat sidekick.simplify)
|
||||||
(flags :standard -w +32 -open Sidekick_util))
|
(flags :standard -w +32 -open Sidekick_util))
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,7 @@ let pp out = function
|
||||||
in
|
in
|
||||||
Fmt.fprintf out "(@[<hv>model@ %a@])" (Util.pp_iter pp_pair)
|
Fmt.fprintf out "(@[<hv>model@ %a@])" (Util.pp_iter pp_pair)
|
||||||
(Term.Tbl.to_iter tbl)
|
(Term.Tbl.to_iter tbl)
|
||||||
|
|
||||||
|
module Internal_ = struct
|
||||||
|
let of_tbl t = Map t
|
||||||
|
end
|
||||||
|
|
|
||||||
18
src/smt/model.mli
Normal file
18
src/smt/model.mli
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
(** Models
|
||||||
|
|
||||||
|
A model can be produced when the solver is found to be in a
|
||||||
|
satisfiable state after a call to {!solve}. *)
|
||||||
|
|
||||||
|
open Sigs
|
||||||
|
|
||||||
|
type t
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
val mem : t -> term -> bool
|
||||||
|
val find : t -> term -> term option
|
||||||
|
val eval : t -> term -> term option
|
||||||
|
val pp : t Fmt.printer
|
||||||
|
|
||||||
|
module Internal_ : sig
|
||||||
|
val of_tbl : term Term.Tbl.t -> t
|
||||||
|
end
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
*)
|
*)
|
||||||
|
|
||||||
include Sidekick_core
|
include Sidekick_core
|
||||||
|
module Simplify = Sidekick_simplify
|
||||||
module CC = Sidekick_cc.CC
|
module CC = Sidekick_cc.CC
|
||||||
module E_node = Sidekick_cc.E_node
|
module E_node = Sidekick_cc.E_node
|
||||||
module CC_expl = Sidekick_cc.Expl
|
module CC_expl = Sidekick_cc.Expl
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
open Sidekick_core
|
|
||||||
open Sigs
|
|
||||||
|
|
||||||
open struct
|
|
||||||
module P = Proof_trace
|
|
||||||
module Rule_ = Proof_core
|
|
||||||
end
|
|
||||||
|
|
||||||
type t = {
|
|
||||||
tst: term_store;
|
|
||||||
proof: proof_trace;
|
|
||||||
mutable hooks: hook list;
|
|
||||||
(* store [t --> u by step_ids] in the cache.
|
|
||||||
We use a bag for the proof steps because it gives us structural
|
|
||||||
sharing of subproofs. *)
|
|
||||||
cache: (Term.t * step_id Bag.t) Term.Tbl.t;
|
|
||||||
}
|
|
||||||
|
|
||||||
and hook = t -> term -> (term * step_id Iter.t) option
|
|
||||||
|
|
||||||
let create tst ~proof : t =
|
|
||||||
{ tst; proof; hooks = []; cache = Term.Tbl.create 32 }
|
|
||||||
|
|
||||||
let[@inline] tst self = self.tst
|
|
||||||
let[@inline] proof self = self.proof
|
|
||||||
let add_hook self f = self.hooks <- f :: self.hooks
|
|
||||||
let clear self = Term.Tbl.clear self.cache
|
|
||||||
|
|
||||||
let normalize (self : t) (t : Term.t) : (Term.t * step_id) option =
|
|
||||||
(* compute and cache normal form of [t] *)
|
|
||||||
let rec loop t : Term.t * _ Bag.t =
|
|
||||||
match Term.Tbl.find self.cache t with
|
|
||||||
| res -> res
|
|
||||||
| exception Not_found ->
|
|
||||||
let steps_u = ref Bag.empty in
|
|
||||||
let u = aux_rec ~steps:steps_u t self.hooks in
|
|
||||||
Term.Tbl.add self.cache t (u, !steps_u);
|
|
||||||
u, !steps_u
|
|
||||||
and loop_add ~steps t =
|
|
||||||
let u, pr_u = loop t in
|
|
||||||
steps := Bag.append !steps pr_u;
|
|
||||||
u
|
|
||||||
(* try each function in [hooks] successively, and rewrite subterms *)
|
|
||||||
and aux_rec ~steps t hooks : Term.t =
|
|
||||||
match hooks with
|
|
||||||
| [] ->
|
|
||||||
let u =
|
|
||||||
Term.map_shallow self.tst ~f:(fun _inb u -> loop_add ~steps u) t
|
|
||||||
in
|
|
||||||
if Term.equal t u then
|
|
||||||
t
|
|
||||||
else
|
|
||||||
loop_add ~steps u
|
|
||||||
| h :: hooks_tl ->
|
|
||||||
(match h self t with
|
|
||||||
| None -> aux_rec ~steps t hooks_tl
|
|
||||||
| Some (u, _) when Term.equal t u -> aux_rec ~steps t hooks_tl
|
|
||||||
| Some (u, pr_u) ->
|
|
||||||
let bag_u = Bag.of_iter pr_u in
|
|
||||||
steps := Bag.append !steps bag_u;
|
|
||||||
let v, pr_v = loop u in
|
|
||||||
(* fixpoint *)
|
|
||||||
steps := Bag.append !steps pr_v;
|
|
||||||
v)
|
|
||||||
in
|
|
||||||
let u, pr_u = loop t in
|
|
||||||
if Term.equal t u then
|
|
||||||
None
|
|
||||||
else (
|
|
||||||
(* proof: [sub_proofs |- t=u] by CC + subproof *)
|
|
||||||
let step =
|
|
||||||
P.add_step self.proof
|
|
||||||
@@ Rule_.lemma_preprocess t u ~using:(Bag.to_iter pr_u)
|
|
||||||
in
|
|
||||||
Some (u, step)
|
|
||||||
)
|
|
||||||
|
|
||||||
let normalize_t self t =
|
|
||||||
match normalize self t with
|
|
||||||
| Some (u, pr_u) -> u, Some pr_u
|
|
||||||
| None -> t, None
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
(** Term simplifier *)
|
|
||||||
|
|
||||||
open Sidekick_core
|
|
||||||
open Sigs
|
|
||||||
|
|
||||||
type t
|
|
||||||
|
|
||||||
val tst : t -> term_store
|
|
||||||
|
|
||||||
val clear : t -> unit
|
|
||||||
(** Reset internal cache, etc. *)
|
|
||||||
|
|
||||||
val proof : t -> proof_trace
|
|
||||||
(** Access proof *)
|
|
||||||
|
|
||||||
type hook = t -> term -> (term * step_id Iter.t) option
|
|
||||||
(** Given a term, try to simplify it. Return [None] if it didn't change.
|
|
||||||
|
|
||||||
A simple example could be a hook that takes a term [t],
|
|
||||||
and if [t] is [app "+" (const x) (const y)] where [x] and [y] are number,
|
|
||||||
returns [Some (const (x+y))], and [None] otherwise.
|
|
||||||
|
|
||||||
The simplifier will take care of simplifying the resulting term further,
|
|
||||||
caching (so that work is not duplicated in subterms), etc.
|
|
||||||
*)
|
|
||||||
|
|
||||||
val add_hook : t -> hook -> unit
|
|
||||||
|
|
||||||
val normalize : t -> term -> (term * step_id) option
|
|
||||||
(** Normalize a term using all the hooks. This performs
|
|
||||||
a fixpoint, i.e. it only stops when no hook applies anywhere inside
|
|
||||||
the term. *)
|
|
||||||
|
|
||||||
val normalize_t : t -> term -> term * step_id option
|
|
||||||
(** Normalize a term using all the hooks, along with a proof that the
|
|
||||||
simplification is correct.
|
|
||||||
returns [t, ø] if no simplification occurred. *)
|
|
||||||
|
|
||||||
val create : Term.store -> proof:Proof_trace.t -> t
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
open Sigs
|
open Sigs
|
||||||
|
|
||||||
open struct
|
open struct
|
||||||
|
module SI = Solver_internal
|
||||||
module P = Proof_trace
|
module P = Proof_trace
|
||||||
module Rule_ = Proof_core
|
module Rule_ = Proof_core
|
||||||
end
|
end
|
||||||
|
|
@ -30,7 +31,7 @@ end
|
||||||
end)
|
end)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
module Sat_solver = Sidekick_sat.Make_cdcl_t (Solver_internal)
|
module Sat_solver = Sidekick_sat
|
||||||
(** the parametrized SAT Solver *)
|
(** the parametrized SAT Solver *)
|
||||||
|
|
||||||
(** {2 Result} *)
|
(** {2 Result} *)
|
||||||
|
|
@ -100,7 +101,7 @@ let create arg ?(stat = Stat.global) ?size ~proof ~theories tst () : t =
|
||||||
si;
|
si;
|
||||||
proof;
|
proof;
|
||||||
last_res = None;
|
last_res = None;
|
||||||
solver = Sat_solver.create ~proof ?size ~stat si;
|
solver = Sat_solver.create ~proof ?size ~stat (SI.to_sat_plugin si);
|
||||||
stat;
|
stat;
|
||||||
count_clause = Stat.mk_int stat "solver.add-clause";
|
count_clause = Stat.mk_int stat "solver.add-clause";
|
||||||
count_solve = Stat.mk_int stat "solver.solve";
|
count_solve = Stat.mk_int stat "solver.solve";
|
||||||
|
|
@ -127,11 +128,11 @@ let reset_last_res_ self = self.last_res <- None
|
||||||
(* preprocess clause, return new proof *)
|
(* preprocess clause, return new proof *)
|
||||||
let preprocess_clause_ (self : t) (c : lit array) (pr : step_id) :
|
let preprocess_clause_ (self : t) (c : lit array) (pr : step_id) :
|
||||||
lit array * step_id =
|
lit array * step_id =
|
||||||
Solver_internal.preprocess_clause_iarray_ self.si c pr
|
Solver_internal.preprocess_clause_array self.si c pr
|
||||||
|
|
||||||
let mk_lit_t (self : t) ?sign (t : term) : lit =
|
let mk_lit_t (self : t) ?sign (t : term) : lit =
|
||||||
let lit = Lit.atom ?sign t in
|
let lit = Lit.atom ?sign t in
|
||||||
let lit, _ = Solver_internal.simplify_and_preproc_lit_ self.si lit in
|
let lit, _ = Solver_internal.simplify_and_preproc_lit self.si lit in
|
||||||
lit
|
lit
|
||||||
|
|
||||||
(** {2 Main} *)
|
(** {2 Main} *)
|
||||||
|
|
@ -171,16 +172,14 @@ let add_clause (self : t) (c : lit array) (proof : step_id) : unit =
|
||||||
let add_clause_l self c p = add_clause self (CCArray.of_list c) p
|
let add_clause_l self c p = add_clause self (CCArray.of_list c) p
|
||||||
|
|
||||||
let assert_terms self c =
|
let assert_terms self c =
|
||||||
let c = CCList.map (fun t -> Lit.atom (tst self) t) c in
|
let c = CCList.map Lit.atom c in
|
||||||
let pr_c =
|
let pr_c =
|
||||||
P.add_step self.proof @@ A.Rule_sat.sat_input_clause (Iter.of_list c)
|
P.add_step self.proof @@ Proof_sat.sat_input_clause (Iter.of_list c)
|
||||||
in
|
in
|
||||||
add_clause_l self c pr_c
|
add_clause_l self c pr_c
|
||||||
|
|
||||||
let assert_term self t = assert_terms self [ t ]
|
let assert_term self t = assert_terms self [ t ]
|
||||||
|
|
||||||
exception Resource_exhausted = Sidekick_sat.Resource_exhausted
|
|
||||||
|
|
||||||
let solve ?(on_exit = []) ?(check = true) ?(on_progress = fun _ -> ())
|
let solve ?(on_exit = []) ?(check = true) ?(on_progress = fun _ -> ())
|
||||||
?(should_stop = fun _ _ -> false) ~assumptions (self : t) : res =
|
?(should_stop = fun _ _ -> false) ~assumptions (self : t) : res =
|
||||||
Profile.with_ "smt-solver.solve" @@ fun () ->
|
Profile.with_ "smt-solver.solve" @@ fun () ->
|
||||||
|
|
@ -194,14 +193,14 @@ let solve ?(on_exit = []) ?(check = true) ?(on_progress = fun _ -> ())
|
||||||
if should_stop self !resource_counter then
|
if should_stop self !resource_counter then
|
||||||
raise_notrace Resource_exhausted
|
raise_notrace Resource_exhausted
|
||||||
in
|
in
|
||||||
self.si.on_progress <- on_progress;
|
Event.on ~f:on_progress (SI.on_progress self.si);
|
||||||
|
|
||||||
let res =
|
let res =
|
||||||
match
|
match
|
||||||
Stat.incr self.count_solve;
|
Stat.incr self.count_solve;
|
||||||
Sat_solver.solve ~on_progress ~assumptions (solver self)
|
Sat_solver.solve ~on_progress ~assumptions (solver self)
|
||||||
with
|
with
|
||||||
| Sat_solver.Sat _ when not self.si.complete ->
|
| Sat_solver.Sat _ when not (SI.is_complete self.si) ->
|
||||||
Log.debugf 1 (fun k ->
|
Log.debugf 1 (fun k ->
|
||||||
k
|
k
|
||||||
"(@[sidekick.smt-solver: SAT@ actual: UNKNOWN@ :reason \
|
"(@[sidekick.smt-solver: SAT@ actual: UNKNOWN@ :reason \
|
||||||
|
|
@ -212,14 +211,14 @@ let solve ?(on_exit = []) ?(check = true) ?(on_progress = fun _ -> ())
|
||||||
|
|
||||||
Log.debugf 5 (fun k ->
|
Log.debugf 5 (fun k ->
|
||||||
let ppc out n =
|
let ppc out n =
|
||||||
Fmt.fprintf out "{@[<hv>class@ %a@]}" (Util.pp_iter N.pp)
|
Fmt.fprintf out "{@[<hv>class@ %a@]}" (Util.pp_iter E_node.pp)
|
||||||
(N.iter_class n)
|
(E_node.iter_class n)
|
||||||
in
|
in
|
||||||
k "(@[sidekick.smt-solver.classes@ (@[%a@])@])" (Util.pp_iter ppc)
|
k "(@[sidekick.smt-solver.classes@ (@[%a@])@])" (Util.pp_iter ppc)
|
||||||
(CC.all_classes @@ Solver_internal.cc self.si));
|
(CC.all_classes @@ Solver_internal.cc self.si));
|
||||||
|
|
||||||
let m =
|
let m =
|
||||||
match self.si.last_model with
|
match SI.last_model self.si with
|
||||||
| Some m -> m
|
| Some m -> m
|
||||||
| None -> assert false
|
| None -> assert false
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -14,32 +14,15 @@ type t
|
||||||
val registry : t -> Registry.t
|
val registry : t -> Registry.t
|
||||||
(** A solver contains a registry so that theories can share data *)
|
(** A solver contains a registry so that theories can share data *)
|
||||||
|
|
||||||
type theory = Theory.t
|
|
||||||
type 'a theory_p = 'a Theory.p
|
|
||||||
|
|
||||||
val mk_theory :
|
val mk_theory :
|
||||||
name:string ->
|
name:string ->
|
||||||
create_and_setup:(Solver_internal.t -> 'th) ->
|
create_and_setup:(Solver_internal.t -> 'th) ->
|
||||||
?push_level:('th -> unit) ->
|
?push_level:('th -> unit) ->
|
||||||
?pop_levels:('th -> int -> unit) ->
|
?pop_levels:('th -> int -> unit) ->
|
||||||
unit ->
|
unit ->
|
||||||
theory
|
Theory.t
|
||||||
(** Helper to create a theory. *)
|
(** Helper to create a theory. *)
|
||||||
|
|
||||||
(** Models
|
|
||||||
|
|
||||||
A model can be produced when the solver is found to be in a
|
|
||||||
satisfiable state after a call to {!solve}. *)
|
|
||||||
module Model : sig
|
|
||||||
type t
|
|
||||||
|
|
||||||
val empty : t
|
|
||||||
val mem : t -> term -> bool
|
|
||||||
val find : t -> term -> term option
|
|
||||||
val eval : t -> term -> term option
|
|
||||||
val pp : t Fmt.printer
|
|
||||||
end
|
|
||||||
|
|
||||||
(* TODO *)
|
(* TODO *)
|
||||||
module Unknown : sig
|
module Unknown : sig
|
||||||
type t
|
type t
|
||||||
|
|
@ -65,7 +48,7 @@ val create :
|
||||||
?size:[ `Big | `Tiny | `Small ] ->
|
?size:[ `Big | `Tiny | `Small ] ->
|
||||||
(* TODO? ?config:Config.t -> *)
|
(* TODO? ?config:Config.t -> *)
|
||||||
proof:proof_trace ->
|
proof:proof_trace ->
|
||||||
theories:theory list ->
|
theories:Theory.t list ->
|
||||||
Term.store ->
|
Term.store ->
|
||||||
unit ->
|
unit ->
|
||||||
t
|
t
|
||||||
|
|
@ -82,15 +65,15 @@ val create :
|
||||||
@param theories theories to load from the start. Other theories
|
@param theories theories to load from the start. Other theories
|
||||||
can be added using {!add_theory}. *)
|
can be added using {!add_theory}. *)
|
||||||
|
|
||||||
val add_theory : t -> theory -> unit
|
val add_theory : t -> Theory.t -> unit
|
||||||
(** Add a theory to the solver. This should be called before
|
(** Add a theory to the solver. This should be called before
|
||||||
any call to {!solve} or to {!add_clause} and the likes (otherwise
|
any call to {!solve} or to {!add_clause} and the likes (otherwise
|
||||||
the theory will have a partial view of the problem). *)
|
the theory will have a partial view of the problem). *)
|
||||||
|
|
||||||
val add_theory_p : t -> 'a theory_p -> 'a
|
val add_theory_p : t -> 'a Theory.p -> 'a
|
||||||
(** Add the given theory and obtain its state *)
|
(** Add the given theory and obtain its state *)
|
||||||
|
|
||||||
val add_theory_l : t -> theory list -> unit
|
val add_theory_l : t -> Theory.t list -> unit
|
||||||
|
|
||||||
val mk_lit_t : t -> ?sign:bool -> term -> lit
|
val mk_lit_t : t -> ?sign:bool -> term -> lit
|
||||||
(** [mk_lit_t _ ~sign t] returns [lit'],
|
(** [mk_lit_t _ ~sign t] returns [lit'],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
open Sigs
|
open Sigs
|
||||||
module Proof_rules = Sidekick_core.Proof_sat
|
module Proof_rules = Sidekick_core.Proof_sat
|
||||||
module P_core_rules = Sidekick_core.Proof_core
|
module P_core_rules = Sidekick_core.Proof_core
|
||||||
module N = Sidekick_cc.E_node
|
|
||||||
module Ty = Term
|
module Ty = Term
|
||||||
|
|
||||||
open struct
|
open struct
|
||||||
|
|
@ -46,7 +45,7 @@ type t = {
|
||||||
cc: CC.t; (** congruence closure *)
|
cc: CC.t; (** congruence closure *)
|
||||||
proof: proof_trace; (** proof logger *)
|
proof: proof_trace; (** proof logger *)
|
||||||
registry: Registry.t;
|
registry: Registry.t;
|
||||||
mutable on_progress: unit -> unit;
|
on_progress: (unit, unit) Event.Emitter.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;
|
||||||
mutable on_th_combination:
|
mutable on_th_combination:
|
||||||
|
|
@ -69,7 +68,10 @@ type t = {
|
||||||
}
|
}
|
||||||
|
|
||||||
and preprocess_hook = t -> preprocess_actions -> term -> unit
|
and preprocess_hook = t -> preprocess_actions -> term -> unit
|
||||||
and model_ask_hook = recurse:(t -> N.t -> term) -> t -> N.t -> term option
|
|
||||||
|
and model_ask_hook =
|
||||||
|
recurse:(t -> E_node.t -> term) -> t -> E_node.t -> term option
|
||||||
|
|
||||||
and model_completion_hook = t -> add:(term -> term -> unit) -> unit
|
and model_completion_hook = t -> add:(term -> term -> unit) -> unit
|
||||||
|
|
||||||
type solver = t
|
type solver = t
|
||||||
|
|
@ -172,8 +174,7 @@ let preprocess_term_ (self : t) (t0 : term) : unit =
|
||||||
preproc_rec_ t0
|
preproc_rec_ t0
|
||||||
|
|
||||||
(* simplify literal, then preprocess the result *)
|
(* simplify literal, then preprocess the result *)
|
||||||
let simplify_and_preproc_lit_ (self : t) (lit : Lit.t) : Lit.t * step_id option
|
let simplify_and_preproc_lit (self : t) (lit : Lit.t) : Lit.t * step_id option =
|
||||||
=
|
|
||||||
let t = Lit.term lit in
|
let t = Lit.term lit in
|
||||||
let sign = Lit.sign lit in
|
let sign = Lit.sign lit in
|
||||||
let u, pr =
|
let u, pr =
|
||||||
|
|
@ -191,7 +192,7 @@ let simplify_and_preproc_lit_ (self : t) (lit : Lit.t) : Lit.t * step_id option
|
||||||
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 *)
|
||||||
let lit, _ = simplify_and_preproc_lit_ self lit in
|
let lit, _ = simplify_and_preproc_lit self lit in
|
||||||
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
|
||||||
|
|
||||||
|
|
@ -210,7 +211,7 @@ module Preprocess_clause (A : ARR) = struct
|
||||||
|
|
||||||
(* simplify a literal, then preprocess it *)
|
(* simplify a literal, then preprocess it *)
|
||||||
let[@inline] simp_lit lit =
|
let[@inline] simp_lit lit =
|
||||||
let lit, pr = simplify_and_preproc_lit_ self lit in
|
let lit, pr = simplify_and_preproc_lit self lit in
|
||||||
Option.iter (fun pr -> steps := pr :: !steps) pr;
|
Option.iter (fun pr -> steps := pr :: !steps) pr;
|
||||||
lit
|
lit
|
||||||
in
|
in
|
||||||
|
|
@ -233,8 +234,8 @@ end
|
||||||
module PC_list = Preprocess_clause (CCList)
|
module PC_list = Preprocess_clause (CCList)
|
||||||
module PC_arr = Preprocess_clause (CCArray)
|
module PC_arr = Preprocess_clause (CCArray)
|
||||||
|
|
||||||
let preprocess_clause_ = PC_list.top
|
let preprocess_clause = PC_list.top
|
||||||
let preprocess_clause_iarray_ = PC_arr.top
|
let preprocess_clause_array = PC_arr.top
|
||||||
|
|
||||||
module type PERFORM_ACTS = sig
|
module type PERFORM_ACTS = sig
|
||||||
type t
|
type t
|
||||||
|
|
@ -250,7 +251,7 @@ module Perform_delayed (A : PERFORM_ACTS) = struct
|
||||||
let act = Queue.pop self.delayed_actions in
|
let act = Queue.pop self.delayed_actions in
|
||||||
match act with
|
match act with
|
||||||
| DA_add_clause { c; pr = pr_c; keep } ->
|
| DA_add_clause { c; pr = pr_c; keep } ->
|
||||||
let c', pr_c' = preprocess_clause_ self c pr_c in
|
let c', pr_c' = preprocess_clause self c pr_c in
|
||||||
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 } ->
|
||||||
preprocess_term_ self (Lit.term lit);
|
preprocess_term_ self (Lit.term lit);
|
||||||
|
|
@ -270,11 +271,11 @@ module Perform_delayed_th = Perform_delayed (struct
|
||||||
end)
|
end)
|
||||||
|
|
||||||
let[@inline] add_clause_temp self _acts c (proof : step_id) : unit =
|
let[@inline] add_clause_temp self _acts c (proof : step_id) : unit =
|
||||||
let c, proof = preprocess_clause_ self c proof in
|
let c, proof = preprocess_clause self c proof in
|
||||||
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[@inline] add_clause_permanent self _acts c (proof : step_id) : unit =
|
||||||
let c, proof = preprocess_clause_ self c proof in
|
let c, proof = preprocess_clause self c proof in
|
||||||
delayed_add_clause self ~keep:true c proof
|
delayed_add_clause self ~keep:true c proof
|
||||||
|
|
||||||
let[@inline] mk_lit _ ?sign t : lit = Lit.atom ?sign t
|
let[@inline] mk_lit _ ?sign t : lit = Lit.atom ?sign t
|
||||||
|
|
@ -284,7 +285,7 @@ let[@inline] add_lit self _acts ?default_pol lit =
|
||||||
|
|
||||||
let add_lit_t self _acts ?sign t =
|
let add_lit_t self _acts ?sign t =
|
||||||
let lit = Lit.atom ?sign t in
|
let lit = Lit.atom ?sign t in
|
||||||
let lit, _ = simplify_and_preproc_lit_ self lit in
|
let lit, _ = simplify_and_preproc_lit self lit in
|
||||||
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
|
||||||
|
|
@ -292,6 +293,7 @@ let on_final_check self f = self.on_final_check <- f :: self.on_final_check
|
||||||
let on_partial_check self f =
|
let on_partial_check self f =
|
||||||
self.on_partial_check <- f :: self.on_partial_check
|
self.on_partial_check <- f :: self.on_partial_check
|
||||||
|
|
||||||
|
let on_progress self = Event.of_emitter self.on_progress
|
||||||
let on_cc_new_term self f = Event.on (CC.on_new_term (cc self)) ~f
|
let on_cc_new_term self f = Event.on (CC.on_new_term (cc self)) ~f
|
||||||
let on_cc_pre_merge self f = Event.on (CC.on_pre_merge (cc self)) ~f
|
let on_cc_pre_merge self f = Event.on (CC.on_pre_merge (cc self)) ~f
|
||||||
let on_cc_post_merge self f = Event.on (CC.on_post_merge (cc self)) ~f
|
let on_cc_post_merge self f = Event.on (CC.on_post_merge (cc self)) ~f
|
||||||
|
|
@ -301,11 +303,13 @@ let on_cc_is_subterm self f = Event.on (CC.on_is_subterm (cc self)) ~f
|
||||||
let cc_add_term self t = CC.add_term (cc self) t
|
let cc_add_term self t = CC.add_term (cc self) t
|
||||||
let cc_mem_term self t = CC.mem_term (cc self) t
|
let cc_mem_term self t = CC.mem_term (cc self) t
|
||||||
let cc_find self n = CC.find (cc self) n
|
let cc_find self n = CC.find (cc self) n
|
||||||
|
let is_complete self = self.complete
|
||||||
|
let last_model self = self.last_model
|
||||||
|
|
||||||
let cc_are_equal self t1 t2 =
|
let cc_are_equal self t1 t2 =
|
||||||
let n1 = cc_add_term self t1 in
|
let n1 = cc_add_term self t1 in
|
||||||
let n2 = cc_add_term self t2 in
|
let n2 = cc_add_term self t2 in
|
||||||
N.equal (cc_find self n1) (cc_find self n2)
|
E_node.equal (cc_find self n1) (cc_find self n2)
|
||||||
|
|
||||||
let cc_resolve_expl self e : lit list * _ =
|
let cc_resolve_expl self e : lit list * _ =
|
||||||
let r = CC.explain_expl (cc self) e in
|
let r = CC.explain_expl (cc self) e in
|
||||||
|
|
@ -337,19 +341,6 @@ let rec pop_lvls_ n = function
|
||||||
r.pop_levels r.st n;
|
r.pop_levels r.st n;
|
||||||
pop_lvls_ n r.next
|
pop_lvls_ n r.next
|
||||||
|
|
||||||
let push_level (self : t) : unit =
|
|
||||||
self.level <- 1 + self.level;
|
|
||||||
CC.push_level (cc self);
|
|
||||||
push_lvl_ self.th_states
|
|
||||||
|
|
||||||
let pop_levels (self : t) n : unit =
|
|
||||||
self.last_model <- None;
|
|
||||||
self.level <- self.level - n;
|
|
||||||
CC.pop_levels (cc self) n;
|
|
||||||
pop_lvls_ n self.th_states
|
|
||||||
|
|
||||||
let n_levels self = self.level
|
|
||||||
|
|
||||||
(** {2 Model construction and theory combination} *)
|
(** {2 Model construction and theory combination} *)
|
||||||
|
|
||||||
(* make model from the congruence closure *)
|
(* make model from the congruence closure *)
|
||||||
|
|
@ -372,7 +363,7 @@ let mk_model_ (self : t) (lits : lit Iter.t) : Model.t =
|
||||||
CC.get_model_for_each_class cc (fun (_, ts, v) ->
|
CC.get_model_for_each_class cc (fun (_, ts, v) ->
|
||||||
Iter.iter
|
Iter.iter
|
||||||
(fun n ->
|
(fun n ->
|
||||||
let t = N.term n in
|
let t = E_node.term n in
|
||||||
M.replace model t v)
|
M.replace model t v)
|
||||||
ts);
|
ts);
|
||||||
*)
|
*)
|
||||||
|
|
@ -390,20 +381,20 @@ let mk_model_ (self : t) (lits : lit Iter.t) : Model.t =
|
||||||
List.iter complete_with model_complete;
|
List.iter complete_with model_complete;
|
||||||
|
|
||||||
(* compute a value for [n]. *)
|
(* compute a value for [n]. *)
|
||||||
let rec val_for_class (n : N.t) : term =
|
let rec val_for_class (n : E_node.t) : term =
|
||||||
Log.debugf 5 (fun k -> k "val-for-term %a" N.pp n);
|
Log.debugf 5 (fun k -> k "val-for-term %a" E_node.pp n);
|
||||||
let repr = CC.find cc n in
|
let repr = CC.find cc n in
|
||||||
Log.debugf 5 (fun k -> k "val-for-term.repr %a" N.pp repr);
|
Log.debugf 5 (fun k -> k "val-for-term.repr %a" E_node.pp repr);
|
||||||
|
|
||||||
(* see if a value is found already (always the case if it's a boolean) *)
|
(* see if a value is found already (always the case if it's a boolean) *)
|
||||||
match M.get model (N.term repr) with
|
match M.get model (E_node.term repr) with
|
||||||
| Some t_val ->
|
| Some t_val ->
|
||||||
Log.debugf 5 (fun k -> k "cached val is %a" Term.pp_debug t_val);
|
Log.debugf 5 (fun k -> k "cached val is %a" Term.pp_debug t_val);
|
||||||
t_val
|
t_val
|
||||||
| None ->
|
| None ->
|
||||||
(* try each model hook *)
|
(* try each model hook *)
|
||||||
let rec try_hooks_ = function
|
let rec try_hooks_ = function
|
||||||
| [] -> N.term repr
|
| [] -> E_node.term repr
|
||||||
| h :: hooks ->
|
| h :: hooks ->
|
||||||
(match h ~recurse:(fun _ n -> val_for_class n) self repr with
|
(match h ~recurse:(fun _ n -> val_for_class n) self repr with
|
||||||
| None -> try_hooks_ hooks
|
| None -> try_hooks_ hooks
|
||||||
|
|
@ -415,15 +406,15 @@ let mk_model_ (self : t) (lits : lit Iter.t) : Model.t =
|
||||||
(* FIXME: the more complete version?
|
(* FIXME: the more complete version?
|
||||||
match
|
match
|
||||||
(* look for a value in the model for any term in the class *)
|
(* look for a value in the model for any term in the class *)
|
||||||
N.iter_class repr
|
E_node.iter_class repr
|
||||||
|> Iter.find_map (fun n -> M.get model (N.term n))
|
|> Iter.find_map (fun n -> M.get model (E_node.term n))
|
||||||
with
|
with
|
||||||
| Some v -> v
|
| Some v -> v
|
||||||
| None -> try_hooks_ model_ask_hooks
|
| None -> try_hooks_ model_ask_hooks
|
||||||
*)
|
*)
|
||||||
in
|
in
|
||||||
|
|
||||||
M.replace model (N.term repr) t_val;
|
M.replace model (E_node.term repr) t_val;
|
||||||
(* be sure to cache the value *)
|
(* be sure to cache the value *)
|
||||||
Log.debugf 5 (fun k -> k "val is %a" Term.pp_debug t_val);
|
Log.debugf 5 (fun k -> k "val is %a" Term.pp_debug t_val);
|
||||||
t_val
|
t_val
|
||||||
|
|
@ -433,11 +424,11 @@ let mk_model_ (self : t) (lits : lit Iter.t) : Model.t =
|
||||||
CC.all_classes cc (fun repr ->
|
CC.all_classes cc (fun repr ->
|
||||||
let t_val = val_for_class repr in
|
let t_val = val_for_class repr in
|
||||||
(* value for this class *)
|
(* value for this class *)
|
||||||
N.iter_class repr (fun u ->
|
E_node.iter_class repr (fun u ->
|
||||||
let t_u = N.term u in
|
let t_u = E_node.term u in
|
||||||
if (not (N.equal u repr)) && not (Term.equal t_u t_val) then
|
if (not (E_node.equal u repr)) && not (Term.equal t_u t_val) then
|
||||||
M.replace model t_u t_val));
|
M.replace model t_u t_val));
|
||||||
Model.Map model
|
Model.Internal_.of_tbl model
|
||||||
|
|
||||||
(* do theory combination using the congruence closure. Each theory
|
(* do theory combination using the congruence closure. Each theory
|
||||||
can merge classes, *)
|
can merge classes, *)
|
||||||
|
|
@ -557,7 +548,7 @@ let check_ ~final (self : t) (acts : sat_acts) =
|
||||||
in
|
in
|
||||||
let iter = iter_atoms_ acts in
|
let iter = iter_atoms_ acts in
|
||||||
Log.debugf 5 (fun k -> k "(smt-solver.assume :len %d)" (Iter.length iter));
|
Log.debugf 5 (fun k -> k "(smt-solver.assume :len %d)" (Iter.length iter));
|
||||||
self.on_progress ();
|
Event.emit self.on_progress ();
|
||||||
assert_lits_ ~final self acts iter;
|
assert_lits_ ~final self acts iter;
|
||||||
Profile.exit pb
|
Profile.exit pb
|
||||||
|
|
||||||
|
|
@ -569,6 +560,28 @@ let[@inline] partial_check (self : t) (acts : Sidekick_sat.acts) : unit =
|
||||||
let[@inline] final_check (self : t) (acts : Sidekick_sat.acts) : unit =
|
let[@inline] final_check (self : t) (acts : Sidekick_sat.acts) : unit =
|
||||||
check_ ~final:true self acts
|
check_ ~final:true self acts
|
||||||
|
|
||||||
|
let push_level self : unit =
|
||||||
|
self.level <- 1 + self.level;
|
||||||
|
CC.push_level (cc self);
|
||||||
|
push_lvl_ self.th_states
|
||||||
|
|
||||||
|
let pop_levels self n : unit =
|
||||||
|
self.last_model <- None;
|
||||||
|
self.level <- self.level - n;
|
||||||
|
CC.pop_levels (cc self) n;
|
||||||
|
pop_lvls_ n self.th_states
|
||||||
|
|
||||||
|
let n_levels self = self.level
|
||||||
|
|
||||||
|
let to_sat_plugin (self : t) : (module Sidekick_sat.PLUGIN) =
|
||||||
|
(module struct
|
||||||
|
let has_theory = true
|
||||||
|
let push_level () = push_level self
|
||||||
|
let pop_levels n = pop_levels self n
|
||||||
|
let partial_check acts = partial_check self acts
|
||||||
|
let final_check acts = final_check self acts
|
||||||
|
end)
|
||||||
|
|
||||||
let declare_pb_is_incomplete self =
|
let declare_pb_is_incomplete self =
|
||||||
if self.complete then Log.debug 1 "(solver.declare-pb-is-incomplete)";
|
if self.complete then Log.debug 1 "(solver.declare-pb-is-incomplete)";
|
||||||
self.complete <- false
|
self.complete <- false
|
||||||
|
|
@ -587,7 +600,7 @@ let create (module A : ARG) ~stat ~proof (tst : Term.store) () : t =
|
||||||
stat;
|
stat;
|
||||||
simp = Simplify.create tst ~proof;
|
simp = Simplify.create tst ~proof;
|
||||||
last_model = None;
|
last_model = None;
|
||||||
on_progress = (fun () -> ());
|
on_progress = Event.Emitter.create ();
|
||||||
preprocess = [];
|
preprocess = [];
|
||||||
model_ask = [];
|
model_ask = [];
|
||||||
model_complete = [];
|
model_complete = [];
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,14 @@ include Sidekick_sigs.BACKTRACKABLE0 with type t := t
|
||||||
|
|
||||||
(** {3 Interface to SAT} *)
|
(** {3 Interface to SAT} *)
|
||||||
|
|
||||||
include Sidekick_sat.PLUGIN_CDCL_T with type t := t
|
val to_sat_plugin : t -> (module Sidekick_sat.PLUGIN)
|
||||||
|
|
||||||
(** {3 Simplifiers} *)
|
(** {3 Simplifiers} *)
|
||||||
|
|
||||||
type simplify_hook = Simplify.hook
|
type simplify_hook = Simplify.hook
|
||||||
|
|
||||||
|
val simplifier : t -> Simplify.t
|
||||||
|
|
||||||
val add_simplifier : t -> Simplify.hook -> unit
|
val add_simplifier : t -> Simplify.hook -> unit
|
||||||
(** Add a simplifier hook for preprocessing. *)
|
(** Add a simplifier hook for preprocessing. *)
|
||||||
|
|
||||||
|
|
@ -90,6 +92,12 @@ type preprocess_hook = t -> preprocess_actions -> term -> unit
|
||||||
val on_preprocess : t -> preprocess_hook -> unit
|
val on_preprocess : t -> preprocess_hook -> unit
|
||||||
(** Add a hook that will be called when terms are preprocessed *)
|
(** Add a hook that will be called when terms are preprocessed *)
|
||||||
|
|
||||||
|
val preprocess_clause : t -> lit list -> step_id -> lit list * step_id
|
||||||
|
val preprocess_clause_array : t -> lit array -> step_id -> lit array * step_id
|
||||||
|
|
||||||
|
val simplify_and_preproc_lit : t -> lit -> lit * step_id option
|
||||||
|
(** Simplify literal then preprocess it *)
|
||||||
|
|
||||||
(** {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
|
||||||
|
|
@ -245,6 +253,26 @@ val on_model :
|
||||||
?ask:model_ask_hook -> ?complete:model_completion_hook -> t -> unit
|
?ask:model_ask_hook -> ?complete:model_completion_hook -> t -> unit
|
||||||
(** Add model production/completion hooks. *)
|
(** Add model production/completion hooks. *)
|
||||||
|
|
||||||
|
val on_progress : t -> (unit, unit) Event.t
|
||||||
|
|
||||||
|
val is_complete : t -> bool
|
||||||
|
(** Are we still in a complete logic fragment? *)
|
||||||
|
|
||||||
|
val last_model : t -> Model.t option
|
||||||
|
|
||||||
|
(** {2 Delayed actions} *)
|
||||||
|
|
||||||
|
module type PERFORM_ACTS = sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val add_clause : solver -> t -> keep:bool -> lit list -> step_id -> unit
|
||||||
|
val add_lit : solver -> t -> ?default_pol:bool -> lit -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
module Perform_delayed (A : PERFORM_ACTS) : sig
|
||||||
|
val top : t -> A.t -> unit
|
||||||
|
end
|
||||||
|
|
||||||
val add_theory_state :
|
val add_theory_state :
|
||||||
st:'a ->
|
st:'a ->
|
||||||
push_level:('a -> unit) ->
|
push_level:('a -> unit) ->
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue