refactor(api): make theory state also explicit

This commit is contained in:
Simon Cruanes 2019-01-18 20:14:47 -06:00 committed by Guillaume Bury
parent e60aff60b6
commit 8b4458b066
8 changed files with 57 additions and 43 deletions

View file

@ -136,4 +136,4 @@ module Make(Elt : RANKED) = struct
); );
x x
end end [@@inline]

View file

@ -4,6 +4,8 @@ Copyright 2014 Guillaume Bury
Copyright 2014 Simon Cruanes Copyright 2014 Simon Cruanes
*) *)
(* TODO: move solver types here *)
module Make module Make
(St : Solver_types.S) (St : Solver_types.S)
(Plugin : Plugin_intf.S with type term = St.term (Plugin : Plugin_intf.S with type term = St.term
@ -13,8 +15,9 @@ module Make
module Proof = Res.Make(St) module Proof = Res.Make(St)
open St open St
type theory = Plugin.t
module H = Heap.Make(struct module H = (Heap.Make [@specialise]) (struct
type t = St.Elt.t type t = St.Elt.t
let[@inline] cmp i j = Elt.weight j < Elt.weight i (* comparison by weight *) let[@inline] cmp i j = Elt.weight j < Elt.weight i (* comparison by weight *)
let idx = Elt.idx let idx = Elt.idx
@ -49,6 +52,8 @@ module Make
type t = { type t = {
st : St.t; st : St.t;
th: Plugin.t;
(* Clauses are simplified for eficiency purposes. In the following (* Clauses are simplified for eficiency purposes. In the following
vectors, the comments actually refer to the original non-simplified vectors, the comments actually refer to the original non-simplified
clause. *) clause. *)
@ -121,8 +126,8 @@ module Make
} }
(* Starting environment. *) (* Starting environment. *)
let create_ ~st () : t = { let create_ ~st (th:theory) : t = {
st; st; th;
unsat_conflict = None; unsat_conflict = None;
next_decision = None; next_decision = None;
@ -152,9 +157,9 @@ module Make
dirty=false; dirty=false;
} }
let create ?(size=`Big) () : t = let create ?(size=`Big) (th:theory) : t =
let st = St.create ~size () in let st = St.create ~size () in
create_ ~st () create_ ~st th
(* Misc functions *) (* Misc functions *)
let to_float = float_of_int let to_float = float_of_int
@ -195,7 +200,7 @@ module Make
| Some _ -> () | Some _ -> ()
| None -> | None ->
let l = ref [] in let l = ref [] in
Plugin.iter_assignable Plugin.iter_assignable st.th
(fun t -> l := Lit.make st.st t :: !l) (fun t -> l := Lit.make st.st t :: !l)
res.var.pa.lit; res.var.pa.lit;
res.var.v_assignable <- Some !l; res.var.v_assignable <- Some !l;
@ -386,7 +391,7 @@ module Make
assert (st.th_head = Vec.size st.trail); assert (st.th_head = Vec.size st.trail);
assert (st.elt_head = Vec.size st.trail); assert (st.elt_head = Vec.size st.trail);
Vec.push st.elt_levels (Vec.size st.trail); Vec.push st.elt_levels (Vec.size st.trail);
Vec.push st.th_levels (Plugin.current_level ()); (* save the current theory state *) Vec.push st.th_levels (Plugin.current_level st.th); (* save the current theory state *)
() ()
(* Attach/Detach a clause. (* Attach/Detach a clause.
@ -454,7 +459,7 @@ module Make
) )
done; done;
(* Recover the right theory state. *) (* Recover the right theory state. *)
Plugin.backtrack (Vec.get st.th_levels lvl); Plugin.backtrack st.th (Vec.get st.th_levels lvl);
(* Resize the vectors according to their new size. *) (* Resize the vectors according to their new size. *)
Vec.shrink st.trail !head; Vec.shrink st.trail !head;
Vec.shrink st.elt_levels lvl; Vec.shrink st.elt_levels lvl;
@ -582,7 +587,7 @@ module Make
by boolean propagation/decision *) by boolean propagation/decision *)
let th_eval st a : bool option = let th_eval st a : bool option =
if a.is_true || a.neg.is_true then None if a.is_true || a.neg.is_true then None
else match Plugin.eval a.lit with else match Plugin.eval st.th a.lit with
| Plugin_intf.Unknown -> None | Plugin_intf.Unknown -> None
| Plugin_intf.Valued (b, l) -> | Plugin_intf.Valued (b, l) ->
if l = [] then if l = [] then
@ -1014,7 +1019,7 @@ module Make
) else ( ) else (
let slice = current_slice st in let slice = current_slice st in
st.th_head <- st.elt_head; (* catch up *) st.th_head <- st.elt_head; (* catch up *)
match Plugin.assume slice with match Plugin.assume st.th slice with
| Plugin_intf.Sat -> | Plugin_intf.Sat ->
propagate st propagate st
| Plugin_intf.Unsat (l, p) -> | Plugin_intf.Unsat (l, p) ->
@ -1067,7 +1072,7 @@ module Make
if v.v_level >= 0 then ( if v.v_level >= 0 then (
assert (v.pa.is_true || v.na.is_true); assert (v.pa.is_true || v.na.is_true);
pick_branch_lit st pick_branch_lit st
) else match Plugin.eval atom.lit with ) else match Plugin.eval st.th atom.lit with
| Plugin_intf.Unknown -> | Plugin_intf.Unknown ->
new_decision_level st; new_decision_level st;
let current_level = decision_level st in let current_level = decision_level st in
@ -1087,7 +1092,7 @@ module Make
if Lit.level l >= 0 then if Lit.level l >= 0 then
pick_branch_lit st pick_branch_lit st
else ( else (
let value = Plugin.assign l.term in let value = Plugin.assign st.th l.term in
new_decision_level st; new_decision_level st;
let current_level = decision_level st in let current_level = decision_level st in
enqueue_assign st l value current_level enqueue_assign st l value current_level
@ -1174,7 +1179,7 @@ module Make
n_of_learnts := !n_of_learnts *. learntsize_inc n_of_learnts := !n_of_learnts *. learntsize_inc
| Sat -> | Sat ->
assert (st.elt_head = Vec.size st.trail); assert (st.elt_head = Vec.size st.trail);
begin match Plugin.if_sat (full_slice st) with begin match Plugin.if_sat st.th (full_slice st) with
| Plugin_intf.Sat -> () | Plugin_intf.Sat -> ()
| Plugin_intf.Unsat (l, p) -> | Plugin_intf.Unsat (l, p) ->
let atoms = List.rev_map (create_atom st) l in let atoms = List.rev_map (create_atom st) l in

View file

@ -60,8 +60,11 @@ type ('term, 'formula, 'proof) slice = {
} }
(** The type for a slice of assertions to assume/propagate in the theory. *) (** The type for a slice of assertions to assume/propagate in the theory. *)
(** Signature for theories to be given to the Model Constructing Solver. *)
module type S = sig module type S = sig
(** Signature for theories to be given to the Model Constructing Solver. *)
type t
(** The plugin state itself *)
type term type term
(** The type of terms. Should be compatible with Expr_intf.Term.t*) (** The type of terms. Should be compatible with Expr_intf.Term.t*)
@ -75,33 +78,30 @@ module type S = sig
type level type level
(** The type for levels to allow backtracking. *) (** The type for levels to allow backtracking. *)
val dummy : level val current_level : t -> level
(** A dummy level. *)
val current_level : unit -> level
(** Return the current level of the theory (either the empty/beginning state, or the (** Return the current level of the theory (either the empty/beginning state, or the
last level returned by the [assume] function). *) last level returned by the [assume] function). *)
val assume : (term, formula, proof) slice -> (formula, proof) res val assume : t -> (term, formula, proof) slice -> (formula, proof) res
(** Assume the formulas in the slice, possibly pushing new formulas to be propagated, (** Assume the formulas in the slice, possibly pushing new formulas to be propagated,
and returns the result of the new assumptions. *) and returns the result of the new assumptions. *)
val if_sat : (term, formula, proof) slice -> (formula, proof) res val if_sat : t -> (term, formula, proof) slice -> (formula, proof) res
(** Called at the end of the search in case a model has been found. If no new clause is (** Called at the end of the search in case a model has been found. If no new clause is
pushed and the function returns [Sat], then proof search ends and 'sat' is returned, pushed and the function returns [Sat], then proof search ends and 'sat' is returned,
else search is resumed. *) else search is resumed. *)
val backtrack : level -> unit val backtrack : t -> level -> unit
(** Backtrack to the given level. After a call to [backtrack l], the theory should be in the (** Backtrack to the given level. After a call to [backtrack l], the theory should be in the
same state as when it returned the value [l], *) same state as when it returned the value [l], *)
val assign : term -> term val assign : t -> term -> term
(** Returns an assignment value for the given term. *) (** Returns an assignment value for the given term. *)
val iter_assignable : (term -> unit) -> formula -> unit val iter_assignable : t -> (term -> unit) -> formula -> unit
(** An iterator over the subterms of a formula that should be assigned a value (usually the poure subterms) *) (** An iterator over the subterms of a formula that should be assigned a value (usually the poure subterms) *)
val eval : formula -> term eval_res val eval : t -> formula -> term eval_res
(** Returns the evaluation of the formula in the current assignment *) (** Returns the evaluation of the formula in the current assignment *)
end end
@ -110,18 +110,19 @@ module Dummy(F: Solver_types.S)
: S with type formula = F.formula : S with type formula = F.formula
and type term = F.term and type term = F.term
and type proof = F.proof and type proof = F.proof
and type t = unit
= struct = struct
type t = unit
type formula = F.formula type formula = F.formula
type term = F.term type term = F.term
type proof = F.proof type proof = F.proof
type level = unit type level = unit
let dummy = ()
let current_level () = () let current_level () = ()
let assume _ = Sat let assume () _ = Sat
let if_sat _ = Sat let if_sat () _ = Sat
let backtrack _ = () let backtrack () _ = ()
let eval _ = Unknown let eval () _ = Unknown
let assign t = t let assign () t = t
let mcsat = false let mcsat = false
let iter_assignable _ _ = () let iter_assignable () _ _ = ()
end end

View file

@ -27,6 +27,7 @@ module Make
type term = St.term type term = St.term
type atom = St.formula type atom = St.formula
type clause = St.clause type clause = St.clause
type theory = Th.t
type t = S.t type t = S.t
type solver = t type solver = t

View file

@ -22,6 +22,7 @@ module Make
and type formula = St.formula and type formula = St.formula
and type clause = St.clause and type clause = St.clause
and type Proof.lemma = St.proof and type Proof.lemma = St.proof
and type theory = Th.t
(** Functor to make a safe external interface. *) (** Functor to make a safe external interface. *)

View file

@ -60,14 +60,17 @@ module type S = sig
type clause type clause
type theory
module Proof : Res.S with type clause = clause module Proof : Res.S with type clause = clause
(** A module to manipulate proofs. *) (** A module to manipulate proofs. *)
type t type t
(** Main solver type, containing all state for solving. *) (** Main solver type, containing all state for solving. *)
val create : ?size:[`Tiny|`Small|`Big] -> unit -> t val create : ?size:[`Tiny|`Small|`Big] -> theory -> t
(** Create new solver (** Create new solver
@param theory the theory
@param size the initial size of internal data structures. The bigger, @param size the initial size of internal data structures. The bigger,
the faster, but also the more RAM it uses. *) the faster, but also the more RAM it uses. *)

View file

@ -37,8 +37,10 @@ type ('form, 'proof) slice = {
propagation queue. They allow to look at the propagated literals, propagation queue. They allow to look at the propagated literals,
and to add new clauses to the solver. *) and to add new clauses to the solver. *)
(** Signature for theories to be given to the Solver. *)
module type S = sig module type S = sig
(** Signature for theories to be given to the Solver. *) type t
(** The state of the theory itself *)
type formula type formula
(** The type of formulas. Should be compatble with Formula_intf.S *) (** The type of formulas. Should be compatble with Formula_intf.S *)
@ -49,32 +51,33 @@ module type S = sig
type level type level
(** The type for levels to allow backtracking. *) (** The type for levels to allow backtracking. *)
val current_level : unit -> level val current_level : t -> level
(** Return the current level of the theory (either the empty/beginning state, or the (** Return the current level of the theory (either the empty/beginning state, or the
last level returned by the [assume] function). *) last level returned by the [assume] function). *)
val assume : (formula, proof) slice -> (formula, proof) res val assume : t -> (formula, proof) slice -> (formula, proof) res
(** Assume the formulas in the slice, possibly pushing new formulas to be propagated, (** Assume the formulas in the slice, possibly pushing new formulas to be propagated,
and returns the result of the new assumptions. *) and returns the result of the new assumptions. *)
val if_sat : (formula, proof) slice -> (formula, proof) res val if_sat : t -> (formula, proof) slice -> (formula, proof) res
(** Called at the end of the search in case a model has been found. If no new clause is (** Called at the end of the search in case a model has been found. If no new clause is
pushed, then 'sat' is returned, else search is resumed. *) pushed, then 'sat' is returned, else search is resumed. *)
val backtrack : level -> unit val backtrack : t -> level -> unit
(** Backtrack to the given level. After a call to [backtrack l], the theory should be in the (** Backtrack to the given level. After a call to [backtrack l], the theory should be in the
same state as when it returned the value [l], *) same state as when it returned the value [l], *)
end end
module Dummy(F: Formula_intf.S) module Dummy(F: Formula_intf.S)
: S with type formula = F.t : S with type formula = F.t and type t = unit
= struct = struct
type t = unit
type formula = F.t type formula = F.t
type proof = unit type proof = unit
type level = unit type level = unit
let current_level () = () let current_level () = ()
let assume _ = Sat let assume () _ = Sat
let if_sat _ = Sat let if_sat () _ = Sat
let backtrack _ = () let backtrack () _ = ()
end end

View file

@ -11,6 +11,6 @@ Copyright 2016 Guillaume Bury
module Expr = Expr_sat module Expr = Expr_sat
include Msat.S with type formula = Expr.t include Msat.S with type formula = Expr.t and type theory = unit
(** A functor that can generate as many solvers as needed. *) (** A functor that can generate as many solvers as needed. *)